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

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: Address comments Created 4 years, 2 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
« no previous file with comments | « chrome/test/data/webui/settings/fake_quick_unlock_private.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
(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 * Returns if the element is visible.
12 * @param {!Element} element
13 */
14 function isVisible(element) {
15 while (element) {
16 if (element.offsetWidth <= 0 || element.offsetHeight <= 0 ||
17 element.hidden) {
18 return false;
19 }
20
21 element = element.parentElement;
22 }
23
24 return true;
25 }
26
27 /**
28 * Returns true if the given |element| has class |className|.
29 * @param {!Element} element
30 * @param {string} className
31 */
32 function assertHasClass(element, className) {
33 assertTrue(element.classList.contains(className));
34 }
35
36 /**
37 * Returns the result of running |selector| on element.
38 * @param {string} selector
39 * @return {Element}
40 */
41 function getFromElement(selector) {
42 var childElement = element.$$(selector);
43 assertTrue(!!childElement);
44 return childElement;
45 }
46
47 /**
48 * Sets the active quick unlock modes and raises a mode change event.
49 * @param {!Array<chrome.quickUnlockPrivate.QuickUnlockMode>} modes
50 */
51 function setActiveModes(modes) {
52 quickUnlockPrivateApi.activeModes = modes;
53 quickUnlockPrivateApi.onActiveModesChanged.callListeners(modes);
54 }
55
56 function registerAuthenticateTests() {
57 suite('authenticate', function() {
58 var passwordElement = null;
59
60 setup(function() {
61 PolymerTest.clearBody();
62
63 quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
64
65 element = document.createElement('settings-password-prompt-dialog');
66 element.quickUnlockPrivate_ = quickUnlockPrivateApi;
67 document.body.appendChild(element);
68
69 passwordElement = getFromElement('#passwordInput');
70 });
71
72 test('PasswordCheckDoesNotChangeActiveMode', function() {
73 // No active modes.
74 quickUnlockPrivateApi.activeModes = [];
75 passwordElement.value = 'foo';
76 element.submitPassword_();
77 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
78 assertDeepEquals([], quickUnlockPrivateApi.credentials);
79
80 // PIN is active.
81 quickUnlockPrivateApi.activeModes = [QuickUnlockMode.PIN];
82 passwordElement.value = 'foo';
83 element.submitPassword_();
84 assertDeepEquals([QuickUnlockMode.PIN],
85 quickUnlockPrivateApi.activeModes);
86 assertDeepEquals([''], quickUnlockPrivateApi.credentials);
87 });
88
89 // A bad password does not provide an authenticated setModes object.
90 test('InvalidPasswordDoesNotProvideAuthentication', function() {
91 quickUnlockPrivateApi.accountPassword = 'bar';
92
93 passwordElement.value = 'foo';
94 element.submitPassword_();
95
96 assertFalse(!!element.setModes);
97 });
98
99 // A valid password provides an authenticated setModes object.
100 test('ValidPasswordProvidesAuthentication', function() {
101 quickUnlockPrivateApi.accountPassword = 'foo';
102
103 passwordElement.value = 'foo';
104 element.submitPassword_();
105
106 assertTrue(!!element.setModes);
107 });
108
109 // The setModes objects times out after a delay.
110 test('AuthenticationTimesOut', function(done) {
111 quickUnlockPrivateApi.accountPassword = 'foo';
112
113 element.passwordActiveDurationMs_ = 0;
114 passwordElement.value = 'foo';
115 element.submitPassword_();
116
117 assertFalse(!!element.password_);
118 assertTrue(!!element.setModes);
119
120 // Two setTimeout calls with the same delay are guaranteed to execute in
121 // the same order that they were submitted in, so using
122 // element.autosubmitDelayMs_ is safe.
123 setTimeout(function() {
124 assertFalse(!!element.password_);
125 assertFalse(!!element.setModes);
126 done();
127 }, element.passwordActiveDurationMs_);
128 });
129 });
130 }
131
132 function registerLockScreenTests() {
133 suite('lock-screen', function() {
134 /** @const */ var ENABLE_LOCK_SCREEN_PREF = 'settings.enable_screen_lock';
135
136 var fakeSettings = null;
137 var passwordRadioButton = null;
138 var pinPasswordRadioButton = null;
139 var noneRadioButton = null;
140 var configureButton = null;
141
142 /**
143 * Asserts that only the given radio button is active and all of the
144 * others are inactive.
145 * @param {Element} radioButton
146 */
147 function assertRadioButtonActive(radioButton) {
148 function doAssert(element, name) {
149 if (radioButton == element)
150 assertTrue(element.active, 'Expected ' + name + ' to be active');
151 else
152 assertFalse(element.active, 'Expected ' + name + ' to be inactive');
153 }
154
155 doAssert(passwordRadioButton, 'passwordButton');
156 doAssert(pinPasswordRadioButton, 'pinPasswordButton');
157 }
158
159 /**
160 * Returns the lock screen pref value.
161 * @return {boolean}
162 */
163 function getLockScreenPref() {
164 var result;
165 fakeSettings.getPref(ENABLE_LOCK_SCREEN_PREF, function(value) {
166 result = value;
167 });
168 assertNotEquals(undefined, result);
169 return result.value;
170 }
171
172 /**
173 * Changes the lock screen pref value using the settings API; this is like
174 * the pref got changed from an unkown source such as another tab.
175 * @param {boolean} value
176 */
177 function setLockScreenPref(value) {
178 fakeSettings.setPref(ENABLE_LOCK_SCREEN_PREF, value, '', assertTrue);
179 }
180
181 suiteSetup(function() {
182 var urls = [
183 'chrome://md-settings/i18n_setup.html',
184 'chrome://md-settings/prefs/prefs.html',
185 ];
186 return Promise.all(urls.map(PolymerTest.importHtml));
187 });
188
189 setup(function(done) {
190 PolymerTest.clearBody();
191
192 CrSettingsPrefs.deferInitialization = true;
193
194 // Build pref fakes.
195 var fakePrefs = [{
196 key: ENABLE_LOCK_SCREEN_PREF,
197 type: chrome.settingsPrivate.PrefType.BOOLEAN,
198 value: true
199 }];
200 fakeSettings = new settings.FakeSettingsPrivate(fakePrefs);
201 setLockScreenPref(true);
202 var prefElement = document.createElement('settings-prefs');
203 prefElement.initialize(fakeSettings);
204 document.body.appendChild(prefElement);
205
206 // Wait for prefElement to finish initializing; it takes some time for
207 // the prefs element to get allocated.
208 prefElement.addEventListener('prefs-changed', function prefsReady() {
209 prefElement.removeEventListener('prefs-changed', prefsReady);
210
211 quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
212
213 // Create choose-method element.
214 element = document.createElement('settings-lock-screen');
215 element.settingsPrivate_ = fakeSettings;
216 element.quickUnlockPrivate_ = quickUnlockPrivateApi;
217 element.prefs = prefElement.prefs;
218
219 document.body.appendChild(element);
220 Polymer.dom.flush();
221
222 element.setModes_ =
223 quickUnlockPrivateApi.setModes.bind(quickUnlockPrivateApi, '');
224
225 passwordRadioButton =
226 getFromElement('paper-radio-button[name="password"]');
227 pinPasswordRadioButton =
228 getFromElement('paper-radio-button[name="pin+password"]');
229 configureButton = getFromElement('paper-button');
230
231 done();
232 });
233 });
234
235 // Showing the choose method screen does not make any destructive pref or
236 // quickUnlockPrivate calls.
237 test('ShowingScreenDoesNotModifyPrefs', function() {
238 assertTrue(getLockScreenPref());
239 assertRadioButtonActive(passwordRadioButton);
240 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
241 });
242
243 // The various radio buttons update internal state and do not modify
244 // prefs.
245 test('TappingButtonsChangesUnderlyingState', function() {
246 function togglePin() {
247 assertRadioButtonActive(passwordRadioButton);
248
249 // Tap pin+password button.
250 MockInteractions.tap(pinPasswordRadioButton);
251 assertRadioButtonActive(pinPasswordRadioButton);
252 assertTrue(isVisible(configureButton));
253 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
254
255 // Enable quick unlock so that we verify tapping password disables it.
256 setActiveModes([QuickUnlockMode.PIN]);
257
258 // Tap password button and verify quick unlock is disabled.
259 MockInteractions.tap(passwordRadioButton);
260 assertRadioButtonActive(passwordRadioButton);
261 assertFalse(isVisible(configureButton));
262 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
263 }
264
265 // Verify toggling PIN on/off does not disable screen lock.
266 setLockScreenPref(true);
267 togglePin();
268 assertTrue(getLockScreenPref());
269
270 // Verify toggling PIN on/off does not enable screen lock.
271 setLockScreenPref(false);
272 togglePin();
273 assertFalse(getLockScreenPref());
274 });
275
276 // If quick unlock is changed by another settings page the radio button
277 // will update to show quick unlock is active.
278 test('EnablingQuickUnlockChangesButtonState', function() {
279 setActiveModes([QuickUnlockMode.PIN]);
280 assertRadioButtonActive(pinPasswordRadioButton);
281 assertTrue(isVisible(configureButton));
282
283 setActiveModes([]);
284 assertRadioButtonActive(passwordRadioButton);
285 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
286 });
287
288 // Tapping the PIN configure button opens up the setup PIN dialog.
289 test('TappingConfigureOpensSetupPin', function() {
290 assertRadioButtonActive(passwordRadioButton);
291
292 MockInteractions.tap(pinPasswordRadioButton);
293 assertTrue(isVisible(configureButton));
294 assertRadioButtonActive(pinPasswordRadioButton)
295
296 MockInteractions.tap(configureButton);
297 var setupPinDialog = getFromElement('#setupPin');
298 assertTrue(setupPinDialog.$.dialog.open);
299 });
300 });
301 }
302
303 function registerSetupPinDialogTests() {
304 suite('setup-pin-dialog', function() {
305 var titleDiv = null;
306 var problemDiv = null;
307 var pinKeyboard = null;
308 var backButton = null;
309 var continueButton = null;
310
311 suiteSetup(function() {
312 var urls = ['chrome://md-settings/i18n_setup.html'];
313 return Promise.all(urls.map(PolymerTest.importHtml));
314 });
315
316 setup(function() {
317 PolymerTest.clearBody();
318
319 quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
320
321 // Create setup-pin element.
322 element = document.createElement('settings-setup-pin-dialog');
323 element.setModes =
324 quickUnlockPrivateApi.setModes.bind(quickUnlockPrivateApi, '');
325
326 document.body.appendChild(element);
327 Polymer.dom.flush();
328
329 element.open();
330
331 titleDiv = getFromElement('div[class="title"]');
332 problemDiv = getFromElement('#problemDiv');
333 pinKeyboard = getFromElement('pin-keyboard');
334 backButton = getFromElement('paper-button[class="cancel-button"]');
335 continueButton = getFromElement('paper-button[class="action-button"]');
336
337 assertTrue(isVisible(backButton));
338 assertTrue(isVisible(continueButton));
339 });
340
341 // The continue button and title change text between the setup and confirm
342 // steps.
343 test('TextChangesBetweenSetupAndConfirmStep', function() {
344 var initialContinue = continueButton.textContent;
345 var initialTitle = titleDiv.textContent;
346
347 pinKeyboard.value = '1111';
348 MockInteractions.tap(continueButton);
349
350 assertNotEquals(initialContinue, continueButton.textContent);
351 assertNotEquals(initialTitle, titleDiv.textContent);
352 });
353
354 // The continue button is disabled unless the user has entered a >= 4
355 // digit PIN.
356 test('CanOnlyContinueAfterEnteringAtLeastFourDigitPin', function() {
357 pinKeyboard.value = '111';
358 assertTrue(continueButton.disabled);
359
360 pinKeyboard.value = '1111';
361 assertFalse(continueButton.disabled);
362
363 pinKeyboard.value = '111';
364 assertTrue(continueButton.disabled);
365
366 pinKeyboard.value = '';
367 assertTrue(continueButton.disabled);
368
369 pinKeyboard.value = '1111111';
370 assertFalse(continueButton.disabled);
371 });
372
373 // Problem messages are hidden if the PIN is cleared.
374 test('NoProblemShownWithEmptyPin', function() {
375 pinKeyboard.value = '11';
376 assertTrue(isVisible(problemDiv));
377
378 pinKeyboard.value = '';
379 assertFalse(isVisible(problemDiv));
380 });
381
382 // If the PIN is too short an error problem is shown.
383 test('ErrorShownForShortPins', function() {
384 assertFalse(isVisible(problemDiv));
385
386 pinKeyboard.value = '11';
387
388 assertTrue(isVisible(problemDiv));
389 assertHasClass(problemDiv, 'error');
390 assertTrue(continueButton.disabled);
391 });
392
393 // If the PIN is weak a warning problem is shown.
394 test('WarningShownForWeakPins', function() {
395 assertFalse(isVisible(problemDiv));
396
397 pinKeyboard.value = '1111';
398
399 assertTrue(isVisible(problemDiv));
400 assertHasClass(problemDiv, 'warning');
401 });
402
403 // If the confirm PIN does not match the initial PIN an error is shown and
404 // the submit button is disabled.
405 test('ErrorShownForMismatchedPins', function() {
406 pinKeyboard.value = '1118';
407 MockInteractions.tap(continueButton);
408 pinKeyboard.value = '1119';
409
410 assertTrue(isVisible(problemDiv));
411 assertHasClass(problemDiv, 'error');
412 assertTrue(continueButton.disabled);
413 });
414
415 // Hitting cancel at the setup step dismisses the dialog.
416 test('HittingBackButtonResetsState', function() {
417 MockInteractions.tap(backButton);
418 assertFalse(element.$.dialog.open);
419 });
420
421 // Hitting cancel at the confirm step dismisses the dialog.
422 test('HittingBackButtonResetsState', function() {
423 pinKeyboard.value = '1111';
424 MockInteractions.tap(continueButton);
425 MockInteractions.tap(backButton);
426 assertFalse(element.$.dialog.open);
427 });
428
429 // User has to re-enter PIN for confirm step.
430 test('PinKeyboardIsResetForConfirmStep', function() {
431 pinKeyboard.value = '1111';
432 MockInteractions.tap(continueButton);
433 assertEquals('', pinKeyboard.value);
434 });
435
436 // Completing the flow results in a call to the quick unlock private API.
437 test('SubmittingPinCallsQuickUnlockApi', function() {
438 // Entering the same (even weak) pin twice calls the quick unlock API
439 // and sets up a PIN.
440 pinKeyboard.value = '1111';
441 MockInteractions.tap(continueButton);
442 pinKeyboard.value = '1111';
443 MockInteractions.tap(continueButton);
444
445 assertDeepEquals(['PIN'], quickUnlockPrivateApi.activeModes);
446 assertDeepEquals(['1111'], quickUnlockPrivateApi.credentials);
447 });
448 });
449 }
450
451 return {
452 registerAuthenticateTests: registerAuthenticateTests,
453 registerLockScreenTests: registerLockScreenTests,
454 registerSetupPinDialogTests: registerSetupPinDialogTests
455 };
456 });
OLDNEW
« no previous file with comments | « chrome/test/data/webui/settings/fake_quick_unlock_private.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698