Commit 8175fca0 authored by David Tseng's avatar David Tseng Committed by Commit Bot

Migrate chromevox classic tests

Change-Id: I8d8b30665ac9627c010002561e710449311a952b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1879333Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: David Tseng <dtseng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709354}
parent 04e07bda
......@@ -149,7 +149,8 @@ group("gn_all") {
"//tools/polymer:polymer_tools_python_unittests",
"//ui/accessibility:accessibility_perftests",
"//ui/accessibility:accessibility_unittests",
"//ui/accessibility/extensions",
"//ui/accessibility/extensions:extension_tests",
"//ui/accessibility/extensions:extensions",
]
}
......
......@@ -576,35 +576,9 @@ js2gtest("chromevox_unitjs_tests") {
"braille/braille_input_handler_test.unitjs",
"braille/expanding_braille_translator_test.unitjs",
"braille/pan_strategy_test.unitjs",
"chromevox/injected/event_watcher_test.unitjs",
"chromevox/injected/live_regions_test.unitjs",
"chromevox/injected/navigation_manager_test.unitjs",
"chromevox/injected/user_commands_test.unitjs",
"common/aria_util_test.unitjs",
"common/braille_text_handler_test.unitjs",
"common/braille_util_test.unitjs",
"common/command_store_test.unitjs",
"common/content_editable_extractor_test.unitjs",
"common/cursor_selection_test.unitjs",
"common/dom_util_test.unitjs",
"common/editable_text_area_shadow_test.unitjs",
"common/editable_text_test.unitjs",
"common/find_util_test.unitjs",
"common/key_sequence_test.unitjs",
"common/page_selection_test.unitjs",
"common/selection_util_test.unitjs",
"common/spannable_test.unitjs",
"common/string_util_test.unitjs",
"host/chrome/braille_integration_test.unitjs",
"testing/mock_feedback_test.unitjs",
"walkers/character_walker_test.unitjs",
"walkers/group_walker_test.unitjs",
"walkers/layout_line_walker_test.unitjs",
"walkers/object_walker_test.unitjs",
"walkers/sentence_walker_test.unitjs",
"walkers/structural_line_walker_test.unitjs",
"walkers/table_walker_test.unitjs",
"walkers/word_walker_test.unitjs",
]
gen_include_files = [
"testing/assert_additions.js",
......
......@@ -14,6 +14,15 @@ group("extensions") {
}
}
group("extension_tests") {
testonly = true
if (is_chromeos) {
deps = [
"chromevoxclassic:chromevox_tests",
]
}
}
locale_files = [
"_locales/am/messages.json",
"_locales/ar/messages.json",
......
......@@ -8,7 +8,7 @@ one-click install from the Settings page.
Some of the extensions have localized strings and need to be built:
ninja -C out/Release ui/accessibility/extensions
ninja -C out/Release ui/accessibility/extensions:extensions
The built extensions will be in your out directory, e.g.:
......@@ -19,6 +19,16 @@ All other extensions should be zipped and uploaded to the webstore.
Note for chromevoxclassic:
see chromevoxclassic/README for further details.
You can build all extension tests by doing:
ninja -C out/Release ui/accessibility/extensions:extension_tests
This currently only produces tests for ChromeVox Classic
out/Release/chromevox_tests
This target is not run on a bot, so run it manually before release!
#
# Instructions for publishing to the web store (new as of August 2019):
#
......
......@@ -25,6 +25,15 @@ out/Release/chromevoxclassic.
Go to chrome://extensions, and click "Load
Unpacked". Select out/Release/chromevoxclassic.
#Automated Testing
Build
ninja -C out/Release ui/accessibility/extensions:extension_tests
and run
out/Release/chromevox_tests
## Maintenance/Contributions
Tooling is minimal for this fork of ChromeVox. Much of what's available for
ChromeVox in Chrome OS (chrome/browser/resources/chromeos/chromevox/tools is
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/../testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture for aria_util.js.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* @extends {cvox.BrailleInterface}
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* A TTS class implementing speak and stop methods intended only for testing.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
UnserializableSpan = function() {};
......
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
// 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.
/**
* @fileoverview Dummy earcons implementation for testing.
*
*/
goog.provide('cvox.TestEarcons');
goog.require('cvox.AbstractEarcons');
goog.require('cvox.HostFactory');
/**
* @constructor
* @extends {cvox.AbstractEarcons}
*/
cvox.TestEarcons = function() {
cvox.Earcon.call(this);
};
goog.inherits(cvox.TestEarcons, cvox.AbstractEarcons);
/** @override */
cvox.HostFactory.earconsConstructor = cvox.TestEarcons;
// 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.
/**
* @fileoverview Dummy implementation of host.js for testing.
*
*/
goog.provide('cvox.TestHost');
goog.require('cvox.AbstractHost');
goog.require('cvox.HostFactory');
/**
* @constructor
* @extends {cvox.AbstractHost}
*/
cvox.TestHost = function() {
cvox.AbstractHost.call(this);
};
goog.inherits(cvox.TestHost, cvox.AbstractHost);
/** @override */
cvox.HostFactory.hostConstructor = cvox.TestHost;
// 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.
/**
* @fileoverview Testing stub for MathJax.
*
*/
goog.provide('cvox.TestMathJax');
goog.require('cvox.AbstractMathJax');
goog.require('cvox.HostFactory');
/**
* @constructor
* @extends {cvox.AbstractMathJax}
*/
cvox.TestMathJax = function() {
goog.base(this);
};
goog.inherits(cvox.TestMathJax, cvox.AbstractMathJax);
/**
* @override
*/
cvox.TestMathJax.prototype.isMathjaxActive = function(callback) { };
/**
* @override
*/
cvox.TestMathJax.prototype.getAllJax = function(callback) { };
/**
* @override
*/
cvox.TestMathJax.prototype.registerSignal = function(
callback, signal) { };
/**
* @override
*/
cvox.TestMathJax.prototype.injectScripts = function() { };
/**
* @override
*/
cvox.TestMathJax.prototype.configMediaWiki = function() { };
/**
* @override
*/
cvox.TestMathJax.prototype.getTex = function(callback, texNode) { };
/**
* @override
*/
cvox.TestMathJax.prototype.getAsciiMath = function(callback, asciiMathNode) { };
/** Export platform constructor. */
cvox.HostFactory.mathJaxConstructor =
cvox.TestMathJax;
// 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.
/**
* @fileoverview Dummy implementation of TTS for testing.
*
*/
goog.provide('cvox.TestTts');
goog.require('cvox.AbstractTts');
goog.require('cvox.DomUtil');
goog.require('cvox.HostFactory');
/**
* @constructor
* @extends {cvox.AbstractTts}
*/
cvox.TestTts = function() {
cvox.AbstractTts.call(this);
this.utterances_ = [];
};
goog.inherits(cvox.TestTts, cvox.AbstractTts);
/**
* @type {string}
* @private
*/
cvox.TestTts.prototype.sentinelText_ = '@@@STOP@@@';
/**
* @override
*/
cvox.TestTts.prototype.speak = function(text, queueMode, opt_properties) {
this.utterances_.push(
{text: text, queueMode: queueMode, properties: opt_properties});
if (opt_properties && opt_properties['endCallback'] != undefined) {
var len = this.utterances_.length;
// 'After' is a sentinel value in the tests that tells TTS to stop and
// ends callbacks being called.
if (this.utterances_[len - 1].text != this.sentinelText_) {
opt_properties['endCallback']();
}
}
};
/**
* Creates a sentinel element that indicates when TTS should stop and callbacks
* should stop being called.
* @return {Element} The sentinel element.
*/
cvox.TestTts.prototype.createSentinel = function() {
var sentinel = document.createElement('div');
sentinel.textContent = this.sentinelText_;
return sentinel;
};
/**
* All calls to tts.speak are saved in an array of utterances.
* Clear any utterances that were saved up to this point.
*/
cvox.TestTts.prototype.clearUtterances = function() {
this.utterances_.length = 0;
};
/**
* Return a string of what was spoken by tts.speak().
* @return {string} A single string containing all utterances spoken
* since initialization or the last call to clearUtterances,
* concatenated together with all whitespace collapsed to single
* spaces.
*/
cvox.TestTts.prototype.getUtterancesAsString = function() {
return cvox.DomUtil.collapseWhitespace(this.getUtteranceList().join(' '));
};
/**
* Processes the utterances spoken the same way the speech queue does,
* as if they were all generated one after another, with no delay between
* them, and returns a list of strings that would be output.
*
* For example, if two strings were spoken with a queue mode of FLUSH,
* only the second string will be returned.
* @return {Array<string>} A list of strings representing the speech output.
*/
cvox.TestTts.prototype.getSpeechQueueOutput = function() {
var queue = [];
for (var i = 0; i < this.utterances_.length; i++) {
var utterance = this.utterances_[i];
switch (utterance.queueMode) {
case cvox.AbstractTts.QUEUE_MODE_FLUSH:
queue = [];
break;
case cvox.AbstractTts.QUEUE_MODE_QUEUE:
break;
case cvox.AbstractTts.QUEUE_MODE_CATEGORY_FLUSH:
queue = queue.filter(function(u) {
return (utterance.properties && utterance.properties.category) &&
(!u.properties ||
u.properties.category != utterance.properties.category);
});
break;
}
queue.push(utterance);
}
return queue.map(function(u) {
return u.text;
});
};
/**
* Return a list of strings of what was spoken by tts.speak().
* @return {Array<string>} A list of all utterances spoken since
* initialization or the last call to clearUtterances.
*/
cvox.TestTts.prototype.getUtteranceList = function() {
var result = [];
for (var i = 0; i < this.utterances_.length; i++) {
result.push(this.utterances_[i].text);
}
return result;
};
/**
* Return a list of strings of what was spoken by tts.speak().
* @return {Array<{text: string, queueMode: cvox.QueueMode}>}
* A list of info about all utterances spoken since
* initialization or the last call to clearUtterances.
*/
cvox.TestTts.prototype.getUtteranceInfoList = function() {
return this.utterances_;
};
/** @override */
cvox.HostFactory.ttsConstructor = cvox.TestTts;
// 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.
GEN_INCLUDE(['assert_additions.js']);
GEN_INCLUDE(['common.js', 'callback_helper.js']);
/**
* Base test fixture for ChromeVox unit tests.
*
* Note that while conceptually these are unit tests, these tests need
* to run in a full web page, so they're actually run as WebUI browser
* tests.
*
* @constructor
* @extends {testing.Test}
*/
function ChromeVoxUnitTestBase() {
if (this.isAsync) {
this.callbackHelper_ = new CallbackHelper(this);
}
}
ChromeVoxUnitTestBase.prototype = {
__proto__: testing.Test.prototype,
/** @override */
closureModuleDeps: [
'cvox.ChromeVoxTester',
'cvox.ChromeVoxUserCommands',
'cvox.SpokenListBuilder',
],
/** @override */
browsePreload: DUMMY_URL,
/**
* @override
* It doesn't make sense to run the accessibility audit on these tests,
* since many of them are deliberately testing inaccessible html.
*/
runAccessibilityChecks: false,
/**
* Loads some inlined html into the body of the current document, replacing
* whatever was there previously.
* @param {string} html The html to load as a string.
*/
loadHtml: function(html) {
while (document.head.firstChild) {
document.head.removeChild(document.head.firstChild);
}
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
this.appendHtml(html);
},
/**
* Loads some inlined html into the current document, replacing
* whatever was there previously. This version takes the html
* encoded as a comment inside a function, so you can use it like this:
*
* this.loadDoc(function() {/*!
* <p>Html goes here</p>
* * /});
*
* @param {Function} commentEncodedHtml The html to load, embedded as a
* comment inside an anonymous function - see example, above.
*/
loadDoc: function(commentEncodedHtml) {
var html =
TestUtils.extractHtmlFromCommentEncodedString(commentEncodedHtml);
this.loadHtml(html);
},
/**
* Appends some inlined html into the current document, at the end of
* the body element. Takes the html encoded as a comment inside a function,
* so you can use it like this:
*
* this.appendDoc(function() {/*!
* <p>Html goes here</p>
* * /});
*
* @param {Function} commentEncodedHtml The html to load, embedded as a
* comment inside an anonymous function - see example, above.
*/
appendDoc: function(commentEncodedHtml) {
var html =
TestUtils.extractHtmlFromCommentEncodedString(commentEncodedHtml);
this.appendHtml(html);
},
/**
* Appends some inlined html into the current document, at the end of
* the body element.
* @param {string} html The html to load as a string.
*/
appendHtml: function(html) {
var div = document.createElement('div');
div.innerHTML = html;
var fragment = document.createDocumentFragment();
while (div.firstChild) {
fragment.appendChild(div.firstChild);
}
document.body.appendChild(fragment);
},
/**
* Waits for the queued events in ChromeVoxEventWatcher to be
* handled, then calls a callback function with provided arguments
* in the test case scope. Very useful for asserting the results of events.
*
* @param {function()} func A function to call when ChromeVox is ready.
* @param {*} var_args Additional arguments to pass through to the function.
* @return {ChromeVoxUnitTestBase} this.
*/
waitForCalm: function(func, var_args) {
var calmArguments = Array.prototype.slice.call(arguments);
calmArguments.shift();
cvox.ChromeVoxEventWatcher.addReadyCallback(this.newCallback(function() {
func.apply(this, calmArguments);
}));
return this; // for chaining.
},
/**
* Asserts the TTS engine spoke a certain string. Clears the TTS buffer.
* @param {string} expectedText The expected text.
* @return {ChromeVoxUnitTestBase} this.
*/
assertSpoken: function(expectedText) {
assertEquals(
expectedText, cvox.ChromeVoxTester.testTts().getUtterancesAsString());
cvox.ChromeVoxTester.clearUtterances();
return this; // for chaining.
},
/**
* Asserts a list of utterances are in the correct queue mode.
* @param {cvox.SpokenListBuilder|Array} expectedList A list
* of [text, queueMode] tuples OR a SpokenListBuilder with the expected
* utterances.
* @return {ChromeVoxUnitTestBase} this.
*/
assertSpokenList: function(expectedList) {
if (expectedList instanceof cvox.SpokenListBuilder) {
expectedList = expectedList.build();
}
var ulist = cvox.ChromeVoxTester.testTts().getUtteranceInfoList();
for (var i = 0; i < expectedList.length; i++) {
var text = expectedList[i][0];
var queueMode = expectedList[i][1];
this.assertSingleUtterance_(
text, queueMode, ulist[i].text, ulist[i].queueMode);
}
cvox.ChromeVoxTester.clearUtterances();
return this; // for chaining.
},
assertSingleUtterance_: function(
expectedText, expectedQueueMode, text, queueMode) {
assertEquals(expectedQueueMode, queueMode);
assertEquals(expectedText, text);
},
/**
* Focuses an element.
* @param {string} id The id of the element to focus.
* @return {ChromeVoxUnitTestBase} this.
*/
setFocus: function(id) {
$(id).focus();
return this; // for chaining.
},
/**
* Executes a ChromeVox user command.
* @param {string} command The name of the command to run.
* @return {ChromeVoxUnitTestBase} this.
*/
userCommand: function(command) {
cvox.ChromeVoxUserCommands.commands[command]();
return this; // for chaining.
},
/**
* @return {cvox.SpokenListBuilder} A new builder.
*/
spokenList: function() {
return new cvox.SpokenListBuilder();
},
/**
* @type {CallbackHelper}
* @private
*/
callbackHelper_: null,
/**
* Creates a callback that optionally calls {@code opt_callback} when
* called. If this method is called one or more times, then
* {@code testDone()} will be called when all callbacks have been called.
* @param {Function=} opt_callback Wrapped callback that will have its this
* reference bound to the test fixture.
* @return {Function}
*/
newCallback: function(opt_callback) {
assertNotEquals(null, this.callbackHelper_);
return this.callbackHelper_.wrap(opt_callback);
}
};
// Copyright 2013 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.
/**
* @fileoverview The spoken list builder. Used in test cases.
*/
goog.provide('cvox.SpokenListBuilder');
goog.require('cvox.QueueMode');
/**
* Builds a spoken list.
* @constructor
*/
cvox.SpokenListBuilder = function() {
this.list_ = [];
};
/**
* Adds an expected flushed utterance to the builder.
* @param {string} expectedText The expected text.
* @return {cvox.SpokenListBuilder} this.
*/
cvox.SpokenListBuilder.prototype.flush = function(expectedText) {
this.list_.push([expectedText, cvox.QueueMode.FLUSH]);
return this; // for chaining
};
/**
* Adds an expected queued utterance to the builder.
* @param {string} expectedText The expected text.
* @return {cvox.SpokenListBuilder} this.
*/
cvox.SpokenListBuilder.prototype.queue = function(expectedText) {
this.list_.push([expectedText, cvox.QueueMode.QUEUE]);
return this; // for chaining
};
/**
* Adds an expected category-flush utterance to the builder.
* @param {string} expectedText The expected text.
* @return {cvox.SpokenListBuilder} this.
*/
cvox.SpokenListBuilder.prototype.categoryFlush = function(expectedText) {
this.list_.push([expectedText, cvox.QueueMode.CATEGORY_FLUSH]);
return this; // for chaining
};
/**
* Builds the list.
* @return {Array} The array of utterances.
*/
cvox.SpokenListBuilder.prototype.build = function() {
return this.list_;
};
// 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.
/**
* @fileoverview Testing stub for messages.
*/
goog.provide('TestMsgs');
goog.require('Msgs');
goog.require('cvox.TestMessages');
/**
* @constructor
*/
TestMsgs = function() {};
/**
* @type {function(string, Array<string>=): string}
* @private
*/
TestMsgs.applySubstitutions_ = Msgs.applySubstitutions_;
/**
* @type {Object<string>}
*/
TestMsgs.Untranslated = Msgs.Untranslated;
/**
* @return {string} The locale.
*/
TestMsgs.getLocale = function() {
return 'testing';
};
/**
* @param {string} messageId
* @param {Array<string>=} opt_subs
* @return {string}
*/
TestMsgs.getMsg = function(messageId, opt_subs) {
if (!messageId) {
throw Error('Message id required');
}
var messageString = TestMsgs.Untranslated[messageId.toUpperCase()];
if (messageString === undefined) {
var messageObj =
cvox.TestMessages[('chromevox_' + messageId).toUpperCase()];
if (messageObj === undefined)
throw Error('missing-msg: ' + messageId);
var messageString = messageObj.message;
var placeholders = messageObj.placeholders;
if (placeholders) {
for (name in placeholders) {
messageString =
messageString.replace('$' + name + '$', placeholders[name].content);
}
}
}
return Msgs.applySubstitutions_(messageString, opt_subs);
};
/**
* @param {number} num
* @return {string}
*/
TestMsgs.getNumber = Msgs.getNumber;
// 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.
goog.provide('cvox.ChromeVoxTester');
goog.require('TestMsgs');
goog.require('cvox.AbstractEarcons');
goog.require('cvox.BrailleInterface');
goog.require('cvox.ChromeVoxEventWatcher');
goog.require('cvox.ChromeVoxUserCommands');
goog.require('cvox.LiveRegions');
goog.require('cvox.NavigationManager');
goog.require('cvox.NavigationShifter');
goog.require('cvox.QueueMode');
goog.require('cvox.TestHost');
goog.require('cvox.TestTts');
/**
* @fileoverview Testing framework for ChromeVox.
*
*/
/**
* Initializes cvox.ChromeVoxTester and sets up the mock ChromeVox
* environment.
* @param {!Document} doc The DOM document to add event listeners to.
*/
cvox.ChromeVoxTester.setUp = function(doc) {
cvox.ChromeVox.navigationManager = new cvox.NavigationManager();
cvox.ChromeVoxTester.testTts_ = new cvox.TestTts();
cvox.ChromeVox.tts = cvox.ChromeVoxTester.testTts_;
// TODO(deboer): Factor this out as 'TestEarcons'
cvox.ChromeVox.earcons = new cvox.AbstractEarcons();
cvox.ChromeVox.earcons.playEarcon = function(earcon) {};
cvox.ChromeVox.braille = new cvox.BrailleInterface();
cvox.ChromeVox.braille.write = function(params) {};
Msgs = TestMsgs;
cvox.ChromeVox.host = new cvox.TestHost();
// Init LiveRegions with a date of 0 so that the initial delay before
// things is spoken is skipped.
cvox.LiveRegions.init(new Date(0), cvox.QueueMode.QUEUE, false);
cvox.ChromeVoxEventWatcher.init(doc);
window.console.log('done setup');
};
/**
* Tears down cvox.ChromeVoxTester.
* @param {!Document} doc The DOM document where event listeners were added.
*/
cvox.ChromeVoxTester.tearDown = function(doc) {
cvox.ChromeVoxEventWatcher.cleanup(doc);
};
/**
* Returns the cvox.TestTts created by the tester.
* @return {cvox.TestTts} The TestTts.
*/
cvox.ChromeVoxTester.testTts = function() {
return cvox.ChromeVoxTester.testTts_;
};
/**
* All calls to tts.speak are saved in an array of utterances.
* Clear any utterances that were saved up to this poing.
*/
cvox.ChromeVoxTester.clearUtterances = function() {
cvox.ChromeVoxTester.testTts_.clearUtterances();
};
/**
* Return a list of strings of what was spoken by tts.speak().
* @return {Array<string>} A list of all utterances spoken since
* initialization or the last call to clearUtterances.
*/
cvox.ChromeVoxTester.getUtteranceList = function() {
return cvox.ChromeVoxTester.testTts_.getUtteranceList();
};
/**
* @type {Object<number>} Map from a navigation strategy name to the Navigation
* Manager strategy enum.
*/
cvox.ChromeVoxTester.STRATEGY_MAP = {
'lineardom': cvox.NavigationShifter.GRANULARITIES.OBJECT,
'smart': cvox.NavigationShifter.GRANULARITIES.GROUP,
'selection': cvox.NavigationShifter.GRANULARITIES.SENTENCE
};
/**
* Switches to a different navigation strategy.
* @param {string} strategy The desired navigation strategy.
*/
cvox.ChromeVoxTester.setStrategy = function(strategy) {
cvox.ChromeVox.navigationManager.ensureNotSubnavigating();
cvox.ChromeVox.navigationManager.setGranularity(
cvox.ChromeVoxTester.STRATEGY_MAP[strategy]);
};
/**
* Starts reading the page from the current node.
*/
cvox.ChromeVoxTester.readFromHere = function() {
cvox.ChromeVox.navigationManager.startReading(cvox.QueueMode.FLUSH);
};
/**
* Syncs to the given node in the test HTML
* @param {Node} node The node to sync to.
*/
cvox.ChromeVoxTester.syncToNode = function(node) {
cvox.ChromeVox.navigationManager.updateSel(
cvox.CursorSelection.fromNode(node));
cvox.ChromeVox.navigationManager.sync();
};
/**
* Syncs to the first node in the test.
*/
cvox.ChromeVoxTester.syncToFirstNode = function() {
cvox.ChromeVox.navigationManager.updateSel(cvox.CursorSelection.fromBody());
cvox.ChromeVox.navigationManager.sync();
};
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
// 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(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
* @constructor
* @extends {ChromeVoxUnitTestBase}
*/
function CvoxMathShifterUnitTest() {}
CvoxMathShifterUnitTest.prototype = {
__proto__: ChromeVoxUnitTestBase.prototype,
closureModuleDeps: [
'cvox.ChromeVoxTester',
'cvox.CursorSelection',
'cvox.DescriptionUtil',
'cvox.MathmlStoreRules'
],
/** @override */
setUp: function() {
cvox.ChromeVoxTester.setUp(document);
},
/** @override */
tearDown: function() {
cvox.ChromeVoxTester.tearDown(document);
},
/**
* Simulates speaking the node (only text, no annotations!).
* @param {Node} node The node to be described.
* @return {!string} The resulting string.
*/
getNodeDescription: function(node) {
if (node) {
var descs = cvox.DescriptionUtil.getMathDescription(node);
var descs_str = descs.map(function(desc) {return desc.text;});
return descs_str.filter(function(str) {return str;}).join(' ');
}
return '';
}
};
TEST_F('CvoxMathShifterUnitTest', 'MathmlMtext', function() {
this.loadHtml(
'<div><math xmlns="http://www.w3.org/1998/Math/MathML" id="m0">' +
'<mtext>Quod erat demonstrandum</mtext>' +
'</math></div>'
);
var node = $('m0');
assertEquals('Quod erat demonstrandum', this.getNodeDescription(node));
});
/** Test MathML individual.
* @export
*/
TEST_F('CvoxMathShifterUnitTest', 'MathmlMi', function() {
this.loadHtml(
'<div><math xmlns="http://www.w3.org/1998/Math/MathML" id="m1">' +
'<mi>x</mi>' +
'</math></div>');
var node = $('m1');
assertEquals('x', this.getNodeDescription(node));
});
/** Test MathML numeral.
* @export
*/
TEST_F('CvoxMathShifterUnitTest', 'MathmlMn', function() {
this.loadHtml(
'<div><math xmlns="http://www.w3.org/1998/Math/MathML" id="m2">' +
'<mn>123</mn>' +
'</math></div>');
var node = $('m2');
assertEquals('123', this.getNodeDescription(node));
});
/** Test MathML operator
* @export
*/
TEST_F('CvoxMathShifterUnitTest', 'MathmlMo', function() {
this.loadHtml(
'<div><math xmlns="http://www.w3.org/1998/Math/MathML" id="m3">' +
'<mo>+</mo>' +
'</math></div>');
var node = $('m3');
assertEquals('+', this.getNodeDescription(node));
});
/** Test MathML superscript.
* @export
*/
TEST_F('CvoxMathShifterUnitTest', 'MathmlMsup', function() {
this.loadHtml(
'<div><math xmlns="http://www.w3.org/1998/Math/MathML" id="m4">' +
'<msup><mi>x</mi><mn>4</mn></msup>' +
'</math></div>');
var node = $('m4');
assertEquals('x super 4', this.getNodeDescription(node));
});
/** Test MathML subscript.
* @export
*/
TEST_F('CvoxMathShifterUnitTest', 'MathmlMsub', function() {
this.loadHtml(
'<div><math xmlns="http://www.w3.org/1998/Math/MathML" id="m5">' +
'<msub><mi>x</mi><mn>3</mn></msub>' +
'</math></div>');
var node = $('m5');
assertEquals('x sub 3', this.getNodeDescription(node));
});
/** Test MathML subsupscript.
* @export
*/
TEST_F('CvoxMathShifterUnitTest', 'MathmlMsubsup', function() {
this.loadHtml(
'<div><math xmlns="http://www.w3.org/1998/Math/MathML" id="m6">' +
'<msubsup><mi>x</mi><mn>3</mn><mn>4</mn></msubsup>' +
'</math></div>');
var node = $('m6');
assertEquals('x sub 3 super 4', this.getNodeDescription(node));
});
......@@ -3,7 +3,7 @@
// found in the LICENSE file.
// Include test fixture.
GEN_INCLUDE(['../testing/chromevox_unittest_base.js']);
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Test fixture.
......
// 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.
GEN_INCLUDE(['//chrome/browser/resources/chromeos/chromevox/testing/chromevox_unittest_base.js']);
/**
* Base class for walker test fixtures.
* @constructor
* @extends {ChromeVoxUnitTestBase}
*/
function ChromeVoxWalkerUnitTestBase() {}
ChromeVoxWalkerUnitTestBase.prototype = {
__proto__: ChromeVoxUnitTestBase.prototype,
/** @override */
closureModuleDeps: [
'TestMsgs',
'cvox.CursorSelection'
],
/**
* Common set up for all walker test cases.
*/
setUp: function() {
// Needed for getDescription and getGranularityMsg.
Msgs = TestMsgs;
// Delete all nodes in the body.
while (document.body.hasChildNodes()) {
document.body.removeChild(document.body.lastChild);
}
this.walker = this.newWalker();
},
/**
* Returns a new walker appropriate for the child test.
* @return {!cvox.AbstractWalker} The walker instance.
*/
// Closure library is not available when this literal is evaluated, so
// we can't use goog.abstractMethod here.
newWalker: function() {
throw Error('newWalker not implemented.');
},
/**
* Makes testing much less verbose. Executes the command on the
* selection, then asserts that for all the parameters passed in desc,
* the new selection matches. Returns the new selections if assertion passes.
* NOTE: If you change the parameters here, you should also change the
* whitelist above.
* @param {!cvox.CursorSelection} sel The selection.
* @param {!string|!cvox.CursorSelection} opt_cmdOrDest The command to
* execute, or the override returned selection.
* @param {{selText: string=,
* selNodeId: string=,
* selParentNodeId: string=,
* selStartIndex: number=,
* selEndIndex: number=,
* selReversed: boolean=,
* descText: string=,
* descContext: string=,
* descAnnotation: string=,
* descUserValue: string=,
* descPersonality: string=}} desc The parameters to assert.
* selText: The text in the new selection matches for both start and end.
* selNodeId: The node in the new selection matches for both start and end.
* selParentNodeId: The parent node of both start and end matches.
* selStartIndex: The index of the absolute start.
* selEndIndex: The index of the absolute end.
* selReversed: True if should be reversed.
* descText: The text in the NavDescription when getDescription is called.
* descContext: The context in the NavDescription
* descAnnotation: The annotation in the NavDescription
* descUserValue: The userValue in the NavDescription
* descPersonality: The personality in the NavDescription
* @return {cvox.CursorSelection} The new selection.
*/
go: function(sel, opt_cmdOrDest, desc) {
if (opt_cmdOrDest instanceof cvox.CursorSelection) {
var ret = opt_cmdOrDest;
} else {
if (ChromeVoxWalkerUnitTestBase.CMD_WHITELIST.indexOf(opt_cmdOrDest) == -1) {
// Intentionally fail the test if there's a typo.
throw 'Got an invalid command: "' + opt_cmdOrDest + '".';
}
var ret = this.walker[opt_cmdOrDest](sel);
}
if (ret == null) {
assertEquals(null, desc);
return;
}
if (desc == null) {
assertEquals(null, ret);
return;
}
for (var key in desc) {
if (ChromeVoxWalkerUnitTestBase.DESC_WHITELIST.indexOf(key) == -1) {
throw 'Invalid key in desc parameter: "' + key + '".';
}
}
// Intentionally only check one-to-one and not onto. This allows us to
// write tests that just ignore everything except what we care about.
if (desc.hasOwnProperty('selText')) {
assertEquals(desc.selText, ret.start.text);
assertEquals(desc.selText, ret.end.text);
}
if (desc.hasOwnProperty('selNodeId')) {
assertEquals(desc.selNodeId, ret.start.node.id);
assertEquals(desc.selNodeId, ret.end.node.id);
}
if (desc.hasOwnProperty('selParentNodeId')) {
assertEquals(desc.selParentNodeId, ret.start.node.parentNode.id);
assertEquals(desc.selParentNodeId, ret.end.node.parentNode.id);
}
if (desc.hasOwnProperty('selStartIndex')) {
assertEquals(desc.selStartIndex, ret.absStart().index);
}
if (desc.hasOwnProperty('selEndIndex')) {
assertEquals(desc.selEndIndex, ret.absEnd().index);
}
if (desc.hasOwnProperty('selReversed')) {
assertEquals(desc.selReversed, ret.isReversed());
}
var trueDesc = this.walker.getDescription(sel, ret)[0];
if (desc.hasOwnProperty('descText')) {
assertEquals(desc.descText, trueDesc.text);
}
if (desc.hasOwnProperty('descContext')) {
assertEquals(desc.descContext, trueDesc.context);
}
if (desc.hasOwnProperty('descAnnotation')) {
assertEquals(desc.descAnnotation, trueDesc.annotation);
}
if (desc.hasOwnProperty('descUserValue')) {
assertEquals(desc.descUserValue, trueDesc.userValue);
}
if (desc.hasOwnProperty('descPersonality')) {
assertEquals(desc.descPersonality, trueDesc.personality);
}
return ret;
},
};
/**
* Whitelist for the commands that are allowed to be executed with go().
* @type {Array.string}
* @const
*/
ChromeVoxWalkerUnitTestBase.CMD_WHITELIST = ['next', 'sync', 'nextRow', 'nextCol'];
/**
* Whitelist for the properties that can be asserted with go().
* @type {Array.string}
* @const
*/
ChromeVoxWalkerUnitTestBase.DESC_WHITELIST = ['selText', 'selNodeId',
'selParentNodeId', 'selStartIndex', 'selEndIndex', 'selReversed', 'descText',
'descContext', 'descAnnotation', 'descUserValue', 'descPersonality'];
/**
* Adds common walker tests
* @param {string} testFixture Name of the test fixture class.
*/
ChromeVoxWalkerUnitTestBase.addCommonTests = function(testFixture) {
/**
* Ensures that syncing to the beginning and ends of the page return
* not null.
*/
TEST_F(testFixture, 'testSyncToPage', function() {
this.loadDoc(function() {/*!
<div><p id="a">a</p></div>
*/});
var ret = this.walker.begin();
assertNotEquals(null, ret);
ret = this.walker.begin({reversed: true});
assertNotEquals(null, ret);
});
/**
* Ensures that sync(sync(sel)) = sync(sel)
* TODO (stoarca): The interfaces are not frozen yet. In particular,
* for TableWalker, sync can return null. Override if it doesn't work yet.
*/
TEST_F(testFixture, 'testSyncInvariant', function() {
this.loadDoc(function() {/*!
<div id="outer">
<p id="a">a</p>
<p id="b">b</p>
<p id="c">c</p>
<p id="d">d</p>
<h1 id="A">h1</h1>
<p id="e">e</p>
<h1 id="B">h1</h1>
</div>
*/});
var sel = cvox.CursorSelection.fromNode(
$('outer').firstChild);
var sync = this.walker.sync(sel);
var syncsync = this.walker.sync(sync);
assertEquals(true, sync.equals(syncsync));
sel = cvox.CursorSelection.fromNode($('a'));
sync = this.walker.sync(sel);
syncsync = this.walker.sync(sync);
assertEquals(true, sync.equals(syncsync));
sel = cvox.CursorSelection.fromNode($('e'));
sync = this.walker.sync(sel);
syncsync = this.walker.sync(sync);
assertEquals(true, sync.equals(syncsync));
sel = cvox.CursorSelection.fromBody();
sync = this.walker.sync(sel);
syncsync = this.walker.sync(sync);
assertEquals(true, sync.equals(syncsync));
});
/**
* Ensures that all operations work on an empty body.
*/
TEST_F(testFixture, 'testEmptyBody', function() {
var sel = cvox.CursorSelection.fromBody();
// Testing for infinite loop. If one exists, this test will fail by timing
// out.
var sync = this.walker.sync(sel);
var next = this.walker.next(sel);
});
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment