| // 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); |
| }); |