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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
diff --git a/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
new file mode 100644
index 0000000000000000000000000000000000000000..68aa394481c74f9f3a0d7f7ff0c18dca63a0ceea
--- /dev/null
+++ b/chrome/test/data/webui/settings/quick_unlock_authenticate_browsertest_chromeos.js
@@ -0,0 +1,482 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('settings_people_page_quick_unlock', function() {
+ var element = null;
+ var quickUnlockPrivateApi = null;
+ var QuickUnlockMode = chrome.quickUnlockPrivate.QuickUnlockMode;
+
+ /**
+ * Verifies element is visible.
+ * @param {!Element} element
+ */
+ 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
+ assertTrue(element.offsetWidth > 0);
+ }
+
+ /**
+ * Verifies element is not visible.
+ * @param {!Element} element
+ */
+ function assertNotVisible(element) {
+ assertTrue(element.offsetWidth <= 0 && element.offsetHeight <= 0);
+ }
+
+ /**
+ * Returns true if the given |element| has class |className|.
+ * @param {!Element} element
+ * @param {string} className
+ */
+ function assertHasClass(element, className) {
+ assertTrue(element.classList.contains(className));
+ }
+
+ /**
+ * Returns the result of running |selector| on element.
+ * @param {string} selector
+ * @return {Element}
+ */
+ function getFromElement(selector) {
+ var childElement = element.$$(selector);
+ assertTrue(!!childElement);
+ return childElement;
+ }
+
+ /**
+ * Sets the active quick unlock modes and raises a mode change event.
+ * @param {!Array<chrome.quickUnlockPrivate.QuickUnlockMode>} modes
+ */
+ function setActiveModes(modes) {
+ quickUnlockPrivateApi.activeModes = modes;
+ quickUnlockPrivateApi.onActiveModesChanged.callListeners(modes);
+ }
+
+ function registerAuthenticateTests() {
+ suite('authenticate', function() {
+ var passwordElement = null;
+
+ setup(function() {
+ PolymerTest.clearBody();
+
+ quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
+
+ element = document.createElement('settings-quick-unlock-authenticate');
+ element.quickUnlockPrivate_ = quickUnlockPrivateApi;
+ document.body.appendChild(element);
+
+ passwordElement = getFromElement('#password-input');
+ });
+
+ // Checking the password does not change the active set of quick unlock
+ // 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.
+ test('PasswordCheckDoesNotChangeActiveMode', function() {
+ // No active modes.
+ quickUnlockPrivateApi.activeModes = [];
+ passwordElement.value = 'foo';
+ element.checkPasswordNow_();
+ assertDeepEquals([], quickUnlockPrivateApi.activeModes);
+ assertDeepEquals([], quickUnlockPrivateApi.credentials);
+
+ // PIN is active.
+ quickUnlockPrivateApi.activeModes = [QuickUnlockMode.PIN];
+ passwordElement.value = 'foo';
+ element.checkPasswordNow_();
+ assertDeepEquals([QuickUnlockMode.PIN],
+ quickUnlockPrivateApi.activeModes);
+ assertDeepEquals([''], quickUnlockPrivateApi.credentials);
+ });
+
+ // A bad password does not provide an authenticated setModes object.
+ test('InvalidPasswordDoesNotProvideAuthentication', function() {
+ quickUnlockPrivateApi.accountPassword = 'bar';
+
+ passwordElement.value = 'foo';
+ element.checkPasswordNow_();
+
+ 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.
+ });
+
+ // A valid password provides an authenticated setModes object.
+ test('ValidPasswordProvidesAuthentication', function() {
+ quickUnlockPrivateApi.accountPassword = 'foo';
+
+ passwordElement.value = 'foo';
+ element.checkPasswordNow_();
+
+ assertTrue(!!element.setModes);
+ });
+
+ // The password automatically submits after a delay.
+ test('PasswordAutoSubmitsAfterDelay', function(done) {
+ quickUnlockPrivateApi.accountPassword = 'foo';
+
+ element.autosubmitDelayMs_ = 0;
+ passwordElement.value = 'foo';
+ element.startDelayedPasswordCheck_();
+
+ setTimeout(function() {
+ assertFalse(!!element.password_);
+ assertTrue(!!element.setModes);
+ done();
+ }, 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.
+ });
+
+ // The setModes objects times out after a delay.
+ test('AuthenticationTimesOut', function(done) {
+ quickUnlockPrivateApi.accountPassword = 'foo';
+
+ element.passwordActiveDurationMs_ = 0;
+ passwordElement.value = 'foo';
+ element.checkPasswordNow_();
+
+ assertFalse(!!element.password_);
+ assertTrue(!!element.setModes);
+
+ setTimeout(function() {
+ assertFalse(!!element.password_);
+ assertFalse(!!element.setModes);
+ done();
+ }, 50);
+ });
+ });
+ }
+
+ function registerChooseMethodTests() {
+ suite('choose-method', function() {
+ /** @const */ var ENABLE_LOCK_SCREEN_PREF = 'settings.enable_screen_lock';
+
+ var fakeSettings = null;
+ var passwordRadioButton = null;
+ var pinPasswordRadioButton = null;
+ var noneRadioButton = null;
+ var configureButton = null;
+
+ /**
+ * Asserts that only the given radio button is active and all of the
+ * others are inactive.
+ * @param {Element} radioButton
+ */
+ function assertRadioButtonActive(radioButton) {
+ function doAssert(element, name) {
+ if (radioButton == element)
+ assertTrue(element.active, 'Expected ' + name + ' to be active');
+ else
+ assertFalse(element.active, 'Expected ' + name + ' to be inactive');
+ }
+
+ doAssert(passwordRadioButton, 'passwordButton');
+ doAssert(pinPasswordRadioButton, 'pinPasswordButton');
+ doAssert(noneRadioButton, 'noneButton');
+ }
+
+ /**
+ * Returns the lock screen pref value.
+ * @return {boolean}
+ */
+ function getLockScreenPref() {
+ return element.getPref(ENABLE_LOCK_SCREEN_PREF).value;
+ }
+
+ /**
+ * Changes the lock screen pref value using the settings API; this is like
+ * the pref got changed from an unkown source such as another tab.
+ * @param {boolean} value
+ */
+ function setLockScreenPrefOnSettings(value) {
+ fakeSettings.setPref(ENABLE_LOCK_SCREEN_PREF, value, '', assertTrue);
+ }
+
+ setup(function(done) {
+ PolymerTest.clearBody();
+
+ CrSettingsPrefs.deferInitialization = true;
+
+ // Build pref fakes.
+ var fakePrefs = [{
+ key: ENABLE_LOCK_SCREEN_PREF,
+ type: chrome.settingsPrivate.PrefType.BOOLEAN,
+ value: true
+ }];
+ fakeSettings = new settings.FakeSettingsPrivate(fakePrefs);
+ setLockScreenPrefOnSettings(true);
+ var prefElement = document.createElement('settings-prefs');
+ prefElement.initializeForTesting(fakeSettings);
+ document.body.appendChild(prefElement);
+
+ // Wait for prefElement to finish initializing; it takes some time for
+ // the prefs element to get allocated.
+ prefElement.addEventListener('prefs-changed', function prefsReady() {
+ prefElement.removeEventListener('prefs-changed', prefsReady);
+
+ quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
+
+ // Create choose-method element.
+ element = document.createElement(
+ 'settings-quick-unlock-choose-method');
+ element.settingsPrivate_ = fakeSettings;
+ element.quickUnlockPrivate_ = quickUnlockPrivateApi;
+ element.prefs = prefElement.prefs;
+ element.currentRoute = {
+ url: '/quickUnlock/chooseMethod',
+ page: 'basic',
+ section: 'people',
+ subpage: ['quick-unlock-choose-method'],
+ };
+ element.setModes =
+ quickUnlockPrivateApi.setModes.bind(quickUnlockPrivateApi, '');
+
+ // Previous test may have disabled the pref.
+ element.setPrefValue(ENABLE_LOCK_SCREEN_PREF, true);
+
+ document.body.appendChild(element);
+ Polymer.dom.flush();
+
+ passwordRadioButton =
+ getFromElement('paper-radio-button[name="password"]');
+ pinPasswordRadioButton =
+ getFromElement('paper-radio-button[name="pin+password"]');
+ noneRadioButton = getFromElement('paper-radio-button[name="none"]');
+ configureButton = getFromElement('paper-button');
+
+ // Give the element some time to initialize.
+ 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
+ });
+ });
+
+ // Showing the choose method screen does not make any destructive pref or
+ // quickUnlockPrivate calls.
+ test('ShowingScreenDoesNotModifyPrefs', function() {
+ assertTrue(getLockScreenPref());
+ assertRadioButtonActive(passwordRadioButton);
+ assertDeepEquals([], quickUnlockPrivateApi.activeModes);
+ });
+
+ // The various radio buttons update the pref and quick unlock state.
+ test('TappingButtonsChangesUnderlyingState', function() {
+ assertTrue(getLockScreenPref());
+ assertRadioButtonActive(passwordRadioButton);
+
+ function tapNone() {
+ MockInteractions.tap(noneRadioButton);
+ assertRadioButtonActive(noneRadioButton);
+ assertNotVisible(configureButton);
+ assertDeepEquals([], quickUnlockPrivateApi.activeModes);
+ assertFalse(getLockScreenPref());
+ }
+
+ // Disable pref.
+ tapNone();
+
+ // Tap pin+password button, verify pref is enabled.
+ MockInteractions.tap(pinPasswordRadioButton);
+ assertRadioButtonActive(pinPasswordRadioButton);
+ assertVisible(configureButton);
+ assertDeepEquals([], quickUnlockPrivateApi.activeModes);
+ assertTrue(getLockScreenPref());
+
+ // Enable quick unlock so that we verify tapping none disables it.
+ setActiveModes([QuickUnlockMode.PIN]);
+ tapNone();
+
+ // Tap password button, verify pref is enabled.
+ MockInteractions.tap(passwordRadioButton);
+ assertRadioButtonActive(passwordRadioButton);
+ assertNotVisible(configureButton);
+ assertDeepEquals([], quickUnlockPrivateApi.activeModes);
+ assertTrue(getLockScreenPref());
+ });
+
+ // If quick unlock is changed by another settings page the radio button
+ // will update to show quick unlock is active.
+ test('EnablingQuickUnlockChangesButtonState', function() {
+ assertTrue(getLockScreenPref());
+ assertRadioButtonActive(passwordRadioButton);
+ assertDeepEquals([], quickUnlockPrivateApi.activeModes);
+
+ setActiveModes([QuickUnlockMode.PIN]);
+ assertRadioButtonActive(pinPasswordRadioButton);
+ assertVisible(configureButton);
+ });
+
+ // If prefs are changed by another source the radio button will update.
+ test('PrefChangeUpdatesButtonState', function() {
+ assertTrue(getLockScreenPref());
+ assertRadioButtonActive(passwordRadioButton);
+
+ setLockScreenPrefOnSettings(false);
+ assertRadioButtonActive(noneRadioButton);
+
+ setLockScreenPrefOnSettings(true);
+ assertRadioButtonActive(passwordRadioButton);
+ }),
+
+ // Tapping the PIN configure button changes the route to the setup pin
+ // page.
+ test('TappingConfigureOpensSetupPin', function() {
+ assertTrue(getLockScreenPref());
+ assertRadioButtonActive(passwordRadioButton);
+
+ MockInteractions.tap(pinPasswordRadioButton);
+ assertVisible(configureButton);
+ assertRadioButtonActive(pinPasswordRadioButton)
+
+ MockInteractions.tap(configureButton);
+ 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
+ element.currentRoute.subpage.slice(-1)[0]);
+ });
+ });
+ }
+
+ function registerSetupPinTests() {
+ suite('setup-pin', function() {
+ var titleDiv = null;
+ var problemDiv = null;
+ var pinKeyboard = null;
+ var backButton = null;
+ var continueButton = null;
+
+ setup(function() {
+ PolymerTest.clearBody();
+
+ quickUnlockPrivateApi = new settings.FakeQuickUnlockPrivate();
+
+ // Create choose-method element.
+ element = document.createElement('settings-quick-unlock-setup-pin');
+ element.quickUnlockPrivate_ = quickUnlockPrivateApi;
+ element.currentRoute = {
+ url: '/quickUnlock/setupPin',
+ page: 'basic',
+ section: 'people',
+ subpage: ['quick-unlock-choose-method', 'quick-unlock-setup-pin'],
+ };
+ element.setModes =
+ quickUnlockPrivateApi.setModes.bind(quickUnlockPrivateApi, '');
+
+ document.body.appendChild(element);
+ Polymer.dom.flush();
+
+ titleDiv = getFromElement('#title-div');
+ problemDiv = getFromElement('#problem-div');
+ pinKeyboard = getFromElement('pin-keyboard');
+ backButton = getFromElement('paper-button[class="cancel-button"]');
+ continueButton = getFromElement('paper-button[class="action-button"]');
+ });
+
+ // The back button is only displayed during the confirm PIN step.
+ test('BackOnlyShownWhenConfirmingPin', function() {
+ assertNotVisible(backButton);
+ assertVisible(continueButton);
+
+ pinKeyboard.value = '1111';
+ MockInteractions.tap(continueButton);
+
+ assertVisible(backButton);
+ });
+
+ // The continue button is disabled unless the user has entered a >= 4
+ // digit PIN.
+ test('CanOnlyContinueAfterEnteringAtLeastFourDigitPin', function() {
+ pinKeyboard.value = '111';
+ assertTrue(continueButton.disabled);
+
+ pinKeyboard.value = '1111';
+ assertFalse(continueButton.disabled);
+
+ pinKeyboard.value = '111';
+ assertTrue(continueButton.disabled);
+
+ pinKeyboard.value = '';
+ assertTrue(continueButton.disabled);
+
+ pinKeyboard.value = '1111111';
+ assertFalse(continueButton.disabled);
+ });
+
+ // Problem messages are hidden if the PIN is cleared.
+ test('NoProblemShownWithEmptyPin', function() {
+ pinKeyboard.value = '11';
+ assertVisible(problemDiv);
+
+ pinKeyboard.value = '';
+ assertNotVisible(problemDiv);
+ });
+
+ // If the PIN is too short an error problem is shown.
+ test('ErrorShownForShortPins', function() {
+ assertVisible(titleDiv);
+ assertNotVisible(problemDiv);
+
+ pinKeyboard.value = '11';
+
+ assertNotVisible(titleDiv);
+ assertVisible(problemDiv);
+ assertHasClass(problemDiv, 'error');
+ assertTrue(continueButton.disabled);
+ });
+
+ // If the PIN is weak a warning problem is shown.
+ test('WarningShownForWeakPins', function() {
+ assertVisible(titleDiv);
+ assertNotVisible(problemDiv);
+
+ pinKeyboard.value = '1111';
+
+ assertNotVisible(titleDiv);
+ assertVisible(problemDiv);
+ assertHasClass(problemDiv, 'warning');
+ });
+
+ // If the confirm PIN does not match the initial PIN an error is shown and
+ // the submit button is disabled.
+ test('ErrorShownForMismatchedPins', function() {
+ pinKeyboard.value = '1118';
+ MockInteractions.tap(continueButton);
+ pinKeyboard.value = '1119';
+
+ assertVisible(problemDiv);
+ assertHasClass(problemDiv, 'error');
+ assertTrue(continueButton.disabled);
+ });
+
+ // Hitting back on the confirm PIN step properly resets the flow.
+ test('HittingBackButtonResetsState', function() {
+ // Submit initial PIN.
+ pinKeyboard.value = '1111';
+ MockInteractions.tap(continueButton);
+ assertVisible(backButton);
+ assertEquals('', pinKeyboard.value);
+
+ // Prepare confirm pin but go back instead.
+ pinKeyboard.value = '1111';
+ MockInteractions.tap(backButton);
+ assertNotVisible(backButton);
+ assertEquals('', pinKeyboard.value);
+
+ // Submit initial PIN; verify we did not call quick unlock private API.
+ pinKeyboard.value = '1111';
+ MockInteractions.tap(continueButton);
+ assertDeepEquals([], quickUnlockPrivateApi.activeModes);
+ });
+
+ // Completing the flow results in a call to the quick unlock private API.
+ test('SubmittingPinCallsQuickUnlockApi', function() {
+ // Entering the same (even weak) pin twice calls the quick unlock API
+ // and sets up a PIN.
+ pinKeyboard.value = '1111';
+ MockInteractions.tap(continueButton);
+ pinKeyboard.value = '1111';
+ MockInteractions.tap(continueButton);
+
+ assertDeepEquals(['PIN'], quickUnlockPrivateApi.activeModes);
+ assertDeepEquals(['1111'], quickUnlockPrivateApi.credentials);
+ });
+ });
+ }
+
+ return {
+ registerAuthenticateTests: registerAuthenticateTests,
+ registerChooseMethodTests: registerChooseMethodTests,
+ registerSetupPinTests: registerSetupPinTests
+ };
+});

Powered by Google App Engine
This is Rietveld 408576698