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

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: Rebase 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
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 elmeent 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 }
stevenjb 2016/10/13 21:36:45 Is just testing element.offsetWidth/Height not suf
jdufault 2016/10/13 23:41:24 Nope :(
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('#foobar');//paper-button');
stevenjb 2016/10/13 21:36:45 ??
jdufault 2016/10/13 23:41:24 Done.
230 configureButton = getFromElement('paper-button');
231
232 // Wait for the element to finish initializing.
233 //element.addEventListener('ready', function() { done(); });
234 //done();
stevenjb 2016/10/13 21:36:45 ??
jdufault 2016/10/13 23:41:24 Done.
235 setTimeout(function() { done(); }, 500);
236 });
237 });
238
239 // Showing the choose method screen does not make any destructive pref or
240 // quickUnlockPrivate calls.
241 test('ShowingScreenDoesNotModifyPrefs', function() {
242 assertTrue(getLockScreenPref());
243 assertRadioButtonActive(passwordRadioButton);
244 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
245 });
246
247 // The various radio buttons update internal state and do not modify
248 // prefs.
249 test('TappingButtonsChangesUnderlyingState', function() {
250 function togglePin() {
251 assertRadioButtonActive(passwordRadioButton);
252
253 // Tap pin+password button.
254 MockInteractions.tap(pinPasswordRadioButton);
255 assertRadioButtonActive(pinPasswordRadioButton);
256 assertTrue(isVisible(configureButton));
257 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
258
259 // Enable quick unlock so that we verify tapping password disables it.
260 setActiveModes([QuickUnlockMode.PIN]);
261
262 // Tap password button and verify quick unlock is disabled.
263 MockInteractions.tap(passwordRadioButton);
264 assertRadioButtonActive(passwordRadioButton);
265 assertFalse(isVisible(configureButton));
266 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
267 }
268
269 // Verify toggling PIN on/off does not disable screen lock.
270 setLockScreenPref(true);
271 togglePin();
272 assertTrue(getLockScreenPref());
273
274 // Verify toggling PIN on/off does not enable screen lock.
275 setLockScreenPref(false);
276 togglePin();
277 assertFalse(getLockScreenPref());
278 });
279
280 // If quick unlock is changed by another settings page the radio button
281 // will update to show quick unlock is active.
282 test('EnablingQuickUnlockChangesButtonState', function() {
283 setActiveModes([QuickUnlockMode.PIN]);
284 assertRadioButtonActive(pinPasswordRadioButton);
285 assertTrue(isVisible(configureButton));
286
287 setActiveModes([]);
288 assertRadioButtonActive(passwordRadioButton);
289 assertDeepEquals([], quickUnlockPrivateApi.activeModes);
290 });
291
292 // Tapping the PIN configure button opens up the setup PIN dialog.
293 test('TappingConfigureOpensSetupPin', function() {
294 assertRadioButtonActive(passwordRadioButton);
295
296 MockInteractions.tap(pinPasswordRadioButton);
297 assertTrue(isVisible(configureButton));
298 assertRadioButtonActive(pinPasswordRadioButton)
299
300 MockInteractions.tap(configureButton);
301 var setupPinDialog = getFromElement('#setupPin');
302 assertTrue(setupPinDialog.$.dialog.open);
303 });
304 });
305 }
306
307 function registerSetupPinDialogTests() {
308 suite('setup-pin-dialog', function() {
309 var titleDiv = null;
310 var problemDiv = null;
311 var pinKeyboard = null;
312 var backButton = null;
313 var continueButton = null;
314
315 suiteSetup(function() {
316 var urls = ['chrome://md-settings/i18n_setup.html'];
317 return Promise.all(urls.map(PolymerTest.importHtml));
318 });
319
320 setup(function() {
321 PolymerTest.clearBody();
322
323 quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
324
325 // Create setup-pin element.
326 element = document.createElement('settings-setup-pin-dialog');
327 element.setModes =
328 quickUnlockPrivateApi.setModes.bind(quickUnlockPrivateApi, '');
329
330 document.body.appendChild(element);
331 Polymer.dom.flush();
332
333 element.open();
334
335 titleDiv = getFromElement('div[class="title"]');
336 problemDiv = getFromElement('#problemDiv');
337 pinKeyboard = getFromElement('pin-keyboard');
338 backButton = getFromElement('paper-button[class="cancel-button"]');
339 continueButton = getFromElement('paper-button[class="action-button"]');
340
341 assertTrue(isVisible(backButton));
342 assertTrue(isVisible(continueButton));
343 });
344
345 // The continue button and title change text between the setup and confirm
346 // steps.
347 test('TextChangesBetweenSetupAndConfirmStep', function() {
348 var initialContinue = continueButton.textContent;
349 var initialTitle = titleDiv.textContent;
350
351 pinKeyboard.value = '1111';
352 MockInteractions.tap(continueButton);
353
354 assertNotEquals(initialContinue, continueButton.textContent);
355 assertNotEquals(initialTitle, titleDiv.textContent);
356 });
357
358 // The continue button is disabled unless the user has entered a >= 4
359 // digit PIN.
360 test('CanOnlyContinueAfterEnteringAtLeastFourDigitPin', function() {
361 pinKeyboard.value = '111';
362 assertTrue(continueButton.disabled);
363
364 pinKeyboard.value = '1111';
365 assertFalse(continueButton.disabled);
366
367 pinKeyboard.value = '111';
368 assertTrue(continueButton.disabled);
369
370 pinKeyboard.value = '';
371 assertTrue(continueButton.disabled);
372
373 pinKeyboard.value = '1111111';
374 assertFalse(continueButton.disabled);
375 });
376
377 // Problem messages are hidden if the PIN is cleared.
378 test('NoProblemShownWithEmptyPin', function() {
379 pinKeyboard.value = '11';
380 assertTrue(isVisible(problemDiv));
381
382 pinKeyboard.value = '';
383 assertFalse(isVisible(problemDiv));
384 });
385
386 // If the PIN is too short an error problem is shown.
387 test('ErrorShownForShortPins', function() {
388 assertFalse(isVisible(problemDiv));
389
390 pinKeyboard.value = '11';
391
392 assertTrue(isVisible(problemDiv));
393 assertHasClass(problemDiv, 'error');
394 assertTrue(continueButton.disabled);
395 });
396
397 // If the PIN is weak a warning problem is shown.
398 test('WarningShownForWeakPins', function() {
399 assertFalse(isVisible(problemDiv));
400
401 pinKeyboard.value = '1111';
402
403 assertTrue(isVisible(problemDiv));
404 assertHasClass(problemDiv, 'warning');
405 });
406
407 // If the confirm PIN does not match the initial PIN an error is shown and
408 // the submit button is disabled.
409 test('ErrorShownForMismatchedPins', function() {
410 pinKeyboard.value = '1118';
411 MockInteractions.tap(continueButton);
412 pinKeyboard.value = '1119';
413
414 assertTrue(isVisible(problemDiv));
415 assertHasClass(problemDiv, 'error');
416 assertTrue(continueButton.disabled);
417 });
418
419 // Hitting cancel at the setup step dismisses the dialog.
420 test('HittingBackButtonResetsState', function() {
421 MockInteractions.tap(backButton);
422 assertFalse(element.$.dialog.open);
423 });
424
425 // Hitting cancel at the confirm step dismisses the dialog.
426 test('HittingBackButtonResetsState', function() {
427 pinKeyboard.value = '1111';
428 MockInteractions.tap(continueButton);
429 MockInteractions.tap(backButton);
430 assertFalse(element.$.dialog.open);
431 });
432
433 // User has to re-enter PIN for confirm step.
434 test('PinKeyboardIsResetForConfirmStep', function() {
435 pinKeyboard.value = '1111';
436 MockInteractions.tap(continueButton);
437 assertEquals('', pinKeyboard.value);
438 });
439
440 // Completing the flow results in a call to the quick unlock private API.
441 test('SubmittingPinCallsQuickUnlockApi', function() {
442 // Entering the same (even weak) pin twice calls the quick unlock API
443 // and sets up a PIN.
444 pinKeyboard.value = '1111';
445 MockInteractions.tap(continueButton);
446 pinKeyboard.value = '1111';
447 MockInteractions.tap(continueButton);
448
449 assertDeepEquals(['PIN'], quickUnlockPrivateApi.activeModes);
450 assertDeepEquals(['1111'], quickUnlockPrivateApi.credentials);
451 });
452 });
453 }
454
455 return {
456 registerAuthenticateTests: registerAuthenticateTests,
457 registerLockScreenTests: registerLockScreenTests,
458 registerSetupPinDialogTests: registerSetupPinDialogTests
459 };
460 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698