| 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 cr.define('settings_search_engines_page', function() { |
| 6 /** |
| 7 * TODO(dpapad): Similar class exists in webui_resource_async_browsertest.js. |
| 8 * Move somewhere else and re-use. |
| 9 * @constructor |
| 10 */ |
| 11 var PromiseResolver = function() { |
| 12 this.promise = new Promise(function(resolve, reject) { |
| 13 this.resolve = resolve; |
| 14 this.reject = reject; |
| 15 }.bind(this)); |
| 16 }; |
| 17 |
| 18 /** |
| 19 * A test version of SearchEnginesBrowserProxy. Provides helper methods |
| 20 * for allowing tests to know when a method was called, as well as |
| 21 * specifying mock responses. |
| 22 * |
| 23 * @constructor |
| 24 * @implements {settings.SearchEnginesBrowserProxy} |
| 25 */ |
| 26 var TestSearchEnginesBrowserProxy = function() { |
| 27 /** @private {!Map<string, !PromiseResolver>} */ |
| 28 this.resolverMap_ = new Map(); |
| 29 var wrapperMethods = [ |
| 30 'getSearchEnginesList', |
| 31 'removeSearchEngine', |
| 32 'searchEngineEditCancelled', |
| 33 'searchEngineEditCompleted', |
| 34 'searchEngineEditStarted', |
| 35 'setDefaultSearchEngine', |
| 36 'validateSearchEngineInput', |
| 37 ]; |
| 38 wrapperMethods.forEach(this.resetResolver, this); |
| 39 |
| 40 /** @private {!SearchEnginesInfo} */ |
| 41 this.searchEnginesInfo_ = {defaults: [], others: [], extensions: []}; |
| 42 }; |
| 43 |
| 44 TestSearchEnginesBrowserProxy.prototype = { |
| 45 /** |
| 46 * @param {string} methodName |
| 47 * @return {!Promise} A promise that is resolved when the given method |
| 48 * is called. |
| 49 */ |
| 50 whenCalled: function(methodName) { |
| 51 return this.resolverMap_.get(methodName).promise; |
| 52 }, |
| 53 |
| 54 /** |
| 55 * Resets the PromiseResolver associated with the given method. |
| 56 * @param {string} methodName |
| 57 */ |
| 58 resetResolver: function(methodName) { |
| 59 this.resolverMap_.set(methodName, new PromiseResolver()); |
| 60 }, |
| 61 |
| 62 /** @override */ |
| 63 setDefaultSearchEngine: function(modelIndex) { |
| 64 this.resolverMap_.get('setDefaultSearchEngine').resolve(modelIndex); |
| 65 }, |
| 66 |
| 67 /** @override */ |
| 68 removeSearchEngine: function(modelIndex) { |
| 69 this.resolverMap_.get('removeSearchEngine').resolve(modelIndex); |
| 70 }, |
| 71 |
| 72 /** @override */ |
| 73 searchEngineEditStarted: function(modelIndex) { |
| 74 this.resolverMap_.get('searchEngineEditStarted').resolve(modelIndex); |
| 75 }, |
| 76 |
| 77 /** @override */ |
| 78 searchEngineEditCancelled: function() { |
| 79 this.resolverMap_.get('searchEngineEditCancelled').resolve(); |
| 80 }, |
| 81 |
| 82 /** @override */ |
| 83 searchEngineEditCompleted: function(searchEngine, keyword, queryUrl) { |
| 84 this.resolverMap_.get('searchEngineEditCompleted').resolve(); |
| 85 }, |
| 86 |
| 87 /** |
| 88 * Sets the response to be returned by |getSearchEnginesList|. |
| 89 * @param {!SearchEnginesInfo} |
| 90 */ |
| 91 setSearchEnginesInfo: function(searchEnginesInfo) { |
| 92 this.searchEnginesInfo_ = searchEnginesInfo; |
| 93 }, |
| 94 |
| 95 /** @override */ |
| 96 getSearchEnginesList: function() { |
| 97 this.resolverMap_.get('getSearchEnginesList').resolve(); |
| 98 return Promise.resolve(this.searchEnginesInfo_); |
| 99 }, |
| 100 |
| 101 /** @override */ |
| 102 validateSearchEngineInput: function(fieldName, fieldValue) { |
| 103 this.resolverMap_.get('validateSearchEngineInput').resolve(); |
| 104 return Promise.resolve(true); |
| 105 }, |
| 106 }; |
| 107 |
| 108 /** @return {!SearchEngine} */ |
| 109 var createSampleSearchEngine = function() { |
| 110 return { |
| 111 canBeDefault: false, |
| 112 canBeEdited: true, |
| 113 canBeRemoved: false, |
| 114 default: false, |
| 115 displayName: "Google", |
| 116 iconURL: "http://www.google.com/favicon.ico", |
| 117 isOmniboxExtension: false, |
| 118 keyword: "google.com", |
| 119 modelIndex: 0, |
| 120 name: "Google", |
| 121 url: "https://search.foo.com/search?p=%s", |
| 122 urlLocked: false, |
| 123 }; |
| 124 }; |
| 125 |
| 126 function registerDialogTests() { |
| 127 suite('AddSearchEngineDialogTests', function() { |
| 128 /** @type {?SettingsAddSearchEngineDialog} */ |
| 129 var dialog = null; |
| 130 var browserProxy = null; |
| 131 |
| 132 setup(function() { |
| 133 browserProxy = new TestSearchEnginesBrowserProxy(); |
| 134 settings.SearchEnginesBrowserProxyImpl.instance_ = browserProxy; |
| 135 PolymerTest.clearBody(); |
| 136 dialog = document.createElement('settings-search-engine-dialog'); |
| 137 document.body.appendChild(dialog); |
| 138 }); |
| 139 |
| 140 teardown(function() { dialog.remove(); }); |
| 141 |
| 142 // Tests that the dialog calls 'searchEngineEditStarted' and |
| 143 // 'searchEngineEditCancelled' when closed from the 'x' button. |
| 144 test('DialogOpenAndClose', function() { |
| 145 return browserProxy.whenCalled('searchEngineEditStarted').then( |
| 146 function() { |
| 147 MockInteractions.tap(dialog.$.close); |
| 148 return browserProxy.whenCalled('searchEngineEditCancelled'); |
| 149 }); |
| 150 }); |
| 151 |
| 152 // Tests that the dialog calls 'searchEngineEditStarted' and |
| 153 // 'searchEngineEditCancelled' when closed from the 'cancel' button. |
| 154 test('DialogOpenAndCancel', function() { |
| 155 return browserProxy.whenCalled('searchEngineEditStarted').then( |
| 156 function() { |
| 157 MockInteractions.tap(dialog.$.cancel); |
| 158 return browserProxy.whenCalled('searchEngineEditCancelled'); |
| 159 }); |
| 160 }); |
| 161 |
| 162 // Tests the dialog to add a new search engine. Specifically |
| 163 // - paper-input elements are empty initially. |
| 164 // - action button initially disabled. |
| 165 // - validation is triggered on 'focus'. 'change' is not teted because |
| 166 // MockInteractions does not currently provide a way to trigger such |
| 167 // events. |
| 168 // - action button is enabled when all fields are valid. |
| 169 // - action button triggers appropriate browser signal when tapped. |
| 170 test('DialogAddSearchEngine', function() { |
| 171 /** |
| 172 * Focuses the given paper-input element and checks that validation is |
| 173 * triggered. |
| 174 * @param {string} inputId |
| 175 * @return {!Promise} |
| 176 */ |
| 177 var focusAndValidate = function(inputId) { |
| 178 browserProxy.resetResolver('validateSearchEngineInput'); |
| 179 MockInteractions.focus(dialog.$[inputId]); |
| 180 return browserProxy.whenCalled('validateSearchEngineInput'); |
| 181 }; |
| 182 |
| 183 assertEquals('', dialog.$.searchEngine.value); |
| 184 assertEquals('', dialog.$.keyword.value); |
| 185 assertEquals('', dialog.$.queryUrl.value); |
| 186 var actionButton = dialog.$.actionButton; |
| 187 assertTrue(actionButton.disabled); |
| 188 |
| 189 return focusAndValidate('searchEngine').then(function() { |
| 190 return focusAndValidate('keyword'); |
| 191 }).then(function() { |
| 192 return focusAndValidate('queryUrl'); |
| 193 }).then(function() { |
| 194 // Manually set the text to a non-empty string for all fields. |
| 195 dialog.$.searchEngine.value = 'foo'; |
| 196 dialog.$.keyword.value = 'bar'; |
| 197 dialog.$.queryUrl.value = 'baz'; |
| 198 |
| 199 // MockInteractions does not provide a way to trigger a 'change' event |
| 200 // yet. Triggering the 'focus' event instead, to update the state of |
| 201 // the action button. |
| 202 return focusAndValidate('searchEngine'); |
| 203 }).then(function() { |
| 204 // Assert that the action button has been enabled now that all input |
| 205 // is valid and non-empty. |
| 206 assertFalse(actionButton.disabled); |
| 207 MockInteractions.tap(actionButton); |
| 208 return browserProxy.whenCalled('searchEngineEditCompleted'); |
| 209 }); |
| 210 }); |
| 211 |
| 212 }); |
| 213 } |
| 214 |
| 215 function registerEntryTests() { |
| 216 suite('SearchEngineEntryTests', function() { |
| 217 /** @type {?SettingsSearchEngineEntryElement} */ |
| 218 var entry = null; |
| 219 |
| 220 var browserProxy = null; |
| 221 |
| 222 setup(function() { |
| 223 browserProxy = new TestSearchEnginesBrowserProxy(); |
| 224 settings.SearchEnginesBrowserProxyImpl.instance_ = browserProxy; |
| 225 PolymerTest.clearBody(); |
| 226 entry = document.createElement('settings-search-engine-entry'); |
| 227 entry.set('engine', createSampleSearchEngine()); |
| 228 document.body.appendChild(entry); |
| 229 }); |
| 230 |
| 231 teardown(function() { entry.remove(); }); |
| 232 |
| 233 test('RemoveSearchEngine', function() { |
| 234 var deleteButton = entry.$.delete; |
| 235 assertTrue(!!deleteButton); |
| 236 MockInteractions.tap(deleteButton); |
| 237 return browserProxy.whenCalled('removeSearchEngine').then( |
| 238 function(modelIndex) { |
| 239 assertEquals(entry.engine.modelIndex, modelIndex); |
| 240 }); |
| 241 }); |
| 242 |
| 243 test('MakeDefault', function() { |
| 244 var makeDefaultButton = entry.$.makeDefault; |
| 245 assertTrue(!!makeDefaultButton); |
| 246 MockInteractions.tap(makeDefaultButton); |
| 247 return browserProxy.whenCalled('setDefaultSearchEngine').then( |
| 248 function(modelIndex) { |
| 249 assertEquals(entry.engine.modelIndex, modelIndex); |
| 250 }); |
| 251 }); |
| 252 |
| 253 // Test that the "make default" and "remove" buttons are hidden for |
| 254 // the default search engine. |
| 255 test('DefaultSearchEngineHiddenButtons', function() { |
| 256 assertFalse(entry.$.makeDefault.hidden); |
| 257 assertFalse(entry.$.edit.hidden); |
| 258 assertFalse(entry.$.delete.hidden); |
| 259 |
| 260 // Mark the engine as the "default" one. |
| 261 var engine = createSampleSearchEngine(); |
| 262 engine.default = true; |
| 263 entry.set('engine', engine); |
| 264 Polymer.dom.flush(); |
| 265 |
| 266 assertTrue(entry.$.makeDefault.hidden); |
| 267 assertFalse(entry.$.edit.hidden); |
| 268 assertTrue(entry.$.delete.hidden); |
| 269 }); |
| 270 |
| 271 // Test that clicking the "edit" button brings up a dialog. |
| 272 test('Edit', function() { |
| 273 var engine = entry.engine; |
| 274 var editButton = entry.$.edit; |
| 275 assertTrue(!!editButton); |
| 276 MockInteractions.tap(editButton); |
| 277 return browserProxy.whenCalled('searchEngineEditStarted').then( |
| 278 function(modelIndex) { |
| 279 assertEquals(engine.modelIndex, modelIndex); |
| 280 var dialog = entry.$$('settings-search-engine-dialog'); |
| 281 assertTrue(!!dialog); |
| 282 |
| 283 // Check that the paper-input fields are pre-populated. |
| 284 assertEquals(engine.displayName, dialog.$.searchEngine.value); |
| 285 assertEquals(engine.keyword, dialog.$.keyword.value); |
| 286 assertEquals(engine.url, dialog.$.queryUrl.value); |
| 287 |
| 288 assertFalse(dialog.$.actionButton.disabled); |
| 289 }); |
| 290 }); |
| 291 }); |
| 292 } |
| 293 |
| 294 function registerPageTests() { |
| 295 suite('SearchEnginePageTests', function() { |
| 296 /** @type {?SettingsSearchEnginesPageElement} */ |
| 297 var page = null; |
| 298 |
| 299 var browserProxy = null; |
| 300 |
| 301 /** @type {!SearchEnginesInfo} */ |
| 302 var searchEnginesInfo = { |
| 303 defaults: [createSampleSearchEngine()], |
| 304 others: [], |
| 305 extensions: [], |
| 306 }; |
| 307 |
| 308 setup(function() { |
| 309 browserProxy = new TestSearchEnginesBrowserProxy(); |
| 310 browserProxy.setSearchEnginesInfo(searchEnginesInfo); |
| 311 settings.SearchEnginesBrowserProxyImpl.instance_ = browserProxy; |
| 312 PolymerTest.clearBody(); |
| 313 page = document.createElement('settings-search-engines-page'); |
| 314 document.body.appendChild(page); |
| 315 }); |
| 316 |
| 317 teardown(function() { page.remove(); }); |
| 318 |
| 319 // Tests that the page is querying and displaying search engine info on |
| 320 // startup. |
| 321 test('Initialization', function() { |
| 322 return browserProxy.whenCalled('getSearchEnginesList').then(function() { |
| 323 var searchEnginesLists = Polymer.dom(page.shadowRoot). |
| 324 querySelectorAll('settings-search-engines-list'); |
| 325 assertEquals(2, searchEnginesLists.length); |
| 326 |
| 327 Polymer.dom.flush(); |
| 328 var defaultsList = searchEnginesLists[0]; |
| 329 var defaultsEntries = Polymer.dom(defaultsList.shadowRoot). |
| 330 querySelectorAll('settings-search-engine-entry'); |
| 331 assertEquals( |
| 332 searchEnginesInfo.defaults.length, defaultsEntries.length); |
| 333 |
| 334 var othersList = searchEnginesLists[1]; |
| 335 var othersEntries = Polymer.dom(othersList.shadowRoot). |
| 336 querySelectorAll('settings-search-engine-entry'); |
| 337 assertEquals( |
| 338 searchEnginesInfo.others.length, othersEntries.length); |
| 339 }); |
| 340 }); |
| 341 |
| 342 // Tests that the add search engine dialog opens when the corresponding |
| 343 // button is tapped. |
| 344 test('AddSearchEngineDialog', function() { |
| 345 assertFalse(!!page.$$('settings-search-engine-dialog')); |
| 346 var addSearchEngineButton = page.$.addSearchEngine; |
| 347 assertTrue(!!addSearchEngineButton); |
| 348 |
| 349 MockInteractions.tap(addSearchEngineButton); |
| 350 Polymer.dom.flush(); |
| 351 assertTrue(!!page.$$('settings-search-engine-dialog')); |
| 352 }); |
| 353 }); |
| 354 } |
| 355 |
| 356 return { |
| 357 registerDialogTests: registerDialogTests, |
| 358 registerEntryTests: registerEntryTests, |
| 359 registerPageTests: registerPageTests, |
| 360 }; |
| 361 }); |
| OLD | NEW |