Backed out changeset eb6428c5e590 (bug 1109282) for webplatform test failures.

This commit is contained in:
Ryan VanderMeulen 2014-12-18 11:18:18 -05:00
parent e8e0c5d803
commit af628f775a
9 changed files with 5 additions and 311 deletions

View File

@ -8,7 +8,6 @@ from marionette import Marionette, HTMLElement, Actions, MultiActions
from marionette_test import MarionetteTestCase, MarionetteJSTestCase, CommonTestCase, expectedFailure, skip, SkipTest from marionette_test import MarionetteTestCase, MarionetteJSTestCase, CommonTestCase, expectedFailure, skip, SkipTest
from errors import ( from errors import (
ElementNotVisibleException, ElementNotVisibleException,
ElementNotAccessibleException,
ErrorCodes, ErrorCodes,
FrameSendFailureError, FrameSendFailureError,
FrameSendNotInitializedError, FrameSendNotInitializedError,

View File

@ -13,7 +13,6 @@ class ErrorCodes(object):
ELEMENT_NOT_VISIBLE = 11 ELEMENT_NOT_VISIBLE = 11
INVALID_ELEMENT_STATE = 12 INVALID_ELEMENT_STATE = 12
UNKNOWN_ERROR = 13 UNKNOWN_ERROR = 13
ELEMENT_NOT_ACCESSIBLE = 56
ELEMENT_IS_NOT_SELECTABLE = 15 ELEMENT_IS_NOT_SELECTABLE = 15
JAVASCRIPT_ERROR = 17 JAVASCRIPT_ERROR = 17
XPATH_LOOKUP_ERROR = 19 XPATH_LOOKUP_ERROR = 19
@ -114,9 +113,6 @@ class ElementNotVisibleException(MarionetteException):
super(ElementNotVisibleException, self).__init__( super(ElementNotVisibleException, self).__init__(
message, status=status, cause=cause, stacktrace=stacktrace) message, status=status, cause=cause, stacktrace=stacktrace)
class ElementNotAccessibleException(MarionetteException):
pass
class NoSuchFrameException(MarionetteException): class NoSuchFrameException(MarionetteException):
pass pass

View File

@ -677,8 +677,6 @@ class Marionette(object):
raise errors.StaleElementException(message=message, status=status, stacktrace=stacktrace) raise errors.StaleElementException(message=message, status=status, stacktrace=stacktrace)
elif status == errors.ErrorCodes.ELEMENT_NOT_VISIBLE: elif status == errors.ErrorCodes.ELEMENT_NOT_VISIBLE:
raise errors.ElementNotVisibleException(message=message, status=status, stacktrace=stacktrace) raise errors.ElementNotVisibleException(message=message, status=status, stacktrace=stacktrace)
elif status == errors.ErrorCodes.ELEMENT_NOT_ACCESSIBLE:
raise errors.ElementNotAccessibleException(message=message, status=status, stacktrace=stacktrace)
elif status == errors.ErrorCodes.INVALID_ELEMENT_STATE: elif status == errors.ErrorCodes.INVALID_ELEMENT_STATE:
raise errors.InvalidElementStateException(message=message, status=status, stacktrace=stacktrace) raise errors.InvalidElementStateException(message=message, status=status, stacktrace=stacktrace)
elif status == errors.ErrorCodes.UNKNOWN_ERROR: elif status == errors.ErrorCodes.UNKNOWN_ERROR:

View File

@ -1,86 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from marionette_test import MarionetteTestCase
from errors import ElementNotAccessibleException
from errors import ElementNotVisibleException
class TestAccessibility(MarionetteTestCase):
# Elements that are accessible with and without the accessibliity API
valid_elementIDs = [
# Button1 is an accessible button with a valid accessible name
# computed from subtree
"button1",
# Button2 is an accessible button with a valid accessible name
# computed from aria-label
"button2"
]
# Elements that are not accessible with the accessibility API
invalid_elementIDs = [
# Button3 does not have an accessible object
"button3",
# Button4 does not support any accessible actions
"button4",
# Button5 does not have a correct accessibility role and may not be
# manipulated via the accessibility API
"button5",
# Button6 is missing an accesible name
"button6",
# Button7 is not currently visible via the accessibility API and may
# not be manipulated by it
"button7",
# Button8 is not currently visible via the accessibility API and may
# not be manipulated by it (in hidden subtree)
"button8"
]
# Elements that are either accessible to accessibility API or not accessible
# at all
falsy_elements = [
# Element is only visible to the accessibility API and may be
# manipulated by it
"button9",
# Element is not currently visible
"button10"
]
def run_element_test(self, ids, testFn):
for id in ids:
element = self.marionette.find_element("id", id)
testFn(element)
def setup_accessibility(self, raisesAccessibilityExceptions=True, navigate=True):
self.marionette.delete_session()
self.marionette.start_session(
{"raisesAccessibilityExceptions": raisesAccessibilityExceptions})
# Navigate to test_accessibility.html
if navigate:
test_accessibility = self.marionette.absolute_url("test_accessibility.html")
self.marionette.navigate(test_accessibility)
def test_valid_single_tap(self):
self.setup_accessibility()
# No exception should be raised
self.run_element_test(self.valid_elementIDs, lambda button: button.tap())
def test_invalid_single_tap(self):
self.setup_accessibility()
self.run_element_test(self.invalid_elementIDs,
lambda button: self.assertRaises(ElementNotAccessibleException,
button.tap))
self.run_element_test(self.falsy_elements,
lambda button: self.assertRaises(ElementNotAccessibleException,
button.tap))
def test_invalid_single_tap_no_exceptions(self):
self.setup_accessibility(False, True)
# No exception should be raised
self.run_element_test(self.invalid_elementIDs, lambda button: button.tap())
# Elements are invisible
self.run_element_test(self.falsy_elements,
lambda button: self.assertRaises(ElementNotVisibleException,
button.tap))

View File

@ -16,8 +16,6 @@ skip = false
[test_session.py] [test_session.py]
[test_capabilities.py] [test_capabilities.py]
[test_accessibility.py]
[test_expectedfail.py] [test_expectedfail.py]
expected = fail expected = fail
[test_import_script.py] [test_import_script.py]

View File

@ -1,38 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<head>
<title>Marionette Test</title>
</head>
<body>
<button id="button1">button1</button>
<button id="button2" aria-label="button2"></button>
<span id="button3">I am a bad button with no accessible</span>
<h1 id="button4">I am a bad button that is actually a header</h1>
<h1 id="button5">
I am a bad button that is actually an actionable header with a listener
</h1>
<button id="button6"></button>
<button id="button7" aria-hidden="true">button7</button>
<div aria-hidden="true">
<button id="button8">button8</button>
</div>
<button id="button9" style="position:absolute;left:-100px;top:-455px;">
button9
</button>
<button id="button10" style="visibility:hidden;">
button10
</button>
<script>
document.getElementById('button5').addEventListener('click', function() {
// A pseudo button that has a listener but is missing button semantics.
return true;
});
</script>
</body>
</html>

View File

@ -12,7 +12,6 @@
*/ */
this.EXPORTED_SYMBOLS = [ this.EXPORTED_SYMBOLS = [
"Accessibility",
"ElementManager", "ElementManager",
"CLASS_NAME", "CLASS_NAME",
"SELECTOR", "SELECTOR",
@ -48,127 +47,6 @@ function ElementException(msg, num, stack) {
this.stack = stack; this.stack = stack;
} }
this.Accessibility = function Accessibility() {
// A flag indicating whether the accessibility issue should be logged or cause
// an exception. Default: log to stdout.
this.strict = false;
this.accessibleRetrieval = Components.classes[
'@mozilla.org/accessibleRetrieval;1'].getService(
Components.interfaces.nsIAccessibleRetrieval);
};
Accessibility.prototype = {
/**
* Accessible object roles that support some action
* @type Object
*/
actionableRoles: new Set([
'pushbutton',
'checkbutton',
'combobox',
'key',
'link',
'menuitem',
'check menu item',
'radio menu item',
'option',
'radiobutton',
'slider',
'spinbutton',
'pagetab',
'entry',
'outlineitem'
]),
/**
* Get an accessible object for a DOM element
* @param nsIDOMElement element
* @param Boolean mustHaveAccessible a flag indicating that the element must
* have an accessible object
* @return nsIAccessible object for the element
*/
getAccessibleObject(element, mustHaveAccessible = false) {
let acc = this.accessibleRetrieval.getAccessibleFor(element);
if (!acc && mustHaveAccessible) {
this.handleErrorMessage('Element does not have an accessible object');
}
return acc;
},
/**
* Check if the accessible has a role that supports some action
* @param nsIAccessible object
* @return Boolean an indicator of role being actionable
*/
isActionableRole(accessible) {
return this.actionableRoles.has(
this.accessibleRetrieval.getStringRole(accessible.role));
},
/**
* Determine if an accessible has at least one action that it supports
* @param nsIAccessible object
* @return Boolean an indicator of supporting at least one accessible action
*/
hasActionCount(accessible) {
return accessible.actionCount > 0;
},
/**
* Determine if an accessible has a valid name
* @param nsIAccessible object
* @return Boolean an indicator that the element has a non empty valid name
*/
hasValidName(accessible) {
return accessible.name && accessible.name.trim();
},
/**
* Check if an accessible has a set hidden attribute
* @param nsIAccessible object
* @return Boolean an indicator that the element has a hidden accessible
* attribute set to true
*/
hasHiddenAttribute(accessible) {
let hidden;
try {
hidden = accessible.attributes.getStringProperty('hidden');
} finally {
// If the property is missing, exception will be thrown.
return hidden && hidden === 'true';
}
},
/**
* Check if an accessible is hidden from the user of the accessibility API
* @param nsIAccessible object
* @return Boolean an indicator that the element is hidden from the user
*/
isHidden(accessible) {
while (accessible) {
if (this.hasHiddenAttribute(accessible)) {
return true;
}
accessible = accessible.parent;
}
return false;
},
/**
* Send an error message or log the error message in the log
* @param String message
*/
handleErrorMessage(message) {
if (!message) {
return;
}
if (this.strict) {
throw new ElementException(message, 56, null);
}
dump(Date.now() + " Marionette: " + message);
}
};
this.ElementManager = function ElementManager(notSupported) { this.ElementManager = function ElementManager(notSupported) {
this.seenItems = {}; this.seenItems = {};
this.timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer); this.timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);

View File

@ -39,7 +39,6 @@ let listenerId = null; //unique ID of this listener
let curFrame = content; let curFrame = content;
let previousFrame = null; let previousFrame = null;
let elementManager = new ElementManager([]); let elementManager = new ElementManager([]);
let accessibility = new Accessibility();
let importedScripts = null; let importedScripts = null;
let inputSource = null; let inputSource = null;
@ -211,7 +210,6 @@ function waitForReady() {
*/ */
function newSession(msg) { function newSession(msg) {
isB2G = msg.json.B2G; isB2G = msg.json.B2G;
accessibility.strict = msg.json.raisesAccessibilityExceptions;
resetValues(); resetValues();
if (isB2G) { if (isB2G) {
readyStateTimer.initWithCallback(waitForReady, 100, Ci.nsITimer.TYPE_ONE_SHOT); readyStateTimer.initWithCallback(waitForReady, 100, Ci.nsITimer.TYPE_ONE_SHOT);
@ -947,15 +945,11 @@ function singleTap(msg) {
let command_id = msg.json.command_id; let command_id = msg.json.command_id;
try { try {
let el = elementManager.getKnownElement(msg.json.id, curFrame); let el = elementManager.getKnownElement(msg.json.id, curFrame);
let acc = accessibility.getAccessibleObject(el, true);
// after this block, the element will be scrolled into view // after this block, the element will be scrolled into view
let visible = checkVisible(el, msg.json.corx, msg.json.cory); if (!checkVisible(el, msg.json.corx, msg.json.cory)) {
checkVisibleAccessibility(acc, visible); sendError("Element is not currently visible and may not be manipulated", 11, null, command_id);
if (!visible) { return;
sendError("Element is not currently visible and may not be manipulated", 11, null, command_id);
return;
} }
checkActionableAccessibility(acc);
if (!curFrame.document.createTouch) { if (!curFrame.document.createTouch) {
mouseEventsOnly = true; mouseEventsOnly = true;
} }
@ -968,48 +962,6 @@ function singleTap(msg) {
} }
} }
/**
* Check if the element's visible state corresponds to its accessibility API
* visibility
* @param nsIAccessible object
* @param Boolean visible element's visibility state
*/
function checkVisibleAccessibility(accesible, visible) {
if (!accesible) {
return;
}
let hiddenAccessibility = accessibility.isHidden(accesible);
let message;
if (visible && hiddenAccessibility) {
message = 'Element is not currently visible via the accessibility API ' +
'and may not be manipulated by it';
} else if (!visible && !hiddenAccessibility) {
message = 'Element is currently only visible via the accessibility API ' +
'and can be manipulated by it';
}
accessibility.handleErrorMessage(message);
}
/**
* Check if it is possible to activate an element with the accessibility API
* @param nsIAccessible object
*/
function checkActionableAccessibility(accesible) {
if (!accesible) {
return;
}
let message;
if (!accessibility.hasActionCount(accesible)) {
message = 'Element does not support any accessible actions';
} else if (!accessibility.isActionableRole(accesible)) {
message = 'Element does not have a correct accessibility role ' +
'and may not be manipulated via the accessibility API';
} else if (!accessibility.hasValidName(accesible)) {
message = 'Element is missing an accesible name';
}
accessibility.handleErrorMessage(message);
}
/** /**
* Given an element and a pair of coordinates, returns an array of the form * Given an element and a pair of coordinates, returns an array of the form
* [ clientX, clientY, pageX, pageY, screenX, screenY ] * [ clientX, clientY, pageX, pageY, screenX, screenY ]

View File

@ -174,7 +174,6 @@ function MarionetteServerConnection(aPrefix, aTransport, aServer)
// Supported features // Supported features
"handlesAlerts": false, "handlesAlerts": false,
"nativeEvents": false, "nativeEvents": false,
"raisesAccessibilityExceptions": false,
"rotatable": appName == "B2G", "rotatable": appName == "B2G",
"secureSsl": false, "secureSsl": false,
"takesElementScreenshot": true, "takesElementScreenshot": true,
@ -2900,10 +2899,8 @@ MarionetteServerConnection.prototype = {
this.curBrowser.elementManager.seenItems[reg.id] = Cu.getWeakReference(listenerWindow); this.curBrowser.elementManager.seenItems[reg.id] = Cu.getWeakReference(listenerWindow);
if (nullPrevious && (this.curBrowser.curFrameId != null)) { if (nullPrevious && (this.curBrowser.curFrameId != null)) {
if (!this.sendAsync("newSession", if (!this.sendAsync("newSession",
{ B2G: (appName == "B2G"), { B2G: (appName == "B2G") },
raisesAccessibilityExceptions: this.newSessionCommandId)) {
this.sessionCapabilities.raisesAccessibilityExceptions },
this.newSessionCommandId)) {
return; return;
} }
if (this.curBrowser.newSession) { if (this.curBrowser.newSession) {