1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * @fileoverview Unit test for the Braille IME.
10 * Mock Chrome event supporting one listener.
13 function MockEvent() {}
15 MockEvent.prototype = {
16 /** @type {Function?} */
20 * @param {Function} listener
22 addListener: function(listener) {
23 assertTrue(this.listener === null);
24 this.listener = listener;
28 * Dispatches an event to the listener if any.
29 * @param {...*} var_args Arguments to pass to the event listener.
30 * @return {*} Return value from listener or {@code undefined} if no
33 dispatch: function() {
35 return this.listener.apply(null, arguments);
41 * Mock port that supports the {@code onMessage} and {@code onDisconnect}
42 * events as well as {@code postMessage}.
46 this.onMessage = new MockEvent();
47 this.onDisconnect = new MockEvent();
48 /** @type {Array.<Object>} */
52 MockPort.prototype = {
54 * Stores {@code message} in this object.
55 * @param {Object} message Message to store.
57 postMessage: function(message) {
58 this.messages.push(message);
63 * Engine ID as specified in manifest.
66 ENGINE_ID = 'braille';
71 * Test fixture for the braille IME unit test.
73 * @extends {testing.Test}
75 function BrailleImeUnitTest() {
76 testing.Test.call(this);
79 BrailleImeUnitTest.prototype = {
80 __proto__: testing.Test.prototype,
89 chrome = chrome || {};
90 chrome.input = chrome.input || {};
91 chrome.input.ime = chrome.input.ime || {};
92 chrome.runtime = chrome.runtime || {};
97 createIme: function() {
98 var IME_EVENTS = [ 'onActivate', 'onDeactivated', 'onFocus', 'onBlur',
99 'onInputContextUpdate', 'onKeyEvent', 'onReset',
100 'onMenuItemActivated' ];
101 for (var i = 0, name; name = IME_EVENTS[i]; ++i) {
102 this[name] = chrome.input.ime[name] = new MockEvent();
105 chrome.input.ime.setMenuItems = function(parameters) {
106 this.menuItems = parameters.items;
108 chrome.runtime.connect = function() {
109 this.port = new MockPort();
112 this.menuItems = null;
114 this.ime = new BrailleIme();
118 activateIme: function() {
119 this.onActivate.dispatch(ENGINE_ID);
120 assertThat(this.port.messages,
121 eqJSON([{type: 'activeState', active: true}]));
122 this.port.messages.length = 0;
125 sendKeyDown: function(code, extra) {
126 var event = {code: code, type: 'keydown'};
127 for (var key in extra) {
128 event[key] = extra[key];
130 return this.onKeyEvent.dispatch(ENGINE_ID, event);
133 sendKeyUp: function(code, extra) {
134 var event = {code: code, type: 'keyup'};
135 for (var key in extra) {
136 event[key] = extra[key];
138 return this.onKeyEvent.dispatch(ENGINE_ID, event);
142 TEST_F('BrailleImeUnitTest', 'KeysWhenStandardKeyboardDisabled', function() {
144 expectFalse(this.sendKeyDown('KeyF'));
145 expectFalse(this.sendKeyDown('KeyD'));
146 expectFalse(this.sendKeyUp('KeyD'));
147 expectFalse(this.sendKeyUp('KeyF'));
148 expectEquals(0, this.port.messages.length);
151 TEST_F('BrailleImeUnitTest', 'KeysWhenStandardKeysEnabled', function() {
153 assertFalse(this.menuItems[0].checked);
154 this.onMenuItemActivated.dispatch(ENGINE_ID, this.menuItems[0].id);
155 assertTrue(this.menuItems[0].checked);
156 // Type the letters 'b' and 'c' and verify the right dots get sent.
157 expectTrue(this.sendKeyDown('KeyF'));
158 expectTrue(this.sendKeyDown('KeyD'));
159 expectTrue(this.sendKeyUp('KeyD'));
160 expectTrue(this.sendKeyUp('KeyF'));
161 expectTrue(this.sendKeyDown('KeyJ'));
162 expectTrue(this.sendKeyDown('KeyF'));
163 expectTrue(this.sendKeyUp('KeyJ'));
164 expectTrue(this.sendKeyUp('KeyF'));
166 // Make sure that other keys are not handled, either by themselves or while
167 // one of the 'braille keys' is pressed.
168 expectFalse(this.sendKeyDown('KeyX'));
169 expectFalse(this.sendKeyUp('KeyX'));
171 expectTrue(this.sendKeyDown('KeyS')); // Dot 3
172 expectFalse(this.sendKeyDown('KeyG')); // To the right of dot 1.
173 expectTrue(this.sendKeyUp('KeyS'));
174 expectFalse(this.sendKeyUp('KeyG'));
176 // Keys like Ctrl L should not be handled, despite L being a dot key.
177 var ctrlFlag = {ctrlKey: true};
178 expectFalse(this.sendKeyDown('ControlLeft', ctrlFlag));
179 expectFalse(this.sendKeyDown('KeyL', ctrlFlag));
180 expectFalse(this.sendKeyUp('KeyL', ctrlFlag));
181 expectFalse(this.sendKeyUp('ControlLeft', ctrlFlag))
183 // Space key by itself should send a blank cell.
184 expectTrue(this.sendKeyDown('Space'));
185 expectTrue(this.sendKeyUp('Space'));
187 // Space and braille dots results in no event.
188 expectTrue(this.sendKeyDown('Space'));
189 expectTrue(this.sendKeyDown('KeyF'));
190 expectTrue(this.sendKeyUp('Space'));
191 expectTrue(this.sendKeyUp('KeyF'));
192 // Send the braille key first, still no event should be produced.
193 expectTrue(this.sendKeyDown('KeyF'));
194 expectTrue(this.sendKeyDown('Space'));
195 expectTrue(this.sendKeyUp('Space'));
196 expectTrue(this.sendKeyUp('KeyF'));
198 assertThat(this.port.messages,
199 eqJSON([{type: 'brailleDots', dots: 0x03},
200 {type: 'brailleDots', dots: 0x09},
201 {type: 'brailleDots', dots: 0}]));
204 TEST_F('BrailleImeUnitTest', 'UseStandardKeyboardSettingPreserved', function() {
206 assertFalse(this.menuItems[0].checked);
207 this.onMenuItemActivated.dispatch(ENGINE_ID, this.menuItems[0].id);
208 assertTrue(this.menuItems[0].checked);
209 // Create a new instance and make sure the setting is still turned on.
212 assertTrue(this.menuItems[0].checked);
215 TEST_F('BrailleImeUnitTest', 'ReplaceText', function() {
217 var hasSelection = false;
219 chrome.input.ime.commitText = function(params) {
220 assertEquals(CONTEXT_ID, params.contextID);
223 chrome.input.ime.deleteSurroundingText = function(params, callback) {
224 assertEquals(ENGINE_ID, params.engineID);
225 assertEquals(CONTEXT_ID, params.contextID);
226 assertEquals(0, params.offset + params.length);
228 assertEquals(0, params.length);
229 hasSelection = false;
231 text = text.slice(0, params.offset);
235 var sendReplaceText = function(deleteBefore, newText) {
236 this.port.onMessage.dispatch(
237 {type: 'replaceText', contextID: CONTEXT_ID,
238 deleteBefore: deleteBefore, newText: newText});
241 sendReplaceText(0, 'hello!');
242 assertEquals('Hi, hello!', text);
244 sendReplaceText('hello!'.length, 'good bye!');
245 assertFalse(hasSelection);
246 assertEquals('Hi, good bye!', text);