OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 var mockController; | 7 var mockController; |
8 var mockTimer; | 8 var mockTimer; |
9 var setComposition; | 9 var setComposition; |
10 var realSetTimeout; | |
10 | 11 |
11 var DEFAULT_CONTEXT_ID = 1; | 12 var DEFAULT_CONTEXT_ID = 1; |
13 var LONGPRESS_DELAY = 1100; | |
12 | 14 |
13 /** | 15 /** |
14 * Create mocks for the virtualKeyboardPrivate API. Any tests that trigger API | 16 * Create mocks for the virtualKeyboardPrivate API. Any tests that trigger API |
15 * calls must set expectations for call signatures. | 17 * calls must set expectations for call signatures. |
16 */ | 18 */ |
17 function setUp() { | 19 function setUp() { |
20 realSetTimeout = setTimeout; | |
bshe
2014/06/03 11:35:26
nit: window.setTimeout
rsadam
2014/06/03 13:41:57
Done.
| |
18 mockController = new MockController(); | 21 mockController = new MockController(); |
19 mockTimer = new MockTimer(); | 22 mockTimer = new MockTimer(); |
20 mockTimer.install(); | 23 mockTimer.install(); |
21 | 24 |
22 mockController.createFunctionMock(chrome.input.ime, 'commitText'); | 25 mockController.createFunctionMock(chrome.input.ime, 'commitText'); |
23 var validateCommit = function(index, expected, observed) { | 26 var validateCommit = function(index, expected, observed) { |
24 // Only consider the first argument, the details object. | 27 // Only consider the first argument, the details object. |
25 var expectedEvent = expected[0]; | 28 var expectedEvent = expected[0]; |
26 var observedEvent = observed[0]; | 29 var observedEvent = observed[0]; |
27 assertEquals(expectedEvent.text, | 30 assertEquals(expectedEvent.text, |
28 observedEvent.text, | 31 observedEvent.text, |
29 'Mismatched commit text.'); | 32 'Mismatched commit text.'); |
30 }; | 33 }; |
31 chrome.input.ime.commitText.validateCall = validateCommit; | 34 chrome.input.ime.commitText.validateCall = validateCommit; |
32 | 35 |
33 setComposition = chrome.input.ime.setComposition; | 36 setComposition = chrome.input.ime.setComposition; |
34 // Mocks setComposition manually to immediately callback. The mock controller | 37 // Mocks setComposition manually to immediately callback. The mock controller |
35 // does not support callback functions. | 38 // does not support callback functions. |
36 chrome.input.ime.setComposition = function(obj, callback) { | 39 chrome.input.ime.setComposition = function(obj, callback) { |
37 callback(); | 40 callback(); |
38 } | 41 } |
39 window.setContext({'contextID': DEFAULT_CONTEXT_ID, 'type': 'text'}); | 42 window.setContext({'contextID': DEFAULT_CONTEXT_ID, 'type': 'text'}); |
40 // TODO(rsadam): Mock additional extension API calls as required. | 43 // TODO(rsadam): Mock additional extension API calls as required. |
41 } | 44 } |
42 | 45 |
46 function RunTest(testFn, testDoneCallback) { | |
47 var pollTillReady = function() { | |
48 if (window.isKeyboardReady()) { | |
49 testFn(); | |
50 testDoneCallback(); | |
51 } else | |
52 realSetTimeout(pollTillReady, 100); | |
53 } | |
54 pollTillReady(); | |
55 } | |
56 | |
43 /** | 57 /** |
44 * Verify that API calls match expectations. | 58 * Verify that API calls match expectations. |
45 */ | 59 */ |
46 function tearDown() { | 60 function tearDown() { |
47 mockController.verifyMocks(); | 61 mockController.verifyMocks(); |
48 mockController.reset(); | 62 mockController.reset(); |
49 mockTimer.uninstall(); | 63 mockTimer.uninstall(); |
50 chrome.input.ime.setComposition = setComposition; | 64 chrome.input.ime.setComposition = setComposition; |
51 } | 65 } |
52 | 66 |
53 /** | 67 /** |
54 * Checks whether the element is currently being displayed on screen. | 68 * Checks whether the element is currently being displayed on screen. |
55 * @param {Object} The object to check. | 69 * @param {Object} The object to check. |
56 * @return {boolean} | 70 * @return {boolean} |
57 */ | 71 */ |
58 function isActive(el) { | 72 function isActive(el) { |
59 return window.getComputedStyle(el).display != "none"; | 73 return window.getComputedStyle(el).display != "none"; |
60 } | 74 } |
61 | 75 |
62 (function(exports) { | 76 (function(exports) { |
63 | 77 |
64 /** | 78 /** |
65 * Map from keys to layout specific key ids. This only contains a small subset | 79 * Map from keys to layout specific key ids. This only contains a small subset |
66 * of the keys which are used in testing. The ids are based on the XKB layouts | 80 * of the keys which are used in testing. The ids are based on the XKB layouts |
67 * in GoogleKeyboardInput-xkb.crx. | 81 * in GoogleKeyboardInput-xkb.crx. Ids that start with a number are escaped |
82 * so that document.querySelector returns the correct element. | |
68 */ | 83 */ |
69 var KEY_IDS = { | 84 var KEY_IDS = { |
70 'a' : { | 85 'a' : { |
71 'us' : '101kbd-k-29', | 86 'us' : '#\\31 01kbd-k-29', |
72 'us.compact' : 'compactkbd-k-key-10', | 87 'us.compact.qwerty' : '#compactkbd-k-key-11', |
73 }, | 88 }, |
74 'c' : { | 89 'c' : { |
75 'us' : '101kbd-k-44', | 90 'us' : '#\\31 01kbd-k-44', |
76 'us.compact' : 'compactkbd-k-key-21', | 91 'us.compact.qwerty' : '#compactkbd-k-key-24', |
77 | 92 |
78 }, | 93 }, |
79 'd' : { | 94 'd' : { |
80 'us' : '101kbd-k-31', | 95 'us' : '#\\31 01kbd-k-31', |
81 'us.compact' : 'compactkbd-k-key-12', | 96 'us.compact.qwerty' : '#compactkbd-k-key-13', |
82 | 97 |
83 }, | 98 }, |
99 'e' : { | |
100 'us' : '#\\31 01kbd-k-43', | |
101 'us.compact.qwerty': '#compactkbd-k-key-2', | |
102 }, | |
84 'l' : { | 103 'l' : { |
85 'us' : '101kbd-k-37', | 104 'us' : '#\\31 01kbd-k-37', |
86 'us.compact' : 'compactkbd-k-key-18', | 105 'us.compact.qwerty' : '#compactkbd-k-key-19', |
87 | 106 |
88 }, | 107 }, |
89 'p' : { | 108 'p' : { |
90 'us' : '101kbd-k-24', | 109 'us' : '#\\31 01kbd-k-24', |
91 'us.compact' : 'compactkbd-k-key-9', | 110 'us.compact.qwerty' : '#compactkbd-k-key-9', |
92 }, | 111 }, |
93 'leftshift' : { | 112 'leftshift' : { |
94 'us' : '101kbd-k-41', | 113 'us' : '#\\31 01kbd-k-41', |
95 'us.compact' : 'compactkbd-k-21', | 114 'us.compact.qwerty' : '#compactkbd-k-21', |
96 }, | 115 }, |
97 "capslock" : { | 116 "capslock" : { |
98 'us' : '101kbd-k-28', | 117 'us' : '#\\31 01kbd-k-28', |
99 } | 118 } |
100 }; | 119 }; |
101 | 120 |
102 /** | 121 /** |
103 * Gets the key id of the specified character. | 122 * Gets the key id of the specified character. |
104 * @param {string} layout The current keyboard layout. | 123 * @param {string} layout The current keyboard layout. |
105 * @param {char} char The character to press. | 124 * @param {char} char The character to press. |
106 */ | 125 */ |
107 var getKeyId_ = function(layout, char) { | 126 var getKeyId_ = function(layout, char) { |
108 var lower = char.toLowerCase(); | 127 var lower = char.toLowerCase(); |
109 assertTrue(!!KEY_IDS[lower], "Cannot find cached key id: " + char); | 128 assertTrue(!!KEY_IDS[lower], "Cannot find cached key id: " + char); |
110 assertTrue(!!KEY_IDS[lower][layout], | 129 assertTrue(!!KEY_IDS[lower][layout], |
111 "Cannot find cached key id: " + char + " in " + layout); | 130 "Cannot find cached key id: " + char + " in " + layout); |
112 return KEY_IDS[lower][layout]; | 131 return KEY_IDS[lower][layout]; |
113 } | 132 } |
114 | 133 |
115 /** | 134 /** |
116 * Returns the current layout id. | 135 * Returns the current layout id. |
117 * @return {string} | 136 * @return {string} |
118 */ | 137 */ |
119 var getLayoutId_ = function() { | 138 var getLayoutId_ = function() { |
120 // TODO(rsadam@): Generalize this. | 139 // TODO(rsadam@): Generalize this. |
121 var id = window.location.search.split("id=")[1]; | 140 var id = window.location.search.split("id=")[1]; |
122 assertTrue(!!id, "No layout found."); | 141 assertTrue(!!id, "No layout found."); |
123 return id; | 142 return id; |
124 } | 143 } |
125 | 144 |
126 /** | 145 /** |
146 * Returns the layout with the id provided. Periods in the id are replaced by | |
147 * hyphens. | |
148 * @param id {string} id The layout id. | |
149 * @return {object} | |
150 */ | |
151 | |
152 var getLayout_ = function(id) { | |
153 // Escape periods to hyphens. | |
154 var layoutId = id.replace(/\./g, '-'); | |
155 var layout = document.querySelector('#' + layoutId); | |
156 assertTrue(!!layout, "Cannot find layout with id: " + layoutId); | |
157 return layout; | |
158 } | |
159 | |
160 /** | |
127 * Returns the key object corresponding to the character. | 161 * Returns the key object corresponding to the character. |
128 * @return {string} char The character. | 162 * @return {string} char The character. |
129 */ | 163 */ |
130 var getKey_ = function(char) { | 164 var getKey_ = function(char) { |
131 var layoutId = getLayoutId(); | 165 var layoutId = getLayoutId(); |
132 var key = document.getElementById(getKeyId_(layoutId, char)); | 166 var layout = getLayout_(layoutId); |
133 assertTrue(!!key, "Key not present in layout: " + char); | 167 |
134 return key; | 168 // All keys in the layout that are in the target keys position. |
169 var candidates = layout.querySelectorAll(getKeyId_(layoutId, char)); | |
170 assertTrue(candidates.length > 0, "Cannot find key: " + char); | |
171 var visible = Array.prototype.filter.call(candidates, isActive); | |
172 assertEquals(1, visible.length, | |
173 "Expect exactly one visible key for char: " + char); | |
174 return visible[0]; | |
135 } | 175 } |
136 | 176 |
137 exports.getKey = getKey_; | 177 exports.getKey = getKey_; |
138 exports.getLayoutId = getLayoutId_; | 178 exports.getLayoutId = getLayoutId_; |
139 })(this); | 179 })(this); |
140 | 180 |
141 /** | 181 /** |
142 * Generates a mouse event and dispatches it on the target. | 182 * Generates a mouse event and dispatches it on the target. |
143 * @param target {Object} The target of the event. | 183 * @param target {Object} The target of the event. |
144 * @param type {String} The type of the mouse event. | 184 * @param type {String} The type of the mouse event. |
(...skipping 30 matching lines...) Expand all Loading... | |
175 var key = getKey(char); | 215 var key = getKey(char); |
176 mockMouseTypeOnKey(key); | 216 mockMouseTypeOnKey(key); |
177 } | 217 } |
178 | 218 |
179 /** | 219 /** |
180 * Generates a touch event and dispatches it on the target. | 220 * Generates a touch event and dispatches it on the target. |
181 * @param target {Object} The target of the event. | 221 * @param target {Object} The target of the event. |
182 * @param type {String} The type of the touch event. | 222 * @param type {String} The type of the touch event. |
183 */ | 223 */ |
184 function generateTouchEvent(target, type) { | 224 function generateTouchEvent(target, type) { |
185 var e = document.createEvent('UIEvents'); | 225 // UIEvent does not allow mocking pageX pageY of the event, so we use the |
226 // parent Event class. | |
227 var e = document.createEvent('Event'); | |
186 e.initEvent(type, true, true); | 228 e.initEvent(type, true, true); |
229 var rect = target.getBoundingClientRect(); | |
230 e.pageX = rect.left; | |
231 e.pageY = rect.top; | |
187 target.dispatchEvent(e); | 232 target.dispatchEvent(e); |
188 } | 233 } |
189 | 234 |
190 /** | 235 /** |
191 * Mocks a character type using touch. | 236 * Mocks a character type using touch. |
192 * @param {String} char The expected character. | 237 * @param {String} char The expected character. |
193 */ | 238 */ |
194 function mockTouchType(char) { | 239 function mockTouchType(char) { |
195 var send = chrome.input.ime.commitText; | 240 var send = chrome.input.ime.commitText; |
196 send.addExpectation({ | 241 send.addExpectation({ |
197 contextId: DEFAULT_CONTEXT_ID, | 242 contextId: DEFAULT_CONTEXT_ID, |
198 text: char, | 243 text: char, |
199 }); | 244 }); |
200 var key = getKey(char); | 245 var key = getKey(char); |
201 generateTouchEvent(key, 'touchstart'); | 246 generateTouchEvent(key, 'touchstart'); |
202 generateTouchEvent(key, 'touchend'); | 247 generateTouchEvent(key, 'touchend'); |
203 } | 248 } |
OLD | NEW |