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

Side by Side Diff: chrome/test/data/webui/settings/search_engines_page_test.js

Issue 1666623006: MD Settings: Manage search engines 3/3, hooking up UI. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@manage_search_engines_handler
Patch Set: Remove console.log. Created 4 years, 10 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
(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.bind(this));
Dan Beam 2016/02/18 23:27:41 nit: wrapperMethods.forEach(this.resetResolver, th
dpapad 2016/02/18 23:45:47 Done.
39
40 /** @private {!SearchEnginesInfo} */
41 this.searchEnginesInfo_ = {};
Dan Beam 2016/02/18 23:27:41 i'd say this should be /** @private {?SearchEng
dpapad 2016/02/18 23:45:47 Done.
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_);
Dan Beam 2016/02/18 23:27:41 if you end up making this.searchEnginesInfo_ = nul
dpapad 2016/02/18 23:45:47 I went with the non-null approach.
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 * Asserts that the given paper-input element is empty.
173 * @param {string} inputId
174 */
175 var assertInputEmpty = function(inputId) {
176 var inputElement = dialog.$[inputId];
177 assertTrue(!!inputElement);
178 assertEquals(0, inputElement.value.length);
179 };
180
181 /**
182 * Asserts that the given paper-input element triggers validation when
183 * focused.
Dan Beam 2016/02/18 23:27:41 nit: update description now
dpapad 2016/02/18 23:45:47 Done.
184 * @param {string} inputId
185 * @return {!Promise} A promise firing when assertion has completed.
186 */
187 var focusAndValidate = function(inputId) {
188 browserProxy.resetResolver('validateSearchEngineInput');
189 MockInteractions.focus(dialog.$[inputId]);
190 return browserProxy.whenCalled('validateSearchEngineInput');
191 };
192
193 assertInputEmpty('searchEngine');
Dan Beam 2016/02/18 23:27:41 nit: assertEquals('', dialog.$.searchEngine.val
dpapad 2016/02/18 23:45:47 Done.
194 assertInputEmpty('keyword');
195 assertInputEmpty('queryUrl');
196 var actionButton = dialog.$.actionButton;
197 assertTrue(actionButton.disabled);
198
199 return focusAndValidate('searchEngine').then(function() {
200 return focusAndValidate('keyword');
201 }).then(function() {
202 return focusAndValidate('queryUrl');
203 }).then(function() {
204 // Manually set the text to a non-empty string for all fields.
205 dialog.$.searchEngine.value = 'foo';
206 dialog.$.keyword.value = 'bar';
207 dialog.$.queryUrl.value = 'baz';
208
209 // MockInteractions does not provide a way to trigger a 'change' event
210 // yet. Triggering the 'focus' event instead, to update the state of
211 // the action button.
212 return focusAndValidate('searchEngine');
213 }).then(function() {
214 // Assert that the action button has been enabled now that all input
215 // is valid and non-empty.
216 assertFalse(actionButton.disabled);
217 MockInteractions.tap(actionButton);
218 return browserProxy.whenCalled('searchEngineEditCompleted');
219 });
220 });
221
222 });
223 }
224
225 function registerEntryTests() {
226 suite('SearchEngineEntryTests', function() {
227 /** @type {?SettingsSearchEngineEntryElement} */
228 var entry = null;
229
230 var browserProxy = null;
231
232 setup(function() {
233 browserProxy = new TestSearchEnginesBrowserProxy();
234 settings.SearchEnginesBrowserProxyImpl.instance_ = browserProxy;
235 PolymerTest.clearBody();
236 entry = document.createElement('settings-search-engine-entry');
237 entry.set('engine', createSampleSearchEngine());
238 document.body.appendChild(entry);
239 });
240
241 teardown(function() { entry.remove(); });
242
243 test('RemoveSearchEngine', function() {
244 var deleteButton = entry.$.delete;
245 assertTrue(!!deleteButton);
246 MockInteractions.tap(deleteButton);
247 return browserProxy.whenCalled('removeSearchEngine').then(
248 function(modelIndex) {
249 assertEquals(entry.engine.modelIndex, modelIndex);
250 });
251 });
252
253 test('MakeDefault', function() {
254 var makeDefaultButton = entry.$.makeDefault;
255 assertTrue(!!makeDefaultButton);
256 MockInteractions.tap(makeDefaultButton);
257 return browserProxy.whenCalled('setDefaultSearchEngine').then(
258 function(modelIndex) {
259 assertEquals(entry.engine.modelIndex, modelIndex);
260 });
261 });
262
263 // Test that the "make default" and "remove" buttons are hidden for
264 // the default search engine.
265 test('DefaultSearchEngineHiddenButtons', function() {
266 assertFalse(entry.$.makeDefault.hidden);
267 assertFalse(entry.$.edit.hidden);
268 assertFalse(entry.$.delete.hidden);
269
270 // Mark the engine as the "default" one.
271 var engine = createSampleSearchEngine();
272 engine.default = true;
273 entry.set('engine', engine);
274 Polymer.dom.flush();
275
276 assertTrue(entry.$.makeDefault.hidden);
277 assertFalse(entry.$.edit.hidden);
278 assertTrue(entry.$.delete.hidden);
279 });
280
281 // Test that clicking the "edit" button brings up a dialog.
282 test('Edit', function() {
283 var engine = entry.engine;
284 var editButton = entry.$.edit;
285 assertTrue(!!editButton);
286 MockInteractions.tap(editButton);
287 return browserProxy.whenCalled('searchEngineEditStarted').then(
288 function(modelIndex) {
289 assertEquals(engine.modelIndex, modelIndex);
290 var dialog = entry.$$('settings-search-engine-dialog');
291 assertTrue(!!dialog);
292
293 // Check that the paper-input fields are pre-populated.
294 assertEquals(engine.displayName, dialog.$.searchEngine.value);
295 assertEquals(engine.keyword, dialog.$.keyword.value);
296 assertEquals(engine.url, dialog.$.queryUrl.value);
297
298 assertFalse(dialog.$.actionButton.disabled);
299 });
300 });
301 });
302 }
303
304 function registerPageTests() {
305 suite('SearchEnginePageTests', function() {
306 /** @type {?SettingsSearchEnginesPageElement} */
307 var page = null;
308
309 var browserProxy = null;
310
311 /** @type {!SearchEnginesInfo} */
312 var searchEnginesInfo = {
313 defaults: [createSampleSearchEngine()],
314 others: [],
315 extensions: [],
316 };
317
318 setup(function() {
319 browserProxy = new TestSearchEnginesBrowserProxy();
320 browserProxy.setSearchEnginesInfo(searchEnginesInfo);
321 settings.SearchEnginesBrowserProxyImpl.instance_ = browserProxy;
322 PolymerTest.clearBody();
323 page = document.createElement('settings-search-engines-page');
324 document.body.appendChild(page);
325 });
326
327 teardown(function() { page.remove(); });
328
329 // Tests that the page is querying and displaying search engine info on
330 // startup.
331 test('Initialization', function() {
332 return browserProxy.whenCalled('getSearchEnginesList').then(function() {
333 var searchEnginesLists = Polymer.dom(page.shadowRoot).
334 querySelectorAll('settings-search-engines-list');
335 assertEquals(2, searchEnginesLists.length);
336
337 Polymer.dom.flush();
338 var defaultsList = searchEnginesLists[0];
339 var defaultsEntries = Polymer.dom(defaultsList.shadowRoot).
340 querySelectorAll('settings-search-engine-entry');
341 assertEquals(
342 searchEnginesInfo.defaults.length, defaultsEntries.length);
343
344 var othersList = searchEnginesLists[1];
345 var othersEntries = Polymer.dom(othersList.shadowRoot).
346 querySelectorAll('settings-search-engine-entry');
347 assertEquals(
348 searchEnginesInfo.others.length, othersEntries.length);
349 });
350 });
351
352 // Tests that the add search engine dialog opens when the corresponding
353 // button is tapped.
354 test('AddSearchEngineDialog', function() {
355 assertFalse(!!page.$$('settings-search-engine-dialog'));
356 var addSearchEngineButton = page.$.addSearchEngine;
357 assertTrue(!!addSearchEngineButton);
358
359 MockInteractions.tap(addSearchEngineButton);
360 Polymer.dom.flush();
361 assertTrue(!!page.$$('settings-search-engine-dialog'));
362 });
363 });
364 }
365
366 return {
367 registerDialogTests: registerDialogTests,
368 registerEntryTests: registerEntryTests,
369 registerPageTests: registerPageTests,
370 };
371 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698