diff options
Diffstat (limited to 'testing/marionette/harness/marionette_harness/tests/unit/test_accessibility.py')
-rw-r--r-- | testing/marionette/harness/marionette_harness/tests/unit/test_accessibility.py | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/testing/marionette/harness/marionette_harness/tests/unit/test_accessibility.py b/testing/marionette/harness/marionette_harness/tests/unit/test_accessibility.py new file mode 100644 index 000000000..0d8d9dca5 --- /dev/null +++ b/testing/marionette/harness/marionette_harness/tests/unit/test_accessibility.py @@ -0,0 +1,210 @@ +# 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_driver.by import By +from marionette_driver.errors import ( + ElementNotAccessibleException, + ElementNotInteractableException +) + +from marionette_harness import MarionetteTestCase + + + +class TestAccessibility(MarionetteTestCase): + def setUp(self): + super(TestAccessibility, self).setUp() + with self.marionette.using_context("chrome"): + self.marionette.set_pref("dom.ipc.processCount", 1) + + def tearDown(self): + with self.marionette.using_context("chrome"): + self.marionette.clear_pref("dom.ipc.processCount") + + # 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", + # Button13 is an accessible button that is implemented via role="button" + # and is explorable using tabindex="0" + "button13", + # button17 is an accessible button that overrides parent's + # pointer-events:none; property with its own pointer-events:all; + "button17" + ] + + # 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", + # Button14 is accessible button but is not explorable because of lack + # of tabindex that would make it focusable. + "button14" + ] + + # 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" + ] + + displayed_elementIDs = [ + "button1", "button2", "button3", "button4", "button5", "button6", + "button9", "no_accessible_but_displayed" + ] + + displayed_but_a11y_hidden_elementIDs = ["button7", "button8"] + + disabled_elementIDs = ["button11", "no_accessible_but_disabled"] + + # Elements that are enabled but otherwise disabled or not explorable via the accessibility API + disabled_accessibility_elementIDs = ["button12", "button15", "button16"] + + # Elements that are reporting selected state + valid_option_elementIDs = ["option1", "option2"] + + def run_element_test(self, ids, testFn): + for id in ids: + element = self.marionette.find_element(By.ID, id) + testFn(element) + + def setup_accessibility(self, enable_a11y_checks=True, navigate=True): + self.marionette.delete_session() + self.marionette.start_session( + {"requiredCapabilities": {"moz:accessibilityChecks": enable_a11y_checks}}) + self.assertEqual( + self.marionette.session_capabilities["moz:accessibilityChecks"], + enable_a11y_checks) + + # 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_single_tap_raises_element_not_accessible(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(ElementNotInteractableException, + button.tap)) + + def test_single_tap_raises_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(ElementNotInteractableException, + button.tap)) + + def test_valid_click(self): + self.setup_accessibility() + # No exception should be raised + self.run_element_test(self.valid_elementIDs, lambda button: button.click()) + + def test_click_raises_element_not_accessible(self): + self.setup_accessibility() + self.run_element_test(self.invalid_elementIDs, + lambda button: self.assertRaises(ElementNotAccessibleException, + button.click)) + self.run_element_test(self.falsy_elements, + lambda button: self.assertRaises(ElementNotInteractableException, + button.click)) + + def test_click_raises_no_exceptions(self): + self.setup_accessibility(False, True) + # No exception should be raised + self.run_element_test(self.invalid_elementIDs, lambda button: button.click()) + # Elements are invisible + self.run_element_test(self.falsy_elements, + lambda button: self.assertRaises(ElementNotInteractableException, + button.click)) + + def test_element_visible_but_not_visible_to_accessbility(self): + self.setup_accessibility() + # Elements are displayed but hidden from accessibility API + self.run_element_test(self.displayed_but_a11y_hidden_elementIDs, + lambda element: self.assertRaises(ElementNotAccessibleException, + element.is_displayed)) + + def test_element_is_visible_to_accessibility(self): + self.setup_accessibility() + # No exception should be raised + self.run_element_test(self.displayed_elementIDs, lambda element: element.is_displayed()) + + def test_element_is_not_enabled_to_accessbility(self): + self.setup_accessibility() + # Buttons are enabled but disabled/not-explorable via the accessibility API + self.run_element_test(self.disabled_accessibility_elementIDs, + lambda element: self.assertRaises(ElementNotAccessibleException, + element.is_enabled)) + + # Buttons are enabled but disabled/not-explorable via the accessibility API and thus are not + # clickable via the accessibility API + self.run_element_test(self.disabled_accessibility_elementIDs, + lambda element: self.assertRaises(ElementNotAccessibleException, + element.click)) + + self.setup_accessibility(False, False) + self.run_element_test(self.disabled_accessibility_elementIDs, + lambda element: element.is_enabled()) + self.run_element_test(self.disabled_accessibility_elementIDs, + lambda element: element.click()) + + def test_element_is_enabled_to_accessibility(self): + self.setup_accessibility() + # No exception should be raised + self.run_element_test(self.disabled_elementIDs, lambda element: element.is_enabled()) + + def test_send_keys_raises_no_exception(self): + self.setup_accessibility() + # Sending keys to valid input should not raise any exceptions + self.run_element_test(['input1'], lambda element: element.send_keys("a")) + + self.setup_accessibility(False, False) + # Sending keys to invalid element should not raise any exceptions when raising accessibility + # exceptions is disabled + self.run_element_test(['button5'], lambda element: element.send_keys("abc")) + + def test_send_keys_raises_element_not_accessible(self): + self.setup_accessibility() + # Sending keys to invalid element should raise an exception + self.run_element_test(['button5'], + lambda element: self.assertRaises(ElementNotAccessibleException, + element.send_keys)) + + def test_is_selected_raises_no_exception(self): + self.setup_accessibility() + # No exception should be raised for valid options + self.run_element_test(self.valid_option_elementIDs, lambda element: element.is_selected()) + # No exception should be raised for non-selectable elements + self.run_element_test(self.valid_elementIDs, lambda element: element.is_selected()) |