diff options
Diffstat (limited to 'chromium/chrome/browser/resources/chromeos/chromevox/braille/braille_input_handler_test.unitjs')
-rw-r--r-- | chromium/chrome/browser/resources/chromeos/chromevox/braille/braille_input_handler_test.unitjs | 698 |
1 files changed, 0 insertions, 698 deletions
diff --git a/chromium/chrome/browser/resources/chromeos/chromevox/braille/braille_input_handler_test.unitjs b/chromium/chrome/browser/resources/chromeos/chromevox/braille/braille_input_handler_test.unitjs deleted file mode 100644 index aeec1fb08d5..00000000000 --- a/chromium/chrome/browser/resources/chromeos/chromevox/braille/braille_input_handler_test.unitjs +++ /dev/null @@ -1,698 +0,0 @@ -// 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']); - -GEN_INCLUDE(['../testing/fake_objects.js']); - -// Fake out the Chrome API namespace we depend on. -var chrome = {}; -/** Fake chrome.runtime object. */ -chrome.runtime = {}; -/** Fake chrome.virtualKeyboardPrivate object. */ -chrome.virtualKeyboardPrivate = {}; - - -/** - * A fake input field that behaves like the Braille IME and also updates - * the input manager's knowledge about the display content when text changes - * in the edit field. - * @param {FakePort} port A fake port. - * @param {cvox.BrailleInputHandler} inputHandler to work with. - * @constructor - */ -function FakeEditor(port, inputHandler) { - /** @private {FakePort} */ - this.port_ = port; - /** @private {cvox.BrailleInputHandler} */ - this.inputHandler_ = inputHandler; - /** @private {string} */ - this.text_ = ''; - /** @private {number} */ - this.selectionStart_ = 0; - /** @private {number} */ - this.selectionEnd_ = 0; - /** @private {number} */ - this.contextID_ = 0; - /** @private {boolean} */ - this.allowDeletes_ = false; - /** @private {string} */ - this.uncommittedText_ = ''; - /** @private {?Array<number>} */ - this.extraCells_ = []; - port.postMessage = goog.bind(this.handleMessage_, this); -} - - -/** - * Sets the content and selection (or cursor) of the edit field. - * This fakes what happens when the field is edited by other means than - * via the braille keyboard. - * @param {string} text Text to replace the current content of the field. - * @param {number} selectionStart Start of the selection or cursor position. - * @param {number=} opt_selectionEnd End of selection, or ommited if the - * selection is a cursor. - */ -FakeEditor.prototype.setContent = function( - text, selectionStart, opt_selectionEnd) { - this.text_ = text; - this.selectionStart_ = selectionStart; - this.selectionEnd_ = goog.isDef(opt_selectionEnd) ? - opt_selectionEnd : selectionStart; - this.callOnDisplayContentChanged_(); -}; - - -/** - * Sets the selection in the editor. - * @param {number} selectionStart Start of the selection or cursor position. - * @param {number=} opt_selectionEnd End of selection, or ommited if the - * selection is a cursor. - */ -FakeEditor.prototype.select = function(selectionStart, opt_selectionEnd) { - this.setContent(this.text_, selectionStart, opt_selectionEnd); -}; - - -/** - * Inserts text into the edit field, optionally selecting the inserted - * text. - * @param {string} newText Text to insert. - * @param {boolean=} opt_select If {@code true}, selects the inserted text, - * otherwise leaves the cursor at the end of the new text. - */ -FakeEditor.prototype.insert = function(newText, opt_select) { - this.text_ = - this.text_.substring(0, this.selectionStart_) + - newText + - this.text_.substring(this.selectionEnd_); - if (opt_select) { - this.selectionEnd_ = this.selectionStart_ + newText.length; - } else { - this.selectionStart_ += newText.length; - this.selectionEnd_ = this.selectionStart_; - } - this.callOnDisplayContentChanged_(); -}; - - -/** - * Sets whether the editor should cause a test failure if the input handler - * tries to delete text before the cursor. By default, thi value is - * {@code false}. - * @param {boolean} allowDeletes The new value. - */ -FakeEditor.prototype.setAllowDeletes = function(allowDeletes) { - this.allowDeletes_ = allowDeletes; -}; - - -/** - * Signals to the input handler that the Braille IME is active or not active, - * depending on the argument. - * @param {boolean} value Whether the IME is active or not. - */ -FakeEditor.prototype.setActive = function(value) { - this.message_({type: 'activeState', active: value}); -}; - - -/** - * Fails if the current editor content and selection range don't match - * the arguments to this function. - * @param {string} text Text that should be in the field. - * @param {number} selectionStart Start of selection. - * @param {number+} opt_selectionEnd End of selection, default to selection - * start to indicate a cursor. - */ -FakeEditor.prototype.assertContentIs = function( - text, selectionStart, opt_selectionEnd) { - var selectionEnd = goog.isDef(opt_selectionEnd) ? opt_selectionEnd : - selectionStart; - assertEquals(text, this.text_); - assertEquals(selectionStart, this.selectionStart_); - assertEquals(selectionEnd, this.selectionEnd_); -}; - - -/** - * Asserts that the uncommitted text last sent to the IME is the given text. - * @param {string} text - */ -FakeEditor.prototype.assertUncommittedTextIs = function(text) { - assertEquals(text, this.uncommittedText_); -}; - - -/** - * Asserts that the input handler has added 'extra cells' for uncommitted - * text into the braille content. - * @param {string} cells Cells as a space-separated list of numbers. - */ -FakeEditor.prototype.assertExtraCellsAre = function(cells) { - assertEqualsJSON(cellsToArray(cells), this.extraCells_); -}; - - -/** - * Sends a message from the IME to the input handler. - * @param {Object} msg The message to send. - * @private - */ -FakeEditor.prototype.message_ = function(msg) { - var listener = this.port_.onMessage.getListener(); - assertNotEquals(null, listener); - listener(msg); -}; - - -/** - * Calls the {@code onDisplayContentChanged} method of the input handler - * with the current editor content and selection. - * @private - */ -FakeEditor.prototype.callOnDisplayContentChanged_ = function() { - var content = cvox.BrailleUtil.createValue( - this.text_, this.selectionStart_, this.selectionEnd_) - var grabExtraCells = function() { - var span = content.getSpanInstanceOf(cvox.ExtraCellsSpan); - assertNotEquals(null, span); - // Convert the ArrayBuffer to a normal array for easier comparision. - this.extraCells_ = Array.prototype.map.call(new Uint8Array(span.cells), - function(a) {return a;}); - }.bind(this); - this.inputHandler_.onDisplayContentChanged(content, grabExtraCells); - grabExtraCells(); -}; - - -/** - * Informs the input handler that a new text field is focused. The content - * of the field is not cleared and should be updated separately. - * @param {string} fieldType The type of the field (see the documentation - * for the {@code chrome.input.ime} API). - */ -FakeEditor.prototype.focus = function(fieldType) { - this.contextID_++; - this.message_({type: 'inputContext', - context: {type: fieldType, - contextID: this.contextID_}}); -}; - - -/** - * Inform the input handler that focus left the input field. - */ -FakeEditor.prototype.blur = function() { - this.message_({type: 'inputContext', context: null}); - this.contextID_ = 0; -}; - - -/** - * Handles a message from the input handler to the IME. - * @param {Object} msg The message. - * @private - */ -FakeEditor.prototype.handleMessage_ = function(msg) { - assertEquals(this.contextID_, msg.contextID); - switch(msg.type) { - case 'replaceText': - var deleteBefore = msg.deleteBefore; - var newText = msg.newText; - assertTrue(goog.isNumber(deleteBefore)); - assertTrue(goog.isString(newText)); - assertTrue(deleteBefore <= this.selectionStart_); - if (deleteBefore > 0) { - assertTrue(this.allowDeletes_); - this.text_ = - this.text_.substring(0, this.selectionStart_ - deleteBefore) + - this.text_.substring(this.selectionEnd_); - this.selectionStart_ -= deleteBefore; - this.selectionEnd_ = this.selectionStart_; - this.callOnDisplayContentChanged_(); - } - this.insert(newText); - break; - case 'setUncommitted': - assertTrue(goog.isString(msg.text)); - this.uncommittedText_ = msg.text; - break; - case 'commitUncommitted': - this.insert(this.uncommittedText_); - this.uncommittedText_ = ''; - break; - default: - throw new Error('Unexpected message to IME: ' + JSON.stringify(msg)); - } -}; - -/* - * Fakes a {@code Port} used for message passing in the Chrome extension APIs. - * @constructor - */ -function FakePort() { - /** @type {FakeChromeEvent} */ - this.onDisconnect = new FakeChromeEvent(); - /** @type {FakeChromeEvent} */ - this.onMessage = new FakeChromeEvent(); - /** @type {string} */ - this.name = cvox.BrailleInputHandler.IME_PORT_NAME_; - /** @type {{id: string}} */ - this.sender = {id: cvox.BrailleInputHandler.IME_EXTENSION_ID_}; -} - -/** - * Mapping from braille cells to Unicode characters. - * @const Array<Array<string> > - */ -var UNCONTRACTED_TABLE = [ - ['0', ' '], - ['1', 'a'], ['12', 'b'], ['14', 'c'], ['145', 'd'], ['15', 'e'], - ['124', 'f'], ['1245', 'g'], ['125', 'h'], ['24', 'i'], ['245', 'j'], - ['13', 'k'], ['123', 'l'], ['134', 'm'], ['1345', 'n'], ['135', 'o'], - ['1234', 'p'], ['12345', 'q'], ['1235', 'r'], ['234', 's'], ['2345', 't'] -]; - - -/** - * Mapping of braille cells to the corresponding word in Grade 2 US English - * braille. This table also includes the uncontracted table above. - * If a match 'pattern' starts with '^', it must be at the beginning of - * the string or be preceded by a blank cell. Similarly, '$' at the end - * of a 'pattern' means that the match must be at the end of the string - * or be followed by a blank cell. Note that order is significant in the - * table. First match wins. - * @const - */ -var CONTRACTED_TABLE = [ - ['12 1235 123', 'braille'], - ['^12$', 'but'], - ['1456', 'this']].concat(UNCONTRACTED_TABLE); - -/** - * A fake braille translator that can do back translation according - * to one of the tables above. - * @param {Array<Array<number>>} table Backtranslation mapping. - * @param {boolean=} opt_capitalize Whether the result should be capitalized. - * @constructor - */ -function FakeTranslator(table, opt_capitalize) { - /** @private */ - this.table_ = table.map(function(entry) { - var cells = entry[0]; - var result = []; - if (cells[0] === '^') { - result.start = true; - cells = cells.substring(1); - } - if (cells[cells.length - 1] === '$') { - result.end = true; - cells = cells.substring(0, cells.length - 1); - } - result[0] = cellsToArray(cells); - result[1] = entry[1]; - return result; - }); - /** @private {boolean} */ - this.capitalize_ = opt_capitalize || false; -} - - -/** - * Implements the {@code cvox.LibLouis.BrailleTranslator.backTranslate} method. - * @param {!ArrayBuffer} cells Cells to be translated. - * @param {function(?string)} callback Callback for result. - */ -FakeTranslator.prototype.backTranslate = function(cells, callback) { - var cellsArray = new Uint8Array(cells); - var result = ''; - var pos = 0; - while (pos < cellsArray.length) { - var match = null; - outer: for (var i = 0, entry; entry = this.table_[i]; ++i) { - if (pos + entry[0].length > cellsArray.length) { - continue; - } - if (entry.start && pos > 0 && cellsArray[pos - 1] !== 0) { - continue; - } - for (var j = 0; j < entry[0].length; ++j) { - if (entry[0][j] !== cellsArray[pos + j]) { - continue outer; - } - } - if (entry.end && pos + j < cellsArray.length && - cellsArray[pos + j] !== 0) { - continue; - } - match = entry; - break; - } - assertNotEquals( - null, match, - 'Backtranslating ' + cellsArray[pos] + ' at ' + pos); - result += match[1]; - pos += match[0].length; - } - if (this.capitalize_) { - result = result.toUpperCase(); - } - callback(result); -}; - -/** @extends {cvox.BrailleTranslatorManager} */ -function FakeTranslatorManager() { -} - -FakeTranslatorManager.prototype = { - defaultTranslator: null, - uncontractedTranslator: null, - changeListener: null, - - /** @override */ - getDefaultTranslator: function() { - return this.defaultTranslator; - }, - - /** @override */ - getUncontractedTranslator: function() { - return this.uncontractedTranslator; - }, - - /** @override */ - addChangeListener: function(listener) { - assertEquals(null, this.changeListener); - }, - - setTranslators: function(defaultTranslator, uncontractedTranslator) { - this.defaultTranslator = defaultTranslator; - this.uncontractedTranslator = uncontractedTranslator; - if (this.changeListener) { - this.changeListener(); - } - } -}; - -/** - * Converts a list of cells, represented as a string, to an array. - * @param {string} cells A string with space separated groups of digits. - * Each group corresponds to one braille cell and each digit in a group - * corresponds to a particular dot in the cell (1 to 8). As a special - * case, the digit 0 by itself represents a blank cell. - * @return {Array<number>} An array with each cell encoded as a bit - * pattern (dot 1 uses bit 0, etc). - */ -function cellsToArray(cells) { - if (!cells) - return []; - return cells.split(/\s+/).map(function(cellString) { - var cell = 0; - assertTrue(cellString.length > 0); - if (cellString != '0') { - for (var i = 0; i < cellString.length; ++i) { - var dot = cellString.charCodeAt(i) - '0'.charCodeAt(0); - assertTrue(dot >= 1); - assertTrue(dot <= 8); - cell |= 1 << (dot - 1); - } - } - return cell; - }); -} - -/** - * Test fixture. - * @constructor - * @extends {ChromeVoxUnitTestBase} - */ -function CvoxBrailleInputHandlerUnitTest() {} - -CvoxBrailleInputHandlerUnitTest.prototype = { - __proto__: ChromeVoxUnitTestBase.prototype, - - /** @override */ - closureModuleDeps: [ - 'cvox.BrailleInputHandler', - 'cvox.BrailleUtil', - ], - - /** - * Creates an editor and establishes a connection from the IME. - * @return {FakeEditor} - */ - createEditor: function() { - chrome.runtime.onConnectExternal.getListener()(this.port); - return new FakeEditor(this.port, this.inputHandler); - }, - - /** - * Sends a series of braille cells to the input handler. - * @param {string} cells Braille cells, encoded as described in - * {@code cellsToArray}. - * @return {boolean} {@code true} iff all cells were sent successfully. - */ - sendCells: function(cells) { - return cellsToArray(cells).reduce(function(prevResult, cell) { - var event = {command: cvox.BrailleKeyCommand.DOTS, brailleDots: cell}; - return prevResult && this.inputHandler.onBrailleKeyEvent(event); - }.bind(this), true); - }, - - /** - * Sends a standard key event (such as backspace) to the braille input - * handler. - * @param {string} keyCode The key code name. - * @return {boolean} Whether the event was handled. - */ - sendKeyEvent: function(keyCode) { - var event = {command: cvox.BrailleKeyCommand.STANDARD_KEY, - standardKeyCode: keyCode}; - return this.inputHandler.onBrailleKeyEvent(event); - }, - - /** - * Shortcut for asserting that the value expansion mode is {@code NONE}. - */ - assertExpandingNone: function() { - assertEquals(cvox.ExpandingBrailleTranslator.ExpansionType.NONE, - this.inputHandler.getExpansionType()); - }, - - /** - * Shortcut for asserting that the value expansion mode is {@code SELECTION}. - */ - assertExpandingSelection: function() { - assertEquals(cvox.ExpandingBrailleTranslator.ExpansionType.SELECTION, - this.inputHandler.getExpansionType()); - }, - - /** - * Shortcut for asserting that the value expansion mode is {@code ALL}. - */ - assertExpandingAll: function() { - assertEquals(cvox.ExpandingBrailleTranslator.ExpansionType.ALL, - this.inputHandler.getExpansionType()); - }, - - storeKeyEvent: function(event, opt_callback) { - var storedCopy = {keyCode: event.keyCode, keyName: event.keyName, - charValue: event.charValue}; - if (event.type == 'keydown') { - this.keyEvents.push(storedCopy); - } else { - assertEquals('keyup', event.type); - assertTrue(this.keyEvents.length > 0); - assertEqualsJSON(storedCopy, this.keyEvents[this.keyEvents.length - 1]); - } - if (goog.isDef(opt_callback)) { - callback(); - } - }, - - /** @override */ - setUp: function() { - chrome.runtime.onConnectExternal = new FakeChromeEvent(); - this.port = new FakePort(); - this.translatorManager = new FakeTranslatorManager(); - this.inputHandler = new cvox.BrailleInputHandler(this.translatorManager); - this.inputHandler.init(); - this.uncontractedTranslator = new FakeTranslator(UNCONTRACTED_TABLE); - this.contractedTranslator = new FakeTranslator(CONTRACTED_TABLE, true); - chrome.virtualKeyboardPrivate.sendKeyEvent = - this.storeKeyEvent.bind(this); - this.keyEvents = []; - } -}; - -TEST_F('CvoxBrailleInputHandlerUnitTest', 'ConnectFromUnknownExtension', - function() { - this.port.sender.id = 'your unknown friend'; - chrome.runtime.onConnectExternal.getListener()(this.port); - this.port.onMessage.assertNoListener(); -}); - - -TEST_F('CvoxBrailleInputHandlerUnitTest', 'NoTranslator', function() { - var editor = this.createEditor(); - editor.setContent('blah', 0); - editor.setActive(true); - editor.focus('email'); - assertFalse(this.sendCells('145 135 125')); - editor.setActive(false); - editor.blur(); - editor.assertContentIs('blah', 0); -}); - - -TEST_F('CvoxBrailleInputHandlerUnitTest', 'InputUncontracted', function() { - this.translatorManager.setTranslators(this.uncontractedTranslator, null); - var editor = this.createEditor(); - editor.setActive(true); - - // Focus and type in a text field. - editor.focus('text'); - assertTrue(this.sendCells('125 15 123 123 135')); // hello - editor.assertContentIs('hello', 'hello'.length); - this.assertExpandingNone(); - - // Move the cursor and type in the middle. - editor.select(2); - assertTrue(this.sendCells('0 2345 125 15 1235 15 0')); // ' there ' - editor.assertContentIs('he there llo', 'he there '.length); - - // Field changes by some other means. - editor.insert('you!'); - // Then type on the braille keyboard again. - assertTrue(this.sendCells('0 125 15')); // ' he' - editor.assertContentIs('he there you! hello', 'he there you! he'.length); - - editor.blur(); - editor.setActive(false); -}); - - -TEST_F('CvoxBrailleInputHandlerUnitTest', 'InputContracted', function() { - var editor = this.createEditor(); - this.translatorManager.setTranslators(this.contractedTranslator, - this.uncontractedTranslator); - editor.setContent('', 0); - editor.setActive(true); - editor.focus('text'); - this.assertExpandingSelection(); - - // First, type a 'b'. - assertTrue(this.sendCells('12')); - editor.assertContentIs('', 0); - // Remember that the contracted translator produces uppercase. - editor.assertUncommittedTextIs('BUT'); - editor.assertExtraCellsAre('12'); - this.assertExpandingNone(); - - // Typing 'rl' changes to a different contraction. - assertTrue(this.sendCells('1235 123')); - editor.assertUncommittedTextIs('BRAILLE'); - editor.assertContentIs('', 0); - editor.assertExtraCellsAre('12 1235 123'); - this.assertExpandingNone(); - - // Now, finish the word. - assertTrue(this.sendCells('0')); - editor.assertContentIs('BRAILLE ', 'BRAILLE '.length); - editor.assertUncommittedTextIs(''); - editor.assertExtraCellsAre(''); - this.assertExpandingSelection(); - - // Move the cursor to the beginning. - editor.select(0); - this.assertExpandingSelection(); - - // Typing now uses the uncontracted table. - assertTrue(this.sendCells('12')); // 'b' - editor.assertContentIs('bBRAILLE ', 1); - this.assertExpandingSelection(); - editor.select('bBRAILLE'.length); - this.assertExpandingSelection(); - assertTrue(this.sendCells('12')); // 'b' - editor.assertContentIs('bBRAILLEb ', 'bBRAILLEb'.length); - // Move to the end, where contracted typing should work. - editor.select('bBRAILLEb '.length); - assertTrue(this.sendCells('1456 0')); // Symbol for 'this', then space. - this.assertExpandingSelection(); - editor.assertContentIs('bBRAILLEb THIS ', 'bBRAILLEb THIS '.length); - - // Move to between the two words. - editor.select('bBRAILLEb'.length); - this.assertExpandingSelection(); - assertTrue(this.sendCells('0 12')); // Space plus 'b' for 'but' - editor.assertUncommittedTextIs('BUT'); - editor.assertExtraCellsAre('12'); - editor.assertContentIs('bBRAILLEb THIS ', 'bBRAILLEb '.length); - this.assertExpandingNone(); -}); - - -TEST_F('CvoxBrailleInputHandlerUnitTest', 'TypingUrlWithContracted', - function() { - var editor = this.createEditor(); - this.translatorManager.setTranslators(this.contractedTranslator, - this.uncontractedTranslator); - editor.setActive(true); - editor.focus('url'); - this.assertExpandingAll(); - assertTrue(this.sendCells('1245')); // 'g' - editor.insert('oogle.com', true /*select*/); - editor.assertContentIs('google.com', 1, 'google.com'.length); - this.assertExpandingAll(); - this.sendCells('135'); // 'o' - editor.insert('ogle.com', true /*select*/); - editor.assertContentIs('google.com', 2, 'google.com'.length); - this.assertExpandingAll(); - this.sendCells('0'); - editor.assertContentIs('go ', 'go '.length); - // In a URL, even when the cursor is in whitespace, all of the value - // is expanded to uncontracted braille. - this.assertExpandingAll(); -}); - - -TEST_F('CvoxBrailleInputHandlerUnitTest', 'Backspace', function() { - var editor = this.createEditor(); - this.translatorManager.setTranslators(this.contractedTranslator, - this.uncontractedTranslator); - editor.setActive(true); - editor.focus('text'); - - // Add some text that we can delete later. - editor.setContent('Text ', 'Text '.length); - - // Type 'brl' to make sure replacement works when deleting text. - assertTrue(this.sendCells('12 1235 123')); - editor.assertUncommittedTextIs('BRAILLE'); - - // Delete what we just typed, one cell at a time. - this.sendKeyEvent('Backspace'); - editor.assertUncommittedTextIs('BR'); - this.sendKeyEvent('Backspace'); - editor.assertUncommittedTextIs('BUT'); - this.sendKeyEvent('Backspace'); - editor.assertUncommittedTextIs(''); - - // Now, backspace should be handled as usual, synthetizing key events. - assertEquals(0, this.keyEvents.length); - this.sendKeyEvent('Backspace'); - assertEqualsJSON([{keyCode: 8, keyName: 'Backspace', charValue: 8}], - this.keyEvents); -}); - - -TEST_F('CvoxBrailleInputHandlerUnitTest', 'KeysImeNotActive', function() { - var editor = this.createEditor(); - this.sendKeyEvent('Enter'); - this.sendKeyEvent('ArrowUp'); - assertEqualsJSON([{keyCode: 13, keyName: 'Enter', charValue: 0x0A}, - {keyCode: 38, keyName: 'ArrowUp', charValue: 0x41}], - this.keyEvents); -}); |