# Copyright 2016 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import os from autotest_lib.client.bin import test from autotest_lib.client.bin import utils from autotest_lib.client.common_lib import error from autotest_lib.client.cros.input_playback import input_playback class a11y_test_base(test.test): """Base class for a11y tests.""" version = 1 # ChromeVox extension id _CHROMEVOX_ID = 'mndnfokpggljbaajbnioimlmbfngpief' _CVOX_STATE_TIMEOUT = 40 _CVOX_INDICATOR_TIMEOUT = 40 def warmup(self): """Test setup.""" # Emulate a keyboard for later ChromeVox toggle (if needed). # See input_playback. The keyboard is used to play back shortcuts. self._player = input_playback.InputPlayback() self._player.emulate(input_type='keyboard') self._player.find_connected_inputs() def _child_test_cleanup(self): """Can be overwritten by child classes and run duing parent cleanup.""" return def cleanup(self): self._player.close() self._child_test_cleanup() def _toggle_chromevox(self): """Use keyboard shortcut and emulated keyboard to toggle ChromeVox.""" self._player.blocking_playback_of_default_file( input_type='keyboard', filename='keyboard_ctrl+alt+z') def _search_shift_move(self, direction): """Playback the keyboard movement shortcut for given direction. @param direction: right, left, up, or down. """ assert direction in ['right', 'left', 'up', 'down'] self._player.blocking_playback_of_default_file( input_type='keyboard', filename='keyboard_search+shift+%s' % direction) def _tab_move(self, direction='forwards'): """Playback a tab or shift+tab for the given direction. @param direction: forwards or backwards. """ assert direction in ['forwards', 'backwards'] is_forwards = direction is 'forwards' filename = 'keyboard_tab' if is_forwards else 'keyboard_shift+tab' self._player.blocking_playback_of_default_file( input_type='keyboard', filename=filename) def _set_feature(self, feature, value): """Set given feature to given value using a11y API call. Presupposes self._extension (with accessibilityFeatures enabled). @param feature: string of accessibility feature to change. @param value: boolean of expected value. @raises: error.TestError if feature cannot be set. """ value_str = 'true' if value else 'false' cmd = ('window.__result = null;\n' 'chrome.accessibilityFeatures.%s.set({value: %s});\n' 'chrome.accessibilityFeatures.%s.get({}, function(d) {' 'window.__result = d[\'value\']; });' % ( feature, value_str, feature)) self._extension.ExecuteJavaScript(cmd) poll_cmd = 'window.__result == %s;' % value_str utils.poll_for_condition( lambda: self._extension.EvaluateJavaScript(poll_cmd), exception = error.TestError( 'Timeout while trying to set %s to %s' % (feature, value_str))) def _get_chromevox_state(self): """Return whether ChromeVox is enabled or not. Presupposes self._extension (with management enabled). @returns: value of management.get.enabled. @raises: error.TestError if state cannot be determined. """ cmd = ('window.__enabled = null;\n' 'chrome.management.get(\'%s\', function(r) {' 'if (r) {window.__enabled = r[\'enabled\'];} ' 'else {window.__enabled = false;}});' % self._CHROMEVOX_ID) self._extension.ExecuteJavaScript(cmd) poll_cmd = 'window.__enabled != null;' utils.poll_for_condition( lambda: self._extension.EvaluateJavaScript(poll_cmd), exception=error.TestError( 'ChromeVox: management.get.enabled was not set!')) return self._extension.EvaluateJavaScript('window.__enabled') def _confirm_chromevox_state(self, value): """Fail test unless ChromeVox state is given value. Presupposes self._extension (with management enabled). @param value: True or False, whether ChromeVox should be enabled. @raises: error.TestFail if actual state doesn't match expected. """ utils.poll_for_condition( lambda: self._get_chromevox_state() == value, exception=error.TestFail('ChromeVox: enabled state ' 'was not %s.' % value), timeout=self._CVOX_STATE_TIMEOUT) def _get_chromevox_indicator(self, tab): """Return whether the orange ChromeVox highlight is present or not. Looks for the orange highlight on the given tab. @returns: whether 'cvox_indicator_container' is found on the page """ cmd = ('document.getElementsByClassName(' ' "cvox_indicator_container").length > 0;') return tab.EvaluateJavaScript(cmd) def _confirm_chromevox_indicator(self, value): """Fail test unless indicator state is given value. Presupposes self._tab (the tab on which to check). @param value: True or False, whether ChromeVox indicator should show. @raises: error.TestFail if actual state doesn't match expected. """ utils.poll_for_condition( lambda: self._get_chromevox_indicator(self._tab) == value, exception=error.TestFail('ChromeVox: "Indicator present" ' 'was not %s.' % value), timeout=self._CVOX_INDICATOR_TIMEOUT) def _get_extension_path(self): """Return the path to the default accessibility extension. @returns: string of path to default extension. """ this_dir = os.path.dirname(__file__) return os.path.join(this_dir, 'a11y_ext')