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.
5 /** @fileoverview Suite of tests for cr-settings-prefs. */
6 cr
.define('cr_settings_prefs', function() {
8 * Creates a deep copy of the object.
12 function deepCopy(obj
) {
13 return JSON
.parse(JSON
.stringify(obj
));
17 * Mock of chrome.settingsPrivate API.
19 * @extends {chrome.settingsPrivate}
21 function MockSettingsApi() {
23 this.listener_
= null;
25 // Hack alert: bind this instance's onPrefsChanged members to this.
26 this.onPrefsChanged
= {
27 addListener
: this.onPrefsChanged
.addListener
.bind(this),
28 removeListener
: this.onPrefsChanged
.removeListener
.bind(this),
31 for (var testCase
of prefsTestCases
)
32 this.addPref_(testCase
.type
, testCase
.key
, testCase
.values
[0]);
35 MockSettingsApi
.prototype = {
36 // chrome.settingsPrivate overrides.
38 addListener: function(listener
) {
39 this.listener_
= listener
;
42 removeListener: function(listener
) {
43 expectNotEquals(null, this.listener_
);
44 this.listener_
= null;
48 getAllPrefs: function(callback
) {
49 // Send a copy of prefs to keep our internal state private.
51 for (var key
in this.prefs
)
52 prefs
.push(deepCopy(this.prefs
[key
]));
57 setPref: function(key
, value
, pageId
, callback
) {
58 var pref
= this.prefs
[key
];
59 assertNotEquals(undefined, pref
);
60 assertEquals(typeof value
, typeof pref
.value
);
61 assertEquals(Array
.isArray(value
), Array
.isArray(pref
.value
));
63 if (this.failNextSetPref_
) {
65 this.failNextSetPref_
= false;
68 assertNotEquals(true, this.disallowSetPref_
);
70 var changed
= JSON
.stringify(pref
.value
) != JSON
.stringify(value
);
71 pref
.value
= deepCopy(value
);
74 // Like chrome.settingsPrivate, send a notification when prefs change.
76 this.sendPrefChanges([{key
: key
, value
: deepCopy(value
)}]);
79 getPref: function(key
, callback
) {
80 var pref
= this.prefs
[key
];
81 assertNotEquals(undefined, pref
);
82 callback(deepCopy(pref
));
85 // Functions used by tests.
87 /** Instructs the API to return a failure when setPref is next called. */
88 failNextSetPref: function() {
89 this.failNextSetPref_
= true;
92 /** Instructs the API to assert (fail the test) if setPref is called. */
93 disallowSetPref: function() {
94 this.disallowSetPref_
= true;
97 allowSetPref: function() {
98 this.disallowSetPref_
= false;
102 * Notifies the listener of pref changes.
103 * @param {!Object<{key: string, value: *}>} changes
105 sendPrefChanges: function(changes
) {
107 for (var change
of changes
) {
108 var pref
= this.prefs
[change
.key
];
109 assertNotEquals(undefined, pref
);
110 pref
.value
= change
.value
;
111 prefs
.push(deepCopy(pref
));
113 this.listener_(prefs
);
116 // Private methods for use by the mock API.
119 * @param {!chrome.settingsPrivate.PrefType} type
120 * @param {string} key
123 addPref_: function(type
, key
, value
) {
132 function registerTests() {
133 suite('CrSettingsPrefs', function() {
135 * Prefs instance created before each test.
136 * @type {CrSettingsPrefs}
140 /** @type {MockSettingsApi} */
144 * @param {!Object} prefStore Pref store from <cr-settings-prefs>.
145 * @param {string} key Pref key of the pref to return.
146 * @return {(chrome.settingsPrivate.PrefObject|undefined)}
148 function getPrefFromKey(prefStore
, key
) {
149 var path
= key
.split('.');
150 var pref
= prefStore
;
151 for (var part
of path
) {
160 * Checks that the mock API pref store contains the expected values.
161 * @param {number} testCaseValueIndex The index of possible values from
162 * the test case to check.
164 function expectMockApiPrefsSet(testCaseValueIndex
) {
165 for (var testCase
of prefsTestCases
) {
166 var expectedValue
= JSON
.stringify(
167 testCase
.values
[testCaseValueIndex
]);
168 var actualValue
= JSON
.stringify(mockApi
.prefs
[testCase
.key
].value
);
169 expectEquals(expectedValue
, actualValue
);
174 * Checks that the <cr-settings-prefs> contains the expected values.
175 * @param {number} testCaseValueIndex The index of possible values from
176 * the test case to check.
178 function expectPrefsSet(testCaseValueIndex
) {
179 for (var testCase
of prefsTestCases
) {
180 var expectedValue
= JSON
.stringify(
181 testCase
.values
[testCaseValueIndex
]);
182 var actualValue
= JSON
.stringify(
183 prefs
.get('prefs.' + testCase
.key
+ '.value'));
184 expectEquals(expectedValue
, actualValue
);
188 // Initialize a <cr-settings-prefs> element before each test.
189 setup(function(done
) {
190 mockApi
= new MockSettingsApi();
191 // TODO(michaelpg): don't use global variables to inject the API.
192 window
.mockApi
= mockApi
;
194 // Create and attach the <cr-settings-prefs> element.
195 PolymerTest
.clearBody();
196 prefs
= document
.createElement('cr-settings-prefs');
197 document
.body
.appendChild(prefs
);
199 window
.mockApi
= undefined;
201 // Wait for CrSettingsPrefs.INITIALIZED.
202 if (!CrSettingsPrefs
.isInitialized
) {
203 var listener = function() {
204 document
.removeEventListener(CrSettingsPrefs
.INITIALIZED
, listener
);
207 document
.addEventListener(CrSettingsPrefs
.INITIALIZED
, listener
);
214 test('receives and caches prefs', function() {
215 // Test that each pref has been successfully copied to the Polymer
217 for (var key
in mockApi
.prefs
) {
218 var expectedPref
= mockApi
.prefs
[key
];
219 var actualPref
= getPrefFromKey(prefs
.prefs
, key
);
220 if (!expectNotEquals(undefined, actualPref
)) {
221 // We've already registered an error, so skip the pref.
225 expectEquals(JSON
.stringify(expectedPref
),
226 JSON
.stringify(actualPref
));
230 test('forwards pref changes to API', function() {
231 // Test that cr-settings-prefs uses the setPref API.
232 for (var testCase
of prefsTestCases
) {
233 prefs
.set('prefs.' + testCase
.key
+ '.value',
234 deepCopy(testCase
.values
[1]));
236 // Check that setPref has been called for the right values.
237 expectMockApiPrefsSet(1);
239 // Test that when setPref fails, the pref is reverted locally.
240 for (var testCase
of prefsTestCases
) {
241 mockApi
.failNextSetPref();
242 prefs
.set('prefs.' + testCase
.key
+ '.value',
243 deepCopy(testCase
.values
[2]));
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',
252 deepCopy(testCase
.values
[1]));
254 expectMockApiPrefsSet(1);
255 mockApi
.allowSetPref();
258 test('responds to API changes', function() {
259 // Changes from the API should not result in those changes being sent
260 // back to the API, as this could trigger a race condition.
261 mockApi
.disallowSetPref();
262 var prefChanges
= [];
263 for (var testCase
of prefsTestCases
)
264 prefChanges
.push({key
: testCase
.key
, value
: testCase
.values
[1]});
266 // Send a set of changes.
267 mockApi
.sendPrefChanges(prefChanges
);
271 for (var testCase
of prefsTestCases
)
272 prefChanges
.push({key
: testCase
.key
, value
: testCase
.values
[2]});
274 // Send a second set of changes.
275 mockApi
.sendPrefChanges(prefChanges
);
278 // Send the same set of changes again -- nothing should happen.
279 mockApi
.sendPrefChanges(prefChanges
);
286 registerTests
: registerTests
,