sync_internals_browsertest.js revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
1// Copyright 2013 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 * Test fixture for sync internals WebUI testing. 7 * @constructor 8 * @extends {testing.Test} 9 */ 10function SyncInternalsWebUITest() {} 11 12SyncInternalsWebUITest.prototype = { 13 __proto__: testing.Test.prototype, 14 15 /** 16 * Browse to the sync internals page. 17 * @override 18 */ 19 browsePreload: 'chrome://sync-internals', 20 21 /** 22 * Disable accessibility testing for this page. 23 * @override 24 */ 25 runAccessibilityChecks: false, 26 27 /** @override */ 28 preLoad: function() { 29 this.makeAndRegisterMockHandler([ 30 'getAllNodes', 31 ]); 32 }, 33 34 /** 35 * Checks aboutInfo's details section for the specified field. 36 * @param {boolean} isValid Whether the field is valid. 37 * @param {string} key The name of the key to search for in details. 38 * @param {string} value The expected value if |key| is found. 39 * @return {boolean} whether the field was found in the details. 40 * @protected 41 */ 42 hasInDetails: function(isValid, key, value) { 43 var details = chrome.sync.aboutInfo.details; 44 if (!details) 45 return false; 46 for (var i = 0; i < details.length; ++i) { 47 if (!details[i].data) 48 continue; 49 for (var j = 0; j < details[i].data.length; ++j) { 50 var obj = details[i].data[j]; 51 if (obj.stat_name == key) 52 return obj.is_valid == isValid && obj.stat_value == value; 53 } 54 } 55 return false; 56 } 57}; 58 59/** 60 * Constant hard-coded value to return from mock getAllNodes. 61 * @const 62 */ 63var HARD_CODED_ALL_NODES = [{ 64 "nodes": [{ 65 "ATTACHMENT_METADATA": "", 66 "BASE_SERVER_SPECIFICS": {}, 67 "BASE_VERSION": "1396470970810000", 68 "CTIME": "Wednesday, December 31, 1969 4:00:00 PM", 69 "ID": "sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf7yXJ1SkJwpp1YL" + 70 "6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==", 71 "IS_DEL": false, 72 "IS_DIR": true, 73 "IS_UNAPPLIED_UPDATE": false, 74 "IS_UNSYNCED": false, 75 "LOCAL_EXTERNAL_ID": "0", 76 "META_HANDLE": "387", 77 "MTIME": "Wednesday, December 31, 1969 4:00:00 PM", 78 "NON_UNIQUE_NAME": "Autofill", 79 "PARENT_ID": "r", 80 "SERVER_CTIME": "Wednesday, December 31, 1969 4:00:00 PM", 81 "SERVER_IS_DEL": false, 82 "SERVER_IS_DIR": true, 83 "SERVER_MTIME": "Wednesday, December 31, 1969 4:00:00 PM", 84 "SERVER_NON_UNIQUE_NAME": "Autofill", 85 "SERVER_PARENT_ID": "r", 86 "SERVER_SPECIFICS": { 87 "autofill": { 88 "usage_timestamp": [] 89 } 90 }, 91 "SERVER_UNIQUE_POSITION": "INVALID[]", 92 "SERVER_VERSION": "1396470970810000", 93 "SPECIFICS": { 94 "autofill": { 95 "usage_timestamp": [] 96 } 97 }, 98 "SYNCING": false, 99 "TRANSACTION_VERSION": "1", 100 "UNIQUE_BOOKMARK_TAG": "", 101 "UNIQUE_CLIENT_TAG": "", 102 "UNIQUE_POSITION": "INVALID[]", 103 "UNIQUE_SERVER_TAG": "google_chrome_autofill", 104 "isDirty": false, 105 "serverModelType": "Autofill" 106 }, { 107 "ATTACHMENT_METADATA": "", 108 "BASE_SERVER_SPECIFICS": {}, 109 "BASE_VERSION": "1394241139528639", 110 "CTIME": "Friday, March 7, 2014 5:12:19 PM", 111 "ID": "sZ:ADqtAZwzc/ol1iaz+yNLjjWak9PBE0o/hATzpqJsyq/HX2xzV2f88" + 112 "FaOrT7HDE4tyn7zx2LWgkAFvZfCA5mOy4p0XFgiY0L+mw==", 113 "IS_DEL": false, 114 "IS_DIR": false, 115 "IS_UNAPPLIED_UPDATE": false, 116 "IS_UNSYNCED": false, 117 "LOCAL_EXTERNAL_ID": "0", 118 "META_HANDLE": "2989", 119 "MTIME": "Friday, March 7, 2014 5:12:19 PM", 120 "NON_UNIQUE_NAME": "autofill_entry|Email|rlsynctet2", 121 "PARENT_ID": "sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf7yXJ1Sk" + 122 "Jwpp1YL6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==", 123 "SERVER_CTIME": "Friday, March 7, 2014 5:12:19 PM", 124 "SERVER_IS_DEL": false, 125 "SERVER_IS_DIR": false, 126 "SERVER_MTIME": "Friday, March 7, 2014 5:12:19 PM", 127 "SERVER_NON_UNIQUE_NAME": "autofill_entry|Email|rlsynctet2", 128 "SERVER_PARENT_ID": "sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf" + 129 "7yXJ1SkJwpp1YL6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==", 130 "SERVER_SPECIFICS": { 131 "autofill": { 132 "name": "Email", 133 "usage_timestamp": ["13038713887000000", "13038713890000000"], 134 "value": "rlsynctet2" 135 } 136 }, 137 "SERVER_UNIQUE_POSITION": "INVALID[]", 138 "SERVER_VERSION": "1394241139528639", 139 "SPECIFICS": { 140 "autofill": { 141 "name": "Email", 142 "usage_timestamp": ["13038713887000000", "13038713890000000"], 143 "value": "rlsynctet2" 144 } 145 }, 146 "SYNCING": false, 147 "TRANSACTION_VERSION": "1", 148 "UNIQUE_BOOKMARK_TAG": "", 149 "UNIQUE_CLIENT_TAG": "EvliorKUf1rLjT+BGkNZp586Tsk=", 150 "UNIQUE_POSITION": "INVALID[]", 151 "UNIQUE_SERVER_TAG": "", 152 "isDirty": false, 153 "serverModelType": "Autofill" 154 }], 155 "type": "Autofill" 156}]; 157 158/** 159 * A value to return in mock onReceivedUpdatedAboutInfo event. 160 * @const 161 */ 162HARD_CODED_ABOUT_INFO = { 163 "actionable_error": [ 164 { 165 "is_valid": false, 166 "stat_name": "Error Type", 167 "stat_value": "Uninitialized" 168 }, 169 { 170 "is_valid": false, 171 "stat_name": "Action", 172 "stat_value": "Uninitialized" 173 }, 174 { 175 "is_valid": false, 176 "stat_name": "URL", 177 "stat_value": "Uninitialized" 178 }, 179 { 180 "is_valid": false, 181 "stat_name": "Error Description", 182 "stat_value": "Uninitialized" 183 } 184 ], 185 "actionable_error_detected": false, 186 "details": [ 187 { 188 "data": [ 189 { 190 "is_valid": true, 191 "stat_name": "Summary", 192 "stat_value": "Sync service initialized" 193 } 194 ], 195 "is_sensitive": false, 196 "title": "Summary" 197 }, 198 ], 199 "type_status": [ 200 { 201 "name": "Model Type", 202 "num_entries": "Total Entries", 203 "num_live": "Live Entries", 204 "status": "header", 205 "value": "Group Type" 206 }, 207 { 208 "name": "Bookmarks", 209 "num_entries": 2793, 210 "num_live": 2793, 211 "status": "ok", 212 "value": "Active: GROUP_UI" 213 }, 214 ], 215 "unrecoverable_error_detected": false 216}; 217 218NETWORK_EVENT_DETAILS_1 = { 219 "details":"Notified types: Bookmarks, Autofill", 220 "proto":{}, 221 "time":1395874542192.407, 222 "type":"Normal GetUpdate request" 223}; 224 225NETWORK_EVENT_DETAILS_2 = { 226 "details":"Received error: SYNC_AUTH_ERROR", 227 "proto":{}, 228 "time":1395874542192.837, 229 "type":"GetUpdates Response" 230}; 231 232TEST_F('SyncInternalsWebUITest', 'Uninitialized', function() { 233 assertNotEquals(null, chrome.sync.aboutInfo); 234 expectTrue(this.hasInDetails(true, 'Username', '')); 235 expectTrue(this.hasInDetails(false, 'Summary', 'Uninitialized')); 236}); 237 238TEST_F('SyncInternalsWebUITest', 'LoadPastedAboutInfo', function() { 239 // Expose the text field. 240 $('import-status').click(); 241 242 // Fill it with fake data. 243 $('status-text').value = JSON.stringify(HARD_CODED_ABOUT_INFO); 244 245 // Trigger the import. 246 $('import-status').click(); 247 248 expectTrue(this.hasInDetails(true, 'Summary', 'Sync service initialized')); 249}); 250 251TEST_F('SyncInternalsWebUITest', 'NetworkEventsTest', function() { 252 networkEvent1 = new Event('onProtocolEvent'); 253 networkEvent1.details = NETWORK_EVENT_DETAILS_1; 254 networkEvent2 = new Event('onProtocolEvent'); 255 networkEvent2.details = NETWORK_EVENT_DETAILS_2; 256 257 chrome.sync.events.dispatchEvent(networkEvent1); 258 chrome.sync.events.dispatchEvent(networkEvent2); 259 260 expectEquals(2, $('traffic-event-container').children.length); 261 262 // Test that repeated events are not re-displayed. 263 chrome.sync.events.dispatchEvent(networkEvent1); 264 expectEquals(2, $('traffic-event-container').children.length); 265}); 266 267TEST_F('SyncInternalsWebUITest', 'SearchTabDoesntChangeOnItemSelect', 268 function() { 269 // Select the search tab. 270 $('sync-search-tab').selected = true; 271 expectTrue($('sync-search-tab').selected); 272 273 // Build the data model and attach to result list. 274 cr.ui.List.decorate($('sync-results-list')); 275 $('sync-results-list').dataModel = new cr.ui.ArrayDataModel([ 276 { 277 value: 'value 0', 278 toString: function() { return 'node 0'; }, 279 }, 280 { 281 value: 'value 1', 282 toString: function() { return 'node 1'; }, 283 } 284 ]); 285 286 // Select the first list item and verify the search tab remains selected. 287 $('sync-results-list').getListItemByIndex(0).selected = true; 288 expectTrue($('sync-search-tab').selected); 289}); 290 291TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() { 292 var getAllNodesSavedArgs = new SaveMockArguments(); 293 this.mockHandler.expects(once()). 294 getAllNodes(getAllNodesSavedArgs.match(ANYTHING)). 295 will(callFunctionWithSavedArgs(getAllNodesSavedArgs, 296 chrome.sync.getAllNodesCallback, 297 HARD_CODED_ALL_NODES)); 298 299 // Hit the refresh button. 300 $('node-browser-refresh-button').click(); 301 302 // Check that the refresh time was updated. 303 expectNotEquals($('node-browser-refresh-time').textContent, 'Never'); 304 305 // Verify some hard-coded assumptions. These depend on the vaue of the 306 // hard-coded nodes, specified elsewhere in this file. 307 308 // Start with the tree itself. 309 var tree = $('sync-node-tree'); 310 assertEquals(1, tree.items.length); 311 312 // Check the type root and expand it. 313 var typeRoot = tree.items[0]; 314 expectFalse(typeRoot.expanded); 315 typeRoot.expanded = true; 316 assertEquals(1, typeRoot.items.length); 317 318 // An actual sync node. The child of the type root. 319 var leaf = typeRoot.items[0]; 320 321 // Verify that selecting it affects the details view. 322 expectTrue($('node-details').hasAttribute('hidden')); 323 leaf.selected = true; 324 expectFalse($('node-details').hasAttribute('hidden')); 325}); 326 327TEST_F('SyncInternalsWebUITest', 'NodeBrowserRefreshOnTabSelect', function() { 328 var getAllNodesSavedArgs = new SaveMockArguments(); 329 this.mockHandler.expects(once()). 330 getAllNodes(getAllNodesSavedArgs.match(ANYTHING)). 331 will(callFunctionWithSavedArgs(getAllNodesSavedArgs, 332 chrome.sync.getAllNodesCallback, 333 HARD_CODED_ALL_NODES)); 334 335 // Should start with non-refreshed node browser. 336 expectEquals($('node-browser-refresh-time').textContent, 'Never'); 337 338 // Selecting the tab will refresh it. 339 $('sync-browser-tab').selected = true; 340 expectNotEquals($('node-browser-refresh-time').textContent, 'Never'); 341 342 // Re-selecting the tab shouldn't re-refresh. 343 $('node-browser-refresh-time').textContent = 'TestCanary'; 344 $('sync-browser-tab').selected = false; 345 $('sync-browser-tab').selected = true; 346 expectEquals($('node-browser-refresh-time').textContent, 'TestCanary'); 347}); 348 349// Tests that the events log page correctly receives and displays an event. 350TEST_F('SyncInternalsWebUITest', 'EventLogTest', function() { 351 // Dispatch an event. 352 var connectionEvent = new Event('onConnectionStatusChange'); 353 connectionEvent.details = {'status': 'CONNECTION_OK'}; 354 chrome.sync.events.dispatchEvent(connectionEvent); 355 356 // Verify that it is displayed in the events log. 357 var syncEventsTable = $('sync-events'); 358 var firstRow = syncEventsTable.children[0]; 359 360 // Makes some assumptions about column ordering. We'll need re-think this if 361 // it turns out to be a maintenance burden. 362 assertEquals(4, firstRow.children.length); 363 var submoduleName = firstRow.children[1].textContent; 364 var eventName = firstRow.children[2].textContent; 365 var detailsText = firstRow.children[3].textContent; 366 367 expectGE(submoduleName.indexOf('manager'), 0, 368 'submoduleName=' + submoduleName); 369 expectGE(eventName.indexOf('onConnectionStatusChange'), 0, 370 'eventName=' + eventName); 371 expectGE(detailsText.indexOf('CONNECTION_OK'), 0, 372 'detailsText=' + detailsText); 373}); 374 375TEST_F('SyncInternalsWebUITest', 'DumpSyncEventsToText', function() { 376 // Dispatch an event. 377 var connectionEvent = new Event('onConnectionStatusChange'); 378 connectionEvent.details = {'status': 'CONNECTION_OK'} 379 chrome.sync.events.dispatchEvent(connectionEvent); 380 381 // Click the dump-to-text button. 382 $('dump-to-text').click(); 383 384 // Verify our event is among the results. 385 var eventDumpText = $('data-dump').textContent; 386 387 expectGE(eventDumpText.indexOf('onConnectionStatusChange'), 0); 388 expectGE(eventDumpText.indexOf('CONNECTION_OK'), 0); 389}); 390