| Index: chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher_test.unitjs
|
| diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher_test.unitjs b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher_test.unitjs
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f9eac4dc678a22ace19154dd550448881421af8d
|
| --- /dev/null
|
| +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/injected/event_watcher_test.unitjs
|
| @@ -0,0 +1,850 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +// Include test fixture.
|
| +GEN_INCLUDE(['../../testing/chromevox_unittest_base.js']);
|
| +
|
| +/**
|
| + * Test fixture.
|
| + * @constructor
|
| + * @extends {ChromeVoxUnitTestBase}
|
| + */
|
| +function CvoxEventWatcherUnitTest() {}
|
| +
|
| +CvoxEventWatcherUnitTest.prototype = {
|
| + __proto__: ChromeVoxUnitTestBase.prototype,
|
| +
|
| + /** @override */
|
| + closureModuleDeps: [
|
| + 'cvox.ChromeVoxTester',
|
| + 'cvox.SpokenListBuilder',
|
| + ],
|
| +
|
| + /** @override */
|
| + setUp: function() {
|
| + cvox.ChromeVoxTester.setUp(document);
|
| + },
|
| +
|
| + /** @override */
|
| + tearDown: function() {
|
| + cvox.ChromeVoxTester.tearDown(document);
|
| + },
|
| +
|
| + /**
|
| + * Create mock event object.
|
| + * @param {Element} target The event target.
|
| + * @param {number=} opt_keyCode The event key code (i.e. 13 for Enter).
|
| + * @param {string=} opt_type The event type (i.e. 'keydown' or
|
| + * 'focus').
|
| + * @param {number=} opt_timeStamp The event timeStamp.
|
| + * @return {Event} The mock event.
|
| + * @suppress {invalidCasts}
|
| + */
|
| + createMockEvent: function(target, opt_keyCode, opt_type, opt_timeStamp) {
|
| + var mockEvent = {};
|
| + mockEvent.target = target;
|
| + if (opt_keyCode) {
|
| + mockEvent.keyCode = opt_keyCode;
|
| + }
|
| + if (opt_type) {
|
| + mockEvent.type = opt_type;
|
| + }
|
| + if (opt_timeStamp) {
|
| + mockEvent.timeStamp = opt_timeStamp;
|
| + }
|
| +
|
| + return /** @type {Event} */ (mockEvent);
|
| + },
|
| +
|
| + /**
|
| + * Simulate typing a key into an text field by modifying a given field and
|
| + * dispatching a keydown event to ChromeVoxEventWatcher. Allows modifying the
|
| + * selection so arrow keypresses can be simulated.
|
| + * @param {Element} textField The text field.
|
| + * @param {string} newValue The new value for the text field.
|
| + * @param {number} newSelStart The new selection start.
|
| + * @param {number} newSelEnd The new selection end.
|
| + * @param {number} keyCode The key code for the keydown event.
|
| + * @return {Element} The modified text field.
|
| + */
|
| + changeTextField: function(
|
| + textField, newValue, newSelStart, newSelEnd, keyCode) {
|
| + textField.value = newValue;
|
| + textField.selectionStart = newSelStart;
|
| + textField.selectionEnd = newSelEnd;
|
| +
|
| + cvox.ChromeVoxEventWatcher.keyDownEventWatcher(
|
| + this.createMockEvent(textField, keyCode, 'keydown'));
|
| + return textField;
|
| + }
|
| +};
|
| +
|
| +TEST_F('CvoxEventWatcherUnitTest', 'ButtonFocusFeedback', function() {
|
| + this.loadHtml('<div> <button id="alpha">Alpha</button> </div>');
|
| + this.setFocus('alpha');
|
| + this.waitForCalm(this.assertSpoken, 'Alpha Button');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when focusing links backwards (like shift-tabbing).
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'FocusLinksBackwards', function() {
|
| + this.loadHtml('<div> <p>before</p>' +
|
| + '<p><a href="#" id="l1">1</a></p>' +
|
| + '<p><a href="#" id="l2">2</a></p>' +
|
| + '<p><a href="#" id="l3">3</a></p>' +
|
| + '</div>');
|
| +
|
| + this.waitForCalm(this.setFocus, 'l1')
|
| + .waitForCalm(this.setFocus, 'l2')
|
| + .waitForCalm(this.setFocus, 'l3')
|
| + .waitForCalm(this.setFocus, 'l2')
|
| + .waitForCalm(this.setFocus, 'l1')
|
| + .waitForCalm(this.assertSpoken,
|
| + '1 Internal link 2 Internal link 3 Internal link ' +
|
| + '2 Internal link 1 Internal link');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when an editable text field gets focus.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'TextFocusFeedback', function() {
|
| + this.loadHtml('<div>' +
|
| + '<label for="mytext">Label</label>' +
|
| + '<input id="mytext" value="Value" title="Title" />' +
|
| + '</div>');
|
| +
|
| + this.setFocus('mytext');
|
| + this.waitForCalm(this.assertSpoken, 'Label Value Edit text');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when a contenteditable field gets focus.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'ContentEditableFocusFeedback', function() {
|
| + this.loadHtml('<div>' +
|
| + '<label for="mytext">Label</label>' +
|
| + '<div id="mytext" contentEditable>This is editable</div>' +
|
| + '</div>');
|
| +
|
| + this.setFocus('mytext');
|
| + this.waitForCalm(this.assertSpoken, 'Label This is editable Edit text');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when an item in an dialog receives focus and then focus
|
| + * leaves the dialog.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'DialogFeedback', function() {
|
| + this.loadHtml('<div>' +
|
| + '<button id="show">Show</button>' +
|
| + '<div aria-label="compose message" role="dialog">' +
|
| + ' <button id="ok">OK</button>' +
|
| + ' <button id="cancel">Cancel</button>' +
|
| + '</div>' +
|
| + '</div>');
|
| +
|
| + // Enter the dialog by focusing an element inside it.
|
| + this.setFocus('ok');
|
| +
|
| + this.waitForCalm(this.assertSpoken,
|
| + 'Entered dialog compose message Dialog OK Button');
|
| +
|
| + // After we've entered a dialog, temporarily moving focus away shouldn't
|
| + // have any effect if we move it right back. (Allow apps to trap focus.)
|
| + this.waitForCalm(function() {
|
| + this.setFocus('show')
|
| + .setFocus('ok');
|
| + });
|
| +
|
| + this.waitForCalm(this.assertSpoken, 'OK Button');
|
| +
|
| + // Now move focus away and leave it there.
|
| + this.waitForCalm(this.setFocus, 'show');
|
| + this.waitForCalm(this.assertSpoken, 'Exited dialog. Show Button');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when an item in an alert dialog receives focus.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'AlertDialogFeedback', function() {
|
| + this.loadHtml('<div>' +
|
| + '<div role="alertdialog">' +
|
| + ' <p>Are you sure you want to install Windows?</p>' +
|
| + ' <button id="yes">Yes</button>' +
|
| + ' <button id="no">No</button>' +
|
| + '</div> </div>');
|
| +
|
| + // Enter the dialog by focusing an element inside it.
|
| + this.setFocus('no');
|
| + this.waitForCalm(this.assertSpoken,
|
| + 'Entered dialog ' +
|
| + 'Are you sure you want to install Windows? Yes Button No Button ' +
|
| + 'No Button');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when focus moves to two different items in a alertdialog
|
| + * quickly - make sure the notification that we entered the dialog
|
| + * isn't interrupted.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'DoubleFocusAlertDialogFeedback', function() {
|
| + this.loadHtml('<div>' +
|
| + '<div role="alertdialog">' +
|
| + ' <p>Are these the droids you\'re looking for?</p>' +
|
| + ' <button id="yes">Yes</button>' +
|
| + ' <button id="no">No</button>' +
|
| + '</div>' +
|
| + '<button id="outside">Outside</button>' +
|
| + '</div>');
|
| +
|
| + // Enter the dialog by focusing an element inside it, but then the Jedi
|
| + // mind trick quickly changes the default answer.
|
| + this.setFocus('yes')
|
| + .setFocus('no');
|
| +
|
| + this.waitForCalm(this.assertSpokenList,
|
| + this.spokenList()
|
| + .categoryFlush('Entered dialog')
|
| + .queue('Are these the droids you\'re looking for?')
|
| + .queue('Yes')
|
| + .queue('Button'));
|
| +
|
| + // Unfocus the dialog so we don't effect other tests.
|
| + this.waitForCalm(this.setFocus, 'outside');
|
| + this.waitForCalm(this.assertSpoken, 'Exited dialog. Outside Button');
|
| +});
|
| +
|
| +/**
|
| + * Test recovery when a dialog box closes and the user sends a tab event.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'CloseDialogTabRecovery', function() {
|
| + this.loadHtml('<div id="container">' +
|
| + '<p id="first">first node</p>' +
|
| + '<button id="button">valid button before</button>' +
|
| + '<p id="before">valid text before</p>' +
|
| + '<p id="dialog">invalid after click</p>' +
|
| + '<p id="last">valid text after</p>' +
|
| + '</div>');
|
| +
|
| + var first = $('first');
|
| + var dialog = $('dialog');
|
| + var displayNone = function() {
|
| + dialog.style.display = 'none';
|
| + };
|
| +
|
| + this.waitForCalm(cvox.ChromeVoxTester.syncToNode, first);
|
| + this.waitForCalm(cvox.ChromeVoxTester.setStrategy, 'lineardom');
|
| + this.waitForCalm(this.userCommand, 'forward');
|
| + this.waitForCalm(this.assertSpoken, 'valid button before Button');
|
| + this.waitForCalm(this.userCommand, 'forward');
|
| + this.waitForCalm(this.assertSpoken, 'valid text before');
|
| + this.waitForCalm(this.userCommand, 'forward');
|
| + this.waitForCalm(this.assertSpoken, 'invalid after click');
|
| +
|
| + // Invalidate the dialog box.
|
| + this.waitForCalm(displayNone);
|
| + this.waitForCalm(this.userCommand, 'forward');
|
| + this.waitForCalm(this.assertSpoken, 'valid text after');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when a list box with an active descendant receives focus.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'ListBoxFeedback', function() {
|
| + this.loadHtml('<div>' +
|
| + '<p id="before">My listbox</p>' +
|
| + '<div id="listbox" role="listbox" tabindex="0"' +
|
| + ' aria-activedescendant="red">' +
|
| + ' <div id="red" aria-selected="true" role="option">Red</div>' +
|
| + ' <div id="yellow" role="option">Yellow</div>' +
|
| + ' <div id="green" role="option">Green</div>' +
|
| + '</div>' +
|
| + '<p id="after">After</p>' +
|
| + '</div>');
|
| +
|
| + // Focus the listbox.
|
| + this.setFocus('listbox');
|
| + this.waitForCalm(this.assertSpoken, 'Red List box Selected 1 of 3')
|
| + .waitForCalm(function() {
|
| + // Set the activeDescendant and fire a keydown event.
|
| + // TODO(dmazzoni): replace with a higher-level API that's
|
| + // less brittle.
|
| + var listbox = $('listbox');
|
| + listbox.setAttribute('aria-activeDescendant', 'yellow');
|
| + cvox.ChromeVoxEventWatcher.keyDownEventWatcher(/** @type {Event} */ (
|
| + { 'target': listbox,
|
| + 'type': 'keydown' }));
|
| + })
|
| + .waitForCalm(this.assertSpoken, 'Yellow 2 of 3');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when the items of a list box receive focus.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'ListBoxOptionFeedback', function() {
|
| + this.loadHtml('<div>' +
|
| + '<p id="before">My listbox</p>' +
|
| + '<div id="listbox" role="listbox">' +
|
| + ' <div id="red" tabindex="0" aria-selected="true" role="option">' +
|
| + 'Red</div>' +
|
| + ' <div id="yellow" tabindex="-1" role="option">Yellow</div>' +
|
| + ' <div id="green" tabindex="-1" role="option">Green</div>' +
|
| + '</div>' +
|
| + '<p id="after">After</p>' +
|
| + '</div>');
|
| +
|
| + // Focus the second item.
|
| + this.setFocus('yellow');
|
| +
|
| + this.waitForCalm(this.assertSpoken, 'List box Yellow 2 of 3')
|
| + .waitForCalm(this.setFocus, 'red')
|
| + .waitForCalm(this.assertSpoken, 'Red Selected 1 of 3');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when the list box is setting focus in response to arrow
|
| + * (or some other) keypress and the user is also using ChromeVox navigation.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'ListBoxOptionFeedbackWithFocus', function() {
|
| + this.loadHtml('<div>' +
|
| + '<p id="before">My listbox</p>' +
|
| + '<div id="listbox" role="listbox">' +
|
| + ' <div id="red" tabindex="0" aria-selected="true" role="option">' +
|
| + 'Red</div>' +
|
| + ' <div id="yellow" tabindex="-1" role="option">Yellow</div>' +
|
| + ' <div id="green" tabindex="-1" role="option">Green</div>' +
|
| + ' <div id="blue" tabindex="-1" role="option">Blue</div>' +
|
| + '</div>' +
|
| + '<p id="after">After</p>' +
|
| + '</div>');
|
| +
|
| + // Simulate the user using ChromeVox navigation to move forward in the listbox
|
| + this.waitForCalm(cvox.ChromeVoxTester.setStrategy, 'lineardom');
|
| + this.waitForCalm(cvox.ChromeVoxTester.syncToFirstNode);
|
| + this.waitForCalm(this.userCommand, 'forward');
|
| + this.waitForCalm(this.assertSpoken, 'List box Red Selected 1 of 4');
|
| +
|
| + // Simulate the listbox setting focus on items in the listbox in response to
|
| + // keypresses
|
| + this.waitForCalm(this.setFocus, 'yellow');
|
| + this.waitForCalm(this.assertSpoken, 'Yellow 2 of 4');
|
| +
|
| + this.waitForCalm(this.setFocus, 'green');
|
| + this.waitForCalm(this.assertSpoken, 'Green 3 of 4');
|
| +
|
| + // ChromeVox navigation again
|
| + this.waitForCalm(this.userCommand, 'forward');
|
| + this.waitForCalm(this.assertSpoken, 'Blue 4 of 4');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when interacting with an editable text field.
|
| + * The low-level details are tested in editable_text_test.js, this is
|
| + * a higher-level test of how that code interacts with the event watcher.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'EditableText', function() {
|
| + cvox.ChromeVoxEditableTextBase.eventTypingEcho = false;
|
| + this.loadHtml('<div>' +
|
| + '<button id="before">Before</button>' +
|
| + '<label for="input">Query</label>' +
|
| + '<input id="input" value="abc">' +
|
| + '<p>After</p>' +
|
| + '</div>');
|
| +
|
| + var before = $('before');
|
| + var input = $('input');
|
| +
|
| + // Focus the button first.
|
| + before.focus();
|
| +
|
| + // Then focus the text field.
|
| + input.focus();
|
| + input.setSelectionRange(3, 3);
|
| +
|
| + this.waitForCalm(this.changeTextField, input, 'abcd', 3, 3, 68) // 'd'
|
| + .waitForCalm(this.changeTextField, input, 'abcde', 4, 4, 69) // 'e'
|
| + .waitForCalm(this.assertSpokenList,
|
| + this.spokenList()
|
| + .categoryFlush('Query')
|
| + .queue('abc')
|
| + .queue('Edit text')
|
| + .flush('d')
|
| + .flush('e'));
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when interacting with an editable text field that drives
|
| + * an listbox (to form an auto-complete combobox) but doesn't get updated.
|
| + * The low-level details are tested in editable_text_test.js, this is
|
| + * a higher-level test of how that code interacts with the event watcher.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'EditableTextListbox', function() {
|
| + this.loadHtml('<div>' +
|
| + '<button id="before">Before</button>' +
|
| + '<label for="input">Query</label>' +
|
| + '<input id="input" value="" role="combobox" aria-autocomplete="list"' +
|
| + ' aria-activedescendant>' +
|
| + '<div role="listbox">' +
|
| + ' <div id="option1" role="option">First pick</div>' +
|
| + ' <div id="option2" role="option">Second pick</div>' +
|
| + '</div>' +
|
| + '<p>After</p>' +
|
| + '</div>');
|
| +
|
| + var before = $('before');
|
| + var input = $('input');
|
| +
|
| + // Focus the text field.
|
| + this.waitForCalm(this.setFocus, 'input')
|
| + .waitForCalm(this.assertSpoken, 'Query Combo box Autocompletion list');
|
| +
|
| + this.waitForCalm(function() {
|
| + input.setAttribute('aria-activedescendant', 'option1');
|
| + this.changeTextField(input, '', 0, 0, 40); // 'down'
|
| + })
|
| + .waitForCalm(this.assertSpoken, 'First pick 1 of 2');
|
| +});
|
| +
|
| +/**
|
| + * Test feedback when interacting with an editable text field that drives
|
| + * an listbox (to form an auto-complete combobox) and *does* get updated.
|
| + * The low-level details are tested in editable_text_test.js, this is
|
| + * a higher-level test of how that code interacts with the event watcher.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'EditableTextListboxUpdatingInput', function() {
|
| + this.loadHtml('<div>' +
|
| + '<button id="before">Before</button>' +
|
| + '<label for="input">Query</label>' +
|
| + '<input id="input" value="" role="combobox" aria-autocomplete="list"' +
|
| + ' aria-activedescendant>' +
|
| + '<div role="listbox">' +
|
| + ' <div id="option1" role="option">First pick</div>' +
|
| + ' <div id="option2" role="option">Second pick</div>' +
|
| + '</div>' +
|
| + '<p>After</p>' +
|
| + '</div>');
|
| +
|
| + var before = $('before');
|
| + var input = $('input');
|
| +
|
| + // Focus the text field.
|
| + this.waitForCalm(this.setFocus, 'input')
|
| + .waitForCalm(this.assertSpoken, 'Query Combo box Autocompletion list');
|
| +
|
| + this.waitForCalm(function() {
|
| + input.setAttribute('aria-activedescendant', 'option1');
|
| + this.changeTextField(input, 'First pick', 9, 9, 40); // 'down'
|
| + })
|
| + .waitForCalm(this.assertSpoken, 'First pick');
|
| +});
|
| +
|
| +/**
|
| + * Tests navigating through a multiline text area.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'MultilineNavigation', function() {
|
| + this.loadHtml('<div> <textarea id="area">' +
|
| + 'one' +
|
| + '\n\n' +
|
| + 'two' +
|
| + '\n\n' +
|
| + 'three</textarea>' +
|
| + '</div>');
|
| +
|
| + var area = $('area');
|
| +
|
| + function setAreaCursor(pos) {
|
| + area.setSelectionRange(pos, pos);
|
| + cvox.ChromeVoxEventWatcher.keyDownEventWatcher(/** @type {Event} */ (
|
| + { 'target': area,
|
| + 'type': 'keydown' }));
|
| + }
|
| +
|
| + area.focus();
|
| + this.waitForCalm(this.assertSpoken, 'one two three Text area')
|
| + .waitForCalm(setAreaCursor, 0)
|
| + // The cursor did not move, so don't say anything -- even though we
|
| + // did press a key.
|
| + .waitForCalm(this.assertSpoken, '')
|
| + .waitForCalm(setAreaCursor, 5) // in front on the 'two'
|
| + .waitForCalm(this.assertSpoken, 'two')
|
| + .waitForCalm(setAreaCursor, 10) // in front of the 'three'
|
| + .waitForCalm(this.assertSpoken, 'three')
|
| + .waitForCalm(setAreaCursor, 0) // back to the first line
|
| + .waitForCalm(this.assertSpoken, 'one')
|
| + .waitForCalm(setAreaCursor, 4) // on the first new line
|
| + .waitForCalm(this.assertSpoken, 'Blank')
|
| + .waitForCalm(setAreaCursor, 5)
|
| + .waitForCalm(this.assertSpoken, 'two')
|
| + .waitForCalm(setAreaCursor, 9)
|
| + .waitForCalm(this.assertSpoken, 'Blank')
|
| + .waitForCalm(setAreaCursor, 10)
|
| + .waitForCalm(this.assertSpoken, 'three');
|
| +});
|
| +
|
| +TEST_F('CvoxEventWatcherUnitTest', 'ShouldWaitToProcess', function() {
|
| + // The focus event just happened, wait.
|
| + assertTrue(
|
| + cvox.ChromeVoxEventWatcherUtil.shouldWaitToProcess(100, 100, 100));
|
| + // The focus event just happened, but the first event is old, don't wait.
|
| + assertFalse(
|
| + cvox.ChromeVoxEventWatcherUtil.shouldWaitToProcess(100, 0, 100));
|
| + // The focus event is old, don't wait.
|
| + assertFalse(
|
| + cvox.ChromeVoxEventWatcherUtil.shouldWaitToProcess(0, 0, 100));
|
| +});
|
| +
|
| +/**
|
| + * Test that no feedback is received for events that fire on elements
|
| + * that are hidden (or the descendant of a hidden element).
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'AriaHiddenFeedback', function() {
|
| + this.loadHtml('<div>' +
|
| + '<div>' +
|
| + ' <button id="button1">Button 1</button>' +
|
| + ' <button id="button2" aria-hidden="true">Button 2</button>' +
|
| + '</div>' +
|
| + '<div aria-hidden="true">' +
|
| + ' <h3>Random header</h3>' +
|
| + ' <div>' +
|
| + ' <button id="button3">Button 3</button>' +
|
| + ' </div>' +
|
| + ' <h3>Random header</h3>' +
|
| + '</div>' +
|
| + '<div>' +
|
| + ' <button id="button4">Button 4</button>' +
|
| + '</div>' +
|
| + '</div>');
|
| +
|
| + this.setFocus('button1')
|
| + .waitForCalm(this.assertSpoken, 'Button 1 Button')
|
| + .waitForCalm(this.setFocus, 'button2')
|
| + .waitForCalm(this.assertSpoken, '')
|
| + .waitForCalm(this.setFocus, 'button3')
|
| + .waitForCalm(this.assertSpoken, '')
|
| + .waitForCalm(this.setFocus, 'button4')
|
| + .waitForCalm(this.assertSpoken, 'Button 4 Button');
|
| +});
|
| +
|
| +/**
|
| + * Test that key down events don't cause excessive value and state announcements
|
| + * when arrowing around radiobuttons.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'RadioButtonAnnouncements', function() {
|
| + this.loadHtml(
|
| + '<input id="radio1" type="radio" aria-label="green" tabindex=0>' +
|
| + '<input id="radio2" type="radio" aria-label="blue" tabindex=0>');
|
| + function performKeyDown(dir) {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keydown', true, true, window, dir, 0, false, false, false, false);
|
| +
|
| + document.activeElement.dispatchEvent(evt);
|
| + };
|
| +
|
| + var radio1 = $('radio1');
|
| + radio1.focus();
|
| +
|
| + // TODO(dtseng): Repeated actual spoken text here; this is most certainly a
|
| + // test framework bug.
|
| + this.waitForCalm(this.assertSpoken, 'green Radio button unselected')
|
| + .waitForCalm(performKeyDown, 'Right') // right arrow
|
| + // Moves to next radiobutton.
|
| + .waitForCalm(this.assertSpoken,
|
| + 'blue Radio button selected blue Radio button selected')
|
| + .waitForCalm(performKeyDown, 'Right') // right arrow
|
| + // Arrowed beyond end. Should be quiet.
|
| + .waitForCalm(this.assertSpoken, '');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Left') // left arrow
|
| + // Moves back to first radio.
|
| + .waitForCalm(this.assertSpoken,
|
| + 'green Radio button selected green Radio button selected')
|
| + .waitForCalm(performKeyDown, 'Left') // left arrow
|
| + // Arrowed beyond beginning. Should be quiet.
|
| + .waitForCalm(this.assertSpoken, '');
|
| +});
|
| +
|
| +/**
|
| + * Test time widget.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'TimeWidget', function() {
|
| + var chromeVer = -1;
|
| + var userAgent = window.navigator.userAgent;
|
| + var startIndex = userAgent.indexOf('Chrome/');
|
| + if (startIndex != -1) {
|
| + userAgent = userAgent.substring(startIndex + 'Chrome/'.length);
|
| + }
|
| + var endIndex = userAgent.indexOf('.');
|
| + if (endIndex != -1) {
|
| + userAgent = userAgent.substring(0, endIndex);
|
| + }
|
| + // This test will only work on Chrome 23 and higher.
|
| + if (userAgent >= 23) {
|
| + this.loadHtml(
|
| + '<label for="timewidget">Set alarm for:</label>');
|
| + this.loadHtml(
|
| + '<input id="timewidget" type="time" value="12:00">');
|
| + var performKeyDown = function(dir) {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keydown', true, true, window, dir, 0, false, false, false, false);
|
| +
|
| + document.activeElement.dispatchEvent(evt);
|
| + };
|
| + var performKeyUp = function(dir) {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keyup', true, true, window, dir, 0, false, false, false, false);
|
| +
|
| + document.activeElement.dispatchEvent(evt);
|
| + };
|
| +
|
| + var timewidget = $('timewidget');
|
| + timewidget.focus();
|
| +
|
| + this.waitForCalm(this.assertSpoken,
|
| + 'Set alarm for: 12:00 Set alarm for: 12 hours 00 minutes PM');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Down') // down arrow
|
| + .waitForCalm(performKeyUp, 'Down') // down arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + '11 hours');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Down') // down arrow
|
| + .waitForCalm(performKeyUp, 'Down') // down arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + '10 hours');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Right') // right arrow
|
| + .waitForCalm(performKeyUp, 'Right') // right arrow
|
| + .waitForCalm(performKeyDown, 'Up') // right arrow
|
| + .waitForCalm(performKeyUp, 'Up') // right arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + '01 minutes');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Down') // down arrow
|
| + .waitForCalm(performKeyUp, 'Down') // down arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + '00 minutes');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Right') // right arrow
|
| + .waitForCalm(performKeyUp, 'Right') // right arrow
|
| + .waitForCalm(performKeyDown, 'Up') // right arrow
|
| + .waitForCalm(performKeyUp, 'Up') // right arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + 'AM');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Down') // down arrow
|
| + .waitForCalm(performKeyUp, 'Down') // down arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + 'PM');
|
| + }
|
| +});
|
| +
|
| +/**
|
| + * Test date widget.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'DateWidget', function() {
|
| + var chromeVer = -1;
|
| + var userAgent = window.navigator.userAgent;
|
| + var startIndex = userAgent.indexOf('Chrome/');
|
| + if (startIndex != -1) {
|
| + userAgent = userAgent.substring(startIndex + 'Chrome/'.length);
|
| + }
|
| + var endIndex = userAgent.indexOf('.');
|
| + if (endIndex != -1) {
|
| + userAgent = userAgent.substring(0, endIndex);
|
| + }
|
| + // This test will only work on Chrome 25 and higher.
|
| + if (userAgent >= 25) {
|
| + this.loadHtml(
|
| + '<label for="datewidget">Set birthdate:</label>');
|
| + this.loadHtml(
|
| + '<input id="datewidget" type="date" value="1998-09-04"/>');
|
| + var performKeyDown = function(dir) {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keydown', true, true, window, dir, 0, false, false, false, false);
|
| +
|
| + document.activeElement.dispatchEvent(evt);
|
| + };
|
| + var performKeyUp = function(dir) {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keyup', true, true, window, dir, 0, false, false, false, false);
|
| +
|
| + document.activeElement.dispatchEvent(evt);
|
| + };
|
| +
|
| + var datewidget = $('datewidget');
|
| + datewidget.focus();
|
| +
|
| + this.waitForCalm(this.assertSpoken,
|
| + 'Set birthdate: 1998-09-04 Date control Set birthdate: September 4 1998');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Down') // down arrow
|
| + .waitForCalm(performKeyUp, 'Down') // down arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + 'August');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Down') // down arrow
|
| + .waitForCalm(performKeyUp, 'Down') // down arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + 'July');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Right') // right arrow
|
| + .waitForCalm(performKeyUp, 'Right') // right arrow
|
| + .waitForCalm(performKeyDown, 'Up') // right arrow
|
| + .waitForCalm(performKeyUp, 'Up') // right arrow
|
| + .waitForCalm(this.assertSpoken, '5');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Down') // down arrow
|
| + .waitForCalm(performKeyUp, 'Down') // down arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + '4');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Right') // right arrow
|
| + .waitForCalm(performKeyUp, 'Right') // right arrow
|
| + .waitForCalm(performKeyDown, 'Up') // right arrow
|
| + .waitForCalm(performKeyUp, 'Up') // right arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + '1999');
|
| +
|
| + this.waitForCalm(performKeyDown, 'Down') // down arrow
|
| + .waitForCalm(performKeyUp, 'Down') // down arrow
|
| + .waitForCalm(this.assertSpoken,
|
| + '1998');
|
| + }
|
| +});
|
| +
|
| +/**
|
| + * Test video widget.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'VideoWidget', function() {
|
| + this.loadHtml('<video id="chromevideo" poster="star.png" controls>' +
|
| + '<source src="Chrome_ImF.mp4" ' +
|
| + ' type=\'video/mp4; codecs="avc1.42E01E, mp4a.40.2"\' />' +
|
| + '<source src="Chrome_ImF.webm" ' +
|
| + ' type=\'video/webm; codecs="vp8, vorbis"\' />' +
|
| + '<source src="Chrome_ImF.ogv" ' +
|
| + ' type=\'video/ogg; codecs="theora, vorbis"\' />' +
|
| + '</video>');
|
| +
|
| + function performKeyDown(dir) {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keydown', true, true, window, dir, 0, false, false, false, false);
|
| +
|
| + document.activeElement.dispatchEvent(evt);
|
| + };
|
| +
|
| + function performKeyUp(dir) {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keyup', true, true, window, dir, 0, false, false, false, false);
|
| + document.activeElement.dispatchEvent(evt);
|
| + };
|
| +
|
| + var self = this;
|
| + var videowidget = $('chromevideo');
|
| +
|
| + videowidget.onload = function() {
|
| + videowidget.focus();
|
| + self.waitForCalm(performKeyDown, 'Enter')
|
| + .waitForCalm(performKeyUp, 'Enter')
|
| + .waitForCalm(self.assertEquals, videowidget.paused, false);
|
| +
|
| + self.waitForCalm(performKeyDown, 'Right')
|
| + .waitForCalm(performKeyUp, 'Right')
|
| + .waitForCalm(self.assertEquals, videowidget.currentTime, 0);
|
| +
|
| + self.waitForCalm(performKeyDown, 'Down')
|
| + .waitForCalm(performKeyUp, 'Down')
|
| + .waitForCalm(self.assertEquals, videowidget.volume, 0);
|
| + };
|
| +});
|
| +
|
| +/**
|
| + * Test audio widget.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'AudioWidget', function() {
|
| + this.loadHtml(
|
| + '<audio id="chromeaudio" controls>' +
|
| + '<source src="http://www.html5rocks.com/en/tutorials/' +
|
| + 'audio/quick/test.mp3" type="audio/mpeg" />' +
|
| + '<source src="http://www.html5rocks.com/en/tutorials/' +
|
| + 'audio/quick/test.ogg" type="audio/ogg" />');
|
| +
|
| + function performKeyDown(dir) {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keydown', true, true, window, dir, 0, false, false, false, false);
|
| +
|
| + document.activeElement.dispatchEvent(evt);
|
| + };
|
| +
|
| + function performKeyUp(dir) {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keyup', true, true, window, dir, 0, false, false, false, false);
|
| + document.activeElement.dispatchEvent(evt);
|
| + };
|
| +
|
| + var self = this;
|
| + var audiowidget = $('chromeaudio');
|
| +
|
| + audiowidget.onload = function() {
|
| + audiowidget.focus();
|
| + self.waitForCalm(performKeyDown, 'Enter')
|
| + .waitForCalm(performKeyUp, 'Enter')
|
| + .waitForCalm(self.assertEquals, audiowidget.paused, false);
|
| +
|
| + self.waitForCalm(performKeyDown, 'Right')
|
| + .waitForCalm(performKeyUp, 'Right')
|
| + .waitForCalm(self.assertEquals, audiowidget.currentTime, 0);
|
| +
|
| + self.waitForCalm(performKeyDown, 'Down')
|
| + .waitForCalm(performKeyUp, 'Down')
|
| + .waitForCalm(self.assertEquals, audiowidget.volume, 0);
|
| + };
|
| +});
|
| +
|
| +/**
|
| + * Test that ChromeVox speaks the correct state when a focused control
|
| + * changes as the result of a key up, not just key down.
|
| + */
|
| +TEST_F('CvoxEventWatcherUnitTest', 'ToggleOnKeyUp', function() {
|
| + this.loadHtml('<div>' +
|
| + '<div tabIndex=0 id="pressable" role="button" aria-pressed="false">' +
|
| + 'Toggle' +
|
| + '</div>' +
|
| + '</div>');
|
| +
|
| + // Focus on the button.
|
| + this.setFocus('pressable');
|
| + this.waitForCalm(this.assertSpoken, 'Toggle Button Not pressed');
|
| +
|
| + function keyupSpace() {
|
| + var evt = document.createEvent('KeyboardEvent');
|
| + evt.initKeyboardEvent(
|
| + 'keyup', true, true, window, ' ', 0, false, false, false, false);
|
| + document.activeElement.dispatchEvent(evt);
|
| + }
|
| +
|
| + function keyupSpaceAndMarkPressed() {
|
| + keyupSpace();
|
| + $('pressable').setAttribute('aria-pressed', 'true');
|
| + };
|
| +
|
| + function keyupSpaceAndMarkNotPressed() {
|
| + keyupSpace();
|
| + $('pressable').setAttribute('aria-pressed', 'false');
|
| + };
|
| +
|
| + this.waitForCalm(keyupSpaceAndMarkPressed)
|
| + .waitForCalm(this.assertSpoken, 'Pressed')
|
| + .waitForCalm(keyupSpaceAndMarkNotPressed)
|
| + .waitForCalm(this.assertSpoken, 'Not pressed');
|
| +});
|
|
|