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

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

Issue 1447103002: MD Settings: FakeSettingsPrivate for tests (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: proto -> interface Created 5 years 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
« no previous file with comments | « chrome/test/data/webui/settings/prefs_test_cases.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** @fileoverview Suite of tests for settings-prefs. */ 5 /** @fileoverview Suite of tests for settings-prefs. */
6 cr.define('settings_prefs', function() { 6 cr.define('settings_prefs', function() {
7 /** 7 /**
8 * Creates a deep copy of the object. 8 * Creates a deep copy of the object.
9 * @param {!Object} obj 9 * @param {!Object} obj
10 * @return {!Object} 10 * @return {!Object}
11 */ 11 */
12 function deepCopy(obj) { 12 function deepCopy(obj) {
13 return JSON.parse(JSON.stringify(obj)); 13 return JSON.parse(JSON.stringify(obj));
14 } 14 }
15 15
16 /**
17 * Mock of chrome.settingsPrivate API.
18 * @constructor
19 * @extends {chrome.settingsPrivate}
20 */
21 function MockSettingsApi() {
22 this.prefs = {};
23
24 // Hack alert: bind this instance's onPrefsChanged members to this.
25 this.onPrefsChanged = {
26 addListener: this.onPrefsChanged.addListener.bind(this),
27 removeListener: this.onPrefsChanged.removeListener.bind(this),
28 };
29
30 for (var testCase of prefsTestCases)
31 this.addPref_(testCase.type, testCase.key, testCase.values[0]);
32 }
33
34 // Make the listener static because it refers to a singleton.
35 MockSettingsApi.listener_ = null;
36
37 MockSettingsApi.prototype = {
38 // chrome.settingsPrivate overrides.
39 onPrefsChanged: {
40 addListener: function(listener) {
41 MockSettingsApi.listener_ = listener;
42 },
43
44 removeListener: function(listener) {
45 MockSettingsApi.listener_ = null;
46 },
47 },
48
49 getAllPrefs: function(callback) {
50 // Send a copy of prefs to keep our internal state private.
51 var prefs = [];
52 for (var key in this.prefs)
53 prefs.push(deepCopy(this.prefs[key]));
54
55 // Run the callback asynchronously to test that the prefs aren't actually
56 // used before they become available.
57 setTimeout(callback.bind(null, prefs));
58 },
59
60 setPref: function(key, value, pageId, callback) {
61 var pref = this.prefs[key];
62 assertNotEquals(undefined, pref);
63 assertEquals(typeof value, typeof pref.value);
64 assertEquals(Array.isArray(value), Array.isArray(pref.value));
65
66 if (this.failNextSetPref_) {
67 callback(false);
68 this.failNextSetPref_ = false;
69 return;
70 }
71 assertNotEquals(true, this.disallowSetPref_);
72
73 var changed = JSON.stringify(pref.value) != JSON.stringify(value);
74 pref.value = deepCopy(value);
75 callback(true);
76
77 // Like chrome.settingsPrivate, send a notification when prefs change.
78 if (changed)
79 this.sendPrefChanges([{key: key, value: deepCopy(value)}]);
80 },
81
82 getPref: function(key, callback) {
83 var pref = this.prefs[key];
84 assertNotEquals(undefined, pref);
85 callback(deepCopy(pref));
86 },
87
88 // Functions used by tests.
89
90 /** Instructs the API to return a failure when setPref is next called. */
91 failNextSetPref: function() {
92 this.failNextSetPref_ = true;
93 },
94
95 /** Instructs the API to assert (fail the test) if setPref is called. */
96 disallowSetPref: function() {
97 this.disallowSetPref_ = true;
98 },
99
100 allowSetPref: function() {
101 this.disallowSetPref_ = false;
102 },
103
104 /**
105 * Notifies the listener of pref changes.
106 * @param {!Object<{key: string, value: *}>} changes
107 */
108 sendPrefChanges: function(changes) {
109 var prefs = [];
110 for (var change of changes) {
111 var pref = this.prefs[change.key];
112 assertNotEquals(undefined, pref);
113 pref.value = change.value;
114 prefs.push(deepCopy(pref));
115 }
116 MockSettingsApi.listener_(prefs);
117 },
118
119 // Private methods for use by the mock API.
120
121 /**
122 * @param {!chrome.settingsPrivate.PrefType} type
123 * @param {string} key
124 * @param {*} value
125 */
126 addPref_: function(type, key, value) {
127 this.prefs[key] = {
128 type: type,
129 key: key,
130 value: value,
131 };
132 },
133 };
134
135 function registerTests() { 16 function registerTests() {
136 suite('CrSettingsPrefs', function() { 17 suite('CrSettingsPrefs', function() {
137 /** 18 /**
138 * Prefs instance created before each test. 19 * Prefs instance created before each test.
139 * @type {CrSettingsPrefsElement|undefined} 20 * @type {CrSettingsPrefsElement|undefined}
140 */ 21 */
141 var prefs; 22 var prefs;
142 23
143 /** @type {MockSettingsApi} */ 24 /** @type {settings.FakeSettingsPrivate} */
144 var mockApi = null; 25 var fakeApi = null;
145 26
146 /** 27 /**
147 * @param {!Object} prefStore Pref store from <settings-prefs>. 28 * @param {!Object} prefStore Pref store from <settings-prefs>.
148 * @param {string} key Pref key of the pref to return. 29 * @param {string} key Pref key of the pref to return.
149 * @return {chrome.settingsPrivate.PrefObject|undefined} 30 * @return {chrome.settingsPrivate.PrefObject|undefined}
150 */ 31 */
151 function getPrefFromKey(prefStore, key) { 32 function getPrefFromKey(prefStore, key) {
152 var path = key.split('.'); 33 var path = key.split('.');
153 var pref = prefStore; 34 var pref = prefStore;
154 for (var part of path) { 35 for (var part of path) {
155 pref = pref[part]; 36 pref = pref[part];
156 if (!pref) 37 if (!pref)
157 return undefined; 38 return undefined;
158 } 39 }
159 return pref; 40 return pref;
160 } 41 }
161 42
162 /** 43 /**
163 * Checks that the mock API pref store contains the expected values. 44 * Checks that the fake API pref store contains the expected values.
164 * @param {number} testCaseValueIndex The index of possible values from 45 * @param {number} testCaseValueIndex The index of possible next values
165 * the test case to check. 46 * from the test case to check.
166 */ 47 */
167 function assertMockApiPrefsSet(testCaseValueIndex) { 48 function assertFakeApiPrefsSet(testCaseValueIndex) {
168 for (var testCase of prefsTestCases) { 49 for (var testCase of prefsTestCases) {
169 var expectedValue = JSON.stringify( 50 var expectedValue = JSON.stringify(
170 testCase.values[testCaseValueIndex]); 51 testCase.nextValues[testCaseValueIndex]);
171 var actualValue = JSON.stringify(mockApi.prefs[testCase.key].value); 52 var actualValue = JSON.stringify(
172 assertEquals(expectedValue, actualValue); 53 fakeApi.prefs[testCase.pref.key].value);
54 assertEquals(expectedValue, actualValue, testCase.pref.key);
173 } 55 }
174 } 56 }
175 57
176 /** 58 /**
177 * Checks that the <settings-prefs> contains the expected values. 59 * Checks that the <settings-prefs> contains the expected values.
178 * @param {number} testCaseValueIndex The index of possible values from 60 * @param {number} testCaseValueIndex The index of possible next values
179 * the test case to check. 61 * from the test case to check.
180 */ 62 */
181 function assertPrefsSet(testCaseValueIndex) { 63 function assertPrefsSet(testCaseValueIndex) {
182 for (var testCase of prefsTestCases) { 64 for (var testCase of prefsTestCases) {
183 var expectedValue = JSON.stringify( 65 var expectedValue = JSON.stringify(
184 testCase.values[testCaseValueIndex]); 66 testCase.nextValues[testCaseValueIndex]);
185 var actualValue = JSON.stringify( 67 var actualValue = JSON.stringify(
186 prefs.get('prefs.' + testCase.key + '.value')); 68 prefs.get('prefs.' + testCase.pref.key + '.value'));
187 assertEquals(expectedValue, actualValue); 69 assertEquals(expectedValue, actualValue);
188 } 70 }
189 } 71 }
190 72
191 /** 73 /**
192 * List of CrSettingsPref elements created for testing. 74 * List of CrSettingsPref elements created for testing.
193 * @type {!Array<!CrSettingsPrefs>} 75 * @type {!Array<!CrSettingsPrefs>}
194 */ 76 */
195 var createdElements = []; 77 var createdElements = [];
196 78
197 // Initialize <settings-prefs> elements before each test. 79 // Initialize <settings-prefs> elements before each test.
198 setup(function() { 80 setup(function() {
199 mockApi = new MockSettingsApi(); 81 // Override chrome.settingsPrivate with FakeSettingsPrivate.
200 // TODO(michaelpg): don't use global variables to inject the API. 82 fakeApi = new settings.FakeSettingsPrivate(
201 window.mockApi = mockApi; 83 prefsTestCases.map(function(testCase) {
84 return testCase.pref;
85 }));
86 CrSettingsPrefs.deferInitialization = true;
202 87
203 // Create and attach the <settings-prefs> elements. Make several of 88 // Create and attach the <settings-prefs> elements. Make several of
204 // them to test that the shared state model scales correctly. 89 // them to test that the shared state model scales correctly.
205 createdElements = []; 90 createdElements = [];
206 for (var i = 0; i < 100; i++) { 91 for (var i = 0; i < 100; i++) {
207 var prefsInstance = document.createElement('settings-prefs'); 92 var prefsInstance = document.createElement('settings-prefs');
208 document.body.appendChild(prefsInstance); 93 document.body.appendChild(prefsInstance);
209 createdElements.push(prefsInstance); 94 createdElements.push(prefsInstance);
95 prefsInstance.initializeForTesting(fakeApi);
210 } 96 }
211 // For simplicity, only use one prefs element in the tests. Use an 97 // For simplicity, only use one prefs element in the tests. Use an
212 // arbitrary index instead of the first or last element created. 98 // arbitrary index instead of the first or last element created.
213 prefs = createdElements[42]; 99 prefs = createdElements[42];
214 100
215 // getAllPrefs is asynchronous, so return the prefs promise. 101 // getAllPrefs is asynchronous, so return the prefs promise.
216 return CrSettingsPrefs.initialized; 102 return CrSettingsPrefs.initialized;
217 }); 103 });
218 104
219 teardown(function() { 105 teardown(function() {
220 CrSettingsPrefs.resetForTesting(); 106 CrSettingsPrefs.resetForTesting();
107 CrSettingsPrefs.deferInitialization = false;
221 108
222 // Reset each <settings-prefs>. 109 // Reset each <settings-prefs>. TODO(michaelpg): make settings-prefs
110 // less dependent on testing state so we don't have to do this.
223 for (var i = 0; i < createdElements.length; i++) 111 for (var i = 0; i < createdElements.length; i++)
224 createdElements[i].resetForTesting(); 112 createdElements[i].resetForTesting();
225 113
226 PolymerTest.clearBody(); 114 PolymerTest.clearBody();
227 window.mockApi = undefined;
228 }); 115 });
229 116
230 test('receives and caches prefs', function() { 117 test('receives and caches prefs', function testGetPrefs() {
231 // Test that each pref has been successfully copied to the Polymer 118 // Test that each pref has been successfully copied to the Polymer
232 // |prefs| property. 119 // |prefs| property.
233 for (var key in mockApi.prefs) { 120 for (var key in fakeApi.prefs) {
234 var expectedPref = mockApi.prefs[key]; 121 var expectedPref = fakeApi.prefs[key];
235 var actualPref = getPrefFromKey(prefs.prefs, key); 122 var actualPref = getPrefFromKey(prefs.prefs, key);
236 if (!expectNotEquals(undefined, actualPref)) { 123 if (!expectNotEquals(undefined, actualPref)) {
237 // We've already registered an error, so skip the pref. 124 // We've already registered an error, so skip the pref.
238 continue; 125 continue;
239 } 126 }
240 127
241 assertEquals(JSON.stringify(expectedPref), 128 assertEquals(JSON.stringify(expectedPref),
242 JSON.stringify(actualPref)); 129 JSON.stringify(actualPref));
243 } 130 }
244 }); 131 });
245 132
246 test('forwards pref changes to API', function() { 133 test('forwards pref changes to API', function testSetPrefs() {
247 // Test that settings-prefs uses the setPref API. 134 // Test that settings-prefs uses the setPref API.
248 for (var testCase of prefsTestCases) { 135 for (var testCase of prefsTestCases) {
249 prefs.set('prefs.' + testCase.key + '.value', 136 prefs.set('prefs.' + testCase.pref.key + '.value',
250 deepCopy(testCase.values[1])); 137 deepCopy(testCase.nextValues[0]));
251 } 138 }
252 // Check that setPref has been called for the right values. 139 // Check that setPref has been called for the right values.
253 assertMockApiPrefsSet(1); 140 assertFakeApiPrefsSet(0);
254 141
255 // Test that when setPref fails, the pref is reverted locally. 142 // Test that when setPref fails, the pref is reverted locally.
256 for (var testCase of prefsTestCases) { 143 for (var testCase of prefsTestCases) {
257 mockApi.failNextSetPref(); 144 fakeApi.failNextSetPref();
258 prefs.set('prefs.' + testCase.key + '.value', 145 prefs.set('prefs.' + testCase.pref.key + '.value',
259 deepCopy(testCase.values[2])); 146 deepCopy(testCase.nextValues[1]));
260 } 147 }
261 148
149 assertPrefsSet(0);
150
151 // Test that setPref is not called when the pref doesn't change.
152 fakeApi.disallowSetPref();
153 for (var testCase of prefsTestCases) {
154 prefs.set('prefs.' + testCase.pref.key + '.value',
155 deepCopy(testCase.nextValues[0]));
156 }
157 assertFakeApiPrefsSet(0);
158 fakeApi.allowSetPref();
159 });
160
161 test('responds to API changes', function testOnChange() {
162 // Changes from the API should not result in those changes being sent
163 // back to the API, as this could trigger a race condition.
164 fakeApi.disallowSetPref();
165 var prefChanges = [];
166 for (var testCase of prefsTestCases) {
167 prefChanges.push({key: testCase.pref.key,
168 value: testCase.nextValues[0]});
169 }
170
171 // Send a set of changes.
172 fakeApi.sendPrefChanges(prefChanges);
173 assertPrefsSet(0);
174
175 prefChanges = [];
176 for (var testCase of prefsTestCases) {
177 prefChanges.push({key: testCase.pref.key,
178 value: testCase.nextValues[1]});
179 }
180
181 // Send a second set of changes.
182 fakeApi.sendPrefChanges(prefChanges);
262 assertPrefsSet(1); 183 assertPrefsSet(1);
263 184
264 // Test that setPref is not called when the pref doesn't change. 185 // Send the same set of changes again -- nothing should happen.
265 mockApi.disallowSetPref(); 186 fakeApi.sendPrefChanges(prefChanges);
266 for (var testCase of prefsTestCases) {
267 prefs.set('prefs.' + testCase.key + '.value',
268 deepCopy(testCase.values[1]));
269 }
270 assertMockApiPrefsSet(1);
271 mockApi.allowSetPref();
272 });
273
274 test('responds to API changes', function() {
275 // Changes from the API should not result in those changes being sent
276 // back to the API, as this could trigger a race condition.
277 mockApi.disallowSetPref();
278 var prefChanges = [];
279 for (var testCase of prefsTestCases)
280 prefChanges.push({key: testCase.key, value: testCase.values[1]});
281
282 // Send a set of changes.
283 mockApi.sendPrefChanges(prefChanges);
284 assertPrefsSet(1); 187 assertPrefsSet(1);
285
286 prefChanges = [];
287 for (var testCase of prefsTestCases)
288 prefChanges.push({key: testCase.key, value: testCase.values[2]});
289
290 // Send a second set of changes.
291 mockApi.sendPrefChanges(prefChanges);
292 assertPrefsSet(2);
293
294 // Send the same set of changes again -- nothing should happen.
295 mockApi.sendPrefChanges(prefChanges);
296 assertPrefsSet(2);
297 }); 188 });
298 }); 189 });
299 } 190 }
300 191
301 return { 192 return {
302 registerTests: registerTests, 193 registerTests: registerTests,
303 }; 194 };
304 }); 195 });
OLDNEW
« no previous file with comments | « chrome/test/data/webui/settings/prefs_test_cases.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698