OLD | NEW |
---|---|
(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 for (var testCase of prefsTestCases) | |
23 this.addPref_(testCase.type, testCase.key, testCase.values[0]); | |
24 } | |
25 | |
26 MockSettingsApi.prototype = { | |
27 // chrome.settingsPrivate overrides. | |
28 onPrefsChanged: { | |
29 addListener: function(listener) { | |
30 this.listener_ = listener; | |
31 }, | |
32 | |
33 removeListener: function(listener) { | |
34 expectNotEquals(null, this.listener_); | |
35 this.listener_ = null; | |
36 }, | |
37 }, | |
38 | |
39 getAllPrefs: function(callback) { | |
40 // Send a copy of prefs to keep our internal state private. | |
41 var prefs = []; | |
42 for (var key in this.prefs) | |
43 prefs.push(Object.assign({}, this.prefs[key])) | |
44 | |
45 setTimeout(callback.bind(null, prefs)); | |
46 }, | |
47 | |
48 setPref: function(key, value, pageId, callback) { | |
49 var pref = this.prefs[key]; | |
50 assertNotEquals(undefined, pref); | |
51 assertEquals(typeof value, typeof pref.value); | |
52 assertEquals(Array.isArray(value), Array.isArray(pref.value)); | |
53 | |
54 if (this.failNextSetPref_) { | |
55 setTimeout(callback.bind(null, false)); | |
56 this.failNextSetPref_ = false; | |
57 return; | |
58 } | |
59 assertNotEquals(true, this.disallowSetPref_); | |
60 | |
61 var changed = JSON.stringify(pref.value) != JSON.stringify(value); | |
62 pref.value = JSON.parse(JSON.stringify(value)); | |
63 setTimeout(function() { | |
64 callback(true); | |
65 | |
66 // Like chrome.settingsPrivate, send a notification when prefs change. | |
67 if (changed) | |
68 this.sendPrefChangesAsync([{key: key, value: value}]); | |
69 }.bind(this)); | |
70 }, | |
71 | |
72 getPref: function(key, callback) { | |
73 var pref = this.prefs[key]; | |
74 assertNotEquals(undefined, pref); | |
75 | |
76 var prefCopy = Object.assign({}, pref); | |
77 setTimeout(callback.bind(null, prefCopy)); | |
78 }, | |
79 | |
80 // Functions used by tests. | |
81 | |
82 /** Instructs the API to return a failure when setPref is next called. */ | |
83 failNextSetPref: function() { | |
84 this.failNextSetPref_ = true; | |
85 }, | |
86 | |
87 /** Instructs the API to assert (fail the test) if setPref is called. */ | |
88 disallowSetPref: function() { | |
89 this.disallowSetPref_ = true; | |
90 }, | |
91 | |
92 allowSetPref: function() { | |
93 this.disallowSetPref_ = false; | |
94 }, | |
95 | |
96 /** | |
97 * Notifies the listener of pref changes. | |
98 * @param {!Object<{key: string, value: *}>} changes | |
99 */ | |
100 sendPrefChangesAsync: function(changes) { | |
101 var prefs = []; | |
102 for (var change of changes) { | |
103 var pref = this.prefs[change.key]; | |
104 assertNotEquals(undefined, pref); | |
105 pref.value = change.value; | |
106 prefs.push(Object.assign({}, pref)); | |
107 } | |
108 | |
109 setTimeout(this.listener_.bind(null, prefs)); | |
110 }, | |
111 | |
112 // Private methods for use by the mock API. | |
113 | |
114 /** | |
115 * @param {!chrome.settingsPrivate.PrefType} type | |
116 * @param {string} key | |
117 * @param {*} value | |
118 */ | |
119 addPref_: function(type, key, value) { | |
120 this.prefs[key] = { | |
121 type: type, | |
122 key: key, | |
123 value: value, | |
124 }; | |
125 }, | |
126 }; | |
127 | |
128 function registerTests() { | |
129 suite('CrSettingsPrefs', function() { | |
130 /** | |
131 * Prefs instance created before each test. | |
132 * @type {CrSettingsPrefs} | |
133 */ | |
134 var prefs; | |
135 | |
136 /** @type {MockSettingsApi} */ | |
137 var mockApi = null; | |
138 | |
139 /** | |
140 * @param {!Object} prefStore Pref store from <cr-settings-prefs>. | |
141 * @param {string} key Pref key of the pref to return. | |
142 * @return {(chrome.settingsPrivate.PrefObject|undefined)} | |
143 */ | |
144 function getPrefFromKey(prefStore, key) { | |
145 var path = key.split('.'); | |
146 var pref = prefStore; | |
147 for (var part of path) { | |
148 pref = pref[part]; | |
149 if (!pref) | |
150 return undefined; | |
151 } | |
152 return pref; | |
153 } | |
154 | |
155 /** | |
156 * Checks that the mock API pref store contains the expected values. | |
157 * @param {number} testCaseValueIndex The index of possible values from | |
158 * the test case to check. | |
159 */ | |
160 function expectMockApiPrefsSet(testCaseValueIndex) { | |
161 for (var testCase of prefsTestCases) { | |
162 var expectedValue = JSON.stringify( | |
163 testCase.values[testCaseValueIndex]); | |
164 var actualValue = JSON.stringify(mockApi.prefs[testCase.key].value); | |
165 expectEquals(expectedValue, actualValue); | |
166 } | |
167 } | |
168 | |
169 /** | |
170 * Checks that the <cr-settings-prefs> contains the expected values. | |
171 * @param {number} testCaseValueIndex The index of possible values from | |
172 * the test case to check. | |
173 */ | |
174 function expectPrefsSet(testCaseValueIndex) { | |
175 for (var testCase of prefsTestCases) { | |
176 var expectedValue = JSON.stringify( | |
177 testCase.values[testCaseValueIndex]); | |
178 var actualValue = JSON.stringify( | |
179 prefs.get('prefs.' + testCase.key + '.value')); | |
180 expectEquals(expectedValue, actualValue); | |
181 } | |
182 } | |
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); | |
194 | |
195 window.mockApi = undefined; | |
196 | |
197 // Wait for CrSettingsPrefs.INITIALIZED. | |
198 if (!CrSettingsPrefs.isInitialized) { | |
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 = getPrefFromKey(prefs.prefs, key); | |
216 if (!expectNotEquals(undefined, actualPref)) { | |
217 // We've already registered an error, so skip the pref. | |
218 continue; | |
219 } | |
220 | |
221 expectEquals(JSON.stringify(expectedPref), | |
222 JSON.stringify(actualPref)); | |
223 } | |
224 }); | |
225 | |
226 test('forwards pref changes to API', function(done) { | |
227 // Test that cr-settings-prefs uses the setPref API. | |
228 for (var testCase of prefsTestCases) | |
229 prefs.set('prefs.' + testCase.key + '.value', testCase.values[1]); | |
230 | |
231 // Check that setPref has been called for the right values. | |
232 expectMockApiPrefsSet(1); | |
233 | |
234 // Test that when setPref fails, the pref is reverted locally. | |
235 for (var testCase of prefsTestCases) { | |
236 mockApi.failNextSetPref(); | |
237 prefs.set('prefs.' + testCase.key + '.value', testCase.values[2]); | |
238 } | |
239 | |
240 // Queue two async tasks to delay checking the prefs until the | |
241 // asynchronous round-trip has completed. | |
242 PolymerTest.async(); | |
243 PolymerTest.async(function() { | |
Dan Beam
2015/09/15 01:37:18
can this be PolymerTest.async().then(...)?
michaelpg
2015/09/15 02:20:53
no:
* = prefs_tests.js
\> = prefs.js
depth = stac
Dan Beam
2015/09/16 00:54:19
this doesn't seem good
michaelpg
2015/09/16 01:14:09
it comes down to: do we want to
A) write a complex
Dan Beam
2015/09/16 01:37:00
you're really just testing a complex mock
| |
244 expectPrefsSet(1); | |
245 }); | |
246 | |
247 PolymerTest.async(function() { | |
248 // Test that setPref is not called when the pref doesn't change. | |
249 mockApi.disallowSetPref(); | |
250 for (var testCase of prefsTestCases) | |
251 prefs.set('prefs.' + testCase.key + '.value', testCase.values[1]); | |
252 | |
253 expectMockApiPrefsSet(1); | |
254 mockApi.allowSetPref(); | |
255 done(); | |
256 }); | |
257 }); | |
258 | |
259 test('responds to API changes', function(done) { | |
260 mockApi.disallowSetPref(); | |
261 var prefChanges = []; | |
262 for (var testCase of prefsTestCases) | |
263 prefChanges.push({key: testCase.key, value: testCase.values[1]}); | |
264 mockApi.sendPrefChangesAsync(prefChanges); | |
265 | |
266 PolymerTest.async(function() { | |
267 expectPrefsSet(1); | |
268 | |
269 prefChanges = []; | |
270 for (var testCase of prefsTestCases) | |
271 prefChanges.push({key: testCase.key, value: testCase.values[2]}); | |
272 mockApi.sendPrefChangesAsync(prefChanges); | |
273 }); | |
274 | |
275 PolymerTest.async(function() { | |
276 expectPrefsSet(2); | |
277 }); | |
278 | |
279 PolymerTest.async(function() { | |
280 // Shouldn't respond to non-changes. | |
Dan Beam
2015/09/15 01:37:18
nit: don't not remove double negatives?
michaelpg
2015/09/15 02:20:53
Not undone.
| |
281 mockApi.disallowSetPref(); | |
282 mockApi.sendPrefChangesAsync(prefChanges); | |
283 }); | |
284 | |
285 PolymerTest.async(done); | |
286 }); | |
287 }); | |
288 } | |
289 | |
290 return { | |
291 registerTests: registerTests, | |
292 }; | |
293 }); | |
OLD | NEW |