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

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

Issue 1310843010: Add Polymer tests for cr-settings-prefs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: preempt stevenjb comments :) Created 5 years, 3 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 2015 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 /** @fileoverview Suite of tests for cr-settings-prefs. */
6 cr.define('cr_settings_prefs', function() {
7 /**
8 * Mock of chrome.settingsPrivate API.
9 * @constructor
10 * @extends {chrome.settingsPrivate}
11 */
12 function MockSettingsApi() {
13 this.prefs = {};
14 this.listener_ = null;
15
16 // Hack alert: bind this instance's onPrefsChanged members to this.
17 this.onPrefsChanged = {
18 addListener: this.onPrefsChanged.addListener.bind(this),
19 removeListener: this.onPrefsChanged.removeListener.bind(this),
20 };
21
22 this.addBooleanPref_('top_level_pref', true);
23 this.addBooleanPref_('browser.enable_flash', false);
24 this.addBooleanPref_('browser.enable_html5', true);
25 this.addNumberPref_('device.overclock', .6);
26 this.addStringPref_('homepage', 'example.com');
27 }
28
29 MockSettingsApi.prototype = {
30 // chrome.settingsPrivate overrides.
31 onPrefsChanged: {
32 addListener: function(listener) {
33 this.listener_ = listener;
34 },
35
36 removeListener: function(listener) {
37 expectNotEquals(null, this.listener_);
Dan Beam 2015/09/11 21:49:13 ^ why?
michaelpg 2015/09/13 03:01:06 why not? I don't much care; nobody calls this any
38 this.listener_ = null;
39 },
40 },
41
42 getAllPrefs: function(callback) {
43 // Send a copy of prefs to keep our internal state private.
44 var prefs = [];
45 for (var key in this.prefs)
46 prefs.push(this.createCopy_(this.prefs[key]));
47
48 setTimeout(callback.bind(null, prefs));
49 },
50
51 setPref: function(key, value, pageId, callback) {
52 var pref = this.prefs[key];
53 assertNotEquals(undefined, pref);
54 assertEquals(typeof value, typeof pref.value);
55 assertEquals(Array.isArray(value), Array.isArray(pref.value));
56
57 if (this.failNextSetPref_) {
58 setTimeout(callback.bind(null, false));
59 this.failNextSetPref_ = false;
60 return;
61 }
62
63 // TODO(michaelpg): support list and dict prefs.
64 var changed = this.prefs[key].value != value;
65 this.prefs[key].value = value;
66 setTimeout(function() {
67 callback(true);
68 // Like chrome.settingsPrivate, send a notification when prefs change.
69 if (changed)
70 this.sendPrefChanges([key], [value]);
71 }.bind(this));
72 },
73
74 getPref: function(key, callback) {
75 var pref = this.prefs[key];
76 assertNotEquals(undefined, pref);
77
78 setTimeout(callback.bind(null, this.createCopy_(pref)));
79 },
80
81 // Functions used by tests.
82
83 /** Instructs the API to fail when setPref is next called. */
84 failNextSetPref: function() {
85 this.failNextSetPref_ = true;
86 },
87
88 /**
89 * Notifies the listener of pref changes.
90 * @param {!Array<string>} keys
91 * @param {!Array<*>} values
92 */
93 sendPrefChanges: function(keys, values) {
94 assertNotEquals(null, this.listener_);
Dan Beam 2015/09/11 21:49:12 assert(this.listener_); (or just remove this becau
michaelpg 2015/09/13 03:01:06 I can't figure out why, but assert doesn't play ni
95
96 var prefs = [];
97 for (var i = 0; i < keys.length; i++) {
98 var key = keys[i];
99 var pref = this.prefs[key];
100 pref.value = values[i];
101 prefs.push(this.createCopy_(pref));
102 }
103
104 setTimeout(this.listener_.bind(null, prefs));
105 },
106
107 // Private methods for use by the mock API.
108
109 /**
110 * @param {!chrome.settingsPrivate.PrefType} type
111 * @param {string} key
112 * @param {*} value
113 */
114 addPref_: function(type, key, value) {
115 this.prefs[key] = {
116 type: type,
117 key: key,
118 value: value,
119 };
120 },
121
122 /**
123 * @param {string} key
124 * @param {boolean} value
125 */
126 addBooleanPref_: function(key, value) {
127 this.addPref_('BOOLEAN', key, value);
stevenjb 2015/09/11 21:03:47 chrome.settingsPrivate.PrefType.BOOLEAN (throughou
Dan Beam 2015/09/11 21:49:12 are these values ('BOOLEAN', 'STRING', 'NUMBER') i
michaelpg 2015/09/13 03:01:06 Done.
michaelpg 2015/09/13 03:01:06 Done.
128 },
129
130 /**
131 * @param {string} key
132 * @param {number} value
133 */
134 addNumberPref_: function(key, value) {
135 this.addPref_('NUMBER', key, value);
136 },
137
138 /**
139 * @param {string} key
140 * @param {string} value
141 */
142 addStringPref_: function(key, value) {
143 this.addPref_('STRING', key, value);
144 },
145
146 /**
147 * Creates a deep copy of the preference.
148 * @param {chrome.settingsPrivate.PrefObject} pref
149 * @return {chrome.settingsPrivate.PrefObject}
150 */
151 createCopy_: function(pref) {
152 return JSON.parse(JSON.stringify(pref));
stevenjb 2015/09/11 21:03:47 Can we use Object.Assign here? https://developer.m
Dan Beam 2015/09/11 21:49:12 I guess using Object.create() here would be too mu
michaelpg 2015/09/13 03:01:06 Done.
michaelpg 2015/09/13 03:01:06 Used Object.assign instead.
153 },
154 };
155
156 /**
157 * Helper function to deal with asynchronicity by repeatedly queueing
158 * tasks to check if the callback returns true.
159 * @param {function(): boolean} callback
160 * @return {Promise}
161 */
162 function waitUntilTrue(callback) {
163 return new Promise(function(resolve, reject) {
164 var interval = setInterval(function() {
Dan Beam 2015/09/11 21:49:12 ew
michaelpg 2015/09/13 03:01:06 agreed. not sure how to solve this, though, withou
165 if (callback.call()) {
166 clearInterval(interval);
167 resolve();
168 }
169 });
Dan Beam 2015/09/11 21:49:12 wait, do this every 0ms?
michaelpg 2015/09/13 03:01:06 Yeah, it posts a task each time. If a function pos
170 });
171 }
172
173 function registerTests() {
174 suite('CrSettingsPrefs', function() {
175 /**
176 * Prefs instance created before each test.
177 * @type {CrSettingsPrefs}
178 */
179 var prefs;
180
181 /** @type {MockSettingsApi} */
182 var mockApi = null;
183
184 // Initialize a <cr-settings-prefs> element before each test.
185 setup(function(done) {
186 mockApi = new MockSettingsApi();
187 // TODO(michaelpg): don't use global variables to inject the API.
188 window.mockApi = mockApi;
189
190 // Create and attach the <cr-settings-prefs> element.
191 PolymerTest.clearBody();
192 prefs = document.createElement('cr-settings-prefs');
193 document.body.appendChild(prefs);
Dan Beam 2015/09/11 21:49:13 damn it http://jsfiddle.net/11hefdtv/
michaelpg 2015/09/13 03:01:06 Yyyyeeeppp. The browser creates and initializes ev
194
195 window.mockApi = undefined;
196
197 // Wait for CrSettingsPrefs.INITIALIZED.
198 if (!CrSettingsPrefs.isInitialized) {
Dan Beam 2015/09/11 21:49:12 can haz promise instead? CrSettingsPrefs.initiali
michaelpg 2015/09/13 03:01:06 Good idea, added the todo to prefs_types.js.
199 var listener = function() {
200 document.removeEventListener(CrSettingsPrefs.INITIALIZED, listener);
201 done();
202 };
203 document.addEventListener(CrSettingsPrefs.INITIALIZED, listener);
204 return;
205 }
206
207 done();
208 });
209
210 test('receives and caches prefs', function() {
211 // Test that each pref has been successfully copied to the Polymer
212 // |prefs| property.
213 for (var key in mockApi.prefs) {
214 var expectedPref = mockApi.prefs[key];
215 var actualPref = prefs.prefs;
216 // Find the preference.
217 var path = key.split('.');
218 var skipPref = false;
219 for (var part of path) {
220 actualPref = actualPref[part];
221 if (!expectNotEquals(undefined, actualPref)) {
222 // We've already registered an error, so skip the pref.
223 skipPref = true;
224 break;
225 }
226 }
stevenjb 2015/09/11 21:03:47 nit: Maybe wrap the above in a function to avoid t
michaelpg 2015/09/13 03:01:06 Done.
227 if (skipPref)
228 continue;
229
230 expectEquals(expectedPref.key, actualPref.key);
231 expectEquals(expectedPref.type, actualPref.type);
232 if (expectedPref.type != chrome.settingsPrivate.LIST) {
233 expectEquals(expectedPref.value, actualPref.value);
234 } else {
235 expectEquals(JSON.stringify(expectedPref.value),
236 JSON.stringify(actualPref.value));
Dan Beam 2015/09/11 21:49:12 just do this for numbers/integers as well?
michaelpg 2015/09/13 03:01:06 but but but... it's perf season!
237 }
238 }
239 });
240
241 test('forwards pref changes to API', function() {
242 // Test that cr-settings-prefs uses the setPref API.
243 prefs.set('prefs.browser.enable_flash.value', true);
244 expectTrue(mockApi.prefs['browser.enable_flash'].value);
Dan Beam 2015/09/11 21:49:13 \n
michaelpg 2015/09/13 03:01:06 Done.
245 prefs.set('prefs.device.overclock.value', 1.2);
246 expectEquals(1.2, mockApi.prefs['device.overclock'].value);
Dan Beam 2015/09/11 21:49:12 \n
michaelpg 2015/09/13 03:01:06 Done.
247 prefs.set('prefs.homepage.value', 'chromium.org');
248 expectEquals('chromium.org', mockApi.prefs['homepage'].value);
249
250 // Test that when setPref fails, the pref is reverted locally.
251 mockApi.failNextSetPref();
252 prefs.set('prefs.browser.enable_flash.value', false);
Dan Beam 2015/09/11 21:49:13 \n
michaelpg 2015/09/13 03:01:06 Done.
253 mockApi.failNextSetPref();
254 prefs.set('prefs.device.overclock.value', 2.0);
Dan Beam 2015/09/11 21:49:13 \n
michaelpg 2015/09/13 03:01:06 Done.
255 mockApi.failNextSetPref();
256 prefs.set('prefs.homepage.value', 'invalid-url');
257
258 // Multiple asynchronous round trips need to happen.
259 return Promise.all([
260 waitUntilTrue(function() {
261 return prefs.prefs.browser.enable_flash.value;
262 }),
263 waitUntilTrue(function() {
264 return prefs.prefs.device.overclock.value == 1.2;
265 }),
266 waitUntilTrue(function() {
267 return prefs.prefs.homepage.value == 'chromium.org';
268 }),
269 ]);
270 });
271
272 test('responds to API changes', function(done) {
273 mockApi.sendPrefChanges(['top_level_pref'], [false]);
274 PolymerTest.async(function() {
275 expectEquals(false, prefs.prefs.top_level_pref.value);
276
277 mockApi.sendPrefChanges(['top_level_pref'], [true]);
278 }).async(function() {
Dan Beam 2015/09/11 21:49:12 can't PolymerTest.async() just return a promise an
michaelpg 2015/09/13 03:01:06 no, we want to chain this logic more than once ("c
279 expectEquals(true, prefs.prefs.top_level_pref.value);
280 done();
281 });
282 });
283 });
284 }
285
286 return {
287 registerTests: registerTests,
288 };
289 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698