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

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

Issue 2157673002: Browser tests for the quick_unlock settings pages. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@pin-unlock-quick-unlock-interface
Patch Set: Created 4 years, 5 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_people_page_quick_unlock', function() {
6 var element = null;
7 var quickUnlockPrivateApi = null;
8 var QuickUnlockMode = chrome.quickUnlockPrivate.QuickUnlockMode;
9
10 /**
11 * Verifies element is visible.
12 * @param {!Element} element
13 */
14 function assertVisible(element) {
tommycli 2016/07/18 20:47:24 I assume it's not practical to test the .hidden pr
jdufault 2016/07/19 00:11:08 Right, the hidden property might have been set in
15 assertTrue(element.offsetWidth > 0);
16 }
17
18 /**
19 * Verifies element is not visible.
20 * @param {!Element} element
21 */
22 function assertNotVisible(element) {
23 assertTrue(element.offsetWidth <= 0 && element.offsetHeight <= 0);
24 }
25
26 /**
27 * Returns true if the given |element| has class |className|.
28 * @param {!Element} element
29 * @param {string} className
30 */
31 function assertHasClass(element, className) {
32 assertTrue(element.classList.contains(className));
33 }
34
35 /**
36 * Returns the result of running |selector| on element.
37 * @param {string} selector
38 * @return {Element}
39 */
40 function getFromElement(selector) {
41 var childElement = element.$$(selector);
42 assertTrue(!!childElement);
43 return childElement;
44 }
45
46 /**
47 * Sets the active quick unlock modes and raises a mode change event.
48 * @param {!Array<chrome.quickUnlockPrivate.QuickUnlockMode>} modes
49 */
50 function setActiveModes(modes) {
51 quickUnlockPrivateApi.activeModes = modes;
52 quickUnlockPrivateApi.onActiveModesChanged.callListeners(modes);
53 }
54
55 function registerAuthenticateTests() {
56 suite('authenticate', function() {
57 var passwordElement = null;
58
59 setup(function() {
60 PolymerTest.clearBody();
61
62 quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
63
64 element = document.createElement('settings-quick-unlock-authenticate');
65 element.quickUnlockPrivate_ = quickUnlockPrivateApi;
66 document.body.appendChild(element);
67
68 passwordElement = getFromElement('#password-input');
69 });
70
71 // Checking the password does not change the active set of quick unlock
72 // modes.
tommycli 2016/07/18 20:47:24 I think the test name explains it well enough so t
jdufault 2016/07/19 00:11:08 Done.
73 test('PasswordCheckDoesNotChangeActiveMode', function() {
74 // No active modes.
75 quickUnlockPrivateApi.activeModes = [];
76 passwordElement.value = 'foo';
77 element.checkPasswordNow_();
78 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
79 assertDeepEquals([], quickUnlockPrivateApi.credentials);
80
81 // PIN is active.
82 quickUnlockPrivateApi.activeModes = [QuickUnlockMode.PIN];
83 passwordElement.value = 'foo';
84 element.checkPasswordNow_();
85 assertDeepEquals([QuickUnlockMode.PIN],
86 quickUnlockPrivateApi.activeModes);
87 assertDeepEquals([''], quickUnlockPrivateApi.credentials);
88 });
89
90 // A bad password does not provide an authenticated setModes object.
91 test('InvalidPasswordDoesNotProvideAuthentication', function() {
92 quickUnlockPrivateApi.accountPassword = 'bar';
93
94 passwordElement.value = 'foo';
95 element.checkPasswordNow_();
96
97 assertTrue(!element.setModes);
tommycli 2016/07/18 20:47:24 For symmetry with the below, can this be assertFal
jdufault 2016/07/19 00:11:08 Done.
98 });
99
100 // A valid password provides an authenticated setModes object.
101 test('ValidPasswordProvidesAuthentication', function() {
102 quickUnlockPrivateApi.accountPassword = 'foo';
103
104 passwordElement.value = 'foo';
105 element.checkPasswordNow_();
106
107 assertTrue(!!element.setModes);
108 });
109
110 // The password automatically submits after a delay.
111 test('PasswordAutoSubmitsAfterDelay', function(done) {
112 quickUnlockPrivateApi.accountPassword = 'foo';
113
114 element.autosubmitDelayMs_ = 0;
115 passwordElement.value = 'foo';
116 element.startDelayedPasswordCheck_();
117
118 setTimeout(function() {
119 assertFalse(!!element.password_);
120 assertTrue(!!element.setModes);
121 done();
122 }, 1050);
jdufault 2016/07/15 22:59:36 Change to 50
tommycli 2016/07/18 20:47:24 Hmm... I'm worried this test might be flaky... but
jdufault 2016/07/19 00:11:08 So long as the 50 is >= all of the other setTimeou
tommycli 2016/07/19 21:27:12 Can we make this not a numeric literal, but autosu
jdufault 2016/10/06 19:15:41 Done.
123 });
124
125 // The setModes objects times out after a delay.
126 test('AuthenticationTimesOut', function(done) {
127 quickUnlockPrivateApi.accountPassword = 'foo';
128
129 element.passwordActiveDurationMs_ = 0;
130 passwordElement.value = 'foo';
131 element.checkPasswordNow_();
132
133 assertFalse(!!element.password_);
134 assertTrue(!!element.setModes);
135
136 setTimeout(function() {
137 assertFalse(!!element.password_);
138 assertFalse(!!element.setModes);
139 done();
140 }, 50);
141 });
142 });
143 }
144
145 function registerChooseMethodTests() {
146 suite('choose-method', function() {
147 /** @const */ var ENABLE_LOCK_SCREEN_PREF = 'settings.enable_screen_lock';
148
149 var fakeSettings = null;
150 var passwordRadioButton = null;
151 var pinPasswordRadioButton = null;
152 var noneRadioButton = null;
153 var configureButton = null;
154
155 /**
156 * Asserts that only the given radio button is active and all of the
157 * others are inactive.
158 * @param {Element} radioButton
159 */
160 function assertRadioButtonActive(radioButton) {
161 function doAssert(element, name) {
162 if (radioButton == element)
163 assertTrue(element.active, 'Expected ' + name + ' to be active');
164 else
165 assertFalse(element.active, 'Expected ' + name + ' to be inactive');
166 }
167
168 doAssert(passwordRadioButton, 'passwordButton');
169 doAssert(pinPasswordRadioButton, 'pinPasswordButton');
170 doAssert(noneRadioButton, 'noneButton');
171 }
172
173 /**
174 * Returns the lock screen pref value.
175 * @return {boolean}
176 */
177 function getLockScreenPref() {
178 return element.getPref(ENABLE_LOCK_SCREEN_PREF).value;
179 }
180
181 /**
182 * Changes the lock screen pref value using the settings API; this is like
183 * the pref got changed from an unkown source such as another tab.
184 * @param {boolean} value
185 */
186 function setLockScreenPrefOnSettings(value) {
187 fakeSettings.setPref(ENABLE_LOCK_SCREEN_PREF, value, '', assertTrue);
188 }
189
190 setup(function(done) {
191 PolymerTest.clearBody();
192
193 CrSettingsPrefs.deferInitialization = true;
194
195 // Build pref fakes.
196 var fakePrefs = [{
197 key: ENABLE_LOCK_SCREEN_PREF,
198 type: chrome.settingsPrivate.PrefType.BOOLEAN,
199 value: true
200 }];
201 fakeSettings = new settings.FakeSettingsPrivate(fakePrefs);
202 setLockScreenPrefOnSettings(true);
203 var prefElement = document.createElement('settings-prefs');
204 prefElement.initializeForTesting(fakeSettings);
205 document.body.appendChild(prefElement);
206
207 // Wait for prefElement to finish initializing; it takes some time for
208 // the prefs element to get allocated.
209 prefElement.addEventListener('prefs-changed', function prefsReady() {
210 prefElement.removeEventListener('prefs-changed', prefsReady);
211
212 quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
213
214 // Create choose-method element.
215 element = document.createElement(
216 'settings-quick-unlock-choose-method');
217 element.settingsPrivate_ = fakeSettings;
218 element.quickUnlockPrivate_ = quickUnlockPrivateApi;
219 element.prefs = prefElement.prefs;
220 element.currentRoute = {
221 url: '/quickUnlock/chooseMethod',
222 page: 'basic',
223 section: 'people',
224 subpage: ['quick-unlock-choose-method'],
225 };
226 element.setModes =
227 quickUnlockPrivateApi.setModes.bind(quickUnlockPrivateApi, '');
228
229 // Previous test may have disabled the pref.
230 element.setPrefValue(ENABLE_LOCK_SCREEN_PREF, true);
231
232 document.body.appendChild(element);
233 Polymer.dom.flush();
234
235 passwordRadioButton =
236 getFromElement('paper-radio-button[name="password"]');
237 pinPasswordRadioButton =
238 getFromElement('paper-radio-button[name="pin+password"]');
239 noneRadioButton = getFromElement('paper-radio-button[name="none"]');
240 configureButton = getFromElement('paper-button');
241
242 // Give the element some time to initialize.
243 setTimeout(done);
tommycli 2016/07/18 20:47:24 This seems like it could be flaky. In other UI tes
jdufault 2016/07/19 00:11:08 Changed to async, I was having troubles getting We
tommycli 2016/07/19 21:27:12 See here: https://cs.chromium.org/chromium/src/chr
jdufault 2016/10/06 19:15:41 The element will now fire a 'ready' event when it
244 });
245 });
246
247 // Showing the choose method screen does not make any destructive pref or
248 // quickUnlockPrivate calls.
249 test('ShowingScreenDoesNotModifyPrefs', function() {
250 assertTrue(getLockScreenPref());
251 assertRadioButtonActive(passwordRadioButton);
252 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
253 });
254
255 // The various radio buttons update the pref and quick unlock state.
256 test('TappingButtonsChangesUnderlyingState', function() {
257 assertTrue(getLockScreenPref());
258 assertRadioButtonActive(passwordRadioButton);
259
260 function tapNone() {
261 MockInteractions.tap(noneRadioButton);
262 assertRadioButtonActive(noneRadioButton);
263 assertNotVisible(configureButton);
264 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
265 assertFalse(getLockScreenPref());
266 }
267
268 // Disable pref.
269 tapNone();
270
271 // Tap pin+password button, verify pref is enabled.
272 MockInteractions.tap(pinPasswordRadioButton);
273 assertRadioButtonActive(pinPasswordRadioButton);
274 assertVisible(configureButton);
275 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
276 assertTrue(getLockScreenPref());
277
278 // Enable quick unlock so that we verify tapping none disables it.
279 setActiveModes([QuickUnlockMode.PIN]);
280 tapNone();
281
282 // Tap password button, verify pref is enabled.
283 MockInteractions.tap(passwordRadioButton);
284 assertRadioButtonActive(passwordRadioButton);
285 assertNotVisible(configureButton);
286 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
287 assertTrue(getLockScreenPref());
288 });
289
290 // If quick unlock is changed by another settings page the radio button
291 // will update to show quick unlock is active.
292 test('EnablingQuickUnlockChangesButtonState', function() {
293 assertTrue(getLockScreenPref());
294 assertRadioButtonActive(passwordRadioButton);
295 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
296
297 setActiveModes([QuickUnlockMode.PIN]);
298 assertRadioButtonActive(pinPasswordRadioButton);
299 assertVisible(configureButton);
300 });
301
302 // If prefs are changed by another source the radio button will update.
303 test('PrefChangeUpdatesButtonState', function() {
304 assertTrue(getLockScreenPref());
305 assertRadioButtonActive(passwordRadioButton);
306
307 setLockScreenPrefOnSettings(false);
308 assertRadioButtonActive(noneRadioButton);
309
310 setLockScreenPrefOnSettings(true);
311 assertRadioButtonActive(passwordRadioButton);
312 }),
313
314 // Tapping the PIN configure button changes the route to the setup pin
315 // page.
316 test('TappingConfigureOpensSetupPin', function() {
317 assertTrue(getLockScreenPref());
318 assertRadioButtonActive(passwordRadioButton);
319
320 MockInteractions.tap(pinPasswordRadioButton);
321 assertVisible(configureButton);
322 assertRadioButtonActive(pinPasswordRadioButton)
323
324 MockInteractions.tap(configureButton);
325 assertDeepEquals('quick-unlock-setup-pin',
tommycli 2016/07/18 20:47:24 does assertEquals(settings.Route.QUICK_UNLOCK_SETU
jdufault 2016/07/19 00:11:08 settings.Route is undefined
tommycli 2016/07/19 21:27:12 Try importing /route.html in the quick_unlock_conf
326 element.currentRoute.subpage.slice(-1)[0]);
327 });
328 });
329 }
330
331 function registerSetupPinTests() {
332 suite('setup-pin', function() {
333 var titleDiv = null;
334 var problemDiv = null;
335 var pinKeyboard = null;
336 var backButton = null;
337 var continueButton = null;
338
339 setup(function() {
340 PolymerTest.clearBody();
341
342 quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
343
344 // Create choose-method element.
345 element = document.createElement('settings-quick-unlock-setup-pin');
346 element.quickUnlockPrivate_ = quickUnlockPrivateApi;
347 element.currentRoute = {
348 url: '/quickUnlock/setupPin',
349 page: 'basic',
350 section: 'people',
351 subpage: ['quick-unlock-choose-method', 'quick-unlock-setup-pin'],
352 };
353 element.setModes =
354 quickUnlockPrivateApi.setModes.bind(quickUnlockPrivateApi, '');
355
356 document.body.appendChild(element);
357 Polymer.dom.flush();
358
359 titleDiv = getFromElement('#title-div');
360 problemDiv = getFromElement('#problem-div');
361 pinKeyboard = getFromElement('pin-keyboard');
362 backButton = getFromElement('paper-button[class="cancel-button"]');
363 continueButton = getFromElement('paper-button[class="action-button"]');
364 });
365
366 // The back button is only displayed during the confirm PIN step.
367 test('BackOnlyShownWhenConfirmingPin', function() {
368 assertNotVisible(backButton);
369 assertVisible(continueButton);
370
371 pinKeyboard.value = '1111';
372 MockInteractions.tap(continueButton);
373
374 assertVisible(backButton);
375 });
376
377 // The continue button is disabled unless the user has entered a >= 4
378 // digit PIN.
379 test('CanOnlyContinueAfterEnteringAtLeastFourDigitPin', function() {
380 pinKeyboard.value = '111';
381 assertTrue(continueButton.disabled);
382
383 pinKeyboard.value = '1111';
384 assertFalse(continueButton.disabled);
385
386 pinKeyboard.value = '111';
387 assertTrue(continueButton.disabled);
388
389 pinKeyboard.value = '';
390 assertTrue(continueButton.disabled);
391
392 pinKeyboard.value = '1111111';
393 assertFalse(continueButton.disabled);
394 });
395
396 // Problem messages are hidden if the PIN is cleared.
397 test('NoProblemShownWithEmptyPin', function() {
398 pinKeyboard.value = '11';
399 assertVisible(problemDiv);
400
401 pinKeyboard.value = '';
402 assertNotVisible(problemDiv);
403 });
404
405 // If the PIN is too short an error problem is shown.
406 test('ErrorShownForShortPins', function() {
407 assertVisible(titleDiv);
408 assertNotVisible(problemDiv);
409
410 pinKeyboard.value = '11';
411
412 assertNotVisible(titleDiv);
413 assertVisible(problemDiv);
414 assertHasClass(problemDiv, 'error');
415 assertTrue(continueButton.disabled);
416 });
417
418 // If the PIN is weak a warning problem is shown.
419 test('WarningShownForWeakPins', function() {
420 assertVisible(titleDiv);
421 assertNotVisible(problemDiv);
422
423 pinKeyboard.value = '1111';
424
425 assertNotVisible(titleDiv);
426 assertVisible(problemDiv);
427 assertHasClass(problemDiv, 'warning');
428 });
429
430 // If the confirm PIN does not match the initial PIN an error is shown and
431 // the submit button is disabled.
432 test('ErrorShownForMismatchedPins', function() {
433 pinKeyboard.value = '1118';
434 MockInteractions.tap(continueButton);
435 pinKeyboard.value = '1119';
436
437 assertVisible(problemDiv);
438 assertHasClass(problemDiv, 'error');
439 assertTrue(continueButton.disabled);
440 });
441
442 // Hitting back on the confirm PIN step properly resets the flow.
443 test('HittingBackButtonResetsState', function() {
444 // Submit initial PIN.
445 pinKeyboard.value = '1111';
446 MockInteractions.tap(continueButton);
447 assertVisible(backButton);
448 assertEquals('', pinKeyboard.value);
449
450 // Prepare confirm pin but go back instead.
451 pinKeyboard.value = '1111';
452 MockInteractions.tap(backButton);
453 assertNotVisible(backButton);
454 assertEquals('', pinKeyboard.value);
455
456 // Submit initial PIN; verify we did not call quick unlock private API.
457 pinKeyboard.value = '1111';
458 MockInteractions.tap(continueButton);
459 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
460 });
461
462 // Completing the flow results in a call to the quick unlock private API.
463 test('SubmittingPinCallsQuickUnlockApi', function() {
464 // Entering the same (even weak) pin twice calls the quick unlock API
465 // and sets up a PIN.
466 pinKeyboard.value = '1111';
467 MockInteractions.tap(continueButton);
468 pinKeyboard.value = '1111';
469 MockInteractions.tap(continueButton);
470
471 assertDeepEquals(['PIN'], quickUnlockPrivateApi.activeModes);
472 assertDeepEquals(['1111'], quickUnlockPrivateApi.credentials);
473 });
474 });
475 }
476
477 return {
478 registerAuthenticateTests: registerAuthenticateTests,
479 registerChooseMethodTests: registerChooseMethodTests,
480 registerSetupPinTests: registerSetupPinTests
481 };
482 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698