OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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. | |
4 | |
5 /** | |
6 * @fileoverview Tests for chrome://bluetooth-internals | |
7 */ | |
8 | |
9 /** @const {string} Path to source root. */ | |
10 var ROOT_PATH = '../../../../'; | |
11 | |
12 /** | |
13 * Test fixture for BluetoothInternals WebUI testing. | |
14 * @constructor | |
15 * @extends testing.Test | |
16 */ | |
17 function BluetoothInternalsTest() { | |
18 this.adapterFactory = null; | |
19 this.setupResolver = new PromiseResolver(); | |
20 } | |
21 | |
22 BluetoothInternalsTest.prototype = { | |
23 __proto__: testing.Test.prototype, | |
24 | |
25 /** @override */ | |
26 browsePreload: 'chrome://bluetooth-internals', | |
27 | |
28 /** @override */ | |
29 isAsync: true, | |
30 | |
31 /** @override */ | |
32 runAccessibilityChecks: false, | |
33 | |
34 /** @override */ | |
35 extraLibraries: [ | |
36 ROOT_PATH + 'third_party/mocha/mocha.js', | |
37 ROOT_PATH + 'chrome/test/data/webui/mocha_adapter.js', | |
38 ROOT_PATH + 'ui/webui/resources/js/promise_resolver.js', | |
39 ROOT_PATH + 'ui/webui/resources/js/cr.js', | |
40 ROOT_PATH + 'ui/webui/resources/js/util.js', | |
41 ROOT_PATH + 'chrome/test/data/webui/settings/test_browser_proxy.js', | |
42 ], | |
43 | |
44 preLoad: function() { | |
45 // A function that is called from chrome://bluetooth-internals to allow this | |
46 // test to replace the real Mojo browser proxy with a fake one, before any | |
47 // other code runs. | |
48 window.setupFn = function() { | |
49 console.log('Importing modules'); | |
50 return importModules([ | |
51 'content/public/renderer/frame_interfaces', | |
dpapad
2016/11/02 23:19:14
Nit: There is 2 more spaces of indentation than ne
mbrunson
2016/11/03 20:59:05
Done.
| |
52 'device/bluetooth/public/interfaces/adapter.mojom', | |
53 'device/bluetooth/public/interfaces/device.mojom', | |
54 'mojo/public/js/bindings', | |
55 'mojo/public/js/connection', | |
56 ]).then(function([frameInterfaces, adapter, device, bindings, | |
57 connection]) { | |
58 console.log('Modules imported'); | |
dpapad
2016/11/02 23:19:15
Can you remove this.
mbrunson
2016/11/03 20:59:05
Done.
| |
59 | |
60 /** | |
61 * A test adapter factory proxy for the chrome://bluetooth-internals | |
62 * page. | |
63 * | |
64 * @constructor | |
65 * @extends {TestBrowserProxyBase} | |
66 */ | |
67 var TestAdapterFactoryProxy = function() { | |
68 settings.TestBrowserProxy.call(this, [ | |
69 'getAdapter', | |
70 ]); | |
71 | |
72 this.adapter = new TestAdapter(); | |
73 this.adapterHandle_ = connection.bindStubDerivedImpl(this.adapter); | |
74 }; | |
75 | |
76 TestAdapterFactoryProxy.prototype = { | |
77 __proto__: settings.TestBrowserProxy.prototype, | |
78 getAdapter: function() { | |
79 this.methodCalled('getAdapter'); | |
80 | |
81 // Create message pipe bound to TestAdapter. | |
82 return Promise.resolve({ | |
83 adapter: this.adapterHandle_, | |
84 }); | |
85 } | |
86 }; | |
87 | |
88 /** | |
89 * A test adapter for the chrome://bluetooth-internals page. | |
90 * Must be used to create message pipe handle from test code. | |
91 * | |
92 * @constructor | |
93 * @extends {adapter.Adapter.stubClass} | |
94 */ | |
95 var TestAdapter = function() { | |
96 this.proxy = new TestAdapterProxy(); | |
97 }; | |
98 | |
99 TestAdapter.prototype = { | |
100 __proto__: adapter.Adapter.stubClass.prototype, | |
101 getInfo: function() { return this.proxy.getInfo(); }, | |
102 getDevices: function() { return this.proxy.getDevices(); }, | |
103 setClient: function(client) { return this.proxy.setClient(client); } | |
104 }; | |
105 | |
106 /** | |
107 * A test adapter proxy for the chrome://bluetooth-internals page. | |
108 * | |
109 * @constructor | |
110 * @extends {TestBrowserProxyBase} | |
111 */ | |
112 var TestAdapterProxy = function() { | |
113 settings.TestBrowserProxy.call(this, [ | |
114 'getInfo', | |
115 'getDevices', | |
116 'setClient', | |
117 ]); | |
118 | |
119 this.client = null; | |
120 | |
121 this.adapterInfo_ = null; | |
122 this.devices_ = []; | |
123 }; | |
124 | |
125 TestAdapterProxy.prototype = { | |
126 __proto__: settings.TestBrowserProxy.prototype, | |
127 getInfo: function() { | |
128 this.methodCalled('getInfo'); | |
129 return Promise.resolve({ info: this.adapterInfo_ }); | |
dpapad
2016/11/02 23:19:15
No need for spaces {info: this.adapterInfo_}
mbrunson
2016/11/03 20:55:10
Done.
| |
130 }, | |
dpapad
2016/11/02 23:19:15
\n between functions
mbrunson
2016/11/03 20:55:10
Done.
| |
131 getDevices: function() { | |
132 this.methodCalled('getDevices'); | |
133 return Promise.resolve({ devices: this.devices_ }); | |
134 }, | |
135 setClient: function(client) { | |
136 this.methodCalled('setClient', client); | |
137 this.client = connection.bindHandleToProxy(client, | |
138 adapter.AdapterClient); | |
dpapad
2016/11/02 23:19:15
Indent is off. Also try to keep all arguments on t
mbrunson
2016/11/03 20:55:10
Done.
| |
139 }, | |
140 setTestAdapter: function(adapterInfo) { | |
141 this.adapterInfo_ = adapterInfo; | |
142 }, | |
143 setTestDevices: function(devices) { | |
144 this.devices_ = devices; | |
145 } | |
146 }; | |
147 | |
148 | |
149 frameInterfaces.addInterfaceOverrideForTesting( | |
150 adapter.AdapterFactory.name, | |
151 function(handle) { | |
152 var stub = connection.bindHandleToStub( | |
153 handle, adapter.AdapterFactory); | |
dpapad
2016/11/02 23:19:15
Indent off by 2.
mbrunson
2016/11/03 20:55:10
Done.
| |
154 this.adapterFactory = new TestAdapterFactoryProxy(); | |
155 bindings.StubBindings(stub).delegate = this.adapterFactory; | |
156 | |
157 this.setupResolver.resolve(); | |
158 }.bind(this)); | |
159 | |
dpapad
2016/11/02 23:19:15
Nit: Remove \n
mbrunson
2016/11/03 20:55:10
Done.
| |
160 }.bind(this)); | |
161 }.bind(this); | |
162 }, | |
163 }; | |
164 | |
165 TEST_F('BluetoothInternalsTest', 'Startup_BluetoothInternals', function() { | |
166 var fakeAdapterInfo = { | |
167 address: '02:1C:7E:6A:11:5A', | |
168 discoverable: false, | |
169 discovering: false, | |
170 initialized: true, | |
171 name: 'computer.example.com-0', | |
172 powered: true, | |
173 present: true, | |
174 }; | |
175 | |
176 var fakeDeviceInfo1 = { | |
177 address: "AA:AA:84:96:92:84", | |
178 name: "AAA", | |
179 name_for_display: "AAA", | |
180 rssi: {value: -40}, | |
181 services: [] | |
182 }; | |
183 | |
184 var fakeDeviceInfo2 = { | |
185 address: "BB:BB:84:96:92:84", | |
186 name: "BBB", | |
187 name_for_display: "BBB", | |
188 rssi: null, | |
189 services: [] | |
190 }; | |
191 | |
192 var fakeDeviceInfo3 = { | |
193 address: "CC:CC:84:96:92:84", | |
194 name: "CCC", | |
195 name_for_display: "CCC", | |
196 }; | |
197 | |
198 var adapterFactory = null; | |
199 | |
200 // Before tests are run, make sure setup completes. | |
201 var setupPromise = this.setupResolver.promise.then(function() { | |
202 adapterFactory = this.adapterFactory; | |
203 }.bind(this)); | |
204 | |
205 | |
206 suite('BluetoothInternalsUITest', function() { | |
207 var EXPECTED_DEVICES = 2; | |
208 | |
209 suiteSetup(function() { | |
210 return setupPromise.then(function() { | |
211 adapterFactory.adapter.proxy.setTestDevices([ | |
212 fakeDeviceInfo1, | |
213 fakeDeviceInfo2 | |
214 ]); | |
215 adapterFactory.adapter.proxy.setTestAdapter(fakeAdapterInfo); | |
216 | |
217 return Promise.all([ | |
218 adapterFactory.whenCalled('getAdapter'), | |
219 adapterFactory.adapter.proxy.whenCalled('getInfo'), | |
220 adapterFactory.adapter.proxy.whenCalled('getDevices'), | |
221 ]); | |
222 }); | |
223 }); | |
224 | |
225 setup(function() { | |
226 var devices = new device_collection.DeviceCollection([]); | |
227 adapterClient.devices = devices; | |
228 deviceTable.setDevices(devices); | |
229 adapterClient.deviceAdded(fakeDeviceInfo1); | |
230 adapterClient.deviceAdded(fakeDeviceInfo2); | |
231 }); | |
232 | |
233 teardown(function() { | |
234 adapterFactory.reset(); | |
235 }); | |
236 | |
237 /** | |
238 * Updates device info and verifies the contents of the device table. | |
239 * @param {!device_collection.DeviceInfo} deviceInfo | |
240 */ | |
241 function changeDevice(deviceInfo) { | |
242 var deviceRow = document.querySelector('#' + escapeDeviceAddress( | |
243 deviceInfo.address)); | |
244 var nameForDisplayColumn = deviceRow.children[0]; | |
245 var addressColumn = deviceRow.children[1]; | |
246 var rssiColumn = deviceRow.children[2]; | |
247 var servicesColumn = deviceRow.children[3]; | |
248 | |
249 expectTrue(!!nameForDisplayColumn); | |
250 expectTrue(!!addressColumn); | |
251 expectTrue(!!rssiColumn); | |
252 expectTrue(!!servicesColumn); | |
253 | |
254 adapterClient.deviceChanged(deviceInfo); | |
255 | |
256 expectEquals(deviceInfo.name_for_display, | |
257 nameForDisplayColumn.textContent); | |
258 expectEquals(deviceInfo.address, addressColumn.textContent); | |
259 | |
260 expectEquals(String(deviceInfo.rssi.value), rssiColumn.textContent); | |
261 | |
262 if (deviceInfo.services) { | |
263 expectEquals(String(deviceInfo.services.length), | |
264 servicesColumn.textContent); | |
265 } else { | |
266 expectEquals('Unknown', servicesColumn.textContent); | |
267 } | |
268 } | |
269 | |
270 /** | |
271 * Escapes colons in a device address for CSS formatting. | |
272 * @param {!string} address | |
dpapad
2016/11/02 23:19:15
"!" is implied for number,boolean,string, so not n
mbrunson
2016/11/03 20:55:10
Done.
| |
273 */ | |
274 function escapeDeviceAddress(address) { | |
275 return address.replace(/:/g, '\\:'); | |
276 } | |
277 | |
278 /** | |
279 * Expects whether device with |address| is removed. | |
280 * @param {!string} address | |
281 * @param {!boolean} expectRemoved | |
282 */ | |
283 function expectDeviceRemoved(address, expectRemoved) { | |
284 var removedRow = document.querySelector('#' + escapeDeviceAddress( | |
285 address)); | |
286 | |
287 expectEquals(expectRemoved, removedRow.classList.contains('removed')); | |
288 } | |
289 | |
290 /** | |
291 * Tests whether a device is added successfully and not duplicated. | |
292 */ | |
293 test('DeviceAdded', function() { | |
294 var devices = document.querySelectorAll('#device-table tbody tr'); | |
295 expectEquals(EXPECTED_DEVICES, devices.length); | |
296 | |
297 adapterClient.deviceAdded(fakeDeviceInfo3); | |
298 | |
299 // Same device shouldn't appear twice. | |
300 adapterClient.deviceAdded(fakeDeviceInfo3); | |
301 | |
302 devices = document.querySelectorAll('#device-table tbody tr'); | |
303 expectEquals(EXPECTED_DEVICES + 1, devices.length); | |
304 }); | |
305 | |
306 /** | |
307 * Tests whether a device is marked properly as removed. | |
308 */ | |
309 test('DeviceSetToRemoved', function() { | |
310 var devices = document.querySelectorAll('#device-table tbody tr'); | |
311 expectEquals(EXPECTED_DEVICES, devices.length); | |
312 adapterClient.deviceRemoved(fakeDeviceInfo2); | |
313 | |
314 // The number of rows shouldn't change. | |
315 devices = document.querySelectorAll('#device-table tbody tr'); | |
316 expectEquals(EXPECTED_DEVICES, devices.length); | |
317 | |
318 expectDeviceRemoved(fakeDeviceInfo2.address, true); | |
319 }); | |
320 | |
321 /** | |
322 * Tests whether a changed device updates the device table properly. | |
323 */ | |
324 test('DeviceChanged', function() { | |
325 var devices = document.querySelectorAll('#device-table tbody tr'); | |
326 expectEquals(EXPECTED_DEVICES, devices.length); | |
327 | |
328 var newDeviceInfo = Object.assign({}, fakeDeviceInfo1); | |
329 newDeviceInfo.name_for_display = 'DDDD'; | |
330 newDeviceInfo.rssi = { value: -20 }; | |
331 newDeviceInfo.services = ['service1', 'service2', 'service3']; | |
332 | |
333 changeDevice(newDeviceInfo); | |
334 }); | |
335 | |
336 /** | |
337 * Tests the entire device cycle: added -> updated -> removed -> re-added. | |
338 */ | |
339 test('DeviceUpdateCycle', function() { | |
340 var devices = document.querySelectorAll('#device-table tbody tr'); | |
341 expectEquals(EXPECTED_DEVICES, devices.length); | |
342 | |
343 adapterClient.deviceAdded(fakeDeviceInfo3); | |
344 | |
345 var newDeviceInfo = Object.assign({}, fakeDeviceInfo3); | |
346 newDeviceInfo.name_for_display = 'DDDD'; | |
347 newDeviceInfo.rssi = { value: -20 }; | |
348 newDeviceInfo.services = ['service1', 'service2', 'service3']; | |
349 | |
350 changeDevice(newDeviceInfo); | |
351 changeDevice(fakeDeviceInfo3); | |
352 | |
353 adapterClient.deviceRemoved(fakeDeviceInfo3); | |
354 expectDeviceRemoved(fakeDeviceInfo3.address, true); | |
355 | |
356 adapterClient.deviceAdded(fakeDeviceInfo3); | |
357 expectDeviceRemoved(fakeDeviceInfo3.address, false); | |
358 }); | |
359 }); | |
360 | |
361 // Run all registered tests. | |
362 mocha.run(); | |
363 }); | |
OLD | NEW |