Roll leveldb 3f7758:803d69 (v1.17 -> v1.18)
[chromium-blink-merge.git] / chrome / test / data / chromeos / virtual_keyboard / inputview / test_base.js
blobe68a17cf5c044d446b977d8e69bd1b87bc81546c
1 /*
2  * Copyright 2014 The Chromium Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
7 var mockController;
8 var mockTimer;
9 var realSetTimeout;
10 var sendMessage;
11 var DEFAULT_CONTEXT_ID = 1;
12 var LONGPRESS_DELAY = 1100;
14 /**
15  * The enumeration of message types. This should be kept in sync with the
16  * InputView enums.
17  * @const
18  * @enum {number}
19  */
20 var Type = {
21   COMMIT_TEXT: 7,
25 /**
26  * Create mocks for the virtualKeyboardPrivate API. Any tests that trigger API
27  * calls must set expectations for call signatures.
28  */
29 function setUp() {
30   realSetTimeout = window.setTimeout;
31   mockController = new MockController();
32   mockTimer = new MockTimer();
33   mockTimer.install();
35   mockController.createFunctionMock(chrome.input.ime, 'commitText');
36   var validateCommit = function(index, expected, observed) {
37     // Only consider the first argument, the details object.
38     var expectedEvent = expected[0];
39     var observedEvent = observed[0];
40     assertEquals(expectedEvent.text,
41                  observedEvent.text,
42                  'Mismatched commit text.');
43   };
44   sendMessage = chrome.runtime.sendMessage;
45   chrome.runtime.sendMessage = function(msg){
46     // Forward message to the mocked method.
47     if (msg.type == Type.COMMIT_TEXT)
48       chrome.input.ime.commitText(msg)
49     else
50       console.error("Unknown message type: " + msg.type);
51   };
52   chrome.input.ime.commitText.validateCall = validateCommit;
55 function RunTest(testFn, testDoneCallback) {
56   var pollTillReady = function() {
57     if (window.isKeyboardReady()) {
58       testFn();
59       testDoneCallback();
60     } else {
61       window.startTest();
62       realSetTimeout(pollTillReady, 100);
63     }
64   }
65   pollTillReady();
68 /**
69  * Verify that API calls match expectations.
70  */
71 function tearDown() {
72   mockController.verifyMocks();
73   mockController.reset();
74   chrome.runtime.sendMessage = sendMessage;
75   mockTimer.uninstall();
78 /**
79 * Checks whether the element is currently being displayed on screen.
80 * @param {Object} The object to check.
81 * @return {boolean}
83 function isActive(el) {
84   return window.getComputedStyle(el).display != "none";
87 (function(exports) {
89   /**
90    * Map from keys to layout specific key ids. This only contains a small subset
91    * of the keys which are used in testing. The ids are based on the XKB layouts
92    * in GoogleKeyboardInput-xkb.crx. Ids that start with a number are escaped
93    * so that document.querySelector returns the correct element.
94    */
95   var KEY_IDS = {
96     'a' : {
97       'us' : '#\\31 01kbd-k-29',
98       'us.compact.qwerty' : '#compactkbd-k-key-11',
99     },
100     'c' : {
101       'us' : '#\\31 01kbd-k-44',
102       'us.compact.qwerty' : '#compactkbd-k-key-24',
103     },
104     'd' : {
105       'us' : '#\\31 01kbd-k-31',
106       'us.compact.qwerty' : '#compactkbd-k-key-13',
107     },
108     'e' : {
109       'us' : '#\\31 01kbd-k-17',
110       'us.compact.qwerty': '#compactkbd-k-key-2',
111     },
112     'l' : {
113       'us' : '#\\31 01kbd-k-37',
114       'us.compact.qwerty' : '#compactkbd-k-key-19',
115     },
116     'p' : {
117       'us' : '#\\31 01kbd-k-24',
118       'us.compact.qwerty' : '#compactkbd-k-key-9',
119     },
120     'leftshift' : {
121       'us' : '#\\31 01kbd-k-41',
122       'us.compact.qwerty' : '#compactkbd-k-21',
123     },
124     "capslock" : {
125       'us' : '#\\31 01kbd-k-28',
126     }
127   };
129   /**
130    * Gets the key id of the specified character.
131    * @param {string} layout The current keyboard layout.
132    * @param {char} char The character to press.
133    */
134   var getKeyId_ = function(layout, char) {
135     var lower = char.toLowerCase();
136     assertTrue(!!KEY_IDS[lower], "Cannot find cached key id: " + char);
137     assertTrue(!!KEY_IDS[lower][layout],
138         "Cannot find cached key id: " + char + " in " + layout);
139     return KEY_IDS[lower][layout];
140   }
142   /**
143    * Returns the current layout id.
144    * @return {string}
145    */
146   var getLayoutId_ = function() {
147     // TODO(rsadam@): Generalize this.
148     var id = window.location.search.split("id=")[1];
149     assertTrue(!!id, "No layout found.");
150     return id;
151   }
153   /**
154    * Returns the layout with the id provided. Periods in the id are replaced by
155    * hyphens.
156    * @param id {string} id The layout id.
157    * @return {object}
158    */
160   var getLayout_ = function(id) {
161     // Escape periods to hyphens.
162     var layoutId = id.replace(/\./g, '-');
163     var layout = document.querySelector('#' + layoutId);
164     assertTrue(!!layout, "Cannot find layout with id: " + layoutId);
165     return layout;
166   }
168   /**
169    * Returns the layout with the id provided. Periods in the id are replaced by
170    * hyphens.
171    * @param id {string} id The layout id.
172    * @return {object}
173    */
175   var getLayout_ = function(id) {
176     // Escape periods to hyphens.
177     var layoutId = id.replace(/\./g, '-');
178     var layout = document.querySelector('#' + layoutId);
179     assertTrue(!!layout, "Cannot find layout with id: " + layoutId);
180     return layout;
181   }
183   /**
184    * Returns the key object corresponding to the character.
185    * @return {string} char The character.
186    */
187   var getKey_ = function(char) {
188     var layoutId = getLayoutId();
189     var layout = getLayout_(layoutId);
191     // All keys in the layout that are in the target keys position.
192     var candidates = layout.querySelectorAll(getKeyId_(layoutId, char));
193     assertTrue(candidates.length > 0, "Cannot find key: " + char);
194     var visible = Array.prototype.filter.call(candidates, isActive);
196     assertEquals(1, visible.length,
197         "Expect exactly one visible key for char: " + char);
198     return visible[0];
199   }
201   exports.getKey = getKey_;
202   exports.getLayoutId = getLayoutId_;
203 })(this);
206  * Generates a mouse event and dispatches it on the target.
207  * @param target {Object} The target of the event.
208  * @param type {String} The type of the mouse event.
209  */
210 function generateMouseEvent(target, type) {
211   var e = new MouseEvent(type, {bubbles:true, cancelable:true});
212   target.dispatchEvent(e);
216  * Mocks a key type using the mouse.
217  * @param {Object} key The key to click on.
218  */
219 function mockMouseTypeOnKey(key) {
220   generateMouseEvent(key, 'mouseover');
221   generateMouseEvent(key, 'mousedown');
222   generateMouseEvent(key, 'mouseup');
223   generateMouseEvent(key, 'click');
224   generateMouseEvent(key, 'mouseover');
225   generateMouseEvent(key, 'mouseout');
229  * Mocks a character type using the mouse. Expects the character will be
230  * committed.
231  * @param {String} char The character to type.
232  */
233 function mockMouseType(char) {
234   var send = chrome.input.ime.commitText;
235   send.addExpectation({
236     contextId: DEFAULT_CONTEXT_ID,
237     text: char,
238   });
239   var key = getKey(char);
240   mockMouseTypeOnKey(key);
244  * Generates a touch event and dispatches it on the target.
245  * @param target {Object} The target of the event.
246  * @param type {String} The type of the touch event.
247  */
248 function generateTouchEvent(target, type) {
249   // UIEvent does not allow mocking pageX pageY of the event, so we use the
250   // parent Event class.
251   var e = document.createEvent('Event');
252   e.initEvent(type, true, true);
253   var rect = target.getBoundingClientRect();
254   e.pageX = rect.left;
255   e.pageY = rect.top;
256   target.dispatchEvent(e);
260  * Mocks a character type using touch.
261  * @param {String} char The expected character.
262  */
263 function mockTouchType(char) {
264   var send = chrome.input.ime.commitText;
265   send.addExpectation({
266     contextId: DEFAULT_CONTEXT_ID,
267     text: char,
268   });
269   var key = getKey(char);
270   generateTouchEvent(key, 'touchstart');
271   generateTouchEvent(key, 'touchend');
275  * Returns, if present, the active alternate key container.
276  * @return {?Object}
277  */
278 function getActiveAltContainer() {
279   // TODO(rsadam): Simplify once code refactor to remove unneeded containers is
280   // complete.
281   var all = document.querySelectorAll('.inputview-altdata-view');
282   var filtered = Array.prototype.filter.call(all, isActive);
283   assertTrue(filtered.length <= 1, "More than one active container.");
284   return filtered.length > 0 ? filtered[0] : null;
288  * Mocks a character long press.
289  * @param {String} char The character to longpress.
290  * @param {Array<string>} altKeys the expected alt keys.
291  * @param {number} index The index of the alt key to select.
292  */
293 function mockLongpress(char, altKeys, index) {
294   var key = getKey(char);
296   generateTouchEvent(key, 'touchstart');
297   mockTimer.tick(LONGPRESS_DELAY);
299   var container = getActiveAltContainer();
300   assertTrue(!!container, "Cannot find active alt container.");
301   var options = container.querySelectorAll('.inputview-altdata-key');
302   assertEquals(altKeys.length, options.length,
303       "Unexpected number of alt keys.");
304   // Check all altKeys present and in order specified.
305   for (var i = 0; i < altKeys.length; i++) {
306     assertEquals(altKeys[i], options[i].textContent);
307   }
308   // Expect selection to be typed
309   var send = chrome.input.ime.commitText;
310   send.addExpectation({
311     contextId: DEFAULT_CONTEXT_ID,
312     text: altKeys[index],
313   });
314   // TODO(rsadam:) Add support for touch move.
315   generateTouchEvent(key, 'touchend', true, true)
316   assertFalse(isActive(container), "Alt key container was not hidden.");