зеркало из https://github.com/mozilla/fxa.git
test(functional): remove old functional intern tests and files
This reverts commit 375aeb0570c8b7ecf424079153637d9c36824d32.
This commit is contained in:
Родитель
3733a298f5
Коммит
5a5e8e7b49
|
@ -25,13 +25,6 @@
|
|||
"start-production": "NODE_ENV=production grunt build && yarn build-css && CONFIG_FILES=server/config/local.json,server/config/production.json,server/config/secrets.json grunt serverproc:dist",
|
||||
"start-remote": "scripts/run_remote_dev.sh",
|
||||
"test": "node tests/intern.js --unit=true",
|
||||
"test-functional": "node tests/intern.js",
|
||||
"test-functional-oauth": "node tests/intern.js --grep='oauth'",
|
||||
"test-functional-settings": "node tests/intern.js --suites=settings",
|
||||
"test-latest": "SKIP_MOCHA=true node tests/intern.js --fxaAuthRoot=https://latest.dev.lcip.org/auth/v1 --fxaContentRoot=https://latest.dev.lcip.org/ --fxaEmailRoot=http://restmail.net --fxaOAuthApp=https://123done-latest.dev.lcip.org/ --fxaUntrustedOauthApp=https://321done-latest.dev.lcip.org/ --fxaProduction=true --fxaToken=https://token.dev.lcip.org/1.0/sync/1.5",
|
||||
"test-pairing": "node tests/intern.js --suites=pairing",
|
||||
"test-pairing-circle": "node tests/intern.js --suites=pairing --fxaAuthRoot=https://fxaci.dev.lcip.org/auth --fxaEmailRoot=http://restmail.net --fxaOAuthApp=https://123done-fxaci.dev.lcip.org/ --fxaProduction=true --bailAfterFirstFailure=true",
|
||||
"test-server": "node tests/intern.js --suites=server",
|
||||
"format": "prettier --write --config ../../_dev/.prettierrc '**'"
|
||||
},
|
||||
"repository": {
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
#!/bin/bash -ex
|
||||
|
||||
DIR=$(dirname "$0")
|
||||
cd "$DIR/.."
|
||||
echo -e "\n###################################"
|
||||
echo "# testing fxa-content-server"
|
||||
echo -e "###################################\n"
|
||||
|
||||
env | sort
|
||||
|
||||
function test_suite() {
|
||||
local suite=$1
|
||||
local numGroups=$2
|
||||
local i=$3
|
||||
|
||||
local fxaAccountsApiDomain="${ACCOUNTS_API_DOMAIN:-api-accounts.stage.mozaws.net}"
|
||||
local fxaAccountsDomain="${ACCOUNTS_DOMAIN:-accounts.stage.mozaws.net}"
|
||||
local relierDomain="${RELIER_DOMAIN:-stage-123done.herokuapp.com}"
|
||||
local untrustedRelierDomain="${UNTRUSTED_RELIER_DOMAIN:-stage-123done-untrusted.herokuapp.com}"
|
||||
|
||||
node tests/intern.js \
|
||||
--suites="${suite}" \
|
||||
--fxaAuthRoot=https://${fxaAccountsApiDomain}/v1 \
|
||||
--fxaContentRoot=https://${fxaAccountsDomain}/ \
|
||||
--fxaOAuthApp=https://${relierDomain}/ \
|
||||
--fxaUntrustedOauthApp=https://${untrustedRelierDomain}/ \
|
||||
--fxaEmailRoot=http://restmail.net \
|
||||
--fxaProduction=true \
|
||||
--output="../../artifacts/tests/${suite}-${numGroups}-${i}-results.xml" \
|
||||
--testProductId="prod_FiJ42WCzZNRSbS" \
|
||||
--testPlanId="plan_HJyNT4gbuyyZ0G" \
|
||||
--groups=${numGroups} \
|
||||
--groupIndex=${i} \
|
||||
|| \
|
||||
node tests/intern.js \
|
||||
--suites="${suite}" \
|
||||
--fxaAuthRoot=https://${fxaAccountsApiDomain}/v1 \
|
||||
--fxaContentRoot=https://${fxaAccountsDomain}/ \
|
||||
--fxaOAuthApp=https://${relierDomain}/ \
|
||||
--fxaUntrustedOauthApp=https://${untrustedRelierDomain}/ \
|
||||
--fxaEmailRoot=http://restmail.net \
|
||||
--fxaProduction=true \
|
||||
--output="../../artifacts/tests/${suite}-${numGroups}-${i}-results.xml" \
|
||||
--grep="$(<rerun.txt)" \
|
||||
--testProductId="prod_FiJ42WCzZNRSbS" \
|
||||
--testPlanId="plan_HJyNT4gbuyyZ0G" \
|
||||
--groups=${numGroups} \
|
||||
--groupIndex=${i}
|
||||
}
|
||||
|
||||
cd ../../
|
||||
mkdir -p artifacts/tests
|
||||
|
||||
cd packages/fxa-content-server
|
||||
|
||||
test_suite functional_smoke $CIRCLE_NODE_TOTAL $CIRCLE_NODE_INDEX && test_suite functional_regression $CIRCLE_NODE_TOTAL $CIRCLE_NODE_INDEX
|
||||
# TODO: Re-enable once configuration in stage is updated
|
||||
# test_suite pairing
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/bash -ex
|
||||
|
||||
DIR=$(dirname "$0")
|
||||
|
||||
function test_suite() {
|
||||
local suite=$1
|
||||
local numGroups=$2
|
||||
|
||||
for i in $(seq "$numGroups")
|
||||
do
|
||||
node tests/intern.js --suites="${suite}" --output="../../artifacts/tests/${suite}-${numGroups}-${i}-results.xml" --groupsCount="${numGroups}" --groupNum="${i}" || \
|
||||
node tests/intern.js --suites="${suite}" --output="../../artifacts/tests/${suite}-${numGroups}-${i}-results.xml" --groupsCount="${numGroups}" --groupNum="${i}" --grep="$(<rerun.txt)"
|
||||
done
|
||||
}
|
||||
|
||||
cd "$DIR/.."
|
||||
|
||||
test_suite circle 3
|
||||
|
||||
# The last node currently has the least work to do in the above tests
|
||||
if [[ "${CIRCLE_NODE_INDEX}" == "2" ]]; then
|
||||
node tests/intern.js --suites='server' --output='../../artifacts/tests/server-results.xml'
|
||||
#Removing the flaky pairing suite, to be addressed in https://mozilla-hub.atlassian.net/browse/FXA-6558
|
||||
#node tests/intern.js --suites='pairing' --output='../../artifacts/tests/pairing-results.xml'
|
||||
fi
|
|
@ -1,87 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const testsSettings = require('./functional_settings');
|
||||
module.exports = testsSettings.concat([
|
||||
// new and flaky tests above here',
|
||||
// 'tests/functional/email_opt_in.js',
|
||||
// 'tests/functional/fx_desktop_handshake.js',
|
||||
|
||||
// 'tests/functional/oauth_sign_up.js',
|
||||
// 'tests/functional/pages.js',
|
||||
// 'tests/functional/post_verify/force_password_change.js',
|
||||
// 'tests/functional/post_verify/account_recovery.js',
|
||||
// 'tests/functional/post_verify/secondary_email.js',
|
||||
// 'tests/functional/sign_in.js',
|
||||
// 'tests/functional/sign_in_blocked.js',
|
||||
// 'tests/functional/sync_v3_sign_up.js',
|
||||
// 'tests/functional/sync_v3_settings.js',
|
||||
|
||||
// Disabled because of https://github.com/mozilla/fxa/issues/9863
|
||||
// 'tests/functional/verification_reminders.js',
|
||||
|
||||
// These tests no longer adds value and have been removed as
|
||||
// part of the analysis in
|
||||
// https://docs.google.com/spreadsheets/d/11Wq-Y-ipeNFXqLHbr3GJCh_f_qEAG-CUuqBt5Dcnh5k/edit#gid=0
|
||||
// 'tests/functional/bounced_email.js',
|
||||
// 'tests/functional/sync_v1.js',
|
||||
// 'tests/functional/pp.js',
|
||||
// 'tests/functional/sync_v2.js',
|
||||
// 'tests/functional/fx_firstrun_v2.js',
|
||||
// 'tests/functional/tos.js',
|
||||
// 'tests/functional/confirm.js',
|
||||
//'tests/functional/fx_ios_v1_sign_in.js',
|
||||
//'tests/functional/fx_ios_v1_sign_up.js',
|
||||
//'tests/functional/oauth_query_param_validation.js',
|
||||
//'tests/functional/refreshes_metrics.js',
|
||||
//'tests/functional/fx_browser_relier.js',
|
||||
//'tests/functional/500.js',
|
||||
//'tests/functional/email_domain_mx_validation.js',
|
||||
//'tests/functional/post_verify/newsletters.js',
|
||||
//''tests/functional/robots_txt.js',
|
||||
//'tests/functional/push.js',
|
||||
//''tests/functional/back_button_after_start.js',
|
||||
|
||||
// Disabled because this test migrated to Playwright
|
||||
// See `/functional-test`
|
||||
// 'tests/functional/oauth_handshake.js',
|
||||
// 'tests/functional/oauth_force_auth.js',
|
||||
// 'tests/functional/sync_v3_force_auth.js',
|
||||
// 'tests/functional/oauth_sign_in.js',
|
||||
//'tests/functional/subscriptions.js',
|
||||
//'tests/functional/support.js',
|
||||
// 'tests/functional/password_visibility.js',
|
||||
//'tests/functional/password_strength.js',
|
||||
//'tests/functional/avatar.js',
|
||||
//'tests/functional/settings/change_password.js',
|
||||
//'tests/functional/settings/connected_services_oauth_clients.js',
|
||||
//'tests/functional/settings/external_links.js',
|
||||
//'tests/functional/settings/recovery_key.js',
|
||||
//'tests/functional/settings/secondary_email.js',
|
||||
//'tests/functional/settings/two_step_auth.js',
|
||||
//'tests/functional/sign_up_with_code.js',
|
||||
//'tests/functional/sync_v3_email_first.js',
|
||||
// 'tests/functional/reset_password.js',
|
||||
//'tests/functional/oauth_reset_password.js',
|
||||
// 'tests/functional/legal.js',
|
||||
//'tests/functional/sign_in_cached.js',
|
||||
// 'tests/functional/cookies_disabled.js',
|
||||
//'tests/functional/sign_up.js',
|
||||
//'tests/functional/oauth_settings_clients.js',
|
||||
//'tests/functional/oauth_require_totp.js',
|
||||
//'tests/functional/force_auth.js',
|
||||
//'tests/functional/sync_v3_sign_in.js',
|
||||
//'tests/functional/sync_v3_reset_password.js',
|
||||
//'tests/functional/oauth_sync_sign_in.js',
|
||||
//'tests/functional/oauth_permissions.js',
|
||||
//'tests/functional/oauth_prompt_none.js',
|
||||
]);
|
||||
|
||||
// Mocha tests are only exposed during local dev, not on prod-like
|
||||
// instances such as latest, stable, stage, and prod. To avoid
|
||||
// Teamcity failing trying to run mocha tests, expose an environment
|
||||
// variable it can use to skip the mocha tests.
|
||||
if (!process.env.SKIP_MOCHA) {
|
||||
module.exports.unshift('tests/functional/mocha.js');
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const { click, openPage, clearBrowserState } = require('./lib/helpers');
|
||||
|
||||
registerSuite('404', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState({ forceAll: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'visit an invalid page': function () {
|
||||
const url = `${intern._config.fxaContentRoot}/four-oh-four`;
|
||||
|
||||
return this.remote
|
||||
.then(openPage(url, selectors['404'].HEADER))
|
||||
.then(click(selectors['404'].LINK_HOME, selectors.ENTER_EMAIL.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,32 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const { clearBrowserState, click, openPage } = require('./lib/helpers');
|
||||
|
||||
const url = intern._config.fxaContentRoot + 'boom';
|
||||
|
||||
registerSuite('500', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState({ forceAll: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'visit an invalid page': function () {
|
||||
const expected = intern._config.fxaProduction
|
||||
? selectors['404'].HEADER
|
||||
: selectors['500'].HEADER;
|
||||
|
||||
const button = intern._config.fxaProduction
|
||||
? selectors['404'].LINK_HOME
|
||||
: selectors['500'].LINK_HOME;
|
||||
|
||||
return this.remote
|
||||
.then(openPage(url, expected))
|
||||
.then(click(button, selectors.ENTER_EMAIL.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,189 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const assert = intern.getPlugin('chai').assert;
|
||||
const path = require('path');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
const SETTINGS_URL = config.fxaContentRoot + 'settings';
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot + '?action=email';
|
||||
const UPLOAD_IMAGE_PATH = path.join(
|
||||
process.cwd(),
|
||||
'app',
|
||||
'apple-touch-icon-152x152.png'
|
||||
);
|
||||
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
getWebChannelMessageData,
|
||||
openPage,
|
||||
storeWebChannelMessageData,
|
||||
testElementExists,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('settings/avatar', {
|
||||
// In order to test creating an avatar from a webcam on a headless test
|
||||
// machine, we set the 'media.navigator.streams.fake' browser pref, which
|
||||
// instructs the browser to return a fake stream from getUserMedia requests.
|
||||
// It turns out browser profile changes aren't reset between test runs, so
|
||||
// we just need to flip the pref once, and reset it when we're done. There's
|
||||
// probably a clever way to do this in a config file, but here we simply use
|
||||
// browser automation to load about:config and change the values directly.
|
||||
before: function () {
|
||||
return this.remote
|
||||
.then(openPage('about:config'))
|
||||
.then(click('#warningButton'))
|
||||
.then(type('#about-config-search', 'media.navigator.streams.fake'))
|
||||
.then(click('.button-toggle'));
|
||||
},
|
||||
|
||||
after: function () {
|
||||
return this.remote
|
||||
.then(openPage('about:config'))
|
||||
.then(click('#warningButton'))
|
||||
.then(type('#about-config-search', 'media.navigator.streams.fake'))
|
||||
.then(click('.button-reset'));
|
||||
},
|
||||
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState({ force: true }))
|
||||
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'attempt to use webcam for avatar': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(SETTINGS_URL, selectors.SETTINGS.HEADER))
|
||||
// go to change avatar
|
||||
.then(click(selectors.SETTINGS_AVATAR.MENU_BUTTON))
|
||||
.then(storeWebChannelMessageData('profile:change'))
|
||||
// click button, look for the loading spinner
|
||||
.then(click(selectors.SETTINGS_AVATAR.BUTTON_CAMERA))
|
||||
.then(click(selectors.SETTINGS_AVATAR.BUTTON_CAPTURING))
|
||||
.then(click(selectors.SETTINGS_AVATAR.SUBMIT))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
//success is seeing the image loaded
|
||||
.then(testElementExists(selectors.SETTINGS_AVATAR.NON_DEFAULT_IMAGE))
|
||||
// Replacement for testIsBrowserNotified
|
||||
.then(getWebChannelMessageData('profile:change'))
|
||||
.then((msg) => {
|
||||
assert.equal(msg.command, 'profile:change');
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
'attempt to use webcam for avatar, then cancel': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(SETTINGS_URL, selectors.SETTINGS.HEADER))
|
||||
|
||||
// go to change avatar
|
||||
.then(click(selectors.SETTINGS_AVATAR.MENU_BUTTON))
|
||||
.then(click(selectors.SETTINGS_AVATAR.BUTTON_CAMERA))
|
||||
// look for the button shown when the webcam capture has begun
|
||||
.then(testElementExists(selectors.SETTINGS_AVATAR.BUTTON_CAPTURING))
|
||||
.then(click(selectors.SETTINGS_AVATAR.BACK))
|
||||
|
||||
// success is returning to the settings page
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'upload and then remove profile image': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(SETTINGS_URL, selectors.SETTINGS.HEADER))
|
||||
.then(click(selectors.SETTINGS_AVATAR.MENU_BUTTON))
|
||||
.then(storeWebChannelMessageData('profile:change'))
|
||||
|
||||
// Selenium's way of interacting with a file picker
|
||||
.findByCssSelector(selectors.SETTINGS_AVATAR.UPLOAD_FILENAME_INPUT)
|
||||
.type(UPLOAD_IMAGE_PATH)
|
||||
.end()
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS_AVATAR.BUTTON_ROTATE))
|
||||
|
||||
.then(click(selectors.SETTINGS_AVATAR.BUTTON_ZOOM_OUT))
|
||||
.then(click(selectors.SETTINGS_AVATAR.BUTTON_ZOOM_IN))
|
||||
.then(click(selectors.SETTINGS_AVATAR.BUTTON_ROTATE))
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS_AVATAR.SUBMIT,
|
||||
selectors.SETTINGS_AVATAR.NON_DEFAULT_IMAGE
|
||||
)
|
||||
)
|
||||
|
||||
//success is seeing the image loaded and navigated to settings
|
||||
.then(testElementExists(selectors.SETTINGS_AVATAR.NON_DEFAULT_IMAGE))
|
||||
.then(visibleByQSA(selectors.SETTINGS.HEADER))
|
||||
// Replacement for testIsBrowserNotified
|
||||
.then(getWebChannelMessageData('profile:change'))
|
||||
.then((msg) => {
|
||||
assert.equal(msg.command, 'profile:change');
|
||||
})
|
||||
|
||||
// Remove the uploaded image
|
||||
.then(click(selectors.SETTINGS_AVATAR.MENU_BUTTON))
|
||||
.then(click(selectors.SETTINGS_AVATAR.REMOVE_BUTTON))
|
||||
|
||||
// Success is navigating to settings and seeing no image
|
||||
.then(visibleByQSA(selectors.SETTINGS.HEADER))
|
||||
.then(testElementExists(selectors.SETTINGS_AVATAR.NON_DEFAULT_IMAGE))
|
||||
);
|
||||
},
|
||||
|
||||
'cancel uploading a profile image': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(SETTINGS_URL, selectors.SETTINGS.HEADER))
|
||||
.then(click(selectors.SETTINGS_AVATAR.MENU_BUTTON))
|
||||
|
||||
// Selenium's way of interacting with a file picker
|
||||
.findByCssSelector(selectors.SETTINGS_AVATAR.UPLOAD_FILENAME_INPUT)
|
||||
.type(UPLOAD_IMAGE_PATH)
|
||||
.end()
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS_AVATAR.BUTTON_ROTATE))
|
||||
|
||||
.then(click(selectors.SETTINGS_AVATAR.BACK))
|
||||
|
||||
// success is returning to the settings page
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'redirects from /settings/avatar/change to /settings/avatar': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(SETTINGS_URL + '/avatar/change'))
|
||||
|
||||
//success is being redirected to /avatar and seeing the page load
|
||||
.then(testElementExists(selectors.SETTINGS_AVATAR.BUTTON_CAMERA))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,38 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const { assert } = intern.getPlugin('chai');
|
||||
const { openPage, clearBrowserState } = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
var FROM_URL = 'http://example.com/';
|
||||
var ENTER_EMAIL_URL = intern._config.fxaContentRoot;
|
||||
|
||||
registerSuite('back button after navigating to the root', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState({ forceAll: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'start at github, visit Fxa root, click `back` - should go back to example': function () {
|
||||
return (
|
||||
this.remote
|
||||
.get(FROM_URL)
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
// click back.
|
||||
.goBack()
|
||||
|
||||
.getCurrentUrl()
|
||||
.then(function (resultUrl) {
|
||||
assert.equal(resultUrl, FROM_URL);
|
||||
})
|
||||
.end()
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,173 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const uaStrings = require('./lib/ua-strings');
|
||||
let bouncedEmail;
|
||||
let deliveredEmail;
|
||||
const PASSWORD = 'password12345678';
|
||||
const ENTER_EMAIL_URL = `${
|
||||
intern._config.fxaContentRoot
|
||||
}?context=fx_desktop_v3&service=sync&forceUA=${encodeURIComponent(
|
||||
uaStrings.desktop_firefox_58
|
||||
)}`; //eslint-disable-line max-len
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
closeCurrentWindow,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
getFxaClient,
|
||||
openPage,
|
||||
pollUntil,
|
||||
respondToWebChannelMessage,
|
||||
switchToWindow,
|
||||
testElementExists,
|
||||
testElementValueEquals,
|
||||
testIsBrowserNotified,
|
||||
thenify,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('signup with an email that bounces', {
|
||||
beforeEach: function () {
|
||||
bouncedEmail = createEmail();
|
||||
deliveredEmail = createEmail();
|
||||
return (
|
||||
this.remote
|
||||
.then(clearBrowserState())
|
||||
// ensure a fresh signup page is loaded. If this suite is
|
||||
// run after a Sync suite, these tests try to use a Sync broker
|
||||
// which results in a channel timeout.
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'sign up, bounce email at /choose_what_to_sync, allow user to restart flow but force a different email': function () {
|
||||
const client = getFxaClient();
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(fillOutEmailFirstSignUp(bouncedEmail, PASSWORD))
|
||||
.then(testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.HEADER))
|
||||
|
||||
.then(() => client.accountDestroy(bouncedEmail, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
// The first can_link_account handler is removed, hook up another.
|
||||
.then(
|
||||
respondToWebChannelMessage('fxaccounts:can_link_account', {
|
||||
ok: true,
|
||||
})
|
||||
)
|
||||
// expect an error message to already be present on redirect
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP_BOUNCED_EMAIL))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, bouncedEmail))
|
||||
// user must change the email address
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT))
|
||||
// error message should still be around
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP_BOUNCED_EMAIL))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, deliveredEmail))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNUP_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
// password is remembered
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.SUBMIT,
|
||||
selectors.CHOOSE_WHAT_TO_SYNC.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.CHOOSE_WHAT_TO_SYNC.SUBMIT,
|
||||
selectors.CONFIRM_SIGNUP_CODE.HEADER
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const setUpBouncedSignIn = thenify(function (email) {
|
||||
const client = getFxaClient();
|
||||
email = email || createEmail('sync{id}');
|
||||
|
||||
return this.parent
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
.then(() => client.accountDestroy(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SIGNIN_BOUNCED.HEADER))
|
||||
.then(testElementExists(selectors.SIGNIN_BOUNCED.CREATE_ACCOUNT))
|
||||
.then(testElementExists(selectors.SIGNIN_BOUNCED.BACK))
|
||||
.then(testElementExists(selectors.SIGNIN_BOUNCED.SUPPORT));
|
||||
});
|
||||
|
||||
registerSuite('signin with an email that bounces', {
|
||||
tests: {
|
||||
'click create-account': function () {
|
||||
return this.remote
|
||||
.then(setUpBouncedSignIn())
|
||||
.then(click(selectors.SIGNIN_BOUNCED.CREATE_ACCOUNT))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, ''));
|
||||
},
|
||||
|
||||
'click back': function () {
|
||||
const email = createEmail('sync{id}');
|
||||
return this.remote
|
||||
.then(setUpBouncedSignIn(email))
|
||||
.then(click(selectors.SIGNIN_BOUNCED.BACK))
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email))
|
||||
.then(
|
||||
testElementValueEquals(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD)
|
||||
);
|
||||
},
|
||||
|
||||
'click support': function () {
|
||||
return this.remote
|
||||
.then(setUpBouncedSignIn())
|
||||
.then(click(selectors.SIGNIN_BOUNCED.SUPPORT))
|
||||
.then(switchToWindow(1))
|
||||
.then(
|
||||
pollUntil(() =>
|
||||
window.location.href.startsWith('https://support.mozilla.org/')
|
||||
)
|
||||
)
|
||||
.then(closeCurrentWindow());
|
||||
},
|
||||
|
||||
refresh: function () {
|
||||
return this.remote
|
||||
.then(setUpBouncedSignIn())
|
||||
.refresh()
|
||||
.then(
|
||||
respondToWebChannelMessage('fxaccounts:fxa_status', {
|
||||
capabilities: null,
|
||||
signedInUser: null,
|
||||
})
|
||||
)
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,65 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const CONFIRM_URL = config.fxaContentRoot + 'confirm';
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const PASSWORD = 'password12345678';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
fillOutEmailFirstSignUp,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testSuccessWasShown,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('confirm', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'visit confirmation screen without initiating sign up, user is redirected to /signup': function () {
|
||||
return (
|
||||
this.remote
|
||||
// user is immediately redirected to / if they have no sessionToken.
|
||||
.then(openPage(CONFIRM_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'sign up, wait for confirmation screen, click resend': function () {
|
||||
const email = 'test_signin' + Math.random() + '@restmail.net';
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.CONFIRM_SIGNUP_CODE.EMAIL_FIELD,
|
||||
email
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.CONFIRM_SIGNUP_CODE.LINK_RESEND))
|
||||
|
||||
// the test below depends on the speed of the email resent XHR
|
||||
// we have to wait until the resent request completes and the
|
||||
// success notification is visible
|
||||
.then(testSuccessWasShown(null, '.success'))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,63 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const UA_STRINGS = require('./lib/ua-strings');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const CONNECT_ANOTHER_DEVICE_URL = `${config.fxaContentRoot}connect_another_device`;
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?context=fx_desktop_v3&service=sync&action=email`;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
fillOutEmailFirstSignUp,
|
||||
noSuchElement,
|
||||
openPage,
|
||||
testElementExists,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
let email;
|
||||
const PASSWORD = 'password12345678';
|
||||
|
||||
registerSuite('connect_another_device', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'signup Fx Desktop, load /connect_another_device page': function () {
|
||||
// should have both links to mobile apps
|
||||
const forceUA = UA_STRINGS['desktop_firefox'];
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: { forceUA },
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.HEADER))
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
CONNECT_ANOTHER_DEVICE_URL,
|
||||
selectors.CONNECT_ANOTHER_DEVICE.HEADER
|
||||
)
|
||||
)
|
||||
.then(noSuchElement(selectors.CONNECT_ANOTHER_DEVICE.SIGNIN_BUTTON))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.CONNECT_ANOTHER_DEVICE.TEXT_INSTALL_FX_DESKTOP
|
||||
)
|
||||
)
|
||||
.then(noSuchElement(selectors.CONNECT_ANOTHER_DEVICE.SUCCESS));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,84 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testErrorWasShown,
|
||||
} = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
// there is no way to disable cookies using wd. Add `disable_cookies`
|
||||
// to the URL to synthesize cookies being disabled.
|
||||
var config = intern._config;
|
||||
var ENTER_EMAIL_COOKIES_DISABLED_URL =
|
||||
config.fxaContentRoot + '?disable_local_storage=1';
|
||||
var ENTER_EMAIL_COOKIES_ENABLED_URL = config.fxaContentRoot;
|
||||
|
||||
// Use fake, but real looking uid & code
|
||||
const VERIFY_COOKIES_DISABLED_URL =
|
||||
config.fxaContentRoot +
|
||||
'verify_email?disable_local_storage=1&uid=240103bbecd645848103021e7d245bcb&code=fc46f44802b2a2ce979f39b2187aa1c0';
|
||||
|
||||
const COOKIES_DISABLED_URL = config.fxaContentRoot + 'cookies_disabled';
|
||||
|
||||
registerSuite('cookies_disabled', {
|
||||
beforeEach() {
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'visit signup page with localStorage disabled': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(
|
||||
ENTER_EMAIL_COOKIES_DISABLED_URL,
|
||||
selectors.COOKIES_DISABLED.HEADER
|
||||
)
|
||||
)
|
||||
// try again, cookies are still disabled.
|
||||
.then(click(selectors.COOKIES_DISABLED.RETRY))
|
||||
|
||||
// show an error message after second try
|
||||
.then(testErrorWasShown(null, '.error'))
|
||||
);
|
||||
},
|
||||
|
||||
'synthesize enabling cookies by visiting the enter email page, then cookies_disabled, then clicking "try again"': function () {
|
||||
// wd has no way of disabling/enabling cookies, so we have to
|
||||
// manually seed history.
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(
|
||||
ENTER_EMAIL_COOKIES_ENABLED_URL,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
openPage(COOKIES_DISABLED_URL, selectors.COOKIES_DISABLED.HEADER)
|
||||
)
|
||||
|
||||
// try again, cookies are enabled.
|
||||
.then(click(selectors.COOKIES_DISABLED.RETRY))
|
||||
|
||||
// Should be redirected back to the signup page.
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'visit verify page with localStorage disabled': function () {
|
||||
return this.remote.then(
|
||||
openPage(VERIFY_COOKIES_DISABLED_URL, selectors.COOKIES_DISABLED.HEADER)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,91 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const EMAIL_FIRST_FORM_URL = intern._config.fxaContentRoot + '?action=email';
|
||||
|
||||
const INVALID_EMAIL = `nofxauser${Math.random()}@asdfafexample.xyz`;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
openPage,
|
||||
testElementTextInclude,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('email domain mx record validation', {
|
||||
beforeEach() {
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'no validation on a popular domain': function () {
|
||||
const email = `coolfxauser${Math.random()}@gmail.com`;
|
||||
|
||||
return this.remote
|
||||
.then(openPage(EMAIL_FIRST_FORM_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNUP_PASSWORD.HEADER)
|
||||
);
|
||||
},
|
||||
|
||||
'show validation error on invalid domain': function () {
|
||||
return this.remote
|
||||
.then(openPage(EMAIL_FIRST_FORM_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, INVALID_EMAIL))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.ENTER_EMAIL.TOOLTIP)
|
||||
)
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.ENTER_EMAIL.TOOLTIP,
|
||||
'Mistyped email? asdfafexample.xyz does not offer email.'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'show tooltip on domain with an A record': function () {
|
||||
const email = `coolfxauser${Math.random()}@mail.google.com`;
|
||||
|
||||
return this.remote
|
||||
.then(openPage(EMAIL_FIRST_FORM_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.ENTER_EMAIL.SUGGEST_EMAIL_DOMAIN_CORRECTION
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.ENTER_EMAIL.SUGGEST_EMAIL_DOMAIN_CORRECTION,
|
||||
'Mistyped email?'
|
||||
)
|
||||
)
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNUP_PASSWORD.HEADER)
|
||||
);
|
||||
},
|
||||
|
||||
'allow submission on domain with an MX record': function () {
|
||||
const email = `coolfxauser${Math.random()}@mozilla.com`;
|
||||
|
||||
return this.remote
|
||||
.then(openPage(EMAIL_FIRST_FORM_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNUP_PASSWORD.HEADER)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,65 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const PAGE_URL = intern._config.fxaContentRoot + '?action=email';
|
||||
|
||||
let email;
|
||||
const PASSWORD = '12345678';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
openPage,
|
||||
testAttribute,
|
||||
testAttributeEquals,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
// okay, not remote so run these for real.
|
||||
registerSuite('communication preferences', {
|
||||
beforeEach: function () {
|
||||
// The plus sign is to ensure the email address is URI-encoded when
|
||||
// passed to basket. See a43061d3
|
||||
email = createEmail('signup{id}+extra');
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'manage link': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// The manage link is not clicked because basket is not
|
||||
// hooked up to latest, and the teamcity test runner
|
||||
// gets redirected to a random allizom.org page.
|
||||
// Check the link is formed as we expect it to be.
|
||||
.then(
|
||||
testAttribute(
|
||||
selectors.SETTINGS_COMMUNICATION.BUTTON_MANAGE,
|
||||
'href',
|
||||
'include',
|
||||
`email=${encodeURIComponent(email)}`
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testAttributeEquals(
|
||||
selectors.SETTINGS_COMMUNICATION.BUTTON_MANAGE,
|
||||
'target',
|
||||
'_blank'
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,113 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutForceAuth,
|
||||
openForceAuth,
|
||||
signOut,
|
||||
testElementDisabled,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testElementValueEquals,
|
||||
type,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const PASSWORD = 'passwordcxzv';
|
||||
let email;
|
||||
|
||||
registerSuite('force_auth', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
tests: {
|
||||
'with a registered email, registered uid': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(function (accountInfo) {
|
||||
return openForceAuth({
|
||||
query: {
|
||||
email: email,
|
||||
uid: accountInfo.uid,
|
||||
},
|
||||
}).call(this);
|
||||
})
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'forgot password flow via force_auth': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openForceAuth({ query: { email: email } }))
|
||||
|
||||
.then(click(selectors.FORCE_AUTH.LINK_RESET_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD.HEADER))
|
||||
.then(testElementValueEquals(selectors.FORCE_AUTH.EMAIL, email))
|
||||
.then(testElementDisabled(selectors.FORCE_AUTH.EMAIL))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.FORCE_AUTH.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
// User thinks they have remembered their password, clicks the
|
||||
// "sign in" link. Go back to /force_auth.
|
||||
.then(click(selectors.RESET_PASSWORD.LINK_SIGNIN))
|
||||
|
||||
.then(testElementExists(selectors.FORCE_AUTH.HEADER))
|
||||
// User goes back to reset password to submit.
|
||||
.then(click(selectors.FORCE_AUTH.LINK_RESET_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD.HEADER))
|
||||
.then(click(selectors.RESET_PASSWORD.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
// User has remembered their password, for real this time.
|
||||
// Go back to /force_auth.
|
||||
.then(click(selectors.CONFIRM_RESET_PASSWORD.LINK_SIGNIN))
|
||||
|
||||
.then(testElementExists(selectors.FORCE_AUTH.HEADER))
|
||||
.then(testElementValueEquals(selectors.FORCE_AUTH.EMAIL, email))
|
||||
.then(testElementDisabled(selectors.FORCE_AUTH.EMAIL))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.FORCE_AUTH.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'form prefill information is cleared after sign in->sign out': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openForceAuth({ query: { email: email } }))
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(signOut())
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNIN_PASSWORD.HEADER)
|
||||
)
|
||||
|
||||
.then(testElementValueEquals(selectors.SIGNIN_PASSWORD.PASSWORD, ''));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,262 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { assert } = intern.getPlugin('chai');
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const uaStrings = require('./lib/ua-strings');
|
||||
|
||||
const config = intern._config;
|
||||
const URL_PARAMS = 'context=fx_desktop_v3&action=email';
|
||||
const EMAIL_FIRST_URL = `${config.fxaContentRoot}?${URL_PARAMS}`;
|
||||
const FIREFOX_CLIENT_ID = '5882386c6d801776';
|
||||
const CAPABILITIES = {
|
||||
multiService: true,
|
||||
pairing: false,
|
||||
engines: ['history'],
|
||||
};
|
||||
|
||||
let email;
|
||||
const PASSWORD = 'passwordvx2';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testIsBrowserNotified,
|
||||
type,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('Firefox Desktop non-sync', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'signup with no service - sync': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.SYNC_DESCRIPTION, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
clientId: FIREFOX_CLIENT_ID,
|
||||
capabilities: CAPABILITIES,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
.then(click(selectors.CHOOSE_WHAT_TO_SYNC.SUBMIT))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
// verify the account
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
);
|
||||
},
|
||||
'signin with no service - do not sync': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.SYNC_DESCRIPTION, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
clientId: FIREFOX_CLIENT_ID,
|
||||
capabilities: CAPABILITIES,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNIN_PASSWORD.HEADER)
|
||||
)
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.WOULD_YOU_LIKE_SYNC.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.WOULD_YOU_LIKE_SYNC.DO_NOT_SYNC,
|
||||
selectors.CONNECT_ANOTHER_DEVICE.HEADER
|
||||
)
|
||||
)
|
||||
.then(testIsBrowserNotified('fxaccounts:login'));
|
||||
},
|
||||
'signin with no service - sync': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.SYNC_DESCRIPTION, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
clientId: FIREFOX_CLIENT_ID,
|
||||
capabilities: CAPABILITIES,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNIN_PASSWORD.HEADER)
|
||||
)
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.WOULD_YOU_LIKE_SYNC.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.WOULD_YOU_LIKE_SYNC.SUBMIT,
|
||||
selectors.CONNECT_ANOTHER_DEVICE.HEADER
|
||||
)
|
||||
)
|
||||
.then(testIsBrowserNotified('fxaccounts:login'));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('Firefox Desktop non-sync - CWTS on signup', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('signuppasswordcwts.{id}');
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'signup with no service - do not sync': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.SYNC_DESCRIPTION, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': { ok: true },
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
clientId: FIREFOX_CLIENT_ID,
|
||||
capabilities: CAPABILITIES,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.VPASSWORD, PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.AGE, 21))
|
||||
// deselect all the sync engines
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_ADDONS))
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_BOOKMARKS))
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_HISTORY))
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_PASSWORDS))
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_PREFS))
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_TABS))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.SUBMIT,
|
||||
selectors.CONFIRM_SIGNUP_CODE.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(
|
||||
testIsBrowserNotified('fxaccounts:login', (event) => {
|
||||
assert.deepEqual(event.data.services, {});
|
||||
})
|
||||
)
|
||||
);
|
||||
},
|
||||
'signup with no service - sync': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.SYNC_DESCRIPTION, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': { ok: true },
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
clientId: FIREFOX_CLIENT_ID,
|
||||
capabilities: CAPABILITIES,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.VPASSWORD, PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.AGE, 21))
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_BOOKMARKS))
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_HISTORY))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.SUBMIT,
|
||||
selectors.CONFIRM_SIGNUP_CODE.HEADER
|
||||
)
|
||||
)
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(
|
||||
testIsBrowserNotified('fxaccounts:login', (event) => {
|
||||
assert.deepEqual(event.data.services, {
|
||||
sync: {
|
||||
declinedEngines: ['bookmarks', 'history'],
|
||||
offeredEngines: [
|
||||
'bookmarks',
|
||||
'history',
|
||||
'passwords',
|
||||
'addons',
|
||||
'tabs',
|
||||
'prefs',
|
||||
],
|
||||
},
|
||||
});
|
||||
})
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,324 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const uaStrings = require('./lib/ua-strings');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const userAgent = uaStrings['desktop_firefox_58'];
|
||||
|
||||
const FORCE_AUTH_PAGE_URL = `${
|
||||
config.fxaContentRoot
|
||||
}force_auth?forceUA=${encodeURIComponent(userAgent)}`;
|
||||
const SYNC_FORCE_AUTH_PAGE_URL = `${FORCE_AUTH_PAGE_URL}&service=sync`;
|
||||
|
||||
const ENTER_EMAIL_PAGE_URL = `${
|
||||
config.fxaContentRoot
|
||||
}?forceUA=${encodeURIComponent(userAgent)}`;
|
||||
const SYNC_ENTER_EMAIL_PAGE_URL = `${ENTER_EMAIL_PAGE_URL}&service=sync`;
|
||||
|
||||
const SETTINGS_PAGE_URL = `${
|
||||
config.fxaContentRoot
|
||||
}settings?forceUA=${encodeURIComponent(userAgent)}`;
|
||||
|
||||
var browserSignedInEmail;
|
||||
let browserSignedInAccount;
|
||||
|
||||
let otherEmail;
|
||||
let otherAccount;
|
||||
|
||||
const PASSWORD = '12345678';
|
||||
|
||||
const {
|
||||
click,
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextEquals,
|
||||
testElementValueEquals,
|
||||
thenify,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const ensureUsers = thenify(function () {
|
||||
return this.parent
|
||||
.then(() => {
|
||||
if (!browserSignedInAccount) {
|
||||
browserSignedInEmail = createEmail();
|
||||
return this.parent
|
||||
.then(
|
||||
createUser(browserSignedInEmail, PASSWORD, { preVerified: true })
|
||||
)
|
||||
.then((_browserSignedInAccount) => {
|
||||
browserSignedInAccount = _browserSignedInAccount;
|
||||
browserSignedInAccount.email = browserSignedInEmail;
|
||||
browserSignedInAccount.verified = true;
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (!otherAccount) {
|
||||
otherEmail = createEmail();
|
||||
return this.parent
|
||||
.then(createUser(otherEmail, PASSWORD, { preVerified: true }))
|
||||
.then((_otherAccount) => {
|
||||
otherAccount = _otherAccount;
|
||||
otherAccount.email = otherEmail;
|
||||
otherAccount.verified = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
registerSuite('Firefox desktop user info handshake', {
|
||||
beforeEach: function () {
|
||||
return this.remote
|
||||
.then(clearBrowserState({ forceAll: true }))
|
||||
.then(ensureUsers());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'Sync - user signed into browser, no user signed in locally': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(
|
||||
SYNC_ENTER_EMAIL_PAGE_URL,
|
||||
selectors.SIGNIN_PASSWORD.HEADER,
|
||||
{
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: browserSignedInAccount,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementValueEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL,
|
||||
browserSignedInEmail
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'Non-Sync - user signed into browser, no user signed in locally': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_PAGE_URL, selectors.SIGNIN_PASSWORD.HEADER, {
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: browserSignedInAccount,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(
|
||||
testElementValueEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL,
|
||||
browserSignedInEmail
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
browserSignedInEmail
|
||||
)
|
||||
)
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'Non-Sync - user signed into browser, user signed in locally': function () {
|
||||
return (
|
||||
this.remote
|
||||
// First, sign in the user to populate localStorage
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_PAGE_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(otherEmail, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
// Then, sign in the user again, synthesizing the user having signed
|
||||
// into Sync after the initial sign in.
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_PAGE_URL, selectors.SIGNIN_PASSWORD.HEADER, {
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: browserSignedInAccount,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
// browser's view of the world takes precedence, it signed in last
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
browserSignedInEmail
|
||||
)
|
||||
)
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'Sync - no user signed into browser, no user signed in locally': function () {
|
||||
return this.remote
|
||||
.then(openPage(SYNC_ENTER_EMAIL_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, ''));
|
||||
},
|
||||
|
||||
'Sync - no user signed into browser, user signed in locally': function () {
|
||||
return (
|
||||
this.remote
|
||||
// First, sign in the user to populate localStorage
|
||||
.then(openPage(ENTER_EMAIL_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(otherEmail, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
SYNC_ENTER_EMAIL_PAGE_URL,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, otherEmail)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'Non-Sync - no user signed into browser, no user signed in locally': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_PAGE_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, ''));
|
||||
},
|
||||
|
||||
'Sync force_auth page - user signed into browser is different to requested user': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(
|
||||
`${SYNC_FORCE_AUTH_PAGE_URL}&email=${encodeURIComponent(
|
||||
otherEmail
|
||||
)}`,
|
||||
selectors.FORCE_AUTH.HEADER,
|
||||
{
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: browserSignedInAccount,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
.then(testElementValueEquals(selectors.FORCE_AUTH.EMAIL, otherEmail));
|
||||
},
|
||||
|
||||
'Non-Sync force_auth page - user signed into browser is different to requested user': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(
|
||||
`${FORCE_AUTH_PAGE_URL}&email=${encodeURIComponent(otherEmail)}`,
|
||||
selectors.FORCE_AUTH.HEADER,
|
||||
{
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: browserSignedInAccount,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
.then(testElementValueEquals(selectors.FORCE_AUTH.EMAIL, otherEmail));
|
||||
},
|
||||
|
||||
// TODO: These tests are dependent on the changes in #8244
|
||||
//
|
||||
/*
|
||||
'Sync settings page - user signed into browser': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(SYNC_SETTINGS_PAGE_URL, selectors.SETTINGS.HEADER, {
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: browserSignedInAccount,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SETTINGS.PROFILE_HEADER,
|
||||
browserSignedInEmail
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'Non-Sync settings page - user signed into browser': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(SETTINGS_PAGE_URL, selectors.SETTINGS.HEADER, {
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: browserSignedInAccount,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SETTINGS.PROFILE_HEADER,
|
||||
browserSignedInEmail
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'Sync settings page - no user signed into browser': function () {
|
||||
return this.remote.then(
|
||||
openPage(SYNC_SETTINGS_PAGE_URL, selectors.ENTER_EMAIL.HEADER)
|
||||
);
|
||||
},
|
||||
|
||||
'Non-Sync settings page - no user signed into browser, no user signed in locally': function () {
|
||||
return this.remote.then(
|
||||
openPage(SETTINGS_PAGE_URL, selectors.ENTER_EMAIL.HEADER)
|
||||
);
|
||||
},
|
||||
*/
|
||||
|
||||
'Non-Sync settings page - no user signed into browser, user signed in locally': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(otherEmail, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(openPage(SETTINGS_PAGE_URL, selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
testElementTextEquals(selectors.SETTINGS.PROFILE_HEADER, otherEmail)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,70 +0,0 @@
|
|||
/* eslint-disable camelcase */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const FORCE_AUTH_PAGE_URL = `${config.fxaContentRoot}force_auth?context=fx_firstrun_v2&service=sync`;
|
||||
const SIGNIN_PAGE_URL = `${config.fxaContentRoot}signin?context=fx_firstrun_v2&service=sync`;
|
||||
const SIGNUP_PAGE_URL = `${config.fxaContentRoot}signin?context=fx_firstrun_v2&service=sync`;
|
||||
const RESET_PASSWORD_PAGE_URL = `${config.fxaContentRoot}reset_password?context=fx_firstrun_v2&service=sync`;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
openPage,
|
||||
testElementExists,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('Firefox Desktop first-run v2', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
afterEach: function () {
|
||||
return this.remote.execute(() => {
|
||||
// Opening about:blank aborts the Firefox download
|
||||
// and prevents the tests from stalling when run on CentOS
|
||||
window.location.href = 'about:blank';
|
||||
});
|
||||
},
|
||||
|
||||
tests: {
|
||||
force_auth: function () {
|
||||
return this.remote
|
||||
.then(openPage(FORCE_AUTH_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER))
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
signin: function () {
|
||||
return this.remote
|
||||
.then(openPage(SIGNIN_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER))
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
signup: function () {
|
||||
return this.remote
|
||||
.then(openPage(SIGNUP_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER))
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
reset_password: function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(RESET_PASSWORD_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER)
|
||||
)
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,174 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const FxDesktopHelpers = require('./lib/fx-desktop');
|
||||
const selectors = require('./lib/selectors');
|
||||
const UA_STRINGS = require('./lib/ua-strings');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?context=fx_ios_v1&service=sync`;
|
||||
const SIGNIN_URL = `${config.fxaContentRoot}signin?context=fx_ios_v1&service=sync`;
|
||||
|
||||
let email;
|
||||
const PASSWORD = '12345678';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutSignInTokenCode,
|
||||
fillOutSignInUnblock,
|
||||
noPageTransition,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testElementValueEquals,
|
||||
thenify,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const {
|
||||
listenForFxaCommands,
|
||||
testIsBrowserNotifiedOfMessage: testIsBrowserNotified,
|
||||
testIsBrowserNotifiedOfLogin,
|
||||
} = FxDesktopHelpers;
|
||||
|
||||
const setupTest = thenify(function (options = {}) {
|
||||
const successSelector = options.blocked
|
||||
? selectors.SIGNIN_UNBLOCK.HEADER
|
||||
: options.preVerified
|
||||
? selectors.SIGNIN_TOKEN_CODE.HEADER
|
||||
: selectors.CONFIRM_SIGNUP_CODE.HEADER;
|
||||
|
||||
return this.parent
|
||||
.then(createUser(email, PASSWORD, { preVerified: options.preVerified }))
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: options.query,
|
||||
})
|
||||
)
|
||||
.execute(listenForFxaCommands)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(successSelector))
|
||||
.then(testIsBrowserNotified('can_link_account'));
|
||||
});
|
||||
|
||||
registerSuite('FxiOS v1 signin', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'open directly to /signin page': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
// redirected immediately to the / page
|
||||
.then(openPage(SIGNIN_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
verified: function () {
|
||||
const forceUA = UA_STRINGS['ios_firefox_6_1'];
|
||||
const query = { forceUA };
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, { query })
|
||||
)
|
||||
.execute(listenForFxaCommands)
|
||||
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.SYNC_DESCRIPTION))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
.then(testIsBrowserNotified('can_link_account'))
|
||||
|
||||
// user thinks they mistyped their email
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email))
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.SHOW_PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.SIGNIN_TOKEN_CODE.HEADER
|
||||
)
|
||||
)
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
.then(testIsBrowserNotifiedOfLogin(email, { expectVerified: false }))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_COMPLETE.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
unverified: function () {
|
||||
const forceUA = UA_STRINGS['ios_firefox_6_1'];
|
||||
const query = { forceUA };
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest({ preVerified: false, query }))
|
||||
|
||||
// email 0 - initial sign up email
|
||||
// email 1 - sign in w/ unverified address email
|
||||
// email 2 - "You have verified your Firefox Account"
|
||||
.then(fillOutSignInTokenCode(email, 1, { query }))
|
||||
|
||||
// In Fx for iOS >= 6.1, user should redirect to the signup-complete
|
||||
// page after verification.
|
||||
.then(testElementExists(selectors.SIGNUP_COMPLETE.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'blocked, valid code entered': function () {
|
||||
email = createEmail('block{id}');
|
||||
const forceUA = UA_STRINGS['ios_firefox_6_1'];
|
||||
const query = { forceUA };
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest({ blocked: true, preVerified: true, query }))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNIN_UNBLOCK.EMAIL_FIELD, email)
|
||||
)
|
||||
.then(fillOutSignInUnblock(email, 0))
|
||||
|
||||
// about:accounts will take over post-unblock, no transition
|
||||
.then(noPageTransition(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(testIsBrowserNotifiedOfLogin(email, { expectVerified: true }))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,86 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const FxDesktopHelpers = require('./lib/fx-desktop');
|
||||
const UA_STRINGS = require('./lib/ua-strings');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?context=fx_ios_v1&service=sync`;
|
||||
const SIGNUP_URL = `${config.fxaContentRoot}signup?context=fx_ios_v1&service=sync`;
|
||||
|
||||
let email;
|
||||
const PASSWORD = 'password12345678';
|
||||
|
||||
const {
|
||||
click,
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testEmailExpected,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const { listenForFxaCommands, testIsBrowserNotifiedOfLogin } = FxDesktopHelpers;
|
||||
|
||||
registerSuite('FxiOS v1 sign_up', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'open directly to /signup page': function () {
|
||||
return (
|
||||
this.remote
|
||||
// redirected immediately to the / page
|
||||
.then(openPage(SIGNUP_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'sign up + CWTS, verify same browser': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceUA: UA_STRINGS['ios_firefox_11_0'],
|
||||
},
|
||||
})
|
||||
)
|
||||
.execute(listenForFxaCommands)
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
// In Fx for iOS >= 11.0, user should be transitioned to the
|
||||
// choose what to Sync page
|
||||
.then(testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.HEADER))
|
||||
|
||||
// uncheck the passwords and history engines
|
||||
.then(click(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_PASSWORDS))
|
||||
.then(click(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_HISTORY))
|
||||
.then(click(selectors.CHOOSE_WHAT_TO_SYNC.SUBMIT))
|
||||
|
||||
// user should be transitioned to the "go confirm your address" page
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
// the login message is only sent after the sync preferences screen
|
||||
// has been cleared.
|
||||
.then(testIsBrowserNotifiedOfLogin(email))
|
||||
|
||||
// verify the user
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.SIGNUP_COMPLETE.HEADER))
|
||||
// A post-verification email should be sent, this is Sync.
|
||||
.then(testEmailExpected(email, 1))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,71 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const assert = intern.getPlugin('chai').assert;
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
var url = intern._config.fxaContentRoot + 'legal';
|
||||
|
||||
var openPage = FunctionalHelpers.openPage;
|
||||
|
||||
registerSuite('legal', {
|
||||
'start at legal page': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(url, '#fxa-legal-header'))
|
||||
|
||||
.findByCssSelector('a[href="/legal/terms"]')
|
||||
.click()
|
||||
.end()
|
||||
|
||||
// success is going to the TOS screen
|
||||
.findByCssSelector('#fxa-tos-back')
|
||||
.click()
|
||||
.end()
|
||||
|
||||
.findByCssSelector('a[href="/legal/privacy"]')
|
||||
.click()
|
||||
.end()
|
||||
|
||||
.findByCssSelector('#fxa-pp-back')
|
||||
.click()
|
||||
.end()
|
||||
|
||||
// success is going back to the legal screen.
|
||||
.findByCssSelector('#fxa-legal-header')
|
||||
.end()
|
||||
);
|
||||
},
|
||||
|
||||
'start at terms page': function () {
|
||||
return this.remote
|
||||
.then(openPage(url + '/terms', '#fxa-tos-header'))
|
||||
|
||||
.then(FunctionalHelpers.visibleByQSA('#legal-copy[data-shown]'))
|
||||
.findByCssSelector('#legal-copy[data-shown]')
|
||||
|
||||
.getVisibleText()
|
||||
.then(function (resultText) {
|
||||
// the legal text shouldn't be empty
|
||||
assert.ok(resultText.trim().length);
|
||||
})
|
||||
.end();
|
||||
},
|
||||
|
||||
'start at privacy page': function () {
|
||||
return this.remote
|
||||
.then(openPage(url + '/privacy', '#fxa-pp-header'))
|
||||
|
||||
.then(FunctionalHelpers.visibleByQSA('#legal-copy[data-shown]'))
|
||||
.findByCssSelector('#legal-copy[data-shown]')
|
||||
.getVisibleText()
|
||||
.then(function (resultText) {
|
||||
// the legal text shouldn't be empty
|
||||
assert.ok(resultText.trim().length);
|
||||
})
|
||||
.end();
|
||||
},
|
||||
});
|
|
@ -1,106 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
const assert = intern.getPlugin('chai').assert;
|
||||
|
||||
/**
|
||||
* Listens for FirefoxAccountsCommand events coming from FxA and
|
||||
* automatically responds so that no error messages are displayed
|
||||
* and the flows can complete.
|
||||
*
|
||||
* Run in the context of the web page.
|
||||
*/
|
||||
function listenForFxaCommands() {
|
||||
// postMessage back responses to the browser so that no error messages
|
||||
// are displayed and the flows can be completed. Mirrors how the browser
|
||||
// handles things in
|
||||
// http://mxr.mozilla.org/mozilla-central/source/browser/base/content/aboutaccounts/aboutaccounts.js#252
|
||||
function sendMessageToFxa(content) {
|
||||
window.postMessage(
|
||||
{
|
||||
content: content,
|
||||
type: 'message',
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
|
||||
// Add an event listener that auto responds to FirefoxAccountsCommands so
|
||||
// that flows can complete and no error messages are displayed.
|
||||
window.addEventListener('FirefoxAccountsCommand', function (e) {
|
||||
var command = e.detail.command;
|
||||
|
||||
// the firefox Selenium driver does not support querying
|
||||
// localStorage, and data appended to the URL is overwritten
|
||||
// when the router updates a route. Waiting for cookies to be
|
||||
// set is difficult, and selenium is great at searching for
|
||||
// DOM elements. Append an element every time a FirefoxAccountsCommand
|
||||
// is received that Selenium can look for to see if the message was
|
||||
// actually received.
|
||||
|
||||
var element = document.createElement('div');
|
||||
element.setAttribute('id', 'message-' + command);
|
||||
element.innerText = JSON.stringify(e.detail.data);
|
||||
document.body.appendChild(element);
|
||||
|
||||
var DOES_NOT_RESPOND = ['loaded', 'change_password', 'delete_account'];
|
||||
|
||||
if (DOES_NOT_RESPOND.indexOf(command) === -1) {
|
||||
sendMessageToFxa({
|
||||
status: command,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the browser has been notified of a CustomEvent login message.
|
||||
*
|
||||
* @param {string} email
|
||||
* @param {object} [options]
|
||||
* @param {boolean} [options.expectVerified] - expected user verification status.
|
||||
* Defaults to `false`
|
||||
* @returns {promise}
|
||||
*/
|
||||
function testIsBrowserNotifiedOfLogin(email, options) {
|
||||
return function () {
|
||||
options = options || {};
|
||||
|
||||
return this.parent
|
||||
.findByCssSelector('#message-login')
|
||||
.getProperty('innerText')
|
||||
.then((innerText) => {
|
||||
options = options || {};
|
||||
var data = JSON.parse(innerText);
|
||||
assert.equal(data.email, email);
|
||||
assert.ok(data.unwrapBKey);
|
||||
assert.ok(data.keyFetchToken);
|
||||
if (options.expectVerified) {
|
||||
assert.isTrue(data.verified);
|
||||
} else {
|
||||
assert.isFalse(data.verified);
|
||||
}
|
||||
})
|
||||
.end();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the browser has been notified of a CustomEvent message
|
||||
*
|
||||
* @param {string} message message to expect
|
||||
* @returns {promise} rejects if message has not been sent.
|
||||
*/
|
||||
function testIsBrowserNotifiedOfMessage(message) {
|
||||
return function () {
|
||||
return this.parent.findByCssSelector('#message-' + message).end();
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
listenForFxaCommands: listenForFxaCommands,
|
||||
testIsBrowserNotifiedOfLogin: testIsBrowserNotifiedOfLogin,
|
||||
testIsBrowserNotifiedOfMessage: testIsBrowserNotifiedOfMessage,
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,26 +0,0 @@
|
|||
/*eslint-disable max-len, camelcase */
|
||||
module.exports = {
|
||||
android_chrome:
|
||||
'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19',
|
||||
android_firefox:
|
||||
'Mozilla/5.0 (Android 4.4; Mobile; rv:43.0) Gecko/41.0 Firefox/43.0',
|
||||
desktop_chrome:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.59 Safari/537.36',
|
||||
desktop_firefox_58:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:58.0) Gecko/20100101 Firefox/58.0',
|
||||
desktop_firefox_71:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:71.0) Gecko/20100101 Firefox/71.0',
|
||||
ios_firefox:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4',
|
||||
ios_firefox_11_0:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/11.0 Mobile/12F69 Safari/600.1.4',
|
||||
ios_firefox_6_1:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/6.1 Mobile/12F69 Safari/600.1.4',
|
||||
ios_firefox_9:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/9.0 Mobile/12F69 Safari/600.1.4',
|
||||
ios_firefox_10:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/10.0 Mobile/12F69 Safari/600.1.4', // eslint-disable-line
|
||||
ios_safari:
|
||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3',
|
||||
};
|
||||
/*eslint-enable max-len*/
|
|
@ -1,74 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
var ERROR_COLOR = '\x1b[1;31m'; // red
|
||||
var DESCRIPTION_COLOR = '\x1b[1;36m'; // cyan
|
||||
var DEFAULT_COLOR = '\x1b[0;0m'; // off
|
||||
|
||||
function errorColor(text) {
|
||||
return ERROR_COLOR + text + DEFAULT_COLOR;
|
||||
}
|
||||
|
||||
function descriptionColor(text) {
|
||||
return DESCRIPTION_COLOR + text + DEFAULT_COLOR;
|
||||
}
|
||||
|
||||
var url = intern._config.fxaContentRoot + 'tests/index.html';
|
||||
var MOCHA_LOADER_SLEEP = 50;
|
||||
|
||||
registerSuite('mocha tests', {
|
||||
'run the mocha tests': function () {
|
||||
var self = this;
|
||||
// timeout after 300 seconds
|
||||
this.timeout = 300000;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.setFindTimeout(this.timeout)
|
||||
.get(url)
|
||||
.refresh()
|
||||
// let the mocha reporter load up
|
||||
.sleep(MOCHA_LOADER_SLEEP)
|
||||
|
||||
// wait for the tests to complete
|
||||
.findById('total-failures')
|
||||
.getVisibleText()
|
||||
.then(function (text) {
|
||||
if (text !== '0') {
|
||||
return (
|
||||
self.remote
|
||||
// print the errors to the console
|
||||
.findAllByCssSelector('.fail')
|
||||
.then(function (elements) {
|
||||
return Promise.all(
|
||||
elements.map(function (element) {
|
||||
return element
|
||||
.getVisibleText()
|
||||
.then(function (errorText) {
|
||||
var parts = errorText.split('‣');
|
||||
console.error(
|
||||
errorColor('Failed test: ' + parts[0].trim())
|
||||
);
|
||||
console.error(
|
||||
descriptionColor(' => ' + parts[1].trim())
|
||||
);
|
||||
});
|
||||
})
|
||||
);
|
||||
})
|
||||
.end()
|
||||
|
||||
.then(function () {
|
||||
throw new Error('Expected 0 mocha test failures');
|
||||
})
|
||||
);
|
||||
}
|
||||
})
|
||||
.end()
|
||||
);
|
||||
},
|
||||
});
|
|
@ -1,107 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
var config = intern._config;
|
||||
var OAUTH_APP = config.fxaOAuthApp;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutForceAuth,
|
||||
fillOutSignInUnblock,
|
||||
fillOutSignUpCode,
|
||||
openFxaFromRp,
|
||||
testElementDisabled,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testElementValueEquals,
|
||||
testUrlEquals,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const PASSWORD = 'password123456789';
|
||||
let email;
|
||||
|
||||
registerSuite('oauth force_auth', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return this.remote.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
tests: {
|
||||
'with a registered email': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openFxaFromRp('force-auth', { query: { email: email } }))
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
// redirected back to the App
|
||||
.then(testUrlEquals(OAUTH_APP))
|
||||
);
|
||||
},
|
||||
|
||||
'with an unregistered email': function () {
|
||||
// Test often times out waiting for emails, give it a bit more time.
|
||||
// See #5024
|
||||
this.timeout = 60 * 1000;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openFxaFromRp('force-auth', {
|
||||
header: selectors.SIGNUP_PASSWORD.HEADER,
|
||||
query: { email: email },
|
||||
})
|
||||
)
|
||||
.then(visibleByQSA(selectors.SIGNUP_PASSWORD.ERROR))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNUP_PASSWORD.ERROR, 'recreate')
|
||||
)
|
||||
// ensure the email is filled in, and not editible.
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.EMAIL, email))
|
||||
.then(testElementDisabled(selectors.SIGNUP_PASSWORD.EMAIL))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD, { enterEmail: false }))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
// redirected back to the App
|
||||
.then(testUrlEquals(OAUTH_APP))
|
||||
);
|
||||
},
|
||||
|
||||
'verified, blocked': function () {
|
||||
email = createEmail('blocked{id}');
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openFxaFromRp('force-auth', { query: { email: email } }))
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(fillOutSignInUnblock(email, 0))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
// redirected back to the App
|
||||
.then(testUrlEquals(OAUTH_APP))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,166 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const uaStrings = require('./lib/ua-strings');
|
||||
|
||||
const userAgent = uaStrings['desktop_firefox_58'];
|
||||
|
||||
var browserSignedInEmail;
|
||||
let browserSignedInAccount;
|
||||
|
||||
let otherEmail;
|
||||
let otherAccount;
|
||||
|
||||
const PASSWORD = '12345678';
|
||||
|
||||
const {
|
||||
click,
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
openFxaFromRp,
|
||||
testElementTextEquals,
|
||||
thenify,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const ensureUsers = thenify(function () {
|
||||
return this.parent
|
||||
.then(() => {
|
||||
if (!browserSignedInAccount) {
|
||||
browserSignedInEmail = createEmail();
|
||||
return this.parent
|
||||
.then(
|
||||
createUser(browserSignedInEmail, PASSWORD, { preVerified: true })
|
||||
)
|
||||
.then((_browserSignedInAccount) => {
|
||||
browserSignedInAccount = _browserSignedInAccount;
|
||||
browserSignedInAccount.email = browserSignedInEmail;
|
||||
browserSignedInAccount.verified = true;
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (!otherAccount) {
|
||||
otherEmail = createEmail();
|
||||
return this.parent
|
||||
.then(createUser(otherEmail, PASSWORD, { preVerified: true }))
|
||||
.then((_otherAccount) => {
|
||||
otherAccount = _otherAccount;
|
||||
otherAccount.email = otherEmail;
|
||||
otherAccount.verified = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
registerSuite('Firefox desktop user info handshake - OAuth flows', {
|
||||
beforeEach: function () {
|
||||
return this.remote
|
||||
.then(clearBrowserState({ forceAll: true }))
|
||||
.then(ensureUsers());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'OAuth signin page - user signed into browser, no user signed in locally': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
query: {
|
||||
forceUA: userAgent,
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: browserSignedInAccount,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
browserSignedInEmail
|
||||
)
|
||||
)
|
||||
// User can sign in with cached credentials, no password needed.
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors['123DONE'].AUTHENTICATED,
|
||||
browserSignedInEmail
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'OAuth signin page - user signed into browser, user signed in locally': function () {
|
||||
return (
|
||||
this.remote
|
||||
// First, sign in the user to populate localStorage
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
query: {
|
||||
forceUA: userAgent,
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(otherEmail, PASSWORD))
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
|
||||
// Wait for the signin button to be visible before
|
||||
// attempting to refresh the page. If the refresh is
|
||||
// done before signout has completed, 123done shows
|
||||
// an alert box which blocks the rest of the text.
|
||||
.then(visibleByQSA(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
|
||||
// Then, sign in the user again, synthesizing the user having signed
|
||||
// into Sync after the initial sign in.
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
query: {
|
||||
forceUA: userAgent,
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: browserSignedInAccount,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
// browser's view of the world takes precedence, it signed in last.
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
browserSignedInEmail
|
||||
)
|
||||
)
|
||||
// User can sign in with cached credentials, no password needed.
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors['123DONE'].AUTHENTICATED,
|
||||
browserSignedInEmail
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,503 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const assert = intern.getPlugin('chai').assert;
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const TIMEOUT = 90 * 1000;
|
||||
|
||||
const TRUSTED_OAUTH_APP = config.fxaOAuthApp;
|
||||
const UNTRUSTED_OAUTH_APP = config.fxaUntrustedOauthApp;
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?action=email`;
|
||||
|
||||
let email;
|
||||
|
||||
const {
|
||||
click,
|
||||
closeCurrentWindow,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutForceAuth,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignInTokenCode,
|
||||
fillOutSignUpCode,
|
||||
noSuchElement,
|
||||
openFxaFromRp: openFxaFromTrustedRp,
|
||||
openFxaFromUntrustedRp,
|
||||
openPage,
|
||||
openSettingsInNewTab,
|
||||
switchToWindow,
|
||||
testElementExists,
|
||||
testUrlEquals,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('oauth permissions for untrusted reliers', {
|
||||
beforeEach: function () {
|
||||
this.timeout = TIMEOUT;
|
||||
email = createEmail();
|
||||
|
||||
return this.remote.then(
|
||||
FunctionalHelpers.clearBrowserState({
|
||||
'321done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
tests: {
|
||||
'signin verified': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openFxaFromUntrustedRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(click(selectors.OAUTH_PERMISSIONS.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
.then(testUrlEquals(UNTRUSTED_OAUTH_APP));
|
||||
},
|
||||
|
||||
're-signin verified, no additional permissions': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openFxaFromUntrustedRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(
|
||||
click(
|
||||
selectors.OAUTH_PERMISSIONS.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
|
||||
.then(testUrlEquals(UNTRUSTED_OAUTH_APP))
|
||||
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
.then(click(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
|
||||
// user signed in previously and should not need to enter
|
||||
// either their email address or password
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
// no permissions additional asked for
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
// redirected back to the App without seeing the permissions screen.
|
||||
.then(testUrlEquals(UNTRUSTED_OAUTH_APP))
|
||||
);
|
||||
},
|
||||
|
||||
'signin unverified, acts like signup': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: false }))
|
||||
.then(openFxaFromUntrustedRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(
|
||||
click(
|
||||
selectors.OAUTH_PERMISSIONS.SUBMIT,
|
||||
selectors.CONFIRM_SIGNUP_CODE.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
// get the second email, the first was sent on client.signUp w/
|
||||
// preVerified: false above.
|
||||
.then(fillOutSignInTokenCode(email, 1))
|
||||
// user verifies in the same tab, so they are logged in to the RP.
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
|
||||
'signup, verify': function () {
|
||||
return this.remote
|
||||
.then(openFxaFromUntrustedRp('enter-email'))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.SUB_HEADER))
|
||||
.getCurrentUrl()
|
||||
.then(function (url) {
|
||||
assert.ok(url.indexOf('client_id=') > -1);
|
||||
assert.ok(url.indexOf('redirect_uri=') > -1);
|
||||
assert.ok(url.indexOf('state=') > -1);
|
||||
})
|
||||
.end()
|
||||
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(
|
||||
click(
|
||||
selectors.OAUTH_PERMISSIONS.SUBMIT,
|
||||
selectors.CONFIRM_SIGNUP_CODE.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED));
|
||||
},
|
||||
|
||||
'signup, then signin with no additional permissions': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromUntrustedRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(
|
||||
click(
|
||||
selectors.OAUTH_PERMISSIONS.SUBMIT,
|
||||
selectors.CONFIRM_SIGNUP_CODE.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
.then(click(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
|
||||
// user signed in previously and should not need to enter
|
||||
// either their email address or password
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
.then(testUrlEquals(UNTRUSTED_OAUTH_APP))
|
||||
);
|
||||
},
|
||||
|
||||
'signin with new permission available b/c of new account information': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openFxaFromUntrustedRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
// display name is not available because user has not set their name
|
||||
.then(
|
||||
noSuchElement(selectors.OAUTH_PERMISSIONS.CHECKBOX_DISPLAY_NAME)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.OAUTH_PERMISSIONS.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
|
||||
.then(testUrlEquals(UNTRUSTED_OAUTH_APP))
|
||||
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
|
||||
.then(openSettingsInNewTab())
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(click(selectors.SETTINGS_DISPLAY_NAME.MENU_BUTTON))
|
||||
.then(click(selectors.SETTINGS_DISPLAY_NAME.INPUT_LABEL_DISPLAY_NAME))
|
||||
.then(
|
||||
type(
|
||||
selectors.SETTINGS_DISPLAY_NAME.INPUT_DISPLAY_NAME,
|
||||
'test user'
|
||||
)
|
||||
)
|
||||
.then(click(selectors.SETTINGS_DISPLAY_NAME.SUBMIT))
|
||||
.then(visibleByQSA(selectors.SETTINGS.SUCCESS))
|
||||
|
||||
.then(closeCurrentWindow())
|
||||
|
||||
// user is already signed in, does not need to enter their password.
|
||||
.then(click(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
// display name is now available
|
||||
.then(
|
||||
testElementExists(selectors.OAUTH_PERMISSIONS.CHECKBOX_DISPLAY_NAME)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.OAUTH_PERMISSIONS.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'signin with additional requested permission': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// make display_name available from the start
|
||||
.then(click(selectors.SETTINGS_DISPLAY_NAME.MENU_BUTTON))
|
||||
.then(click(selectors.SETTINGS_DISPLAY_NAME.INPUT_LABEL_DISPLAY_NAME))
|
||||
.then(
|
||||
type(
|
||||
selectors.SETTINGS_DISPLAY_NAME.INPUT_DISPLAY_NAME,
|
||||
'test user'
|
||||
)
|
||||
)
|
||||
// user is already signed in, does not need to enter their password.
|
||||
.then(click(selectors.SETTINGS_DISPLAY_NAME.SUBMIT))
|
||||
.then(visibleByQSA(selectors.SETTINGS.SUCCESS))
|
||||
|
||||
// the first time through, only request email and uid
|
||||
.then(
|
||||
openFxaFromUntrustedRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
query: {
|
||||
scope: 'openid profile:email profile:uid',
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
// display name is not available because it's not requested
|
||||
.then(
|
||||
noSuchElement(selectors.OAUTH_PERMISSIONS.CHECKBOX_DISPLAY_NAME)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.OAUTH_PERMISSIONS.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
|
||||
.then(testUrlEquals(UNTRUSTED_OAUTH_APP))
|
||||
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
.then(click(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
// the second time through, profile:email, profile:uid, and
|
||||
// profile:display_name will be asked for, so display_name is
|
||||
// available
|
||||
.then(
|
||||
testElementExists(selectors.OAUTH_PERMISSIONS.CHECKBOX_DISPLAY_NAME)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.OAUTH_PERMISSIONS.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'signin after de-selecting a requested permission': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// make display_name available from the start
|
||||
.then(click(selectors.SETTINGS_DISPLAY_NAME.MENU_BUTTON))
|
||||
.then(click(selectors.SETTINGS_DISPLAY_NAME.INPUT_LABEL_DISPLAY_NAME))
|
||||
.then(
|
||||
type(
|
||||
selectors.SETTINGS_DISPLAY_NAME.INPUT_DISPLAY_NAME,
|
||||
'test user'
|
||||
)
|
||||
)
|
||||
.then(click(selectors.SETTINGS_DISPLAY_NAME.SUBMIT))
|
||||
.then(visibleByQSA(selectors.SETTINGS.SUCCESS))
|
||||
|
||||
.then(
|
||||
openFxaFromUntrustedRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
})
|
||||
)
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
.then(
|
||||
testElementExists(selectors.OAUTH_PERMISSIONS.CHECKBOX_DISPLAY_NAME)
|
||||
)
|
||||
// deselect display name to ensure permission state is
|
||||
// saved correctly.
|
||||
.then(click(selectors.OAUTH_PERMISSIONS.CHECKBOX_DISPLAY_NAME))
|
||||
.then(
|
||||
click(
|
||||
selectors.OAUTH_PERMISSIONS.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
// signin again, no permissions should be asked for even though
|
||||
// display_name was de-selected last time.
|
||||
.then(click(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('oauth permissions for trusted reliers', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote.then(
|
||||
FunctionalHelpers.clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'signup without `prompt=consent`': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromTrustedRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
// no permissions asked for, straight to confirm
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'signup with `prompt=consent`': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openFxaFromTrustedRp('enter-email', {
|
||||
query: { prompt: 'consent' },
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
// permissions are asked for with `prompt=consent`
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(click(selectors.OAUTH_PERMISSIONS.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'signin without `prompt=consent`': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromTrustedRp('enter-email'))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// no permissions asked for, straight to relier
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
|
||||
'signin with `prompt=consent`': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openFxaFromTrustedRp('enter-email', {
|
||||
query: { prompt: 'consent' },
|
||||
})
|
||||
)
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// permissions are asked for with `prompt=consent`
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(click(selectors.OAUTH_PERMISSIONS.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
|
||||
'signin without `prompt=consent`, then re-signin with `prompt=consent`': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openFxaFromTrustedRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// no permissions asked for, straight to relier
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
.then(testUrlEquals(TRUSTED_OAUTH_APP))
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
// currently there is no way to tell when 123done fully logged out
|
||||
// give the logout request some time to complete
|
||||
.sleep(1000)
|
||||
.then(visibleByQSA('#splash .signup'))
|
||||
|
||||
// relier changes to request consent
|
||||
.then(
|
||||
openFxaFromTrustedRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
query: { prompt: 'consent' },
|
||||
})
|
||||
)
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
// since consent is now requested, user should see prompt
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(click(selectors.OAUTH_PERMISSIONS.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
|
||||
'force_auth without `prompt=consent`': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openFxaFromTrustedRp('force-auth', { query: { email: email } }))
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
// no permissions asked for, straight to relier
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
|
||||
'force_auth with `prompt=consent`': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromTrustedRp('force-auth', {
|
||||
query: {
|
||||
email: email,
|
||||
prompt: 'consent',
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
// permissions are asked for with `prompt=consent`
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(click(selectors.OAUTH_PERMISSIONS.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,223 +0,0 @@
|
|||
/* eslint-disable camelcase */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const config = intern._config;
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const EMAIL_FIRST_URL = `${config.fxaContentRoot}?action=email`;
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
destroySessionForEmail,
|
||||
fillOutEmailFirstSignIn,
|
||||
openPage,
|
||||
openRP,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('oauth prompt=none', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
afterEach: function () {
|
||||
return this.remote.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'fails RP that is not allowed': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openRP({
|
||||
untrusted: true,
|
||||
query: { login_hint: email, return_on_error: false },
|
||||
})
|
||||
)
|
||||
.then(click(selectors['123DONE'].BUTTON_PROMPT_NONE))
|
||||
.then(testElementExists(selectors['400'].HEADER))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors['400'].ERROR,
|
||||
'prompt=none is not enabled for this client'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'fails if requesting keys': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openRP({
|
||||
query: {
|
||||
client_id: '7f368c6886429f19', // eslint-disable-line camelcase
|
||||
forceUA:
|
||||
'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Mobile Safari/537.36',
|
||||
keys_jwk:
|
||||
'eyJrdHkiOiJFQyIsImtpZCI6Im9DNGFudFBBSFZRX1pmQ09RRUYycTRaQlZYblVNZ2xISGpVRzdtSjZHOEEiLCJjcnYiOi' +
|
||||
'JQLTI1NiIsIngiOiJDeUpUSjVwbUNZb2lQQnVWOTk1UjNvNTFLZVBMaEg1Y3JaQlkwbXNxTDk0IiwieSI6IkJCWDhfcFVZeHpTaldsdX' +
|
||||
'U5MFdPTVZwamIzTlpVRDAyN0xwcC04RW9vckEifQ',
|
||||
login_hint: email,
|
||||
redirect_uri:
|
||||
'https://mozilla.github.io/notes/fxa/android-redirect.html', // eslint-disable-line camelcase
|
||||
return_on_error: false,
|
||||
scope: 'profile https://identity.mozilla.com/apps/notes',
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(click(selectors['123DONE'].BUTTON_PROMPT_NONE))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors['400'].ERROR,
|
||||
'prompt=none cannot be used when requesting keys'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'fails if no login_hint': function () {
|
||||
const email = createEmail();
|
||||
// We do the session check before the login_hint/id_token_hint check,
|
||||
// so need a session to generate this error.
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(
|
||||
openRP({
|
||||
query: { return_on_error: false },
|
||||
})
|
||||
)
|
||||
.then(click(selectors['123DONE'].BUTTON_PROMPT_NONE))
|
||||
.then(testElementExists(selectors['400'].HEADER))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors['400'].ERROR,
|
||||
'missing oauth parameter'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'fails if no user logged in': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openRP({
|
||||
query: {
|
||||
login_hint: email,
|
||||
return_on_error: false,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(click(selectors['123DONE'].BUTTON_PROMPT_NONE))
|
||||
.then(testElementExists(selectors['400'].HEADER))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors['400'].ERROR,
|
||||
'User is not signed in'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'fails if account is not verified': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: false }))
|
||||
|
||||
.then(openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
.then(openRP({ query: { login_hint: email, return_on_error: false } }))
|
||||
.then(click(selectors['123DONE'].BUTTON_PROMPT_NONE))
|
||||
.then(testElementExists(selectors['400'].HEADER))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors['400'].ERROR,
|
||||
'Unverified user or session'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'fails if login_hint is different to logged in user': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
|
||||
.then(openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
openRP({
|
||||
query: { login_hint: createEmail(), return_on_error: false },
|
||||
})
|
||||
)
|
||||
.then(click(selectors['123DONE'].BUTTON_PROMPT_NONE))
|
||||
.then(testElementExists(selectors['400'].HEADER))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors['400'].ERROR,
|
||||
'a different user is signed in'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'fails if session is no longer valid': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
|
||||
.then(openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(destroySessionForEmail(email))
|
||||
.then(
|
||||
openRP({
|
||||
query: { login_hint: email, return_on_error: false },
|
||||
})
|
||||
)
|
||||
.then(click(selectors['123DONE'].BUTTON_PROMPT_NONE))
|
||||
.then(testElementExists(selectors['400'].HEADER))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors['400'].ERROR,
|
||||
'User is not signed in'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'succeeds if login_hint same as logged in user': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
|
||||
.then(openPage(EMAIL_FIRST_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(openRP({ query: { login_hint: email } }))
|
||||
.then(click(selectors['123DONE'].BUTTON_PROMPT_NONE))
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,407 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
let TRUSTED_CLIENT_ID;
|
||||
const TRUSTED_SCOPE = 'profile';
|
||||
let UNTRUSTED_CLIENT_ID;
|
||||
const UNTRUSTED_SCOPE = 'profile:uid profile:email';
|
||||
const UNTRUSTED_NO_VALID_SCOPES = 'profile';
|
||||
const TRUSTED_REDIRECT_URI = `${config.fxaOAuthApp}api/oauth`;
|
||||
const UNTRUSTED_REDIRECT_URI = `${config.fxaUntrustedOauthApp}api/oauth`;
|
||||
const AUTHORIZATION_URL = `${config.fxaContentRoot}authorization`;
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}oauth/`;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
getQueryParamValue,
|
||||
openFxaFromRp,
|
||||
openFxaFromUntrustedRp,
|
||||
openPage,
|
||||
testElementTextInclude,
|
||||
thenify,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
var openPageWithQueryParams = thenify(function (query, expectedHeader) {
|
||||
return this.parent.then(openPage(ENTER_EMAIL_URL, expectedHeader, { query }));
|
||||
});
|
||||
|
||||
var openEmailFirstExpect200 = thenify(function (queryParams) {
|
||||
return this.parent.then(
|
||||
openPageWithQueryParams(queryParams, selectors.ENTER_EMAIL.HEADER)
|
||||
);
|
||||
});
|
||||
|
||||
var openEmailFirstExpect400 = thenify(function (queryParams) {
|
||||
return this.parent.then(
|
||||
openPageWithQueryParams(queryParams, selectors['400'].HEADER)
|
||||
);
|
||||
});
|
||||
|
||||
const openAuthorizationWithQueryParams = thenify(function (
|
||||
query,
|
||||
expectedHeader
|
||||
) {
|
||||
return this.parent.then(
|
||||
openPage(AUTHORIZATION_URL, expectedHeader, { query })
|
||||
);
|
||||
});
|
||||
|
||||
var testErrorInclude = function (expected) {
|
||||
return testElementTextInclude('.error', expected);
|
||||
};
|
||||
|
||||
/*eslint-disable camelcase */
|
||||
registerSuite('oauth query parameter validation', {
|
||||
beforeEach: function () {
|
||||
return this.remote
|
||||
.then(
|
||||
clearBrowserState({
|
||||
forceAll: true,
|
||||
})
|
||||
)
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(getQueryParamValue('client_id'))
|
||||
.then(function (clientId) {
|
||||
TRUSTED_CLIENT_ID = clientId;
|
||||
})
|
||||
.then(openFxaFromUntrustedRp('enter-email'))
|
||||
.then(getQueryParamValue('client_id'))
|
||||
.then(function (clientId) {
|
||||
UNTRUSTED_CLIENT_ID = clientId;
|
||||
});
|
||||
},
|
||||
tests: {
|
||||
'service specified': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
service: 'sync',
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('service'));
|
||||
},
|
||||
|
||||
'invalid access_type': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
access_type: 'invalid',
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('access_type'));
|
||||
},
|
||||
|
||||
'valid access_type (offline)': function () {
|
||||
return this.remote.then(
|
||||
openEmailFirstExpect200({
|
||||
access_type: 'offline',
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
'valid access_type (online)': function () {
|
||||
return this.remote.then(
|
||||
openEmailFirstExpect200({
|
||||
access_type: 'online',
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
'missing client_id': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('missing'))
|
||||
.then(testErrorInclude('client_id'));
|
||||
},
|
||||
|
||||
'empty client_id': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: '',
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('client_id'));
|
||||
},
|
||||
|
||||
'space client_id': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: ' ',
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('client_id'));
|
||||
},
|
||||
|
||||
'invalid client_id': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: 'invalid_client_id',
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('client_id'));
|
||||
},
|
||||
|
||||
'unknown client_id': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: 'deadbeefdeadbeef',
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('unknown client'));
|
||||
},
|
||||
|
||||
'empty prompt': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
prompt: '',
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('prompt'));
|
||||
},
|
||||
|
||||
'space prompt': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
prompt: ' ',
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('prompt'));
|
||||
},
|
||||
|
||||
'invalid prompt': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
prompt: 'invalid',
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('prompt'));
|
||||
},
|
||||
|
||||
'valid prompt (consent)': function () {
|
||||
return this.remote.then(
|
||||
openEmailFirstExpect200({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
prompt: 'consent',
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
'invalid redirectTo (url)': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirectTo: 'localhost',
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('redirectTo'));
|
||||
},
|
||||
|
||||
'valid redirectTo (url)': function () {
|
||||
return this.remote.then(
|
||||
openEmailFirstExpect200({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
redirectTo: 'http://localhost',
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
'invalid redirect_uri (url)': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: 'localhost',
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('redirect_uri'));
|
||||
},
|
||||
|
||||
'valid redirect_uri (url)': function () {
|
||||
return this.remote.then(
|
||||
openEmailFirstExpect200({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
'missing scope': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('missing'))
|
||||
.then(testErrorInclude('scope'));
|
||||
},
|
||||
|
||||
'empty scope': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
scope: '',
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('scope'));
|
||||
},
|
||||
|
||||
'space scope': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
scope: ' ',
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('scope'));
|
||||
},
|
||||
|
||||
'no valid scopes (untrusted)': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openEmailFirstExpect400({
|
||||
client_id: UNTRUSTED_CLIENT_ID,
|
||||
redirect_uri: UNTRUSTED_REDIRECT_URI,
|
||||
scope: UNTRUSTED_NO_VALID_SCOPES,
|
||||
})
|
||||
)
|
||||
.then(testErrorInclude('invalid'))
|
||||
.then(testErrorInclude('scope'));
|
||||
},
|
||||
|
||||
'valid scope (trusted)': function () {
|
||||
return this.remote.then(
|
||||
openEmailFirstExpect200({
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
'valid scope (untrusted)': function () {
|
||||
return this.remote.then(
|
||||
openEmailFirstExpect200({
|
||||
client_id: UNTRUSTED_CLIENT_ID,
|
||||
redirect_uri: UNTRUSTED_REDIRECT_URI,
|
||||
scope: UNTRUSTED_SCOPE,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
'authorization with no action (trusted)': function () {
|
||||
return this.remote.then(
|
||||
openAuthorizationWithQueryParams(
|
||||
{
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
},
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'authorization with force_auth with no email (trusted)': function () {
|
||||
return (
|
||||
this.remote
|
||||
// 400s because there is no email set
|
||||
.then(
|
||||
openAuthorizationWithQueryParams(
|
||||
{
|
||||
action: 'force_auth',
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
},
|
||||
selectors['400'].HEADER
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'authorization with unknown action (trusted)': function () {
|
||||
return (
|
||||
this.remote
|
||||
// 400s because there is no email set
|
||||
.then(
|
||||
openAuthorizationWithQueryParams(
|
||||
{
|
||||
action: 'unknown',
|
||||
client_id: TRUSTED_CLIENT_ID,
|
||||
redirect_uri: TRUSTED_REDIRECT_URI,
|
||||
scope: TRUSTED_SCOPE,
|
||||
},
|
||||
selectors['400'].HEADER
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
/*eslint-enable camelcase */
|
|
@ -1,162 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const assert = intern.getPlugin('chai').assert;
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const config = intern._config;
|
||||
const OAUTH_APP = config.fxaOAuthApp;
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?action=email`;
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
confirmTotpCode,
|
||||
createEmail,
|
||||
createUser,
|
||||
enableTotpInline,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
generateTotpCode,
|
||||
openFxaFromRp,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
thenify,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const testAtOAuthApp = thenify(function () {
|
||||
return this.parent
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
.then(testElementTextInclude(selectors['123DONE'].AUTHENTICATED_TOTP, '🔒'))
|
||||
.getCurrentUrl()
|
||||
.then(function (url) {
|
||||
// redirected back to the App
|
||||
assert.ok(url.indexOf(OAUTH_APP) > -1);
|
||||
});
|
||||
});
|
||||
|
||||
registerSuite('oauth require totp', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
force: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
signup: function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openFxaFromRp('two-step-authentication', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER));
|
||||
},
|
||||
|
||||
'account without TOTP redirects to TOTP setup and completes TOTP flow': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('two-step-authentication', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(enableTotpInline())
|
||||
.then(testAtOAuthApp());
|
||||
},
|
||||
|
||||
'after enabling TOTP in the login flow, account bypasses TOTP setup on second visit': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('two-step-authentication', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(enableTotpInline())
|
||||
.then(testAtOAuthApp())
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
.then(visibleByQSA(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
.then(
|
||||
openFxaFromRp('two-step-authentication', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
})
|
||||
)
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
.then(testAtOAuthApp());
|
||||
},
|
||||
|
||||
'succeed for account with TOTP': function () {
|
||||
this.timeout = 60 * 1000;
|
||||
let secret;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(click(selectors.TOTP.MENU_BUTTON))
|
||||
|
||||
.then(click(selectors.TOTP.SHOW_CODE_LINK))
|
||||
.then(visibleByQSA(selectors.TOTP.MANUAL_CODE))
|
||||
|
||||
// Store the secret key to recalculate the code later
|
||||
.findByCssSelector(selectors.TOTP.MANUAL_CODE)
|
||||
.getVisibleText()
|
||||
.then((secretKey) => {
|
||||
secret = secretKey;
|
||||
})
|
||||
.end()
|
||||
.then(() => this.remote.then(click(selectors.TOTP.KEY_OK_BUTTON)))
|
||||
.then(() => this.remote.then(confirmTotpCode(secret)))
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(
|
||||
openFxaFromRp('two-step-authentication', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
|
||||
// Correctly submits the totp code and navigates to oauth page
|
||||
.then(() => {
|
||||
return this.remote.then(
|
||||
type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret))
|
||||
);
|
||||
})
|
||||
.then(click(selectors.TOTP_SIGNIN.SUBMIT))
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,384 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const config = intern._config;
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
const TIMEOUT = 90 * 1000;
|
||||
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?action=email`;
|
||||
|
||||
let email;
|
||||
let secret;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
closeCurrentWindow,
|
||||
createEmail,
|
||||
createUser,
|
||||
enableTotp,
|
||||
fillOutCompleteResetPassword,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutResetPassword,
|
||||
generateTotpCode,
|
||||
openExternalSite,
|
||||
openFxaFromRp,
|
||||
openPage,
|
||||
openPasswordResetLinkInDifferentBrowser,
|
||||
openVerificationLinkInNewTab,
|
||||
openVerificationLinkInSameTab,
|
||||
signOut,
|
||||
switchToWindow,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('oauth reset password', {
|
||||
beforeEach: function () {
|
||||
// timeout after 90 seconds
|
||||
this.timeout = TIMEOUT;
|
||||
email = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(
|
||||
clearBrowserState({
|
||||
forceAll: true,
|
||||
})
|
||||
)
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }));
|
||||
},
|
||||
tests: {
|
||||
'reset password, verify same browser': function () {
|
||||
this.timeout = TIMEOUT;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD,
|
||||
selectors.RESET_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(openVerificationLinkInNewTab(email, 0))
|
||||
|
||||
// Complete the reset password in the new tab
|
||||
.then(switchToWindow(1))
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
// this tab's success is seeing the reset password complete header.
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
// user sees the name of the rp, but cannot redirect
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.RESET_PASSWORD_COMPLETE.SUB_HEADER,
|
||||
'123done'
|
||||
)
|
||||
)
|
||||
.then(closeCurrentWindow())
|
||||
|
||||
// the original tab should automatically sign in
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
|
||||
'reset password, verify same browser with original tab closed':
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD,
|
||||
selectors.RESET_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
// user browses to another site.
|
||||
.then(openExternalSite())
|
||||
.then(openVerificationLinkInNewTab(email, 0))
|
||||
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
|
||||
// switch to the original window
|
||||
.then(closeCurrentWindow())
|
||||
);
|
||||
},
|
||||
|
||||
'reset password, verify same browser by replacing the original tab':
|
||||
function () {
|
||||
return this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD,
|
||||
selectors.RESET_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(openVerificationLinkInSameTab(email, 0))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED));
|
||||
},
|
||||
|
||||
"reset password, verify in a different browser, from the original tab's P.O.V.":
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD,
|
||||
selectors.RESET_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
.then(openPasswordResetLinkInDifferentBrowser(email, PASSWORD))
|
||||
|
||||
// user verified in a new browser, they have to enter
|
||||
// their updated credentials in the original tab.
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(visibleByQSA(selectors.SIGNIN_PASSWORD.SUCCESS))
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
|
||||
// user is redirected to RP
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
|
||||
"reset password, verify in a different browser, from the new browser's P.O.V.":
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD,
|
||||
selectors.RESET_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD.HEADER))
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
// clear all browser state, simulate opening in a new browser
|
||||
.then(
|
||||
clearBrowserState({
|
||||
forceAll: true,
|
||||
})
|
||||
)
|
||||
.then(openVerificationLinkInSameTab(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
// user sees the name of the rp, but cannot redirect
|
||||
.then(testElementTextInclude('.account-ready-service', '123done'))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('oauth reset password with TOTP', {
|
||||
beforeEach: function () {
|
||||
// timeout after 90 seconds
|
||||
this.timeout = TIMEOUT;
|
||||
email = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(
|
||||
clearBrowserState({
|
||||
forceAll: true,
|
||||
})
|
||||
)
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(enableTotp())
|
||||
.then((_secret) => {
|
||||
secret = _secret;
|
||||
})
|
||||
.then(signOut())
|
||||
.then(
|
||||
clearBrowserState({
|
||||
forceAll: true,
|
||||
})
|
||||
)
|
||||
.then(
|
||||
openFxaFromRp('enter-email', { header: selectors.ENTER_EMAIL.HEADER })
|
||||
)
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNIN_PASSWORD.HEADER)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD,
|
||||
selectors.RESET_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
.then(fillOutResetPassword(email));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'reset password, verify same browser same tab': function () {
|
||||
return this.remote
|
||||
.then(openVerificationLinkInSameTab(email, 2))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret)))
|
||||
.then(
|
||||
click(
|
||||
selectors.TOTP_SIGNIN.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED_TOTP
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED_TOTP));
|
||||
},
|
||||
|
||||
'reset password, verify same browser different tab': function () {
|
||||
return this.remote
|
||||
.then(openVerificationLinkInNewTab(email, 2))
|
||||
.then(switchToWindow(1))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret)))
|
||||
.then(
|
||||
click(
|
||||
selectors.TOTP_SIGNIN.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED_TOTP
|
||||
)
|
||||
)
|
||||
|
||||
.then(switchToWindow(0))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER));
|
||||
},
|
||||
|
||||
"reset password, verify in a different browser, from the original tab's P.O.V.":
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPasswordResetLinkInDifferentBrowser(email, PASSWORD, 2))
|
||||
|
||||
// user verified in a new browser, they have to enter
|
||||
// their password in the original tab.
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.TOTP_SIGNIN.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret)))
|
||||
.then(
|
||||
click(
|
||||
selectors.TOTP_SIGNIN.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED_TOTP
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
"reset password, verify in a different browser from new browser's P.O.V.":
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
// clear all browser state, simulate opening in a new browser
|
||||
.then(clearBrowserState({ forceAll: true }))
|
||||
.then(openVerificationLinkInSameTab(email, 2))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
// this tab's success is seeing the reset password complete header.
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,125 +0,0 @@
|
|||
/* eslint-disable indent */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
var config = intern._config;
|
||||
var CONTENT_SERVER = config.fxaContentRoot;
|
||||
var APPS_SETTINGS_URL = CONTENT_SERVER + 'settings#connected-services';
|
||||
var UNTRUSTED_OAUTH_APP = config.fxaUntrustedOauthApp;
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
var PASSWORD = 'password123456789';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
closeCurrentWindow,
|
||||
createEmail,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
noSuchElement,
|
||||
openFxaFromRp,
|
||||
openPage,
|
||||
openTab,
|
||||
pollUntilGoneByQSA,
|
||||
switchToWindow,
|
||||
testElementExists,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
var email;
|
||||
|
||||
registerSuite('oauth settings clients', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
tests: {
|
||||
'rp listed in apps, can be deleted': function () {
|
||||
var self = this;
|
||||
self.timeout = 90 * 1000;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
|
||||
// lists the first client
|
||||
.then(openPage(APPS_SETTINGS_URL, selectors.SETTINGS_CLIENTS.HEADER))
|
||||
|
||||
// sign in into another app
|
||||
.then(openTab(UNTRUSTED_OAUTH_APP))
|
||||
.then(switchToWindow(1))
|
||||
|
||||
// cannot use the helper method here, the helper method uses $ (jQuery)
|
||||
// 123Done loads jQuery in the <body> this leads to '$ is undefined' error
|
||||
// when running tests, because jQuery can be slow to load
|
||||
|
||||
.then(click(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
.then(testElementExists(selectors.OAUTH_PERMISSIONS.HEADER))
|
||||
.then(click(selectors.OAUTH_PERMISSIONS.SUBMIT))
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
|
||||
.then(closeCurrentWindow())
|
||||
|
||||
// second app should show up using 'refresh'
|
||||
.then(click(selectors.SETTINGS_CLIENTS.BUTTON_REFRESH))
|
||||
|
||||
.then(
|
||||
testElementExists(
|
||||
'[data-testid=settings-connected-service][data-name^="321"]'
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
'[data-testid=settings-connected-service][data-name^="123"] [data-testid=connected-service-sign-out]'
|
||||
)
|
||||
)
|
||||
// wait for the element to be gone or else it's possible for the subsequent
|
||||
// `click` can fail with a StaleElementReference because click on 123Done's
|
||||
// button happens, the XHR request takes a bit of time, the reference to the
|
||||
// 321Done button is fetched, the XHR request completes and updates the DOM,
|
||||
// making the reference to the 321Done button stale.
|
||||
.then(
|
||||
pollUntilGoneByQSA(
|
||||
'[data-testid=settings-connected-service][data-name^="123"]'
|
||||
)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
'[data-testid=settings-connected-service][data-name^="321"] [data-testid=connected-service-sign-out]'
|
||||
)
|
||||
)
|
||||
.then(pollUntilGoneByQSA(selectors.SETTINGS_CLIENTS.OAUTH_CLIENT))
|
||||
|
||||
// the deleted clients should not show up again, this ensures
|
||||
// that access tokens are deleted along with the refresh tokens.
|
||||
.then(click(selectors.SETTINGS_CLIENTS.BUTTON_REFRESH))
|
||||
.then(
|
||||
pollUntilGoneByQSA(
|
||||
'[data-testid=settings-connected-service][data-name^="321"]'
|
||||
)
|
||||
)
|
||||
|
||||
.then(noSuchElement(selectors.SETTINGS_CLIENTS.OAUTH_CLIENT))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,706 +0,0 @@
|
|||
/* eslint-disable camelcase */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const assert = intern.getPlugin('chai').assert;
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const config = intern._config;
|
||||
const OAUTH_APP = config.fxaOAuthApp;
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?action=email`;
|
||||
const otplib = require('otplib');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
// Default options for TOTP
|
||||
otplib.authenticator.options = { encoding: 'hex' };
|
||||
|
||||
const SETTINGS_URL = `${config.fxaContentRoot}settings`;
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
const CODE_CHALLENGE = 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM';
|
||||
const CODE_CHALLENGE_METHOD = 'S256';
|
||||
|
||||
let email;
|
||||
let secret;
|
||||
|
||||
const thenify = FunctionalHelpers.thenify;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
confirmTotpCode,
|
||||
createEmail,
|
||||
createUser,
|
||||
destroySessionForEmail,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignInUnblock,
|
||||
fillOutSignInTokenCode,
|
||||
fillOutSignUpCode,
|
||||
generateTotpCode,
|
||||
openFxaFromRp,
|
||||
openPage,
|
||||
signOut,
|
||||
testElementExists,
|
||||
testElementTextEquals,
|
||||
testElementTextInclude,
|
||||
testElementValueEquals,
|
||||
testUrlInclude,
|
||||
testUrlPathnameEquals,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const testAtOAuthApp = thenify(function () {
|
||||
return this.parent
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
|
||||
.getCurrentUrl()
|
||||
.then(function (url) {
|
||||
// redirected back to the App
|
||||
assert.ok(url.indexOf(OAUTH_APP) > -1);
|
||||
});
|
||||
});
|
||||
|
||||
registerSuite('oauth signin', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote.then(
|
||||
FunctionalHelpers.clearBrowserState({
|
||||
forceAll: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
tests: {
|
||||
verified: function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testAtOAuthApp());
|
||||
},
|
||||
|
||||
'verified using a cached login': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
|
||||
// sign in with a verified account to cache credentials
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
.then(
|
||||
click(
|
||||
selectors['123DONE'].LINK_LOGOUT,
|
||||
selectors['123DONE'].BUTTON_SIGNIN
|
||||
)
|
||||
)
|
||||
|
||||
.then(visibleByQSA(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
// round 2 - with the cached credentials
|
||||
.then(
|
||||
click(
|
||||
selectors['123DONE'].BUTTON_SIGNIN,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
);
|
||||
},
|
||||
|
||||
'verified using a cached expired login': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
|
||||
// sign in with a verified account to cache credentials
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
.then(
|
||||
click(
|
||||
selectors['123DONE'].LINK_LOGOUT,
|
||||
selectors['123DONE'].BUTTON_SIGNIN
|
||||
)
|
||||
)
|
||||
|
||||
.then(visibleByQSA(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
// round 2 - with the cached credentials
|
||||
.then(
|
||||
click(
|
||||
selectors['123DONE'].BUTTON_SIGNIN,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(destroySessionForEmail(email))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
// we only know the sessionToken is expired once the
|
||||
// user submits the form.
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
// we now know the sessionToken is expired. Allow the user to sign in
|
||||
// with their password.
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email))
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
);
|
||||
},
|
||||
|
||||
'cached credentials that expire while on page': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
.then(testAtOAuthApp())
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
|
||||
// user is signed in, use cached credentials no password is needed
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
})
|
||||
)
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
.then(destroySessionForEmail(email))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN,
|
||||
selectors.SIGNIN_PASSWORD.ERROR
|
||||
)
|
||||
)
|
||||
// Session expired error should show.
|
||||
.then(visibleByQSA(selectors.SIGNIN_PASSWORD.ERROR))
|
||||
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors['123DONE'].AUTHENTICATED
|
||||
)
|
||||
)
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
);
|
||||
},
|
||||
|
||||
'unverified, acts like signup': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: false }))
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
// get the second email, the first was sent on client.signUp w/
|
||||
// preVerified: false above. The second email has the `service` and
|
||||
// `resume` parameters.
|
||||
.then(fillOutSignInTokenCode(email, 1))
|
||||
// user verifies in the same tab, so they are logged in to the RP.
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
|
||||
'unverified with a cached login': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
// first, sign the user up to cache the login
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
// round 2 - try to sign in with the unverified user.
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
})
|
||||
)
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.SUB_HEADER))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN,
|
||||
selectors.CONFIRM_SIGNUP_CODE.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
// success is using a cached login and being redirected
|
||||
// to a confirmation screen
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
// get the second email, the first was sent via fillOutEmailFirstSignUp above.
|
||||
.then(fillOutSignInTokenCode(email, 1))
|
||||
.then(testAtOAuthApp())
|
||||
);
|
||||
},
|
||||
|
||||
'oauth endpoint chooses the right auth flows': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(OAUTH_APP, '.ready'))
|
||||
|
||||
// use the 'Choose my sign-in flow for me' button
|
||||
.then(click(selectors['123DONE'].BUTTON_SIGNIN_CHOOSE_FLOW_FOR_ME))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
// go back to the OAuth app, the /oauth flow should
|
||||
// now suggest a cached login
|
||||
.get(OAUTH_APP)
|
||||
// again, use the 'Choose my sign-in flow for me' button
|
||||
.then(click(selectors['123DONE'].BUTTON_SIGNIN_CHOOSE_FLOW_FOR_ME))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'email specified by relier, invalid': function () {
|
||||
const invalidEmail = 'invalid@';
|
||||
|
||||
return this.remote
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
query: {
|
||||
email: invalidEmail,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, invalidEmail))
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.ENTER_EMAIL.TOOLTIP,
|
||||
'Valid email required'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'email specified by relier, not registered': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNUP_PASSWORD.HEADER,
|
||||
query: {
|
||||
email,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.EMAIL, email))
|
||||
// user realizes it's the wrong email address.
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
);
|
||||
},
|
||||
|
||||
'login_hint specified by relier, not registered': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNUP_PASSWORD.HEADER,
|
||||
query: {
|
||||
login_hint: email,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.EMAIL, email))
|
||||
// user realizes it's the wrong email address.
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
);
|
||||
},
|
||||
|
||||
'email specified by relier, registered': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
query: {
|
||||
email,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email))
|
||||
// user realizes it's the wrong email address.
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
);
|
||||
},
|
||||
|
||||
'login_hint specified by relier, registered': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
query: {
|
||||
login_hint: email,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email));
|
||||
},
|
||||
|
||||
'cached credentials, login_hint specified by relier': function () {
|
||||
const loginHintEmail = createEmail();
|
||||
const oAuthEmail = createEmail();
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(createUser(oAuthEmail, PASSWORD, { preVerified: true }))
|
||||
.then(createUser(loginHintEmail, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('email-first', {
|
||||
header: selectors.ENTER_EMAIL.HEADER,
|
||||
})
|
||||
)
|
||||
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT))
|
||||
.then(testAtOAuthApp())
|
||||
.then(
|
||||
click(
|
||||
selectors['123DONE'].LINK_LOGOUT,
|
||||
selectors['123DONE'].BUTTON_SIGNIN
|
||||
)
|
||||
)
|
||||
|
||||
// login_hint takes precedence over the signed in user
|
||||
.then(
|
||||
openFxaFromRp('email-first', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
query: {
|
||||
login_hint: loginHintEmail,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
.then(
|
||||
testElementValueEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL,
|
||||
loginHintEmail
|
||||
)
|
||||
)
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT))
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
);
|
||||
},
|
||||
|
||||
'login_hint specified by relier, registered, user changes email':
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
query: {
|
||||
login_hint: email,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(
|
||||
testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email)
|
||||
)
|
||||
|
||||
// user realizes they want to use a different account.
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
);
|
||||
},
|
||||
|
||||
'verified, blocked': function () {
|
||||
email = createEmail('blocked{id}');
|
||||
|
||||
return this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(fillOutSignInUnblock(email, 0))
|
||||
|
||||
.then(testAtOAuthApp());
|
||||
},
|
||||
|
||||
'verified, blocked, incorrect password': function () {
|
||||
email = createEmail('blocked{id}');
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, 'bad' + PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(fillOutSignInUnblock(email, 0))
|
||||
|
||||
// wait until at the signin page to check the URL to
|
||||
// avoid latency problems with submitting the unblock code.
|
||||
// w/o the wait, the URL can be checked before
|
||||
// the submit completes.
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(testUrlPathnameEquals('/oauth/signin'))
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.SIGNIN_UNBLOCK.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutSignInUnblock(email, 1))
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
);
|
||||
},
|
||||
|
||||
'signin in Chrome for Android, verify same browser': function () {
|
||||
// The `sync` prefix is needed to force signin confirmation.
|
||||
email = createEmail('sync{id}');
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
query: {
|
||||
client_id: '7f368c6886429f19', // eslint-disable-line camelcase
|
||||
code_challenge: CODE_CHALLENGE,
|
||||
code_challenge_method: CODE_CHALLENGE_METHOD,
|
||||
forceUA:
|
||||
'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Mobile Safari/537.36',
|
||||
// eslint-disable-next-line camelcase
|
||||
keys_jwk:
|
||||
'eyJrdHkiOiJFQyIsImtpZCI6Im9DNGFudFBBSFZRX1pmQ09RRUYycTRaQlZYblVNZ2xISGpVRzdtSjZHOEEiLCJjcnYiOi' +
|
||||
'JQLTI1NiIsIngiOiJDeUpUSjVwbUNZb2lQQnVWOTk1UjNvNTFLZVBMaEg1Y3JaQlkwbXNxTDk0IiwieSI6IkJCWDhfcFVZeHpTaldsdX' +
|
||||
'U5MFdPTVZwamIzTlpVRDAyN0xwcC04RW9vckEifQ',
|
||||
redirect_uri:
|
||||
'https://mozilla.github.io/notes/fxa/android-redirect.html', // eslint-disable-line camelcase
|
||||
scope: 'profile https://identity.mozilla.com/apps/notes',
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementTextInclude(selectors.ENTER_EMAIL.SUB_HEADER, 'notes'))
|
||||
.then(testUrlInclude('client_id='))
|
||||
.then(testUrlInclude('state='))
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.FIREFOX_NOTES.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('oauth signin - TOTP', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return (
|
||||
this.remote
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(openPage(SETTINGS_URL, selectors.SETTINGS.HEADER))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(testElementExists(selectors.TOTP.MENU_BUTTON))
|
||||
|
||||
.then(click(selectors.TOTP.MENU_BUTTON))
|
||||
|
||||
.then(testElementExists(selectors.TOTP.QR_CODE))
|
||||
.then(testElementExists(selectors.TOTP.SHOW_CODE_LINK))
|
||||
|
||||
.then(click(selectors.TOTP.SHOW_CODE_LINK))
|
||||
.then(testElementExists(selectors.TOTP.MANUAL_CODE))
|
||||
|
||||
// Store the secret key to recalculate the code later
|
||||
.findByCssSelector(selectors.TOTP.MANUAL_CODE)
|
||||
.getVisibleText()
|
||||
.then((secretKey) => {
|
||||
secret = secretKey;
|
||||
})
|
||||
.end()
|
||||
.then(() => this.remote.then(click(selectors.TOTP.KEY_OK_BUTTON)))
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'can add TOTP to account and confirm oauth signin': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(confirmTotpCode(secret))
|
||||
|
||||
.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
)
|
||||
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// Correctly submits the totp code and navigates to oauth page
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret)))
|
||||
.then(click(selectors.TOTP_SIGNIN.SUBMIT))
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
);
|
||||
},
|
||||
|
||||
'can remove TOTP from account and skip confirmation': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(confirmTotpCode(secret))
|
||||
|
||||
// Remove token
|
||||
.then(click(selectors.TOTP.DELETE_BUTTON))
|
||||
.then(click(selectors.TOTP.CONFIRM_DELETE))
|
||||
.then(testElementExists(selectors.TOTP.DISABLE_SUCCESS))
|
||||
.then(testElementExists(selectors.TOTP.MENU_BUTTON))
|
||||
|
||||
// Does not prompt for code
|
||||
.then(signOut())
|
||||
.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
)
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testAtOAuthApp())
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,130 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const assert = intern.getPlugin('chai').assert;
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
destroySessionForEmail,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutSignInTokenCode,
|
||||
openFxaFromRp,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
getEmailHeaders,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const NOTES_REDIRECT_PAGE_SELECTOR = '#notes-by-firefox';
|
||||
const NOTES_PAGE_TEXT_SELECTOR = 'Notes by Firefox';
|
||||
const experimentParams = {
|
||||
query: {
|
||||
client_id: '7f368c6886429f19', // eslint-disable-line camelcase
|
||||
code_challenge: 'aSOwsmuRBE1ZIVtiW6bzKMaf47kCFl7duD6ZWAXdnJo', // eslint-disable-line camelcase
|
||||
code_challenge_method: 'S256', // eslint-disable-line camelcase
|
||||
forceUA:
|
||||
'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Mobile Safari/537.36',
|
||||
// eslint-disable-next-line camelcase
|
||||
keys_jwk:
|
||||
'eyJrdHkiOiJFQyIsImtpZCI6Im9DNGFudFBBSFZRX1pmQ09RRUYycTRaQlZYblVNZ2xISGpVRzdtSjZHOEEiLCJjcnYiOi' +
|
||||
'JQLTI1NiIsIngiOiJDeUpUSjVwbUNZb2lQQnVWOTk1UjNvNTFLZVBMaEg1Y3JaQlkwbXNxTDk0IiwieSI6IkJCWDhfcFVZeHpTaldsdX' +
|
||||
'U5MFdPTVZwamIzTlpVRDAyN0xwcC04RW9vckEifQ',
|
||||
redirect_uri: 'https://mozilla.github.io/notes/fxa/android-redirect.html', // eslint-disable-line camelcase
|
||||
scope: 'profile https://identity.mozilla.com/apps/notes',
|
||||
},
|
||||
};
|
||||
|
||||
registerSuite('OAuth signin token code', {
|
||||
beforeEach: function () {
|
||||
// The `sync` prefix is needed to force confirmation.
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return this.remote
|
||||
.then(clearBrowserState({ forceAll: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'verified - invalid token': function () {
|
||||
experimentParams.query.forceExperiment = 'tokenCode';
|
||||
experimentParams.query.forceExperimentGroup = 'treatment-code';
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email', experimentParams))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
// This will cause the token become 'invalid' and ultimately cause an
|
||||
// INVALID_TOKEN error to be thrown.
|
||||
.then(destroySessionForEmail(email))
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'verified - valid code': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email', experimentParams))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// Displays invalid code errors
|
||||
.then(type(selectors.SIGNIN_TOKEN_CODE.INPUT, '000000'))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_TOKEN_CODE.SUBMIT,
|
||||
selectors.SIGNIN_TOKEN_CODE.TOOLTIP
|
||||
)
|
||||
)
|
||||
.then(visibleByQSA(selectors.SIGNIN_TOKEN_CODE.TOOLTIP))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SIGNIN_TOKEN_CODE.TOOLTIP,
|
||||
'Invalid or expired'
|
||||
)
|
||||
)
|
||||
// Can resend code
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_TOKEN_CODE.LINK_RESEND,
|
||||
selectors.SIGNIN_TOKEN_CODE.SUCCESS
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SIGNIN_TOKEN_CODE.SUCCESS,
|
||||
'Email resent.'
|
||||
)
|
||||
)
|
||||
|
||||
// Correctly submits the token code and navigates to oauth page
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
.then(getEmailHeaders(email, 1))
|
||||
.then((headers) => {
|
||||
assert.equal(headers['x-template-name'], 'verifyLoginCode');
|
||||
})
|
||||
.then(fillOutSignInTokenCode(email, 1))
|
||||
.then(testElementExists(NOTES_REDIRECT_PAGE_SELECTOR))
|
||||
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
NOTES_REDIRECT_PAGE_SELECTOR,
|
||||
NOTES_PAGE_TEXT_SELECTOR
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,100 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const PASSWORD = 'password12345678';
|
||||
const SUCCESS_URL = config.fxaContentRoot + 'oauth/success/dcdb5ae7add825d2';
|
||||
let email;
|
||||
let bouncedEmail;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
getFxaClient,
|
||||
noEmailExpected,
|
||||
openFxaFromRp,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testUrlInclude,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('oauth signup', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
bouncedEmail = createEmail();
|
||||
|
||||
// clear localStorage to avoid polluting other tests.
|
||||
// Without the clear, /signup tests fail because of the info stored
|
||||
// in prefillEmail
|
||||
return this.remote.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
signup: function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(testUrlInclude('client_id='))
|
||||
.then(testUrlInclude('redirect_uri='))
|
||||
.then(testUrlInclude('state='))
|
||||
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
|
||||
// Do not expect a post-verification email, those are for Sync.
|
||||
.then(noEmailExpected(email, 1))
|
||||
);
|
||||
},
|
||||
|
||||
'signup, bounce email, allow user to restart flow but force a different email':
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
.then(fillOutEmailFirstSignUp(bouncedEmail, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(function () {
|
||||
return getFxaClient().accountDestroy(bouncedEmail, PASSWORD);
|
||||
})
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
// expect an error message to already be present on redirect
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP_BOUNCED_EMAIL))
|
||||
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
);
|
||||
},
|
||||
|
||||
'a success screen is available': function () {
|
||||
return this.remote.then(
|
||||
openPage(SUCCESS_URL, '#fxa-oauth-success-header')
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,151 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const SYNC_EMAIL_FIRST_URL =
|
||||
config.fxaContentRoot + '?context=fx_desktop_v3&service=sync&action=email';
|
||||
|
||||
let email;
|
||||
let email2;
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
|
||||
const {
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignInTokenCode,
|
||||
fillOutSignUpCode,
|
||||
openFxaFromRp,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextEquals,
|
||||
testIsBrowserNotified,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('signin with OAuth after Sync', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
email2 = createEmail();
|
||||
|
||||
// clear localStorage to avoid pollution from other tests.
|
||||
return this.remote.then(
|
||||
FunctionalHelpers.clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'signin to OAuth with Sync creds': function () {
|
||||
this.timeout = 60 * 1000;
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(SYNC_EMAIL_FIRST_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
|
||||
// Sync signins must be verified.
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
// Sign up for a new account via OAuth
|
||||
.then(
|
||||
openFxaFromRp('enter-email', {
|
||||
header: selectors.SIGNIN_PASSWORD.HEADER,
|
||||
})
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
.then(fillOutEmailFirstSignUp(email2, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email2, 0))
|
||||
|
||||
// RP is logged in, logout then back in again.
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
|
||||
.then(visibleByQSA(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
.then(click(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
|
||||
// By default, we should see the email we signed up for Sync with
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
|
||||
// no need to enter the password!
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT))
|
||||
|
||||
// We should see the email we signed up for Sync with
|
||||
.then(
|
||||
testElementTextEquals(selectors['123DONE'].AUTHENTICATED, email)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('signin to Sync after OAuth', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
email2 = createEmail();
|
||||
|
||||
// clear localStorage to avoid pollution from other tests.
|
||||
return this.remote.then(
|
||||
FunctionalHelpers.clearBrowserState({
|
||||
'123done': true,
|
||||
contentServer: true,
|
||||
force: true,
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'email-first Sync signin': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openFxaFromRp('email-first', { header: selectors.ENTER_EMAIL.HEADER })
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementTextEquals(selectors['123DONE'].AUTHENTICATED, email))
|
||||
|
||||
.then(openPage(SYNC_EMAIL_FIRST_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
.then(fillOutSignInTokenCode(email, 1))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,78 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
var url = intern._config.fxaContentRoot;
|
||||
|
||||
// Commented out pages here likely mean the React version is rolled out to 100%
|
||||
// and we don't want to check these for `#stage header` selectors.
|
||||
var pages = [
|
||||
'',
|
||||
'authorization',
|
||||
'boom',
|
||||
'choose_what_to_sync',
|
||||
'complete_reset_password',
|
||||
'complete_signin',
|
||||
'confirm',
|
||||
'confirm_reset_password',
|
||||
'confirm_signin',
|
||||
'connect_another_device',
|
||||
'force_auth',
|
||||
'non_existent',
|
||||
'oauth',
|
||||
'oauth/force_auth',
|
||||
'oauth/signin',
|
||||
'oauth/signup',
|
||||
'report_signin',
|
||||
'reset_password',
|
||||
'reset_password_confirmed',
|
||||
'reset_password_complete', // redirects to reset_password_verified
|
||||
'reset_password_verified',
|
||||
'settings',
|
||||
'settings/avatar',
|
||||
'settings/change_password',
|
||||
'settings/clients',
|
||||
'settings/communication_preferences',
|
||||
'settings/delete_account',
|
||||
'settings/display_name',
|
||||
'signin',
|
||||
'signin_bounced',
|
||||
'signin_confirmed',
|
||||
'signin_complete', // redirects to signin_verified
|
||||
'signin_permissions',
|
||||
'signin_reported',
|
||||
'signin_unblock',
|
||||
'signin_verified',
|
||||
'signup',
|
||||
'signup_confirmed',
|
||||
'signup_complete', // redirects to signup_verified
|
||||
'signup_permissions',
|
||||
'signup_verified',
|
||||
'support',
|
||||
'verify_email',
|
||||
'v1/complete_reset_password',
|
||||
'v1/reset_password',
|
||||
'v1/verify_email',
|
||||
];
|
||||
|
||||
var suite = {};
|
||||
|
||||
var visitFn = function (path) {
|
||||
return function () {
|
||||
return this.remote
|
||||
.get(url + path)
|
||||
.setFindTimeout(intern._config.pageLoadTimeout)
|
||||
.findByCssSelector('#stage header')
|
||||
.end();
|
||||
};
|
||||
};
|
||||
|
||||
pages.forEach(function (path) {
|
||||
suite['visit page ' + url + path] = visitFn(path);
|
||||
suite['visit page ' + url + path + '/'] = visitFn(path + '/');
|
||||
});
|
||||
|
||||
registerSuite('pages', suite);
|
|
@ -1,326 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
//const assert = intern.getPlugin('chai').assert;
|
||||
const selectors = require('./lib/selectors');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const config = intern._config;
|
||||
|
||||
//const QUERY_PARAMS =
|
||||
('?context=fx_desktop_v3&service=sync&automatedBrowser=true&action=email');
|
||||
//const SIGNIN_PAGE_URL = `${config.fxaContentRoot}${QUERY_PARAMS}`;
|
||||
//const REDIRECT_HOST = encodeURIComponent(config.fxaContentRoot);
|
||||
const BAD_CLIENT_ID = 'dcdb5ae7add825d2';
|
||||
const BAD_OAUTH_REDIRECT = `${config.fxaOAuthApp}api/oauth`;
|
||||
//const GOOD_CLIENT_ID = '3c49430b43dfba77';
|
||||
////const GOOD_PAIR_URL = `${config.fxaContentRoot}pair/supp?response_type=code&client_id=${GOOD_CLIENT_ID}&redirect_uri=${REDIRECT_HOST}oauth%2Fsuccess%2F3c49430b43dfba77&scope=profile%2Bhttps%3A%2F%2Fidentity.mozilla.com%2Fapps%2Foldsync&state=foo&code_challenge_method=S256&code_challenge=IpOAcntLUmKITcxI_rDqMvFTeC9n_g0B8_Pj2yWZp7w&access_type=offline&keys_jwk=eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImlmcWY2U1pwMlM0ZjA5c3VhS093dmNsbWJxUm8zZXdGY0pvRURpYnc4MTQiLCJ5IjoiSE9LTXh5c1FseExqRGttUjZZbFpaY1Y4MFZBdk9nSWo1ZHRVaWJmYy1qTSJ9`; //eslint-disable-line max-len
|
||||
const BAD_PAIR_URL = `${config.fxaContentRoot}pair/supp?response_type=code&client_id=${BAD_CLIENT_ID}&redirect_uri=${BAD_OAUTH_REDIRECT}&scope=profile%2Bhttps%3A%2F%2Fidentity.mozilla.com%2Fapps%2Foldsync&state=foo&code_challenge_method=S256&code_challenge=IpOAcntLUmKITcxI_rDqMvFTeC9n_g0B8_Pj2yWZp7w&access_type=offline&keys_jwk=eyJjcnYiOiJQLTI1NiIsImt0eSI6IkVDIiwieCI6ImlmcWY2U1pwMlM0ZjA5c3VhS093dmNsbWJxUm8zZXdGY0pvRURpYnc4MTQiLCJ5IjoiSE9LTXh5c1FseExqRGttUjZZbFpaY1Y4MFZBdk9nSWo1ZHRVaWJmYy1qTSJ9`; //eslint-disable-line max-len
|
||||
//const SETTINGS_URL = `${config.fxaContentRoot}settings`;
|
||||
const DESKTOP_SIGNUP_URL = `${config.fxaContentRoot}signup?context=fx_desktop_v3&entrypoint=fxa_app_menu&service=sync`;
|
||||
|
||||
const PASSWORD = 'PASSWORD123123';
|
||||
let email;
|
||||
|
||||
const {
|
||||
createUser,
|
||||
clearBrowserState,
|
||||
click,
|
||||
//closeCurrentWindow,
|
||||
createEmail,
|
||||
//confirmTotpCode,
|
||||
enableTotp,
|
||||
generateTotpCode,
|
||||
openPage,
|
||||
//openTab,
|
||||
//switchToWindow,
|
||||
type,
|
||||
//thenify,
|
||||
testElementTextInclude,
|
||||
testElementExists,
|
||||
//testIsBrowserNotified,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
/*function getQrData(buffer) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const jsQR = require('jsqr');
|
||||
const png = require('upng-js');
|
||||
|
||||
try {
|
||||
const data = png.decode(buffer);
|
||||
const out = {
|
||||
data: new Uint8ClampedArray(png.toRGBA8(data)[0]),
|
||||
height: data.height,
|
||||
width: data.width,
|
||||
};
|
||||
|
||||
const code = jsQR(out.data, out.width, out.height);
|
||||
|
||||
if (code) {
|
||||
return resolve(code.data);
|
||||
} else {
|
||||
return reject('No QR code found');
|
||||
}
|
||||
} catch (e) {
|
||||
return reject('Failed to read QR code', e);
|
||||
}
|
||||
});
|
||||
}*/
|
||||
|
||||
/*const waitForQR = thenify(function () {
|
||||
let requestAttempts = 0;
|
||||
const maxAttempts = 5;
|
||||
const parent = this.parent;
|
||||
|
||||
function pollForScreenshot() {
|
||||
return parent
|
||||
.sleep(1500)
|
||||
.takeScreenshot()
|
||||
.then((buffer) => {
|
||||
return getQrData(buffer)
|
||||
.then((result) => {
|
||||
const pairingStuff = result.split('#')[1];
|
||||
return parent.then(
|
||||
openTab(
|
||||
GOOD_PAIR_URL + '#' + pairingStuff,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
requestAttempts++;
|
||||
if (requestAttempts >= maxAttempts) {
|
||||
return Promise.reject(new Error(`QRTimeout: ${err}`));
|
||||
} else {
|
||||
return new Promise(function (resolve, reject) {
|
||||
setTimeout(function () {
|
||||
pollForScreenshot().then(resolve, reject);
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return pollForScreenshot();
|
||||
});*/
|
||||
|
||||
registerSuite('pairing', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
//disabling this flaky test
|
||||
tests: {
|
||||
/*'it can pair': function () {
|
||||
let secret;
|
||||
email = createEmail();
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(SIGNIN_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.CONNECT_ANOTHER_DEVICE.HEADER
|
||||
)
|
||||
)
|
||||
// but the login message is sent automatically.
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
`${config.fxaContentRoot}pair`,
|
||||
selectors.PAIRING.START_PAIRING
|
||||
)
|
||||
)
|
||||
.then(click(selectors.PAIRING.START_PAIRING))
|
||||
|
||||
.then(waitForQR())
|
||||
|
||||
.then(switchToWindow(1))
|
||||
.then(click(selectors.PAIRING.SUPP_SUBMIT))
|
||||
.catch((err) => {
|
||||
if (err.message && err.message.includes('Web element reference')) {
|
||||
// We have to catch an error here due to https://bugzilla.mozilla.org/show_bug.cgi?id=1422769
|
||||
// .click still works, but just throws for no reason. We assert below that pairing still works.
|
||||
} else {
|
||||
// if this is an unknown error, then we throw
|
||||
throw err;
|
||||
}
|
||||
})
|
||||
.then(switchToWindow(0))
|
||||
.then(click(selectors.PAIRING.AUTH_SUBMIT))
|
||||
|
||||
.then(switchToWindow(1))
|
||||
.then(testElementExists(selectors.PAIRING.COMPLETE))
|
||||
|
||||
.getCurrentUrl()
|
||||
.then(function (redirectResult) {
|
||||
assert.ok(
|
||||
redirectResult.includes('code='),
|
||||
'final OAuth redirect has the code'
|
||||
);
|
||||
assert.ok(
|
||||
redirectResult.includes('state='),
|
||||
'final OAuth redirect has the state'
|
||||
);
|
||||
})
|
||||
.end()
|
||||
.then(closeCurrentWindow())
|
||||
|
||||
.then(openPage(SETTINGS_URL, selectors.TOTP.MENU_BUTTON))
|
||||
|
||||
.then(click(selectors.TOTP.MENU_BUTTON))
|
||||
.then(click(selectors.TOTP.SHOW_CODE_LINK))
|
||||
|
||||
.findByCssSelector(selectors.TOTP.MANUAL_CODE)
|
||||
.getVisibleText()
|
||||
.then((secretKey) => {
|
||||
secret = secretKey;
|
||||
})
|
||||
.then(() => this.remote.then(click(selectors.TOTP.KEY_OK_BUTTON)))
|
||||
.then(() => {
|
||||
return this.remote.then(confirmTotpCode(secret));
|
||||
})
|
||||
.end()
|
||||
.then(
|
||||
openPage(
|
||||
`${config.fxaContentRoot}pair`,
|
||||
selectors.PAIRING.START_PAIRING
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.PAIRING.START_PAIRING))
|
||||
|
||||
.then(waitForQR())
|
||||
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(click(selectors.PAIRING.SUPP_SUBMIT))
|
||||
.catch((err) => {
|
||||
if (err.message && err.message.includes('Web element reference')) {
|
||||
// We have to catch an error here due to https://bugzilla.mozilla.org/show_bug.cgi?id=1422769
|
||||
// .click still works, but just throws for no reason. We assert below that pairing still works.
|
||||
} else {
|
||||
// if this is an unknown error, then we throw
|
||||
throw err;
|
||||
}
|
||||
})
|
||||
.then(switchToWindow(0))
|
||||
|
||||
.then(() => {
|
||||
return this.remote.then(
|
||||
type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret))
|
||||
);
|
||||
})
|
||||
.then(click(selectors.TOTP_SIGNIN.SUBMIT))
|
||||
.then(click(selectors.PAIRING.AUTH_SUBMIT))
|
||||
|
||||
.then(switchToWindow(1))
|
||||
.then(testElementExists(selectors.PAIRING.COMPLETE))
|
||||
.getCurrentUrl()
|
||||
.then(function (redirectResult) {
|
||||
assert.ok(
|
||||
redirectResult.includes('code='),
|
||||
'final OAuth redirect has the code'
|
||||
);
|
||||
assert.ok(
|
||||
redirectResult.includes('state='),
|
||||
'final OAuth redirect has the state'
|
||||
);
|
||||
})
|
||||
.end()
|
||||
.then(closeCurrentWindow())
|
||||
);
|
||||
},*/
|
||||
|
||||
'handles invalid clients': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(
|
||||
`${BAD_PAIR_URL}#channel_id=foo&channel_key=bar`,
|
||||
selectors['400'].ERROR
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors['400'].ERROR,
|
||||
'Invalid pairing client'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'it shows qr code after sign in from fx desktop pre': function () {
|
||||
email = createEmail();
|
||||
let secret = '';
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(DESKTOP_SIGNUP_URL))
|
||||
.then(() =>
|
||||
this.remote.findAllByCssSelector(
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT
|
||||
)
|
||||
)
|
||||
.then((r) => r[0]?.click())
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT))
|
||||
.then(() => this.remote.sleep(100))
|
||||
.then(() => this.remote.acceptAlert())
|
||||
.catch(() => {})
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(selectors.SIGNIN_PASSWORD.SUBMIT, selectors.PAIRING.HEADER)
|
||||
)
|
||||
.then(testElementExists(selectors.PAIRING.CONNECT_ANOTHER_QR_CODE))
|
||||
|
||||
// also check that this works with 2FA enabled.
|
||||
.then(enableTotp())
|
||||
.then((_secret) => {
|
||||
secret = _secret;
|
||||
})
|
||||
.then(openPage(DESKTOP_SIGNUP_URL))
|
||||
.then(() =>
|
||||
this.remote.findAllByCssSelector(
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT
|
||||
)
|
||||
)
|
||||
.then((r) => r[0]?.click())
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT))
|
||||
.then(() => this.remote.sleep(100))
|
||||
.then(() => this.remote.acceptAlert())
|
||||
.catch(() => {})
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.TOTP_SIGNIN.HEADER
|
||||
)
|
||||
)
|
||||
// Correctly submits the totp code and navigates to oauth page
|
||||
.then(() => {
|
||||
return this.remote.then(
|
||||
type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret))
|
||||
);
|
||||
})
|
||||
.then(click(selectors.TOTP_SIGNIN.SUBMIT))
|
||||
.then(testElementExists(selectors.PAIRING.CONNECT_ANOTHER_QR_CODE))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,176 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const PAGE_URL = `${config.fxaContentRoot}?context=fx_desktop_v3&service=sync&action=email`; //eslint-disable-line max-len
|
||||
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
openPage,
|
||||
testElementExists,
|
||||
type,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('password strength balloon', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(openPage(PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNUP_PASSWORD.HEADER)
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'submit w/o a password': function () {
|
||||
return this.remote
|
||||
.then(click(selectors.SIGNUP_PASSWORD.SUBMIT))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.MIN_LENGTH_FAIL
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_EMAIL_UNMET
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_COMMON_UNMET
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'too short of a password': function () {
|
||||
return this.remote
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, 'p'))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.MIN_LENGTH_FAIL
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_EMAIL_UNMET
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_COMMON_UNMET
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'password is too common': function () {
|
||||
return this.remote
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, 'password'))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.MIN_LENGTH_MET
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_EMAIL_MET
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_COMMON_FAIL
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'password is the same as the full email': function () {
|
||||
return this.remote
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, email))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.MIN_LENGTH_MET
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_EMAIL_FAIL
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_COMMON_UNMET
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'password is same as the local part of the email': function () {
|
||||
return this.remote
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, email.split('@')[0]))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.MIN_LENGTH_MET
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_EMAIL_FAIL
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_COMMON_UNMET
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'good password, then back to too short': function () {
|
||||
return this.remote
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, 'password123123'))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.MIN_LENGTH_MET
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_EMAIL_MET
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_COMMON_MET
|
||||
)
|
||||
)
|
||||
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, 'pass'))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.MIN_LENGTH_FAIL
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_EMAIL_UNMET
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD_BALLOON.NOT_COMMON_UNMET
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,94 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
mousedown,
|
||||
noSuchAttribute,
|
||||
openPage,
|
||||
testAttributeEquals,
|
||||
testElementExists,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('password visibility', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
tests: {
|
||||
'show password ended with second mousedown': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, createEmail()))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNUP_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, 'p'))
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.SHOW_PASSWORD))
|
||||
.then(visibleByQSA(selectors.SIGNUP_PASSWORD.SHOW_PASSWORD))
|
||||
|
||||
// turn password field into a text field
|
||||
.then(mousedown(selectors.SIGNUP_PASSWORD.SHOW_PASSWORD))
|
||||
|
||||
.then(
|
||||
testAttributeEquals(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD,
|
||||
'type',
|
||||
'text'
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testAttributeEquals(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD,
|
||||
'autocomplete',
|
||||
'off'
|
||||
)
|
||||
)
|
||||
|
||||
// turn text field back into a password field
|
||||
.then(mousedown(selectors.SIGNUP_PASSWORD.SHOW_PASSWORD))
|
||||
|
||||
.then(
|
||||
testAttributeEquals(
|
||||
selectors.SIGNUP_PASSWORD.PASSWORD,
|
||||
'type',
|
||||
'password'
|
||||
)
|
||||
)
|
||||
.then(
|
||||
noSuchAttribute(selectors.SIGNUP_PASSWORD.PASSWORD, 'autocomplete')
|
||||
)
|
||||
|
||||
// \u0008 is unicode for backspace char. By default `type` clears the
|
||||
// element value before typing, we want the character to do so.
|
||||
.then(
|
||||
type(selectors.SIGNUP_PASSWORD.PASSWORD, '\u0008', {
|
||||
clearValue: true,
|
||||
})
|
||||
)
|
||||
// give a short pause to clear the input
|
||||
.sleep(1000)
|
||||
// element still exists
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.SHOW_PASSWORD))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,171 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./../lib/helpers');
|
||||
const selectors = require('./../lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const ACCOUNT_RECOVERY_URL =
|
||||
config.fxaContentRoot + 'post_verify/account_recovery/add_recovery_key';
|
||||
|
||||
const PASSWORD = 'password1234567';
|
||||
let email, recoveryKey;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testElementTextNotEmpty,
|
||||
testSuccessWasShown,
|
||||
testSuccessWasNotShown,
|
||||
thenify,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const getRecoveryKey = thenify(function () {
|
||||
return (
|
||||
this.parent
|
||||
// Extract the account recovery key from form
|
||||
.findByCssSelector(selectors.POST_VERIFY_SAVE_RECOVERY_KEY.RECOVERY_KEY)
|
||||
.getVisibleText()
|
||||
.then((key) => {
|
||||
recoveryKey = key;
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
registerSuite('post_verify_account_recovery', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'create account recovery': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(
|
||||
openPage(
|
||||
ACCOUNT_RECOVERY_URL,
|
||||
selectors.POST_VERIFY_ADD_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.POST_VERIFY_ADD_RECOVERY_KEY.SUBMIT,
|
||||
selectors.POST_VERIFY_CONFIRM_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
.then(testElementExists(selectors.POST_VERIFY_CONFIRM_PASSWORD.HEADER))
|
||||
|
||||
.then(type(selectors.POST_VERIFY_CONFIRM_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.POST_VERIFY_CONFIRM_PASSWORD.SUBMIT,
|
||||
selectors.POST_VERIFY_SAVE_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
.then(testElementExists(selectors.POST_VERIFY_SAVE_RECOVERY_KEY.HEADER))
|
||||
.then(
|
||||
testElementTextNotEmpty(
|
||||
selectors.POST_VERIFY_SAVE_RECOVERY_KEY.RECOVERY_KEY
|
||||
)
|
||||
)
|
||||
.then(getRecoveryKey())
|
||||
.then(() => {
|
||||
return this.remote
|
||||
.then(
|
||||
click(
|
||||
selectors.POST_VERIFY_SAVE_RECOVERY_KEY.DONE,
|
||||
selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
type(
|
||||
selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.RECOVERY_KEY,
|
||||
'INVALIDKEY'
|
||||
)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.SUBMIT,
|
||||
selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.TOOLTIP
|
||||
)
|
||||
)
|
||||
.then(
|
||||
visibleByQSA(selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.TOOLTIP)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.TOOLTIP,
|
||||
'Invalid account recovery key'
|
||||
)
|
||||
)
|
||||
.then(
|
||||
type(
|
||||
selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.RECOVERY_KEY,
|
||||
recoveryKey
|
||||
)
|
||||
)
|
||||
.then(click(selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.SUBMIT))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.POST_VERIFY_RECOVERY_KEY_VERIFIED.HEADER
|
||||
)
|
||||
)
|
||||
.then(click(selectors.POST_VERIFY_RECOVERY_KEY_VERIFIED.SUBMIT))
|
||||
.then(testSuccessWasShown('Account recovery enabled'));
|
||||
});
|
||||
},
|
||||
'abort account recovery at add_recovery_key': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(
|
||||
openPage(
|
||||
ACCOUNT_RECOVERY_URL,
|
||||
selectors.POST_VERIFY_ADD_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
.then(click(selectors.POST_VERIFY_ADD_RECOVERY_KEY.MAYBE_LATER))
|
||||
.then(testSuccessWasNotShown());
|
||||
},
|
||||
'abort account recovery at confirm_password': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(
|
||||
openPage(
|
||||
ACCOUNT_RECOVERY_URL,
|
||||
selectors.POST_VERIFY_ADD_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
.then(click(selectors.POST_VERIFY_ADD_RECOVERY_KEY.SUBMIT))
|
||||
.then(click(selectors.POST_VERIFY_CONFIRM_PASSWORD.MAYBE_LATER))
|
||||
.then(testSuccessWasNotShown());
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,96 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const { assert } = intern.getPlugin('chai');
|
||||
const FunctionalHelpers = require('./../lib/helpers');
|
||||
const selectors = require('./../lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?context=fx_desktop_v3&service=sync`;
|
||||
const CAD_QR_URL = `${config.fxaContentRoot}post_verify/cad_qr/get_started?context=fx_desktop_v3&service=sync`;
|
||||
|
||||
const PASSWORD = 'password1234567';
|
||||
const TEST_DEVICE_NAME = 'Test Runner Session Device';
|
||||
const TEST_DEVICE_TYPE = 'mobile';
|
||||
let email, accountData, client;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
openPage,
|
||||
testElementExists,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('cad_qr', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
client = FunctionalHelpers.getFxaClient();
|
||||
return this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then((result) => {
|
||||
accountData = result;
|
||||
});
|
||||
},
|
||||
|
||||
tests: {
|
||||
'CAD via QR code': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(
|
||||
openPage(
|
||||
CAD_QR_URL,
|
||||
selectors.POST_VERIFY_CAD_QR_GET_STARTED.HEADER
|
||||
)
|
||||
)
|
||||
.then(click(selectors.POST_VERIFY_CAD_QR_GET_STARTED.LATER))
|
||||
.getCurrentUrl()
|
||||
.then(function (url) {
|
||||
assert.isTrue(url.includes('mozilla.org'));
|
||||
})
|
||||
.goBack()
|
||||
.then(click(selectors.POST_VERIFY_CAD_QR_GET_STARTED.SUBMIT))
|
||||
|
||||
.then(click(selectors.POST_VERIFY_CAD_QR_READY_TO_SCAN.LATER))
|
||||
.getCurrentUrl()
|
||||
.then(function (url) {
|
||||
assert.isTrue(url.includes('mozilla.org'));
|
||||
})
|
||||
.goBack()
|
||||
.then(
|
||||
testElementExists(selectors.POST_VERIFY_CAD_QR_READY_TO_SCAN.HEADER)
|
||||
)
|
||||
.then(click(selectors.POST_VERIFY_CAD_QR_READY_TO_SCAN.SUBMIT))
|
||||
|
||||
.then(
|
||||
testElementExists(selectors.POST_VERIFY_CAD_QR_SCAN_CODE.HEADER)
|
||||
)
|
||||
|
||||
// This page will be polling for a new device record. This typically
|
||||
// happens when the user successfully authenticates on a new
|
||||
// device.
|
||||
.then(function () {
|
||||
return client.deviceRegister(
|
||||
accountData.sessionToken,
|
||||
TEST_DEVICE_NAME,
|
||||
TEST_DEVICE_TYPE
|
||||
);
|
||||
})
|
||||
|
||||
.then(
|
||||
testElementExists(selectors.POST_VERIFY_CAD_QR_CONNECTED.HEADER)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,108 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const { assert } = intern.getPlugin('chai');
|
||||
const FunctionalHelpers = require('./../lib/helpers');
|
||||
const selectors = require('./../lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const ForceChangePassword =
|
||||
config.fxaContentRoot + 'post_verify/password/force_password_change';
|
||||
|
||||
const ENTER_EMAIL_SYNC_URL = `${config.fxaContentRoot}?context=fx_desktop_v3&service=sync`;
|
||||
|
||||
const OAUTH_APP = config.fxaOAuthApp;
|
||||
|
||||
const PASSWORD = 'password1234567';
|
||||
const NEW_PASSWORD = '1234zxcvasdf';
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutForceChangePassword,
|
||||
fillOutSignInTokenCode,
|
||||
openFxaFromRp,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testIsBrowserNotified,
|
||||
thenify,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const testAtOAuthApp = thenify(function () {
|
||||
return this.parent
|
||||
.then(testElementExists(selectors['123DONE'].AUTHENTICATED))
|
||||
|
||||
.getCurrentUrl()
|
||||
.then(function (url) {
|
||||
// redirected back to the App
|
||||
assert.ok(url.indexOf(OAUTH_APP) > -1);
|
||||
});
|
||||
});
|
||||
|
||||
registerSuite('post_verify_force_password_change', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('forcepwdchange{id}');
|
||||
|
||||
return this.remote
|
||||
.then(clearBrowserState({ forceAll: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'navigate to page directly and can change password': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
.then(
|
||||
testElementExists(selectors.POST_VERIFY_FORCE_PASSWORD_CHANGE.HEADER)
|
||||
)
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
ForceChangePassword,
|
||||
selectors.POST_VERIFY_FORCE_PASSWORD_CHANGE.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutForceChangePassword(PASSWORD, NEW_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
'force change password on login - sync': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_SYNC_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
.then(
|
||||
testElementExists(selectors.POST_VERIFY_FORCE_PASSWORD_CHANGE.HEADER)
|
||||
)
|
||||
|
||||
.then(fillOutForceChangePassword(PASSWORD, NEW_PASSWORD))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER));
|
||||
},
|
||||
'force change password on login - oauth': function () {
|
||||
return this.remote
|
||||
.then(openFxaFromRp('enter-email'))
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
|
||||
.then(
|
||||
testElementExists(selectors.POST_VERIFY_FORCE_PASSWORD_CHANGE.HEADER)
|
||||
)
|
||||
|
||||
.then(fillOutForceChangePassword(PASSWORD, NEW_PASSWORD))
|
||||
.then(testAtOAuthApp());
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,77 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./../lib/helpers');
|
||||
const selectors = require('./../lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const Newsletters =
|
||||
config.fxaContentRoot + 'post_verify/newsletters/add_newsletters';
|
||||
|
||||
const PASSWORD = 'password1234567';
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('post_verify_newsletters', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'subscribe to newsletters': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
openPage(Newsletters, selectors.POST_VERIFY_ADD_NEWSLETTERS.HEADER, {})
|
||||
)
|
||||
|
||||
.then(
|
||||
click(selectors.POST_VERIFY_ADD_NEWSLETTERS.NEWSLETTERS.ONLINE_SAFETY)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.POST_VERIFY_ADD_NEWSLETTERS.NEWSLETTERS.HEALTHY_INTERNET
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.POST_VERIFY_ADD_NEWSLETTERS.SUBMIT,
|
||||
email
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.POST_VERIFY_ADD_NEWSLETTERS.DESCRIPTION,
|
||||
'Get practical knowledge in your inbox'
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.POST_VERIFY_ADD_NEWSLETTERS.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,98 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./../lib/helpers');
|
||||
const selectors = require('./../lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const ENTER_SECONDARY_EMAIL =
|
||||
config.fxaContentRoot + 'post_verify/secondary_email/add_secondary_email';
|
||||
|
||||
const PASSWORD = 'password1234567';
|
||||
let email, secondaryEmail;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutPostVerifySecondaryEmailCode,
|
||||
fillOutEmailFirstSignIn,
|
||||
openPage,
|
||||
testElementExists,
|
||||
type,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('post_verify_secondary_email', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
secondaryEmail = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'create secondary email': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
ENTER_SECONDARY_EMAIL,
|
||||
selectors.POST_VERIFY_ADD_SECONDARY_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
type(
|
||||
selectors.POST_VERIFY_ADD_SECONDARY_EMAIL.EMAIL,
|
||||
secondaryEmail
|
||||
)
|
||||
)
|
||||
.then(click(selectors.POST_VERIFY_ADD_SECONDARY_EMAIL.SUBMIT))
|
||||
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.POST_VERIFY_CONFIRM_SECONDARY_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
// Click `use different email` and verify you can
|
||||
.then(
|
||||
click(
|
||||
selectors.POST_VERIFY_CONFIRM_SECONDARY_EMAIL.USE_DIFFERENT_EMAIL
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(selectors.POST_VERIFY_ADD_SECONDARY_EMAIL.HEADER)
|
||||
)
|
||||
.then(
|
||||
type(
|
||||
selectors.POST_VERIFY_ADD_SECONDARY_EMAIL.EMAIL,
|
||||
secondaryEmail
|
||||
)
|
||||
)
|
||||
.then(click(selectors.POST_VERIFY_ADD_SECONDARY_EMAIL.SUBMIT))
|
||||
|
||||
// Complete the email verification flow
|
||||
.then(fillOutPostVerifySecondaryEmailCode(secondaryEmail, 1))
|
||||
|
||||
.then(testElementExists(selectors.POST_VERIFY_VERIFIED.READY))
|
||||
|
||||
.then(click(selectors.POST_VERIFY_VERIFIED.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,49 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const ENTER_EMAIL_URL = intern._config.fxaContentRoot;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
openPage,
|
||||
type,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('privacy policy', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'from signup': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, createEmail()))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNUP_PASSWORD.HEADER)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.PRIVACY_POLICY,
|
||||
selectors.PRIVACY_POLICY.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.PRIVACY_POLICY.LINK_BACK,
|
||||
selectors.SIGNUP_PASSWORD.HEADER
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,71 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const QUERY_PARAMS = '?context=fx_desktop_v3&service=sync&action=email';
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}${QUERY_PARAMS}`;
|
||||
|
||||
const PASSWORD = 'password1234567';
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
openPage,
|
||||
testElementExists,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('push_login', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'verify login via push - treatment': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceExperiment: 'pushLogin',
|
||||
forceExperimentGroup: 'treatment',
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.PUSH_VERIFY_LOGIN.HEADER))
|
||||
|
||||
.then(click(selectors.PUSH_VERIFY_LOGIN.RESEND))
|
||||
.then(click(selectors.PUSH_VERIFY_LOGIN.SEND_EMAIL))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER));
|
||||
},
|
||||
control: function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceExperiment: 'pushLogin',
|
||||
forceExperimentGroup: 'control',
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,43 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
var AUTOMATED = '?automatedBrowser=true';
|
||||
var ENTER_EMAIL_URL = intern._config.fxaContentRoot + AUTOMATED;
|
||||
|
||||
var clearBrowserState = FunctionalHelpers.clearBrowserState;
|
||||
var openPage = FunctionalHelpers.openPage;
|
||||
var testAreEventsLogged = FunctionalHelpers.testAreEventsLogged;
|
||||
var testElementExists = FunctionalHelpers.testElementExists;
|
||||
|
||||
registerSuite('refreshing a screen logs a refresh event', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
tests: {
|
||||
'refreshing the enter_email screen': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
.refresh()
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
// Unload the page to flush the metrics
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(
|
||||
testAreEventsLogged([
|
||||
'screen.enter-email',
|
||||
'screen.enter-email',
|
||||
'signup.refresh',
|
||||
])
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,629 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_PAGE_URL = config.fxaContentRoot;
|
||||
const RESET_PAGE_URL = config.fxaContentRoot + 'reset_password';
|
||||
const CONFIRM_PAGE_URL = config.fxaContentRoot + 'confirm_reset_password';
|
||||
const COMPLETE_PAGE_URL_ROOT =
|
||||
config.fxaContentRoot + 'complete_reset_password';
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
const TIMEOUT = 90 * 1000;
|
||||
|
||||
let client;
|
||||
let code;
|
||||
let email;
|
||||
let token;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
closeCurrentWindow,
|
||||
createEmail,
|
||||
createRandomHexString,
|
||||
createUser,
|
||||
fillOutCompleteResetPassword,
|
||||
fillOutResetPassword,
|
||||
getFxaClient,
|
||||
getVerificationLink,
|
||||
noSuchElement,
|
||||
openExternalSite,
|
||||
openPage,
|
||||
openPasswordResetLinkInDifferentBrowser,
|
||||
openVerificationLinkInNewTab,
|
||||
openVerificationLinkInSameTab,
|
||||
switchToWindow,
|
||||
testElementExists,
|
||||
testElementValueEquals,
|
||||
testEmailExpected,
|
||||
testSuccessWasShown,
|
||||
thenify,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
/**
|
||||
* Programatically initiate a reset password using the
|
||||
* FxA Client. Saves the token and code.
|
||||
*/
|
||||
const initiateResetPassword = thenify(function (emailAddress, emailNumber) {
|
||||
return this.parent
|
||||
.then(() => client.passwordForgotSendCode(emailAddress))
|
||||
.then(getVerificationLink(emailAddress, emailNumber))
|
||||
.then((link) => {
|
||||
// token and code are hex values
|
||||
token = link.match(/token=([a-f\d]+)/)[1];
|
||||
code = link.match(/code=([a-f\d]+)/)[1];
|
||||
});
|
||||
});
|
||||
|
||||
const openCompleteResetPassword = thenify(function (
|
||||
email,
|
||||
token,
|
||||
code,
|
||||
header
|
||||
) {
|
||||
let url = COMPLETE_PAGE_URL_ROOT + '?';
|
||||
|
||||
const queryParams = [];
|
||||
if (email) {
|
||||
queryParams.push('email=' + encodeURIComponent(email));
|
||||
}
|
||||
|
||||
if (token) {
|
||||
queryParams.push('token=' + encodeURIComponent(token));
|
||||
}
|
||||
|
||||
if (code) {
|
||||
queryParams.push('code=' + encodeURIComponent(code));
|
||||
}
|
||||
|
||||
url += queryParams.join('&');
|
||||
return this.parent.then(openPage(url, header));
|
||||
});
|
||||
|
||||
const testAtSettingsWithVerifiedMessage = thenify(function () {
|
||||
return this.parent
|
||||
.setFindTimeout(intern._config.pageLoadTimeout)
|
||||
.sleep(1000)
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
// TODO: https://github.com/mozilla/fxa/issues/7882
|
||||
// .then(testSuccessWasShown());
|
||||
});
|
||||
|
||||
const testAtSettings = thenify(function () {
|
||||
return this.parent
|
||||
.setFindTimeout(intern._config.pageLoadTimeout)
|
||||
.sleep(1000)
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
});
|
||||
|
||||
registerSuite('reset_password', {
|
||||
beforeEach: function () {
|
||||
this.timeout = TIMEOUT;
|
||||
|
||||
email = createEmail();
|
||||
return this.remote
|
||||
.then(() => getFxaClient())
|
||||
.then((_client) => {
|
||||
client = _client;
|
||||
})
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState());
|
||||
},
|
||||
tests: {
|
||||
'visit confirmation screen without initiating reset_password, user is redirected to /reset_password': function () {
|
||||
// user is immediately redirected to /reset_password if they have no
|
||||
// sessionToken.
|
||||
// Success is showing the screen
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(CONFIRM_PAGE_URL, selectors.RESET_PASSWORD.HEADER))
|
||||
// There was an error were users who browsed directly to /confirm_reset_password were
|
||||
// displayed the 400 page. The user should not see the error but should be allowed
|
||||
// to fill out their email address. See #6724
|
||||
.then(noSuchElement(selectors['400'].HEADER, 5000))
|
||||
);
|
||||
},
|
||||
|
||||
'open /reset_password page from /signin': function () {
|
||||
const updatedEmail = createEmail();
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD.HEADER))
|
||||
// email should not be pre-filled
|
||||
.then(testElementValueEquals(selectors.RESET_PASSWORD.EMAIL, ''))
|
||||
// go back, ensure the email address is still pre-filled on the signin page.
|
||||
.then(click(selectors.RESET_PASSWORD.LINK_SIGNIN))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD))
|
||||
|
||||
// update the email in the reset_password form, go back, ensure the
|
||||
// change is reflected in the /signin page
|
||||
.then(testElementExists(selectors.RESET_PASSWORD.HEADER))
|
||||
.then(testElementValueEquals(selectors.RESET_PASSWORD.EMAIL, ''))
|
||||
.then(type(selectors.RESET_PASSWORD.EMAIL, updatedEmail))
|
||||
.then(click(selectors.RESET_PASSWORD.LINK_SIGNIN))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(
|
||||
testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, updatedEmail)
|
||||
)
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD.HEADER))
|
||||
.then(testElementValueEquals(selectors.RESET_PASSWORD.EMAIL, ''))
|
||||
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
//Check email resent for reset password
|
||||
.then(click(selectors.CONFIRM_RESET_PASSWORD.LINK_RESEND))
|
||||
|
||||
//Confirm the success message for resend email
|
||||
.then(visibleByQSA(selectors.CONFIRM_RESET_PASSWORD.RESEND_SUCCESS))
|
||||
|
||||
//continue to sign in again
|
||||
.then(click(selectors.CONFIRM_RESET_PASSWORD.LINK_SIGNIN))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'enter an email with leading whitespace': function () {
|
||||
return this.remote
|
||||
.then(fillOutResetPassword(' ' + email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER));
|
||||
},
|
||||
|
||||
'enter an email with trailing whitespace': function () {
|
||||
return this.remote
|
||||
.then(fillOutResetPassword(email + ' '))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER));
|
||||
},
|
||||
|
||||
'open confirm_reset_password page, click resend': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(click(selectors.CONFIRM_RESET_PASSWORD.LINK_RESEND))
|
||||
|
||||
.then(testEmailExpected(email, 1))
|
||||
|
||||
// Success is showing the success message
|
||||
.then(
|
||||
testSuccessWasShown(
|
||||
'Email resent. Add accounts@firefox.com to your contacts to ensure a smooth delivery.',
|
||||
'.success[data-shown]'
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.CONFIRM_RESET_PASSWORD.LINK_RESEND))
|
||||
.then(click(selectors.CONFIRM_RESET_PASSWORD.LINK_RESEND))
|
||||
|
||||
// Stills shows success message
|
||||
//
|
||||
// this uses .visibleByQSA instead of testSuccessWasShown because
|
||||
// the element is not re-shown, but rather should continue to
|
||||
// be visible.
|
||||
.then(visibleByQSA(selectors.CONFIRM_RESET_PASSWORD.RESEND_SUCCESS))
|
||||
);
|
||||
},
|
||||
|
||||
'open complete page with missing token shows damaged screen': function () {
|
||||
return this.remote
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
email,
|
||||
null,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.DAMAGED_LINK_HEADER
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'open complete page with malformed token shows damaged screen': function () {
|
||||
return this.remote
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(function () {
|
||||
const malformedToken = createRandomHexString(token.length - 1);
|
||||
return openCompleteResetPassword(
|
||||
email,
|
||||
malformedToken,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.DAMAGED_LINK_HEADER
|
||||
).call(this);
|
||||
});
|
||||
},
|
||||
|
||||
'open complete page with invalid token shows expired screen': function () {
|
||||
return this.remote
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(function () {
|
||||
const invalidToken = createRandomHexString(token.length);
|
||||
return openCompleteResetPassword(
|
||||
email,
|
||||
invalidToken,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.EXPIRED_LINK_HEADER
|
||||
).call(this);
|
||||
});
|
||||
},
|
||||
|
||||
'open complete page with empty token shows damaged screen': function () {
|
||||
return this.remote
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
email,
|
||||
'',
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.DAMAGED_LINK_HEADER
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'open complete page with missing code shows damaged screen': function () {
|
||||
return this.remote
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
email,
|
||||
token,
|
||||
null,
|
||||
selectors.COMPLETE_RESET_PASSWORD.DAMAGED_LINK_HEADER
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'open complete page with empty code shows damaged screen': function () {
|
||||
return this.remote
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
email,
|
||||
token,
|
||||
'',
|
||||
selectors.COMPLETE_RESET_PASSWORD.DAMAGED_LINK_HEADER
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'open complete page with malformed code shows damaged screen': function () {
|
||||
return this.remote
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(function () {
|
||||
const malformedCode = createRandomHexString(code.length - 1);
|
||||
return openCompleteResetPassword(
|
||||
email,
|
||||
token,
|
||||
malformedCode,
|
||||
selectors.COMPLETE_RESET_PASSWORD.DAMAGED_LINK_HEADER
|
||||
).call(this);
|
||||
});
|
||||
},
|
||||
|
||||
'open complete page with missing email shows damaged screen': function () {
|
||||
return this.remote
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
null,
|
||||
token,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.DAMAGED_LINK_HEADER
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'open complete page with empty email shows damaged screen': function () {
|
||||
return this.remote
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
'',
|
||||
token,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.DAMAGED_LINK_HEADER
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'open complete page with malformed email shows damaged screen': function () {
|
||||
return this.remote.then(initiateResetPassword(email, 0)).then(
|
||||
openCompleteResetPassword(
|
||||
'invalidemail',
|
||||
token,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.DAMAGED_LINK_HEADER // #fxa-reset-link-damaged-header
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'reset password, verify same browser': function () {
|
||||
this.timeout = TIMEOUT;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
.then(openVerificationLinkInNewTab(email, 0))
|
||||
|
||||
// Complete the reset password in the new tab
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
// this tab's success is seeing the reset password complete header.
|
||||
.then(testAtSettingsWithVerifiedMessage())
|
||||
|
||||
.then(closeCurrentWindow())
|
||||
|
||||
.then(testAtSettings())
|
||||
);
|
||||
},
|
||||
|
||||
'reset password, verify same browser with original tab closed': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
// user browses to another site.
|
||||
.then(openExternalSite())
|
||||
.then(openVerificationLinkInNewTab(email, 0))
|
||||
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
// this tab's success is seeing the reset password complete header.
|
||||
.then(testAtSettingsWithVerifiedMessage())
|
||||
|
||||
// switch to the original window
|
||||
.then(closeCurrentWindow())
|
||||
);
|
||||
},
|
||||
|
||||
'reset password, verify same browser by replacing the original tab': function () {
|
||||
this.timeout = 90 * 1000;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(openVerificationLinkInSameTab(email, 0))
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
// this tab's success is seeing the reset password complete header.
|
||||
.then(testAtSettingsWithVerifiedMessage())
|
||||
);
|
||||
},
|
||||
|
||||
"reset password, verify in a different browser, from the original tab's P.O.V.": function () {
|
||||
this.timeout = 90 * 1000;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(openPasswordResetLinkInDifferentBrowser(email, PASSWORD))
|
||||
|
||||
// user verified in a new browser, they have to enter
|
||||
// their updated credentials in the original tab.
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(
|
||||
testSuccessWasShown(
|
||||
'Password reset successfully. Sign in to continue.',
|
||||
'.success[data-shown]'
|
||||
)
|
||||
)
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT))
|
||||
|
||||
// no success message, the user should have seen that above.
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
"reset password, verify in a different browser, from the new browser's P.O.V.": function () {
|
||||
this.timeout = 90 * 1000;
|
||||
return (
|
||||
this.remote
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
// clear all browser state, simulate opening in
|
||||
// a new browser
|
||||
.then(clearBrowserState({ contentServer: true }))
|
||||
|
||||
.then(openVerificationLinkInSameTab(email, 0))
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
.then(testAtSettingsWithVerifiedMessage())
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('try to re-use a link', {
|
||||
beforeEach: function () {
|
||||
this.timeout = TIMEOUT;
|
||||
email = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(initiateResetPassword(email, 0))
|
||||
.then(clearBrowserState());
|
||||
},
|
||||
tests: {
|
||||
'complete reset, then re-open verification link, click resend': function () {
|
||||
this.timeout = TIMEOUT;
|
||||
|
||||
return this.remote
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
email,
|
||||
token,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
email,
|
||||
token,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.EXPIRED_LINK_HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.CONFIRM_RESET_PASSWORD.LINK_RESEND))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('reset_password with email specified on URL', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState());
|
||||
},
|
||||
tests: {
|
||||
'browse directly to page with email on query params': function () {
|
||||
const url = RESET_PAGE_URL + '?email=' + email;
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(url, selectors.RESET_PASSWORD.HEADER))
|
||||
// email address should not be pre-filled from the query param.
|
||||
.then(testElementValueEquals(selectors.RESET_PASSWORD.EMAIL, ''))
|
||||
// ensure there is no back button when browsing directly to page
|
||||
.then(noSuchElement(selectors.RESET_PASSWORD.BACK))
|
||||
// fill in email
|
||||
.then(type(selectors.RESET_PASSWORD.EMAIL, email))
|
||||
.then(click(selectors.RESET_PASSWORD.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('password change while at confirm_reset_password screen', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(() => getFxaClient())
|
||||
.then((_client) => {
|
||||
client = _client;
|
||||
})
|
||||
.then(clearBrowserState());
|
||||
},
|
||||
tests: {
|
||||
'original page transitions after completion': function () {
|
||||
return this.remote
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(function () {
|
||||
return client.signIn(email, PASSWORD);
|
||||
})
|
||||
.then(function (accountInfo) {
|
||||
return client.passwordChange(email, PASSWORD, 'newpassword', {
|
||||
sessionToken: accountInfo.sessionToken,
|
||||
});
|
||||
})
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('reset_password with unknown email', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
tests: {
|
||||
'open /reset_password page, enter unknown email, wait for error': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(fillOutResetPassword(email))
|
||||
// The error area shows a link to /signup
|
||||
.then(visibleByQSA(selectors.RESET_PASSWORD.ERROR))
|
||||
|
||||
.then(click(selectors.RESET_PASSWORD.LINK_ERROR_SIGNUP))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
// check the email address was written
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,202 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const config = intern._config;
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutCompleteResetPassword,
|
||||
fillOutEmailFirstSignIn,
|
||||
getFxaClient,
|
||||
getVerificationLink,
|
||||
noSuchElement,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
thenify,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const SECURITY_EVENTS_URL = `${config.fxaContentRoot}security_events`;
|
||||
const COMPLETE_PAGE_URL_ROOT =
|
||||
config.fxaContentRoot + 'complete_reset_password';
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
|
||||
let client;
|
||||
let code;
|
||||
let email;
|
||||
let token;
|
||||
|
||||
const initiateResetPassword = thenify(function (emailAddress, emailNumber) {
|
||||
client = getFxaClient();
|
||||
|
||||
return this.parent
|
||||
.then(() => client.passwordForgotSendCode(emailAddress))
|
||||
.then(getVerificationLink(emailAddress, emailNumber))
|
||||
.then((link) => {
|
||||
// token and code are hex values
|
||||
token = link.match(/token=([a-f\d]+)/)[1];
|
||||
code = link.match(/code=([a-f\d]+)/)[1];
|
||||
});
|
||||
});
|
||||
|
||||
const openCompleteResetPassword = thenify(function (
|
||||
email,
|
||||
token,
|
||||
code,
|
||||
header
|
||||
) {
|
||||
let url = COMPLETE_PAGE_URL_ROOT + '?';
|
||||
|
||||
const queryParams = [];
|
||||
if (email) {
|
||||
queryParams.push('email=' + encodeURIComponent(email));
|
||||
}
|
||||
|
||||
if (token) {
|
||||
queryParams.push('token=' + encodeURIComponent(token));
|
||||
}
|
||||
|
||||
if (code) {
|
||||
queryParams.push('code=' + encodeURIComponent(code));
|
||||
}
|
||||
|
||||
url += queryParams.join('&');
|
||||
return this.parent.then(openPage(url, header));
|
||||
});
|
||||
|
||||
registerSuite('security_events', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(clearBrowserState({ forceAll: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(initiateResetPassword(email, 0));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'gets security events table': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD, true))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
SECURITY_EVENTS_URL,
|
||||
selectors.SECURITY_EVENTS.RECENT_ACTIVITY_HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(selectors.SECURITY_EVENTS.SECURITY_EVENTS_HEADER)
|
||||
);
|
||||
},
|
||||
|
||||
'login event is shown': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD, true))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
SECURITY_EVENTS_URL,
|
||||
selectors.SECURITY_EVENTS.RECENT_ACTIVITY_HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SECURITY_EVENTS.FIRST_EVENT_NAME,
|
||||
'account.login'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'reset event is shown': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
email,
|
||||
token,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
openCompleteResetPassword(
|
||||
email,
|
||||
token,
|
||||
code,
|
||||
selectors.COMPLETE_RESET_PASSWORD.EXPIRED_LINK_HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
click(
|
||||
selectors.CONFIRM_RESET_PASSWORD.LINK_RESEND,
|
||||
selectors.CONFIRM_RESET_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
SECURITY_EVENTS_URL,
|
||||
selectors.SECURITY_EVENTS.RECENT_ACTIVITY_HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SECURITY_EVENTS.EVENT_TABLE,
|
||||
'account.reset'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'delete security events': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD, true))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
SECURITY_EVENTS_URL,
|
||||
selectors.SECURITY_EVENTS.RECENT_ACTIVITY_HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SECURITY_EVENTS.FIRST_EVENT_NAME,
|
||||
'account.login'
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(selectors.SECURITY_EVENTS.DELETE_EVENTS_BUTTON)
|
||||
)
|
||||
.then(click(selectors.SECURITY_EVENTS.DELETE_EVENTS_BUTTON))
|
||||
|
||||
// reload the page to verify that all the security events have been deleted
|
||||
.refresh()
|
||||
.then(noSuchElement(selectors.SECURITY_EVENTS.SECURITY_EVENT))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,285 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('../lib/helpers');
|
||||
const selectors = require('../lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
const NEW_PASSWORD = 'passwordzxcv1';
|
||||
|
||||
let email;
|
||||
let secondaryEmail;
|
||||
let newPrimaryEmail;
|
||||
|
||||
const {
|
||||
addAndVerifySecondaryEmail,
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
fillOutDeleteAccount,
|
||||
fillOutChangePassword,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutSignInUnblock,
|
||||
fillOutSignUpCode,
|
||||
openPage,
|
||||
signOut,
|
||||
testElementExists,
|
||||
testElementTextEquals,
|
||||
testElementTextInclude,
|
||||
testErrorTextInclude,
|
||||
testSuccessWasShown,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('settings change email', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
secondaryEmail = createEmail();
|
||||
return (
|
||||
this.remote
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(visibleByQSA(selectors.SETTINGS.PROFILE_HEADER))
|
||||
.then(click(selectors.EMAIL.MENU_BUTTON))
|
||||
|
||||
.then(addAndVerifySecondaryEmail(secondaryEmail))
|
||||
.then(testSuccessWasShown())
|
||||
|
||||
// set new primary email
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.MAKE_PRIMARY,
|
||||
selectors.EMAIL.SUCCESS
|
||||
)
|
||||
)
|
||||
.then(visibleByQSA(selectors.EMAIL.SUCCESS))
|
||||
|
||||
.then(
|
||||
testElementTextEquals(selectors.EMAIL.ADDRESS_LABEL, secondaryEmail)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'can change primary email and login': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(signOut())
|
||||
|
||||
// sign in with old primary email fails
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testErrorTextInclude('Primary account email required'))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
// sign in with new primary email
|
||||
.then(fillOutEmailFirstSignIn(secondaryEmail, PASSWORD))
|
||||
|
||||
// shows new primary email
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SETTINGS.PROFILE_HEADER,
|
||||
secondaryEmail
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'can change primary email, change password and login': function () {
|
||||
return (
|
||||
this.remote
|
||||
// change password
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
.then(fillOutChangePassword(PASSWORD, NEW_PASSWORD))
|
||||
|
||||
// sign out and fails login with old password
|
||||
.then(signOut())
|
||||
.then(fillOutEmailFirstSignIn(secondaryEmail, PASSWORD))
|
||||
.then(visibleByQSA(selectors.SIGNIN_PASSWORD.TOOLTIP))
|
||||
|
||||
// sign in with new password
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, NEW_PASSWORD))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SETTINGS.PROFILE_HEADER,
|
||||
secondaryEmail
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'can change primary email, change password, login, change email and login': function () {
|
||||
return (
|
||||
this.remote
|
||||
// change password
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
.then(fillOutChangePassword(PASSWORD, NEW_PASSWORD))
|
||||
|
||||
// sign out and fails login with old password
|
||||
.then(signOut())
|
||||
.then(fillOutEmailFirstSignIn(secondaryEmail, PASSWORD))
|
||||
.then(visibleByQSA(selectors.SIGNIN_PASSWORD.TOOLTIP))
|
||||
|
||||
// sign in with new password
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(secondaryEmail, NEW_PASSWORD))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SETTINGS.PROFILE_HEADER,
|
||||
secondaryEmail
|
||||
)
|
||||
)
|
||||
|
||||
// set primary email to original email
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.HEADER_VALUE,
|
||||
email
|
||||
)
|
||||
)
|
||||
.then(click(selectors.EMAIL.SET_PRIMARY_EMAIL_BUTTON))
|
||||
.then(visibleByQSA(selectors.EMAIL.SUCCESS))
|
||||
|
||||
// sign out and login with new password
|
||||
.then(signOut())
|
||||
.then(fillOutEmailFirstSignIn(email, NEW_PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'can change primary email, delete account': function () {
|
||||
return (
|
||||
this.remote
|
||||
// go to delete account screen
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS_DELETE_ACCOUNT.DELETE_ACCOUNT_BUTTON,
|
||||
selectors.SETTINGS_DELETE_ACCOUNT.DETAILS
|
||||
)
|
||||
)
|
||||
// enter correct password for deleting account
|
||||
.then(fillOutDeleteAccount(PASSWORD))
|
||||
|
||||
// Try creating a new account with the same secondary email as previous account and new password
|
||||
.then(fillOutEmailFirstSignUp(secondaryEmail, NEW_PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(secondaryEmail, 3))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
// Verify that user can add the same primary email as secondary as used in the previous account
|
||||
.then(click(selectors.EMAIL.MENU_BUTTON))
|
||||
.then(addAndVerifySecondaryEmail(email, 3))
|
||||
.then(testSuccessWasShown())
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('settings change email - unblock', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
// Create a new primary email that is always forced through the unblock flow
|
||||
newPrimaryEmail = createEmail('blocked{id}');
|
||||
return (
|
||||
this.remote
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(click(selectors.EMAIL.MENU_BUTTON))
|
||||
|
||||
.then(addAndVerifySecondaryEmail(newPrimaryEmail))
|
||||
.then(testSuccessWasShown())
|
||||
|
||||
// set new primary email
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.MAKE_PRIMARY,
|
||||
selectors.EMAIL.SUCCESS
|
||||
)
|
||||
)
|
||||
.then(visibleByQSA(selectors.EMAIL.SUCCESS))
|
||||
|
||||
.then(
|
||||
testElementTextEquals(selectors.EMAIL.ADDRESS_LABEL, newPrimaryEmail)
|
||||
)
|
||||
|
||||
// sign out
|
||||
.then(signOut())
|
||||
);
|
||||
},
|
||||
|
||||
afterEach: function () {
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'can change primary email, get blocked with invalid password, redirect enter password page': function () {
|
||||
return (
|
||||
this.remote
|
||||
// sign in
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(newPrimaryEmail, 'INVALID_PASSWORD'))
|
||||
|
||||
// fill out unblock
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SIGNIN_UNBLOCK.VERIFICATION,
|
||||
newPrimaryEmail
|
||||
)
|
||||
)
|
||||
.then(fillOutSignInUnblock(newPrimaryEmail, 3))
|
||||
|
||||
// redirected to correct password
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'can change primary email, get blocked with valid password, redirect settings page': function () {
|
||||
return (
|
||||
this.remote
|
||||
// sign in
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(newPrimaryEmail, PASSWORD))
|
||||
|
||||
// fill out unblock
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SIGNIN_UNBLOCK.VERIFICATION,
|
||||
newPrimaryEmail
|
||||
)
|
||||
)
|
||||
.then(fillOutSignInUnblock(newPrimaryEmail, 3))
|
||||
|
||||
// redirected to settings
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,247 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('../lib/helpers');
|
||||
const selectors = require('../lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
|
||||
const ANIMATION_DELAY_MS = 500;
|
||||
const FIRST_PASSWORD = 'password';
|
||||
const SECOND_PASSWORD = 'new_password';
|
||||
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
denormalizeStoredEmail,
|
||||
fillOutChangePassword,
|
||||
fillOutEmailFirstSignIn,
|
||||
noSuchElement,
|
||||
openPage,
|
||||
pollUntilHiddenByQSA,
|
||||
testElementExists,
|
||||
testElementTextEquals,
|
||||
thenify,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const setupTest = thenify(function (options = {}) {
|
||||
const signUpEmail = options.signUpEmail || email;
|
||||
const signInEmail = options.signInEmail || email;
|
||||
|
||||
return this.parent
|
||||
.then(createUser(signUpEmail, FIRST_PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(signInEmail, FIRST_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(
|
||||
testElementTextEquals(selectors.SETTINGS.PROFILE_HEADER, signUpEmail)
|
||||
);
|
||||
});
|
||||
|
||||
registerSuite('change password', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
},
|
||||
|
||||
tests: {
|
||||
'try to change password with an incorrect old password': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest())
|
||||
|
||||
// Go to change password screen
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
.then(
|
||||
fillOutChangePassword('INCORRECT', SECOND_PASSWORD, {
|
||||
expectSuccess: false,
|
||||
})
|
||||
)
|
||||
// the validation tooltip should be visible
|
||||
.then(visibleByQSA(selectors.CHANGE_PASSWORD.TOOLTIP))
|
||||
|
||||
// Change form so that it is valid, error should be hidden.
|
||||
.then(type(selectors.CHANGE_PASSWORD.OLD_PASSWORD, FIRST_PASSWORD))
|
||||
.then(noSuchElement(selectors.CHANGE_PASSWORD.TOOLTIP))
|
||||
);
|
||||
},
|
||||
|
||||
'try to change password with short password, tooltip shows, cancel, try to change password again, tooltip is not shown': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest())
|
||||
|
||||
// Go to change password screen
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
.then(
|
||||
fillOutChangePassword('A', SECOND_PASSWORD, {
|
||||
expectSuccess: false,
|
||||
})
|
||||
)
|
||||
// the validation tooltip should be visible
|
||||
.then(visibleByQSA(selectors.CHANGE_PASSWORD.TOOLTIP))
|
||||
// click the cancel button
|
||||
.then(click(selectors.CHANGE_PASSWORD.CANCEL_BUTTON))
|
||||
.sleep(ANIMATION_DELAY_MS)
|
||||
// try to change password again
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
// check no tooltip exists
|
||||
.then(noSuchElement(selectors.CHANGE_PASSWORD.TOOLTIP))
|
||||
);
|
||||
},
|
||||
|
||||
'new_password validation': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest())
|
||||
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
|
||||
// new_password empty
|
||||
.then(click(selectors.CHANGE_PASSWORD.OLD_PASSWORD_LABEL))
|
||||
.then(type(selectors.CHANGE_PASSWORD.OLD_PASSWORD, FIRST_PASSWORD))
|
||||
.then(
|
||||
testElementExists(selectors.SETTINGS.CHANGE_PASSWORD.UNSET_LENGTH)
|
||||
)
|
||||
|
||||
// new_password too short
|
||||
.then(click(selectors.CHANGE_PASSWORD.NEW_PASSWORD_LABEL))
|
||||
.then(type(selectors.CHANGE_PASSWORD.NEW_PASSWORD, 'pass'))
|
||||
.then(
|
||||
testElementExists(selectors.SETTINGS.CHANGE_PASSWORD.INVALID_LENGTH)
|
||||
)
|
||||
|
||||
// new_password too close to the email address
|
||||
.then(click(selectors.CHANGE_PASSWORD.NEW_PASSWORD_LABEL))
|
||||
.then(type(selectors.CHANGE_PASSWORD.NEW_PASSWORD, email))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.CHANGE_PASSWORD.INVALID_SIMILAR_TO_EMAIL
|
||||
)
|
||||
)
|
||||
|
||||
// new_password too common
|
||||
.then(click(selectors.CHANGE_PASSWORD.NEW_PASSWORD_LABEL))
|
||||
.then(type(selectors.CHANGE_PASSWORD.NEW_PASSWORD, 'password'))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.CHANGE_PASSWORD.INVALID_TOO_COMMON
|
||||
)
|
||||
)
|
||||
|
||||
// all good
|
||||
.then(click(selectors.CHANGE_PASSWORD.NEW_PASSWORD_LABEL))
|
||||
.then(type(selectors.CHANGE_PASSWORD.NEW_PASSWORD, SECOND_PASSWORD))
|
||||
.then(click(selectors.CHANGE_PASSWORD.NEW_VPASSWORD_LABEL))
|
||||
.then(type(selectors.CHANGE_PASSWORD.NEW_VPASSWORD, SECOND_PASSWORD))
|
||||
.then(
|
||||
testElementExists(selectors.SETTINGS.CHANGE_PASSWORD.VALID_LENGTH)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.CHANGE_PASSWORD.VALID_SIMILAR_TO_EMAIL
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.CHANGE_PASSWORD.VALID_TOO_COMMON
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.CHANGE_PASSWORD.VALID_PASSWORD_MATCH
|
||||
)
|
||||
)
|
||||
.then(click(selectors.CHANGE_PASSWORD.SUBMIT))
|
||||
.then(pollUntilHiddenByQSA(selectors.CHANGE_PASSWORD.DETAILS))
|
||||
);
|
||||
},
|
||||
|
||||
'change password, sign in with new password': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest())
|
||||
|
||||
// Go to change password screen
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
|
||||
.then(fillOutChangePassword(FIRST_PASSWORD, SECOND_PASSWORD))
|
||||
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, SECOND_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'sign in with an unnormalized email, change password, sign in with new password': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
setupTest({ signInEmail: email.toUpperCase(), signUpEmail: email })
|
||||
)
|
||||
|
||||
// Go to change password screen
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
|
||||
.then(fillOutChangePassword(FIRST_PASSWORD, SECOND_PASSWORD))
|
||||
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, SECOND_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'cached unnormalized email, change password, sign in with new password': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest())
|
||||
|
||||
// synthesize a user who signed in pre #4470 with an unnormalized email
|
||||
.then(denormalizeStoredEmail(email))
|
||||
// refresh to load denormalized email from localStorage
|
||||
.refresh()
|
||||
// email should be normalized on refresh!
|
||||
.then(testElementTextEquals(selectors.SETTINGS.PROFILE_HEADER, email))
|
||||
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
|
||||
.then(fillOutChangePassword(FIRST_PASSWORD, SECOND_PASSWORD))
|
||||
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, SECOND_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'reset password via settings works': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest())
|
||||
|
||||
// Go to change password screen
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
.then(click(selectors.CHANGE_PASSWORD.LINK_RESET_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD.HEADER))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,110 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const intern = require('intern').default;
|
||||
const config = intern._config;
|
||||
const { describe, it, beforeEach } = intern.getPlugin('interface.bdd');
|
||||
const selectors = require('../lib/selectors');
|
||||
const FunctionalHelpers = require('../lib/helpers');
|
||||
const { createEmail } = FunctionalHelpers;
|
||||
const connectedServices = selectors.SETTINGS.CONNECTED_SERVICES;
|
||||
|
||||
describe('connected services: oauth clients', () => {
|
||||
let email;
|
||||
const password = 'topnotchsupercoolpassworddealwithit';
|
||||
let {
|
||||
clearBrowserState,
|
||||
openFxaFromRp,
|
||||
fillOutEmailFirstSignUp,
|
||||
testElementExists,
|
||||
fillOutSignUpCode,
|
||||
openPage,
|
||||
testElementTextInclude,
|
||||
click,
|
||||
pollUntilGoneByQSA,
|
||||
noSuchElement,
|
||||
openTab,
|
||||
switchToWindow,
|
||||
closeCurrentWindow,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
beforeEach(async ({ remote }) => {
|
||||
({
|
||||
clearBrowserState,
|
||||
openFxaFromRp,
|
||||
fillOutEmailFirstSignUp,
|
||||
testElementExists,
|
||||
fillOutSignUpCode,
|
||||
openPage,
|
||||
testElementTextInclude,
|
||||
click,
|
||||
pollUntilGoneByQSA,
|
||||
noSuchElement,
|
||||
openTab,
|
||||
switchToWindow,
|
||||
closeCurrentWindow,
|
||||
} = FunctionalHelpers.applyRemote(remote));
|
||||
|
||||
await clearBrowserState({
|
||||
forceAll: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('lists and disconnects RP clients', async (remote) => {
|
||||
email = createEmail();
|
||||
await openFxaFromRp('enter-email');
|
||||
await fillOutEmailFirstSignUp(email, password);
|
||||
await testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER);
|
||||
await fillOutSignUpCode(email, 0);
|
||||
await testElementExists(selectors['123DONE'].AUTHENTICATED);
|
||||
|
||||
// client is listed
|
||||
await openPage(config.fxaSettingsV2Root, connectedServices.HEADER);
|
||||
await testElementTextInclude(connectedServices.HEADER, '123Done');
|
||||
|
||||
await openTab(config.fxaUntrustedOauthApp);
|
||||
await switchToWindow(1);
|
||||
await click(selectors['123DONE'].BUTTON_SIGNIN);
|
||||
|
||||
await click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN);
|
||||
|
||||
await testElementExists(selectors.OAUTH_PERMISSIONS.HEADER);
|
||||
await click(selectors.OAUTH_PERMISSIONS.SUBMIT);
|
||||
await testElementExists(selectors['123DONE'].AUTHENTICATED);
|
||||
await closeCurrentWindow();
|
||||
|
||||
// refresh the list
|
||||
await click(connectedServices.REFRESH_BUTTON);
|
||||
await testElementTextInclude(connectedServices.HEADER, '321Done');
|
||||
|
||||
// disconnect
|
||||
await click(
|
||||
`${connectedServices.SERVICE}[data-name^="123"] ${connectedServices.SIGN_OUT}`
|
||||
);
|
||||
await pollUntilGoneByQSA(
|
||||
`${connectedServices.SERVICE}[data-name^="123"] ${connectedServices.SIGN_OUT}`
|
||||
);
|
||||
|
||||
// refresh to confirm app and its tokens are gone
|
||||
await click(connectedServices.REFRESH_BUTTON);
|
||||
await noSuchElement(
|
||||
`${connectedServices.SERVICE}[data-name^="123"] ${connectedServices.SIGN_OUT}`
|
||||
);
|
||||
});
|
||||
|
||||
it('redirect from /settings/clients', async () => {
|
||||
email = createEmail();
|
||||
await openFxaFromRp('enter-email');
|
||||
await fillOutEmailFirstSignUp(email, password);
|
||||
await testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER);
|
||||
await fillOutSignUpCode(email, 0);
|
||||
await testElementExists(selectors['123DONE'].AUTHENTICATED);
|
||||
const oldUrl = `${config.fxaSettingsV2Root}/clients`;
|
||||
// page is redirected and client list is shown
|
||||
await openPage(oldUrl, connectedServices.HEADER);
|
||||
await testElementTextInclude(connectedServices.HEADER, '123Done');
|
||||
});
|
||||
});
|
|
@ -1,155 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('../lib/helpers');
|
||||
const selectors = require('../lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const DELETE_ACCOUNT_URL = `${config.fxaContentRoot}settings/delete_account` ;
|
||||
|
||||
const PASSWORD = 'password1234567';
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
type,
|
||||
fillOutEmailFirstSignIn,
|
||||
testElementTextInclude,
|
||||
openPage,
|
||||
pollUntilHiddenByQSA,
|
||||
visibleByQSA,
|
||||
testElementExists,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('delete_account', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'sign in, delete account': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
// Go to delete account screen
|
||||
.then(click(selectors.SETTINGS_DELETE_ACCOUNT.DELETE_ACCOUNT_BUTTON))
|
||||
.then(testElementExists(selectors.SETTINGS_DELETE_ACCOUNT.DETAILS))
|
||||
|
||||
// Intern won't click on checkboxes with SVGs on top. So click the
|
||||
// checkbox labels instead :-\
|
||||
.findAllByCssSelector(selectors.SETTINGS_DELETE_ACCOUNT.CHECKBOXES)
|
||||
.then((labels) => labels.map((label) => label.click()))
|
||||
.end()
|
||||
.then(click(selectors.SETTINGS.DELETE_ACCOUNT.SUBMIT_BUTTON))
|
||||
|
||||
// enter incorrect password
|
||||
// but first, click the label to get it out of the way.
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.DELETE_ACCOUNT.INPUT_PASSWORD_LABEL
|
||||
)
|
||||
)
|
||||
.then(click(selectors.SETTINGS.DELETE_ACCOUNT.INPUT_PASSWORD_LABEL))
|
||||
.then(
|
||||
type(
|
||||
selectors.SETTINGS_DELETE_ACCOUNT.INPUT_PASSWORD,
|
||||
'incorrect password'
|
||||
)
|
||||
)
|
||||
.then(click(selectors.SETTINGS_DELETE_ACCOUNT.CONFIRM))
|
||||
.then(
|
||||
visibleByQSA(
|
||||
selectors.SETTINGS_DELETE_ACCOUNT.TOOLTIP_INCORRECT_PASSWORD
|
||||
)
|
||||
)
|
||||
|
||||
//enter correct password
|
||||
.then(
|
||||
type(selectors.SETTINGS_DELETE_ACCOUNT.INPUT_PASSWORD, PASSWORD)
|
||||
)
|
||||
.then(click(selectors.SETTINGS_DELETE_ACCOUNT.CONFIRM))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT))
|
||||
);
|
||||
},
|
||||
|
||||
'sign in, cancel delete account': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// Go to delete account screen
|
||||
.then(click(selectors.SETTINGS_DELETE_ACCOUNT.DELETE_ACCOUNT_BUTTON))
|
||||
.then(testElementExists(selectors.SETTINGS_DELETE_ACCOUNT.DETAILS))
|
||||
|
||||
// Intern won't click on checkboxes with SVGs on top. So click the
|
||||
// checkbox labels instead :-\
|
||||
.findAllByCssSelector(selectors.SETTINGS_DELETE_ACCOUNT.CHECKBOXES)
|
||||
.then((labels) => labels.map((label) => label.click()))
|
||||
.end()
|
||||
.then(click(selectors.SETTINGS.DELETE_ACCOUNT.SUBMIT_BUTTON))
|
||||
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.DELETE_ACCOUNT.INPUT_PASSWORD_LABEL
|
||||
)
|
||||
)
|
||||
.then(click(selectors.SETTINGS.DELETE_ACCOUNT.INPUT_PASSWORD_LABEL))
|
||||
.then(
|
||||
type(selectors.SETTINGS_DELETE_ACCOUNT.INPUT_PASSWORD, PASSWORD)
|
||||
)
|
||||
.then(click(selectors.SETTINGS.DELETE_ACCOUNT.CANCEL_BUTTON))
|
||||
.then(pollUntilHiddenByQSA(selectors.SETTINGS_DELETE_ACCOUNT.DETAILS))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SETTINGS.PROFILE_HEADER, email)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'navigate directly to delete account, sign in': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(DELETE_ACCOUNT_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS_DELETE_ACCOUNT.DETAILS))
|
||||
|
||||
// Intern won't click on checkboxes with SVGs on top. So click the
|
||||
// checkbox labels instead :-\
|
||||
.findAllByCssSelector(selectors.SETTINGS_DELETE_ACCOUNT.CHECKBOXES)
|
||||
.then((labels) => labels.map((label) => label.click()))
|
||||
.end()
|
||||
.then(click(selectors.SETTINGS.DELETE_ACCOUNT.SUBMIT_BUTTON))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.DELETE_ACCOUNT.INPUT_PASSWORD_LABEL
|
||||
)
|
||||
)
|
||||
.then(click(selectors.SETTINGS.DELETE_ACCOUNT.INPUT_PASSWORD_LABEL))
|
||||
.then(
|
||||
type(selectors.SETTINGS_DELETE_ACCOUNT.INPUT_PASSWORD, PASSWORD)
|
||||
)
|
||||
.then(click(selectors.SETTINGS_DELETE_ACCOUNT.CONFIRM))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,171 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const intern = require('intern').default;
|
||||
const assert = intern.getPlugin('chai').assert;
|
||||
const { describe, it, beforeEach } = intern.getPlugin('interface.bdd');
|
||||
const selectors = require('../lib/selectors');
|
||||
const FunctionalHelpers = require('../lib/helpers');
|
||||
const FunctionalSettingsHelpers = require('./lib/helpers');
|
||||
|
||||
const { navigateToSettingsV2 } = FunctionalSettingsHelpers;
|
||||
const {
|
||||
click,
|
||||
getWebChannelMessageData,
|
||||
storeWebChannelMessageData,
|
||||
testElementTextEquals,
|
||||
testElementTextInclude,
|
||||
type,
|
||||
} = FunctionalHelpers.helpersRemoteWrapped;
|
||||
const CHANGE_PROFILE_COMMAND = 'profile:change';
|
||||
|
||||
describe('display name', () => {
|
||||
let email;
|
||||
beforeEach(async ({ remote }) => {
|
||||
email = await navigateToSettingsV2(remote);
|
||||
await click(
|
||||
selectors.SETTINGS.DISPLAY_NAME.ADD_BUTTON,
|
||||
selectors.SETTINGS.DISPLAY_NAME.TEXTBOX_LABEL,
|
||||
remote
|
||||
);
|
||||
await type(
|
||||
selectors.SETTINGS.DISPLAY_NAME.TEXTBOX_FIELD,
|
||||
'Test User',
|
||||
{},
|
||||
remote
|
||||
);
|
||||
});
|
||||
|
||||
it('can add a display name', async ({ remote }) => {
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.SUBMIT_BUTTON, remote);
|
||||
|
||||
// Verify the saved name is displayed
|
||||
await testElementTextEquals(
|
||||
selectors.SETTINGS.DISPLAY_NAME.SAVED_DISPLAY_NAME,
|
||||
'Test User',
|
||||
remote
|
||||
);
|
||||
|
||||
// Also check the avatar dropdown displays the saved name
|
||||
await click(selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.MENU_BUTTON, remote);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.DISPLAY_NAME_LABEL,
|
||||
'Test User',
|
||||
remote
|
||||
);
|
||||
});
|
||||
|
||||
it('can click cancel and not add a display name', async ({ remote }) => {
|
||||
// Click cancel without providing a display name
|
||||
await click(
|
||||
selectors.SETTINGS.DISPLAY_NAME.CANCEL_BUTTON,
|
||||
selectors.SETTINGS.HEADER,
|
||||
remote
|
||||
);
|
||||
|
||||
// Verify the display name is not saved
|
||||
await testElementTextEquals(
|
||||
selectors.SETTINGS.DISPLAY_NAME.SAVED_DISPLAY_NAME,
|
||||
'None',
|
||||
remote
|
||||
);
|
||||
|
||||
// Also check the avatar dropdown displays the email id
|
||||
await click(selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.MENU_BUTTON, remote);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.DISPLAY_NAME_LABEL,
|
||||
email,
|
||||
remote
|
||||
);
|
||||
});
|
||||
|
||||
it('can change a display name', async ({ remote }) => {
|
||||
await storeWebChannelMessageData(CHANGE_PROFILE_COMMAND, remote);
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.SUBMIT_BUTTON, remote);
|
||||
|
||||
// Click change and change the display name
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.ADD_BUTTON, remote);
|
||||
await type(
|
||||
selectors.SETTINGS.DISPLAY_NAME.TEXTBOX_FIELD,
|
||||
'New User',
|
||||
{},
|
||||
remote
|
||||
);
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.SUBMIT_BUTTON, remote);
|
||||
const msg = await getWebChannelMessageData(CHANGE_PROFILE_COMMAND, remote);
|
||||
assert.equal(msg.command, CHANGE_PROFILE_COMMAND);
|
||||
assert.isString(msg.data.uid);
|
||||
// Verify the saved name is displayed
|
||||
await testElementTextEquals(
|
||||
selectors.SETTINGS.DISPLAY_NAME.SAVED_DISPLAY_NAME,
|
||||
'New User',
|
||||
remote
|
||||
);
|
||||
|
||||
// Also check the avatar dropdown displays the saved name
|
||||
await click(selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.MENU_BUTTON, remote);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.DISPLAY_NAME_LABEL,
|
||||
'New User',
|
||||
remote
|
||||
);
|
||||
});
|
||||
|
||||
it('can click cancel and not change display name', async ({ remote }) => {
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.SUBMIT_BUTTON, remote);
|
||||
|
||||
// Click change to change the display name
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.ADD_BUTTON, remote);
|
||||
await type(
|
||||
selectors.SETTINGS.DISPLAY_NAME.TEXTBOX_FIELD,
|
||||
'New User',
|
||||
{},
|
||||
remote
|
||||
);
|
||||
|
||||
// Click cancel and don't save the new display name
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.CANCEL_BUTTON, remote);
|
||||
// Verify the previous name is displayed
|
||||
await testElementTextEquals(
|
||||
selectors.SETTINGS.DISPLAY_NAME.SAVED_DISPLAY_NAME,
|
||||
'Test User',
|
||||
remote
|
||||
);
|
||||
|
||||
// Also check the avatar dropdown displays the saved name
|
||||
await click(selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.MENU_BUTTON, remote);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.DISPLAY_NAME_LABEL,
|
||||
'Test User',
|
||||
remote
|
||||
);
|
||||
});
|
||||
|
||||
it('can remove a display name', async ({ remote }) => {
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.SUBMIT_BUTTON, remote);
|
||||
|
||||
// Click change to change the display name
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.ADD_BUTTON, remote);
|
||||
await type(selectors.SETTINGS.DISPLAY_NAME.TEXTBOX_FIELD, '', {}, remote);
|
||||
|
||||
// Click submit without providing a display name
|
||||
await click(selectors.SETTINGS.DISPLAY_NAME.SUBMIT_BUTTON, remote);
|
||||
// Verify there is no display name
|
||||
await testElementTextEquals(
|
||||
selectors.SETTINGS.DISPLAY_NAME.SAVED_DISPLAY_NAME,
|
||||
'None',
|
||||
remote
|
||||
);
|
||||
|
||||
// Also check the avatar dropdown displays email id
|
||||
await click(selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.MENU_BUTTON, remote);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.DISPLAY_NAME_LABEL,
|
||||
email,
|
||||
remote
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,75 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const intern = require('intern').default;
|
||||
const config = intern._config;
|
||||
const SETTINGS_URL = config.fxaSettingsV2Root;
|
||||
const { describe, it, beforeEach } = intern.getPlugin('interface.bdd');
|
||||
const selectors = require('../lib/selectors');
|
||||
const FunctionalHelpers = require('../lib/helpers');
|
||||
const { createEmail } = FunctionalHelpers;
|
||||
const FunctionalSettingsHelpers = require('./lib/helpers');
|
||||
const { navigateToSettingsV2 } = FunctionalSettingsHelpers;
|
||||
|
||||
describe('external links', () => {
|
||||
let primaryEmail,
|
||||
testHrefEquals,
|
||||
testHrefIncludes,
|
||||
testElementExists,
|
||||
clearBrowserState,
|
||||
openPage,
|
||||
subscribeAndSigninToRp;
|
||||
|
||||
beforeEach(async ({ remote }) => {
|
||||
({
|
||||
clearBrowserState,
|
||||
testHrefEquals,
|
||||
testHrefIncludes,
|
||||
testElementExists,
|
||||
openPage,
|
||||
subscribeAndSigninToRp,
|
||||
} = FunctionalHelpers.applyRemote(remote));
|
||||
await clearBrowserState();
|
||||
primaryEmail = await navigateToSettingsV2(remote);
|
||||
});
|
||||
|
||||
it('renders external links correctly', async () => {
|
||||
await testElementExists(selectors.SETTINGS.NAVIGATION.NEWSLETTERS_LINK);
|
||||
await testHrefIncludes(
|
||||
selectors.SETTINGS.NAVIGATION.NEWSLETTERS_LINK,
|
||||
encodeURIComponent(primaryEmail)
|
||||
);
|
||||
|
||||
await testElementExists(selectors.SETTINGS.FOOTER.PRIVACY_LINK);
|
||||
await testHrefEquals(
|
||||
selectors.SETTINGS.FOOTER.PRIVACY_LINK,
|
||||
'https://www.mozilla.org/en-US/privacy/websites/'
|
||||
);
|
||||
|
||||
await testElementExists(selectors.SETTINGS.FOOTER.TERMS_LINK);
|
||||
await testHrefEquals(
|
||||
selectors.SETTINGS.FOOTER.TERMS_LINK,
|
||||
'https://www.mozilla.org/en-US/about/legal/terms/services/'
|
||||
);
|
||||
});
|
||||
|
||||
it('renders Subscriptions link in navigation when we are subscribed to a product', async function () {
|
||||
if (process.env.CIRCLECI === 'true' && !process.env.SUBHUB_STRIPE_APIKEY) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
|
||||
const email = createEmail();
|
||||
await subscribeAndSigninToRp(email);
|
||||
await openPage(SETTINGS_URL, selectors.SETTINGS.APP);
|
||||
|
||||
// test
|
||||
await testElementExists(selectors.SETTINGS.NAVIGATION.SUBSCRIPTIONS_LINK);
|
||||
await testHrefEquals(
|
||||
selectors.SETTINGS.NAVIGATION.SUBSCRIPTIONS_LINK,
|
||||
`/subscriptions`
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,34 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const selectors = require('../../lib/selectors');
|
||||
const FunctionalHelpers = require('../../lib/helpers');
|
||||
|
||||
const { createEmail } = FunctionalHelpers;
|
||||
const config = intern._config;
|
||||
const EMAIL_FIRST = config.fxaContentRoot;
|
||||
const password = 'passwordzxcv';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
createUser,
|
||||
openPage,
|
||||
fillOutEmailFirstSignIn,
|
||||
testElementExists,
|
||||
} = FunctionalHelpers.helpersRemoteWrapped;
|
||||
|
||||
async function navigateToSettingsV2(remote) {
|
||||
const email = createEmail();
|
||||
await clearBrowserState(remote);
|
||||
await createUser(email, password, { preVerified: true }, remote);
|
||||
|
||||
await openPage(EMAIL_FIRST, selectors.ENTER_EMAIL.HEADER, remote);
|
||||
await fillOutEmailFirstSignIn(email, password, remote);
|
||||
await testElementExists(selectors.SETTINGS.APP, remote);
|
||||
return email;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
navigateToSettingsV2,
|
||||
};
|
|
@ -1,316 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('../lib/helpers');
|
||||
const selectors = require('../lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const RESET_PASSWORD_URL =
|
||||
config.fxaContentRoot + 'reset_password?context=fx_desktop_v3&service=sync';
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
const NEW_PASSWORD = '()()():|';
|
||||
let email, recoveryKey;
|
||||
|
||||
const {
|
||||
createEmail,
|
||||
createUser,
|
||||
clearBrowserState,
|
||||
click,
|
||||
fillOutCompleteResetPassword,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutRecoveryKey,
|
||||
fillOutResetPassword,
|
||||
fillOutSignUpCode,
|
||||
fillOutVerificationCode,
|
||||
openPage,
|
||||
openVerificationLinkInSameTab,
|
||||
testIsBrowserNotified,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
type,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('Account recovery key', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
const remote = this.remote;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(clearBrowserState({ forceAll: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(testElementTextInclude(selectors.RECOVERY_KEY.STATUS, 'Not set'))
|
||||
|
||||
// Complete the steps to add an account recovery key
|
||||
.then(
|
||||
click(
|
||||
selectors.RECOVERY_KEY.GENERATE_KEY_BUTTON,
|
||||
selectors.RECOVERY_KEY.PASSWORD_INPUT_LABEL
|
||||
)
|
||||
) // recovery-key-unit-row-rouote
|
||||
// Once again, click the label first to get it out of the way
|
||||
.then(
|
||||
click(
|
||||
selectors.RECOVERY_KEY.PASSWORD_INPUT_LABEL,
|
||||
selectors.RECOVERY_KEY.PASSWORD_INPUT
|
||||
)
|
||||
)
|
||||
.then(click(selectors.RECOVERY_KEY.PASSWORD_INPUT))
|
||||
.then(type(selectors.RECOVERY_KEY.PASSWORD_INPUT, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.RECOVERY_KEY.CONFIRM_PASSWORD_CONTINUE,
|
||||
selectors.RECOVERY_KEY.RECOVERY_KEY_TEXT
|
||||
)
|
||||
) // continue-button
|
||||
.then(testElementExists(selectors.RECOVERY_KEY.RECOVERY_KEY_TEXT))
|
||||
|
||||
// Store the key to be used later
|
||||
.findByCssSelector(selectors.RECOVERY_KEY.RECOVERY_KEY_TEXT)
|
||||
.getVisibleText()
|
||||
.then((key) => {
|
||||
recoveryKey = key;
|
||||
return remote.then(
|
||||
click(
|
||||
selectors.RECOVERY_KEY.RECOVERY_KEY_DONE_BUTTON,
|
||||
selectors.RECOVERY_KEY.STATUS
|
||||
)
|
||||
);
|
||||
})
|
||||
.end()
|
||||
.then(testElementTextInclude(selectors.RECOVERY_KEY.STATUS, 'Enabled'))
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'can revoke account recovery key': function () {
|
||||
const remote = this.remote;
|
||||
let secondKey;
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.SECURITY.RECOVERY_KEY.REMOVE_RECOVERY_KEY,
|
||||
selectors.RECOVERY_KEY.CONFIRM_REVOKE_DESCRIPTION
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementExists(selectors.RECOVERY_KEY.CONFIRM_REVOKE_DESCRIPTION)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.RECOVERY_KEY.CONFIRM_REVOKE_OK,
|
||||
selectors.RECOVERY_KEY.STATUS
|
||||
)
|
||||
)
|
||||
|
||||
// Unfortunately need a delay here because no elements are added/removed that we can
|
||||
// wait on to check the text.
|
||||
.sleep(1000)
|
||||
.then(
|
||||
testElementTextInclude(selectors.RECOVERY_KEY.STATUS, 'Not set')
|
||||
)
|
||||
|
||||
// create a new account recovery key
|
||||
.then(click(selectors.RECOVERY_KEY.GENERATE_KEY_BUTTON))
|
||||
.then(click(selectors.RECOVERY_KEY.PASSWORD_INPUT_LABEL))
|
||||
.then(type(selectors.RECOVERY_KEY.PASSWORD_INPUT, PASSWORD))
|
||||
.then(click(selectors.RECOVERY_KEY.CONFIRM_PASSWORD_CONTINUE))
|
||||
.then(testElementExists(selectors.RECOVERY_KEY.RECOVERY_KEY_TEXT))
|
||||
.findByCssSelector(selectors.RECOVERY_KEY.RECOVERY_KEY_TEXT)
|
||||
.getVisibleText()
|
||||
.then((key) => {
|
||||
secondKey = key;
|
||||
return remote.then(
|
||||
click(selectors.RECOVERY_KEY.RECOVERY_KEY_DONE_BUTTON)
|
||||
);
|
||||
})
|
||||
.end()
|
||||
.then(
|
||||
testElementTextInclude(selectors.RECOVERY_KEY.STATUS, 'Enabled')
|
||||
)
|
||||
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
.then(openVerificationLinkInSameTab(email, 4))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
// enter old key and check for error tooltip
|
||||
.then(fillOutRecoveryKey(recoveryKey))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD_RECOVERY_KEY.TOOLTIP
|
||||
)
|
||||
)
|
||||
|
||||
// enter the new key
|
||||
.then(() => {
|
||||
return remote.then(fillOutRecoveryKey(secondKey));
|
||||
})
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
.then(fillOutCompleteResetPassword(NEW_PASSWORD, NEW_PASSWORD))
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.SUB_HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
// For good measure, lets re-login with new password
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, NEW_PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'can reset password with account recovery key': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
.then(openVerificationLinkInSameTab(email, 2))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
// enter invalid account recovery key
|
||||
.then(fillOutRecoveryKey('N8TVALID'))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD_RECOVERY_KEY.TOOLTIP
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutRecoveryKey(recoveryKey))
|
||||
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
.then(fillOutCompleteResetPassword(NEW_PASSWORD, NEW_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.SUB_HEADER))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
// For good measure, lets re-login with new password
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, NEW_PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'can reset password when forgot account recovery key': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
.then(openVerificationLinkInSameTab(email, 2))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.COMPLETE_RESET_PASSWORD_RECOVERY_KEY.LOST_KEY))
|
||||
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
.then(fillOutCompleteResetPassword(NEW_PASSWORD, NEW_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.SUB_HEADER))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
// For good measure, lets re-login with new password
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, NEW_PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'can not re-use account recovery key': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
.then(openVerificationLinkInSameTab(email, 2))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD_RECOVERY_KEY.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutRecoveryKey(recoveryKey))
|
||||
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
.then(fillOutCompleteResetPassword(NEW_PASSWORD, NEW_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.SUB_HEADER))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
// Attempt to re-use reset link, shows expired link
|
||||
.then(openVerificationLinkInSameTab(email, 2))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD.EXPIRED_LINK_HEADER
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('Account recovery key - unverified session', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
// when an account is created, the original session is verified
|
||||
// re-login to destroy original session and created an unverified one
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'gated in unverified session open verification same tab': function () {
|
||||
return (
|
||||
this.remote
|
||||
// send and open verification in same tab
|
||||
.then(click(selectors.RECOVERY_KEY.GENERATE_KEY_BUTTON))
|
||||
// if the session is unverified, then the modal will be shown.
|
||||
.then(testElementExists('[data-testid=modal-verify-session]'))
|
||||
.then(fillOutVerificationCode(email, 1))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.SECURITY.RECOVERY_KEY.PASSWORD_TEXTBOX_LABEL
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,127 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const intern = require('intern').default;
|
||||
const { describe, it, beforeEach } = intern.getPlugin('interface.bdd');
|
||||
const selectors = require('../lib/selectors');
|
||||
const FunctionalHelpers = require('../lib/helpers');
|
||||
const { createEmail } = FunctionalHelpers;
|
||||
const FunctionalSettingsHelpers = require('./lib/helpers');
|
||||
const { navigateToSettingsV2 } = FunctionalSettingsHelpers;
|
||||
|
||||
describe('secondary email', () => {
|
||||
let primaryEmail;
|
||||
const secondaryEmail = createEmail();
|
||||
let click,
|
||||
getEmailCode,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
type,
|
||||
visibleByQSA;
|
||||
|
||||
beforeEach(async ({ remote }) => {
|
||||
({
|
||||
click,
|
||||
getEmailCode,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers.applyRemote(remote));
|
||||
primaryEmail = await navigateToSettingsV2(remote);
|
||||
});
|
||||
|
||||
it('can add and verify secondary email', async () => {
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.ADD_BUTTON,
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_LABEL
|
||||
);
|
||||
|
||||
// try adding the primary as the secondary
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_LABEL,
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_FIELD
|
||||
);
|
||||
await type(selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_FIELD, primaryEmail);
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.SUBMIT_BUTTON,
|
||||
selectors.SETTINGS.TOOLTIP
|
||||
);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.TOOLTIP,
|
||||
'secondary email must be different than your account email'
|
||||
);
|
||||
|
||||
// add secondary email, resend, remove
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_LABEL,
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_FIELD
|
||||
);
|
||||
await type(selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_FIELD, secondaryEmail);
|
||||
await click(selectors.SETTINGS.SECONDARY_EMAIL.SUBMIT_BUTTON);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.FORM,
|
||||
secondaryEmail
|
||||
);
|
||||
await click(
|
||||
selectors.SETTINGS.BACK_BUTTON,
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.HEADER_VALUE
|
||||
);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.HEADER_VALUE,
|
||||
secondaryEmail
|
||||
);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.HEADER_VALUE,
|
||||
'unconfirmed'
|
||||
);
|
||||
await testElementExists(selectors.SETTINGS.SECONDARY_EMAIL.DELETE_BUTTON);
|
||||
await testElementExists(selectors.SETTINGS.SECONDARY_EMAIL.REFRESH_BUTTON);
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.DELETE_BUTTON,
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.ADD_BUTTON
|
||||
);
|
||||
|
||||
// add and verify
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.ADD_BUTTON,
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_LABEL
|
||||
);
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_LABEL,
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_FIELD
|
||||
);
|
||||
await type(selectors.SETTINGS.SECONDARY_EMAIL.EMAIL_FIELD, secondaryEmail);
|
||||
await click(selectors.SETTINGS.SECONDARY_EMAIL.SUBMIT_BUTTON);
|
||||
const verifyCode = await getEmailCode(secondaryEmail, 1);
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.VERIFY_FORM_LABEL,
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.VERIFY_FIELD
|
||||
);
|
||||
await type(selectors.SETTINGS.SECONDARY_EMAIL.VERIFY_FIELD, verifyCode);
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.VERIFY_FORM_SUBMIT_BUTTON,
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.DELETE_BUTTON
|
||||
);
|
||||
await testElementExists(selectors.SETTINGS.SECONDARY_EMAIL.DELETE_BUTTON);
|
||||
await testElementExists(selectors.SETTINGS.SECONDARY_EMAIL.MAKE_PRIMARY);
|
||||
|
||||
// swap primary and secondary
|
||||
await click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.MAKE_PRIMARY,
|
||||
selectors.EMAIL.SUCCESS
|
||||
);
|
||||
await visibleByQSA(selectors.EMAIL.SUCCESS);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.PRIMARY_EMAIL.HEADER_VALUE,
|
||||
secondaryEmail
|
||||
);
|
||||
await testElementTextInclude(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.HEADER_VALUE,
|
||||
primaryEmail
|
||||
);
|
||||
});
|
||||
});
|
|
@ -1,325 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const { testElementDisabled } = require('../lib/helpers');
|
||||
const FunctionalHelpers = require('../lib/helpers');
|
||||
const selectors = require('../lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const SETTINGS_URL = `${config.fxaContentRoot}settings`;
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
const SYNC_ENTER_EMAIL_URL = `${config.fxaContentRoot}?context=fx_desktop_v3&service=sync`;
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?action=email`;
|
||||
const RECOVERY_CODES_URL = `${config.fxaContentRoot}settings/two_step_authentication/replace_codes`;
|
||||
const RESET_PASSWORD_URL = `${config.fxaContentRoot}reset_password?context=fx_desktop_v3&service=sync`;
|
||||
|
||||
let email;
|
||||
let secret;
|
||||
|
||||
const {
|
||||
confirmTotpCode,
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutCompleteResetPassword,
|
||||
fillOutDeleteAccount,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutResetPassword,
|
||||
fillOutSignUpCode,
|
||||
fillOutVerificationCode,
|
||||
generateTotpCode,
|
||||
openPage,
|
||||
openVerificationLinkInNewTab,
|
||||
openVerificationLinkInSameTab,
|
||||
signOut,
|
||||
switchToWindow,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testIsBrowserNotified,
|
||||
testSuccessWasShown,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('TOTP', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return (
|
||||
this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(openPage(SETTINGS_URL, selectors.SETTINGS.HEADER))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(testElementExists(selectors.TOTP.MENU_BUTTON))
|
||||
|
||||
.then(click(selectors.TOTP.MENU_BUTTON))
|
||||
|
||||
.then(testElementExists(selectors.TOTP.QR_CODE))
|
||||
.then(testElementExists(selectors.TOTP.SHOW_CODE_LINK))
|
||||
|
||||
.then(click(selectors.TOTP.SHOW_CODE_LINK))
|
||||
.then(testElementExists(selectors.TOTP.MANUAL_CODE))
|
||||
|
||||
// Store the secret key to recalculate the code later
|
||||
.findByCssSelector(selectors.TOTP.MANUAL_CODE)
|
||||
.getVisibleText()
|
||||
.then((secretKey) => {
|
||||
secret = secretKey;
|
||||
})
|
||||
.end()
|
||||
.then(() => this.remote.then(click(selectors.TOTP.KEY_OK_BUTTON)))
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'can add TOTP to account and confirm web signin': function () {
|
||||
return (
|
||||
this.remote
|
||||
// Shows tool tip for invalid codes on setup
|
||||
// Note: as usual we have to click the label first, to get it out
|
||||
// of the way, then we can click into the input.
|
||||
.then(click(selectors.TOTP.CONFIRM_CODE_INPUT_LABEL))
|
||||
.then(click(selectors.TOTP.CONFIRM_CODE_INPUT))
|
||||
.then(type(selectors.TOTP.CONFIRM_CODE_INPUT, '123432'))
|
||||
.then(click(selectors.TOTP.CONFIRM_CODE_BUTTON))
|
||||
.then(visibleByQSA(selectors.TOTP.TOOLTIP))
|
||||
.then(testElementTextInclude(selectors.TOTP.TOOLTIP, 'Incorrect'))
|
||||
|
||||
.then(confirmTotpCode(secret))
|
||||
|
||||
.then(signOut())
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
|
||||
// Show tool tip for invalid codes on sign-in
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, '123432'))
|
||||
.then(click(selectors.TOTP_SIGNIN.SUBMIT))
|
||||
.then(visibleByQSA(selectors.TOTP.LOGIN_FLOW_TOOLTIP))
|
||||
.then(
|
||||
testElementTextInclude(selectors.TOTP.LOGIN_FLOW_TOOLTIP, 'Invalid')
|
||||
)
|
||||
|
||||
// Redirect to /settings when successful
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret)))
|
||||
.then(click(selectors.TOTP_SIGNIN.SUBMIT))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'can add TOTP to account and confirm sync signin': function () {
|
||||
return this.remote
|
||||
.then(confirmTotpCode(secret))
|
||||
|
||||
.then(signOut())
|
||||
.then(
|
||||
openPage(SYNC_ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {},
|
||||
})
|
||||
)
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret)))
|
||||
.then(click(selectors.TOTP_SIGNIN.SUBMIT))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER));
|
||||
},
|
||||
|
||||
'can remove TOTP from account and skip confirmation': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(confirmTotpCode(secret))
|
||||
|
||||
// Remove token, first in unit row then in confirmation modal
|
||||
.then(
|
||||
click(selectors.TOTP.DELETE_BUTTON, selectors.TOTP.CONFIRM_DELETE)
|
||||
)
|
||||
.then(click(selectors.TOTP.CONFIRM_DELETE))
|
||||
.then(testSuccessWasShown)
|
||||
.then(testElementExists(selectors.TOTP.MENU_BUTTON))
|
||||
.refresh()
|
||||
|
||||
// Does not prompt for code
|
||||
.then(signOut())
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'can add TOTP to account and then delete it': function () {
|
||||
return this.remote
|
||||
.then(confirmTotpCode(secret))
|
||||
.then(click(selectors.SETTINGS_DELETE_ACCOUNT.DELETE_ACCOUNT_BUTTON))
|
||||
.then(visibleByQSA(selectors.SETTINGS_DELETE_ACCOUNT.DETAILS))
|
||||
|
||||
.then(fillOutDeleteAccount(PASSWORD))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER));
|
||||
},
|
||||
|
||||
'can change backup authentication codes': function () {
|
||||
return this.remote
|
||||
.then(confirmTotpCode(secret))
|
||||
.then(
|
||||
openPage(
|
||||
RECOVERY_CODES_URL,
|
||||
selectors.TOTP.RECOVERY_CODES_DESCRIPTION
|
||||
)
|
||||
)
|
||||
.then(testElementExists(selectors.SETTINGS.SECURITY.TFA.RECOVERY_CODES))
|
||||
.findByCssSelector(selectors.SETTINGS.SECURITY.TFA.FIRST_RECOVERY_CODE)
|
||||
.getVisibleText()
|
||||
.then((code) => {
|
||||
return this.remote
|
||||
.then(click(selectors.SETTINGS.SECURITY.TFA.CONTINUE_RECOVERY_KEY))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.SECURITY.TFA.RECOVERY_KEY_INPUT
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementDisabled(
|
||||
selectors.SETTINGS.SECURITY.TFA.SUBMIT_RECOVERY_KEY
|
||||
)
|
||||
)
|
||||
.then(
|
||||
type(selectors.SETTINGS.SECURITY.TFA.RECOVERY_KEY_INPUT, code)
|
||||
)
|
||||
.then(click(selectors.SETTINGS.SECURITY.TFA.SUBMIT_RECOVERY_KEY));
|
||||
});
|
||||
},
|
||||
|
||||
'can reset password, prompt for TOTP and login - same browser same tab':
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(confirmTotpCode(secret))
|
||||
|
||||
.then(signOut())
|
||||
//.then(clearBrowserState())
|
||||
|
||||
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(openVerificationLinkInSameTab(email, 2))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret)))
|
||||
.then(
|
||||
click(
|
||||
selectors.TOTP_SIGNIN.SUBMIT,
|
||||
selectors.CONNECT_ANOTHER_DEVICE.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.CONNECTED))
|
||||
);
|
||||
},
|
||||
|
||||
'can reset password, prompt for TOTP and login - same browser different tab':
|
||||
function () {
|
||||
return this.remote
|
||||
.then(confirmTotpCode(secret))
|
||||
.then(signOut())
|
||||
|
||||
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(openVerificationLinkInNewTab(email, 2))
|
||||
.then(switchToWindow(1))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret)))
|
||||
.then(
|
||||
click(
|
||||
selectors.TOTP_SIGNIN.SUBMIT,
|
||||
selectors.CONNECT_ANOTHER_DEVICE.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.CONNECTED));
|
||||
},
|
||||
|
||||
'can reset password, prompt for TOTP and login - verify different browser':
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(confirmTotpCode(secret))
|
||||
.then(signOut())
|
||||
|
||||
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
|
||||
.then(fillOutResetPassword(email))
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
|
||||
// clear all browser state, simulate opening in a new browser
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(openVerificationLinkInSameTab(email, 2))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
|
||||
.then(type(selectors.TOTP_SIGNIN.INPUT, generateTotpCode(secret)))
|
||||
.then(click(selectors.TOTP_SIGNIN.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('TOTP - unverified session', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'gated in unverified session open verification same tab': function () {
|
||||
return (
|
||||
this.remote
|
||||
// when an account is created, the original session is verified
|
||||
// re-login to destroy original session and created an unverified one
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP.UNLOCK_BUTTON))
|
||||
|
||||
// unlock panel
|
||||
.then(click(selectors.TOTP.UNLOCK_BUTTON))
|
||||
.then(testElementExists(selectors.TOTP.UNLOCK_SEND_VERIFY))
|
||||
|
||||
// send and open verification in same tab
|
||||
.then(fillOutVerificationCode(email, 1))
|
||||
|
||||
// panel becomes verified and can be opened
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SETTINGS.SECURITY.TFA.SECURITY_CODE_TEXTBOX_LABEL
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,204 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const fxaProduction = intern._config.fxaProduction;
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const PASSWORD = 'passwordcxzv';
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
closeCurrentWindow,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
openPage,
|
||||
openTab,
|
||||
signOut,
|
||||
switchToWindow,
|
||||
testAttributeMatches,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('signin', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'signin verified with incorrect password, click `forgot password?`': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, 'incorrect password'))
|
||||
// success is seeing the error message.
|
||||
.then(visibleByQSA(selectors.SIGNIN_PASSWORD.TOOLTIP))
|
||||
// If user clicks on "forgot your password?",
|
||||
// begin the reset password flow.
|
||||
.then(click(selectors.SIGNIN_PASSWORD.LINK_FORGOT_PASSWORD))
|
||||
.then(testElementExists(selectors.RESET_PASSWORD.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'signin with email with leading space strips space': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(' ' + email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'signin with email with trailing space strips space': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email + ' ', PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'signin verified with password that incorrectly has leading whitespace': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, ' ' + PASSWORD))
|
||||
// success is seeing the error message.
|
||||
.then(visibleByQSA(selectors.SIGNIN_PASSWORD.TOOLTIP))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SIGNIN_PASSWORD.TOOLTIP,
|
||||
'password'
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'signin from second tab while at /': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(openTab(ENTER_EMAIL_URL))
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(closeCurrentWindow())
|
||||
.then(switchToWindow(0))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'signin from second tab while at /signin': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNIN_PASSWORD.HEADER)
|
||||
)
|
||||
|
||||
.then(openTab(ENTER_EMAIL_URL))
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(closeCurrentWindow())
|
||||
.then(switchToWindow(0))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'signin from second tab while at /signup': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNUP_PASSWORD.HEADER)
|
||||
)
|
||||
|
||||
.then(openTab(ENTER_EMAIL_URL))
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(closeCurrentWindow())
|
||||
.then(switchToWindow(0))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'login as an existing user': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
// success is seeing the header
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(signOut())
|
||||
|
||||
// login as existing user
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
.then(type(selectors.SIGNIN.PASSWORD, PASSWORD))
|
||||
.then(click(selectors.SIGNIN.SUBMIT))
|
||||
|
||||
// success is seeing the existing user logged in
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'data-flow-begin attribute is set': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(
|
||||
testAttributeMatches('body', 'data-flow-begin', /^[1-9][0-9]{12,}$/)
|
||||
);
|
||||
},
|
||||
|
||||
'integrity attribute is set on scripts and css': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(testAttributeMatches('script', 'integrity', /^sha512-/))
|
||||
.then(testAttributeMatches('link', 'integrity', /^sha512-/))
|
||||
.catch(function (err) {
|
||||
// this tests only in production
|
||||
if (fxaProduction || err.name !== 'AssertionError') {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,452 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const PASSWORD = 'passwordcxvz';
|
||||
let email;
|
||||
|
||||
const {
|
||||
addAndVerifySecondaryEmail,
|
||||
clearBrowserState,
|
||||
click,
|
||||
closeCurrentWindow,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutSignInTokenCode,
|
||||
fillOutSignInUnblock,
|
||||
getUnblockInfo,
|
||||
openPage,
|
||||
openTab,
|
||||
signOut,
|
||||
switchToWindow,
|
||||
testElementTextEquals,
|
||||
testErrorTextInclude,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testSuccessWasShown,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('signin blocked', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('blocked{id}');
|
||||
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState({ forceAll: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'valid code entered': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNIN_UNBLOCK.VERIFICATION, email)
|
||||
)
|
||||
.then(fillOutSignInUnblock(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'valid code with whitespace at the beginning entered': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNIN_UNBLOCK.VERIFICATION, email)
|
||||
)
|
||||
.then(getUnblockInfo(email, 0))
|
||||
.then(function (unblockInfo) {
|
||||
return this.parent.then(
|
||||
type(
|
||||
selectors.SIGNIN_UNBLOCK.UNBLOCK_CODE,
|
||||
' ' + unblockInfo.unblockCode
|
||||
)
|
||||
);
|
||||
})
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'valid code with whitespace at the end entered': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNIN_UNBLOCK.VERIFICATION, email)
|
||||
)
|
||||
.then(getUnblockInfo(email, 0))
|
||||
.then(function (unblockInfo) {
|
||||
return this.parent.then(
|
||||
type(
|
||||
selectors.SIGNIN_UNBLOCK.UNBLOCK_CODE,
|
||||
unblockInfo.unblockCode + ' '
|
||||
)
|
||||
);
|
||||
})
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'invalid code entered': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNIN_UNBLOCK.VERIFICATION, email)
|
||||
)
|
||||
.then(type(selectors.SIGNIN_UNBLOCK.UNBLOCK_CODE, 'i'))
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
|
||||
.then(visibleByQSA(selectors.SIGNIN_UNBLOCK.TOOLTIP))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNIN_UNBLOCK.TOOLTIP, 'invalid')
|
||||
);
|
||||
},
|
||||
|
||||
'incorrect code entered': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNIN_UNBLOCK.VERIFICATION, email)
|
||||
)
|
||||
.then(type(selectors.SIGNIN_UNBLOCK.UNBLOCK_CODE, 'incorrec'))
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
.then(visibleByQSA(selectors.SIGNIN_UNBLOCK.ERROR))
|
||||
.then(testErrorTextInclude('invalid'))
|
||||
.then(getUnblockInfo(email, 0))
|
||||
.then(function (unblockInfo) {
|
||||
return this.parent.then(
|
||||
type(selectors.SIGNIN_UNBLOCK.UNBLOCK_CODE, unblockInfo.unblockCode)
|
||||
);
|
||||
})
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'incorrect password entered': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, 'incorrect'))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNIN_UNBLOCK.VERIFICATION, email)
|
||||
)
|
||||
.then(fillOutSignInUnblock(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(testErrorTextInclude('incorrect password'))
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNIN_UNBLOCK.VERIFICATION, email)
|
||||
)
|
||||
|
||||
.then(fillOutSignInUnblock(email, 0))
|
||||
// the first code is no longer valid, must use the 2nd.
|
||||
.then(visibleByQSA(selectors.SIGNIN_UNBLOCK.ERROR))
|
||||
.then(testErrorTextInclude('invalid'))
|
||||
|
||||
// get and consume the second code
|
||||
.then(fillOutSignInUnblock(email, 1))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
resend: function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.LINK_RESEND))
|
||||
.then(visibleByQSA('.success'))
|
||||
.then(testElementTextInclude('.success', 'resent'))
|
||||
// use the 2nd unblock code
|
||||
.then(fillOutSignInUnblock(email, 1))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'report signin success': function () {
|
||||
let unblockCode;
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(getUnblockInfo(email, 0))
|
||||
.then(function (unblockInfo) {
|
||||
unblockCode = unblockInfo.unblockCode;
|
||||
return this.parent.then(openTab(unblockInfo.reportSignInLink));
|
||||
})
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists(selectors.REPORT_SIGNIN.HEADER))
|
||||
.then(click(selectors.REPORT_SIGNIN.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_REPORTED.HEADER))
|
||||
|
||||
.then(closeCurrentWindow())
|
||||
|
||||
// try to use the code that was reported, it should error
|
||||
.then(function () {
|
||||
return this.parent.then(
|
||||
type(selectors.SIGNIN_UNBLOCK.UNBLOCK_CODE, unblockCode)
|
||||
);
|
||||
})
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
.then(visibleByQSA(selectors.SIGNIN_UNBLOCK.ERROR))
|
||||
.then(testErrorTextInclude('invalid'))
|
||||
);
|
||||
},
|
||||
|
||||
'report signin link unblockCode broken': function () {
|
||||
let unblockCode;
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(getUnblockInfo(email, 0))
|
||||
.then(function (unblockInfo) {
|
||||
unblockCode = unblockInfo.unblockCode;
|
||||
const invalidLink = unblockInfo.reportSignInLink.replace(
|
||||
/unblockCode=[^&]+/,
|
||||
'unblockCode=invalid_code'
|
||||
);
|
||||
return this.parent.then(openTab(invalidLink));
|
||||
})
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists('#fxa-report-sign-in-link-damaged-header'))
|
||||
.then(closeCurrentWindow())
|
||||
|
||||
// code can still be used
|
||||
.then(function () {
|
||||
return this.parent.then(
|
||||
type(selectors.SIGNIN_UNBLOCK.UNBLOCK_CODE, unblockCode)
|
||||
);
|
||||
})
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'report signin link uid broken': function () {
|
||||
let unblockCode;
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(getUnblockInfo(email, 0))
|
||||
.then(function (unblockInfo) {
|
||||
unblockCode = unblockInfo.unblockCode;
|
||||
const invalidLink = unblockInfo.reportSignInLink.replace(
|
||||
/uid=[^&]+/,
|
||||
'uid=invalid_uid'
|
||||
);
|
||||
return this.parent.then(openTab(invalidLink));
|
||||
})
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists('#fxa-report-sign-in-link-damaged-header'))
|
||||
.then(closeCurrentWindow())
|
||||
|
||||
// code can still be used
|
||||
.then(function () {
|
||||
return this.parent.then(
|
||||
type(selectors.SIGNIN_UNBLOCK.UNBLOCK_CODE, unblockCode)
|
||||
);
|
||||
})
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'report link opened after code used': function () {
|
||||
let reportSignInLink;
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(getUnblockInfo(email, 0))
|
||||
.then(function (unblockInfo) {
|
||||
reportSignInLink = unblockInfo.reportSignInLink;
|
||||
return this.parent.then(
|
||||
type(
|
||||
selectors.SIGNIN_UNBLOCK.UNBLOCK_CODE,
|
||||
unblockInfo.unblockCode
|
||||
)
|
||||
);
|
||||
})
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(function () {
|
||||
return this.parent.then(
|
||||
openPage(reportSignInLink, '#fxa-report-sign-in-header')
|
||||
);
|
||||
})
|
||||
// report link is expired and can no longer be used.
|
||||
.then(click(selectors.SIGNIN_UNBLOCK.SUBMIT))
|
||||
.then(visibleByQSA(selectors.SIGNIN_UNBLOCK.ERROR))
|
||||
.then(testErrorTextInclude('invalid'))
|
||||
);
|
||||
},
|
||||
|
||||
unverified: function () {
|
||||
email = createEmail('blocked{id}');
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: false }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
// email 0 is the signup email, email 1 contains the code
|
||||
.then(fillOutSignInUnblock(email, 1))
|
||||
|
||||
// It's substandard UX, but we decided to punt on making
|
||||
// users verified until v2. When submitting an unblock code
|
||||
// verifies unverified users, they will not need to enter
|
||||
// the verification code, instead they'll go directly
|
||||
// to the settings page.
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
.then(fillOutSignInTokenCode(email, 2))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'with primary email changed': function () {
|
||||
email = createEmail('{id}');
|
||||
const secondaryEmail = createEmail('blocked{id}');
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(click(selectors.EMAIL.MENU_BUTTON))
|
||||
.then(addAndVerifySecondaryEmail(secondaryEmail))
|
||||
.then(testSuccessWasShown())
|
||||
// set new primary email
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.MAKE_PRIMARY,
|
||||
selectors.EMAIL.SUCCESS
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
testElementTextEquals(selectors.EMAIL.ADDRESS_LABEL, secondaryEmail)
|
||||
)
|
||||
.then(signOut())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
// Try login with new primary email
|
||||
.then(fillOutEmailFirstSignIn(secondaryEmail, PASSWORD))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SIGNIN_UNBLOCK.VERIFICATION,
|
||||
secondaryEmail
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(fillOutSignInUnblock(email, 3))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'with primary email changed incorrect password': function () {
|
||||
email = createEmail('{id}');
|
||||
const secondaryEmail = createEmail('blocked{id}');
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(click(selectors.EMAIL.MENU_BUTTON))
|
||||
.then(addAndVerifySecondaryEmail(secondaryEmail))
|
||||
.then(testSuccessWasShown())
|
||||
// set new primary email
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.SECONDARY_EMAIL.MAKE_PRIMARY,
|
||||
selectors.EMAIL.SUCCESS
|
||||
)
|
||||
)
|
||||
|
||||
.then(
|
||||
testElementTextEquals(selectors.EMAIL.ADDRESS_LABEL, secondaryEmail)
|
||||
)
|
||||
.then(signOut())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
// Try login with new primary email and invalid
|
||||
.then(fillOutEmailFirstSignIn(secondaryEmail, 'invalid pw'))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SIGNIN_UNBLOCK.VERIFICATION,
|
||||
secondaryEmail
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(fillOutSignInUnblock(secondaryEmail, 3))
|
||||
|
||||
.then(visibleByQSA(selectors.SIGNIN_UNBLOCK.ERROR))
|
||||
.then(testErrorTextInclude('incorrect password'))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,410 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const assert = intern.getPlugin('chai').assert;
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const { FX_DESKTOP_V3_CONTEXT } = require('../../app/scripts/lib/constants');
|
||||
const selectors = require('./lib/selectors');
|
||||
const userAgent = require('./lib/ua-strings');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const PAGE_ENTER_EMAIL_SYNC_DESKTOP = `${config.fxaContentRoot}?context=${FX_DESKTOP_V3_CONTEXT}&service=sync`;
|
||||
|
||||
const PASSWORD = 'password12345678';
|
||||
let email;
|
||||
let email2;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
clearSessionStorage,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
denormalizeStoredEmail,
|
||||
destroySessionForEmail,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignInTokenCode,
|
||||
getStoredAccountByEmail,
|
||||
openPage,
|
||||
respondToWebChannelMessage,
|
||||
testElementExists,
|
||||
testElementTextEquals,
|
||||
testElementValueEquals,
|
||||
testIsBrowserNotified,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('cached signin', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
email2 = createEmail();
|
||||
return this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(createUser(email2, PASSWORD, { preVerified: true }));
|
||||
},
|
||||
tests: {
|
||||
'sign in twice, on second attempt email will be cached': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
// reset prefill and context
|
||||
.then(clearSessionStorage())
|
||||
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'sign in with incorrect email case before normalization fix, on second attempt canonical form is used':
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
// reset prefill and context
|
||||
.then(clearSessionStorage())
|
||||
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
// synthesize signin pre-#4470 with incorrect email case.
|
||||
// to avoid a timing issue where the de-normalized email was
|
||||
// being overwritten in localStorage when denormalization was
|
||||
// done on the settings page, wait for the signin page to load,
|
||||
// denormalize, then refresh. See #4711
|
||||
.then(denormalizeStoredEmail(email))
|
||||
|
||||
.refresh()
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
// email is normalized!
|
||||
.then(
|
||||
testElementTextEquals(selectors.SETTINGS.PROFILE_HEADER, email)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'sign in once, use a different account': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
// testing to make sure "Use different account" button works
|
||||
.then(click(selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT))
|
||||
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email2, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
// testing to make sure cached signin comes back after a refresh
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.EMAIL))
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email2))
|
||||
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
email2
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'expired cached credentials': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(destroySessionForEmail(email))
|
||||
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'cached credentials that expire while on page': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE))
|
||||
|
||||
.then(destroySessionForEmail(email))
|
||||
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
// Session expired error should show.
|
||||
.then(visibleByQSA(selectors.SIGNIN_PASSWORD.ERROR))
|
||||
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
.then(testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email))
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'unverified cached signin redirects to confirm email': function () {
|
||||
const email = createEmail();
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
// cached login should still go to email confirmation screen for unverified accounts
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
// get the second email, the first was sent via fillOutEmailFirstSignUp above.
|
||||
.then(fillOutSignInTokenCode(email, 1))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'sign in on desktop then specify a different email on query parameter continues to cache desktop signin':
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(
|
||||
PAGE_ENTER_EMAIL_SYNC_DESKTOP,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
respondToWebChannelMessage('fxaccounts:can_link_account', {
|
||||
ok: true,
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
ENTER_EMAIL_URL + '?email=' + email2,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email2)
|
||||
)
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
// reset prefill and context
|
||||
.then(clearSessionStorage())
|
||||
|
||||
// testing to make sure cached signin comes back after a refresh
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
.then(click(selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.EMAIL))
|
||||
);
|
||||
},
|
||||
|
||||
'sign in with desktop context then no context, desktop credentials should persist':
|
||||
function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(
|
||||
PAGE_ENTER_EMAIL_SYNC_DESKTOP,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
respondToWebChannelMessage('fxaccounts:can_link_account', {
|
||||
ok: true,
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
|
||||
// ensure signin page is visible otherwise credentials might
|
||||
// not be cleared by clicking #use-different
|
||||
.then(
|
||||
openPage(
|
||||
ENTER_EMAIL_URL,
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT
|
||||
)
|
||||
)
|
||||
.then(visibleByQSA(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT))
|
||||
// need to wait for the email field to be visible
|
||||
// before attempting to sign-in.
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.EMAIL))
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email2, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
// reset prefill and context
|
||||
.then(clearSessionStorage())
|
||||
|
||||
// testing to make sure cached signin comes back after a refresh
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
|
||||
.refresh()
|
||||
|
||||
.then(
|
||||
testElementExists(selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT)
|
||||
)
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNIN_PASSWORD.EMAIL_NOT_EDITABLE,
|
||||
email
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'sign in then use cached credentials to sign in again, existing session token should be re-authenticated':
|
||||
function () {
|
||||
let accountData1, accountData2;
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(getStoredAccountByEmail(email))
|
||||
.then((accountData) => {
|
||||
assert.ok(accountData.sessionToken);
|
||||
accountData1 = accountData;
|
||||
})
|
||||
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(click(selectors.SIGNIN_PASSWORD.SUBMIT_USE_SIGNED_IN))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(getStoredAccountByEmail(email))
|
||||
.then((accountData) => {
|
||||
assert.ok(accountData.sessionToken);
|
||||
accountData2 = accountData;
|
||||
})
|
||||
|
||||
.then(() => {
|
||||
assert.equal(accountData1.uid, accountData2.uid);
|
||||
assert.equal(accountData1.sessionToken, accountData2.sessionToken);
|
||||
});
|
||||
},
|
||||
|
||||
'sign in then use cached credentials to sign in to sync, a new session token should be created':
|
||||
function () {
|
||||
let accountData1, accountData2;
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(getStoredAccountByEmail(email))
|
||||
.then((accountData) => {
|
||||
assert.ok(accountData.sessionToken);
|
||||
accountData1 = accountData;
|
||||
})
|
||||
|
||||
.then(
|
||||
openPage(
|
||||
PAGE_ENTER_EMAIL_SYNC_DESKTOP,
|
||||
selectors.SIGNIN_PASSWORD.HEADER,
|
||||
{
|
||||
query: {
|
||||
forceUA: userAgent['desktop_firefox_71'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': {
|
||||
ok: true,
|
||||
},
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
.then(respondToWebChannelMessage())
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.SIGNIN_TOKEN_CODE.HEADER
|
||||
)
|
||||
)
|
||||
.then(fillOutSignInTokenCode(email, 1))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
.then(getStoredAccountByEmail(email))
|
||||
.then((accountData) => {
|
||||
assert.ok(accountData.sessionToken);
|
||||
accountData2 = accountData;
|
||||
})
|
||||
|
||||
.then(() => {
|
||||
assert.equal(accountData1.uid, accountData2.uid);
|
||||
assert.notEqual(
|
||||
accountData1.sessionToken,
|
||||
accountData2.sessionToken
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,218 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?action=email`;
|
||||
const SETTINGS_URL = `${config.fxaContentRoot}settings`;
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
const SYNC_ENTER_EMAIL_URL = `${config.fxaContentRoot}?context=fx_desktop_v3&service=sync`;
|
||||
|
||||
let email;
|
||||
let recoveryCode, recoveryCode2;
|
||||
let secret;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
generateTotpCode,
|
||||
getEmail,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testIsBrowserNotified,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('backup authentication code', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
const self = this;
|
||||
return (
|
||||
this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
|
||||
.then(openPage(SETTINGS_URL, selectors.SETTINGS.HEADER))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(testElementExists(selectors.TOTP.MENU_BUTTON))
|
||||
|
||||
.then(click(selectors.TOTP.MENU_BUTTON))
|
||||
|
||||
.then(testElementExists(selectors.TOTP.QR_CODE))
|
||||
.then(testElementExists(selectors.TOTP.SHOW_CODE_LINK))
|
||||
|
||||
.then(click(selectors.TOTP.SHOW_CODE_LINK))
|
||||
.then(testElementExists(selectors.TOTP.MANUAL_CODE))
|
||||
|
||||
// Store the secret key to recalculate the code later
|
||||
.findByCssSelector(selectors.TOTP.MANUAL_CODE)
|
||||
.getVisibleText()
|
||||
.then((secretKey) => {
|
||||
secret = secretKey;
|
||||
return (
|
||||
self.remote
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.SECURITY.TFA.SECURITY_CODE_TEXTBOX_LABEL
|
||||
)
|
||||
)
|
||||
.then(
|
||||
type(
|
||||
selectors.TOTP.CONFIRM_CODE_INPUT,
|
||||
generateTotpCode(secret)
|
||||
)
|
||||
)
|
||||
.then(click(selectors.TOTP.CONFIRM_CODE_BUTTON))
|
||||
|
||||
// Store a backup authentication code
|
||||
.findByCssSelector(
|
||||
selectors.SETTINGS.SECURITY.TFA.FIRST_RECOVERY_CODE
|
||||
)
|
||||
.getVisibleText()
|
||||
.then((code) => {
|
||||
recoveryCode = code;
|
||||
return self.remote
|
||||
.findByCssSelector(
|
||||
selectors.SETTINGS.SECURITY.TFA.SECOND_RECOVERY_CODE
|
||||
)
|
||||
.getVisibleText()
|
||||
.then((code) => {
|
||||
recoveryCode2 = code;
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
return self.remote
|
||||
.then(
|
||||
click(selectors.SETTINGS.SECURITY.TFA.CONTINUE_RECOVERY_KEY)
|
||||
)
|
||||
.then(
|
||||
type(selectors.TOTP.CONFIRM_RECOVERY_INPUT, recoveryCode)
|
||||
)
|
||||
.then(click(selectors.TOTP.CONFIRM_RECOVERY_BUTTON));
|
||||
})
|
||||
);
|
||||
})
|
||||
.end()
|
||||
);
|
||||
},
|
||||
|
||||
tests: {
|
||||
'can sign-in with backup authentication code - sync': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.MENU_BUTTON,
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.SIGNOUT_BUTTON
|
||||
)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.SIGNOUT_BUTTON,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
openPage(SYNC_ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {},
|
||||
})
|
||||
)
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
.then(click(selectors.SIGNIN_RECOVERY_CODE.LINK))
|
||||
|
||||
// Fails for invalid code
|
||||
.then(type(selectors.SIGNIN_RECOVERY_CODE.INPUT, 'invalid!!!!'))
|
||||
.then(click(selectors.SIGNIN_RECOVERY_CODE.SUBMIT))
|
||||
.then(visibleByQSA('.tooltip'))
|
||||
.then(testElementTextInclude('.tooltip', 'invalid'))
|
||||
|
||||
.then(type(selectors.SIGNIN_RECOVERY_CODE.INPUT, recoveryCode))
|
||||
.then(click(selectors.SIGNIN_RECOVERY_CODE.SUBMIT))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'can regenerate backup authentication code when low': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.MENU_BUTTON,
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.SIGNOUT_BUTTON
|
||||
)
|
||||
)
|
||||
.then(
|
||||
click(
|
||||
selectors.SETTINGS.AVATAR_DROP_DOWN_MENU.SIGNOUT_BUTTON,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
openPage(SYNC_ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {},
|
||||
})
|
||||
)
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
.then(click(selectors.SIGNIN_RECOVERY_CODE.LINK))
|
||||
|
||||
.then(type(selectors.SIGNIN_RECOVERY_CODE.INPUT, recoveryCode))
|
||||
.then(click(selectors.SIGNIN_RECOVERY_CODE.SUBMIT))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
// Next attempt to use backup authentication code will redirect to
|
||||
// page where user can generate more backup authentication codes
|
||||
.then(clearBrowserState({ force: true }))
|
||||
|
||||
.then(
|
||||
openPage(SYNC_ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {},
|
||||
})
|
||||
)
|
||||
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.TOTP_SIGNIN.HEADER))
|
||||
.then(click(selectors.SIGNIN_RECOVERY_CODE.LINK))
|
||||
|
||||
.then(type(selectors.SIGNIN_RECOVERY_CODE.INPUT, recoveryCode2))
|
||||
.then(click(selectors.SIGNIN_RECOVERY_CODE.SUBMIT))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
|
||||
// User gets an email notifying them to generate new backup authentication codes.
|
||||
// Clicking the link in email opens the security page
|
||||
.then(getEmail(email, 3))
|
||||
.then((emailData) => {
|
||||
return openPage(
|
||||
emailData.headers['x-link'],
|
||||
selectors.SETTINGS.SECURITY.TFA.CHANGE_TFA
|
||||
);
|
||||
})
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,371 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const selectors = require('./lib/selectors');
|
||||
const UA_STRINGS = require('./lib/ua-strings');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
|
||||
let email;
|
||||
const PASSWORD = 'password12345678';
|
||||
|
||||
const {
|
||||
click,
|
||||
clearBrowserState,
|
||||
closeCurrentWindow,
|
||||
createEmail,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
noPageTransition,
|
||||
noSuchElement,
|
||||
openPage,
|
||||
openSignUpInNewTab,
|
||||
pollUntilHiddenByQSA,
|
||||
signOut,
|
||||
switchToWindow,
|
||||
testAttributeIncludes,
|
||||
testElementExists,
|
||||
testElementTextEquals,
|
||||
testElementTextInclude,
|
||||
testElementValueEquals,
|
||||
testErrorTextInclude,
|
||||
testSuccessWasShown,
|
||||
testUrlInclude,
|
||||
type,
|
||||
visibleByQSA,
|
||||
waitForUrl,
|
||||
} = require('./lib/helpers');
|
||||
|
||||
const ENTER_EMAIL_ENTRYPOINT = `entrypoint=${encodeURIComponent(
|
||||
'fxa:enter_email'
|
||||
)}`;
|
||||
var SYNC_CONTEXT_DESKTOP = 'context=fx_desktop_v3';
|
||||
var SYNC_SERVICE = 'service=sync';
|
||||
const PRODUCT_URL = `${config.fxaContentRoot}subscriptions/products/${config.testProductId}?signin=true`;
|
||||
|
||||
function testAtConfirmScreen(email) {
|
||||
return function () {
|
||||
return this.parent
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(selectors.CONFIRM_SIGNUP_CODE.EMAIL_FIELD, email)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
registerSuite('signup here', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'with an invalid email': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL + '?email=invalid', selectors['400'].HEADER)
|
||||
)
|
||||
.then(testErrorTextInclude('invalid'))
|
||||
.then(testErrorTextInclude('email'));
|
||||
},
|
||||
|
||||
'with an empty email': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL + '?email=', selectors['400'].HEADER))
|
||||
.then(testErrorTextInclude('invalid'))
|
||||
.then(testErrorTextInclude('email'));
|
||||
},
|
||||
|
||||
'signup, verify and sign out of two accounts, all in the same tab, then sign in to the first account':
|
||||
function () {
|
||||
// https://github.com/mozilla/fxa-content-server/issues/2209
|
||||
var secondEmail = createEmail();
|
||||
this.timeout = 90000;
|
||||
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testAtConfirmScreen(email))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(testSuccessWasShown())
|
||||
.then(signOut())
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
.then(fillOutEmailFirstSignUp(secondEmail, PASSWORD))
|
||||
.then(testAtConfirmScreen(secondEmail))
|
||||
.then(fillOutSignUpCode(secondEmail, 0))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(testSuccessWasShown())
|
||||
.then(signOut())
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'signup with email with leading whitespace on the email': function () {
|
||||
var emailWithoutSpace = email;
|
||||
var emailWithSpace = ' ' + email;
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(emailWithSpace, PASSWORD))
|
||||
.then(testAtConfirmScreen(emailWithoutSpace))
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(emailWithoutSpace, PASSWORD))
|
||||
|
||||
// user is not confirmed, success is seeing the confirm screen.
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'signup with email with trailing whitespace on the email': function () {
|
||||
var emailWithoutSpace = email;
|
||||
var emailWithSpace = ' ' + email;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(emailWithSpace, PASSWORD))
|
||||
.then(testAtConfirmScreen(emailWithoutSpace))
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(emailWithoutSpace, PASSWORD))
|
||||
|
||||
// user is not confirmed, success is seeing the confirm screen.
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'signup with invalid email address': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, `${email}-`))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT))
|
||||
|
||||
// wait five seconds to allow any errant navigation to occur
|
||||
.then(noPageTransition(selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
// the validation tooltip should be visible
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP))
|
||||
);
|
||||
},
|
||||
|
||||
'coppa is empty': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD, { age: ' ' }))
|
||||
|
||||
// navigation should not occur
|
||||
.then(noPageTransition(selectors.SIGNUP_PASSWORD.HEADER))
|
||||
|
||||
// an error should be visible
|
||||
.then(visibleByQSA(selectors.SIGNUP_PASSWORD.TOOLTIP_AGE_REQUIRED))
|
||||
);
|
||||
},
|
||||
|
||||
'coppa is too young': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD, { age: 12 }))
|
||||
|
||||
// should have navigated to cannot-create-account view
|
||||
.then(testElementExists(selectors.COPPA.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'visiting the pp links saves information for return': function () {
|
||||
// Skip for now, we'll need to account for this in the React signup epic
|
||||
// if we want to keep this functionality
|
||||
this.skip();
|
||||
return testRepopulateFields.call(
|
||||
this,
|
||||
'/legal/terms',
|
||||
selectors.TOS.HEADER
|
||||
);
|
||||
},
|
||||
|
||||
'visiting the tos links saves information for return': function () {
|
||||
// Skip for now, we'll need to account for this in the React signup epic
|
||||
// if we want to keep this functionality
|
||||
this.skip();
|
||||
return testRepopulateFields.call(
|
||||
this,
|
||||
'/legal/privacy',
|
||||
selectors.PRIVACY_POLICY.HEADER
|
||||
);
|
||||
},
|
||||
|
||||
'form prefill information is cleared after signup->sign out': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testAtConfirmScreen(email))
|
||||
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
// The original tab should transition to the settings page w/ success
|
||||
// message.
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(signOut())
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
// check the email address was cleared
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, ''))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, createEmail()))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNUP_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
// check the password was cleared
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.PASSWORD, ''))
|
||||
);
|
||||
},
|
||||
|
||||
'signup, open sign-up in second tab, verify in original tab': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testAtConfirmScreen(email))
|
||||
.then(openSignUpInNewTab())
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_PASSWORD.HEADER))
|
||||
|
||||
.then(switchToWindow(0))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(switchToWindow(1))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(closeCurrentWindow());
|
||||
},
|
||||
|
||||
'signup via product page and redirect after confirm': async function () {
|
||||
if (
|
||||
process.env.CIRCLECI === 'true' &&
|
||||
!process.env.SUBHUB_STRIPE_APIKEY
|
||||
) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
// Depending on timing the final page might be the redirect page (PRODUCT_URL),
|
||||
// or might be the product page (which is a URL that ends the same, but has a
|
||||
// different domain), so we test for the path only:
|
||||
const productUrlPath = new URL(PRODUCT_URL).pathname;
|
||||
return this.remote
|
||||
.then(openPage(PRODUCT_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testAtConfirmScreen(email))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
.then(waitForUrl((url) => url.includes(productUrlPath)));
|
||||
},
|
||||
|
||||
'signup non matching passwords': function () {
|
||||
const DROWSSAP = 'drowssap';
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(
|
||||
fillOutEmailFirstSignUp(email, PASSWORD, { vpassword: DROWSSAP })
|
||||
)
|
||||
// wait five seconds to allow any errant navigation to occur
|
||||
.then(noPageTransition(selectors.SIGNUP_PASSWORD.HEADER))
|
||||
// the validation tooltip should be visible
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNUP_PASSWORD.TOOLTIP,
|
||||
'Passwords do not match'
|
||||
)
|
||||
)
|
||||
// Tooltip should disappear
|
||||
.then(type(selectors.SIGNUP_PASSWORD.VPASSWORD, PASSWORD))
|
||||
.then(pollUntilHiddenByQSA(selectors.SIGNUP_PASSWORD.TOOLTIP))
|
||||
|
||||
// Tooltip should reappear
|
||||
.then(type(selectors.SIGNUP_PASSWORD.VPASSWORD, DROWSSAP))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNUP_PASSWORD.TOOLTIP,
|
||||
'Passwords do not match'
|
||||
)
|
||||
)
|
||||
|
||||
// user can enter to next input despite tooltip error
|
||||
.then(type(selectors.SIGNUP_PASSWORD.AGE, '42'))
|
||||
);
|
||||
},
|
||||
|
||||
'sync suggestion for Fx Desktop': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceUA: UA_STRINGS['desktop_firefox_58'],
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(click(selectors.ENTER_EMAIL.LINK_SUGGEST_SYNC))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.SYNC_DESCRIPTION))
|
||||
.then(noSuchElement(selectors.ENTER_EMAIL.LINK_SUGGEST_SYNC))
|
||||
.then(testUrlInclude(SYNC_CONTEXT_DESKTOP))
|
||||
.then(testUrlInclude(SYNC_SERVICE))
|
||||
.then(testUrlInclude(ENTER_EMAIL_ENTRYPOINT));
|
||||
},
|
||||
|
||||
'sync suggestion for everyone else': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceUA: UA_STRINGS['desktop_chrome'],
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.LINK_SUGGEST_SYNC))
|
||||
.then(
|
||||
testAttributeIncludes(
|
||||
selectors.ENTER_EMAIL.LINK_SUGGEST_SYNC,
|
||||
'href',
|
||||
'utm_content=fx-sync-get-started'
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
function testRepopulateFields(dest, header) {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNUP_PASSWORD.HEADER))
|
||||
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.VPASSWORD, PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.AGE, '24'))
|
||||
|
||||
.then(click('a[href="' + dest + '"]'))
|
||||
.then(testElementExists(header))
|
||||
.then(click('.back'))
|
||||
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.EMAIL, email))
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.AGE, '24'));
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
let email;
|
||||
|
||||
const {
|
||||
click,
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
getFxaClient,
|
||||
getSignupCode,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testSuccessWasShown,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
|
||||
function testAtConfirmScreen(email) {
|
||||
return function () {
|
||||
return this.parent
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(
|
||||
testElementTextInclude(selectors.CONFIRM_SIGNUP_CODE.EMAIL_FIELD, email)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
registerSuite('signup with code', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'bounced email': function () {
|
||||
const client = getFxaClient();
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testAtConfirmScreen(email))
|
||||
.then(() => client.accountDestroy(email, PASSWORD))
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
// expect an error message to already be present on redirect
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP_BOUNCED_EMAIL))
|
||||
);
|
||||
},
|
||||
|
||||
'valid code then click back': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testAtConfirmScreen(email))
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(testSuccessWasShown())
|
||||
.goBack()
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER));
|
||||
},
|
||||
|
||||
'invalid code': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
.then(testAtConfirmScreen(email))
|
||||
.then(getSignupCode(email, 0))
|
||||
.then((code) => {
|
||||
code = code === '123123' ? '123124' : '123123';
|
||||
return this.remote.then(
|
||||
type(selectors.SIGNIN_TOKEN_CODE.INPUT, code)
|
||||
);
|
||||
})
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_TOKEN_CODE.SUBMIT,
|
||||
selectors.SIGNIN_TOKEN_CODE.TOOLTIP
|
||||
)
|
||||
)
|
||||
.then(visibleByQSA(selectors.SIGNIN_TOKEN_CODE.TOOLTIP))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.SIGNIN_TOKEN_CODE.TOOLTIP,
|
||||
'invalid or expired confirmation code'
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,183 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
/*eslint-disable camelcase */
|
||||
const productIdNameMap = {
|
||||
prod_GqM9ToKK62qjkK: '123Done Pro',
|
||||
prod_FiJ42WCzZNRSbS: 'mozilla vpn',
|
||||
};
|
||||
/*eslint-enable camelcase*/
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUserAndLoadSettings,
|
||||
fillOutFinishAccountSetup,
|
||||
fillOutEmailFirstSignIn,
|
||||
getTestProductSubscriptionUrl,
|
||||
openPage,
|
||||
openRP,
|
||||
openVerificationLinkInSameTab,
|
||||
signInToTestProduct,
|
||||
subscribeAndSigninToRp,
|
||||
subscribeToTestProductWithCardNumber,
|
||||
subscribeToTestProductWithPasswordlessAccount,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const config = intern.config;
|
||||
const ENTER_EMAIL_PAGE_URL = config.fxaContentRoot;
|
||||
|
||||
registerSuite('subscriptions', {
|
||||
tests: {
|
||||
'visit product page without signing in, expect to see product name displayed in sub-header':
|
||||
function () {
|
||||
if (
|
||||
process.env.CIRCLECI === 'true' &&
|
||||
!process.env.SUBHUB_STRIPE_APIKEY
|
||||
) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
return this.remote
|
||||
.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
force: true,
|
||||
})
|
||||
)
|
||||
.then(
|
||||
openPage(
|
||||
getTestProductSubscriptionUrl(),
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.ENTER_EMAIL.SUB_HEADER,
|
||||
`Continue to ${productIdNameMap[intern.config.testProductId]}`
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'sign up, subscribe, sign in to verify subscription': function () {
|
||||
if (
|
||||
process.env.CIRCLECI === 'true' &&
|
||||
!process.env.SUBHUB_STRIPE_APIKEY
|
||||
) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
const email = createEmail();
|
||||
return this.remote.then(subscribeAndSigninToRp(email));
|
||||
},
|
||||
'sign up, failed to subscribe due to expired CC': function () {
|
||||
if (
|
||||
process.env.CIRCLECI === 'true' &&
|
||||
!process.env.SUBHUB_STRIPE_APIKEY
|
||||
) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
const email = createEmail();
|
||||
return this.remote
|
||||
.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
force: true,
|
||||
})
|
||||
)
|
||||
.then(createUserAndLoadSettings(email))
|
||||
.then(signInToTestProduct())
|
||||
|
||||
.then(click(selectors['123DONE'].LINK_LOGOUT))
|
||||
.then(visibleByQSA(selectors['123DONE'].BUTTON_SIGNIN))
|
||||
|
||||
.then(subscribeToTestProductWithCardNumber('4000000000000069'))
|
||||
|
||||
.then(testElementTextInclude('.payment-error', 'expired'));
|
||||
},
|
||||
'sign up, failed to subscribe with mismatching currency': function () {
|
||||
if (
|
||||
process.env.CIRCLECI === 'true' &&
|
||||
!process.env.SUBHUB_STRIPE_APIKEY
|
||||
) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
const email = createEmail();
|
||||
return this.remote
|
||||
.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
force: true,
|
||||
})
|
||||
)
|
||||
.then(createUserAndLoadSettings(email))
|
||||
.then(
|
||||
subscribeToTestProductWithCardNumber(
|
||||
'4000000000000069',
|
||||
getTestProductSubscriptionUrl('myr')
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
'.payment-error',
|
||||
'It looks like your credit card has expired.'
|
||||
)
|
||||
);
|
||||
},
|
||||
'sign up for subscription with password less account': function () {
|
||||
if (
|
||||
process.env.CIRCLECI === 'true' &&
|
||||
!process.env.SUBHUB_STRIPE_APIKEY
|
||||
) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
const email = createEmail();
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
force: true,
|
||||
})
|
||||
)
|
||||
.then(openRP())
|
||||
.then(
|
||||
click(
|
||||
selectors['123DONE'].BUTTON_SUBSCRIBE_PASSWORDLESS,
|
||||
'.new-user-email-form'
|
||||
)
|
||||
)
|
||||
.then(
|
||||
subscribeToTestProductWithPasswordlessAccount(
|
||||
'4242424242424242',
|
||||
email
|
||||
)
|
||||
)
|
||||
.then(testElementExists('.payment-confirmation'))
|
||||
|
||||
// Set password on passwordless account
|
||||
.then(openVerificationLinkInSameTab(email, 0))
|
||||
.then(fillOutFinishAccountSetup(PASSWORD))
|
||||
.then(testElementExists('#splash-logo'))
|
||||
.then(
|
||||
clearBrowserState({
|
||||
'123done': true,
|
||||
force: true,
|
||||
})
|
||||
)
|
||||
.then(openPage(ENTER_EMAIL_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,135 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = config.fxaContentRoot;
|
||||
const SUPPORT_URL = config.fxaContentRoot + 'support';
|
||||
const PASSWORD = 'amazingpassword';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
openPage,
|
||||
subscribeToTestProduct,
|
||||
testUrlPathnameEquals,
|
||||
testElementExists,
|
||||
type,
|
||||
typeNative,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('support form without valid session', {
|
||||
tests: {
|
||||
'go to support form, redirects to index': function () {
|
||||
return this.remote
|
||||
.then(clearBrowserState({ force: true }))
|
||||
.then(openPage(SUPPORT_URL, selectors.ENTER_EMAIL.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('support form without active subscriptions', {
|
||||
tests: {
|
||||
'go to support form, redirects to subscription management, then back to settings': function () {
|
||||
if (
|
||||
process.env.CIRCLECI === 'true' &&
|
||||
!process.env.SUBHUB_STRIPE_APIKEY
|
||||
) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
const email = createEmail();
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(openPage(SUPPORT_URL, selectors.SETTINGS.SUB_PANELS))
|
||||
.then(testUrlPathnameEquals('/settings'));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('support form with an active subscription', {
|
||||
tests: {
|
||||
'go to support form, submits the form': function () {
|
||||
if (
|
||||
process.env.CIRCLECI === 'true' &&
|
||||
!process.env.SUBHUB_STRIPE_APIKEY
|
||||
) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
const email = createEmail();
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(subscribeToTestProduct())
|
||||
.then(openPage(SUPPORT_URL, 'div.support'))
|
||||
.then(click('#product_chosen a.chosen-single'))
|
||||
.then(
|
||||
click(
|
||||
'#product_chosen ul.chosen-results li[data-option-array-index="1"]'
|
||||
)
|
||||
)
|
||||
.then(click('#topic_chosen a.chosen-single'))
|
||||
.then(
|
||||
click(
|
||||
'#topic_chosen ul.chosen-results li[data-option-array-index="1"]'
|
||||
)
|
||||
)
|
||||
// This next bit rely on the product having at least one
|
||||
// 'support:app:...' entry in its metadata
|
||||
.then(click('#app_chosen a.chosen-single'))
|
||||
.then(
|
||||
click(
|
||||
'#app_chosen ul.chosen-results li[data-option-array-index="1"]'
|
||||
)
|
||||
)
|
||||
// test hitting enter and making sure we don't leave the form
|
||||
.then(typeNative('input[name="subject"]', 'ENTER'))
|
||||
.then(
|
||||
type(
|
||||
'textarea[name=message]',
|
||||
'please send halp for functional tests'
|
||||
)
|
||||
)
|
||||
);
|
||||
// Since we don't have proper Zendesk config in CircleCI, the form
|
||||
// cannot be successfully submitted.
|
||||
// .then(click('button[type=submit]'))
|
||||
// .then(testElementExists('.subscription-management'));
|
||||
},
|
||||
|
||||
'go to support form, cancel, redirects to subscription management': function () {
|
||||
if (
|
||||
process.env.CIRCLECI === 'true' &&
|
||||
!process.env.SUBHUB_STRIPE_APIKEY
|
||||
) {
|
||||
this.skip('missing Stripe API key in CircleCI run');
|
||||
}
|
||||
const email = createEmail();
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState())
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
.then(testElementExists(selectors.SETTINGS.HEADER))
|
||||
.then(subscribeToTestProduct())
|
||||
.then(openPage(SUPPORT_URL, 'div.support'))
|
||||
.then(click('button.cancel', '.subscription-management'));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,70 +0,0 @@
|
|||
/* eslint-disable camelcase */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const FORCE_AUTH_PAGE_URL = `${config.fxaContentRoot}force_auth?context=fx_desktop_v1&service=sync`;
|
||||
const SIGNIN_PAGE_URL = `${config.fxaContentRoot}signin?context=fx_desktop_v1&service=sync`;
|
||||
const SIGNUP_PAGE_URL = `${config.fxaContentRoot}signin?context=fx_desktop_v1&service=sync`;
|
||||
const RESET_PASSWORD_PAGE_URL = `${config.fxaContentRoot}reset_password?context=fx_desktop_v1&service=sync`;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
openPage,
|
||||
testElementExists,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('Firefox Desktop Sync v1', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
afterEach: function () {
|
||||
return this.remote.execute(() => {
|
||||
// Opening about:blank aborts the Firefox download
|
||||
// and prevents the tests from stalling when run on CentOS
|
||||
window.location.href = 'about:blank';
|
||||
});
|
||||
},
|
||||
|
||||
tests: {
|
||||
force_auth: function () {
|
||||
return this.remote
|
||||
.then(openPage(FORCE_AUTH_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER))
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
signin: function () {
|
||||
return this.remote
|
||||
.then(openPage(SIGNIN_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER))
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
signup: function () {
|
||||
return this.remote
|
||||
.then(openPage(SIGNUP_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER))
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
reset_password: function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(RESET_PASSWORD_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER)
|
||||
)
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,70 +0,0 @@
|
|||
/* eslint-disable camelcase */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const config = intern._config;
|
||||
|
||||
const FORCE_AUTH_PAGE_URL = `${config.fxaContentRoot}force_auth?context=fx_desktop_v2&service=sync`;
|
||||
const SIGNIN_PAGE_URL = `${config.fxaContentRoot}signin?context=fx_desktop_v2&service=sync`;
|
||||
const SIGNUP_PAGE_URL = `${config.fxaContentRoot}signin?context=fx_desktop_v2&service=sync`;
|
||||
const RESET_PASSWORD_PAGE_URL = `${config.fxaContentRoot}reset_password?context=fx_desktop_v2&service=sync`;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
openPage,
|
||||
testElementExists,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('Firefox Desktop Sync v2', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
afterEach: function () {
|
||||
return this.remote.execute(() => {
|
||||
// Opening about:blank aborts the Firefox download
|
||||
// and prevents the tests from stalling when run on CentOS
|
||||
window.location.href = 'about:blank';
|
||||
});
|
||||
},
|
||||
|
||||
tests: {
|
||||
force_auth: function () {
|
||||
return this.remote
|
||||
.then(openPage(FORCE_AUTH_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER))
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
signin: function () {
|
||||
return this.remote
|
||||
.then(openPage(SIGNIN_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER))
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
signup: function () {
|
||||
return this.remote
|
||||
.then(openPage(SIGNUP_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER))
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
reset_password: function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(RESET_PASSWORD_PAGE_URL, selectors.UPDATE_FIREFOX.HEADER)
|
||||
)
|
||||
.then(click(selectors.UPDATE_FIREFOX.BUTTON_DOWNLOAD_FIREFOX))
|
||||
|
||||
.then(testElementExists(selectors.DOWNLOAD_FIREFOX_THANKS.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,373 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const QUERY_PARAMS = '?context=fx_desktop_v3&service=sync&action=email';
|
||||
const INDEX_PAGE_URL = `${config.fxaContentRoot}${QUERY_PARAMS}`;
|
||||
const SIGNUP_PAGE_URL = `${config.fxaContentRoot}signup${QUERY_PARAMS}`;
|
||||
const SIGNIN_PAGE_URL = `${config.fxaContentRoot}signin${QUERY_PARAMS}`;
|
||||
|
||||
let email;
|
||||
const PASSWORD = 'PASSWORD123123';
|
||||
const PASSWORD_WITH_TYPO = 'PASSWORD1234';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutSignUpCode,
|
||||
fillOutSignInTokenCode,
|
||||
noSuchElement,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testElementTextEquals,
|
||||
testElementTextInclude,
|
||||
testElementValueEquals,
|
||||
testIsBrowserNotified,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('Firefox Desktop Sync v3 email first', {
|
||||
beforeEach() {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'open directly to /signup page, refresh on the /signup page': function () {
|
||||
return (
|
||||
this.remote
|
||||
// redirected immediately to the / page
|
||||
.then(openPage(SIGNUP_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNUP_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.refresh()
|
||||
|
||||
// refresh sends the user back to the first step
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'open directly to /signin page, refresh on the /signin page': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
// redirected immediately to the / page
|
||||
.then(openPage(SIGNIN_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.refresh()
|
||||
|
||||
// refresh sends the user back to the first step
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'enter a firefox.com address': function () {
|
||||
return this.remote
|
||||
.then(openPage(INDEX_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.SYNC_DESCRIPTION))
|
||||
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, 'testuser@firefox.com'))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT))
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP))
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors.ENTER_EMAIL.TOOLTIP,
|
||||
'firefox.com does not offer email'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
signup: function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(openPage(INDEX_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.SYNC_DESCRIPTION))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNUP_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.EMAIL, email))
|
||||
// user thinks they mistyped their email
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNUP_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
// passwords do not match should cause an error
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.SHOW_PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.VPASSWORD, PASSWORD_WITH_TYPO))
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.SHOW_VPASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.AGE, 21))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.SUBMIT,
|
||||
selectors.SIGNUP_PASSWORD.ERROR_PASSWORDS_DO_NOT_MATCH
|
||||
)
|
||||
)
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.SIGNUP_PASSWORD.TOOLTIP,
|
||||
'Passwords do not match'
|
||||
)
|
||||
)
|
||||
|
||||
// fix the password mismatch
|
||||
.then(type(selectors.SIGNUP_PASSWORD.VPASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.SUBMIT,
|
||||
selectors.CHOOSE_WHAT_TO_SYNC.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(click(selectors.CHOOSE_WHAT_TO_SYNC.SUBMIT))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'COPPA disabled': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(INDEX_PAGE_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
coppa: 'false',
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.SYNC_DESCRIPTION))
|
||||
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNUP_PASSWORD.HEADER)
|
||||
)
|
||||
.then(noSuchElement(selectors.SIGNUP_PASSWORD.AGE))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.VPASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.SUBMIT,
|
||||
selectors.CHOOSE_WHAT_TO_SYNC.HEADER
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'merge cancelled': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(INDEX_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.SYNC_DESCRIPTION))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(click(selectors.ENTER_EMAIL.SUBMIT, selectors.ENTER_EMAIL.ERROR))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'));
|
||||
},
|
||||
|
||||
'email specified by relier, invalid': function () {
|
||||
const invalidEmail = 'invalid@';
|
||||
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(INDEX_PAGE_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
email: invalidEmail,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, invalidEmail))
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.ENTER_EMAIL.TOOLTIP,
|
||||
'Valid email required'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'email specified by relier, empty string': function () {
|
||||
const emptyEmail = '';
|
||||
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(INDEX_PAGE_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
email: emptyEmail,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, emptyEmail))
|
||||
.then(visibleByQSA(selectors.ENTER_EMAIL.TOOLTIP))
|
||||
.then(
|
||||
testElementTextEquals(
|
||||
selectors.ENTER_EMAIL.TOOLTIP,
|
||||
'Valid email required'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'email specified by relier, not registered': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(INDEX_PAGE_URL, selectors.SIGNUP_PASSWORD.HEADER, {
|
||||
query: {
|
||||
email,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.EMAIL, email))
|
||||
// user realizes it's the wrong email address.
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
);
|
||||
},
|
||||
|
||||
'email specified by relier, registered': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openPage(INDEX_PAGE_URL, selectors.SIGNIN_PASSWORD.HEADER, {
|
||||
query: {
|
||||
email,
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email))
|
||||
// user realizes it's the wrong email address.
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
);
|
||||
},
|
||||
|
||||
'email specified by relier, cancel merge': function () {
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(INDEX_PAGE_URL, selectors['400'].HEADER, {
|
||||
query: {
|
||||
email,
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': { ok: false },
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(
|
||||
testElementTextInclude(
|
||||
selectors['400'].ERROR,
|
||||
'Login attempt cancelled'
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'cached credentials': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(INDEX_PAGE_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.SIGNIN_TOKEN_CODE.HEADER
|
||||
)
|
||||
)
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
|
||||
// Use cached credentials form last time, but user must enter password
|
||||
.then(openPage(INDEX_PAGE_URL, selectors.SIGNIN_PASSWORD.HEADER))
|
||||
.then(testElementValueEquals(selectors.SIGNIN_PASSWORD.EMAIL, email))
|
||||
// user wants to use a different email
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.LINK_USE_DIFFERENT,
|
||||
selectors.ENTER_EMAIL.HEADER
|
||||
)
|
||||
)
|
||||
.then(testElementValueEquals(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNIN_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(type(selectors.SIGNIN_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNIN_PASSWORD.SUBMIT,
|
||||
selectors.SIGNIN_TOKEN_CODE.HEADER
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,299 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const uaStrings = require('./lib/ua-strings');
|
||||
|
||||
let email;
|
||||
const PASSWORD = 'password12345678';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
createUID,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutForceAuth,
|
||||
fillOutSignInTokenCode,
|
||||
fillOutSignInUnblock,
|
||||
noSuchBrowserNotification,
|
||||
noSuchElement,
|
||||
openForceAuth,
|
||||
testElementDisabled,
|
||||
testElementExists,
|
||||
testElementTextInclude,
|
||||
testElementValueEquals,
|
||||
testIsBrowserNotified,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('Firefox Desktop Sync v3 force_auth', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'with a registered email, no uid': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(function (accountInfo) {
|
||||
return openForceAuth({
|
||||
query: {
|
||||
context: 'fx_desktop_v3',
|
||||
email,
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
service: 'sync',
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': {
|
||||
ok: true,
|
||||
},
|
||||
'fxaccounts:fxa_status': {
|
||||
capabilities: null,
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
}).call(this);
|
||||
})
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'));
|
||||
},
|
||||
|
||||
'with a registered email, registered uid': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(function (accountInfo) {
|
||||
return openForceAuth({
|
||||
query: {
|
||||
context: 'fx_desktop_v3',
|
||||
email: email,
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
service: 'sync',
|
||||
uid: accountInfo.uid,
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': {
|
||||
ok: true,
|
||||
},
|
||||
'fxaccounts:fxa_status': {
|
||||
capabilities: null,
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
}).call(this);
|
||||
})
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'));
|
||||
},
|
||||
|
||||
'with a registered email, unregistered uid': function () {
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openForceAuth({
|
||||
query: {
|
||||
context: 'fx_desktop_v3',
|
||||
email: email,
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
service: 'sync',
|
||||
uid: createUID(),
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': {
|
||||
ok: true,
|
||||
},
|
||||
'fxaccounts:fxa_status': {
|
||||
capabilities: null,
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(noSuchBrowserNotification('fxaccounts:logout'))
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'));
|
||||
},
|
||||
|
||||
'with an unregistered email, no uid': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openForceAuth({
|
||||
// user should be automatically redirected to the
|
||||
// signup page where they can signup with the
|
||||
// specified email
|
||||
header: selectors.SIGNUP_PASSWORD.HEADER,
|
||||
query: {
|
||||
context: 'fx_desktop_v3',
|
||||
email: email,
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
service: 'sync',
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': {
|
||||
ok: true,
|
||||
},
|
||||
'fxaccounts:fxa_status': {
|
||||
capabilities: null,
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(visibleByQSA(selectors.SIGNUP_PASSWORD.ERROR))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNUP_PASSWORD.ERROR, 'recreate')
|
||||
)
|
||||
// ensure the email is filled in, and not editible.
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.EMAIL, email))
|
||||
.then(testElementDisabled(selectors.SIGNUP_PASSWORD.EMAIL))
|
||||
.then(noSuchElement(selectors.SIGNUP_PASSWORD.LINK_USE_DIFFERENT))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD, { enterEmail: false }))
|
||||
|
||||
.then(testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.HEADER))
|
||||
.then(click(selectors.CHOOSE_WHAT_TO_SYNC.SUBMIT))
|
||||
|
||||
// the default behavior of not transitioning to the confirm
|
||||
// screen is overridden because the user is signing up outside
|
||||
// of about:accounts.
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
);
|
||||
},
|
||||
|
||||
'with an unregistered email, registered uid': function () {
|
||||
var unregisteredEmail = 'a' + email;
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(function (accountInfo) {
|
||||
return openForceAuth({
|
||||
// user should be automatically redirected to the
|
||||
// signup page where they can signup with the
|
||||
// specified email
|
||||
header: selectors.SIGNUP_PASSWORD.HEADER,
|
||||
query: {
|
||||
context: 'fx_desktop_v3',
|
||||
email: unregisteredEmail,
|
||||
service: 'sync',
|
||||
uid: accountInfo.uid,
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': {
|
||||
ok: true,
|
||||
},
|
||||
'fxaccounts:fxa_status': {
|
||||
capabilities: null,
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
}).call(this);
|
||||
})
|
||||
.then(visibleByQSA(selectors.SIGNUP_PASSWORD.ERROR))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNUP_PASSWORD.ERROR, 'recreate')
|
||||
)
|
||||
// ensure the email is filled in, and not editible.
|
||||
.then(
|
||||
testElementValueEquals(
|
||||
selectors.SIGNUP_PASSWORD.EMAIL,
|
||||
unregisteredEmail
|
||||
)
|
||||
)
|
||||
.then(testElementDisabled(selectors.SIGNUP_PASSWORD.EMAIL))
|
||||
.then(noSuchElement(selectors.SIGNUP_PASSWORD.LINK_USE_DIFFERENT))
|
||||
);
|
||||
},
|
||||
|
||||
'with an unregistered email, unregistered uid': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openForceAuth({
|
||||
// user should be automatically redirected to the
|
||||
// signup page where they can signup with the
|
||||
// specified email
|
||||
header: selectors.SIGNUP_PASSWORD.HEADER,
|
||||
query: {
|
||||
context: 'fx_desktop_v3',
|
||||
email: email,
|
||||
service: 'sync',
|
||||
uid: createUID(),
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': {
|
||||
ok: true,
|
||||
},
|
||||
'fxaccounts:fxa_status': {
|
||||
capabilities: null,
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(visibleByQSA(selectors.SIGNUP_PASSWORD.ERROR))
|
||||
.then(
|
||||
testElementTextInclude(selectors.SIGNUP_PASSWORD.ERROR, 'recreate')
|
||||
)
|
||||
// ensure the email is filled in, and not editible.
|
||||
.then(testElementValueEquals(selectors.SIGNUP_PASSWORD.EMAIL, email))
|
||||
.then(testElementDisabled(selectors.SIGNUP_PASSWORD.EMAIL))
|
||||
.then(noSuchElement(selectors.SIGNUP_PASSWORD.LINK_USE_DIFFERENT))
|
||||
);
|
||||
},
|
||||
|
||||
'verified, blocked': function () {
|
||||
email = createEmail('blocked{id}');
|
||||
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openForceAuth({
|
||||
query: {
|
||||
context: 'fx_desktop_v3',
|
||||
email: email,
|
||||
service: 'sync',
|
||||
uid: createUID(),
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(noSuchBrowserNotification('fxaccounts:logout'))
|
||||
.then(fillOutForceAuth(PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_UNBLOCK.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
.then(fillOutSignInUnblock(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,135 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const uaStrings = require('./lib/ua-strings');
|
||||
|
||||
const config = intern._config;
|
||||
|
||||
const PASSWORD = 'passwordzxcv';
|
||||
const RESET_PASSWORD_URL = `${config.fxaContentRoot}reset_password?context=fx_desktop_v3&service=sync`;
|
||||
|
||||
let email;
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
closeCurrentWindow,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutResetPassword,
|
||||
fillOutCompleteResetPassword,
|
||||
noSuchBrowserNotification,
|
||||
openPage,
|
||||
openVerificationLinkInNewTab,
|
||||
switchToWindow,
|
||||
testElementExists,
|
||||
testIsBrowserNotified,
|
||||
thenify,
|
||||
type,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const setupTest = thenify(function (query) {
|
||||
return (
|
||||
this.parent
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER, {
|
||||
query,
|
||||
})
|
||||
)
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
.then(openVerificationLinkInNewTab(email, 0))
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
.then(fillOutCompleteResetPassword(PASSWORD, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.SUB_HEADER))
|
||||
|
||||
// the verification tab sends the WebChannel message. This fixes
|
||||
// two problems: 1) initiating tab is closed, 2) The initiating
|
||||
// tab when running in E10s does not have all the necessary data
|
||||
// because localStorage is not shared.
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
.then(closeCurrentWindow())
|
||||
);
|
||||
});
|
||||
|
||||
registerSuite('Firefox Desktop Sync v3 reset password', {
|
||||
beforeEach: function () {
|
||||
// timeout after 90 seconds
|
||||
this.timeout = 90000;
|
||||
|
||||
email = createEmail();
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
|
||||
afterEach: function () {
|
||||
// clear localStorage to avoid polluting other tests.
|
||||
return this.remote.then(clearBrowserState());
|
||||
},
|
||||
tests: {
|
||||
'reset password, verify same browser': function () {
|
||||
const query = { forceUA: uaStrings['desktop_firefox_58'] };
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest(query))
|
||||
|
||||
// In fx >= 58, about:accounts expects FxA to transition after email verification
|
||||
.then(testElementExists(selectors.RESET_PASSWORD_COMPLETE.HEADER))
|
||||
// Only expect the login message in the verification tab to avoid
|
||||
// a race condition within the browser when it receives two login messages.
|
||||
.then(noSuchBrowserNotification('fxaccounts:login'))
|
||||
);
|
||||
},
|
||||
|
||||
'reset password, verify same browser, password validation': function () {
|
||||
const query = {
|
||||
forceExperiment: 'passwordStrength',
|
||||
forceExperimentGroup: 'designF',
|
||||
};
|
||||
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
|
||||
.then(fillOutResetPassword(email))
|
||||
|
||||
.then(testElementExists(selectors.CONFIRM_RESET_PASSWORD.HEADER))
|
||||
.then(openVerificationLinkInNewTab(email, 0, { query }))
|
||||
.then(switchToWindow(1))
|
||||
|
||||
.then(testElementExists(selectors.COMPLETE_RESET_PASSWORD.HEADER))
|
||||
|
||||
.then(type(selectors.COMPLETE_RESET_PASSWORD.PASSWORD, 'pass'))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD.PASSWORD_BALLOON.MIN_LENGTH_FAIL
|
||||
)
|
||||
)
|
||||
|
||||
.then(type(selectors.COMPLETE_RESET_PASSWORD.PASSWORD, 'password'))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD.PASSWORD_BALLOON.NOT_COMMON_FAIL
|
||||
)
|
||||
)
|
||||
|
||||
.then(type(selectors.COMPLETE_RESET_PASSWORD.PASSWORD, email))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.COMPLETE_RESET_PASSWORD.PASSWORD_BALLOON.NOT_EMAIL_FAIL
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,119 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const {
|
||||
click,
|
||||
clearBrowserState,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutChangePassword,
|
||||
fillOutDeleteAccount,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutSignInTokenCode,
|
||||
noSuchBrowserNotification,
|
||||
noSuchElement,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testIsBrowserNotified,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL =
|
||||
config.fxaContentRoot + '?context=fx_desktop_v3&service=sync';
|
||||
const SETTINGS_URL =
|
||||
config.fxaContentRoot + 'settings?context=fx_desktop_v3&service=sync';
|
||||
const SETTINGS_NOCONTEXT_URL = config.fxaContentRoot + 'settings';
|
||||
|
||||
const FIRST_PASSWORD = 'password';
|
||||
const SECOND_PASSWORD = 'new_password';
|
||||
let email;
|
||||
|
||||
registerSuite('Firefox Desktop Sync v3 settings', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(createUser(email, FIRST_PASSWORD, { preVerified: true }))
|
||||
.then(clearBrowserState())
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': {
|
||||
ok: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, FIRST_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.SIGNIN_TOKEN_CODE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
|
||||
// wait until account data is in localstorage before redirecting
|
||||
.then(
|
||||
FunctionalHelpers.pollUntil(
|
||||
function () {
|
||||
const accounts = Object.keys(
|
||||
JSON.parse(localStorage.getItem('__fxa_storage.accounts')) || {}
|
||||
);
|
||||
return accounts.length === 1 ? true : null;
|
||||
},
|
||||
[],
|
||||
10000
|
||||
)
|
||||
)
|
||||
|
||||
.then(openPage(SETTINGS_URL, selectors.SETTINGS.HEADER))
|
||||
);
|
||||
},
|
||||
tests: {
|
||||
'sign in, change the password': function () {
|
||||
return this.remote
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
.then(visibleByQSA(selectors.CHANGE_PASSWORD.DETAILS))
|
||||
|
||||
.then(fillOutChangePassword(FIRST_PASSWORD, SECOND_PASSWORD));
|
||||
},
|
||||
|
||||
'sign in, change the password by browsing directly to settings':
|
||||
function () {
|
||||
return this.remote
|
||||
.then(openPage(SETTINGS_NOCONTEXT_URL, selectors.SETTINGS.HEADER))
|
||||
.then(click(selectors.CHANGE_PASSWORD.MENU_BUTTON))
|
||||
.then(visibleByQSA(selectors.CHANGE_PASSWORD.DETAILS))
|
||||
.then(noSuchBrowserNotification('fxaccounts:change_password'))
|
||||
|
||||
.then(fillOutChangePassword(FIRST_PASSWORD, SECOND_PASSWORD));
|
||||
},
|
||||
|
||||
'sign in, delete the account': function () {
|
||||
return this.remote
|
||||
.then(click(selectors.SETTINGS_DELETE_ACCOUNT.DELETE_ACCOUNT_BUTTON))
|
||||
.then(visibleByQSA(selectors.SETTINGS_DELETE_ACCOUNT.DETAILS))
|
||||
|
||||
.then(fillOutDeleteAccount(FIRST_PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.ENTER_EMAIL.HEADER));
|
||||
},
|
||||
|
||||
'sign in, no way to sign out': function () {
|
||||
return (
|
||||
this.remote
|
||||
// make sure the sign out element doesn't exist
|
||||
.then(noSuchElement(selectors.SETTINGS.SIGNOUT))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,201 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const uaStrings = require('./lib/ua-strings');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?context=fx_desktop_v3&service=sync`;
|
||||
|
||||
let email;
|
||||
const PASSWORD = '12345678';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
createUser,
|
||||
fillOutEmailFirstSignIn,
|
||||
fillOutSignInTokenCode,
|
||||
fillOutSignInUnblock,
|
||||
noEmailExpected,
|
||||
openPage,
|
||||
respondToWebChannelMessage,
|
||||
testElementExists,
|
||||
testEmailExpected,
|
||||
testIsBrowserNotified,
|
||||
thenify,
|
||||
type,
|
||||
visibleByQSA,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
const setupTest = thenify(function (options = {}) {
|
||||
const signInEmail = options.signInEmail || email;
|
||||
const signUpEmail = options.signUpEmail || email;
|
||||
|
||||
const successSelector = options.blocked
|
||||
? selectors.SIGNIN_UNBLOCK.HEADER
|
||||
: options.preVerified
|
||||
? selectors.SIGNIN_TOKEN_CODE.HEADER
|
||||
: selectors.CONFIRM_SIGNUP_CODE.HEADER;
|
||||
|
||||
const query = options.query || {
|
||||
forceUA: uaStrings['desktop_firefox_58'],
|
||||
};
|
||||
return this.parent
|
||||
.then(
|
||||
createUser(signUpEmail, PASSWORD, { preVerified: options.preVerified })
|
||||
)
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query,
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(signInEmail, PASSWORD))
|
||||
.then(testElementExists(successSelector))
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'));
|
||||
});
|
||||
|
||||
registerSuite('Firefox Desktop Sync v3 signin', {
|
||||
beforeEach: function () {
|
||||
email = createEmail('sync{id}');
|
||||
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'verified, does not need to confirm ': function () {
|
||||
email = createEmail();
|
||||
const query = {
|
||||
forceUA: uaStrings['desktop_firefox_58'],
|
||||
};
|
||||
return this.remote
|
||||
.then(createUser(email, PASSWORD, { preVerified: true }))
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query,
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignIn(email, PASSWORD))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'));
|
||||
},
|
||||
|
||||
verified: function () {
|
||||
return this.remote
|
||||
.then(setupTest({ preVerified: true }))
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'));
|
||||
},
|
||||
|
||||
'verified, resend': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest({ preVerified: true }))
|
||||
|
||||
.then(click(selectors.SIGNIN_TOKEN_CODE.LINK_RESEND))
|
||||
.then(visibleByQSA(selectors.SIGNIN_TOKEN_CODE.SUCCESS))
|
||||
|
||||
// email 0 is the original signin email, open the resent email instead
|
||||
.then(fillOutSignInTokenCode(email, 1))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
);
|
||||
},
|
||||
|
||||
'verified - invalid code': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest({ preVerified: true }))
|
||||
|
||||
// Displays invalid code errors
|
||||
.then(type(selectors.SIGNIN_TOKEN_CODE.INPUT, 'INVALID'))
|
||||
.then(click(selectors.SIGNIN_TOKEN_CODE.SUBMIT))
|
||||
.then(visibleByQSA(selectors.SIGNIN_TOKEN_CODE.TOOLTIP))
|
||||
.then(fillOutSignInTokenCode(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
);
|
||||
},
|
||||
|
||||
unverified: function () {
|
||||
// this test does a lot of waiting around, give it a little extra time
|
||||
this.timeout = 60 * 1000;
|
||||
|
||||
return (
|
||||
this.remote
|
||||
.then(setupTest({ preVerified: false }))
|
||||
|
||||
// email 0 - initial sign up email
|
||||
// email 1 - sign in w/ unverified address email
|
||||
// email 2 - "You have verified your Firefox Account"
|
||||
|
||||
// there was a problem with 2 emails being sent on signin,
|
||||
// ensure only one is sent. See #3890. Check for extra email
|
||||
// must be done before opening the verification link,
|
||||
// otherwise the "Account verified!" email is sent.
|
||||
|
||||
// maxAttempts is set to avoid intererence from
|
||||
// the verification reminder emails. 5 attempts occur in 5 seconds,
|
||||
// the first verification reminder is set after 10 seconds.
|
||||
.then(noEmailExpected(email, 2, { maxAttempts: 5 }))
|
||||
.then(fillOutSignInTokenCode(email, 1))
|
||||
.then(testEmailExpected(email, 2))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
);
|
||||
},
|
||||
|
||||
'verified, blocked': function () {
|
||||
email = createEmail('blocked{id}');
|
||||
return this.remote
|
||||
.then(setupTest({ blocked: true, preVerified: true }))
|
||||
|
||||
.then(fillOutSignInUnblock(email, 0))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'));
|
||||
},
|
||||
|
||||
'verified, blocked, incorrect email case': function () {
|
||||
const signUpEmail = createEmail('blocked{id}');
|
||||
const signInEmail = signUpEmail.toUpperCase();
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
setupTest({
|
||||
blocked: true,
|
||||
preVerified: true,
|
||||
signInEmail: signInEmail,
|
||||
signUpEmail: signUpEmail,
|
||||
})
|
||||
)
|
||||
|
||||
// a second `can_link_account` request is sent to the browser after the
|
||||
// unblock code is filled in, this time with the canonicalized email address.
|
||||
// If a different user was signed in to the browser, two "merge" dialogs
|
||||
// are presented, the first for the non-canonicalized email, the 2nd for
|
||||
// the canonicalized email. Ugly UX, but at least the user can proceed.
|
||||
.then(
|
||||
respondToWebChannelMessage('fxaccounts:can_link_account', {
|
||||
ok: true,
|
||||
})
|
||||
)
|
||||
.then(fillOutSignInUnblock(signUpEmail, 0))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,235 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
const uaStrings = require('./lib/ua-strings');
|
||||
|
||||
const config = intern._config;
|
||||
const ENTER_EMAIL_URL = `${config.fxaContentRoot}?context=fx_desktop_v3&service=sync`;
|
||||
|
||||
let email;
|
||||
const PASSWORD = 'password12345678';
|
||||
|
||||
const {
|
||||
clearBrowserState,
|
||||
click,
|
||||
createEmail,
|
||||
fillOutEmailFirstSignUp,
|
||||
fillOutSignUpCode,
|
||||
noSuchElement,
|
||||
noSuchBrowserNotification,
|
||||
openPage,
|
||||
testElementExists,
|
||||
testIsBrowserNotified,
|
||||
type,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('Firefox Desktop Sync v3 signup', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return this.remote.then(clearBrowserState({ force: true }));
|
||||
},
|
||||
|
||||
tests: {
|
||||
'verify with signup code and CWTS': function () {
|
||||
email = createEmail();
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_71'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:can_link_account': { ok: true },
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
capabilities: {
|
||||
multiService: true,
|
||||
engines: ['history'],
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, email))
|
||||
.then(
|
||||
click(
|
||||
selectors.ENTER_EMAIL.SUBMIT,
|
||||
selectors.SIGNUP_PASSWORD.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(type(selectors.SIGNUP_PASSWORD.PASSWORD, PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.VPASSWORD, PASSWORD))
|
||||
.then(type(selectors.SIGNUP_PASSWORD.AGE, '24'))
|
||||
.then(
|
||||
testElementExists(
|
||||
selectors.SIGNUP_PASSWORD.CHOOSE_WHAT_TO_SYNC_HEADER
|
||||
)
|
||||
)
|
||||
// check all the expected fields are there, and only the expected fields
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.ENGINE_ADDONS))
|
||||
.then(noSuchElement(selectors.SIGNUP_PASSWORD.ENGINE_ADDRESSES))
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.ENGINE_BOOKMARKS))
|
||||
.then(noSuchElement(selectors.SIGNUP_PASSWORD.ENGINE_CREDIT_CARDS))
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.ENGINE_HISTORY))
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.ENGINE_PASSWORDS))
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.ENGINE_PREFS))
|
||||
.then(testElementExists(selectors.SIGNUP_PASSWORD.ENGINE_TABS))
|
||||
|
||||
// uncheck the passwords and history engines
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_PASSWORDS))
|
||||
.then(click(selectors.SIGNUP_PASSWORD.ENGINE_HISTORY))
|
||||
.then(
|
||||
click(
|
||||
selectors.SIGNUP_PASSWORD.SUBMIT,
|
||||
selectors.CONFIRM_SIGNUP_CODE.HEADER
|
||||
)
|
||||
)
|
||||
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
|
||||
// about:accounts does not take over, expect a screen transition.
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
);
|
||||
},
|
||||
'verify at CWTS': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_58'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
capabilities: {
|
||||
// CWTS page only shown if multi-service is not enabled
|
||||
multiService: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(noSuchElement(selectors.ENTER_EMAIL.LINK_SUGGEST_SYNC))
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
// user should be transitioned to /choose_what_to_sync
|
||||
.then(testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.HEADER))
|
||||
.then(noSuchElement(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_ADDRESSES))
|
||||
.then(
|
||||
noSuchElement(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_CREDIT_CARDS)
|
||||
)
|
||||
.then(noSuchElement(selectors.CHOOSE_WHAT_TO_SYNC.DO_NOT_SYNC))
|
||||
|
||||
.then(testIsBrowserNotified('fxaccounts:can_link_account'))
|
||||
.then(noSuchBrowserNotification('fxaccounts:login'))
|
||||
|
||||
.then(click(selectors.CHOOSE_WHAT_TO_SYNC.SUBMIT))
|
||||
|
||||
// user should be transitioned to the "go confirm your address" page
|
||||
.then(testElementExists(selectors.CONFIRM_SIGNUP_CODE.HEADER))
|
||||
|
||||
.then(fillOutSignUpCode(email, 0))
|
||||
// the login message is only sent after the sync preferences screen
|
||||
// has been cleared.
|
||||
.then(testIsBrowserNotified('fxaccounts:login'))
|
||||
|
||||
.then(testElementExists(selectors.CONNECT_ANOTHER_DEVICE.HEADER))
|
||||
);
|
||||
},
|
||||
|
||||
'engines not supported': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_58'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
// user should be transitioned to /choose_what_to_sync
|
||||
.then(testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.HEADER))
|
||||
.then(noSuchElement(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_ADDRESSES))
|
||||
.then(
|
||||
noSuchElement(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_CREDIT_CARDS)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'neither `creditcards` nor `addresses` supported': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_58'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
capabilities: {
|
||||
engines: [],
|
||||
},
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
// user should be transitioned to /choose_what_to_sync
|
||||
.then(testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.HEADER))
|
||||
.then(noSuchElement(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_ADDRESSES))
|
||||
.then(
|
||||
noSuchElement(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_CREDIT_CARDS)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
'`creditcards` and `addresses` supported': function () {
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER, {
|
||||
query: {
|
||||
forceUA: uaStrings['desktop_firefox_58'],
|
||||
},
|
||||
webChannelResponses: {
|
||||
'fxaccounts:fxa_status': {
|
||||
capabilities: {
|
||||
engines: ['creditcards', 'addresses'],
|
||||
},
|
||||
signedInUser: null,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
.then(fillOutEmailFirstSignUp(email, PASSWORD))
|
||||
|
||||
// user should be transitioned to /choose_what_to_sync
|
||||
.then(testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.HEADER))
|
||||
.then(
|
||||
testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_ADDRESSES)
|
||||
)
|
||||
.then(
|
||||
testElementExists(selectors.CHOOSE_WHAT_TO_SYNC.ENGINE_CREDIT_CARDS)
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,33 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const ENTER_EMAIL_URL = intern._config.fxaContentRoot;
|
||||
|
||||
const { click, createEmail, openPage, type } = FunctionalHelpers;
|
||||
|
||||
registerSuite('terms of service', {
|
||||
beforeEach: function () {
|
||||
return this.remote.then(FunctionalHelpers.clearBrowserState());
|
||||
},
|
||||
|
||||
tests: {
|
||||
'from signup': function () {
|
||||
return this.remote
|
||||
.then(openPage(ENTER_EMAIL_URL, selectors.ENTER_EMAIL.HEADER))
|
||||
.then(type(selectors.ENTER_EMAIL.EMAIL, createEmail()))
|
||||
.then(
|
||||
click(selectors.ENTER_EMAIL.SUBMIT, selectors.SIGNUP_PASSWORD.HEADER)
|
||||
)
|
||||
|
||||
.then(click(selectors.SIGNUP_PASSWORD.TOS, selectors.TOS.HEADER))
|
||||
.then(click(selectors.TOS.LINK_BACK, selectors.SIGNUP_PASSWORD.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,147 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
const { registerSuite } = intern.getInterface('object');
|
||||
const Constants = require('../../app/scripts/lib/constants');
|
||||
const FunctionalHelpers = require('./lib/helpers');
|
||||
const selectors = require('./lib/selectors');
|
||||
|
||||
const config = intern._config;
|
||||
const CONFIRM_EMAIL_ROOT = config.fxaContentRoot + 'verify_email';
|
||||
const PASSWORD = 'passwordcxzv';
|
||||
let email;
|
||||
let accountData;
|
||||
let code;
|
||||
let uid;
|
||||
|
||||
const {
|
||||
createEmail,
|
||||
createRandomHexString,
|
||||
createUser,
|
||||
getVerificationLink,
|
||||
noSuchElement,
|
||||
openPage,
|
||||
sendVerificationReminders,
|
||||
} = FunctionalHelpers;
|
||||
|
||||
registerSuite('verification reminders', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
createUser(email, PASSWORD, {
|
||||
preVerified: false,
|
||||
verificationMethod: 'email-otp',
|
||||
})
|
||||
)
|
||||
.then(function (result) {
|
||||
accountData = result;
|
||||
uid = accountData.uid;
|
||||
})
|
||||
|
||||
// The first email is a code, we need to wait for verification
|
||||
// reminders which contain a link.
|
||||
.then(sendVerificationReminders())
|
||||
.then(getVerificationLink(email, 1))
|
||||
|
||||
.then(function (link) {
|
||||
code = link.match(/code=([A-Za-z0-9]+)/)[1];
|
||||
})
|
||||
);
|
||||
},
|
||||
tests: {
|
||||
'open verification link with malformed code': function () {
|
||||
const code = createRandomHexString(Constants.CODE_LENGTH - 1);
|
||||
const uid = accountData.uid;
|
||||
const url = CONFIRM_EMAIL_ROOT + '?uid=' + uid + '&code=' + code;
|
||||
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(url, selectors.COMPLETE_SIGNUP.VERIFICATION_LINK_DAMAGED)
|
||||
)
|
||||
.then(
|
||||
noSuchElement(selectors.COMPLETE_SIGNUP.VERIFICATION_LINK_EXPIRED)
|
||||
);
|
||||
},
|
||||
|
||||
'open verification link with server reported bad code': function () {
|
||||
const code = createRandomHexString(Constants.CODE_LENGTH);
|
||||
const uid = accountData.uid;
|
||||
const url = CONFIRM_EMAIL_ROOT + '?uid=' + uid + '&code=' + code;
|
||||
|
||||
return this.remote.then(
|
||||
openPage(url, selectors.COMPLETE_SIGNUP.VERIFICATION_LINK_DAMAGED)
|
||||
);
|
||||
},
|
||||
|
||||
'open verification link with malformed uid': function () {
|
||||
const uid = createRandomHexString(Constants.UID_LENGTH - 1);
|
||||
const url = CONFIRM_EMAIL_ROOT + '?uid=' + uid + '&code=' + code;
|
||||
|
||||
return this.remote.then(
|
||||
openPage(url, selectors.COMPLETE_SIGNUP.VERIFICATION_LINK_DAMAGED)
|
||||
);
|
||||
},
|
||||
|
||||
'open verification link with server reported bad uid': function () {
|
||||
const uid = createRandomHexString(Constants.UID_LENGTH);
|
||||
const url = CONFIRM_EMAIL_ROOT + '?uid=' + uid + '&code=' + code;
|
||||
|
||||
return this.remote.then(
|
||||
openPage(url, selectors.COMPLETE_SIGNUP.VERIFICATION_LINK_EXPIRED)
|
||||
);
|
||||
},
|
||||
|
||||
'open valid email verification link': function () {
|
||||
const url = CONFIRM_EMAIL_ROOT + '?uid=' + uid + '&code=' + code;
|
||||
|
||||
return this.remote.then(openPage(url, selectors.SIGNUP_COMPLETE.HEADER));
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
registerSuite('verification reminders - re-sign up after reminders are sent', {
|
||||
beforeEach: function () {
|
||||
email = createEmail();
|
||||
return (
|
||||
this.remote
|
||||
.then(
|
||||
createUser(email, PASSWORD, {
|
||||
preVerified: false,
|
||||
verificationMethod: 'email-otp',
|
||||
})
|
||||
)
|
||||
.then(function (result) {
|
||||
accountData = result;
|
||||
uid = accountData.uid;
|
||||
})
|
||||
|
||||
// The first email is a code, we need to wait for verification
|
||||
// reminders which contain a link.
|
||||
.then(sendVerificationReminders())
|
||||
.then(getVerificationLink(email, 1))
|
||||
.then(function (link) {
|
||||
code = link.match(/code=([A-Za-z0-9]+)/)[1];
|
||||
})
|
||||
// re-sign up the same user with a different password, should expire
|
||||
// the original verification link.
|
||||
.then(createUser(email, 'secondpassword', { preVerified: false }))
|
||||
);
|
||||
},
|
||||
tests: {
|
||||
'open expired email verification link': function () {
|
||||
const url = CONFIRM_EMAIL_ROOT + '?uid=' + uid + '&code=' + code;
|
||||
|
||||
return this.remote
|
||||
.then(
|
||||
openPage(url, selectors.COMPLETE_SIGNUP.VERIFICATION_LINK_EXPIRED)
|
||||
)
|
||||
|
||||
.then(noSuchElement(selectors.COMPLETE_SIGNUP.LINK_RESEND));
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,39 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* Select which tests to run on circleci.
|
||||
*
|
||||
* If CIRCLE_NODE_TOTAL and CIRCLE_NODE_INDEX environment vars are defined,
|
||||
* tests are parallelized into CIRCLE_NODE_TOTAL runners. The suites are not
|
||||
* exactly the same size and will take a different amount of time to run,
|
||||
* but this is a good place to start.
|
||||
*/
|
||||
function selectCircleTests(allTests, groupsCount, groupNum) {
|
||||
var testsToRun = allTests;
|
||||
|
||||
if (process.env.CIRCLE_NODE_TOTAL) {
|
||||
console.log('CIRCLE_NODE_INDEX', process.env.CIRCLE_NODE_INDEX);
|
||||
console.log('CIRCLE_NODE_TOTAL', process.env.CIRCLE_NODE_TOTAL);
|
||||
|
||||
var circleTotal = parseInt(process.env.CIRCLE_NODE_TOTAL, 10);
|
||||
var circleIndex = parseInt(process.env.CIRCLE_NODE_INDEX, 10);
|
||||
|
||||
testsToRun = allTests.filter((test, index) => {
|
||||
var passes = index % circleTotal === circleIndex;
|
||||
return passes;
|
||||
});
|
||||
}
|
||||
|
||||
if (groupsCount && groupNum) {
|
||||
testsToRun = testsToRun.slice(
|
||||
Math.floor(((groupNum - 1) / groupsCount) * testsToRun.length),
|
||||
Math.floor((groupNum / groupsCount) * testsToRun.length)
|
||||
);
|
||||
}
|
||||
|
||||
return testsToRun;
|
||||
}
|
||||
|
||||
module.exports = selectCircleTests;
|
|
@ -1,7 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//Disabling the suite as the tests are being flaky,
|
||||
//We will revisit this later, ticket created https://mozilla-hub.atlassian.net/browse/FXA-6558
|
||||
//module.exports = ['tests/functional/pairing.js'];
|
|
@ -1,212 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const fs = require('fs');
|
||||
const intern = require('intern').default;
|
||||
const args = require('yargs').argv;
|
||||
const firefoxProfile = require('./tools/firefox_profile');
|
||||
|
||||
// Tests
|
||||
const testsMain = require('./functional');
|
||||
const testsCircleCi = require('./functional_circle')(
|
||||
testsMain,
|
||||
args.groupsCount,
|
||||
args.groupNum
|
||||
);
|
||||
const testsFunctionalSmoke = require('./functional_smoke');
|
||||
const testsFunctionalRegression = require('./functional_regression');
|
||||
const testsPairing = require('./functional_pairing');
|
||||
const testsServer = require('./tests_server');
|
||||
const testsServerResources = require('./tests_server_resources');
|
||||
const testsSettings = require('./functional_settings');
|
||||
|
||||
const fxaAuthRoot = args.fxaAuthRoot || 'http://localhost:9000/v1';
|
||||
const fxaContentRoot = args.fxaContentRoot || 'http://localhost:3030/';
|
||||
const fxaOAuthRoot = args.fxaOAuthRoot || 'http://localhost:9000';
|
||||
const fxaProfileRoot = args.fxaProfileRoot || 'http://localhost:1111';
|
||||
const fxaTokenRoot = args.fxaTokenRoot || 'http://localhost:5000/token';
|
||||
const fxaEmailRoot = args.fxaEmailRoot || 'http://localhost:9001';
|
||||
const fxaOAuthApp = args.fxaOAuthApp || 'http://localhost:8080/';
|
||||
const fxaUntrustedOauthApp =
|
||||
args.fxaUntrustedOauthApp || 'http://localhost:10139/';
|
||||
const fxaPaymentsRoot = args.fxaPaymentsRoot || 'http://localhost:3031/';
|
||||
const output = args.output || 'test-results.xml';
|
||||
const fxaSettingsV2Root = args.fxaSettingsV2Root || `${fxaContentRoot}settings`;
|
||||
|
||||
// "fxaProduction" is a little overloaded in how it is used in the tests.
|
||||
// Sometimes it means real "stage" or real production configuration, but
|
||||
// sometimes it also means fxa-dev style boxes like "latest". Configuration
|
||||
// parameter "fxaDevBox" can be used as a crude way to distinguish between
|
||||
// two.
|
||||
const fxaProduction = !!args.fxaProduction;
|
||||
const fxaDevBox = !!args.fxaDevBox;
|
||||
|
||||
const fxaToken = args.fxaToken || 'http://';
|
||||
const asyncTimeout = parseInt(args.asyncTimeout || 10000, 10);
|
||||
|
||||
// On Circle, we bail after the first failure.
|
||||
// args.bailAfterFirstFailure comes in as a string.
|
||||
const bailAfterFirstFailure = args.bailAfterFirstFailure === 'true';
|
||||
|
||||
const testProductId = args.testProductId || 'prod_GqM9ToKK62qjkK';
|
||||
const testPlanId = args.testPlanId || 'plan_GqM9N6qyhvxaVk';
|
||||
|
||||
// Intern specific options are here: https://theintern.io/docs.html#Intern/4/docs/docs%2Fconfiguration.md/properties
|
||||
const config = {
|
||||
asyncTimeout: asyncTimeout,
|
||||
bail: bailAfterFirstFailure,
|
||||
defaultTimeout: 45000, // 30 seconds just isn't long enough for some tests.
|
||||
environments: {
|
||||
browserName: 'firefox',
|
||||
fixSessionCapabilities: 'no-detect',
|
||||
usesHandleParameter: true,
|
||||
},
|
||||
filterErrorStack: true,
|
||||
functionalSuites: testsMain,
|
||||
|
||||
fxaAuthRoot: fxaAuthRoot,
|
||||
fxaContentRoot: fxaContentRoot,
|
||||
fxaSettingsV2Root: fxaSettingsV2Root,
|
||||
fxaDevBox: fxaDevBox,
|
||||
fxaEmailRoot: fxaEmailRoot,
|
||||
fxaOAuthApp: fxaOAuthApp,
|
||||
fxaOAuthRoot: fxaOAuthRoot,
|
||||
fxaProduction: fxaProduction,
|
||||
fxaProfileRoot: fxaProfileRoot,
|
||||
fxaToken: fxaToken,
|
||||
fxaTokenRoot: fxaTokenRoot,
|
||||
fxaUntrustedOauthApp: fxaUntrustedOauthApp,
|
||||
fxaPaymentsRoot,
|
||||
|
||||
pageLoadTimeout: 30000,
|
||||
reporters: [
|
||||
{
|
||||
name: 'junit',
|
||||
options: {
|
||||
filename: output,
|
||||
},
|
||||
},
|
||||
'runner',
|
||||
],
|
||||
serverPort: 9091,
|
||||
serverUrl: 'http://localhost:9091',
|
||||
socketPort: 9077,
|
||||
tunnelOptions: {
|
||||
drivers: [
|
||||
{
|
||||
name: 'firefox',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
testProductId,
|
||||
testPlanId,
|
||||
};
|
||||
|
||||
if (args.grep) {
|
||||
config.grep = new RegExp(args.grep, 'i');
|
||||
}
|
||||
|
||||
if (args.suites) {
|
||||
switch (args.suites) {
|
||||
case 'pairing':
|
||||
config.functionalSuites = testsPairing;
|
||||
config.isTestingPairing = true;
|
||||
break;
|
||||
case 'functional_smoke':
|
||||
config.functionalSuites = testsFunctionalSmoke;
|
||||
break;
|
||||
case 'functional_regression':
|
||||
config.functionalSuites = testsFunctionalRegression;
|
||||
break;
|
||||
case 'settings':
|
||||
config.functionalSuites = testsSettings;
|
||||
break;
|
||||
case 'all':
|
||||
config.functionalSuites = testsMain;
|
||||
break;
|
||||
case 'circle':
|
||||
config.functionalSuites = testsCircleCi;
|
||||
console.log('Running tests:', config.functionalSuites);
|
||||
break;
|
||||
case 'server':
|
||||
case 'server-resources':
|
||||
config.functionalSuites = [];
|
||||
config.node = {
|
||||
suites: testsServer,
|
||||
};
|
||||
config.tunnelOptions = {};
|
||||
config.environments = {
|
||||
browserName: 'node',
|
||||
};
|
||||
config.reporters = 'pretty';
|
||||
if (args.suites === 'server-resources') {
|
||||
config.node.suites = testsServerResources;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (args.unit) {
|
||||
config.functionalSuites.unshift('tests/functional/mocha.js');
|
||||
}
|
||||
|
||||
if (args.groups !== undefined && args.groupIndex !== undefined) {
|
||||
const index = args.groupIndex;
|
||||
const groups = args.groups;
|
||||
const groupSize = Math.ceil(config.functionalSuites.length / groups);
|
||||
const originalSuiteSize = config.functionalSuites.length;
|
||||
const targeted = config.functionalSuites.splice(groupSize * index, groupSize);
|
||||
|
||||
console.log(`Running group ${args.groupIndex + 1} of ${args.groups}.`);
|
||||
console.log(
|
||||
`Running ${targeted.length} of ${originalSuiteSize} tests suites.`
|
||||
);
|
||||
|
||||
// Target a 'block' of tests to run
|
||||
config.functionalSuites = targeted;
|
||||
}
|
||||
|
||||
config.capabilities = {};
|
||||
config.capabilities['moz:firefoxOptions'] = {};
|
||||
// to create a profile, give it the `config` option.
|
||||
config.capabilities['moz:firefoxOptions'].profile = firefoxProfile(config); //eslint-disable-line camelcase
|
||||
// uncomment to show devtools on launch
|
||||
// config.capabilities['moz:firefoxOptions'].args = ['-devtools'];
|
||||
|
||||
// custom Firefox binary location, if specified then the default is ignored.
|
||||
// ref: https://code.google.com/p/selenium/wiki/DesiredCapabilities#WebDriver
|
||||
if (args.firefoxBinary) {
|
||||
config.capabilities['moz:firefoxOptions'].binary = args.firefoxBinary; //eslint-disable-line camelcase
|
||||
}
|
||||
|
||||
const failed = [];
|
||||
|
||||
intern.on('suiteEnd', (test) => {
|
||||
if (test.error) {
|
||||
failed.push(test);
|
||||
}
|
||||
});
|
||||
|
||||
intern.on('testEnd', (test) => {
|
||||
if (test.error) {
|
||||
failed.push(test);
|
||||
}
|
||||
});
|
||||
|
||||
intern.on('afterRun', () => {
|
||||
if (failed.length) {
|
||||
// This text output is used later to target tests to rerun. The value
|
||||
// is essentially just a big regex. Note that that the postfixed $
|
||||
// helps the regex be more precisely.
|
||||
fs.writeFileSync('rerun.txt', failed.map((f) => `${f.name}$`).join('|'));
|
||||
}
|
||||
});
|
||||
|
||||
intern.configure(config);
|
||||
intern.run().catch((e) => {
|
||||
// This might not throw, BUG filed: https://github.com/theintern/intern/issues/868
|
||||
console.log(e);
|
||||
process.exit(1);
|
||||
});
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
const request = require('./request');
|
||||
|
||||
const config = intern._config;
|
||||
const EMAIL_SERVER_ROOT = config.fxaEmailRoot;
|
||||
const EMAIL_SERVER_ROOT = 'http://localhost:9001';
|
||||
|
||||
/**
|
||||
* Wait for an email.
|
||||
|
|
Загрузка…
Ссылка в новой задаче