Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: chrome/test/data/webui/bluetooth_internals_browsertest.js

Issue 2576603002: bluetooth: Add device details page with basic properties to internals page. (Closed)
Patch Set: Fix formatting, fix comments, fix test, change service/rssi display Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview Tests for chrome://bluetooth-internals 6 * @fileoverview Tests for chrome://bluetooth-internals
7 */ 7 */
8 8
9 /** @const {string} Path to source root. */ 9 /** @const {string} Path to source root. */
10 var ROOT_PATH = '../../../../'; 10 var ROOT_PATH = '../../../../';
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 // test to replace the real Mojo browser proxy with a fake one, before any 46 // test to replace the real Mojo browser proxy with a fake one, before any
47 // other code runs. 47 // other code runs.
48 window.setupFn = function() { 48 window.setupFn = function() {
49 return importModules([ 49 return importModules([
50 'content/public/renderer/frame_interfaces', 50 'content/public/renderer/frame_interfaces',
51 'device/bluetooth/public/interfaces/adapter.mojom', 51 'device/bluetooth/public/interfaces/adapter.mojom',
52 'device/bluetooth/public/interfaces/device.mojom', 52 'device/bluetooth/public/interfaces/device.mojom',
53 'mojo/public/js/bindings', 53 'mojo/public/js/bindings',
54 ]).then(function([frameInterfaces, adapter, device, bindings]) { 54 ]).then(function([frameInterfaces, adapter, device, bindings]) {
55 /** 55 /**
56 * A test adapter factory proxy for the chrome://bluetooth-internals 56 * A test adapter factory proxy for the chrome://bluetooth-internals
57 * page. 57 * page.
58 * 58 *
59 * @constructor 59 * @constructor
60 * @extends {TestBrowserProxyBase} 60 * @extends {TestBrowserProxyBase}
61 */ 61 */
62 var TestAdapterFactoryProxy = function() { 62 var TestAdapterFactoryProxy = function() {
63 settings.TestBrowserProxy.call(this, [ 63 settings.TestBrowserProxy.call(this, [
64 'getAdapter', 64 'getAdapter',
65 ]); 65 ]);
66 66
67 this.binding = new bindings.Binding(adapter.AdapterFactory, this); 67 this.binding = new bindings.Binding(adapter.AdapterFactory, this);
68 this.adapter = new TestAdapterProxy(); 68 this.adapter = new TestAdapterProxy();
69 this.adapterBinding_ = new bindings.Binding(adapter.Adapter, 69 this.adapterBinding_ = new bindings.Binding(adapter.Adapter,
70 this.adapter); 70 this.adapter);
71 }; 71 };
72 72
73 TestAdapterFactoryProxy.prototype = { 73 TestAdapterFactoryProxy.prototype = {
74 __proto__: settings.TestBrowserProxy.prototype, 74 __proto__: settings.TestBrowserProxy.prototype,
75 getAdapter: function() { 75 getAdapter: function() {
76 this.methodCalled('getAdapter'); 76 this.methodCalled('getAdapter');
77 77
78 // Create message pipe bound to TestAdapter. 78 // Create message pipe bound to TestAdapter.
79 return Promise.resolve({ 79 return Promise.resolve({
80 adapter: this.adapterBinding_.createInterfacePtrAndBind(), 80 adapter: this.adapterBinding_.createInterfacePtrAndBind(),
81 }); 81 });
82 } 82 }
83 }; 83 };
84 84
85 /** 85 /**
86 * A test adapter proxy for the chrome://bluetooth-internals page. 86 * A test adapter proxy for the chrome://bluetooth-internals page.
87 * 87 * @constructor
88 * @constructor 88 * @extends {TestBrowserProxyBase}
89 * @extends {TestBrowserProxyBase} 89 */
90 */
91 var TestAdapterProxy = function() { 90 var TestAdapterProxy = function() {
92 settings.TestBrowserProxy.call(this, [ 91 settings.TestBrowserProxy.call(this, [
93 'getInfo', 92 'getInfo',
94 'getDevices', 93 'getDevices',
95 'setClient', 94 'setClient',
96 ]); 95 ]);
97 96
97 this.deviceProxyMap = new Map();
98 this.adapterInfo_ = null; 98 this.adapterInfo_ = null;
99 this.devices_ = []; 99 this.devices_ = [];
100 this.connectResult_ = adapter.AdapterInfo.SUCCESS;
100 }; 101 };
101 102
102 TestAdapterProxy.prototype = { 103 TestAdapterProxy.prototype = {
103 __proto__: settings.TestBrowserProxy.prototype, 104 __proto__: settings.TestBrowserProxy.prototype,
104 105
106 connectToDevice: function(address) {
107 assert(this.deviceProxyMap.has(address), 'Device does not exist');
108
109 return Promise.resolve({
110 result: this.connectResult_,
111 device: this.deviceProxyMap.get(
112 address).binding.createInterfacePtrAndBind(),
113 });
114 },
115
105 getInfo: function() { 116 getInfo: function() {
106 this.methodCalled('getInfo'); 117 this.methodCalled('getInfo');
107 return Promise.resolve({info: this.adapterInfo_}); 118 return Promise.resolve({info: this.adapterInfo_});
108 }, 119 },
109 120
110 getDevices: function() { 121 getDevices: function() {
111 this.methodCalled('getDevices'); 122 this.methodCalled('getDevices');
112 return Promise.resolve({devices: this.devices_}); 123 return Promise.resolve({devices: this.devices_});
113 }, 124 },
114 125
115 setClient: function(client) { 126 setClient: function(client) {
116 this.methodCalled('setClient', client); 127 this.methodCalled('setClient', client);
117 }, 128 },
118 129
119 setTestAdapter: function(adapterInfo) { 130 setTestAdapter: function(adapterInfo) {
120 this.adapterInfo_ = adapterInfo; 131 this.adapterInfo_ = adapterInfo;
121 }, 132 },
122 133
134 setTestConnectResult: function(connectResult) {
135 this.connectResult_ = connectResult;
136 },
137
123 setTestDevices: function(devices) { 138 setTestDevices: function(devices) {
124 this.devices_ = devices; 139 this.devices_ = devices;
125 } 140 this.devices_.forEach(function(device) {
141 this.deviceProxyMap.set(
142 device.address, new TestDeviceProxy(device));
143 }, this);
144 },
126 }; 145 };
127 146
147 /**
148 * A test Device proxy for the chrome://bluetooth-internals
149 * page. Proxies are generated by a TestAdapterProxy which provides
150 * the DeviceInfo.
151 * @constructor
152 * @extends {TestBrowserProxyBase}
153 * @param {!device.DeviceInfo} info
154 */
155 var TestDeviceProxy = function(info) {
156 settings.TestBrowserProxy.call(this, [
157 'getInfo',
158 'getServices',
159 ]);
160
161 this.binding = new bindings.Binding(device.Device, this);
162 this.info_ = info;
163 this.services_ = [];
164 }
165
166 TestDeviceProxy.prototype = {
167 __proto__: settings.TestBrowserProxy.prototype,
168
169 disconnect: function() {
170 this.binding.close();
171 },
172
173 getInfo: function() {
174 this.methodCalled('getInfo');
175 return Promise.resolve({info: this.info_});
176 },
177
178 getServices: function() {
179 this.methodCalled('getServices');
180 return Promise.resolve({services: this.services_});
181 },
182
183 setTestServices: function(services) {
184 this.services_ = services;
185 },
186 }
187
128 frameInterfaces.addInterfaceOverrideForTesting( 188 frameInterfaces.addInterfaceOverrideForTesting(
129 adapter.AdapterFactory.name, function(handle) { 189 adapter.AdapterFactory.name, function(handle) {
130 this.adapterFactory = new TestAdapterFactoryProxy(); 190 this.adapterFactory = new TestAdapterFactoryProxy();
131 this.adapterFactory.binding.bind(handle); 191 this.adapterFactory.binding.bind(handle);
132 192
133 this.adapterFactory.adapter.setTestDevices([ 193 this.adapterFactory.adapter.setTestDevices([
134 this.fakeDeviceInfo1(), 194 this.fakeDeviceInfo1(),
135 this.fakeDeviceInfo2(), 195 this.fakeDeviceInfo2(),
136 ]); 196 ]);
137 this.adapterFactory.adapter.setTestAdapter( 197 this.adapterFactory.adapter.setTestAdapter(
138 this.fakeAdapterInfo()); 198 this.fakeAdapterInfo());
139 199
200 this.adapterFactory.adapter.deviceProxyMap.forEach(
201 function(deviceProxy) {
202 deviceProxy.setTestServices([
203 this.fakeServiceInfo1(),
204 this.fakeServiceInfo2(),
205 ])
206 }, this);
207
140 this.setupResolver.resolve(); 208 this.setupResolver.resolve();
141 }.bind(this)); 209 }.bind(this));
142 210
143 }.bind(this)); 211 }.bind(this));
144 }.bind(this); 212 }.bind(this);
145 }, 213 },
146 214
147 /** 215 /**
148 * Returns a copy of fake adapter info object. 216 * Returns a copy of fake adapter info object.
149 * @return {!Object} 217 * @return {!Object}
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 * rssi and services properties. 261 * rssi and services properties.
194 * @return {!Object} 262 * @return {!Object}
195 */ 263 */
196 fakeDeviceInfo3: function() { 264 fakeDeviceInfo3: function() {
197 return { 265 return {
198 address: "CC:CC:84:96:92:84", 266 address: "CC:CC:84:96:92:84",
199 name: "CCC", 267 name: "CCC",
200 name_for_display: "CCC", 268 name_for_display: "CCC",
201 }; 269 };
202 }, 270 },
271
272 /**
273 * Returns a copy of fake service info object (variant 1).
274 * @return {!Object}
275 */
276 fakeServiceInfo1: function() {
277 return {
278 uuid: '00002a05-0000-1000-8000-00805f9b34fb',
279 is_primary: true,
280 }
281 },
282
283 /**
284 * Returns a copy of fake service info object (variant 2).
285 * @return {!Object}
286 */
287 fakeServiceInfo2: function() {
288 return {
289 uuid: '0000180d-0000-1000-8000-00805f9b34fb',
290 is_primary: true,
291 }
292 },
203 }; 293 };
204 294
205 TEST_F('BluetoothInternalsTest', 'Startup_BluetoothInternals', function() { 295 TEST_F('BluetoothInternalsTest', 'Startup_BluetoothInternals', function() {
206 /** @const */ var PageManager = cr.ui.pageManager.PageManager; 296 /** @const */ var PageManager = cr.ui.pageManager.PageManager;
207 297
208 var adapterFactory = null; 298 var adapterFactory = null;
209 var adapterFieldSet = null; 299 var adapterFieldSet = null;
210 var deviceTable = null; 300 var deviceTable = null;
211 var sidebarNode = null; 301 var sidebarNode = null;
302 var pageNames = ['adapter', 'devices'];
212 303
213 var fakeAdapterInfo = this.fakeAdapterInfo; 304 var fakeAdapterInfo = this.fakeAdapterInfo;
214 var fakeDeviceInfo1 = this.fakeDeviceInfo1; 305 var fakeDeviceInfo1 = this.fakeDeviceInfo1;
215 var fakeDeviceInfo2 = this.fakeDeviceInfo2; 306 var fakeDeviceInfo2 = this.fakeDeviceInfo2;
216 var fakeDeviceInfo3 = this.fakeDeviceInfo3; 307 var fakeDeviceInfo3 = this.fakeDeviceInfo3;
308 var fakeServiceInfo1 = this.fakeServiceInfo1;
309 var fakeServiceInfo2 = this.fakeServiceInfo2;
217 310
218 // Before tests are run, make sure setup completes. 311 // Before tests are run, make sure setup completes.
219 var setupPromise = this.setupResolver.promise.then(function() { 312 var setupPromise = this.setupResolver.promise.then(function() {
220 adapterFactory = this.adapterFactory; 313 adapterFactory = this.adapterFactory;
221 }.bind(this)); 314 }.bind(this));
222 315
223 suite('BluetoothInternalsUITest', function() { 316 suite('BluetoothInternalsUITest', function() {
224 var EXPECTED_DEVICES = 2; 317 var EXPECTED_DEVICES = 2;
225 318
226 suiteSetup(function() { 319 suiteSetup(function() {
227 return setupPromise.then(function() { 320 return setupPromise.then(function() {
228 return Promise.all([ 321 return Promise.all([
229 adapterFactory.whenCalled('getAdapter'), 322 adapterFactory.whenCalled('getAdapter'),
230 adapterFactory.adapter.whenCalled('getInfo'), 323 adapterFactory.adapter.whenCalled('getInfo'),
231 adapterFactory.adapter.whenCalled('getDevices'), 324 adapterFactory.adapter.whenCalled('getDevices'),
232 adapterFactory.adapter.whenCalled('setClient'), 325 adapterFactory.adapter.whenCalled('setClient'),
233 ]); 326 ]);
234 }); 327 });
235 }); 328 });
236 329
237 setup(function() { 330 setup(function() {
238 adapterFieldSet = document.querySelector('#adapter fieldset'); 331 adapterFieldSet = document.querySelector('#adapter fieldset');
239 deviceTable = document.querySelector('#devices table'); 332 deviceTable = document.querySelector('#devices table');
240 sidebarNode = document.querySelector('#sidebar'); 333 sidebarNode = document.querySelector('#sidebar');
241 devices.splice(0, devices.length); 334 devices.splice(0, devices.length);
242 adapterBroker.adapterClient_.deviceAdded(fakeDeviceInfo1()); 335 adapterBroker.adapterClient_.deviceAdded(fakeDeviceInfo1());
243 adapterBroker.adapterClient_.deviceAdded(fakeDeviceInfo2()); 336 adapterBroker.adapterClient_.deviceAdded(fakeDeviceInfo2());
337
244 }); 338 });
245 339
246 teardown(function() { 340 teardown(function() {
247 adapterFactory.reset(); 341 adapterFactory.reset();
248 sidebarObj.close(); 342 sidebarObj.close();
249 snackbar.Snackbar.dismiss(true); 343 snackbar.Snackbar.dismiss(true);
344
345 adapterFactory.adapter.deviceProxyMap.forEach(function(deviceProxy) {
346 deviceProxy.reset();
347 });
348
250 PageManager.registeredPages['adapter'].setAdapterInfo(fakeAdapterInfo()); 349 PageManager.registeredPages['adapter'].setAdapterInfo(fakeAdapterInfo());
350
351 for (var pageName in PageManager.registeredPages) {
352 var page = PageManager.registeredPages[pageName];
353
354 if (pageNames.indexOf(pageName) < 0) {
355 page.pageDiv.parentNode.removeChild(page.pageDiv);
356 PageManager.unregister(page);
357 }
358 }
251 }); 359 });
252 360
253 /** 361 /**
254 * Updates device info and verifies the contents of the device table. 362 * Updates device info and verifies the contents of the device table.
255 * @param {!device_collection.DeviceInfo} deviceInfo 363 * @param {!device_collection.DeviceInfo} deviceInfo
256 */ 364 */
257 function changeDevice(deviceInfo) { 365 function changeDevice(deviceInfo) {
258 var deviceRow = deviceTable.querySelector('#' + escapeDeviceAddress( 366 var deviceRow = deviceTable.querySelector('#' + escapeDeviceAddress(
259 deviceInfo.address)); 367 deviceInfo.address));
260 var nameForDisplayColumn = deviceRow.children[0]; 368 var nameForDisplayColumn = deviceRow.children[0];
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 newDeviceInfo3.rssi = {value: -17}; 518 newDeviceInfo3.rssi = {value: -17};
411 adapterBroker.adapterClient_.deviceChanged(newDeviceInfo3); 519 adapterBroker.adapterClient_.deviceChanged(newDeviceInfo3);
412 expectEquals('-17', rssiColumn.textContent); 520 expectEquals('-17', rssiColumn.textContent);
413 }); 521 });
414 522
415 /* Sidebar Tests */ 523 /* Sidebar Tests */
416 test('Sidebar_Setup', function() { 524 test('Sidebar_Setup', function() {
417 var sidebarItems = Array.from( 525 var sidebarItems = Array.from(
418 sidebarNode.querySelectorAll('.sidebar-content li')); 526 sidebarNode.querySelectorAll('.sidebar-content li'));
419 527
420 ['adapter', 'devices'].forEach(function(pageName) { 528 pageNames.forEach(function(pageName) {
421 expectTrue(sidebarItems.some(function(item) { 529 expectTrue(sidebarItems.some(function(item) {
422 return item.dataset.pageName === pageName; 530 return item.dataset.pageName === pageName;
423 })); 531 }));
424 }); 532 });
425 }); 533 });
426 534
427 test('Sidebar_DefaultState', function() { 535 test('Sidebar_DefaultState', function() {
428 // Sidebar should be closed by default. 536 // Sidebar should be closed by default.
429 expectFalse(sidebarNode.classList.contains('open')); 537 expectFalse(sidebarNode.classList.contains('open'));
430 }); 538 });
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 checkAdapterFieldSet(adapterInfo); 701 checkAdapterFieldSet(adapterInfo);
594 adapterBroker.adapterClient_.presentChanged(adapterInfo.present); 702 adapterBroker.adapterClient_.presentChanged(adapterInfo.present);
595 checkAdapterFieldSet(adapterInfo); 703 checkAdapterFieldSet(adapterInfo);
596 704
597 adapterInfo.discovering = !adapterInfo.discovering; 705 adapterInfo.discovering = !adapterInfo.discovering;
598 adapterBroker.adapterClient_.discoveringChanged(adapterInfo.discovering); 706 adapterBroker.adapterClient_.discoveringChanged(adapterInfo.discovering);
599 checkAdapterFieldSet(adapterInfo); 707 checkAdapterFieldSet(adapterInfo);
600 adapterBroker.adapterClient_.discoveringChanged(adapterInfo.discovering); 708 adapterBroker.adapterClient_.discoveringChanged(adapterInfo.discovering);
601 checkAdapterFieldSet(adapterInfo); 709 checkAdapterFieldSet(adapterInfo);
602 }); 710 });
711
712 /** Device Details Page Tests */
713
714 /**
715 * Checks DeviceDetailsPage status fieldset.
716 * @param {!HTMLElement} detailsPage
717 * @param {!Object} deviceInfo
718 */
719 function checkDeviceDetailsFieldSet(detailsPage, deviceInfo) {
720 [
721 'name',
722 'address',
723 'is_gatt_connected',
724 'rssi.value',
725 'services.length',
726 ].forEach(function(propName){
727 var valueCell = detailsPage.querySelector(
728 'fieldset [data-field="' + propName + '"]');
729
730 var parts = propName.split('.');
731 var value = deviceInfo;
732
733 while (value != null && parts.length > 0) {
734 var part = parts.shift();
735 value = value[part];
736 }
737
738 if (propName == 'is_gatt_connected')
739 value = value ? 'Connected' : 'Not Connected';
740
741 if (typeof(value) === 'boolean') {
742 expectEquals(value, valueCell.classList.contains('checked'));
743 } else if (typeof(value) === 'string') {
744 expectEquals(value, valueCell.textContent);
745 } else {
746 assert('boolean or string type expected but got ' + typeof(value));
747 }
748 });
749 }
750
751 test('DeviceDetailsPage_NewDelete', function() {
752 var device = devices.item(0);
753
754 var deviceInspectLink = $(device.address).querySelector(
755 '[is="action-link"]');
756
757 var deviceDetailsPageId = 'devices/' + device.address.toLowerCase();
758
759 deviceInspectLink.click();
760 expectEquals("#" + deviceDetailsPageId, window.location.hash);
761
762 var detailsPage = $(deviceDetailsPageId);
763 assertTrue(!!detailsPage);
764
765 return adapterFactory.adapter.deviceProxyMap.get(
766 device.address).whenCalled('getServices').then(function() {
767 // At this point, the device details page should be fully loaded.
768 checkDeviceDetailsFieldSet(detailsPage, device);
769
770 detailsPage.querySelector('.forget').click();
771 expectEquals('#devices', window.location.hash);
772 detailsPage = $(deviceDetailsPageId);
773 expectFalse(!!detailsPage);
774 });
775 });
776
777 test('DeviceDetailsPage_NewDelete_FromDevicesPage', function() {
778 var device = devices.item(0);
779 var deviceDetailsPageId = 'devices/' + device.address.toLowerCase();
780
781 var deviceLinks = $(device.address).querySelectorAll(
782 '[is="action-link"]');
783
784 // First link is 'Inspect'.
785 deviceLinks[0].click();
786 expectEquals("#" + deviceDetailsPageId, window.location.hash);
787
788 var detailsPage = $(deviceDetailsPageId);
789 assertTrue(!!detailsPage);
790
791 return adapterFactory.adapter.deviceProxyMap.get(
792 device.address).whenCalled('getServices').then(function() {
793 checkDeviceDetailsFieldSet(detailsPage, device);
794
795 // Second link is 'Forget'.
796 deviceLinks[1].click();
797 expectEquals('#devices', window.location.hash);
798 detailsPage = $(deviceDetailsPageId);
799 expectFalse(!!detailsPage);
800 });
801 });
603 }); 802 });
604 803
605 // Run all registered tests. 804 // Run all registered tests.
606 mocha.run(); 805 mocha.run();
607 }); 806 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698