Merge pull request #15861 from mozilla/create-smoke-test-suite

config(functional): remove content-server-remote steps for old tests
This commit is contained in:
Ankita Shrivastava 2023-10-05 14:37:10 -04:00 коммит произвёл GitHub
Родитель fd43506d54 8051e36ff8
Коммит df2685bfac
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
56 изменённых файлов: 5776 добавлений и 5568 удалений

Просмотреть файл

@ -265,28 +265,6 @@ commands:
- fxa-yarn-001-{{ checksum "yarn.lock" }}
- fxa-yarn-001-
test-content-server-remote-part:
parameters:
index:
type: integer
total:
type: integer
steps:
- git-checkout
- provision
- run:
name: Running test section << parameters.index >> of << parameters.total >>
environment:
CIRCLE_NODE_INDEX: << parameters.index >>
CIRCLE_NODE_TOTAL: << parameters.total >>
ACCOUNTS_DOMAIN: << pipeline.parameters.accounts-domain >>
PAYMENTS_DOMAIN: << pipeline.parameters.payments-domain >>
ACCOUNTS_API_DOMAIN: << pipeline.parameters.accounts-api-domain >>
RELIER_DOMAIN: << pipeline.parameters.relier-domain >>
UNTRUSTED_RELIER_DOMAIN: << pipeline.parameters.untrusted-relier-domain >>
command: ./packages/fxa-content-server/scripts/test-ci-remote.sh
- store-artifacts
wait-for-infrastructure:
steps:
- run:
@ -329,14 +307,20 @@ commands:
command: |
if [[ "<< parameters.project >>" == "production" ]]; then
export FEATURE_FLAGS_SHOW_RECOVERY_KEY_V2=true
GREP="--grep=\"severity-1\""
elif [[ "<< parameters.project >>" == "stage" ]]; then
export FEATURE_FLAGS_SHOW_RECOVERY_KEY_V2=true
GREP="--grep=\"severity-(1|2)\""
else
export FEATURE_FLAGS_SHOW_RECOVERY_KEY_V2=true
GREP=""
fi
echo "targeting project << parameters.project >> $GREP"
npx nx build fxa-auth-client
cd packages/functional-tests/tests
TEST_FILES=$(circleci tests glob "./**/*.spec.ts")
cd ..
echo $TEST_FILES | circleci tests run --command="xargs yarn playwright test --project=<< parameters.project >>" --verbose --split-by=timings
echo $TEST_FILES | circleci tests run --command="xargs yarn playwright test --project=<< parameters.project >> $GREP" --verbose --split-by=timings
environment:
NODE_OPTIONS: --dns-result-order=ipv4first
JEST_JUNIT_OUTPUT_DIR: ./artifacts/tests
@ -620,37 +604,6 @@ jobs:
no_output_timeout: 20m
- store-artifacts
# This job is manually triggered for now. see .circleci/README.md
test-content-server-remote:
executor: smoke-test-executor
steps:
- git-checkout
- provision
- run:
name: Running test section against a remote target
command: ./packages/fxa-content-server/scripts/test-ci-remote.sh
- store-artifacts
# These jobs are manually triggered for now. see .circleci/README.md
test-content-server-remote-part-0:
executor: smoke-test-executor
steps:
- test-content-server-remote-part:
index: 0
total: 3
test-content-server-remote-part-1:
executor: smoke-test-executor
steps:
- test-content-server-remote-part:
index: 1
total: 3
test-content-server-remote-part-2:
executor: smoke-test-executor
steps:
- test-content-server-remote-part:
index: 2
total: 3
# Deprecated - use workflows in conjunction with smoke-tests job instead!
# This job is manually triggered for now. see .circleci/README.md
production-smoke-tests:

Просмотреть файл

@ -4,73 +4,75 @@
import { test, expect } from '../../lib/fixtures/standard';
test.describe('force auth', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
const config = await configPage.getConfig();
// TODO: Remove forceAuth tests. React pages don't have this flow.
test.skip(config.showReactApp.resetPasswordRoutes === true);
});
test('with a registered email, registered uid', async ({
credentials,
pages: { login, forceAuth },
}) => {
await forceAuth.open(credentials);
await login.setPassword(credentials.password);
await login.submit();
expect(await login.isUserLoggedIn()).toBe(true);
});
test.describe('severity-1 #smoke', () => {
test.describe('force auth', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
const config = await configPage.getConfig();
// TODO: Remove forceAuth tests. React pages don't have this flow.
test.skip(config.showReactApp.resetPasswordRoutes === true);
});
test('with a registered email, registered uid', async ({
credentials,
pages: { login, forceAuth },
}) => {
await forceAuth.open(credentials);
await login.setPassword(credentials.password);
await login.submit();
expect(await login.isUserLoggedIn()).toBe(true);
});
test('forgot password flow via force_auth', async ({
credentials,
pages: { login, resetPassword, forceAuth },
}) => {
await forceAuth.open(credentials);
await login.clickForgotPassword();
test('forgot password flow via force_auth', async ({
credentials,
pages: { login, resetPassword, forceAuth },
}) => {
await forceAuth.open(credentials);
await login.clickForgotPassword();
// Verify reset password header
await resetPassword.resetPasswordHeader();
// Verify reset password header
await resetPassword.resetPasswordHeader();
//Verify email is prefilled
expect(await login.getPrefilledEmail()).toContain(credentials.email);
//Verify email is prefilled
expect(await login.getPrefilledEmail()).toContain(credentials.email);
//Click 'Remember password? Sign in', redirected to force auth page
await resetPassword.clickRememberPassword();
expect(await login.getPrefilledEmail()).toContain(credentials.email);
//Click 'Remember password? Sign in', redirected to force auth page
await resetPassword.clickRememberPassword();
expect(await login.getPrefilledEmail()).toContain(credentials.email);
//Click forgot password again
await login.clickForgotPassword();
await resetPassword.clickBeginReset();
//Click forgot password again
await login.clickForgotPassword();
await resetPassword.clickBeginReset();
//Verify confirm reset password header
await resetPassword.confirmResetPasswordHeader();
//Verify confirm reset password header
await resetPassword.confirmResetPasswordHeader();
//Click 'Remember password? Sign in', redirected to force auth page
await resetPassword.clickRememberPassword();
expect(await login.getPrefilledEmail()).toContain(credentials.email);
});
//Click 'Remember password? Sign in', redirected to force auth page
await resetPassword.clickRememberPassword();
expect(await login.getPrefilledEmail()).toContain(credentials.email);
});
test('form prefill information is cleared after sign in->sign out', async ({
credentials,
pages: { login, forceAuth, settings },
}) => {
await forceAuth.open(credentials);
await login.setPassword(credentials.password);
await login.submit();
expect(await login.isUserLoggedIn()).toBe(true);
test('form prefill information is cleared after sign in->sign out', async ({
credentials,
pages: { login, forceAuth, settings },
}) => {
await forceAuth.open(credentials);
await login.setPassword(credentials.password);
await login.submit();
expect(await login.isUserLoggedIn()).toBe(true);
//Sign out
await settings.signOut();
//Sign out
await settings.signOut();
//Verify user need to enter email
await login.waitForEmailHeader();
await login.setEmail(credentials.email);
await login.submit();
//Verify user need to enter email
await login.waitForEmailHeader();
await login.setEmail(credentials.email);
await login.submit();
//Verify password is empty and user need to enter password
await login.waitForPasswordHeader();
expect(await login.getPasswordInput()).toContain('');
await login.setPassword(credentials.password);
await login.submit();
expect(await login.isUserLoggedIn()).toBe(true);
//Verify password is empty and user need to enter password
await login.waitForPasswordHeader();
expect(await login.getPasswordInput()).toContain('');
await login.setPassword(credentials.password);
await login.submit();
expect(await login.isUserLoggedIn()).toBe(true);
});
});
});

Просмотреть файл

@ -1,3 +1,7 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
test.describe('404', () => {

Просмотреть файл

@ -1,70 +1,77 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
test.describe('OAuth force auth', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
const config = await configPage.getConfig();
// TODO: Remove forceAuth tests. React pages don't have this flow.
test.skip(config.showReactApp.resetPasswordRoutes === true);
});
test('with a registered email', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto(`email=${credentials.email}`);
await relier.clickForceAuth();
test.describe('severity-1 #smoke', () => {
test.describe('OAuth force auth', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
const config = await configPage.getConfig();
// TODO: Remove forceAuth tests. React pages don't have this flow.
test.skip(config.showReactApp.resetPasswordRoutes === true);
});
test('with a registered email', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto(`email=${credentials.email}`);
await relier.clickForceAuth();
// Email is prefilled
await expect(await login.page.innerText('#prefillEmail')).toContain(
credentials.email
);
await login.setPassword(credentials.password);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
});
// Email is prefilled
await expect(await login.page.innerText('#prefillEmail')).toContain(
credentials.email
);
await login.setPassword(credentials.password);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
});
test('with a unregistered email', async ({
credentials,
pages: { login, relier },
}, { project }) => {
test.slow(project.name !== 'local', 'email delivery can be slow');
const newEmail = `${Date.now()}@restmail.net`;
await relier.goto(`email=${newEmail}`);
await relier.clickForceAuth();
test('with a unregistered email', async ({
credentials,
pages: { login, relier },
}, { project }) => {
test.slow(project.name !== 'local', 'email delivery can be slow');
const newEmail = `${Date.now()}@restmail.net`;
await relier.goto(`email=${newEmail}`);
await relier.clickForceAuth();
// Signup form is shown and email is prefilled
await expect(await login.getPrefilledEmail()).toContain(newEmail);
await login.setAge('21');
await login.setNewPassword(credentials.password);
await login.fillOutSignUpCode(newEmail);
// Signup form is shown and email is prefilled
await expect(await login.getPrefilledEmail()).toContain(newEmail);
await login.setAge('21');
await login.setNewPassword(credentials.password);
await login.fillOutSignUpCode(newEmail);
expect(await relier.isLoggedIn()).toBe(true);
});
expect(await relier.isLoggedIn()).toBe(true);
});
test('with blocked email', async ({ credentials, pages: { login, relier } }, {
project,
}) => {
test.slow(project.name !== 'local', 'email delivery can be slow');
test('with blocked email', async ({
credentials,
pages: { login, relier },
}, { project }) => {
test.slow(project.name !== 'local', 'email delivery can be slow');
const blockedEmail = `blocked${Date.now()}@restmail.net`;
await relier.goto(`email=${blockedEmail}`);
await relier.clickForceAuth();
const blockedEmail = `blocked${Date.now()}@restmail.net`;
await relier.goto(`email=${blockedEmail}`);
await relier.clickForceAuth();
await expect(await login.getPrefilledEmail()).toContain(blockedEmail);
await login.setAge('21');
await login.setNewPassword(credentials.password);
await login.fillOutSignUpCode(blockedEmail);
await expect(await login.getPrefilledEmail()).toContain(blockedEmail);
await login.setAge('21');
await login.setNewPassword(credentials.password);
await login.fillOutSignUpCode(blockedEmail);
expect(await relier.isLoggedIn()).toBe(true);
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
await relier.signOut();
// Attempt to log in again which will show the blocked page
await relier.goto(`email=${blockedEmail}`);
await relier.clickForceAuth();
await login.setPassword(credentials.password);
await login.submit();
// Attempt to log in again which will show the blocked page
await relier.goto(`email=${blockedEmail}`);
await relier.clickForceAuth();
await login.setPassword(credentials.password);
await login.submit();
await login.unblock(blockedEmail);
expect(await relier.isLoggedIn()).toBe(true);
await login.unblock(blockedEmail);
expect(await relier.isLoggedIn()).toBe(true);
});
});
});

Просмотреть файл

@ -1,97 +1,103 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
const PASSWORD = 'passwordzxcv';
test.describe('OAuth `login_hint` and `email` param', () => {
test('email specified by relier, invalid', async ({
pages: { login, relier },
}) => {
const invalidEmail = 'invalid@';
await relier.goto(`email=${invalidEmail}`);
await relier.clickEmailFirst();
const error = await login.getTooltipError();
expect(error).toContain('Valid email required');
});
test.describe('severity-2 #smoke', () => {
test.describe('OAuth `login_hint` and `email` param', () => {
test('email specified by relier, invalid', async ({
pages: { login, relier },
}) => {
const invalidEmail = 'invalid@';
await relier.goto(`email=${invalidEmail}`);
await relier.clickEmailFirst();
const error = await login.getTooltipError();
expect(error).toContain('Valid email required');
});
test('login_hint specified by relier, not registered', async ({
pages: { login, relier },
}) => {
const email = login.createEmail();
await relier.goto(`login_hint=${email}`);
await relier.clickEmailFirst();
test('login_hint specified by relier, not registered', async ({
pages: { login, relier },
}) => {
const email = login.createEmail();
await relier.goto(`login_hint=${email}`);
await relier.clickEmailFirst();
// Email is prefilled
await expect(await login.getPrefilledEmail()).toEqual(email);
expect(await login.signUpPasswordHeader()).toEqual(true);
// Email is prefilled
await expect(await login.getPrefilledEmail()).toEqual(email);
expect(await login.signUpPasswordHeader()).toEqual(true);
await login.useDifferentAccountLink();
await login.useDifferentAccountLink();
// Email first page has email input prefilled
await expect(await login.getEmailInput()).toEqual(email);
});
// Email first page has email input prefilled
await expect(await login.getEmailInput()).toEqual(email);
});
test('email specified by relier, registered', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto(`email=${credentials.email}`);
await relier.clickEmailFirst();
test('email specified by relier, registered', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto(`email=${credentials.email}`);
await relier.clickEmailFirst();
// Email is prefilled
await expect(await login.getPrefilledEmail()).toEqual(credentials.email);
expect(await login.signInPasswordHeader()).toEqual(true);
// Email is prefilled
await expect(await login.getPrefilledEmail()).toEqual(credentials.email);
expect(await login.signInPasswordHeader()).toEqual(true);
await login.useDifferentAccountLink();
await login.useDifferentAccountLink();
// Email first page has email input prefilled
await expect(await login.getEmailInput()).toEqual(credentials.email);
});
// Email first page has email input prefilled
await expect(await login.getEmailInput()).toEqual(credentials.email);
});
test('login_hint specified by relier, registered', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto(`login_hint=${credentials.email}`);
await relier.clickEmailFirst();
test('login_hint specified by relier, registered', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto(`login_hint=${credentials.email}`);
await relier.clickEmailFirst();
// Email is prefilled
await expect(await login.getPrefilledEmail()).toEqual(credentials.email);
expect(await login.signInPasswordHeader()).toEqual(true);
// Email is prefilled
await expect(await login.getPrefilledEmail()).toEqual(credentials.email);
expect(await login.signInPasswordHeader()).toEqual(true);
await login.useDifferentAccountLink();
await login.useDifferentAccountLink();
// Email first page has email input prefilled
await expect(await login.getEmailInput()).toEqual(credentials.email);
});
// Email first page has email input prefilled
await expect(await login.getEmailInput()).toEqual(credentials.email);
});
test('cached credentials, login_hint specified by relier', async ({
target,
pages: { login, relier },
}) => {
const email = login.createEmail();
await target.createAccount(email, PASSWORD);
test('cached credentials, login_hint specified by relier', async ({
target,
pages: { login, relier },
}) => {
const email = login.createEmail();
await target.createAccount(email, PASSWORD);
const loginHintEmail = login.createEmail();
await target.createAccount(loginHintEmail, PASSWORD);
const loginHintEmail = login.createEmail();
await target.createAccount(loginHintEmail, PASSWORD);
// Create a cached login
await relier.goto();
await relier.clickEmailFirst();
await login.login(email, PASSWORD);
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
// Create a cached login
await relier.goto();
await relier.clickEmailFirst();
await login.login(email, PASSWORD);
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
// login_hint takes precedence over the signed-in user
await relier.goto(`login_hint=${loginHintEmail}`);
await relier.clickEmailFirst();
// login_hint takes precedence over the signed-in user
await relier.goto(`login_hint=${loginHintEmail}`);
await relier.clickEmailFirst();
// Email is prefilled
await expect(await login.getPrefilledEmail()).toEqual(loginHintEmail);
expect(await login.signInPasswordHeader()).toEqual(true);
// Email is prefilled
await expect(await login.getPrefilledEmail()).toEqual(loginHintEmail);
expect(await login.signInPasswordHeader()).toEqual(true);
await login.useDifferentAccountLink();
await login.useDifferentAccountLink();
// Email first page has email input prefilled
await expect(await login.getEmailInput()).toEqual(loginHintEmail);
// Email first page has email input prefilled
await expect(await login.getEmailInput()).toEqual(loginHintEmail);
});
});
});

Просмотреть файл

@ -7,171 +7,173 @@ import { test, expect } from '../../lib/fixtures/standard';
let email;
const password = 'passwordzxcv';
test.describe('oauth permissions for trusted reliers - sign up', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
email = login.createEmail();
await login.clearCache();
});
test.describe('severity-1 #smoke', () => {
test.describe('oauth permissions for trusted reliers - sign up', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
email = login.createEmail();
await login.clearCache();
});
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
}
});
test('signup without `prompt=consent`', async ({
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password, { verify: false });
//no permissions asked for, straight to confirm
await login.waitForSignUpCodeHeader();
});
test('signup with `prompt=consent`', async ({
target,
page,
pages: { login, relier },
}) => {
const query = { prompt: 'consent' };
const queryParam = new URLSearchParams(query);
await page.goto(`${target.relierUrl}/?${queryParam.toString()}`, {
waitUntil: 'load',
});
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password, { verify: false });
//Verify permissions header
expect(await login.permissionsHeader()).toBe(true);
await login.acceptOauthPermissions();
test('signup without `prompt=consent`', async ({
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password, { verify: false });
//Verify sign up code header
await login.waitForSignUpCodeHeader();
});
});
test.describe('oauth permissions for trusted reliers - sign in', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
await login.clearCache();
});
test('signin without `prompt=consent`', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutEmailFirstSignIn(
credentials.email,
credentials.password
);
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
test('signin with `prompt=consent`', async ({
target,
page,
credentials,
pages: { login, relier },
}) => {
const query = { prompt: 'consent' };
const queryParam = new URLSearchParams(query);
await page.goto(`${target.relierUrl}/?${queryParam.toString()}`, {
waitUntil: 'load',
});
await relier.clickEmailFirst();
await login.fillOutEmailFirstSignIn(
credentials.email,
credentials.password
);
//Verify permissions header
expect(await login.permissionsHeader()).toBe(true);
await login.acceptOauthPermissions();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
test('signin without `prompt=consent`, then re-signin with `prompt=consent`', async ({
target,
page,
credentials,
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutEmailFirstSignIn(
credentials.email,
credentials.password
);
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
const query = { prompt: 'consent' };
const queryParam = new URLSearchParams(query);
await page.goto(`${target.relierUrl}/?${queryParam.toString()}`, {
waitUntil: 'load',
});
await relier.clickEmailFirst();
await login.clickSignIn();
//Verify permissions header
expect(await login.permissionsHeader()).toBe(true);
await login.acceptOauthPermissions();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
test('force_auth without `prompt=consent`', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto(`email=${credentials.email}`);
await relier.clickForceAuth();
await login.setPassword(credentials.password);
await login.submit();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
test('force_auth with `prompt=consent`', async ({
target,
page,
credentials,
pages: { login, relier },
}) => {
const query = new URLSearchParams({
prompt: 'consent',
email: credentials.email,
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.clickForceAuth();
await login.setPassword(credentials.password);
await login.submit();
//Verify permissions header
expect(await login.permissionsHeader()).toBe(true);
await login.acceptOauthPermissions();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
//no permissions asked for, straight to confirm
await login.waitForSignUpCodeHeader();
});
test('signup with `prompt=consent`', async ({
target,
page,
pages: { login, relier },
}) => {
const query = { prompt: 'consent' };
const queryParam = new URLSearchParams(query);
await page.goto(`${target.relierUrl}/?${queryParam.toString()}`, {
waitUntil: 'load',
});
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password, { verify: false });
//Verify permissions header
expect(await login.permissionsHeader()).toBe(true);
await login.acceptOauthPermissions();
//Verify sign up code header
await login.waitForSignUpCodeHeader();
});
});
test.describe('oauth permissions for trusted reliers - sign in', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
await login.clearCache();
});
test('signin without `prompt=consent`', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutEmailFirstSignIn(
credentials.email,
credentials.password
);
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
test('signin with `prompt=consent`', async ({
target,
page,
credentials,
pages: { login, relier },
}) => {
const query = { prompt: 'consent' };
const queryParam = new URLSearchParams(query);
await page.goto(`${target.relierUrl}/?${queryParam.toString()}`, {
waitUntil: 'load',
});
await relier.clickEmailFirst();
await login.fillOutEmailFirstSignIn(
credentials.email,
credentials.password
);
//Verify permissions header
expect(await login.permissionsHeader()).toBe(true);
await login.acceptOauthPermissions();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
test('signin without `prompt=consent`, then re-signin with `prompt=consent`', async ({
target,
page,
credentials,
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutEmailFirstSignIn(
credentials.email,
credentials.password
);
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
const query = { prompt: 'consent' };
const queryParam = new URLSearchParams(query);
await page.goto(`${target.relierUrl}/?${queryParam.toString()}`, {
waitUntil: 'load',
});
await relier.clickEmailFirst();
await login.clickSignIn();
//Verify permissions header
expect(await login.permissionsHeader()).toBe(true);
await login.acceptOauthPermissions();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
test('force_auth without `prompt=consent`', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto(`email=${credentials.email}`);
await relier.clickForceAuth();
await login.setPassword(credentials.password);
await login.submit();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
test('force_auth with `prompt=consent`', async ({
target,
page,
credentials,
pages: { login, relier },
}) => {
const query = new URLSearchParams({
prompt: 'consent',
email: credentials.email,
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.clickForceAuth();
await login.setPassword(credentials.password);
await login.submit();
//Verify permissions header
expect(await login.permissionsHeader()).toBe(true);
await login.acceptOauthPermissions();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
});
});

Просмотреть файл

@ -7,258 +7,261 @@ import { test, expect } from '../../lib/fixtures/standard';
let email;
const password = 'passwordzxcv';
test.describe('oauth prompt none', () => {
test.beforeEach(async ({ pages: { login } }, { project }) => {
test.slow();
test.describe('severity-1 #smoke', () => {
test.describe('oauth prompt none', () => {
test.beforeEach(async ({ pages: { login } }, { project }) => {
test.slow();
//Epic Fxa-7861 filed for the work to add plans in prod
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
email = login.createEmail();
await login.clearCache();
//Epic Fxa-7861 filed for the work to add plans in prod
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
email = login.createEmail();
await login.clearCache();
});
test('fails if no user logged in', async ({
page,
target,
pages: { relier },
}) => {
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain('User is not signed in');
});
test('fails RP that is not allowed', async ({ page, pages: { relier } }, {
project,
}) => {
test.skip(
project.name !== 'local',
'we dont have an untrusted oauth for stage and prod'
);
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
});
await page.goto(`http://localhost:10139` + `/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain(
'prompt=none is not enabled for this client'
);
});
test('fails if requesting keys', async ({
page,
target,
pages: { relier },
}) => {
const query = new URLSearchParams({
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',
// eslint-disable-next-line camelcase
keys_jwk:
'eyJrdHkiOiJFQyIsImtpZCI6Im9DNGFudFBBSFZRX1pmQ09RRUYycTRaQlZYblVNZ2xISGpVRzdtSjZHOEEiLCJjcnYiOi' +
'JQLTI1NiIsIngiOiJDeUpUSjVwbUNZb2lQQnVWOTk1UjNvNTFLZVBMaEg1Y3JaQlkwbXNxTDk0IiwieSI6IkJCWDhfcFVZeHpTaldsdX' +
'U5MFdPTVZwamIzTlpVRDAyN0xwcC04RW9vckEifQ',
login_hint: email, // eslint-disable-line camelcase
redirect_uri:
'https://mozilla.github.io/notes/fxa/android-redirect.html', // eslint-disable-line camelcase
scope: 'profile https://identity.mozilla.com/apps/notes',
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain(
'prompt=none cannot be used when requesting keys'
);
});
test('fails if session is no longer valid', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await target.auth.accountDestroy(email, password);
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain('User is not signed in');
});
test('fails if account is not verified', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'false',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify sign up code header
await login.waitForSignUpCodeHeader();
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain(
'Unverified user or session'
);
});
});
test('fails if no user logged in', async ({
page,
target,
pages: { relier },
}) => {
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
test.describe('oauth prompt none with emails', () => {
test.beforeEach(async ({ pages: { login } }, { project }) => {
test.slow();
//Epic Fxa-7861 filed for the work to add plans in prod
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
email = login.createEmail();
await login.clearCache();
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain('User is not signed in');
});
test('fails RP that is not allowed', async ({ page, pages: { relier } }, {
project,
}) => {
test.skip(
project.name !== 'local',
'we dont have an untrusted oauth for stage and prod'
);
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
});
await page.goto(`http://localhost:10139` + `/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain(
'prompt=none is not enabled for this client'
);
});
test('fails if requesting keys', async ({
page,
target,
pages: { relier },
}) => {
const query = new URLSearchParams({
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',
// eslint-disable-next-line camelcase
keys_jwk:
'eyJrdHkiOiJFQyIsImtpZCI6Im9DNGFudFBBSFZRX1pmQ09RRUYycTRaQlZYblVNZ2xISGpVRzdtSjZHOEEiLCJjcnYiOi' +
'JQLTI1NiIsIngiOiJDeUpUSjVwbUNZb2lQQnVWOTk1UjNvNTFLZVBMaEg1Y3JaQlkwbXNxTDk0IiwieSI6IkJCWDhfcFVZeHpTaldsdX' +
'U5MFdPTVZwamIzTlpVRDAyN0xwcC04RW9vckEifQ',
login_hint: email, // eslint-disable-line camelcase
redirect_uri: 'https://mozilla.github.io/notes/fxa/android-redirect.html', // eslint-disable-line camelcase
scope: 'profile https://identity.mozilla.com/apps/notes',
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain(
'prompt=none cannot be used when requesting keys'
);
});
test('fails if session is no longer valid', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await target.auth.accountDestroy(email, password);
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain('User is not signed in');
});
test('fails if account is not verified', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'false',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify sign up code header
await login.waitForSignUpCodeHeader();
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain(
'Unverified user or session'
);
});
});
test.describe('oauth prompt none with emails', () => {
test.beforeEach(async ({ pages: { login } }, { project }) => {
test.slow();
//Epic Fxa-7861 filed for the work to add plans in prod
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
email = login.createEmail();
await login.clearCache();
});
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
}
});
test('fails if no login_hint', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
test('fails if no login_hint', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
const query = new URLSearchParams({
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain(
'Missing OAuth parameter: login_hint'
);
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
test('fails if login_hint is different to logged in user', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
const query = new URLSearchParams({
return_on_error: 'false',
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
const query = new URLSearchParams({
login_hint: login.createEmail(),
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain(
'A different user is signed in'
);
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
test('succeeds if login_hint same as logged in user', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify error message
expect(await relier.promptNoneError()).toContain(
'Missing OAuth parameter: login_hint'
);
});
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
test('fails if login_hint is different to logged in user', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
const query = new URLSearchParams({
login_hint: login.createEmail(),
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify error message
expect(await relier.promptNoneError()).toContain(
'A different user is signed in'
);
});
test('succeeds if login_hint same as logged in user', async ({
page,
target,
pages: { relier, login },
}) => {
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
const query = new URLSearchParams({
login_hint: email,
return_on_error: 'false',
});
await page.goto(`${target.relierUrl}/?${query.toString()}`);
await relier.signInPromptNone();
//Verify logged in to relier
expect(await relier.isLoggedIn()).toBe(true);
});
});

Просмотреть файл

@ -5,41 +5,43 @@
import { test, expect } from '../../lib/fixtures/standard';
import { EmailHeader, EmailType } from '../../lib/email';
test.describe('oauth reset password', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
test.slow();
test.describe('severity-1 #smoke', () => {
test.describe('oauth reset password', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
test.slow();
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes === true);
test.skip(config.showReactApp.oauthRoutes === true);
});
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes === true);
test.skip(config.showReactApp.oauthRoutes === true);
});
test('reset password happy path', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.setEmail(credentials.email);
await login.submit();
await login.clickForgotPassword();
test('reset password happy path', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.setEmail(credentials.email);
await login.submit();
await login.clickForgotPassword();
// Verify reset password header
await resetPassword.resetPasswordHeader();
// Verify reset password header
await resetPassword.resetPasswordHeader();
await resetPassword.fillOutResetPassword(credentials.email);
await resetPassword.fillOutResetPassword(credentials.email);
const link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
await page.goto(link);
await resetPassword.resetNewPassword(credentials.password);
const link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
await page.goto(link);
await resetPassword.resetNewPassword(credentials.password);
// Verify logged in
expect(await relier.isLoggedIn()).toBe(true);
// Verify logged in
expect(await relier.isLoggedIn()).toBe(true);
});
});
});

Просмотреть файл

@ -1,3 +1,7 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
const PASSWORD = 'passwordzxcv';

Просмотреть файл

@ -8,82 +8,84 @@ let email;
let bouncedEmail;
const password = 'passwordzxcv';
test.describe('Oauth sign up', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
email = login.createEmail();
bouncedEmail = login.createEmail('bounced{id}');
await login.clearCache();
test.describe('severity-1 #smoke', () => {
test.describe('Oauth sign up', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
email = login.createEmail();
bouncedEmail = login.createEmail('bounced{id}');
await login.clearCache();
});
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
await target.auth.accountDestroy(email, password);
}
});
test('sign up', async ({ pages: { login, relier } }) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password, { verify: false });
//Verify sign up code header
await login.waitForSignUpCodeHeader();
await login.fillOutSignUpCode(email);
//Verify logged in on relier page
expect(await relier.isLoggedIn()).toBe(true);
});
test('signup, bounce email, allow user to restart flow but force a different email', async ({
target,
pages: { login, relier },
}) => {
const client = await login.getFxaClient(target);
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(bouncedEmail, password, { verify: false });
//Verify sign up code header
await login.waitForSignUpCodeHeader();
await client.accountDestroy(bouncedEmail, password);
//Verify error message
expect(await login.getTooltipError()).toContain(
'Your confirmation email was just returned. Mistyped email?'
);
await login.clearEmailTextBox();
await login.fillOutFirstSignUp(email, password, { verify: false });
//Verify sign up code header
await login.waitForSignUpCodeHeader();
await login.fillOutSignUpCode(email);
//Verify logged in on relier page
expect(await relier.isLoggedIn()).toBe(true);
});
});
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
await target.auth.accountDestroy(email, password);
}
});
test.describe('Oauth sign up success', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
await login.clearCache();
});
test('sign up', async ({ pages: { login, relier } }) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password, { verify: false });
test('a success screen is available', async ({
target,
page,
pages: { relier },
}) => {
await page.goto(
`${target.contentServerUrl}/oauth/success/dcdb5ae7add825d2`
);
//Verify sign up code header
await login.waitForSignUpCodeHeader();
await login.fillOutSignUpCode(email);
//Verify logged in on relier page
expect(await relier.isLoggedIn()).toBe(true);
});
test('signup, bounce email, allow user to restart flow but force a different email', async ({
target,
pages: { login, relier },
}) => {
const client = await login.getFxaClient(target);
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(bouncedEmail, password, { verify: false });
//Verify sign up code header
await login.waitForSignUpCodeHeader();
await client.accountDestroy(bouncedEmail, password);
//Verify error message
expect(await login.getTooltipError()).toContain(
'Your confirmation email was just returned. Mistyped email?'
);
await login.clearEmailTextBox();
await login.fillOutFirstSignUp(email, password, { verify: false });
//Verify sign up code header
await login.waitForSignUpCodeHeader();
await login.fillOutSignUpCode(email);
//Verify logged in on relier page
expect(await relier.isLoggedIn()).toBe(true);
});
});
test.describe('Oauth sign up success', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
await login.clearCache();
});
test('a success screen is available', async ({
target,
page,
pages: { relier },
}) => {
await page.goto(
`${target.contentServerUrl}/oauth/success/dcdb5ae7add825d2`
);
//Verify oauth success header
expect(await relier.isOauthSuccessHeader()).toBe(true);
//Verify oauth success header
expect(await relier.isOauthSuccessHeader()).toBe(true);
});
});
});

Просмотреть файл

@ -1,169 +1,182 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
let email = '';
const PASSWORD = 'passwordzxcv';
test.describe('OAuth signin', () => {
test.beforeEach(({}, testInfo) => {
test.slow(testInfo.project.name !== 'local', 'email delivery can be slow');
});
test('verified', async ({ credentials, pages: { login, relier } }) => {
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
expect(await relier.isLoggedIn()).toBe(true);
});
test('verified using a cached login', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
// Attempt to sign back in
await relier.clickEmailFirst();
// Email is prefilled
await expect(await login.getPrefilledEmail()).toContain(credentials.email);
expect(await login.isCachedLogin()).toBe(true);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
});
test('verified using a cached expired login', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
// Attempt to sign back in with cached user
await relier.clickEmailFirst();
await expect(await login.getPrefilledEmail()).toContain(credentials.email);
expect(await login.isCachedLogin()).toBe(true);
await login.submit();
await relier.signOut();
// Clear cache and try to login
await login.clearCache();
await relier.goto();
await relier.clickEmailFirst();
// User will have to re-enter login information
await login.login(credentials.email, credentials.password);
expect(await relier.isLoggedIn()).toBe(true);
});
test('unverified, acts like signup', async ({
target,
pages: { login, relier },
}) => {
// Create unverified account via backend
email = login.createEmail();
await target.auth.signUp(email, PASSWORD, {
lang: 'en',
preVerified: 'false',
test.describe('severity-1 #smoke', () => {
test.describe('OAuth signin', () => {
test.beforeEach(({}, testInfo) => {
test.slow(
testInfo.project.name !== 'local',
'email delivery can be slow'
);
});
await relier.goto();
await relier.clickEmailFirst();
await login.login(email, PASSWORD);
test('verified', async ({ credentials, pages: { login, relier } }) => {
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
expect(await relier.isLoggedIn()).toBe(true);
});
// User is shown confirm email page
await login.fillOutSignInCode(email);
test('verified using a cached login', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
expect(await relier.isLoggedIn()).toBe(true);
expect(await relier.isLoggedIn()).toBe(true);
});
await relier.signOut();
test('unverified with a cached login', async ({
pages: { login, relier },
}) => {
// Create unverified account
email = login.createEmail();
const password = 'passwordzxcv';
// Attempt to sign back in
await relier.clickEmailFirst();
await relier.goto();
await relier.clickEmailFirst();
// Email is prefilled
await expect(await login.getPrefilledEmail()).toContain(
credentials.email
);
expect(await login.isCachedLogin()).toBe(true);
await login.submit();
// Dont register account and attempt to login via relier
await login.fillOutFirstSignUp(email, password, { verify: false });
expect(await relier.isLoggedIn()).toBe(true);
});
await relier.goto();
await relier.clickEmailFirst();
test('verified using a cached expired login', async ({
credentials,
pages: { login, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
expect(await relier.isLoggedIn()).toBe(true);
// Cached user detected
await expect(await login.getPrefilledEmail()).toContain(email);
expect(await login.isCachedLogin()).toBe(true);
await login.submit();
await relier.signOut();
// Verify email and ensure user is redirected to relier
await login.fillOutSignUpCode(email);
// Attempt to sign back in with cached user
await relier.clickEmailFirst();
expect(await relier.isLoggedIn()).toBe(true);
});
await expect(await login.getPrefilledEmail()).toContain(
credentials.email
);
expect(await login.isCachedLogin()).toBe(true);
await login.submit();
await relier.signOut();
test('oauth endpoint chooses the right auth flows', async ({
target,
page,
credentials,
pages: { login, relier },
}, { project }) => {
test.slow(project.name !== 'local', 'email delivery can be slow');
// Clear cache and try to login
await login.clearCache();
await relier.goto();
await relier.clickEmailFirst();
// Create unverified account
email = login.createEmail();
// User will have to re-enter login information
await login.login(credentials.email, credentials.password);
expect(await relier.isLoggedIn()).toBe(true);
});
await relier.goto();
await relier.clickChooseFlow();
await login.fillOutFirstSignUp(email, PASSWORD, { verify: false });
test('unverified, acts like signup', async ({
target,
pages: { login, relier },
}) => {
// Create unverified account via backend
email = login.createEmail();
await target.auth.signUp(email, PASSWORD, {
lang: 'en',
preVerified: 'false',
});
// go back to the OAuth app, the /oauth flow should
// now suggest a cached login
await relier.goto();
await relier.clickChooseFlow();
await relier.goto();
await relier.clickEmailFirst();
await login.login(email, PASSWORD);
// User shown signin enter password page
expect(await login.signInPasswordHeader()).toEqual(true);
});
// User is shown confirm email page
await login.fillOutSignInCode(email);
test('verified, blocked', async ({ target, pages: { login, relier } }) => {
const blockedEmail = login.createEmail('blocked{id}');
await target.createAccount(blockedEmail, PASSWORD);
expect(await relier.isLoggedIn()).toBe(true);
});
await relier.goto();
await relier.clickEmailFirst();
await login.login(blockedEmail, PASSWORD);
test('unverified with a cached login', async ({
pages: { login, relier },
}) => {
// Create unverified account
email = login.createEmail();
const password = 'passwordzxcv';
await login.unblock(blockedEmail);
expect(await relier.isLoggedIn()).toBe(true);
});
await relier.goto();
await relier.clickEmailFirst();
test('verified, blocked, incorrect password', async ({
target,
pages: { login, relier },
}) => {
const blockedEmail = login.createEmail('blocked{id}');
await target.createAccount(blockedEmail, PASSWORD);
// Dont register account and attempt to login via relier
await login.fillOutFirstSignUp(email, password, { verify: false });
await relier.goto();
await relier.clickEmailFirst();
await login.login(blockedEmail, 'wrong password');
await relier.goto();
await relier.clickEmailFirst();
await login.unblock(blockedEmail);
// Cached user detected
await expect(await login.getPrefilledEmail()).toContain(email);
expect(await login.isCachedLogin()).toBe(true);
await login.submit();
// After filling in the unblock code, the user is prompted again to enter password
expect(await login.signInPasswordHeader()).toEqual(true);
// Verify email and ensure user is redirected to relier
await login.fillOutSignUpCode(email);
expect(await relier.isLoggedIn()).toBe(true);
});
test('oauth endpoint chooses the right auth flows', async ({
target,
page,
credentials,
pages: { login, relier },
}, { project }) => {
test.slow(project.name !== 'local', 'email delivery can be slow');
// Create unverified account
email = login.createEmail();
await relier.goto();
await relier.clickChooseFlow();
await login.fillOutFirstSignUp(email, PASSWORD, { verify: false });
// go back to the OAuth app, the /oauth flow should
// now suggest a cached login
await relier.goto();
await relier.clickChooseFlow();
// User shown signin enter password page
expect(await login.signInPasswordHeader()).toEqual(true);
});
test('verified, blocked', async ({ target, pages: { login, relier } }) => {
const blockedEmail = login.createEmail('blocked{id}');
await target.createAccount(blockedEmail, PASSWORD);
await relier.goto();
await relier.clickEmailFirst();
await login.login(blockedEmail, PASSWORD);
await login.unblock(blockedEmail);
expect(await relier.isLoggedIn()).toBe(true);
});
test('verified, blocked, incorrect password', async ({
target,
pages: { login, relier },
}) => {
const blockedEmail = login.createEmail('blocked{id}');
await target.createAccount(blockedEmail, PASSWORD);
await relier.goto();
await relier.clickEmailFirst();
await login.login(blockedEmail, 'wrong password');
await login.unblock(blockedEmail);
// After filling in the unblock code, the user is prompted again to enter password
expect(await login.signInPasswordHeader()).toEqual(true);
});
});
});

Просмотреть файл

@ -1,112 +1,120 @@
/* 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/. */
import { EmailHeader, EmailType } from '../../lib/email';
import { test, expect } from '../../lib/fixtures/standard';
test.describe('OAuth signin token code', () => {
function toQueryString(obj) {
return Object.entries(obj)
.map((x) => `${x[0]}=${x[1]}`)
.join('&');
}
/* Email for fake account */
let email = '';
/* Password for fake account */
const password = 'passwordzxcv';
/* eslint-disable camelcase */
const queryParameters = {
client_id: '7f368c6886429f19',
code_challenge: 'aSOwsmuRBE1ZIVtiW6bzKMaf47kCFl7duD6ZWAXdnJo',
code_challenge_method: 'S256',
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:
'eyJrdHkiOiJFQyIsImtpZCI6Im9DNGFudFBBSFZRX1pmQ09RRUYycTRaQlZYblVNZ2xISGpVRzdtSjZHOEEiLCJjcnYiOiJQLTI1NiIsIngiOiJDeUpUSjVwbUNZb2lQQnVWOTk1UjNvNTFLZVBMaEg1Y3JaQlkwbXNxTDk0IiwieSI6IkJCWDhfcFVZeHpTaldsdXU5MFdPTVZwamIzTlpVRDAyN0xwcC04RW9vckEifQ',
redirect_uri: 'https://mozilla.github.io/notes/fxa/android-redirect.html',
scope: 'profile https://identity.mozilla.com/apps/notes',
};
/* eslint-enable camelcase */
test.beforeEach(async ({ target }, { project }) => {
// The `sync` prefix is needed to force confirmation.
email = `sync${Math.random()}@restmail.net`;
await target.createAccount(email, password);
});
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {}
test.describe('severity-2 #smoke', () => {
test.describe('OAuth signin token code', () => {
function toQueryString(obj) {
return Object.entries(obj)
.map((x) => `${x[0]}=${x[1]}`)
.join('&');
}
});
test('verified - invalid token', async ({
page,
pages: { login, relier, signinTokenCode },
}) => {
await relier.goto(toQueryString(queryParameters));
/* Email for fake account */
let email = '';
// Click the Email First flow, which should direct to the sign in page
await relier.clickEmailFirst();
/* Password for fake account */
const password = 'passwordzxcv';
// Enter email, then enter password
await login.fillOutEmailFirstSignIn(email, password);
/* eslint-disable camelcase */
const queryParameters = {
client_id: '7f368c6886429f19',
code_challenge: 'aSOwsmuRBE1ZIVtiW6bzKMaf47kCFl7duD6ZWAXdnJo',
code_challenge_method: 'S256',
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',
// Check that the sign in page is show, and is asking for a sign in code
expect(await signinTokenCode.tokenCodeHeader.isVisible()).toBeTruthy();
keys_jwk:
'eyJrdHkiOiJFQyIsImtpZCI6Im9DNGFudFBBSFZRX1pmQ09RRUYycTRaQlZYblVNZ2xISGpVRzdtSjZHOEEiLCJjcnYiOiJQLTI1NiIsIngiOiJDeUpUSjVwbUNZb2lQQnVWOTk1UjNvNTFLZVBMaEg1Y3JaQlkwbXNxTDk0IiwieSI6IkJCWDhfcFVZeHpTaldsdXU5MFdPTVZwamIzTlpVRDAyN0xwcC04RW9vckEifQ',
redirect_uri: 'https://mozilla.github.io/notes/fxa/android-redirect.html',
scope: 'profile https://identity.mozilla.com/apps/notes',
};
/* eslint-enable camelcase */
// This will cause the token become 'invalid' and ultimately cause an
// INVALID_TOKEN error to be thrown.
await login.destroySession(email);
await page.waitForURL(/oauth\/signin/);
// Destroying the session should direct user back to sign in page
await login.passwordHeader.waitFor({ state: 'visible' });
});
test.beforeEach(async ({ target }, { project }) => {
// The `sync` prefix is needed to force confirmation.
email = `sync${Math.random()}@restmail.net`;
await target.createAccount(email, password);
});
test('verified - valid code', async ({
target,
page,
pages: { login, relier, signinTokenCode },
}) => {
await relier.goto(toQueryString(queryParameters));
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {}
}
});
// Click the Email First flow, which should direct to the sign in page
await relier.clickEmailFirst();
test('verified - invalid token', async ({
page,
pages: { login, relier, signinTokenCode },
}) => {
await relier.goto(toQueryString(queryParameters));
// Enter email, then enter password
await login.fillOutEmailFirstSignIn(email, password);
// Click the Email First flow, which should direct to the sign in page
await relier.clickEmailFirst();
// Enter invalid code, ensure it doesn't work
await signinTokenCode.input.fill('000000');
await signinTokenCode.submit.click();
await expect(signinTokenCode.tooltip).toContainText('Invalid or expired');
// Enter email, then enter password
await login.fillOutEmailFirstSignIn(email, password);
// Resend the code
await signinTokenCode.resendLink.click();
await signinTokenCode.successMessage.waitFor({ state: 'visible' });
await expect(signinTokenCode.successMessage).toBeVisible();
await expect(signinTokenCode.successMessage).toContainText('Email resent.');
// Check that the sign in page is show, and is asking for a sign in code
expect(await signinTokenCode.tokenCodeHeader.isVisible()).toBeTruthy();
// Correctly submits the token code and navigates to oauth page
await expect(signinTokenCode.tokenCodeHeader).toBeVisible();
// This will cause the token become 'invalid' and ultimately cause an
// INVALID_TOKEN error to be thrown.
await login.destroySession(email);
await page.waitForURL(/oauth\/signin/);
// Destroying the session should direct user back to sign in page
await login.passwordHeader.waitFor({ state: 'visible' });
});
const code = await target.email.waitForEmail(
email,
EmailType.verifyLoginCode,
EmailHeader.signinCode
);
await signinTokenCode.input.fill(code);
await signinTokenCode.submit.click();
await page.waitForLoadState();
test('verified - valid code', async ({
target,
page,
pages: { login, relier, signinTokenCode },
}) => {
await relier.goto(toQueryString(queryParameters));
const NOTES_REDIRECT_PAGE_SELECTOR = '#notes-by-firefox';
await expect(page.locator(NOTES_REDIRECT_PAGE_SELECTOR)).toBeVisible();
await expect(page.locator(NOTES_REDIRECT_PAGE_SELECTOR)).toContainText(
'Notes by Firefox'
);
// Click the Email First flow, which should direct to the sign in page
await relier.clickEmailFirst();
// Enter email, then enter password
await login.fillOutEmailFirstSignIn(email, password);
// Enter invalid code, ensure it doesn't work
await signinTokenCode.input.fill('000000');
await signinTokenCode.submit.click();
await expect(signinTokenCode.tooltip).toContainText('Invalid or expired');
// Resend the code
await signinTokenCode.resendLink.click();
await signinTokenCode.successMessage.waitFor({ state: 'visible' });
await expect(signinTokenCode.successMessage).toBeVisible();
await expect(signinTokenCode.successMessage).toContainText(
'Email resent.'
);
// Correctly submits the token code and navigates to oauth page
await expect(signinTokenCode.tokenCodeHeader).toBeVisible();
const code = await target.email.waitForEmail(
email,
EmailType.verifyLoginCode,
EmailHeader.signinCode
);
await signinTokenCode.input.fill(code);
await signinTokenCode.submit.click();
await page.waitForLoadState();
const NOTES_REDIRECT_PAGE_SELECTOR = '#notes-by-firefox';
await expect(page.locator(NOTES_REDIRECT_PAGE_SELECTOR)).toBeVisible();
await expect(page.locator(NOTES_REDIRECT_PAGE_SELECTOR)).toContainText(
'Notes by Firefox'
);
});
});
});

Просмотреть файл

@ -7,74 +7,76 @@ import { test, expect, newPagesForSync } from '../../lib/fixtures/standard';
const password = 'passwordzxcv';
let syncBrowserPages;
test.describe('signin with OAuth after Sync', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
test.describe('severity-1 #smoke', () => {
test.describe('signin with OAuth after Sync', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
});
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
test('signin to OAuth with Sync creds', async ({ target }) => {
const { page, login, connectAnotherDevice, relier } = syncBrowserPages;
const email = login.createEmail('sync{id}');
const email2 = login.createEmail();
await target.createAccount(email, password);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email&`
);
await login.login(email, password);
await login.fillOutSignInCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await page.pause();
// Sign up for a new account via OAuth
await relier.goto();
await relier.clickEmailFirst();
await login.useDifferentAccountLink();
await login.fillOutFirstSignUp(email2, password);
// RP is logged in, logout then back in again
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
await relier.clickSignIn();
// By default, we should see the email we signed up for Sync with
expect(await login.getPrefilledEmail()).toContain(email);
await login.clickSignIn();
expect(await relier.isLoggedIn()).toBe(true);
});
});
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
test.describe('signin to Sync after OAuth', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
});
test('signin to OAuth with Sync creds', async ({ target }) => {
const { page, login, connectAnotherDevice, relier } = syncBrowserPages;
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
const email = login.createEmail('sync{id}');
const email2 = login.createEmail();
await target.createAccount(email, password);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email&`
);
await login.login(email, password);
await login.fillOutSignInCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await page.pause();
test('email-first Sync signin', async ({ target }) => {
const { page, login, connectAnotherDevice, relier } = syncBrowserPages;
// Sign up for a new account via OAuth
await relier.goto();
await relier.clickEmailFirst();
await login.useDifferentAccountLink();
await login.fillOutFirstSignUp(email2, password);
// RP is logged in, logout then back in again
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
await relier.clickSignIn();
// By default, we should see the email we signed up for Sync with
expect(await login.getPrefilledEmail()).toContain(email);
await login.clickSignIn();
expect(await relier.isLoggedIn()).toBe(true);
});
});
test.describe('signin to Sync after OAuth', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
});
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
test('email-first Sync signin', async ({ target }) => {
const { page, login, connectAnotherDevice, relier } = syncBrowserPages;
const email = login.createEmail('sync{id}');
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password);
expect(await relier.isLoggedIn()).toBe(true);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email&`
);
expect(await login.getPrefilledEmail()).toContain(email);
await login.setPassword(password);
await login.submit();
await login.fillOutSignInCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
const email = login.createEmail('sync{id}');
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password);
expect(await relier.isLoggedIn()).toBe(true);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email&`
);
expect(await login.getPrefilledEmail()).toContain(email);
await login.setPassword(password);
await login.submit();
await login.fillOutSignInCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
});
});

Просмотреть файл

@ -1,45 +1,51 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
test.describe('OAuth totp', () => {
test.beforeEach(async ({}, { project }) => {
test.slow();
});
test.describe('severity-1 #smoke', () => {
test.describe('OAuth totp', () => {
test.beforeEach(async ({}, { project }) => {
test.slow();
});
test('can add TOTP to account and confirm oauth signin', async ({
credentials,
pages: { login, relier, settings, totp },
}) => {
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
await settings.signOut();
test('can add TOTP to account and confirm oauth signin', async ({
credentials,
pages: { login, relier, settings, totp },
}) => {
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
await settings.signOut();
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
await login.setTotp(credentials.secret);
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
await login.setTotp(credentials.secret);
expect(await relier.isLoggedIn()).toBe(true);
});
expect(await relier.isLoggedIn()).toBe(true);
});
test('can remove TOTP from account and skip confirmation', async ({
credentials,
pages: { login, relier, settings, totp },
}) => {
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
test('can remove TOTP from account and skip confirmation', async ({
credentials,
pages: { login, relier, settings, totp },
}) => {
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
await settings.totp.clickDisable();
await settings.clickModalConfirm();
await settings.waitForAlertBar();
let status = await settings.totp.statusText();
expect(status).toEqual('Not Set');
await settings.totp.clickDisable();
await settings.clickModalConfirm();
await settings.waitForAlertBar();
let status = await settings.totp.statusText();
expect(status).toEqual('Not Set');
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
await relier.goto();
await relier.clickEmailFirst();
await login.login(credentials.email, credentials.password);
expect(await relier.isLoggedIn()).toBe(true);
expect(await relier.isLoggedIn()).toBe(true);
});
});
});

Просмотреть файл

@ -7,66 +7,68 @@ import { test, expect } from '../../lib/fixtures/standard';
const PASSWORD = 'Password123!';
test.describe('oauth webchannel', () => {
test.beforeEach(async ({ pages: { login } }) => {
await login.clearCache();
});
test('signup', async ({ pages: { login, relier } }) => {
const customEventDetail = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
choose_what_to_sync: true,
engines: ['bookmarks', 'history'],
},
signedInUser: null,
}
);
const email = login.createEmail();
await relier.goto('context=oauth_webchannel_v1&automatedBrowser=true');
await relier.clickEmailFirst();
await login.respondToWebChannelMessage(customEventDetail);
await login.setEmail(email);
await login.submit();
// the CWTS form is on the same signup page
await login.waitForCWTSEngineHeader();
expect(await login.isCWTSEngineBookmarks()).toBe(true);
expect(await login.isCWTSEngineHistory()).toBe(true);
await login.fillOutFirstSignUp(email, PASSWORD, {
enterEmail: false,
waitForNavOnSubmit: false,
test.describe('severity-1 #smoke', () => {
test.describe('oauth webchannel', () => {
test.beforeEach(async ({ pages: { login } }) => {
await login.clearCache();
});
await login.checkWebChannelMessage(FirefoxCommand.OAuthLogin);
});
test('signin', async ({ pages: { login, relier, page }, credentials }) => {
const customEventDetail = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
engines: ['bookmarks', 'history'],
},
signedInUser: null,
}
);
test('signup', async ({ pages: { login, relier } }) => {
const customEventDetail = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
choose_what_to_sync: true,
engines: ['bookmarks', 'history'],
},
signedInUser: null,
}
);
const email = login.createEmail();
await relier.goto('context=oauth_webchannel_v1&automatedBrowser=true');
await relier.clickEmailFirst();
await relier.goto('context=oauth_webchannel_v1&automatedBrowser=true');
await relier.clickEmailFirst();
await login.respondToWebChannelMessage(customEventDetail);
await login.respondToWebChannelMessage(customEventDetail);
const { searchParams } = new URL(page.url());
expect(searchParams.has('client_id')).toBe(true);
expect(searchParams.has('redirect_uri')).toBe(true);
expect(searchParams.has('state')).toBe(true);
expect(searchParams.has('context')).toBe(true);
await login.setEmail(email);
await login.submit();
await login.login(credentials.email, credentials.password, '', false);
// the CWTS form is on the same signup page
await login.waitForCWTSEngineHeader();
expect(await login.isCWTSEngineBookmarks()).toBe(true);
expect(await login.isCWTSEngineHistory()).toBe(true);
await login.fillOutFirstSignUp(email, PASSWORD, {
enterEmail: false,
waitForNavOnSubmit: false,
});
await login.checkWebChannelMessage(FirefoxCommand.OAuthLogin);
});
test('signin', async ({ pages: { login, relier, page }, credentials }) => {
const customEventDetail = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
engines: ['bookmarks', 'history'],
},
signedInUser: null,
}
);
await relier.goto('context=oauth_webchannel_v1&automatedBrowser=true');
await relier.clickEmailFirst();
await login.respondToWebChannelMessage(customEventDetail);
const { searchParams } = new URL(page.url());
expect(searchParams.has('client_id')).toBe(true);
expect(searchParams.has('redirect_uri')).toBe(true);
expect(searchParams.has('state')).toBe(true);
expect(searchParams.has('context')).toBe(true);
await login.login(credentials.email, credentials.password, '', false);
});
});
});

Просмотреть файл

@ -6,127 +6,129 @@ import { test, expect } from '../../lib/fixtures/standard';
const password = 'passwordzxcv';
let email;
test.describe('post verify - account recovery', () => {
test.beforeEach(async ({ target, pages: { login } }) => {
// Generating and consuming recovery keys is a slow process
test.slow();
email = login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
test.describe('severity-1 #smoke', () => {
test.describe('post verify - account recovery', () => {
test.beforeEach(async ({ target, pages: { login } }) => {
// Generating and consuming recovery keys is a slow process
test.slow();
email = login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await login.clearCache();
});
await login.clearCache();
});
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
}
});
test('create account recovery', async ({
target,
pages: { page, login, postVerify },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
test('create account recovery', async ({
target,
pages: { page, login, postVerify },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
await page.goto(
`${target.contentServerUrl}/post_verify/account_recovery/add_recovery_key`,
{ waitUntil: 'load' }
);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Verify account recovery header
expect(await postVerify.isAccountRecoveryHeader()).toBe(true);
await page.goto(
`${target.contentServerUrl}/post_verify/account_recovery/add_recovery_key`,
{ waitUntil: 'load' }
);
//Add recovery key
await postVerify.addRecoveryKey(password);
await postVerify.submit();
//Verify account recovery header
expect(await postVerify.isAccountRecoveryHeader()).toBe(true);
// Store key to be used later
const key = await postVerify.getKey();
await postVerify.clickDone();
//Add recovery key
await postVerify.addRecoveryKey(password);
await postVerify.submit();
//Enter invalid key
await postVerify.inputRecoveryKey('invalid key');
// Store key to be used later
const key = await postVerify.getKey();
await postVerify.clickDone();
//Verify error message
expect(await postVerify.getTooltipError()).toContain(
'Invalid account recovery key'
);
//Enter invalid key
await postVerify.inputRecoveryKey('invalid key');
//Enter correct key
await postVerify.inputRecoveryKey(key);
//Verify error message
expect(await postVerify.getTooltipError()).toContain(
'Invalid account recovery key'
);
//Verify post verify account recovery key complete header
expect(await postVerify.isAccountRecoveryVerifiedHeader()).toBe(true);
});
//Enter correct key
await postVerify.inputRecoveryKey(key);
test('abort account recovery at add_recovery_key', async ({
target,
pages: { page, login, postVerify },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
//Verify post verify account recovery key complete header
expect(await postVerify.isAccountRecoveryVerifiedHeader()).toBe(true);
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
test('abort account recovery at add_recovery_key', async ({
target,
pages: { page, login, postVerify },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
await page.goto(
`${target.contentServerUrl}/post_verify/account_recovery/add_recovery_key`,
{ waitUntil: 'load' }
);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Verify account recovery header
expect(await postVerify.isAccountRecoveryHeader()).toBe(true);
await page.goto(
`${target.contentServerUrl}/post_verify/account_recovery/add_recovery_key`,
{ waitUntil: 'load' }
);
//Add recovery key
await postVerify.clickMaybeLater();
//Verify account recovery header
expect(await postVerify.isAccountRecoveryHeader()).toBe(true);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Add recovery key
await postVerify.clickMaybeLater();
test('abort account recovery at confirm_recovery_key', async ({
target,
pages: { page, login, postVerify },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
test('abort account recovery at confirm_recovery_key', async ({
target,
pages: { page, login, postVerify },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
await page.goto(
`${target.contentServerUrl}/post_verify/account_recovery/add_recovery_key`,
{ waitUntil: 'load' }
);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Verify account recovery header
expect(await postVerify.isAccountRecoveryHeader()).toBe(true);
await page.goto(
`${target.contentServerUrl}/post_verify/account_recovery/add_recovery_key`,
{ waitUntil: 'load' }
);
//Add recovery key
await postVerify.addRecoveryKey(password);
await postVerify.clickMaybeLater();
//Verify account recovery header
expect(await postVerify.isAccountRecoveryHeader()).toBe(true);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Add recovery key
await postVerify.addRecoveryKey(password);
await postVerify.clickMaybeLater();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
});
});

Просмотреть файл

@ -7,68 +7,70 @@ let email;
const password = 'password';
const newPassword = 'new_password';
test.describe('post verify - force password change', () => {
test.beforeEach(async ({ target, pages: { login } }) => {
test.slow();
email = login.createEmail('forcepwdchange{id}');
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
test.describe('severity-2 #smoke', () => {
test.describe('post verify - force password change', () => {
test.beforeEach(async ({ target, pages: { login } }) => {
test.slow();
email = login.createEmail('forcepwdchange{id}');
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await login.clearCache();
});
await login.clearCache();
});
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, newPassword);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, newPassword);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
}
});
test('navigate to page directly and can change password', async ({
target,
pages: { page, login, postVerify },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
await login.fillOutSignInCode(email);
//Verify force password change header
expect(await postVerify.isForcePasswordChangeHeader()).toBe(true);
test('navigate to page directly and can change password', async ({
target,
pages: { page, login, postVerify },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
await login.fillOutSignInCode(email);
//Fill out change password
await postVerify.fillOutChangePassword(password, newPassword);
await postVerify.submit();
//Verify force password change header
expect(await postVerify.isForcePasswordChangeHeader()).toBe(true);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Fill out change password
await postVerify.fillOutChangePassword(password, newPassword);
await postVerify.submit();
test('force change password on login - oauth', async ({
pages: { login, postVerify, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutEmailFirstSignIn(email, password);
await login.fillOutSignInCode(email);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Verify force password change header
expect(await postVerify.isForcePasswordChangeHeader()).toBe(true);
test('force change password on login - oauth', async ({
pages: { login, postVerify, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutEmailFirstSignIn(email, password);
await login.fillOutSignInCode(email);
//Fill out change password
await postVerify.fillOutChangePassword(password, newPassword);
await postVerify.submit();
//Verify force password change header
expect(await postVerify.isForcePasswordChangeHeader()).toBe(true);
//Verify logged in on relier page
expect(await relier.isLoggedIn()).toBe(true);
//Fill out change password
await postVerify.fillOutChangePassword(password, newPassword);
await postVerify.submit();
//Verify logged in on relier page
expect(await relier.isLoggedIn()).toBe(true);
});
});
});

Просмотреть файл

@ -8,51 +8,54 @@ const password = 'password';
const newPassword = 'new_password';
let syncBrowserPages;
test.describe('post verify - force password change sync', () => {
test.beforeEach(async ({ target }) => {
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('forcepwdchange{id}');
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
test.describe('severity-2 #smoke', () => {
test.describe('post verify - force password change sync', () => {
test.beforeEach(async ({ target }) => {
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('forcepwdchange{id}');
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
});
test.afterEach(async ({ target }) => {
await syncBrowserPages.browser?.close();
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, newPassword);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
});
test('force change password on login - sync', async ({ target }) => {
const { page, login, postVerify, connectAnotherDevice } =
syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`,
{
waitUntil: 'load',
}
);
await login.fillOutEmailFirstSignIn(email, password);
await login.fillOutSignInCode(email);
//Verify force password change header
expect(await postVerify.isForcePasswordChangeHeader()).toBe(true);
//Fill out change password
await postVerify.fillOutChangePassword(password, newPassword);
await postVerify.submit();
//Verify logged in on connect another device page
expect(await connectAnotherDevice.fxaConnected.isEnabled()).toBeTruthy();
});
});
test.afterEach(async ({ target }) => {
await syncBrowserPages.browser?.close();
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, newPassword);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
});
test('force change password on login - sync', async ({ target }) => {
const { page, login, postVerify, connectAnotherDevice } = syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`,
{
waitUntil: 'load',
}
);
await login.fillOutEmailFirstSignIn(email, password);
await login.fillOutSignInCode(email);
//Verify force password change header
expect(await postVerify.isForcePasswordChangeHeader()).toBe(true);
//Fill out change password
await postVerify.fillOutChangePassword(password, newPassword);
await postVerify.submit();
//Verify logged in on connect another device page
expect(await connectAnotherDevice.fxaConnected.isEnabled()).toBeTruthy();
});
});

Просмотреть файл

@ -11,60 +11,62 @@ test.beforeEach(async ({ pages: { configPage } }) => {
test.skip(config.showReactApp.simpleRoutes !== true);
});
test.describe('legal', () => {
test('start at legal page', async ({ page, target }) => {
await page.goto(getReactFeatureFlagUrl(target, '/legal'));
test.describe('severity-2 #smoke', () => {
test.describe('legal', () => {
test('start at legal page', async ({ page, target }) => {
await page.goto(getReactFeatureFlagUrl(target, '/legal'));
// Verify react page has been loaded
expect(await page.locator('#root').isEnabled()).toBeTruthy();
// Verify react page has been loaded
expect(await page.locator('#root').isEnabled()).toBeTruthy();
// Verify legal page is visible
expect(
await page.locator('.card-header:has-text("Legal")').isEnabled()
).toBeTruthy();
// Verify legal page is visible
expect(
await page.locator('.card-header:has-text("Legal")').isEnabled()
).toBeTruthy();
// Verify Terms Of Service link is visible
expect(
await page.locator('a:has-text("Terms of Service")').isVisible()
).toBeTruthy();
// Verify Terms Of Service link is visible
expect(
await page.locator('a:has-text("Terms of Service")').isVisible()
).toBeTruthy();
// Currently Back button on this page is not working,
// check https://mozilla-hub.atlassian.net/browse/FXA-6874
// await page.locator('a:has-text("Terms of Service")').click();
//await page.locator('button:has-text("Back")').click();
//expect(await page.locator('.card-header:has-text("Legal")').isVisible()).toBeTruthy();
// Currently Back button on this page is not working,
// check https://mozilla-hub.atlassian.net/browse/FXA-6874
// await page.locator('a:has-text("Terms of Service")').click();
//await page.locator('button:has-text("Back")').click();
//expect(await page.locator('.card-header:has-text("Legal")').isVisible()).toBeTruthy();
// Verify Privacy Notice link is visible
expect(
await page.locator('a:has-text("Privacy Notice")').isVisible()
).toBeTruthy();
await page.locator('a:has-text("Privacy Notice")').click();
await page.locator('button:has-text("Back")').click();
await page.waitForSelector('.card-header:has-text("Legal")');
});
// Verify Privacy Notice link is visible
expect(
await page.locator('a:has-text("Privacy Notice")').isVisible()
).toBeTruthy();
await page.locator('a:has-text("Privacy Notice")').click();
await page.locator('button:has-text("Back")').click();
await page.waitForSelector('.card-header:has-text("Legal")');
});
test('start at terms page', async ({ page, target }) => {
await page.goto(getReactFeatureFlagUrl(target, '/legal/terms'));
test('start at terms page', async ({ page, target }) => {
await page.goto(getReactFeatureFlagUrl(target, '/legal/terms'));
// Verify react page has been loaded
await page.locator('#root').isVisible();
// Verify react page has been loaded
await page.locator('#root').isVisible();
// Verify legal page is visible
// this text is not in our codebase, it's pulled from the `legal-docs` repo
await page
.locator('text="Firefox Cloud Services: Terms of Service"')
.isVisible();
});
// Verify legal page is visible
// this text is not in our codebase, it's pulled from the `legal-docs` repo
await page
.locator('text="Firefox Cloud Services: Terms of Service"')
.isVisible();
});
test('start at privacy page', async ({ page, target }) => {
await page.goto(getReactFeatureFlagUrl(target, '/legal/privacy'));
test('start at privacy page', async ({ page, target }) => {
await page.goto(getReactFeatureFlagUrl(target, '/legal/privacy'));
// Verify react page has been loaded
await page.locator('#root').isVisible();
// Verify react page has been loaded
await page.locator('#root').isVisible();
// Verify privacy page is visible
await page.waitForTimeout(1000);
// this text is not in our codebase, it's pulled from the `legal-docs` repo
await page.locator('text="Firefox Privacy Notice"').isVisible();
// Verify privacy page is visible
await page.waitForTimeout(1000);
// this text is not in our codebase, it's pulled from the `legal-docs` repo
await page.locator('text="Firefox Privacy Notice"').isVisible();
});
});
});

Просмотреть файл

@ -5,294 +5,299 @@
import { test, expect } from '../../lib/fixtures/standard';
import { EmailHeader, EmailType } from '../../lib/email';
test.describe('oauth reset password react', () => {
let resetPasswordReactFlag = false;
test.describe('severity-1 #smoke', () => {
test.describe('oauth reset password react', () => {
let resetPasswordReactFlag = false;
test.beforeEach(async ({ pages: { configPage, resetPassword } }) => {
resetPasswordReactFlag = resetPassword.react;
resetPassword.react = true;
test.slow();
test.beforeEach(async ({ pages: { configPage, resetPassword } }) => {
resetPasswordReactFlag = resetPassword.react;
resetPassword.react = true;
test.slow();
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes !== true);
});
test.afterEach(async ({ pages: { resetPassword } }) => {
resetPassword.react = resetPasswordReactFlag;
});
test('reset password', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword, settings },
}) => {
await openRelier({ pages: { settings, relier } });
await passwordResetFlow(
{
target,
page,
credentials,
pages: { login, relier, resetPassword },
},
{}
);
});
test('reset password different tab', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword, settings },
}) => {
await openRelier({ pages: { relier, settings } });
await passwordResetFlow(
{
target,
page,
credentials,
pages: { login, relier, resetPassword },
},
{
newTab: true,
}
);
});
test('reset password scoped keys', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword, settings },
}) => {
await openRelier({ pages: { relier, settings } });
await passwordResetFlow(
{
target,
page,
credentials,
pages: { login, relier, resetPassword },
},
{
action: 'scopedKeys',
}
);
});
test('reset password with PKCE different tab', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword },
}) => {
await passwordResetFlow(
{
target,
page,
credentials,
pages: { login, relier, resetPassword },
},
{
action: 'pkce',
newTab: true,
}
);
});
test('reset password with account recovery key', async ({
target,
credentials,
page,
pages: { login, resetPassword, relier, settings, recoveryKey },
}) => {
const accountRecoveryKey = await addAccountRecoveryKeyFlow({
credentials,
pages: { settings, recoveryKey },
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes !== true);
});
await openRelier({ pages: { relier, settings } });
await passwordResetFlow(
{
target,
test.afterEach(async ({ pages: { resetPassword } }) => {
resetPassword.react = resetPasswordReactFlag;
});
test('reset password', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword, settings },
}) => {
await openRelier({ pages: { settings, relier } });
await passwordResetFlow(
{
target,
page,
credentials,
pages: { login, relier, resetPassword },
},
{}
);
});
test('reset password different tab', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword, settings },
}) => {
await openRelier({ pages: { relier, settings } });
await passwordResetFlow(
{
target,
page,
credentials,
pages: { login, relier, resetPassword },
},
{
newTab: true,
}
);
});
test('reset password scoped keys', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword, settings },
}) => {
await openRelier({ pages: { relier, settings } });
await passwordResetFlow(
{
target,
page,
credentials,
pages: { login, relier, resetPassword },
},
{
action: 'scopedKeys',
}
);
});
/* Disabling this until FXA-8006 is fixed
test('reset password with PKCE different tab', async ({
target,
page,
credentials,
pages: { login, relier, resetPassword },
}) => {
await passwordResetFlow(
{
target,
page,
credentials,
pages: { login, relier, resetPassword },
},
{
action: 'pkce',
newTab: true,
}
);
});*/
test('reset password with account recovery key', async ({
target,
credentials,
page,
pages: { login, resetPassword, relier, settings, recoveryKey },
}) => {
const accountRecoveryKey = await addAccountRecoveryKeyFlow({
credentials,
page,
pages: { login, resetPassword, relier },
},
{
action: 'emailFirst',
accountRecoveryKey,
}
);
pages: { settings, recoveryKey },
});
await openRelier({ pages: { relier, settings } });
await passwordResetFlow(
{
target,
credentials,
page,
pages: { login, resetPassword, relier },
},
{
action: 'emailFirst',
accountRecoveryKey,
}
);
});
test('reset password with valid totp', async ({
target,
credentials,
page,
pages: { login, resetPassword, relier, totp, settings },
}) => {
await addTotpFlow({ credentials, pages: { totp, settings } });
await openRelier({ pages: { relier, settings } });
await passwordResetFlow(
{
target,
credentials,
page,
pages: { login, resetPassword, relier },
},
{
action: 'emailFirst',
}
);
});
});
test('reset password with valid totp', async ({
target,
/**
* Makes sure user is not signed in, and goes to the relier (ie 123done)
*/
async function openRelier({ pages: { settings, relier } }) {
await relier.goto('showReactApp=true');
}
/**
* Goes to settings and enables totp on user's account.
*/
async function addTotpFlow({ credentials, pages: { totp, settings } }) {
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
}
/**
* Goes to settings and enables the account recovery key on user's account.
*/
async function addAccountRecoveryKeyFlow({
credentials,
page,
pages: { login, resetPassword, relier, totp, settings },
}) => {
await addTotpFlow({ credentials, pages: { totp, settings } });
await openRelier({ pages: { relier, settings } });
await passwordResetFlow(
{
target,
credentials,
page,
pages: { login, resetPassword, relier },
},
{
action: 'emailFirst',
}
);
});
});
pages: { settings, recoveryKey },
}) {
await settings.goto();
await settings.recoveryKey.clickCreate();
await recoveryKey.clickStart();
await recoveryKey.setPassword(credentials.password);
await recoveryKey.clickCreateAccountRecoveryKey();
const accountRecoveryKey = await recoveryKey.getKey();
await recoveryKey.clickNext();
await recoveryKey.clickFinish();
/**
* Makes sure user is not signed in, and goes to the relier (ie 123done)
*/
async function openRelier({ pages: { settings, relier } }) {
await relier.goto('showReactApp=true');
}
/**
* Goes to settings and enables totp on user's account.
*/
async function addTotpFlow({ credentials, pages: { totp, settings } }) {
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
}
/**
* Goes to settings and enables the account recovery key on user's account.
*/
async function addAccountRecoveryKeyFlow({
credentials,
pages: { settings, recoveryKey },
}) {
await settings.goto();
await settings.recoveryKey.clickCreate();
await recoveryKey.clickStart();
await recoveryKey.setPassword(credentials.password);
await recoveryKey.clickCreateAccountRecoveryKey();
const accountRecoveryKey = await recoveryKey.getKey();
await recoveryKey.clickNext();
await recoveryKey.clickFinish();
return accountRecoveryKey;
}
/**
* Primary function for running various permutations on reset password flows
* @param param0
* @param opts {
* action - The button to click on the relier 123done
* newTab - Whether or not the flow is conducted in a single tab, or if the processes is carried out
* in one tab, and then another after the confirmation email is received.
* accountRecoveryKey - If account recovery keys were enabled, then supply the key and activate that
* part of the flow.
* totp - If 2 factor auth is enabled, then activate that part of the flow.
* }
*/
async function passwordResetFlow(
{ target, page, credentials, pages: { login, relier, resetPassword } },
opts: {
action?: 'emailFirst' | 'scopedKeys' | 'pkce';
newTab?: boolean;
accountRecoveryKey?: string;
}
) {
const { action, newTab, accountRecoveryKey } = opts;
// Decide which flow to start from 123done
if (action == null || action === 'emailFirst') {
await relier.clickEmailFirst();
} else if (action === 'scopedKeys') {
await relier.clickSignInScopedKeys();
} else if (action === 'pkce') {
// TODO, the PKCE button is broken at the moment, so for now navigate directly to the link.
// TODO: PKCE button doesn't appear to work at the moment locally. Some sort of cors error keeps getting in the way. Just go to link directly for now.
await page.goto(
'http://localhost:3030/authorization?showReactApp=true&access_type=offline&client_id=dcdb5ae7add825d2&pkce_client_id=38a6b9b3a65a1871&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fapi%2Foauth&scope=profile%20openid&action=signin&state=12eeaba43cc7548bf1f6b478b9de95328855b46df1e754fe94b21036c41c9cba',
{
waitUntil: 'load',
}
);
return accountRecoveryKey;
}
// Step 1 - Begin the password reset.
// - Go to the login page
// - Enter current email
// - Select the forgot password link
/**
* Primary function for running various permutations on reset password flows
* @param param0
* @param opts {
* action - The button to click on the relier 123done
* newTab - Whether or not the flow is conducted in a single tab, or if the processes is carried out
* in one tab, and then another after the confirmation email is received.
* accountRecoveryKey - If account recovery keys were enabled, then supply the key and activate that
* part of the flow.
* totp - If 2 factor auth is enabled, then activate that part of the flow.
* }
*/
async function passwordResetFlow(
{ target, page, credentials, pages: { login, relier, resetPassword } },
opts: {
action?: 'emailFirst' | 'scopedKeys' | 'pkce';
newTab?: boolean;
accountRecoveryKey?: string;
}
) {
const { action, newTab, accountRecoveryKey } = opts;
// TODO: Update once we port signin / signup.
// param is set, this view is still using backbone.
await login.setEmail(credentials.email);
await login.submit();
await login.clickForgotPassword();
// Decide which flow to start from 123done
if (action == null || action === 'emailFirst') {
await relier.clickEmailFirst();
} else if (action === 'scopedKeys') {
await relier.clickSignInScopedKeys();
} else if (action === 'pkce') {
// TODO, the PKCE button is broken at the moment, so for now navigate directly to the link.
// TODO: PKCE button doesn't appear to work at the moment locally. Some sort of cors error keeps getting in the way. Just go to link directly for now.
await page.goto(
'http://localhost:3030/authorization?showReactApp=true&access_type=offline&client_id=dcdb5ae7add825d2&pkce_client_id=38a6b9b3a65a1871&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fapi%2Foauth&scope=profile%20openid&action=signin&state=12eeaba43cc7548bf1f6b478b9de95328855b46df1e754fe94b21036c41c9cba',
{
waitUntil: 'load',
}
);
}
// TODO: Once the full flow is implemented in react, we can remove this. For now, we must 'refresh'
// the page so that the 'showReactApp' param takes effect. Once conversion is complete this can be removed
await page.reload();
await checkForReactApp({ page });
// Step 1 - Begin the password reset.
// - Go to the login page
// - Enter current email
// - Select the forgot password link
// Verify reset password header
// The service name can change based on environments and all of our test RPs have service names
// that begin with '123'. This test just ensures that the OAuth service name is rendered, it's
// OK that it does not exactly match.
expect(
await resetPassword.resetPasswordHeader('Reset password to continue to 123')
).toBe(true);
await resetPassword.fillOutResetPassword(credentials.email);
// Step 2 - Get the confirmation email
let link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
// Make sure showReactApp is appended to link
link = link.includes('showReactApp=true')
? link
: link.includes('?')
? `${link}&showReactApp=true`
: `${link}?showReactApp=true`;
// Clearing session state simulates a 'new' tab, and changes the navigation at the end of the flow.
if (newTab) {
await page.evaluate(() => window.sessionStorage.clear());
}
// Step 3 (optional) - Reset the password!
await page.goto(link, { waitUntil: 'load' });
await checkForReactApp({ page });
// This is an alternate flow for accounts with recovery keys
if (accountRecoveryKey) {
await login.setRecoveryKey(accountRecoveryKey);
// TODO: Update once we port signin / signup.
// param is set, this view is still using backbone.
await login.setEmail(credentials.email);
await login.submit();
await login.clickForgotPassword();
// TODO: Once the full flow is implemented in react, we can remove this. For now, we must 'refresh'
// the page so that the 'showReactApp' param takes effect. Once conversion is complete this can be removed
await page.reload();
await checkForReactApp({ page });
// Verify reset password header
// The service name can change based on environments and all of our test RPs have service names
// that begin with '123'. This test just ensures that the OAuth service name is rendered, it's
// OK that it does not exactly match.
expect(
await resetPassword.resetPasswordHeader(
'Reset password to continue to 123'
)
).toBe(true);
await resetPassword.fillOutResetPassword(credentials.email);
// Step 2 - Get the confirmation email
let link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
// Make sure showReactApp is appended to link
link = link.includes('showReactApp=true')
? link
: link.includes('?')
? `${link}&showReactApp=true`
: `${link}?showReactApp=true`;
// Clearing session state simulates a 'new' tab, and changes the navigation at the end of the flow.
if (newTab) {
await page.evaluate(() => window.sessionStorage.clear());
}
// Step 3 (optional) - Reset the password!
await page.goto(link, { waitUntil: 'load' });
await checkForReactApp({ page });
// This is an alternate flow for accounts with recovery keys
if (accountRecoveryKey) {
await login.setRecoveryKey(accountRecoveryKey);
await login.submit();
}
await resetPassword.resetNewPassword(credentials.password);
// Step 4 - Verify the end state. The user should either be:
// See a nice success message in fxa. Note, that we used to redirect the user back to
// the relier in some cases, but we've decided to just show the success message for now
// And let the user re-authenticate with the relier.
await isSuccessMessageDisplayed({ page });
}
await resetPassword.resetNewPassword(credentials.password);
// Step 4 - Verify the end state. The user should either be:
// See a nice success message in fxa. Note, that we used to redirect the user back to
// the relier in some cases, but we've decided to just show the success message for now
// And let the user re-authenticate with the relier.
await isSuccessMessageDisplayed({ page });
}
/** Checks that the reset password success screen is being displayed. */
async function isSuccessMessageDisplayed({ page }) {
// The user should get a verification message and the originating
// service's name should be displayed.
await page.waitForURL(
/(reset_password_verified|reset_password_with_recovery_key_verified)/
);
await page.getByText('Your password has been reset').waitFor();
await page.getByText(/.*123done.*/i).waitFor();
}
/** Checks that the reset password success screen is being displayed. */
async function isSuccessMessageDisplayed({ page }) {
// The user should get a verification message and the originating
// service's name should be displayed.
await page.waitForURL(
/(reset_password_verified|reset_password_with_recovery_key_verified)/
);
await page.getByText('Your password has been reset').waitFor();
await page.getByText(/.*123done.*/i).waitFor();
}
/** Checks that the version of the app being used is the React Version. */
async function checkForReactApp({ page }) {
expect(await page.locator('#root')).toBeVisible();
}
/** Checks that the version of the app being used is the React Version. */
async function checkForReactApp({ page }) {
expect(await page.locator('#root')).toBeVisible();
}
});

Просмотреть файл

@ -7,140 +7,142 @@ let originalEncryptionKeys;
const NEW_PASSWORD = 'notYourAveragePassW0Rd';
test.describe('recovery key react', () => {
test.beforeEach(
async ({
target,
credentials,
pages: { login, configPage, settings, recoveryKey },
}) => {
// Generating and consuming recovery keys is a slow process
test.slow();
test.describe('severity-1 #smoke', () => {
test.describe('recovery key react', () => {
test.beforeEach(
async ({
target,
credentials,
pages: { login, configPage, settings, recoveryKey },
}) => {
// Generating and consuming recovery keys is a slow process
test.slow();
// Ensure that the react reset password route feature flag is enabled
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes !== true);
// Ensure that the react reset password route feature flag is enabled
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes !== true);
await settings.goto();
let status = await settings.recoveryKey.statusText();
expect(status).toEqual('Not Set');
// Check which account recovery key generation flow to use (based on feature flag)
// TODO in FXA-7419 - remove the condition and else block that goes through the old key generation flow
if (config.featureFlags.showRecoveryKeyV2 === true) {
await settings.goto();
await settings.recoveryKey.clickCreate();
// View 1/4 info
await recoveryKey.clickStart();
// View 2/4 confirm password and generate key
await recoveryKey.setPassword(credentials.password);
await recoveryKey.submit();
let status = await settings.recoveryKey.statusText();
expect(status).toEqual('Not Set');
// View 3/4 key download
// Store key to be used later
key = await recoveryKey.getKey();
await recoveryKey.clickNext();
// Check which account recovery key generation flow to use (based on feature flag)
// TODO in FXA-7419 - remove the condition and else block that goes through the old key generation flow
if (config.featureFlags.showRecoveryKeyV2 === true) {
await settings.goto();
await settings.recoveryKey.clickCreate();
// View 1/4 info
await recoveryKey.clickStart();
// View 2/4 confirm password and generate key
await recoveryKey.setPassword(credentials.password);
await recoveryKey.submit();
// View 4/4 hint
// store hint to be used later
hint = 'secret key location';
await recoveryKey.setHint(hint);
await recoveryKey.clickFinish();
} else {
await settings.recoveryKey.clickCreate();
await recoveryKey.setPassword(credentials.password);
await recoveryKey.submit();
// View 3/4 key download
// Store key to be used later
key = await recoveryKey.getKey();
await recoveryKey.clickNext();
// Store key to be used later
key = await recoveryKey.getKey();
await recoveryKey.clickClose();
// View 4/4 hint
// store hint to be used later
hint = 'secret key location';
await recoveryKey.setHint(hint);
await recoveryKey.clickFinish();
} else {
await settings.recoveryKey.clickCreate();
await recoveryKey.setPassword(credentials.password);
await recoveryKey.submit();
// Store key to be used later
key = await recoveryKey.getKey();
await recoveryKey.clickClose();
}
// Verify status as 'enabled'
status = await settings.recoveryKey.statusText();
expect(status).toEqual('Enabled');
// Ensure password reset occurs with no session token available
login.clearCache();
// Stash original encryption keys to be verified later
const res = await target.auth.sessionReauth(
credentials.sessionToken,
credentials.email,
credentials.password,
{
keys: true,
reason: 'recovery_key',
}
);
originalEncryptionKeys = await target.auth.accountKeys(
res.keyFetchToken,
res.unwrapBKey
);
}
);
// Verify status as 'enabled'
status = await settings.recoveryKey.statusText();
expect(status).toEqual('Enabled');
test('can reset password with recovery key', async ({
credentials,
target,
page,
pages: { resetPasswordReact },
}) => {
await resetPasswordReact.goto();
// Ensure password reset occurs with no session token available
login.clearCache();
// Stash original encryption keys to be verified later
const res = await target.auth.sessionReauth(
credentials.sessionToken,
// Verify react page is loaded
await page.waitForSelector('#root');
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
await resetPasswordReact.confirmResetPasswordHeadingVisible();
// We need to append `&showReactApp=true` to reset link in order to enroll in reset password experiment
let link = await target.email.waitForEmail(
credentials.email,
credentials.password,
EmailType.recovery,
EmailHeader.link
);
link = `${link}&showReactApp=true`;
// Loads the React version
await page.goto(link);
// Verify react page is loaded
await page.waitForSelector('#root');
await resetPasswordReact.confirmRecoveryKeyHeadingVisible();
await resetPasswordReact.submitRecoveryKey(key);
await page.waitForURL(/account_recovery_reset_password/);
await resetPasswordReact.submitNewPassword(NEW_PASSWORD);
await page.waitForURL(/reset_password_with_recovery_key_verified/);
// Attempt to login with new password
const { sessionToken } = await target.auth.signIn(
credentials.email,
NEW_PASSWORD
);
const res = await target.auth.sessionReauth(
sessionToken,
credentials.email,
NEW_PASSWORD,
{
keys: true,
reason: 'recovery_key',
}
);
originalEncryptionKeys = await target.auth.accountKeys(
const newEncryptionKeys = await target.auth.accountKeys(
res.keyFetchToken,
res.unwrapBKey
);
}
);
expect(originalEncryptionKeys).toEqual(newEncryptionKeys);
test('can reset password with recovery key', async ({
credentials,
target,
page,
pages: { resetPasswordReact },
}) => {
await resetPasswordReact.goto();
// Cleanup requires setting this value to correct password
credentials.password = NEW_PASSWORD;
// Verify react page is loaded
await page.waitForSelector('#root');
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
await resetPasswordReact.confirmResetPasswordHeadingVisible();
// We need to append `&showReactApp=true` to reset link in order to enroll in reset password experiment
let link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
link = `${link}&showReactApp=true`;
// Loads the React version
await page.goto(link);
// Verify react page is loaded
await page.waitForSelector('#root');
await resetPasswordReact.confirmRecoveryKeyHeadingVisible();
await resetPasswordReact.submitRecoveryKey(key);
await page.waitForURL(/account_recovery_reset_password/);
await resetPasswordReact.submitNewPassword(NEW_PASSWORD);
await page.waitForURL(/reset_password_with_recovery_key_verified/);
// Attempt to login with new password
const { sessionToken } = await target.auth.signIn(
credentials.email,
NEW_PASSWORD
);
const res = await target.auth.sessionReauth(
sessionToken,
credentials.email,
NEW_PASSWORD,
{
keys: true,
reason: 'recovery_key',
}
);
const newEncryptionKeys = await target.auth.accountKeys(
res.keyFetchToken,
res.unwrapBKey
);
expect(originalEncryptionKeys).toEqual(newEncryptionKeys);
// Cleanup requires setting this value to correct password
credentials.password = NEW_PASSWORD;
await page
.getByRole('button', { name: 'Generate a new account recovery key' })
.click();
await page.waitForURL(/settings\/account_recovery/);
await page
.getByRole('button', { name: 'Generate a new account recovery key' })
.click();
await page.waitForURL(/settings\/account_recovery/);
});
});
});

Просмотреть файл

@ -8,236 +8,238 @@ import { getReactFeatureFlagUrl } from '../../lib/react-flag';
const NEW_PASSWORD = 'notYourAveragePassW0Rd';
test.describe('reset password react', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
test.slow();
// Ensure that the feature flag is enabled
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes !== true);
});
test('can reset password', async ({
page,
target,
credentials,
context,
pages: { login, resetPasswordReact },
}) => {
await resetPasswordReact.goto();
// Verify react page has been loaded
await page.waitForSelector('#root');
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
// Wait for navigation after email submitted
await page.waitForURL(
getReactFeatureFlagUrl(target, '/confirm_reset_password')
);
// Verify confirm password reset page rendered
await resetPasswordReact.confirmResetPasswordHeadingVisible();
// We need to append `&showReactApp=true` to reset link in order to enroll in reset password experiment
let link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
link = `${link}&showReactApp=true`;
// Open link in a new window
const diffPage = await context.newPage();
await diffPage.goto(link);
// Renders the React version of complete password reset page
await page.waitForSelector('#root');
await resetPasswordReact.completeResetPwdHeadingVisible(diffPage);
// Create and submit new password
await resetPasswordReact.submitNewPassword(NEW_PASSWORD, diffPage);
// Wait for new page to navigate
await diffPage.waitForURL(/reset_password_verified/);
// Wait for initial page to automatically redirect once password is reset
await page.waitForURL(`${target.contentServerUrl}/signin`);
// Verify password reset confirmation page is rendered
await resetPasswordReact.resetPwdConfirmedHeadingVisible(diffPage);
await diffPage.close();
// Verify initial page redirected to sign in and sign in page rendered
await login.emailHeader.waitFor();
await login.setEmail(credentials.email);
await login.clickSubmit();
await page.waitForURL(`${target.contentServerUrl}/signin`);
await login.setPassword(NEW_PASSWORD);
await login.clickSubmit();
await page.waitForURL(`${target.contentServerUrl}/settings`);
await page.getByRole('heading', { name: 'Settings', level: 2 }).waitFor();
// Check that connected service name is not empty!
expect(await page.getByTestId('service-name').innerText()).toContain(
'Firefox'
);
// Cleanup requires setting this value to correct password
credentials.password = NEW_PASSWORD;
});
test('cannot set an invalid password', async ({
page,
target,
credentials,
context,
pages: { login, resetPasswordReact },
}) => {
await resetPasswordReact.goto();
// Verify react page has been loaded
await page.waitForSelector('#root');
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
// Wait for navigation after email submitted
await page.waitForURL(
getReactFeatureFlagUrl(target, '/confirm_reset_password')
);
// Verify confirm password reset page rendered
await resetPasswordReact.confirmResetPasswordHeadingVisible();
// We need to append `&showReactApp=true` to reset link in order to enroll in reset password experiment
let link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
link = `${link}&showReactApp=true`;
// Open link in a new window
const diffPage = await context.newPage();
await diffPage.goto(link);
// Renders the React version of complete password reset page
await page.waitForSelector('#root');
await resetPasswordReact.completeResetPwdHeadingVisible(diffPage);
// Attempt to submit short password
await resetPasswordReact.submitNewPassword('2short', diffPage);
await diffPage.getByText('At least 8 characters').waitFor();
await expect(
diffPage.getByRole('textbox', { name: 'New password' })
).toBeFocused();
// Attempt to submit email as password
await resetPasswordReact.submitNewPassword(credentials.email, diffPage);
await diffPage.getByText('Not your email').waitFor();
await expect(
diffPage.getByRole('textbox', { name: 'New password' })
).toBeFocused();
// Attempt to submit a common password
await resetPasswordReact.submitNewPassword('password', diffPage);
await diffPage.getByText('Not a commonly used password').waitFor();
await expect(
diffPage.getByRole('textbox', { name: 'New password' })
).toBeFocused();
});
test('visit confirmation screen without initiating reset_password, user is redirected to /reset_password', async ({
target,
page,
pages: { resetPasswordReact },
}) => {
await resetPasswordReact.goto('/confirm_reset_password');
// Verify its redirected to react reset password page
expect(await page.locator('#root').isEnabled()).toBe(true);
await resetPasswordReact.resetPasswordHeadingVisible();
});
test('open /reset_password page from /signin', async ({
credentials,
page,
pages: { login },
}) => {
await login.goto();
await login.setEmail(credentials.email);
await login.submit();
await login.clickForgotPassword();
// Verify react page has been loaded - to be enabled when link to react page from sign in is active
// await page.waitForSelector('#root');
});
// tests for submission success with leading/trailing whitespace in email has been moved to unit tests
test('open confirm_reset_password page, click resend', async ({
credentials,
target,
page,
pages: { resetPasswordReact },
}) => {
await resetPasswordReact.goto();
// Verify react page is loaded
await page.waitForSelector('#root');
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
await page.waitForURL(
getReactFeatureFlagUrl(target, '/confirm_reset_password')
);
await resetPasswordReact.confirmResetPasswordHeadingVisible();
const resendButton = page.getByRole('button', {
name: 'Not in inbox or spam folder? Resend',
test.describe('severity-1 #smoke', () => {
test.describe('reset password react', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
test.slow();
// Ensure that the feature flag is enabled
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes !== true);
});
await resendButton.waitFor();
await resendButton.click();
await page.getByText(/Email resent/).waitFor();
});
test('open /reset_password page, enter unknown email, wait for error', async ({
target,
page,
pages: { login, resetPasswordReact },
}) => {
await resetPasswordReact.goto();
test('can reset password', async ({
page,
target,
credentials,
context,
pages: { login, resetPasswordReact },
}) => {
await resetPasswordReact.goto();
// Verify react page is loaded
await page.waitForSelector('#root');
await resetPasswordReact.fillEmailToResetPwd('email@restmail.net');
await page.getByText('Unknown account').waitFor();
});
// Verify react page has been loaded
await page.waitForSelector('#root');
test('browse directly to page with email on query params', async ({
credentials,
target,
page,
pages: { resetPasswordReact },
}) => {
await resetPasswordReact.goto(undefined, `email=${credentials.email}`);
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
// Verify react page is loaded
await page.waitForSelector('#root');
// Wait for navigation after email submitted
await page.waitForURL(
getReactFeatureFlagUrl(target, '/confirm_reset_password')
);
//The email shouldn't be pre-filled
const emailInput = await resetPasswordReact.getEmailValue();
expect(emailInput).toEqual('');
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
await page.waitForURL(
getReactFeatureFlagUrl(target, '/confirm_reset_password')
);
await page.waitForSelector('#root');
await resetPasswordReact.confirmResetPasswordHeadingVisible();
// Verify confirm password reset page rendered
await resetPasswordReact.confirmResetPasswordHeadingVisible();
// We need to append `&showReactApp=true` to reset link in order to enroll in reset password experiment
let link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
link = `${link}&showReactApp=true`;
// Open link in a new window
const diffPage = await context.newPage();
await diffPage.goto(link);
// Renders the React version of complete password reset page
await page.waitForSelector('#root');
await resetPasswordReact.completeResetPwdHeadingVisible(diffPage);
// Create and submit new password
await resetPasswordReact.submitNewPassword(NEW_PASSWORD, diffPage);
// Wait for new page to navigate
await diffPage.waitForURL(/reset_password_verified/);
// Wait for initial page to automatically redirect once password is reset
await page.waitForURL(`${target.contentServerUrl}/signin`);
// Verify password reset confirmation page is rendered
await resetPasswordReact.resetPwdConfirmedHeadingVisible(diffPage);
await diffPage.close();
// Verify initial page redirected to sign in and sign in page rendered
await login.emailHeader.waitFor();
await login.setEmail(credentials.email);
await login.clickSubmit();
await page.waitForURL(`${target.contentServerUrl}/signin`);
await login.setPassword(NEW_PASSWORD);
await login.clickSubmit();
await page.waitForURL(`${target.contentServerUrl}/settings`);
await page.getByRole('heading', { name: 'Settings', level: 2 }).waitFor();
// Check that connected service name is not empty!
expect(await page.getByTestId('service-name').innerText()).toContain(
'Firefox'
);
// Cleanup requires setting this value to correct password
credentials.password = NEW_PASSWORD;
});
test('cannot set an invalid password', async ({
page,
target,
credentials,
context,
pages: { login, resetPasswordReact },
}) => {
await resetPasswordReact.goto();
// Verify react page has been loaded
await page.waitForSelector('#root');
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
// Wait for navigation after email submitted
await page.waitForURL(
getReactFeatureFlagUrl(target, '/confirm_reset_password')
);
// Verify confirm password reset page rendered
await resetPasswordReact.confirmResetPasswordHeadingVisible();
// We need to append `&showReactApp=true` to reset link in order to enroll in reset password experiment
let link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
link = `${link}&showReactApp=true`;
// Open link in a new window
const diffPage = await context.newPage();
await diffPage.goto(link);
// Renders the React version of complete password reset page
await page.waitForSelector('#root');
await resetPasswordReact.completeResetPwdHeadingVisible(diffPage);
// Attempt to submit short password
await resetPasswordReact.submitNewPassword('2short', diffPage);
await diffPage.getByText('At least 8 characters').waitFor();
await expect(
diffPage.getByRole('textbox', { name: 'New password' })
).toBeFocused();
// Attempt to submit email as password
await resetPasswordReact.submitNewPassword(credentials.email, diffPage);
await diffPage.getByText('Not your email').waitFor();
await expect(
diffPage.getByRole('textbox', { name: 'New password' })
).toBeFocused();
// Attempt to submit a common password
await resetPasswordReact.submitNewPassword('password', diffPage);
await diffPage.getByText('Not a commonly used password').waitFor();
await expect(
diffPage.getByRole('textbox', { name: 'New password' })
).toBeFocused();
});
test('visit confirmation screen without initiating reset_password, user is redirected to /reset_password', async ({
target,
page,
pages: { resetPasswordReact },
}) => {
await resetPasswordReact.goto('/confirm_reset_password');
// Verify its redirected to react reset password page
expect(await page.locator('#root').isEnabled()).toBe(true);
await resetPasswordReact.resetPasswordHeadingVisible();
});
test('open /reset_password page from /signin', async ({
credentials,
page,
pages: { login },
}) => {
await login.goto();
await login.setEmail(credentials.email);
await login.submit();
await login.clickForgotPassword();
// Verify react page has been loaded - to be enabled when link to react page from sign in is active
// await page.waitForSelector('#root');
});
// tests for submission success with leading/trailing whitespace in email has been moved to unit tests
test('open confirm_reset_password page, click resend', async ({
credentials,
target,
page,
pages: { resetPasswordReact },
}) => {
await resetPasswordReact.goto();
// Verify react page is loaded
await page.waitForSelector('#root');
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
await page.waitForURL(
getReactFeatureFlagUrl(target, '/confirm_reset_password')
);
await resetPasswordReact.confirmResetPasswordHeadingVisible();
const resendButton = page.getByRole('button', {
name: 'Not in inbox or spam folder? Resend',
});
await resendButton.waitFor();
await resendButton.click();
await page.getByText(/Email resent/).waitFor();
});
test('open /reset_password page, enter unknown email, wait for error', async ({
target,
page,
pages: { login, resetPasswordReact },
}) => {
await resetPasswordReact.goto();
// Verify react page is loaded
await page.waitForSelector('#root');
await resetPasswordReact.fillEmailToResetPwd('email@restmail.net');
await page.getByText('Unknown account').waitFor();
});
test('browse directly to page with email on query params', async ({
credentials,
target,
page,
pages: { resetPasswordReact },
}) => {
await resetPasswordReact.goto(undefined, `email=${credentials.email}`);
// Verify react page is loaded
await page.waitForSelector('#root');
//The email shouldn't be pre-filled
const emailInput = await resetPasswordReact.getEmailValue();
expect(emailInput).toEqual('');
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
await page.waitForURL(
getReactFeatureFlagUrl(target, '/confirm_reset_password')
);
await page.waitForSelector('#root');
await resetPasswordReact.confirmResetPasswordHeadingVisible();
});
});
});

Просмотреть файл

@ -8,147 +8,150 @@ import { createCustomEventDetail, FirefoxCommand } from '../../lib/channels';
const PASSWORD = 'passwordzxcv';
test.describe('signup react', () => {
let email;
test.beforeEach(async ({ pages: { login, configPage } }) => {
test.slow();
// Ensure that the feature flag is enabled
const config = await configPage.getConfig();
test.skip(config.showReactApp.signUpRoutes !== true);
test.describe('severity-1 #smoke', () => {
test.describe('signup react', () => {
let email;
test.beforeEach(async ({ pages: { login, configPage } }) => {
test.slow();
// Ensure that the feature flag is enabled
const config = await configPage.getConfig();
test.skip(config.showReactApp.signUpRoutes !== true);
email = login.createEmail('signup_react{id}');
});
email = login.createEmail('signup_react{id}');
});
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, PASSWORD);
} catch (e) {
// Ignore errors
test.afterEach(async ({ target }) => {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, PASSWORD);
} catch (e) {
// Ignore errors
}
}
}
});
});
test('signup web', async ({ page, target, pages: { signupReact } }) => {
await signupReact.goto();
await signupReact.fillOutEmailFirst(email);
await signupReact.fillOutSignupForm(PASSWORD);
test('signup web', async ({ page, target, pages: { signupReact } }) => {
await signupReact.goto();
await signupReact.fillOutEmailFirst(email);
await signupReact.fillOutSignupForm(PASSWORD);
const code = await target.email.waitForEmail(
email,
EmailType.verifyShortCode,
EmailHeader.shortCode
);
const code = await target.email.waitForEmail(
email,
EmailType.verifyShortCode,
EmailHeader.shortCode
);
await signupReact.fillOutCodeForm(code);
await signupReact.fillOutCodeForm(code);
// Verify logged into settings page
await page.waitForURL(/settings/);
});
// Verify logged into settings page
await page.waitForURL(/settings/);
});
test('signup oauth', async ({
target,
pages: { page, signupReact, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
test('signup oauth', async ({
target,
pages: { page, signupReact, relier },
}) => {
await relier.goto();
await relier.clickEmailFirst();
const { searchParams } = new URL(page.url());
searchParams.set('email', email);
const { searchParams } = new URL(page.url());
searchParams.set('email', email);
// We want to append the experiment params here, but also keep the original oauth params
await signupReact.goto('/oauth/signup', searchParams);
await signupReact.fillOutSignupForm(PASSWORD);
// We want to append the experiment params here, but also keep the original oauth params
await signupReact.goto('/oauth/signup', searchParams);
await signupReact.fillOutSignupForm(PASSWORD);
// TODO: This needs to be uncommented once oauth is redirecting back to relier
// const code = await target.email.waitForEmail(
// email,
// EmailType.verifyShortCode,
// EmailHeader.shortCode
// );
// TODO: This needs to be uncommented once oauth is redirecting back to relier
// const code = await target.email.waitForEmail(
// email,
// EmailType.verifyShortCode,
// EmailHeader.shortCode
// );
// await signupReact.fillOutCodeForm(code);
// await signupReact.fillOutCodeForm(code);
// Verify logged in on relier page
// expect(await relier.isLoggedIn()).toBe(true);
// await page.waitForURL(/settings/);
});
// Verify logged in on relier page
// expect(await relier.isLoggedIn()).toBe(true);
// await page.waitForURL(/settings/);
});
test('signup oauth webchannel', async ({
page,
target,
pages: { login, relier, signupReact },
}) => {
const customEventDetail = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
choose_what_to_sync: true,
engines: ['bookmarks', 'history'],
},
signedInUser: null,
}
);
/* Disabling this until FXA-8287 is fixed
test('signup oauth webchannel', async ({
page,
target,
pages: { login, relier, signupReact },
}) => {
const customEventDetail = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
choose_what_to_sync: true,
engines: ['bookmarks', 'history'],
},
signedInUser: null,
}
);
await relier.goto('context=oauth_webchannel_v1&automatedBrowser=true');
await relier.clickEmailFirst();
await relier.goto('context=oauth_webchannel_v1&automatedBrowser=true');
await relier.clickEmailFirst();
await login.respondToWebChannelMessage(customEventDetail);
await login.respondToWebChannelMessage(customEventDetail);
// TODO: CTWS has not been implemented yet, probably better to pull into signupReact page
// await login.waitForCWTSEngineHeader();
// expect(await login.isCWTSEngineBookmarks()).toBe(true);
// expect(await login.isCWTSEngineHistory()).toBe(true);
// TODO: CTWS has not been implemented yet, probably better to pull into signupReact page
// await login.waitForCWTSEngineHeader();
// expect(await login.isCWTSEngineBookmarks()).toBe(true);
// expect(await login.isCWTSEngineHistory()).toBe(true);
const { searchParams } = new URL(page.url());
searchParams.set('email', email);
const { searchParams } = new URL(page.url());
searchParams.set('email', email);
// We want to append the experiment params here, but also keep the original oauth params
await signupReact.goto('/oauth/signup', searchParams);
await signupReact.fillOutSignupForm(PASSWORD);
// We want to append the experiment params here, but also keep the original oauth params
await signupReact.goto('/oauth/signup', searchParams);
await signupReact.fillOutSignupForm(PASSWORD);
// TODO: This needs to be implemented as well
// const code = await target.email.waitForEmail(
// email,
// EmailType.verifyShortCode,
// EmailHeader.shortCode
// );
//
// await signupReact.fillOutCodeForm(code);
// await login.checkWebChannelMessage(FirefoxCommand.OAuthLogin);
});
// TODO: This needs to be implemented as well
// const code = await target.email.waitForEmail(
// email,
// EmailType.verifyShortCode,
// EmailHeader.shortCode
// );
//
// await signupReact.fillOutCodeForm(code);
// await login.checkWebChannelMessage(FirefoxCommand.OAuthLogin);
});*/
test('signup sync', async ({ target }) => {
test.slow();
const syncBrowserPages = await newPagesForSync(target);
const { login, signupReact } = syncBrowserPages;
test('signup sync', async ({ target }) => {
test.slow();
const syncBrowserPages = await newPagesForSync(target);
const { login, signupReact } = syncBrowserPages;
email = login.createEmail('sync{id}');
email = login.createEmail('sync{id}');
await signupReact.goto(
'/',
new URLSearchParams({
context: 'fx_desktop_v3',
service: 'sync',
action: 'email',
})
);
await signupReact.goto(
'/',
new URLSearchParams({
context: 'fx_desktop_v3',
service: 'sync',
action: 'email',
})
);
await signupReact.fillOutEmailFirst(email);
await signupReact.fillOutSignupForm(PASSWORD);
await signupReact.fillOutEmailFirst(email);
await signupReact.fillOutSignupForm(PASSWORD);
const code = await target.email.waitForEmail(
email,
EmailType.verifyShortCode,
EmailHeader.shortCode
);
const code = await target.email.waitForEmail(
email,
EmailType.verifyShortCode,
EmailHeader.shortCode
);
await signupReact.fillOutCodeForm(code);
await signupReact.fillOutCodeForm(code);
// TODO Uncomment once sync is working
// expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
// TODO Uncomment once sync is working
// expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await syncBrowserPages.browser?.close();
await syncBrowserPages.browser?.close();
});
});
});

Просмотреть файл

@ -9,54 +9,56 @@ import { getReactFeatureFlagUrl } from '../../lib/react-flag';
test.describe.configure({ mode: 'parallel' });
let syncBrowserPages;
test.describe('Firefox Desktop Sync v3 reset password react', () => {
test.beforeEach(async ({ target, pages: { configPage } }) => {
test.slow();
// Ensure that the feature flag is enabled
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes !== true);
test.describe('severity-1 #smoke', () => {
test.describe('Firefox Desktop Sync v3 reset password react', () => {
test.beforeEach(async ({ target, pages: { configPage } }) => {
test.slow();
// Ensure that the feature flag is enabled
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes !== true);
syncBrowserPages = await newPagesForSync(target);
});
syncBrowserPages = await newPagesForSync(target);
});
test('reset pw for sync user', async ({ credentials, target }) => {
const { page, resetPasswordReact } = syncBrowserPages;
await page.goto(
getReactFeatureFlagUrl(
target,
'/reset_password',
'context=fx_desktop_v3&service=sync'
)
);
test('reset pw for sync user', async ({ credentials, target }) => {
const { page, resetPasswordReact } = syncBrowserPages;
await page.goto(
getReactFeatureFlagUrl(
target,
'/reset_password',
'context=fx_desktop_v3&service=sync'
)
);
// Verify react page has been loaded
await page.waitForSelector('#root');
// Verify react page has been loaded
await page.waitForSelector('#root');
// Check that the sync relier is in the heading
await page
.getByRole('heading', {
name: /Firefox Sync/,
})
.waitFor();
// Check that the sync relier is in the heading
await page
.getByRole('heading', {
name: /Firefox Sync/,
})
.waitFor();
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
await resetPasswordReact.fillEmailToResetPwd(credentials.email);
// We need to append `&showReactApp=true` to reset link in order to enroll in reset password experiment
let link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
link = `${link}&showReactApp=true`;
// We need to append `&showReactApp=true` to reset link in order to enroll in reset password experiment
let link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
link = `${link}&showReactApp=true`;
await page.goto(link);
await page.goto(link);
await resetPasswordReact.submitNewPassword('Newpassword@');
await page.waitForURL(/reset_password_verified/);
await resetPasswordReact.submitNewPassword('Newpassword@');
await page.waitForURL(/reset_password_verified/);
await resetPasswordReact.resetPwdConfirmedHeadingVisible();
await resetPasswordReact.resetPwdConfirmedHeadingVisible();
// Update credentials file so that account can be deleted as part of test cleanup
credentials.password = 'Newpassword@';
// Update credentials file so that account can be deleted as part of test cleanup
credentials.password = 'Newpassword@';
});
});
});

Просмотреть файл

@ -1,145 +1,151 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
import { EmailHeader, EmailType } from '../../lib/email';
const NEW_PASSWORD = 'passwordzxcv';
test.describe('Reset password current', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
test.slow();
test.describe('severity-2 #smoke', () => {
test.describe('Reset password current', () => {
test.beforeEach(async ({ pages: { configPage } }) => {
test.slow();
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes === true);
});
const config = await configPage.getConfig();
test.skip(config.showReactApp.resetPasswordRoutes === true);
});
test('can reset password', async ({
page,
target,
credentials,
context,
pages: { login, resetPassword, settings },
}) => {
await page.goto(`${target.contentServerUrl}/reset_password`);
test('can reset password', async ({
page,
target,
credentials,
context,
pages: { login, resetPassword, settings },
}) => {
await page.goto(`${target.contentServerUrl}/reset_password`);
// Verify backbone page has been loaded
await page.waitForSelector('#stage');
// Verify backbone page has been loaded
await page.waitForSelector('#stage');
await resetPassword.fillOutResetPassword(credentials.email);
await resetPassword.fillOutResetPassword(credentials.email);
// Verify confirm password reset page has rendered
await resetPassword.confirmResetPasswordHeader();
// Verify confirm password reset page has rendered
await resetPassword.confirmResetPasswordHeader();
const link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
const link = await target.email.waitForEmail(
credentials.email,
EmailType.recovery,
EmailHeader.link
);
// Open link in a new window
const diffPage = await context.newPage();
await diffPage.goto(link);
// Open link in a new window
const diffPage = await context.newPage();
await diffPage.goto(link);
await resetPassword.completeResetPasswordHeader(diffPage);
await resetPassword.completeResetPasswordHeader(diffPage);
await resetPassword.resetNewPassword(NEW_PASSWORD, diffPage);
await resetPassword.resetNewPassword(NEW_PASSWORD, diffPage);
await page.getByRole('heading', { name: 'Settings', level: 2 }).waitFor();
await page.getByRole('heading', { name: 'Settings', level: 2 }).waitFor();
await diffPage
.getByRole('heading', { name: 'Settings', level: 2 })
.waitFor();
await diffPage
.getByRole('heading', { name: 'Settings', level: 2 })
.waitFor();
await diffPage.close();
await settings.signOut();
await diffPage.close();
await settings.signOut();
// Verify that new password can be used to log in
await login.setEmail(credentials.email);
await login.submit();
await login.setPassword(NEW_PASSWORD);
await login.submit();
// Verify that new password can be used to log in
await login.setEmail(credentials.email);
await login.submit();
await login.setPassword(NEW_PASSWORD);
await login.submit();
await page.getByRole('heading', { name: 'Settings', level: 2 }).waitFor();
await page.getByRole('heading', { name: 'Settings', level: 2 }).waitFor();
// Cleanup requires setting this value to correct password
credentials.password = NEW_PASSWORD;
});
// Cleanup requires setting this value to correct password
credentials.password = NEW_PASSWORD;
});
test('visit confirmation screen without initiating reset_password, user is redirected to /reset_password', async ({
target,
page,
pages: { resetPassword },
}) => {
await page.goto(
`${target.contentServerUrl}/confirm_reset_password?showReactApp=false`
);
test('visit confirmation screen without initiating reset_password, user is redirected to /reset_password', async ({
target,
page,
pages: { resetPassword },
}) => {
await page.goto(
`${target.contentServerUrl}/confirm_reset_password?showReactApp=false`
);
// Verify its redirected to reset password page
await resetPassword.resetPasswordHeader();
});
// Verify its redirected to reset password page
await resetPassword.resetPasswordHeader();
});
test('open /reset_password page from /signin', async ({
credentials,
pages: { login },
}) => {
await login.goto();
await login.setEmail(credentials.email);
await login.submit();
await login.clickForgotPassword();
});
test('open /reset_password page from /signin', async ({
credentials,
pages: { login },
}) => {
await login.goto();
await login.setEmail(credentials.email);
await login.submit();
await login.clickForgotPassword();
});
test('enter an email with leading/trailing whitespace', async ({
credentials,
target,
page,
pages: { login, resetPassword },
}) => {
await page.goto(`${target.contentServerUrl}/reset_password`);
await resetPassword.fillOutResetPassword(' ' + credentials.email);
await resetPassword.confirmResetPasswordHeader();
test('enter an email with leading/trailing whitespace', async ({
credentials,
target,
page,
pages: { login, resetPassword },
}) => {
await page.goto(`${target.contentServerUrl}/reset_password`);
await resetPassword.fillOutResetPassword(' ' + credentials.email);
await resetPassword.confirmResetPasswordHeader();
await page.goto(`${target.contentServerUrl}/reset_password`);
await resetPassword.fillOutResetPassword(credentials.email + ' ');
await resetPassword.confirmResetPasswordHeader();
});
await page.goto(`${target.contentServerUrl}/reset_password`);
await resetPassword.fillOutResetPassword(credentials.email + ' ');
await resetPassword.confirmResetPasswordHeader();
});
test('open confirm_reset_password page, click resend', async ({
credentials,
target,
page,
pages: { resetPassword },
}) => {
await page.goto(`${target.contentServerUrl}/reset_password`);
await resetPassword.fillOutResetPassword(credentials.email);
await resetPassword.clickResend();
expect(await resetPassword.resendSuccessMessage()).toContain(
'Email resent. Add accounts@firefox.com to your contacts to ensure a smooth delivery.'
);
});
test('open confirm_reset_password page, click resend', async ({
credentials,
target,
page,
pages: { resetPassword },
}) => {
await page.goto(`${target.contentServerUrl}/reset_password`);
await resetPassword.fillOutResetPassword(credentials.email);
await resetPassword.clickResend();
expect(await resetPassword.resendSuccessMessage()).toContain(
'Email resent. Add accounts@firefox.com to your contacts to ensure a smooth delivery.'
);
});
test('open /reset_password page, enter unknown email, wait for error', async ({
target,
page,
pages: { login, resetPassword },
}) => {
await page.goto(`${target.contentServerUrl}/reset_password`);
await login.setEmail('email@restmail.net');
await resetPassword.clickBeginReset();
expect(await resetPassword.unknownAccountError()).toContain(
'Unknown account.'
);
});
test('open /reset_password page, enter unknown email, wait for error', async ({
target,
page,
pages: { login, resetPassword },
}) => {
await page.goto(`${target.contentServerUrl}/reset_password`);
await login.setEmail('email@restmail.net');
await resetPassword.clickBeginReset();
expect(await resetPassword.unknownAccountError()).toContain(
'Unknown account.'
);
});
test('browse directly to page with email on query params', async ({
credentials,
target,
page,
pages: { resetPassword },
}) => {
const url = `${target.contentServerUrl}/reset_password?email=${credentials.email}`;
await page.goto(url);
test('browse directly to page with email on query params', async ({
credentials,
target,
page,
pages: { resetPassword },
}) => {
const url = `${target.contentServerUrl}/reset_password?email=${credentials.email}`;
await page.goto(url);
//The email shouldn't be pre-filled
expect(await resetPassword.getEmailValue()).toBeEmpty();
await resetPassword.fillOutResetPassword(credentials.email);
await resetPassword.confirmResetPasswordHeader();
//The email shouldn't be pre-filled
expect(await resetPassword.getEmailValue()).toBeEmpty();
await resetPassword.fillOutResetPassword(credentials.email);
await resetPassword.confirmResetPasswordHeader();
});
});
});

Просмотреть файл

@ -1,6 +1,10 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
test.describe('severity-2 #smoke', () => {
test.describe('severity-1 #smoke', () => {
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293498
test('settings avatar drop-down #1293498', async ({
credentials,

Просмотреть файл

@ -1,161 +1,167 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
let newEmail;
test.describe('change primary email tests', () => {
test.beforeEach(
async ({ credentials, pages: { settings, secondaryEmail } }) => {
test.slow();
await settings.goto();
await settings.secondaryEmail.clickAdd();
newEmail = credentials.email.replace(/(\w+)/, '$1_alt');
await secondaryEmail.addAndVerify(newEmail);
await settings.waitForAlertBar();
await settings.secondaryEmail.clickMakePrimary();
}
);
test('change primary email and login', async ({
credentials,
page,
pages: { login, settings },
}) => {
await settings.signOut();
// Sign in with old primary email fails
await login.setEmail(credentials.email);
await page.locator('button[type=submit]').click();
await login.setPassword(credentials.password);
await page.locator('button[type=submit]').click();
expect(await login.signInError()).toContain(
'Primary account email required for sign-in'
test.describe('severity-1 #smoke', () => {
test.describe('change primary email tests', () => {
test.beforeEach(
async ({ credentials, pages: { settings, secondaryEmail } }) => {
test.slow();
await settings.goto();
await settings.secondaryEmail.clickAdd();
newEmail = credentials.email.replace(/(\w+)/, '$1_alt');
await secondaryEmail.addAndVerify(newEmail);
await settings.waitForAlertBar();
await settings.secondaryEmail.clickMakePrimary();
}
);
// Success signing in with New email
await login.useDifferentAccountLink();
await login.login(newEmail, credentials.password);
const primary = await settings.primaryEmail.statusText();
expect(primary).toEqual(newEmail);
});
test('change primary email, password and login', async ({
credentials,
page,
pages: { settings, changePassword, login },
}) => {
const newPassword = credentials.password + '@@2';
await settings.password.clickChange();
await changePassword.setCurrentPassword(credentials.password);
await changePassword.setNewPassword(newPassword);
await changePassword.setConfirmPassword(newPassword);
await changePassword.submit();
await settings.signOut();
// Sign in with old password
await login.setEmail(newEmail);
await page.locator('button[type=submit]').click();
await login.setPassword(credentials.password);
await page.locator('button[type=submit]').click();
expect(await login.getTooltipError()).toContain('Incorrect password');
// Sign in with new password
credentials.password = newPassword;
await login.setPassword(credentials.password);
await login.submit();
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(newEmail);
});
test('change primary email, change password, login, change email and login', async ({
credentials,
pages: { settings, changePassword, login },
}) => {
const newPassword = credentials.password + '@@4';
await settings.password.clickChange();
await changePassword.setCurrentPassword(credentials.password);
await changePassword.setNewPassword(newPassword);
await changePassword.setConfirmPassword(newPassword);
await changePassword.submit();
await settings.signOut();
// Sign in with new password
credentials.password = newPassword;
await login.login(newEmail, credentials.password);
// Change back the primary email again
await settings.secondaryEmail.clickMakePrimary();
await settings.signOut();
// Login with primary email and new password
await login.login(credentials.email, credentials.password);
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(credentials.email);
});
test('can change primary email, delete account', async ({
credentials,
page,
pages: { settings, deleteAccount, login, secondaryEmail },
}) => {
// Click delete account
await settings.clickDeleteAccount();
await deleteAccount.checkAllBoxes();
await deleteAccount.clickContinue();
// Enter the correct password
await deleteAccount.setPassword(credentials.password);
await deleteAccount.submit();
// // Try creating a new account with the same secondary email as previous account and new password
await login.fillOutFirstSignUp(newEmail, credentials.password);
expect(await settings.alertBarText()).toContain(
'Account confirmed successfully'
);
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(newEmail);
});
});
test.describe('change primary - unblock', () => {
test.beforeEach(
async ({ credentials, pages: { settings, secondaryEmail } }) => {
test.slow();
await settings.goto();
await settings.secondaryEmail.clickAdd();
const newEmail = `blocked${Math.floor(
Math.random() * 100000
)}@restmail.net`;
await secondaryEmail.addAndVerify(newEmail);
await settings.secondaryEmail.clickMakePrimary();
credentials.email = newEmail;
test('change primary email and login', async ({
credentials,
page,
pages: { login, settings },
}) => {
await settings.signOut();
}
);
test('change primary email, get blocked with invalid password, redirect enter password page', async ({
credentials,
pages: { login },
}) => {
const invalidPassword = credentials.password + '@@2';
await login.login(credentials.email, invalidPassword);
// Sign in with old primary email fails
await login.setEmail(credentials.email);
await page.locator('button[type=submit]').click();
await login.setPassword(credentials.password);
await page.locator('button[type=submit]').click();
expect(await login.signInError()).toContain(
'Primary account email required for sign-in'
);
// Fill out unblock
await login.unblock(credentials.email);
// Success signing in with New email
await login.useDifferentAccountLink();
await login.login(newEmail, credentials.password);
const primary = await settings.primaryEmail.statusText();
expect(primary).toEqual(newEmail);
});
// Verify the incorrect password error
expect(await login.signInError()).toContain('Incorrect password');
test('change primary email, password and login', async ({
credentials,
page,
pages: { settings, changePassword, login },
}) => {
const newPassword = credentials.password + '@@2';
await settings.password.clickChange();
await changePassword.setCurrentPassword(credentials.password);
await changePassword.setNewPassword(newPassword);
await changePassword.setConfirmPassword(newPassword);
await changePassword.submit();
await settings.signOut();
// Sign in with old password
await login.setEmail(newEmail);
await page.locator('button[type=submit]').click();
await login.setPassword(credentials.password);
await page.locator('button[type=submit]').click();
expect(await login.getTooltipError()).toContain('Incorrect password');
// Sign in with new password
credentials.password = newPassword;
await login.setPassword(credentials.password);
await login.submit();
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(newEmail);
});
test('change primary email, change password, login, change email and login', async ({
credentials,
pages: { settings, changePassword, login },
}) => {
const newPassword = credentials.password + '@@4';
await settings.password.clickChange();
await changePassword.setCurrentPassword(credentials.password);
await changePassword.setNewPassword(newPassword);
await changePassword.setConfirmPassword(newPassword);
await changePassword.submit();
await settings.signOut();
// Sign in with new password
credentials.password = newPassword;
await login.login(newEmail, credentials.password);
// Change back the primary email again
await settings.secondaryEmail.clickMakePrimary();
await settings.signOut();
// Login with primary email and new password
await login.login(credentials.email, credentials.password);
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(credentials.email);
});
test('can change primary email, delete account', async ({
credentials,
page,
pages: { settings, deleteAccount, login, secondaryEmail },
}) => {
// Click delete account
await settings.clickDeleteAccount();
await deleteAccount.checkAllBoxes();
await deleteAccount.clickContinue();
// Enter the correct password
await deleteAccount.setPassword(credentials.password);
await deleteAccount.submit();
// // Try creating a new account with the same secondary email as previous account and new password
await login.fillOutFirstSignUp(newEmail, credentials.password);
expect(await settings.alertBarText()).toContain(
'Account confirmed successfully'
);
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(newEmail);
});
});
test('can change primary email, get blocked with valid password, redirect settings page', async ({
credentials,
page,
pages: { settings, login },
}) => {
await login.login(credentials.email, credentials.password);
test.describe('change primary - unblock', () => {
test.beforeEach(
async ({ credentials, pages: { settings, secondaryEmail } }) => {
test.slow();
await settings.goto();
await settings.secondaryEmail.clickAdd();
const newEmail = `blocked${Math.floor(
Math.random() * 100000
)}@restmail.net`;
await secondaryEmail.addAndVerify(newEmail);
await settings.secondaryEmail.clickMakePrimary();
credentials.email = newEmail;
await settings.signOut();
}
);
// Fill out unblock
await login.unblock(credentials.email);
test('change primary email, get blocked with invalid password, redirect enter password page', async ({
credentials,
pages: { login },
}) => {
const invalidPassword = credentials.password + '@@2';
await login.login(credentials.email, invalidPassword);
// Verify settings url redirected
expect(page.url()).toBe(settings.url);
// Fill out unblock
await login.unblock(credentials.email);
// Verify the incorrect password error
expect(await login.signInError()).toContain('Incorrect password');
});
test('can change primary email, get blocked with valid password, redirect settings page', async ({
credentials,
page,
pages: { settings, login },
}) => {
await login.login(credentials.email, credentials.password);
// Fill out unblock
await login.unblock(credentials.email);
// Verify settings url redirected
expect(page.url()).toBe(settings.url);
});
});
});

Просмотреть файл

@ -1,101 +1,107 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
let newPassword;
test.describe('change password tests', () => {
test.beforeEach(async ({ pages: { settings }, credentials }) => {
newPassword = credentials.password + '@@2';
await settings.goto();
await settings.password.clickChange();
});
test.describe('severity-1 #smoke', () => {
test.describe('change password tests', () => {
test.beforeEach(async ({ pages: { settings }, credentials }) => {
newPassword = credentials.password + '@@2';
await settings.goto();
await settings.password.clickChange();
});
test('change password with an incorrect old password', async ({
pages: { changePassword },
}) => {
test.slow();
// Enter incorrect old password and verify the tooltip error
await changePassword.fillOutChangePassword(
'Incorrect Password',
newPassword
);
await changePassword.clickSignIn();
expect(await changePassword.changePasswordTooltip()).toContain(
'Incorrect password'
);
});
test('change password with an incorrect old password', async ({
pages: { changePassword },
}) => {
test.slow();
// Enter incorrect old password and verify the tooltip error
await changePassword.fillOutChangePassword(
'Incorrect Password',
newPassword
);
await changePassword.clickSignIn();
expect(await changePassword.changePasswordTooltip()).toContain(
'Incorrect password'
);
});
test('change password with a correct password', async ({
pages: { settings, changePassword, login },
credentials,
}) => {
test.slow();
// Enter the correct old password and verify that change password is successful
await changePassword.fillOutChangePassword(
credentials.password,
newPassword
);
await changePassword.submit();
test('change password with a correct password', async ({
pages: { settings, changePassword, login },
credentials,
}) => {
test.slow();
// Enter the correct old password and verify that change password is successful
await changePassword.fillOutChangePassword(
credentials.password,
newPassword
);
await changePassword.submit();
// Sign out and login with new password
await settings.signOut();
credentials.password = newPassword;
await login.setEmail(credentials.email);
await changePassword.clickSignIn();
await login.setPassword(credentials.password);
await login.submit();
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(credentials.email);
});
// Sign out and login with new password
await settings.signOut();
credentials.password = newPassword;
await login.setEmail(credentials.email);
await changePassword.clickSignIn();
await login.setPassword(credentials.password);
await login.submit();
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(credentials.email);
});
test('new password validation', async ({
pages: { changePassword },
credentials,
}) => {
// Short password
await changePassword.setNewPassword('short');
expect(await changePassword.passwordLengthError()).toBe(true);
test('new password validation', async ({
pages: { changePassword },
credentials,
}) => {
// Short password
await changePassword.setNewPassword('short');
expect(await changePassword.passwordLengthError()).toBe(true);
// Password same as email
await changePassword.setNewPassword(credentials.email);
expect(await changePassword.passwordSameAsEmailError()).toBe(true);
// Password same as email
await changePassword.setNewPassword(credentials.email);
expect(await changePassword.passwordSameAsEmailError()).toBe(true);
// Set a common password
await changePassword.setNewPassword('passwords');
expect(await changePassword.commonPasswordError()).toBe(true);
// Set a common password
await changePassword.setNewPassword('passwords');
expect(await changePassword.commonPasswordError()).toBe(true);
// Confirm password doesn't match the new password
await changePassword.setNewPassword(credentials.password);
await changePassword.setConfirmPassword(credentials.password + '2');
expect(await changePassword.confirmPasswordError()).toBe(true);
// Confirm password doesn't match the new password
await changePassword.setNewPassword(credentials.password);
await changePassword.setConfirmPassword(credentials.password + '2');
expect(await changePassword.confirmPasswordError()).toBe(true);
// valid password
await changePassword.setCurrentPassword(credentials.password);
await changePassword.setNewPassword(newPassword);
await changePassword.setConfirmPassword(newPassword);
expect(await changePassword.submitButton()).toBe(true);
});
// valid password
await changePassword.setCurrentPassword(credentials.password);
await changePassword.setNewPassword(newPassword);
await changePassword.setConfirmPassword(newPassword);
expect(await changePassword.submitButton()).toBe(true);
});
test('change password with short password tooltip shows, cancel and try to change password again, tooltip is not shown', async ({
pages: { settings, changePassword },
}) => {
// Short password
await changePassword.setNewPassword('short');
expect(await changePassword.passwordLengthError()).toBe(true);
test('change password with short password tooltip shows, cancel and try to change password again, tooltip is not shown', async ({
pages: { settings, changePassword },
}) => {
// Short password
await changePassword.setNewPassword('short');
expect(await changePassword.passwordLengthError()).toBe(true);
// Click cancel and navigate to change password again
await changePassword.clickCancelChangePassword();
await settings.password.clickChange();
expect(await changePassword.validPasswordLength()).toBe(true);
});
// Click cancel and navigate to change password again
await changePassword.clickCancelChangePassword();
await settings.password.clickChange();
expect(await changePassword.validPasswordLength()).toBe(true);
});
test('reset password via settings works', async ({
pages: { login, resetPassword },
}, { project }) => {
test.slow();
test('reset password via settings works', async ({
pages: { login, resetPassword },
}, { project }) => {
test.slow();
// Click forgot password link
await login.clickForgotPassword();
// Click forgot password link
await login.clickForgotPassword();
// Verify it navigates to reset password page
await resetPassword.resetPasswordHeader();
// Verify it navigates to reset password page
await resetPassword.resetPasswordHeader();
});
});
});

Просмотреть файл

@ -1,4 +1,8 @@
import { test, expect, newPages } from '../../lib/fixtures/standard';
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
test.describe('severity-1 #smoke', () => {
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293493

Просмотреть файл

@ -1,4 +1,8 @@
import { test, expect, newPages } from '../../lib/fixtures/standard';
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
test.describe('severity-2 #smoke', () => {
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293371

Просмотреть файл

@ -1,4 +1,8 @@
import { test, expect, newPages } from '../../lib/fixtures/standard';
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
test.describe('severity-1 #smoke', () => {
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293407
@ -53,7 +57,7 @@ test.describe('severity-1 #smoke', () => {
});
});
test.describe('severity-3 #smoke', () => {
test.describe('severity-2 #smoke', () => {
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293501
test('settings bento menu #1293501', async ({
page,

Просмотреть файл

@ -1,3 +1,7 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
import { EmailHeader, EmailType } from '../../lib/email';

Просмотреть файл

@ -1,3 +1,7 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
test.describe('password visibility tests', () => {

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,156 +1,162 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
import { EmailHeader, EmailType } from '../../lib/email';
test.describe('two step auth', () => {
test.beforeEach(async ({}, { project }) => {
// 2FA test can be slow because of time to generate recovery keys
test.slow();
});
test.describe('severity-1 #smoke', () => {
test.describe('two step auth', () => {
test.beforeEach(async ({}, { project }) => {
// 2FA test can be slow because of time to generate recovery keys
test.slow();
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293446
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293452
test('add and remove totp', async ({
credentials,
pages: { settings, totp, login },
}) => {
await settings.goto();
let status = await settings.totp.statusText();
expect(status).toEqual('Not Set');
await settings.totp.clickAdd();
await totp.enable(credentials);
await settings.waitForAlertBar();
status = await settings.totp.statusText();
expect(status).toEqual('Enabled');
await settings.totp.clickDisable();
await settings.clickModalConfirm();
await settings.waitForAlertBar();
status = await settings.totp.statusText();
expect(status).toEqual('Not Set');
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293446
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293452
test('add and remove totp', async ({
credentials,
pages: { settings, totp, login },
}) => {
await settings.goto();
let status = await settings.totp.statusText();
expect(status).toEqual('Not Set');
await settings.totp.clickAdd();
await totp.enable(credentials);
await settings.waitForAlertBar();
status = await settings.totp.statusText();
expect(status).toEqual('Enabled');
await settings.totp.clickDisable();
await settings.clickModalConfirm();
await settings.waitForAlertBar();
status = await settings.totp.statusText();
expect(status).toEqual('Not Set');
// Login to verify no prompt for code
await settings.signOut();
await login.login(credentials.email, credentials.password);
expect(await login.isUserLoggedIn()).toBe(true);
});
// Login to verify no prompt for code
await settings.signOut();
await login.login(credentials.email, credentials.password);
expect(await login.isUserLoggedIn()).toBe(true);
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293445
test('totp use QR code #1293445', async ({
credentials,
pages: { settings, totp },
}) => {
await settings.goto();
let status = await settings.totp.statusText();
expect(status).toEqual('Not Set');
await settings.totp.clickAdd();
await totp.enable(credentials, 'qr');
await settings.waitForAlertBar();
status = await settings.totp.statusText();
expect(status).toEqual('Enabled');
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293445
test('totp use QR code #1293445', async ({
credentials,
pages: { settings, totp },
}) => {
await settings.goto();
let status = await settings.totp.statusText();
expect(status).toEqual('Not Set');
await settings.totp.clickAdd();
await totp.enable(credentials, 'qr');
await settings.waitForAlertBar();
status = await settings.totp.statusText();
expect(status).toEqual('Enabled');
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293459
test('add TOTP and login', async ({
credentials,
pages: { login, settings, totp },
}) => {
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
await settings.signOut();
await login.login(credentials.email, credentials.password);
await login.setTotp(credentials.secret);
const status = await settings.totp.statusText();
expect(status).toEqual('Enabled');
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293459
test('add TOTP and login', async ({
credentials,
pages: { login, settings, totp },
}) => {
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
await settings.signOut();
await login.login(credentials.email, credentials.password);
await login.setTotp(credentials.secret);
const status = await settings.totp.statusText();
expect(status).toEqual('Enabled');
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293450
test('can change backup authentication codes #1293450', async ({
credentials,
page,
pages: { settings, totp, login },
}) => {
await settings.goto();
await settings.totp.clickAdd();
const { recoveryCodes } = await totp.enable(credentials);
await settings.totp.clickChange();
await settings.clickModalConfirm();
const newCodes = await totp.getRecoveryCodes();
for (const code of recoveryCodes) {
expect(newCodes).not.toContain(code);
}
await settings.clickRecoveryCodeAck();
await totp.setRecoveryCode(newCodes[0]);
await totp.submit();
await settings.waitForAlertBar();
await settings.signOut();
await login.login(credentials.email, credentials.password);
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293450
test('can change backup authentication codes #1293450', async ({
credentials,
page,
pages: { settings, totp, login },
}) => {
await settings.goto();
await settings.totp.clickAdd();
const { recoveryCodes } = await totp.enable(credentials);
await settings.totp.clickChange();
await settings.clickModalConfirm();
const newCodes = await totp.getRecoveryCodes();
for (const code of recoveryCodes) {
expect(newCodes).not.toContain(code);
}
await settings.clickRecoveryCodeAck();
await totp.setRecoveryCode(newCodes[0]);
await totp.submit();
await settings.waitForAlertBar();
await settings.signOut();
await login.login(credentials.email, credentials.password);
// Make sure an invalid code doesn't work
await login.clickUseRecoveryCode();
await login.setCode('invalid!!!!');
await login.submitButton.click();
await expect(login.tooltip).toContainText('Invalid');
// Make sure an invalid code doesn't work
await login.clickUseRecoveryCode();
await login.setCode('invalid!!!!');
await login.submitButton.click();
await expect(login.tooltip).toContainText('Invalid');
// Apply the correct code
await login.setCode(newCodes[0]);
await login.submit();
// Apply the correct code
await login.setCode(newCodes[0]);
await login.submit();
expect(page.url()).toContain(settings.url);
});
expect(page.url()).toContain(settings.url);
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293460
test('can get new backup authentication codes via email #1293460', async ({
target,
credentials,
pages: { page, login, settings, totp },
}, { project }) => {
await settings.goto();
await settings.totp.clickAdd();
const { recoveryCodes } = await totp.enable(credentials);
await settings.signOut();
for (let i = 0; i < recoveryCodes.length - 3; i++) {
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293460
test('can get new backup authentication codes via email #1293460', async ({
target,
credentials,
pages: { page, login, settings, totp },
}, { project }) => {
await settings.goto();
await settings.totp.clickAdd();
const { recoveryCodes } = await totp.enable(credentials);
await settings.signOut();
for (let i = 0; i < recoveryCodes.length - 3; i++) {
await login.login(
credentials.email,
credentials.password,
recoveryCodes[i]
);
await login.page.waitForURL(/settings/);
await settings.signOut();
}
await login.login(
credentials.email,
credentials.password,
recoveryCodes[i]
recoveryCodes[recoveryCodes.length - 1]
);
await login.page.waitForURL(/settings/);
await settings.signOut();
}
await login.login(
credentials.email,
credentials.password,
recoveryCodes[recoveryCodes.length - 1]
);
await login.page.waitForURL(/settings/);
const link = await target.email.waitForEmail(
credentials.email,
EmailType.lowRecoveryCodes,
EmailHeader.link
);
await page.goto(link);
const newCodes = await totp.getRecoveryCodes();
expect(newCodes.length).toEqual(recoveryCodes.length);
});
const link = await target.email.waitForEmail(
credentials.email,
EmailType.lowRecoveryCodes,
EmailHeader.link
);
await page.goto(link);
const newCodes = await totp.getRecoveryCodes();
expect(newCodes.length).toEqual(recoveryCodes.length);
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293461
test('delete account with totp enabled #1293461', async ({
credentials,
page,
pages: { settings, totp, login, deleteAccount },
}) => {
await settings.goto();
await settings.totp.clickAdd();
const { secret } = await totp.enable(credentials);
await settings.signOut();
await login.login(credentials.email, credentials.password);
await login.setTotp(secret);
await settings.clickDeleteAccount();
await deleteAccount.checkAllBoxes();
await deleteAccount.clickContinue();
await deleteAccount.setPassword(credentials.password);
await deleteAccount.submit();
const success = await page.waitForSelector('.success');
expect(await success.isVisible()).toBeTruthy();
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293461
test('delete account with totp enabled #1293461', async ({
credentials,
page,
pages: { settings, totp, login, deleteAccount },
}) => {
await settings.goto();
await settings.totp.clickAdd();
const { secret } = await totp.enable(credentials);
await settings.signOut();
await login.login(credentials.email, credentials.password);
await login.setTotp(secret);
await settings.clickDeleteAccount();
await deleteAccount.checkAllBoxes();
await deleteAccount.clickContinue();
await deleteAccount.setPassword(credentials.password);
await deleteAccount.submit();
const success = await page.waitForSelector('.success');
expect(await success.isVisible()).toBeTruthy();
});
});
});

Просмотреть файл

@ -6,191 +6,203 @@ import { test, expect } from '../../lib/fixtures/standard';
const password = 'password12345678';
test.describe('signup here', () => {
test.beforeEach(async () => {
test.slow();
});
test.describe('severity-2 #smoke', () => {
test.describe('signup here', () => {
test.beforeEach(async () => {
test.slow();
});
test('with an invalid email, empty email query query param', async ({
target,
page,
pages: { login },
}) => {
await page.goto(`${target.contentServerUrl}?email=invalid`);
expect(await login.getErrorMessage()).toContain('Invalid parameter: email');
test('with an invalid email, empty email query query param', async ({
target,
page,
pages: { login },
}) => {
await page.goto(`${target.contentServerUrl}?email=invalid`);
expect(await login.getErrorMessage()).toContain(
'Invalid parameter: email'
);
await page.goto(`${target.contentServerUrl}?email=`);
expect(await login.getErrorMessage()).toContain('Invalid parameter: email');
});
test('signup with email with leading/trailing whitespace on the email', async ({
target,
page,
pages: { login },
}) => {
let email = login.createEmail();
let emailWithoutSpace = email;
let emailWithSpace = ' ' + email;
await page.goto(target.contentServerUrl);
await login.fillOutFirstSignUp(emailWithSpace, password, { verify: false });
// Verify the confirm code header and the email
await login.waitForSignUpCodeHeader();
expect(await login.confirmEmail()).toContain(emailWithoutSpace);
// Need to clear the cache to get the new email
await login.clearCache();
await page.goto(target.contentServerUrl);
email = login.createEmail();
emailWithoutSpace = email;
emailWithSpace = email + ' ';
await login.fillOutFirstSignUp(emailWithSpace, password, { verify: false });
await login.waitForSignUpCodeHeader();
expect(await login.confirmEmail()).toContain(emailWithoutSpace);
});
test('signup with invalid email address', async ({
target,
page,
pages: { login },
}) => {
await page.goto(target.contentServerUrl);
await login.setEmail('invalidemail');
await login.clickSubmit();
// Verify the error
expect(await login.getTooltipError()).toContain('Valid email required');
});
test('coppa is empty and too young', async ({
target,
page,
pages: { login },
}) => {
const email = login.createEmail();
await page.goto(target.contentServerUrl);
await login.setEmail(email);
await login.clickSubmit();
await page.waitForURL(/signup/);
await login.setPassword(password);
await login.confirmPassword(password);
await login.clickSubmit();
// Verify the error
expect(await login.getTooltipError()).toContain(
'You must enter your age to sign up'
);
await login.setAge('12');
await login.clickSubmit();
// Verify navigated to the cannot create account page
await page.waitForURL(/cannot_create_account/);
// TODO: this is flaky
// expect(await login.cannotCreateAccountHeader()).toBe(true);
});
test('sign up with non matching passwords', async ({
target,
page,
pages: { login },
}) => {
const email = login.createEmail();
await page.goto(target.contentServerUrl);
await login.setEmail(email);
await login.clickSubmit();
await login.setPassword(password);
await login.confirmPassword('wrongpassword');
await login.setAge('24');
await login.clickSubmit();
// Verify the error
expect(await login.getTooltipError()).toContain('Passwords do not match');
});
test('form prefill information is cleared after signup->sign out', async ({
target,
page,
pages: { login, settings },
}) => {
const email = login.createEmail();
await page.goto(target.contentServerUrl);
await login.fillOutFirstSignUp(email, password);
// The original tab should transition to the settings page w/ success
// message.
expect(await login.isUserLoggedIn()).toBe(true);
await settings.signOut();
// check the email address was cleared
await login.waitForEmailHeader();
expect(await login.getEmailInput()).toContain('');
await login.setEmail(login.createEmail());
await login.clickSubmit();
// check the password was cleared
expect(await login.getPasswordInput()).toContain('');
});
test('signup via relier page and redirect after confirm', async ({
pages: { login, relier },
}) => {
const email = login.createEmail();
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password);
expect(await relier.isLoggedIn()).toBe(true);
});
test('signup, verify and sign out of two accounts, all in the same tab, then sign in to the first account', async ({
target,
page,
pages: { login, settings },
}) => {
const email = login.createEmail();
const secondEmail = login.createEmail();
await page.goto(target.contentServerUrl);
await login.fillOutFirstSignUp(email, password);
// The original tab should transition to the settings page w/ success
// message.
expect(await login.isUserLoggedIn()).toBe(true);
// Verify the account is in local storage and has a correct state
const currentAccountUid = await page.evaluate(() => {
return JSON.parse(
localStorage.getItem('__fxa_storage.currentAccountUid') || ''
await page.goto(`${target.contentServerUrl}?email=`);
expect(await login.getErrorMessage()).toContain(
'Invalid parameter: email'
);
});
const accounts = await page.evaluate(() => {
return JSON.parse(localStorage.getItem('__fxa_storage.accounts') || '{}');
test('signup with email with leading/trailing whitespace on the email', async ({
target,
page,
pages: { login },
}) => {
let email = login.createEmail();
let emailWithoutSpace = email;
let emailWithSpace = ' ' + email;
await page.goto(target.contentServerUrl);
await login.fillOutFirstSignUp(emailWithSpace, password, {
verify: false,
});
// Verify the confirm code header and the email
await login.waitForSignUpCodeHeader();
expect(await login.confirmEmail()).toContain(emailWithoutSpace);
// Need to clear the cache to get the new email
await login.clearCache();
await page.goto(target.contentServerUrl);
email = login.createEmail();
emailWithoutSpace = email;
emailWithSpace = email + ' ';
await login.fillOutFirstSignUp(emailWithSpace, password, {
verify: false,
});
await login.waitForSignUpCodeHeader();
expect(await login.confirmEmail()).toContain(emailWithoutSpace);
});
const account = accounts[currentAccountUid];
expect(currentAccountUid).toBeDefined();
expect(accounts).toBeDefined();
expect(accounts[currentAccountUid]).toBeDefined();
expect(account.email).toBe(email);
expect(account.lastLogin).toBeDefined();
expect(account.metricsEnabled).toBe(true);
expect(account.sessionToken).toBeDefined();
expect(account.uid).toBeDefined();
expect(account.verified).toBe(true);
await settings.signOut();
test('signup with invalid email address', async ({
target,
page,
pages: { login },
}) => {
await page.goto(target.contentServerUrl);
await login.setEmail('invalidemail');
await login.clickSubmit();
await login.fillOutFirstSignUp(secondEmail, password);
// Verify the error
expect(await login.getTooltipError()).toContain('Valid email required');
});
// The original tab should transition to the settings page w/ success
// message.
expect(await login.isUserLoggedIn()).toBe(true);
await settings.signOut();
test('coppa is empty and too young', async ({
target,
page,
pages: { login },
}) => {
const email = login.createEmail();
await page.goto(target.contentServerUrl);
await login.setEmail(email);
await login.clickSubmit();
await page.waitForURL(/signup/);
await login.setPassword(password);
await login.confirmPassword(password);
await login.clickSubmit();
await login.setEmail(email);
await login.clickSubmit();
await login.setPassword(password);
await login.submit();
expect(await login.isUserLoggedIn()).toBe(true);
// Verify the error
expect(await login.getTooltipError()).toContain(
'You must enter your age to sign up'
);
await login.setAge('12');
await login.clickSubmit();
// Verify navigated to the cannot create account page
await page.waitForURL(/cannot_create_account/);
// TODO: this is flaky
// expect(await login.cannotCreateAccountHeader()).toBe(true);
});
test('sign up with non matching passwords', async ({
target,
page,
pages: { login },
}) => {
const email = login.createEmail();
await page.goto(target.contentServerUrl);
await login.setEmail(email);
await login.clickSubmit();
await login.setPassword(password);
await login.confirmPassword('wrongpassword');
await login.setAge('24');
await login.clickSubmit();
// Verify the error
expect(await login.getTooltipError()).toContain('Passwords do not match');
});
test('form prefill information is cleared after signup->sign out', async ({
target,
page,
pages: { login, settings },
}) => {
const email = login.createEmail();
await page.goto(target.contentServerUrl);
await login.fillOutFirstSignUp(email, password);
// The original tab should transition to the settings page w/ success
// message.
expect(await login.isUserLoggedIn()).toBe(true);
await settings.signOut();
// check the email address was cleared
await login.waitForEmailHeader();
expect(await login.getEmailInput()).toContain('');
await login.setEmail(login.createEmail());
await login.clickSubmit();
// check the password was cleared
expect(await login.getPasswordInput()).toContain('');
});
test('signup via relier page and redirect after confirm', async ({
pages: { login, relier },
}) => {
const email = login.createEmail();
await relier.goto();
await relier.clickEmailFirst();
await login.fillOutFirstSignUp(email, password);
expect(await relier.isLoggedIn()).toBe(true);
});
test('signup, verify and sign out of two accounts, all in the same tab, then sign in to the first account', async ({
target,
page,
pages: { login, settings },
}) => {
const email = login.createEmail();
const secondEmail = login.createEmail();
await page.goto(target.contentServerUrl);
await login.fillOutFirstSignUp(email, password);
// The original tab should transition to the settings page w/ success
// message.
expect(await login.isUserLoggedIn()).toBe(true);
// Verify the account is in local storage and has a correct state
const currentAccountUid = await page.evaluate(() => {
return JSON.parse(
localStorage.getItem('__fxa_storage.currentAccountUid') || ''
);
});
const accounts = await page.evaluate(() => {
return JSON.parse(
localStorage.getItem('__fxa_storage.accounts') || '{}'
);
});
const account = accounts[currentAccountUid];
expect(currentAccountUid).toBeDefined();
expect(accounts).toBeDefined();
expect(accounts[currentAccountUid]).toBeDefined();
expect(account.email).toBe(email);
expect(account.lastLogin).toBeDefined();
expect(account.metricsEnabled).toBe(true);
expect(account.sessionToken).toBeDefined();
expect(account.uid).toBeDefined();
expect(account.verified).toBe(true);
await settings.signOut();
await login.fillOutFirstSignUp(secondEmail, password);
// The original tab should transition to the settings page w/ success
// message.
expect(await login.isUserLoggedIn()).toBe(true);
await settings.signOut();
await login.setEmail(email);
await login.clickSubmit();
await login.setPassword(password);
await login.submit();
expect(await login.isUserLoggedIn()).toBe(true);
});
});
});

Просмотреть файл

@ -7,50 +7,54 @@ import { test, expect } from '../../lib/fixtures/standard';
const PASSWORD = 'passwordzxcv';
let email;
test.describe('Sign up with code', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
email = login.createEmail();
await login.clearCache();
});
test('bounced email', async ({ target, page, pages: { login } }) => {
const client = await login.getFxaClient(target);
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
test.describe('severity-1 #smoke', () => {
test.describe('Sign up with code', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
email = login.createEmail();
await login.clearCache();
});
await login.fillOutFirstSignUp(email, PASSWORD);
await client.accountDestroy(email, PASSWORD);
await login.waitForPasswordHeader();
});
test('bounced email', async ({ target, page, pages: { login } }) => {
const client = await login.getFxaClient(target);
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutFirstSignUp(email, PASSWORD);
test('valid code then click back', async ({
target,
page,
pages: { login },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
await client.accountDestroy(email, PASSWORD);
await login.waitForPasswordHeader();
});
await login.fillOutFirstSignUp(email, PASSWORD, {waitForNavOnSubmit: false});
await page.goBack({waitUntil: 'load'});
expect(await login.isUserLoggedIn()).toBe(true);
});
test('invalid code', async ({
target,
page,
pages: { login, signinTokenCode },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
test('valid code then click back', async ({
target,
page,
pages: { login },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutFirstSignUp(email, PASSWORD, {
waitForNavOnSubmit: false,
});
await page.goBack({ waitUntil: 'load' });
expect(await login.isUserLoggedIn()).toBe(true);
});
test('invalid code', async ({
target,
page,
pages: { login, signinTokenCode },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutFirstSignUp(email, PASSWORD, { verify: false });
await login.setCode('1234');
await signinTokenCode.clickSubmitButton();
expect(await login.getTooltipError()).toContain(
'Invalid or expired confirmation code'
);
});
await login.fillOutFirstSignUp(email, PASSWORD, { verify: false });
await login.setCode('1234');
await signinTokenCode.clickSubmitButton();
expect(await login.getTooltipError()).toContain(
'Invalid or expired confirmation code'
);
});
});

Просмотреть файл

@ -1,27 +1,33 @@
/* 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/. */
import { test, expect, newPagesForSync } from '../../lib/fixtures/standard';
test.describe('connect_another_device', () => {
test('signup Fx Desktop, load /connect_another_device page', async ({
credentials,
target,
}) => {
const { browser, page, login, connectAnotherDevice } =
await newPagesForSync(target);
await target.auth.accountDestroy(credentials.email, credentials.password);
test.describe('severity-2 #smoke', () => {
test.describe('connect_another_device', () => {
test('signup Fx Desktop, load /connect_another_device page', async ({
credentials,
target,
}) => {
const { browser, page, login, connectAnotherDevice } =
await newPagesForSync(target);
await target.auth.accountDestroy(credentials.email, credentials.password);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`,
{ waitUntil: 'load' }
);
await login.fillOutFirstSignUp(credentials.email, credentials.password);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`,
{ waitUntil: 'load' }
);
await login.fillOutFirstSignUp(credentials.email, credentials.password);
// Move on to the connect another device page
await connectAnotherDevice.goto('load');
await expect(connectAnotherDevice.header).toHaveCount(1);
await expect(connectAnotherDevice.signInButton).toHaveCount(0);
await expect(connectAnotherDevice.installFxDesktop).toHaveCount(1);
await expect(connectAnotherDevice.success).toHaveCount(0);
// Move on to the connect another device page
await connectAnotherDevice.goto('load');
await expect(connectAnotherDevice.header).toHaveCount(1);
await expect(connectAnotherDevice.signInButton).toHaveCount(0);
await expect(connectAnotherDevice.installFxDesktop).toHaveCount(1);
await expect(connectAnotherDevice.success).toHaveCount(0);
await browser?.close();
await browser?.close();
});
});
});

Просмотреть файл

@ -4,57 +4,59 @@
import { test, expect } from '../../lib/fixtures/standard';
test.describe('redirect_to', () => {
test.beforeEach(async ({ credentials, pages: { settings, login } }) => {
await settings.goto();
await settings.signOut();
await login.login(credentials.email, credentials.password);
});
test.describe('severity-2 #smoke', () => {
test.describe('redirect_to', () => {
test.beforeEach(async ({ credentials, pages: { settings, login } }) => {
await settings.goto();
await settings.signOut();
await login.login(credentials.email, credentials.password);
});
async function engageRedirect(page, target, redirectTo) {
await page.goto(
`${target.contentServerUrl}/confirm_signup_code?redirect_to=${redirectTo}`
);
await page.click('button[type=submit]');
}
async function engageRedirect(page, target, redirectTo) {
await page.goto(
`${target.contentServerUrl}/confirm_signup_code?redirect_to=${redirectTo}`
);
await page.click('button[type=submit]');
}
test('prevent invalid redirect_to parameter', async ({
target,
pages: { page },
}) => {
const redirectTo = 'https://evil.com/';
await engageRedirect(page, target, redirectTo);
test('prevent invalid redirect_to parameter', async ({
target,
pages: { page },
}) => {
const redirectTo = 'https://evil.com/';
await engageRedirect(page, target, redirectTo);
const error = await page.waitForSelector('.error');
expect(await error.isVisible()).toBeTruthy();
expect(await error.textContent()).toEqual('Invalid redirect!');
expect(page.url).not.toEqual(redirectTo);
});
const error = await page.waitForSelector('.error');
expect(await error.isVisible()).toBeTruthy();
expect(await error.textContent()).toEqual('Invalid redirect!');
expect(page.url).not.toEqual(redirectTo);
});
test('prevent xss in redirect_to parameter', async ({
target,
pages: { page },
}) => {
const redirectTo = 'javascript:alert(1)';
await engageRedirect(page, target, redirectTo);
test('prevent xss in redirect_to parameter', async ({
target,
pages: { page },
}) => {
const redirectTo = 'javascript:alert(1)';
await engageRedirect(page, target, redirectTo);
const error = await page.waitForSelector('.error');
expect(await error.isVisible()).toBeTruthy();
expect(await error.textContent()).toEqual('Invalid redirect!');
});
const error = await page.waitForSelector('.error');
expect(await error.isVisible()).toBeTruthy();
expect(await error.textContent()).toEqual('Invalid redirect!');
});
test('allows valid redirect_to parameter', async ({
target,
pages: { page },
}) => {
const redirectTo = `${target.contentServerUrl}/settings`;
await page.goto(
`${target.contentServerUrl}/confirm_signup_code?redirect_to=${redirectTo}`
);
await page.click('button[type=submit]');
test('allows valid redirect_to parameter', async ({
target,
pages: { page },
}) => {
const redirectTo = `${target.contentServerUrl}/settings`;
await page.goto(
`${target.contentServerUrl}/confirm_signup_code?redirect_to=${redirectTo}`
);
await page.click('button[type=submit]');
await page.waitForURL(/settings\?/);
await page.waitForURL(/settings\?/);
expect(page.url().startsWith(redirectTo)).toBeTruthy();
expect(page.url().startsWith(redirectTo)).toBeTruthy();
});
});
});

Просмотреть файл

@ -1,3 +1,7 @@
/* 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/. */
import { test, expect, newPagesForSync } from '../../lib/fixtures/standard';
test.describe('severity-1 #smoke', () => {
@ -60,7 +64,7 @@ test.describe('severity-1 #smoke', () => {
});
});
test.describe('severity-3 #smoke', () => {
test.describe('severity-2 #smoke', () => {
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293362
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293469
test('can login to addons #1293362 #1293469', async ({

Просмотреть файл

@ -4,127 +4,129 @@
import { test, expect } from '../../lib/fixtures/standard';
test.describe('signin here', () => {
test('signin verified with incorrect password, click `forgot password?`', async ({
target,
page,
credentials,
pages: { login, resetPassword },
}) => {
await page.goto(target.contentServerUrl);
await login.setEmail(credentials.email);
await login.clickSubmit();
await login.setPassword('incorrect password');
await login.clickSubmit();
test.describe('severity-2 #smoke', () => {
test.describe('signin here', () => {
test('signin verified with incorrect password, click `forgot password?`', async ({
target,
page,
credentials,
pages: { login, resetPassword },
}) => {
await page.goto(target.contentServerUrl);
await login.setEmail(credentials.email);
await login.clickSubmit();
await login.setPassword('incorrect password');
await login.clickSubmit();
// Verify the error
expect(await login.getTooltipError()).toContain('Incorrect password');
// Verify the error
expect(await login.getTooltipError()).toContain('Incorrect password');
//Click forgot password link
await login.clickForgotPassword();
//Click forgot password link
await login.clickForgotPassword();
//Verify reset password header
await resetPassword.resetPasswordHeader();
});
//Verify reset password header
await resetPassword.resetPasswordHeader();
});
test('signin with email with leading/trailing whitespace on the email', async ({
target,
page,
credentials,
pages: { login },
}) => {
const emailWithleadingSpace = ' ' + credentials.email;
await page.goto(target.contentServerUrl);
await login.fillOutEmailFirstSignIn(
emailWithleadingSpace,
credentials.password
);
test('signin with email with leading/trailing whitespace on the email', async ({
target,
page,
credentials,
pages: { login },
}) => {
const emailWithleadingSpace = ' ' + credentials.email;
await page.goto(target.contentServerUrl);
await login.fillOutEmailFirstSignIn(
emailWithleadingSpace,
credentials.password
);
// Verify the header after login
expect(await login.isUserLoggedIn()).toBe(true);
// Verify the header after login
expect(await login.isUserLoggedIn()).toBe(true);
// Need to clear the cache to get the new email
await login.clearCache();
// Need to clear the cache to get the new email
await login.clearCache();
await page.goto(target.contentServerUrl);
const emailWithTrailingSpace = credentials.email + ' ';
await login.fillOutEmailFirstSignIn(
emailWithTrailingSpace,
credentials.password
);
await page.goto(target.contentServerUrl);
const emailWithTrailingSpace = credentials.email + ' ';
await login.fillOutEmailFirstSignIn(
emailWithTrailingSpace,
credentials.password
);
// Verify the header after login
expect(await login.isUserLoggedIn()).toBe(true);
});
// Verify the header after login
expect(await login.isUserLoggedIn()).toBe(true);
});
test('signin verified with password that incorrectly has leading whitespace', async ({
target,
page,
credentials,
pages: { login },
}) => {
await page.goto(target.contentServerUrl);
await login.setEmail(credentials.email);
await login.clickSubmit();
await login.setPassword(' ' + credentials.password);
await login.clickSubmit();
test('signin verified with password that incorrectly has leading whitespace', async ({
target,
page,
credentials,
pages: { login },
}) => {
await page.goto(target.contentServerUrl);
await login.setEmail(credentials.email);
await login.clickSubmit();
await login.setPassword(' ' + credentials.password);
await login.clickSubmit();
// Verify the error
expect(await login.getTooltipError()).toContain('Incorrect password');
});
// Verify the error
expect(await login.getTooltipError()).toContain('Incorrect password');
});
test('login as an existing user', async ({
target,
page,
credentials,
pages: { login, settings },
}) => {
await page.goto(target.contentServerUrl);
await login.fillOutEmailFirstSignIn(
credentials.email,
credentials.password
);
test('login as an existing user', async ({
target,
page,
credentials,
pages: { login, settings },
}) => {
await page.goto(target.contentServerUrl);
await login.fillOutEmailFirstSignIn(
credentials.email,
credentials.password
);
// Verify the header after login
expect(await login.isUserLoggedIn()).toBe(true);
// Verify the header after login
expect(await login.isUserLoggedIn()).toBe(true);
// Sign out
await settings.signOut();
// Sign out
await settings.signOut();
// Login as existing user
await login.setEmail(credentials.email);
await login.clickSubmit();
await login.setPassword(credentials.password);
await login.clickSubmit();
// Login as existing user
await login.setEmail(credentials.email);
await login.clickSubmit();
await login.setPassword(credentials.password);
await login.clickSubmit();
// Verify the header after login
expect(await login.isUserLoggedIn()).toBe(true);
});
// Verify the header after login
expect(await login.isUserLoggedIn()).toBe(true);
});
test('with bounced email', async ({
target,
page,
pages: { login, settings },
}) => {
const email = login.createEmail('sync{id}');
const password = 'password123';
await target.createAccount(email, password);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email&`
);
await login.fillOutEmailFirstSignIn(email, password);
test('with bounced email', async ({
target,
page,
pages: { login, settings },
}) => {
const email = login.createEmail('sync{id}');
const password = 'password123';
await target.createAccount(email, password);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email&`
);
await login.fillOutEmailFirstSignIn(email, password);
// Verify the header after login
await login.waitForSignInCodeHeader();
await target.auth.accountDestroy(email, password);
await page.waitForURL(/signin_bounced/);
// Verify the header after login
await login.waitForSignInCodeHeader();
await target.auth.accountDestroy(email, password);
await page.waitForURL(/signin_bounced/);
//Verify sign in bounced header
expect(await login.isSigninBouncedHeader()).toBe(true);
await login.clickBouncedCreateAccount();
//Verify sign in bounced header
expect(await login.isSigninBouncedHeader()).toBe(true);
await login.clickBouncedCreateAccount();
//Verify user redirected to login page
await login.waitForEmailHeader();
expect(await login.getEmailInput()).toContain('');
//Verify user redirected to login page
await login.waitForEmailHeader();
expect(await login.getEmailInput()).toContain('');
});
});
});

Просмотреть файл

@ -9,161 +9,171 @@ let email;
let newEmail;
let unverifiedEmail;
test.describe('signin blocked', () => {
test.beforeEach(async ({ target, pages: { login } }) => {
test.slow(); //This test has steps for email rendering that runs slow on stage
blockedEmail = login.createEmail('blocked{id}');
await target.auth.signUp(blockedEmail, password, {
lang: 'en',
preVerified: 'true',
test.describe('severity-2 #smoke', () => {
test.describe('signin blocked', () => {
test.beforeEach(async ({ target, pages: { login } }) => {
test.slow(); //This test has steps for email rendering that runs slow on stage
blockedEmail = login.createEmail('blocked{id}');
await target.auth.signUp(blockedEmail, password, {
lang: 'en',
preVerified: 'true',
});
email = await login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
newEmail = login.createEmail('blocked{id}');
unverifiedEmail = login.createEmail('blocked{id}');
await target.auth.signUp(unverifiedEmail, password, {
lang: 'en',
preVerified: 'false',
});
await login.clearCache();
});
email = await login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
newEmail = login.createEmail('blocked{id}');
unverifiedEmail = login.createEmail('blocked{id}');
await target.auth.signUp(unverifiedEmail, password, {
lang: 'en',
preVerified: 'false',
});
await login.clearCache();
});
test.afterEach(async ({ target }) => {
test.slow(); //The cleanup was timing out and exceeding 3000ms
const emails = [blockedEmail, email, newEmail, unverifiedEmail];
for (const email of emails) {
if (email) {
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle any errors if needed
test.afterEach(async ({ target }) => {
test.slow(); //The cleanup was timing out and exceeding 3000ms
const emails = [blockedEmail, email, newEmail, unverifiedEmail];
for (const email of emails) {
if (email) {
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle any errors if needed
}
}
}
}
});
test('valid code entered', async ({ target, page, pages: { login } }) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(blockedEmail, password);
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(blockedEmail);
test('valid code entered', async ({ target, page, pages: { login } }) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(blockedEmail, password);
//Unblock the email
await login.unblock(blockedEmail);
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(blockedEmail);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Unblock the email
await login.unblock(blockedEmail);
test('incorrect code entered', async ({ target, page, pages: { login } }) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
await login.fillOutEmailFirstSignIn(blockedEmail, password);
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(blockedEmail);
await login.enterUnblockCode('incorrect');
test('incorrect code entered', async ({
target,
page,
pages: { login },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(blockedEmail, password);
//Verify tooltip error
expect(await login.getTooltipError()).toContain(
'Invalid authorization code'
);
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(blockedEmail);
await login.enterUnblockCode('incorrect');
//Unblock the email
await login.unblock(blockedEmail);
//Verify tooltip error
expect(await login.getTooltipError()).toContain(
'Invalid authorization code'
);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Unblock the email
await login.unblock(blockedEmail);
test('resend', async ({ target, page, pages: { login, resetPassword } }) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
await login.fillOutEmailFirstSignIn(blockedEmail, password);
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(blockedEmail);
test('resend', async ({
target,
page,
pages: { login, resetPassword },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(blockedEmail, password);
//Click resend link
await resetPassword.clickResend();
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(blockedEmail);
//Verify success message
expect(await resetPassword.resendSuccessMessage()).toContain(
'Email resent. Add accounts@firefox.com to your contacts to ensure a smooth delivery.'
);
//Click resend link
await resetPassword.clickResend();
//Unblock the email
await login.unblock(blockedEmail);
//Verify success message
expect(await resetPassword.resendSuccessMessage()).toContain(
'Email resent. Add accounts@firefox.com to your contacts to ensure a smooth delivery.'
);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Unblock the email
await login.unblock(blockedEmail);
test('with primary email changed', async ({
target,
page,
pages: { login, settings, secondaryEmail },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
test('with primary email changed', async ({
target,
page,
pages: { login, settings, secondaryEmail },
}) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
await settings.goto();
await settings.secondaryEmail.clickAdd();
await secondaryEmail.addAndVerify(newEmail);
await settings.secondaryEmail.clickMakePrimary();
await settings.signOut();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
await settings.goto();
await settings.secondaryEmail.clickAdd();
await secondaryEmail.addAndVerify(newEmail);
await settings.secondaryEmail.clickMakePrimary();
await settings.signOut();
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(newEmail, password);
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(newEmail);
//Unblock the email
await login.unblock(newEmail);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
await login.fillOutEmailFirstSignIn(newEmail, password);
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(newEmail);
test('unverified', async ({ target, page, pages: { login } }) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(unverifiedEmail, password);
//Unblock the email
await login.unblock(newEmail);
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(unverifiedEmail);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Unblock the email
await login.unblock(unverifiedEmail);
test('unverified', async ({ target, page, pages: { login } }) => {
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
//Verify confirm code header
await login.waitForSignUpCodeHeader();
await login.fillOutSignInCode(unverifiedEmail);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
await login.fillOutEmailFirstSignIn(unverifiedEmail, password);
//Verify sign in block header
await login.waitForSigninUnblockHeader();
expect(await login.getUnblockEmail()).toContain(unverifiedEmail);
//Unblock the email
await login.unblock(unverifiedEmail);
//Verify confirm code header
await login.waitForSignUpCodeHeader();
await login.fillOutSignInCode(unverifiedEmail);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
});

Просмотреть файл

@ -8,205 +8,207 @@ let email;
let email2;
let syncBrowserPages;
test.describe('signin cached', () => {
test.beforeEach(async ({ target }) => {
test.slow(); //This test has steps for email rendering that runs slow on stage
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('sync{id}');
email2 = login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
test.describe('severity-2 #smoke', () => {
test.describe('signin cached', () => {
test.beforeEach(async ({ target }) => {
test.slow(); //This test has steps for email rendering that runs slow on stage
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('sync{id}');
email2 = login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await target.auth.signUp(email2, password, {
lang: 'en',
preVerified: 'true',
});
});
await target.auth.signUp(email2, password, {
lang: 'en',
preVerified: 'true',
});
});
test.afterEach(async ({ target }) => {
test.slow(); //The cleanup was timing out and exceeding 3000ms
await syncBrowserPages.browser?.close();
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
test.afterEach(async ({ target }) => {
test.slow(); //The cleanup was timing out and exceeding 3000ms
await syncBrowserPages.browser?.close();
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
}
});
test('sign in twice, on second attempt email will be cached', async ({
target,
}) => {
const { page, login } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await login.clearSessionStorage();
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
expect(await login.getPrefilledEmail()).toContain(email);
await login.clickSignIn();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
test('sign in with incorrect email case before normalization fix, on second attempt canonical form is used', async ({
target,
}) => {
const { page, login, settings } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await login.clearSessionStorage();
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.denormalizeStoredEmail(email);
await page.reload();
expect(await login.getPrefilledEmail()).toContain(email);
await login.clickSignIn();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Verify email is normalized
const primary = await settings.primaryEmail.statusText();
expect(primary).toEqual(email);
});
test('sign in once, use a different account', async ({ target }) => {
const { page, login } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email);
await login.useDifferentAccountLink();
await login.fillOutEmailFirstSignIn(email2, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
// testing to make sure cached signin comes back after a refresh
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email2);
});
test('expired cached credentials', async ({ target }) => {
const { page, login } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await login.destroySession(email);
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email);
await login.setPassword(password);
await login.clickSubmit();
test('sign in twice, on second attempt email will be cached', async ({
target,
}) => {
const { page, login } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
test('cached credentials that expire while on page', async ({ target }) => {
const { page, login } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
await login.clearSessionStorage();
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
expect(await login.getPrefilledEmail()).toContain(email);
await login.clickSignIn();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email);
test('sign in with incorrect email case before normalization fix, on second attempt canonical form is used', async ({
target,
}) => {
const { page, login, settings } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
await login.destroySession(email);
await login.clickSignIn();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Session expired error should show.
expect(await login.signInError()).toContain(
'Session expired. Sign in to continue.'
);
await login.setPassword(password);
await login.clickSubmit();
await login.clearSessionStorage();
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.denormalizeStoredEmail(email);
await page.reload();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
expect(await login.getPrefilledEmail()).toContain(email);
await login.clickSignIn();
test('unverified cached signin redirects to confirm email', async ({
target,
}) => {
const { page, login } = syncBrowserPages;
const email_unverified = login.createEmail();
await target.auth.signUp(email_unverified, password, {
lang: 'en',
preVerified: 'false',
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Verify email is normalized
const primary = await settings.primaryEmail.statusText();
expect(primary).toEqual(email);
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
test('sign in once, use a different account', async ({ target }) => {
const { page, login } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email);
await login.useDifferentAccountLink();
await login.fillOutEmailFirstSignIn(email2, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
// testing to make sure cached signin comes back after a refresh
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email2);
});
await login.fillOutEmailFirstSignIn(email_unverified, password);
//Verify sign up code header is visible
await login.waitForSignUpCodeHeader();
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
test('expired cached credentials', async ({ target }) => {
const { page, login } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await login.destroySession(email);
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email);
await login.setPassword(password);
await login.clickSubmit();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email_unverified);
await login.clickSignIn();
//Cached login should still go to email confirmation screen for unverified accounts
await login.waitForSignUpCodeHeader();
test('cached credentials that expire while on page', async ({ target }) => {
const { page, login } = syncBrowserPages;
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email, password);
//Fill the code and submit
await login.fillOutSignUpCode(email_unverified);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email);
await login.destroySession(email);
await login.clickSignIn();
//Session expired error should show.
expect(await login.signInError()).toContain(
'Session expired. Sign in to continue.'
);
await login.setPassword(password);
await login.clickSubmit();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
test('unverified cached signin redirects to confirm email', async ({
target,
}) => {
const { page, login } = syncBrowserPages;
const email_unverified = login.createEmail();
await target.auth.signUp(email_unverified, password, {
lang: 'en',
preVerified: 'false',
});
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
await login.fillOutEmailFirstSignIn(email_unverified, password);
//Verify sign up code header is visible
await login.waitForSignUpCodeHeader();
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email_unverified);
await login.clickSignIn();
//Cached login should still go to email confirmation screen for unverified accounts
await login.waitForSignUpCodeHeader();
//Fill the code and submit
await login.fillOutSignUpCode(email_unverified);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
});
});
});

Просмотреть файл

@ -1,227 +1,233 @@
/* 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/. */
import { test, expect } from '../../../lib/fixtures/standard';
test.describe.configure({ mode: 'parallel' });
test.describe('coupon test', () => {
test.beforeEach(() => {
test.slow();
});
test.describe('severity-2 #smoke', () => {
test.describe('coupon test', () => {
test.beforeEach(() => {
test.slow();
});
test('apply an expired coupon', async ({ pages: { relier, subscribe } }, {
project,
}) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
test('apply an expired coupon', async ({ pages: { relier, subscribe } }, {
project,
}) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'autoexpired' coupon is an expired coupon for a 6mo plan
await subscribe.addCouponCode('autoexpired');
// 'autoexpired' coupon is an expired coupon for a 6mo plan
await subscribe.addCouponCode('autoexpired');
// Verifying the correct error message
expect(await subscribe.couponErrorMessageText()).toContain(
'The code you entered has expired'
);
});
// Verifying the correct error message
expect(await subscribe.couponErrorMessageText()).toContain(
'The code you entered has expired'
);
});
test('apply an invalid coupon', async ({ pages: { relier, subscribe } }, {
project,
}) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
test('apply an invalid coupon', async ({ pages: { relier, subscribe } }, {
project,
}) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'autoinvalid' coupon is an invalid coupon for a 6mo plan
// But valid for a 12mo plan
await subscribe.addCouponCode('autoinvalid');
// 'autoinvalid' coupon is an invalid coupon for a 6mo plan
// But valid for a 12mo plan
await subscribe.addCouponCode('autoinvalid');
// Asserting that the code is invalid for a 6mo plan
expect(await subscribe.couponErrorMessageText()).toContain(
'The code you entered is invalid'
);
// Asserting that the code is invalid for a 6mo plan
expect(await subscribe.couponErrorMessageText()).toContain(
'The code you entered is invalid'
);
// Adding the same code to a 12mo plan
await relier.goto();
await relier.clickSubscribe12Month();
// Adding the same code to a 12mo plan
await relier.goto();
await relier.clickSubscribe12Month();
// 'autoinvalid' coupon is an invalid coupon for a 6mo plan
// But valid for a 12mo plan
await subscribe.addCouponCode('autoinvalid');
// 'autoinvalid' coupon is an invalid coupon for a 6mo plan
// But valid for a 12mo plan
await subscribe.addCouponCode('autoinvalid');
// Verifying the coupon is valid with a discount line item
expect(await subscribe.discountAppliedSuccess()).toBe(true);
});
// Verifying the coupon is valid with a discount line item
expect(await subscribe.discountAppliedSuccess()).toBe(true);
});
test('subscribe successfully with an invalid coupon', async ({
pages: { relier, subscribe, login },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
test('subscribe successfully with an invalid coupon', async ({
pages: { relier, subscribe, login },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'autoinvalid' coupon is an invalid coupon for a 6mo plan
await subscribe.addCouponCode('autoinvalid');
// 'autoinvalid' coupon is an invalid coupon for a 6mo plan
await subscribe.addCouponCode('autoinvalid');
// Asserting that the code is invalid for a 6m plan
expect(await subscribe.couponErrorMessageText()).toContain(
'The code you entered is invalid'
);
// Asserting that the code is invalid for a 6m plan
expect(await subscribe.couponErrorMessageText()).toContain(
'The code you entered is invalid'
);
// Successfully subscribe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
// Successfully subscribe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
test('subscribe successfully with a forever discount coupon', async ({
pages: { relier, subscribe, login },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
test('subscribe successfully with a forever discount coupon', async ({
pages: { relier, subscribe, login },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
// Verify the line items after applying discount
expect(await subscribe.discountListPrice()).toBe(true);
expect(await subscribe.discountLineItem()).toBe(true);
// Verify the line items after applying discount
expect(await subscribe.discountListPrice()).toBe(true);
expect(await subscribe.discountLineItem()).toBe(true);
// Successfully subscribe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
// Successfully subscribe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
test('subscribe with a one time discount coupon', async ({
pages: { relier, subscribe, login },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe12Month();
test('subscribe with a one time discount coupon', async ({
pages: { relier, subscribe, login },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe12Month();
// 'auto50ponetime' is a one time 50% discount coupon for a 12mo plan
await subscribe.addCouponCode('auto50ponetime');
// 'auto50ponetime' is a one time 50% discount coupon for a 12mo plan
await subscribe.addCouponCode('auto50ponetime');
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
expect(await subscribe.oneTimeDiscountSuccess()).toBe(true);
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
expect(await subscribe.oneTimeDiscountSuccess()).toBe(true);
// Verify the line items is visible after applying discount
expect(await subscribe.discountListPrice()).toBe(true);
expect(await subscribe.discountLineItem()).toBe(true);
// Verify the line items is visible after applying discount
expect(await subscribe.discountListPrice()).toBe(true);
expect(await subscribe.discountLineItem()).toBe(true);
// Successfully subscribe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
// Successfully subscribe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
test('subscribe with credit card and use coupon', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
test('subscribe with credit card and use coupon', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
test('subscribe with paypal and use coupon', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe12Month();
test('subscribe with paypal and use coupon', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe12Month();
// 'auto50ponetime' is a one time 50% discount coupon for a 12mo plan
await subscribe.addCouponCode('auto50ponetime');
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setPayPalInfo();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
// 'auto50ponetime' is a one time 50% discount coupon for a 12mo plan
await subscribe.addCouponCode('auto50ponetime');
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setPayPalInfo();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
test('remove a coupon and verify', async ({
pages: { relier, subscribe, login },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
test('remove a coupon and verify', async ({
pages: { relier, subscribe, login },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await relier.goto();
await relier.clickSubscribe12Month();
await relier.goto();
await relier.clickSubscribe12Month();
// 'auto50ponetime' is a one time 50% discount coupon for a 12mo plan
await subscribe.addCouponCode('auto50ponetime');
// 'auto50ponetime' is a one time 50% discount coupon for a 12mo plan
await subscribe.addCouponCode('auto50ponetime');
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
expect(await subscribe.oneTimeDiscountSuccess()).toBe(true);
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
expect(await subscribe.oneTimeDiscountSuccess()).toBe(true);
// Verify the line items is visible after applying discount
expect(await subscribe.discountListPrice()).toBe(true);
expect(await subscribe.discountLineItem()).toBe(true);
// Verify the line items is visible after applying discount
expect(await subscribe.discountListPrice()).toBe(true);
expect(await subscribe.discountLineItem()).toBe(true);
// Remove the coupon
await subscribe.removeCouponCode();
// Remove the coupon
await subscribe.removeCouponCode();
// Verify the discount is removed
expect(await subscribe.discountLineItem()).toBe(false);
// Verify the discount is removed
expect(await subscribe.discountLineItem()).toBe(false);
});
});
});

Просмотреть файл

@ -1,193 +1,199 @@
/* 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/. */
import { test, expect } from '../../../lib/fixtures/standard';
test.describe.configure({ mode: 'parallel' });
test.describe('resubscription test', () => {
test.beforeEach(() => {
test.slow();
test.describe('severity-2 #smoke', () => {
test.describe('resubscription test', () => {
test.beforeEach(() => {
test.slow();
});
test('resubscribe successfully with the same coupon after canceling for stripe', async ({
page,
pages: { relier, subscribe, login, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
const total = await subscribe.getTotalPrice();
//Subscribe successfully with Stripe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
//Verify no coupon details are visible
expect(await subscriptionManagement.subscriptionDetails()).not.toContain(
'Promo'
);
//Cancel subscription and then resubscribe
await subscriptionManagement.cancelSubscription();
await subscriptionManagement.resubscribe();
//Verify that the resubscription has the same coupon applied
expect(await subscriptionManagement.getResubscriptionPrice()).toEqual(
total
);
//Verify no coupon details are visible
expect(await subscriptionManagement.subscriptionDetails()).not.toContain(
'Promo'
);
});
test('resubscribe successfully with the same coupon after canceling for paypal', async ({
page,
pages: { relier, subscribe, login, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
const total = await subscribe.getTotalPrice();
//Subscribe successfully using Paypal
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setPayPalInfo();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
//Verify no coupon details are visible
expect(await subscriptionManagement.subscriptionDetails()).not.toContain(
'Promo'
);
//Cancel subscription and then resubscribe
await subscriptionManagement.cancelSubscription();
await subscriptionManagement.resubscribe();
//Verify that the resubscription has the same coupon applied
expect(await subscriptionManagement.getResubscriptionPrice()).toEqual(
total
);
//Verify no coupon details are visible
expect(await subscriptionManagement.subscriptionDetails()).not.toContain(
'Promo'
);
});
test('update mode of payment for stripe', async ({
page,
pages: { relier, subscribe, login, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
//Subscribe successfully
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
//Change stripe card information
await subscriptionManagement.changeStripeCardDetails();
//Verify that the card info is updated
expect(await subscriptionManagement.getCardInfo()).toContain('4444');
});
//Disable as paypal sandbox is taking a long time to load
/*test('update mode of payment for paypal', async ({
page,
pages: { relier, subscribe, login, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name !== 'local',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
//Subscribe successfully
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setPayPalInfo();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
//Change Paypal information
const paypalPage = await subscriptionManagement.clickPaypalChange();
subscriptionManagement.page = paypalPage;
//Login to Paypal sandbox
await subscriptionManagement.loginPaypal();
//Verify the account as 'CREDIT UNION'
expect(await subscriptionManagement.checkPaypalAccount()).toContain(
'CREDIT UNION'
);
//Change account from 'Credit Union' to 'Visa'
await subscriptionManagement.updatePaypalAccount();
//Added this timeout wait for page to be loaded correctly
await page.waitForTimeout(2000);
//Verify that the payment info is updated
expect(await subscriptionManagement.checkPaypalAccount()).toContain('Visa');
});*/
});
test('resubscribe successfully with the same coupon after canceling for stripe', async ({
page,
pages: { relier, subscribe, login, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
const total = await subscribe.getTotalPrice();
//Subscribe successfully with Stripe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
//Verify no coupon details are visible
expect(await subscriptionManagement.subscriptionDetails()).not.toContain(
'Promo'
);
//Cancel subscription and then resubscribe
await subscriptionManagement.cancelSubscription();
await subscriptionManagement.resubscribe();
//Verify that the resubscription has the same coupon applied
expect(await subscriptionManagement.getResubscriptionPrice()).toEqual(
total
);
//Verify no coupon details are visible
expect(await subscriptionManagement.subscriptionDetails()).not.toContain(
'Promo'
);
});
test('resubscribe successfully with the same coupon after canceling for paypal', async ({
page,
pages: { relier, subscribe, login, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
const total = await subscribe.getTotalPrice();
//Subscribe successfully using Paypal
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setPayPalInfo();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
//Verify no coupon details are visible
expect(await subscriptionManagement.subscriptionDetails()).not.toContain(
'Promo'
);
//Cancel subscription and then resubscribe
await subscriptionManagement.cancelSubscription();
await subscriptionManagement.resubscribe();
//Verify that the resubscription has the same coupon applied
expect(await subscriptionManagement.getResubscriptionPrice()).toEqual(
total
);
//Verify no coupon details are visible
expect(await subscriptionManagement.subscriptionDetails()).not.toContain(
'Promo'
);
});
test('update mode of payment for stripe', async ({
page,
pages: { relier, subscribe, login, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
//Subscribe successfully
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
//Change stripe card information
await subscriptionManagement.changeStripeCardDetails();
//Verify that the card info is updated
expect(await subscriptionManagement.getCardInfo()).toContain('4444');
});
//Disable as paypal sandbox is taking a long time to load
/*test('update mode of payment for paypal', async ({
page,
pages: { relier, subscribe, login, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name !== 'local',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
//Subscribe successfully
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setPayPalInfo();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
//Change Paypal information
const paypalPage = await subscriptionManagement.clickPaypalChange();
subscriptionManagement.page = paypalPage;
//Login to Paypal sandbox
await subscriptionManagement.loginPaypal();
//Verify the account as 'CREDIT UNION'
expect(await subscriptionManagement.checkPaypalAccount()).toContain(
'CREDIT UNION'
);
//Change account from 'Credit Union' to 'Visa'
await subscriptionManagement.updatePaypalAccount();
//Added this timeout wait for page to be loaded correctly
await page.waitForTimeout(2000);
//Verify that the payment info is updated
expect(await subscriptionManagement.checkPaypalAccount()).toContain('Visa');
});*/
});

Просмотреть файл

@ -1,71 +1,77 @@
/* 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/. */
import { expect, test } from '../../../lib/fixtures/standard';
import { MetricsObserver } from '../../../lib/metrics';
test.describe('ui functionality', () => {
let metricsObserver: MetricsObserver;
test.describe('severity-2 #smoke', () => {
test.describe('ui functionality', () => {
let metricsObserver: MetricsObserver;
test.beforeEach(({ pages: { subscribe } }) => {
test.slow();
metricsObserver = new MetricsObserver(subscribe);
metricsObserver.startTracking();
});
test('verify plan change funnel metrics & coupon feature not available when changing plans', async ({
page,
pages: { relier, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// Verify discount section is displayed
expect(await subscribe.discountTextbox()).toBe(true);
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
//Subscribe successfully with Stripe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
//Change the plan
await relier.clickSubscribe12Month();
//Verify Discount section is not displayed
expect(await subscribe.planUpgradeDetails()).not.toContain('Promo');
//Submit the changes
await subscribe.clickConfirmPlanChange();
await subscribe.clickPayNow();
await subscribe.submit();
//Verify the subscription is successful
expect(await subscribe.isSubscriptionSuccess()).toBe(true);
// check conversion funnel metrics
const expectedEventTypes = [
'amplitude.subPaySetup.view',
'amplitude.subPaySetup.engage',
'amplitude.subPaySetup.submit',
'amplitude.subPaySetup.success',
'amplitude.subPaySubChange.view',
'amplitude.subPaySubChange.engage',
'amplitude.subPaySubChange.submit',
'amplitude.subPaySubChange.success',
];
const actualEventTypes = metricsObserver.rawEvents.map((event) => {
return event.type;
test.beforeEach(({ pages: { subscribe } }) => {
test.slow();
metricsObserver = new MetricsObserver(subscribe);
metricsObserver.startTracking();
});
test('verify plan change funnel metrics & coupon feature not available when changing plans', async ({
page,
pages: { relier, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe6Month();
// Verify discount section is displayed
expect(await subscribe.discountTextbox()).toBe(true);
// 'auto10pforever' is a 10% forever discount coupon for a 6mo plan
await subscribe.addCouponCode('auto10pforever');
// Verify the coupon is applied successfully
expect(await subscribe.discountAppliedSuccess()).toBe(true);
//Subscribe successfully with Stripe
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
//Change the plan
await relier.clickSubscribe12Month();
//Verify Discount section is not displayed
expect(await subscribe.planUpgradeDetails()).not.toContain('Promo');
//Submit the changes
await subscribe.clickConfirmPlanChange();
await subscribe.clickPayNow();
await subscribe.submit();
//Verify the subscription is successful
expect(await subscribe.isSubscriptionSuccess()).toBe(true);
// check conversion funnel metrics
const expectedEventTypes = [
'amplitude.subPaySetup.view',
'amplitude.subPaySetup.engage',
'amplitude.subPaySetup.submit',
'amplitude.subPaySetup.success',
'amplitude.subPaySubChange.view',
'amplitude.subPaySubChange.engage',
'amplitude.subPaySubChange.submit',
'amplitude.subPaySubChange.success',
];
const actualEventTypes = metricsObserver.rawEvents.map((event) => {
return event.type;
});
expect(actualEventTypes).toMatchObject(expectedEventTypes);
});
expect(actualEventTypes).toMatchObject(expectedEventTypes);
});
});

Просмотреть файл

@ -1,205 +1,51 @@
/* 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/. */
import { expect, test } from '../../lib/fixtures/standard';
import { MetricsObserver } from '../../lib/metrics';
test.describe.configure({ mode: 'parallel' });
test.describe('subscription test with cc and paypal', () => {
let metricsObserver: MetricsObserver;
test.describe('severity-2 #smoke', () => {
test.describe('subscription test with cc and paypal', () => {
let metricsObserver: MetricsObserver;
test.beforeEach(({ pages: { subscribe } }) => {
test.slow();
metricsObserver = new MetricsObserver(subscribe);
metricsObserver.startTracking();
});
test('subscribe with credit card and login to product', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
test('subscribe with credit card after initial failed subscription & verify existing user checkout funnel metrics', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setFailedCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.clickTryAgain();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
// check conversion funnel metrics
const expectedEventTypes = [
'amplitude.subPaySetup.view',
'amplitude.subPaySetup.engage',
'amplitude.subPaySetup.submit',
'amplitude.subPaySetup.fail',
'amplitude.subPaySetup.submit',
'amplitude.subPaySetup.success',
];
const actualEventTypes = metricsObserver.rawEvents.map((event) => {
return event.type;
test.beforeEach(({ pages: { subscribe } }) => {
test.slow();
metricsObserver = new MetricsObserver(subscribe);
metricsObserver.startTracking();
});
expect(actualEventTypes).toMatchObject(expectedEventTypes);
});
test('subscribe with paypal and login to product', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setPayPalInfo();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
});
test.describe('Flow, acquisition and new user checkout funnel metrics', () => {
let metricsObserver: MetricsObserver;
test.beforeEach(({ pages: { subscribe } }) => {
test.slow();
metricsObserver = new MetricsObserver(subscribe);
metricsObserver.startTracking();
});
test.describe('severity-2', () => {
test('Metrics disabled: existing user checkout URL to not have flow params', async ({
pages: { settings, relier, page },
test('subscribe with credit card and login to product', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
'no real payment method available in prod'
);
// Go to settings page and verify the Data Collection toggle switch is visible
await settings.goto();
expect(await settings.dataCollection.isToggleSwitch()).toBe(true);
// Toggle swtich, verify the alert bar appears and its status
await settings.dataCollection.toggleShareData('off');
expect(await settings.alertBarText()).toContain('Opt out successful.');
expect(await settings.dataCollection.getToggleStatus()).toBe('false');
// Subscribe to plan and verify URL does not include flow parameter
await relier.goto();
await relier.clickSubscribe6Month();
expect(page.url()).not.toContain('&flow_begin_time=');
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
});
test.describe('severity-3', () => {
test('Existing user checkout URL to have flow params', async ({
pages: { settings, relier, page },
test('subscribe with credit card after initial failed subscription & verify existing user checkout funnel metrics', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
'no real payment method available in prod'
);
// Go to settings page and verify the Data Collection toggle switch is visible
await settings.goto();
expect(await settings.dataCollection.isToggleSwitch()).toBe(true);
// Toggle swtich and verify its status
await settings.dataCollection.toggleShareData('on');
expect(await settings.dataCollection.getToggleStatus()).toBe('true');
// Subscribe to plan and verify URL does not include flow parameter
await relier.goto();
await relier.clickSubscribe6Month();
expect(page.url()).toContain('&flow_begin_time=');
});
test('New user checkout URL to have flow params', async ({
pages: { settings, relier, page },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await settings.goto();
await settings.signOut();
await relier.goto();
await relier.clickSubscribe6Month();
expect(page.url()).toContain('&flow_begin_time=');
});
test('New user checkout URL to have flow params with cache cleared', async ({
pages: { settings, login, relier, page },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await settings.goto();
await settings.signOut();
await login.clearCache();
await relier.goto();
await relier.clickSubscribe6Month();
expect(page.url()).toContain('&flow_begin_time=');
});
test('New user checkout URL to have RP-provided flow params, acquisition params & verify funnel metrics', async ({
pages: { settings, relier, page, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await settings.goto();
await settings.signOut();
await relier.goto();
const subscribeUrl = await relier.getUrl();
if (!subscribeUrl) {
fail('Subscribe button has no href.');
}
const rpSearchParamsBefore = relier.getRpSearchParams(subscribeUrl);
const rpFlowParamsBefore = relier.getRpFlowParams(rpSearchParamsBefore);
const acquisitionParamsBefore =
relier.getRpAcquisitionParams(rpSearchParamsBefore);
// check flow metrics
await relier.clickSubscribeRPFlowMetrics();
const rpSearchParamsAfter = relier.getRpSearchParams(page.url());
const rpFlowParamsAfter = relier.getRpFlowParams(rpSearchParamsAfter);
expect(rpFlowParamsAfter).toStrictEqual(rpFlowParamsBefore);
// subscribe, failing first then succeeding
await subscribe.setEmailAndConfirmNewUser();
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setFailedCreditCardInfo();
@ -208,11 +54,10 @@ test.describe('Flow, acquisition and new user checkout funnel metrics', () => {
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
// check acquisition metrics
const acquisitionParamsAfter =
metricsObserver.getAcquisitionParamsFromEvents();
expect(acquisitionParamsAfter).toStrictEqual(acquisitionParamsBefore);
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
// check conversion funnel metrics
const expectedEventTypes = [
@ -228,5 +73,166 @@ test.describe('Flow, acquisition and new user checkout funnel metrics', () => {
});
expect(actualEventTypes).toMatchObject(expectedEventTypes);
});
test('subscribe with paypal and login to product', async ({
pages: { relier, login, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setPayPalInfo();
await subscribe.submit();
await relier.goto();
await relier.clickEmailFirst();
await login.submit();
expect(await relier.isPro()).toBe(true);
});
});
test.describe('Flow, acquisition and new user checkout funnel metrics', () => {
let metricsObserver: MetricsObserver;
test.beforeEach(({ pages: { subscribe } }) => {
test.slow();
metricsObserver = new MetricsObserver(subscribe);
metricsObserver.startTracking();
});
test.describe('severity-2', () => {
test('Metrics disabled: existing user checkout URL to not have flow params', async ({
pages: { settings, relier, page },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
// Go to settings page and verify the Data Collection toggle switch is visible
await settings.goto();
expect(await settings.dataCollection.isToggleSwitch()).toBe(true);
// Toggle swtich, verify the alert bar appears and its status
await settings.dataCollection.toggleShareData('off');
expect(await settings.alertBarText()).toContain('Opt out successful.');
expect(await settings.dataCollection.getToggleStatus()).toBe('false');
// Subscribe to plan and verify URL does not include flow parameter
await relier.goto();
await relier.clickSubscribe6Month();
expect(page.url()).not.toContain('&flow_begin_time=');
});
});
test.describe('severity-2', () => {
test('Existing user checkout URL to have flow params', async ({
pages: { settings, relier, page },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
// Go to settings page and verify the Data Collection toggle switch is visible
await settings.goto();
expect(await settings.dataCollection.isToggleSwitch()).toBe(true);
// Toggle swtich and verify its status
await settings.dataCollection.toggleShareData('on');
expect(await settings.dataCollection.getToggleStatus()).toBe('true');
// Subscribe to plan and verify URL does not include flow parameter
await relier.goto();
await relier.clickSubscribe6Month();
expect(page.url()).toContain('&flow_begin_time=');
});
test('New user checkout URL to have flow params', async ({
pages: { settings, relier, page },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await settings.goto();
await settings.signOut();
await relier.goto();
await relier.clickSubscribe6Month();
expect(page.url()).toContain('&flow_begin_time=');
});
test('New user checkout URL to have flow params with cache cleared', async ({
pages: { settings, login, relier, page },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await settings.goto();
await settings.signOut();
await login.clearCache();
await relier.goto();
await relier.clickSubscribe6Month();
expect(page.url()).toContain('&flow_begin_time=');
});
test('New user checkout URL to have RP-provided flow params, acquisition params & verify funnel metrics', async ({
pages: { settings, relier, page, subscribe },
}, { project }) => {
test.skip(
project.name === 'production',
'test plan not yet available in prod'
);
await settings.goto();
await settings.signOut();
await relier.goto();
const subscribeUrl = await relier.getUrl();
if (!subscribeUrl) {
fail('Subscribe button has no href.');
}
const rpSearchParamsBefore = relier.getRpSearchParams(subscribeUrl);
const rpFlowParamsBefore = relier.getRpFlowParams(rpSearchParamsBefore);
const acquisitionParamsBefore =
relier.getRpAcquisitionParams(rpSearchParamsBefore);
// check flow metrics
await relier.clickSubscribeRPFlowMetrics();
const rpSearchParamsAfter = relier.getRpSearchParams(page.url());
const rpFlowParamsAfter = relier.getRpFlowParams(rpSearchParamsAfter);
expect(rpFlowParamsAfter).toStrictEqual(rpFlowParamsBefore);
// subscribe, failing first then succeeding
await subscribe.setEmailAndConfirmNewUser();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setFailedCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.clickTryAgain();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
// check acquisition metrics
const acquisitionParamsAfter =
metricsObserver.getAcquisitionParamsFromEvents();
expect(acquisitionParamsAfter).toStrictEqual(acquisitionParamsBefore);
// check conversion funnel metrics
const expectedEventTypes = [
'amplitude.subPaySetup.view',
'amplitude.subPaySetup.engage',
'amplitude.subPaySetup.submit',
'amplitude.subPaySetup.fail',
'amplitude.subPaySetup.submit',
'amplitude.subPaySetup.success',
];
const actualEventTypes = metricsObserver.rawEvents.map((event) => {
return event.type;
});
expect(actualEventTypes).toMatchObject(expectedEventTypes);
});
});
});
});

Просмотреть файл

@ -1,91 +1,99 @@
/* 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/. */
import { test, expect } from '../../lib/fixtures/standard';
test.describe('support form without valid session', () => {
test('go to support form, redirects to index', async ({
page,
target,
pages: { login },
}) => {
await login.clearCache();
await page.goto(`${target.contentServerUrl}/support`, {
waitUntil: 'load',
test.describe('severity-1 #smoke', () => {
test.describe('support form without valid session', () => {
test('go to support form, redirects to index', async ({
page,
target,
pages: { login },
}) => {
await login.clearCache();
await page.goto(`${target.contentServerUrl}/support`, {
waitUntil: 'load',
});
await login.waitForEmailHeader();
});
await login.waitForEmailHeader();
});
});
test.describe('support form without active subscriptions', () => {
test('go to support form, redirects to subscription management, then back to settings', async ({
page,
target,
pages: { login },
}) => {
test.slow();
await page.goto(`${target.contentServerUrl}/support`, {
waitUntil: 'load',
test.describe('support form without active subscriptions', () => {
test('go to support form, redirects to subscription management, then back to settings', async ({
page,
target,
pages: { login },
}) => {
test.slow();
await page.goto(`${target.contentServerUrl}/support`, {
waitUntil: 'load',
});
await page.waitForURL(/settings/);
expect(await login.isUserLoggedIn()).toBe(true);
});
await page.waitForURL(/settings/);
expect(await login.isUserLoggedIn()).toBe(true);
});
});
test.describe('support form with active subscriptions', () => {
test.beforeEach(() => {
test.slow();
});
test.describe('severity-2 #smoke', () => {
test.describe('support form with active subscriptions', () => {
test.beforeEach(() => {
test.slow();
});
test('go to support form, submits the form', async ({
pages: { login, relier, subscribe, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
test('go to support form, submits the form', async ({
pages: { login, relier, subscribe, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
await subscriptionManagement.fillSupportForm();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
await subscriptionManagement.fillSupportForm();
//Since we don't have proper Zendesk config in CircleCI, the form cannot be successfully submitted
//await subscriptionManagement.submitSupportForm();
//expect(await subscriptionManagement.subscriptionManagementHeader()).toBe(true);
});
//Since we don't have proper Zendesk config in CircleCI, the form cannot be successfully submitted
//await subscriptionManagement.submitSupportForm();
//expect(await subscriptionManagement.subscriptionManagementHeader()).toBe(true);
});
test('go to support form, cancel, redirects to subscription management', async ({
page,
pages: { login, relier, subscribe, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
test('go to support form, cancel, redirects to subscription management', async ({
page,
pages: { login, relier, subscribe, settings, subscriptionManagement },
}, { project }) => {
test.skip(
project.name === 'production',
'no real payment method available in prod'
);
await relier.goto();
await relier.clickSubscribe();
await subscribe.setConfirmPaymentCheckbox();
await subscribe.setFullName();
await subscribe.setCreditCardInfo();
await subscribe.clickPayNow();
await subscribe.submit();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
await subscriptionManagement.fillSupportForm();
await subscriptionManagement.cancelSupportForm();
//Login to FxA account
await login.goto();
await login.clickSignIn();
const subscriptionPage = await settings.clickPaidSubscriptions();
subscriptionManagement.page = subscriptionPage;
await subscriptionManagement.fillSupportForm();
await subscriptionManagement.cancelSupportForm();
//Verify it redirects back to the subscription management page
expect(await subscriptionManagement.subscriptiontHeader()).toBe(true);
//Verify it redirects back to the subscription management page
expect(await subscriptionManagement.subscriptiontHeader()).toBe(true);
});
});
});

Просмотреть файл

@ -14,250 +14,252 @@ let otherEmail;
test.describe.configure({ mode: 'parallel' });
test.describe('Firefox desktop user info handshake', () => {
test.beforeEach(async ({ target, page }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
browserSignedInEmail = login.createEmail();
await target.auth.signUp(browserSignedInEmail, password, {
lang: 'en',
preVerified: 'true',
test.describe('severity-2 #smoke', () => {
test.describe('Firefox desktop user info handshake', () => {
test.beforeEach(async ({ target, page }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
browserSignedInEmail = login.createEmail();
await target.auth.signUp(browserSignedInEmail, password, {
lang: 'en',
preVerified: 'true',
});
otherEmail = login.createEmail();
await target.auth.signUp(otherEmail, password, {
lang: 'en',
preVerified: 'true',
});
});
otherEmail = login.createEmail();
await target.auth.signUp(otherEmail, password, {
lang: 'en',
preVerified: 'true',
});
});
test.afterEach(async ({ target }) => {
await syncBrowserPages.browser?.close();
const emails = [browserSignedInEmail, otherEmail];
for (const email of emails) {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
test.afterEach(async ({ target }) => {
await syncBrowserPages.browser?.close();
const emails = [browserSignedInEmail, otherEmail];
for (const email of emails) {
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
}
}
});
test('Non-Sync - user signed into browser, user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
}
);
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.fillOutEmailFirstSignIn(otherEmail, password);
expect(await login.isUserLoggedIn()).toBe(true);
// Then, sign in the user again, synthesizing the user having signed
// into Sync after the initial sign in.
const eventDetailStatusSignIn = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatusSignIn);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
test('Non-Sync - user signed into browser, user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
}
);
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.fillOutEmailFirstSignIn(otherEmail, password);
expect(await login.isUserLoggedIn()).toBe(true);
expect(await login.getPrefilledEmail()).toContain(otherEmail);
await login.clickSignIn();
expect(await login.isUserLoggedIn()).toBe(true);
});
// Then, sign in the user again, synthesizing the user having signed
// into Sync after the initial sign in.
const eventDetailStatusSignIn = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatusSignIn);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
test('Sync - no user signed into browser, no user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
expect(await login.getPrefilledEmail()).toContain(otherEmail);
await login.clickSignIn();
expect(await login.isUserLoggedIn()).toBe(true);
});
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&${query.toString()}`
);
await login.waitForEmailHeader();
expect(await login.getEmailInput()).toContain('');
});
test('Sync - no user signed into browser, user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
test('Sync - no user signed into browser, no user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
});
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&${query.toString()}`
);
await login.waitForEmailHeader();
expect(await login.getEmailInput()).toContain('');
});
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.fillOutEmailFirstSignIn(otherEmail, password);
expect(await login.isUserLoggedIn()).toBe(true);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
expect(await login.getPrefilledEmail()).toContain(otherEmail);
});
test('Non-Sync - no user signed into browser, no user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
test('Sync - no user signed into browser, user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
});
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.fillOutEmailFirstSignIn(otherEmail, password);
expect(await login.isUserLoggedIn()).toBe(true);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
expect(await login.getPrefilledEmail()).toContain(otherEmail);
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
}
);
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getEmailInput()).toContain('');
});
test('Sync force_auth page - user signed into browser is different to requested user', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
email: otherEmail,
test('Non-Sync - no user signed into browser, no user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
}
);
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getEmailInput()).toContain('');
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${
target.contentServerUrl
}?force_auth&automatedBrowser=true&context=fx_desktop_v3&service=sync&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getPrefilledEmail()).toContain(otherEmail);
});
test('Non-Sync force_auth page - user signed into browser is different to requested user', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
email: otherEmail,
test('Sync force_auth page - user signed into browser is different to requested user', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
email: otherEmail,
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${
target.contentServerUrl
}?force_auth&automatedBrowser=true&context=fx_desktop_v3&service=sync&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getPrefilledEmail()).toContain(otherEmail);
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${
target.contentServerUrl
}?force_auth&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getPrefilledEmail()).toContain(otherEmail);
});
test('Sync - user signed into browser, no user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
email: browserSignedInEmail,
test('Non-Sync force_auth page - user signed into browser is different to requested user', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
email: otherEmail,
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${
target.contentServerUrl
}?force_auth&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getPrefilledEmail()).toContain(otherEmail);
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getPrefilledEmail()).toContain(browserSignedInEmail);
});
test('Non-Sync - user signed into browser, no user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
email: browserSignedInEmail,
test('Sync - user signed into browser, no user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
email: browserSignedInEmail,
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getPrefilledEmail()).toContain(browserSignedInEmail);
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getPrefilledEmail()).toContain(browserSignedInEmail);
await login.setPassword(password);
await login.clickSubmit();
expect(await login.isUserLoggedIn()).toBe(true);
});
test('Non-Sync settings page - no user signed into browser, user signed in locally', async ({
target,
}) => {
const { login, page, settings } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
test('Non-Sync - user signed into browser, no user signed in locally', async ({
target,
}) => {
const { login, page } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
email: browserSignedInEmail,
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: browserSignedInEmail,
}
);
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
expect(await login.getPrefilledEmail()).toContain(browserSignedInEmail);
await login.setPassword(password);
await login.clickSubmit();
expect(await login.isUserLoggedIn()).toBe(true);
});
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.fillOutEmailFirstSignIn(otherEmail, password);
expect(await login.isUserLoggedIn()).toBe(true);
await settings.goto();
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(otherEmail);
test('Non-Sync settings page - no user signed into browser, user signed in locally', async ({
target,
}) => {
const { login, page, settings } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
});
await page.goto(
`${target.contentServerUrl}?automatedBrowser=true&${query.toString()}`
);
await login.fillOutEmailFirstSignIn(otherEmail, password);
expect(await login.isUserLoggedIn()).toBe(true);
await settings.goto();
const primaryEmail = await settings.primaryEmail.statusText();
expect(primaryEmail).toEqual(otherEmail);
});
});
});

Просмотреть файл

@ -13,181 +13,185 @@ let syncBrowserPages;
test.describe.configure({ mode: 'parallel' });
test.describe('Desktop Sync V3 force auth', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
});
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
test('sync v3 with a registered email, no uid', async ({
credentials,
target,
}) => {
const {
fxDesktopV3ForceAuth,
login,
connectAnotherDevice,
signinTokenCode,
} = syncBrowserPages;
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
uid: undefined,
test.describe('severity-1 #smoke', () => {
test.describe('Desktop Sync V3 force auth', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
});
await login.setPassword(credentials.password);
await login.submit();
expect(await signinTokenCode.tokenCodeHeader.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await login.fillOutSignInCode(credentials.email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
test('sync v3 with a registered email, registered uid', async ({
credentials,
target,
}) => {
const {
fxDesktopV3ForceAuth,
login,
connectAnotherDevice,
signinTokenCode,
} = syncBrowserPages;
await fxDesktopV3ForceAuth.open(credentials);
await login.setPassword(credentials.password);
await login.submit();
expect(await signinTokenCode.tokenCodeHeader.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await login.fillOutSignInCode(credentials.email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
test('sync v3 with a registered email, unregistered uid', async ({
credentials,
target,
}) => {
const {
fxDesktopV3ForceAuth,
login,
connectAnotherDevice,
signinTokenCode,
} = syncBrowserPages;
const uid = makeUid();
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, { uid });
await fxDesktopV3ForceAuth.noSuchWebChannelMessage('fxaccounts:logout');
await login.setPassword(credentials.password);
await login.submit();
expect(await signinTokenCode.tokenCodeHeader.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await login.fillOutSignInCode(credentials.email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
test('sync v3 with an unregistered email, no uid', async ({
credentials,
target,
}) => {
const { fxDesktopV3ForceAuth, login } = syncBrowserPages;
const email = `sync${Math.random()}@restmail.net`;
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
email,
uid: undefined,
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
const error = await login.signInError();
expect(error).toContain('Recreate');
const emailInputValue = await login.getEmailInput();
expect(emailInputValue).toBe(email);
const emailInput = await login.getEmailInputElement();
expect(emailInput.isDisabled());
await expect(
await (await login.getUseDifferentAccountLink()).count()
).toEqual(0);
await login.fillOutFirstSignUp(email, credentials.password, {
enterEmail: false,
test('sync v3 with a registered email, no uid', async ({
credentials,
target,
}) => {
const {
fxDesktopV3ForceAuth,
login,
connectAnotherDevice,
signinTokenCode,
} = syncBrowserPages;
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
uid: undefined,
});
await login.setPassword(credentials.password);
await login.submit();
expect(await signinTokenCode.tokenCodeHeader.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await login.fillOutSignInCode(credentials.email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
test('sync v3 with an unregistered email, registered uid', async ({
credentials,
target,
}) => {
const { fxDesktopV3ForceAuth, login } = syncBrowserPages;
test('sync v3 with a registered email, registered uid', async ({
credentials,
target,
}) => {
const {
fxDesktopV3ForceAuth,
login,
connectAnotherDevice,
signinTokenCode,
} = syncBrowserPages;
const email = `sync${Math.random()}@restmail.net`;
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
email,
await fxDesktopV3ForceAuth.open(credentials);
await login.setPassword(credentials.password);
await login.submit();
expect(await signinTokenCode.tokenCodeHeader.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await login.fillOutSignInCode(credentials.email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
const error = await login.signInError();
expect(error).toContain('Recreate');
const emailInputValue = await login.getEmailInput();
expect(emailInputValue).toBe(email);
const emailInput = await login.getEmailInputElement();
expect(emailInput.isDisabled());
await expect(
await (await login.getUseDifferentAccountLink()).count()
).toEqual(0);
});
test('sync v3 with an unregistered email, unregistered uid', async ({
credentials,
target,
}) => {
const { fxDesktopV3ForceAuth, login } = syncBrowserPages;
test('sync v3 with a registered email, unregistered uid', async ({
credentials,
target,
}) => {
const {
fxDesktopV3ForceAuth,
login,
connectAnotherDevice,
signinTokenCode,
} = syncBrowserPages;
const email = `sync${Math.random()}@restmail.net`;
const uid = makeUid();
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
email,
uid,
const uid = makeUid();
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
uid,
});
await fxDesktopV3ForceAuth.noSuchWebChannelMessage('fxaccounts:logout');
await login.setPassword(credentials.password);
await login.submit();
expect(await signinTokenCode.tokenCodeHeader.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await login.fillOutSignInCode(credentials.email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
const error = await login.signInError();
expect(error).toContain('Recreate');
const emailInputValue = await login.getEmailInput();
expect(emailInputValue).toBe(email);
const emailInput = await login.getEmailInputElement();
expect(emailInput.isDisabled());
await expect(
await (await login.getUseDifferentAccountLink()).count()
).toEqual(0);
});
test('blocked with an registered email, unregistered uid', async ({
credentials,
target,
}) => {
const { fxDesktopV3ForceAuth, login, connectAnotherDevice } =
syncBrowserPages;
test('sync v3 with an unregistered email, no uid', async ({
credentials,
target,
}) => {
const { fxDesktopV3ForceAuth, login } = syncBrowserPages;
const uid = makeUid();
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
uid,
const email = `sync${Math.random()}@restmail.net`;
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
email,
uid: undefined,
});
const error = await login.signInError();
expect(error).toContain('Recreate');
const emailInputValue = await login.getEmailInput();
expect(emailInputValue).toBe(email);
const emailInput = await login.getEmailInputElement();
expect(emailInput.isDisabled());
await expect(
await (await login.getUseDifferentAccountLink()).count()
).toEqual(0);
await login.fillOutFirstSignUp(email, credentials.password, {
enterEmail: false,
});
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
test('sync v3 with an unregistered email, registered uid', async ({
credentials,
target,
}) => {
const { fxDesktopV3ForceAuth, login } = syncBrowserPages;
const email = `sync${Math.random()}@restmail.net`;
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
email,
});
const error = await login.signInError();
expect(error).toContain('Recreate');
const emailInputValue = await login.getEmailInput();
expect(emailInputValue).toBe(email);
const emailInput = await login.getEmailInputElement();
expect(emailInput.isDisabled());
await expect(
await (await login.getUseDifferentAccountLink()).count()
).toEqual(0);
});
test('sync v3 with an unregistered email, unregistered uid', async ({
credentials,
target,
}) => {
const { fxDesktopV3ForceAuth, login } = syncBrowserPages;
const email = `sync${Math.random()}@restmail.net`;
const uid = makeUid();
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
email,
uid,
});
const error = await login.signInError();
expect(error).toContain('Recreate');
const emailInputValue = await login.getEmailInput();
expect(emailInputValue).toBe(email);
const emailInput = await login.getEmailInputElement();
expect(emailInput.isDisabled());
await expect(
await (await login.getUseDifferentAccountLink()).count()
).toEqual(0);
});
test('blocked with an registered email, unregistered uid', async ({
credentials,
target,
}) => {
const { fxDesktopV3ForceAuth, login, connectAnotherDevice } =
syncBrowserPages;
const uid = makeUid();
await fxDesktopV3ForceAuth.openWithReplacementParams(credentials, {
uid,
});
await fxDesktopV3ForceAuth.noSuchWebChannelMessage('fxaccounts:logout');
await login.setPassword(credentials.password);
await login.submit();
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await login.unblock(credentials.email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
await fxDesktopV3ForceAuth.noSuchWebChannelMessage('fxaccounts:logout');
await login.setPassword(credentials.password);
await login.submit();
await fxDesktopV3ForceAuth.checkWebChannelMessage(
'fxaccounts:can_link_account'
);
await login.unblock(credentials.email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
await fxDesktopV3ForceAuth.checkWebChannelMessage('fxaccounts:login');
});
});

Просмотреть файл

@ -12,120 +12,122 @@ let syncBrowserPages;
test.describe.configure({ mode: 'parallel' });
test.describe('Firefox Desktop Sync v3 settings', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
const { login, connectAnotherDevice, page } = syncBrowserPages;
email = login.createEmail('sync{id}');
await target.auth.signUp(email, firstPassword, {
lang: 'en',
preVerified: 'true',
test.describe('severity-2 #smoke', () => {
test.describe('Firefox Desktop Sync v3 settings', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
const { login, connectAnotherDevice, page } = syncBrowserPages;
email = login.createEmail('sync{id}');
await target.auth.signUp(email, firstPassword, {
lang: 'en',
preVerified: 'true',
});
const customEventDetail = createCustomEventDetail(
FirefoxCommand.LinkAccount,
{
ok: true,
}
);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.respondToWebChannelMessage(customEventDetail);
await login.fillOutEmailFirstSignIn(email, firstPassword);
await login.waitForSignInCodeHeader();
await login.checkWebChannelMessage(FirefoxCommand.LinkAccount);
await login.fillOutSignInCode(email);
await login.checkWebChannelMessage(FirefoxCommand.Login);
expect(await connectAnotherDevice.fxaConnected.isEnabled()).toBeTruthy();
});
const customEventDetail = createCustomEventDetail(
FirefoxCommand.LinkAccount,
{
ok: true,
test.afterEach(async ({ target }, test) => {
await syncBrowserPages.browser?.close();
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, secondPassword);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
);
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.respondToWebChannelMessage(customEventDetail);
await login.fillOutEmailFirstSignIn(email, firstPassword);
await login.waitForSignInCodeHeader();
});
await login.checkWebChannelMessage(FirefoxCommand.LinkAccount);
await login.fillOutSignInCode(email);
await login.checkWebChannelMessage(FirefoxCommand.Login);
expect(await connectAnotherDevice.fxaConnected.isEnabled()).toBeTruthy();
test('sign in, change the password', async ({ target }) => {
const { changePassword, settings, page } = syncBrowserPages;
//Goto settings sync url
await page.goto(
`${target.contentServerUrl}/settings?context=fx_desktop_v3&service=sync`
);
//Change password
await settings.password.clickChange();
await changePassword.fillOutChangePassword(firstPassword, secondPassword);
await changePassword.submit();
//Verify success message
expect(await changePassword.changePasswordSuccess()).toContain(
'Password updated'
);
});
test('sign in, change the password by browsing directly to settings', async ({
target,
}) => {
const { login, changePassword, settings } = syncBrowserPages;
//Goto settings non-sync url
await settings.goto();
//Change password
await settings.password.clickChange();
await login.noSuchWebChannelMessage(FirefoxCommand.ChangePassword);
await changePassword.fillOutChangePassword(firstPassword, secondPassword);
await changePassword.submit();
//Verify success message
expect(await changePassword.changePasswordSuccess()).toContain(
'Password updated'
);
});
});
test.afterEach(async ({ target }, test) => {
await syncBrowserPages.browser?.close();
if (email) {
// Cleanup any accounts created during the test
try {
await target.auth.accountDestroy(email, secondPassword);
} catch (e) {
// Handle the error here
console.error('An error occurred during account cleanup:', e);
// Optionally, rethrow the error to propagate it further
throw e;
}
}
});
test.describe('Firefox Desktop Sync v3 settings - delete account', () => {
test('sign in, delete the account', async ({ target }) => {
syncBrowserPages = await newPagesForSync(target);
const { login, settings, deleteAccount, page } = syncBrowserPages;
test.slow();
email = login.createEmail('sync{id}');
await target.auth.signUp(email, firstPassword, {
lang: 'en',
preVerified: 'true',
});
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.fillOutEmailFirstSignIn(email, firstPassword);
await login.fillOutSignInCode(email);
test('sign in, change the password', async ({ target }) => {
const { changePassword, settings, page } = syncBrowserPages;
//Go to setting page
await page.goto(
`${target.contentServerUrl}/settings?context=fx_desktop_v3&service=sync`
);
//Click Delete account
await settings.clickDeleteAccount();
await deleteAccount.checkAllBoxes();
await deleteAccount.clickContinue();
//Goto settings sync url
await page.goto(
`${target.contentServerUrl}/settings?context=fx_desktop_v3&service=sync`
);
//Enter password
await deleteAccount.setPassword(firstPassword);
await deleteAccount.submit();
//Change password
await settings.password.clickChange();
await changePassword.fillOutChangePassword(firstPassword, secondPassword);
await changePassword.submit();
//Verify success message
expect(await changePassword.changePasswordSuccess()).toContain(
'Password updated'
);
});
test('sign in, change the password by browsing directly to settings', async ({
target,
}) => {
const { login, changePassword, settings } = syncBrowserPages;
//Goto settings non-sync url
await settings.goto();
//Change password
await settings.password.clickChange();
await login.noSuchWebChannelMessage(FirefoxCommand.ChangePassword);
await changePassword.fillOutChangePassword(firstPassword, secondPassword);
await changePassword.submit();
//Verify success message
expect(await changePassword.changePasswordSuccess()).toContain(
'Password updated'
);
});
});
test.describe('Firefox Desktop Sync v3 settings - delete account', () => {
test('sign in, delete the account', async ({ target }) => {
syncBrowserPages = await newPagesForSync(target);
const { login, settings, deleteAccount, page } = syncBrowserPages;
test.slow();
email = login.createEmail('sync{id}');
await target.auth.signUp(email, firstPassword, {
lang: 'en',
preVerified: 'true',
});
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.fillOutEmailFirstSignIn(email, firstPassword);
await login.fillOutSignInCode(email);
//Go to setting page
await page.goto(
`${target.contentServerUrl}/settings?context=fx_desktop_v3&service=sync`
);
//Click Delete account
await settings.clickDeleteAccount();
await deleteAccount.checkAllBoxes();
await deleteAccount.clickContinue();
//Enter password
await deleteAccount.setPassword(firstPassword);
await deleteAccount.submit();
const success = await page.waitForSelector('.success');
expect(await success.isVisible()).toBeTruthy();
const success = await page.waitForSelector('.success');
expect(await success.isVisible()).toBeTruthy();
});
});
});

Просмотреть файл

@ -11,195 +11,208 @@ let syncBrowserPages;
test.describe.configure({ mode: 'parallel' });
test.describe('Firefox Desktop Sync v3 sign in', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('sync{id}');
});
test.afterEach(async () => {
test.slow();//The cleanup was timing out and exceeding 3000ms
await syncBrowserPages.browser?.close();
});
test('verified, does not need to confirm', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
const email = login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
test.describe('severity-2 #smoke', () => {
test.describe('Firefox Desktop Sync v3 sign in', () => {
test.beforeEach(async ({ target }) => {
test.slow();
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('sync{id}');
});
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.submit();
expect(await connectAnotherDevice.fxaConnected.isEnabled()).toBeTruthy();
});
test('verified, resend', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Click resend link
await signinTokenCode.resendLink.click();
await signinTokenCode.successMessage.waitFor({ state: 'visible' });
await expect(signinTokenCode.successMessage).toBeVisible();
await expect(signinTokenCode.successMessage).toContainText('Email resent.');
const code = await target.email.waitForEmail(
email,
EmailType.verifyShortCode,
EmailHeader.shortCode
);
await signinTokenCode.input.fill(code);
await login.submit();
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('verified - invalid code', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Input invalid code and verify the tooltip error
await signinTokenCode.input.fill('000000');
await signinTokenCode.submit.click();
await expect(signinTokenCode.tooltip).toContainText('Invalid or expired');
//Input Valid code and verify the success
await login.fillOutSignUpCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('verified, blocked', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
const blockedEmail = login.createEmail('blocked{id}');
await target.auth.signUp(blockedEmail, password, {
lang: 'en',
preVerified: 'true',
test.afterEach(async () => {
test.slow(); //The cleanup was timing out and exceeding 3000ms
await syncBrowserPages.browser?.close();
});
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`
);
await login.setEmail(blockedEmail);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.submit();
await login.unblock(blockedEmail);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('unverified', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'false',
test('verified, does not need to confirm', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
const email = login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.submit();
expect(await connectAnotherDevice.fxaConnected.isEnabled()).toBeTruthy();
});
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.submit();
await login.fillOutSignInCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('add TOTP and confirm sync signin', async ({ credentials, target }) => {
const { page, login, connectAnotherDevice, settings, totp } =
syncBrowserPages;
test('verified, resend', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
await settings.signOut();
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Sync sign in
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`,
{ waitUntil: 'load' }
);
await login.login(credentials.email, credentials.password);
await login.setTotp(credentials.secret);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
// Click resend link
await signinTokenCode.resendLink.click();
await signinTokenCode.successMessage.waitFor({ state: 'visible' });
await expect(signinTokenCode.successMessage).toBeVisible();
await expect(signinTokenCode.successMessage).toContainText(
'Email resent.'
);
const code = await target.email.waitForEmail(
email,
EmailType.verifyShortCode,
EmailHeader.shortCode
);
await signinTokenCode.input.fill(code);
await login.submit();
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('verified - invalid code', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Input invalid code and verify the tooltip error
await signinTokenCode.input.fill('000000');
await signinTokenCode.submit.click();
await expect(signinTokenCode.tooltip).toContainText('Invalid or expired');
//Input Valid code and verify the success
await login.fillOutSignUpCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('verified, blocked', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
const blockedEmail = login.createEmail('blocked{id}');
await target.auth.signUp(blockedEmail, password, {
lang: 'en',
preVerified: 'true',
});
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`
);
await login.setEmail(blockedEmail);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.submit();
await login.unblock(blockedEmail);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('unverified', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'false',
});
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.submit();
await login.fillOutSignInCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('add TOTP and confirm sync signin', async ({
credentials,
target,
}) => {
const { page, login, connectAnotherDevice, settings, totp } =
syncBrowserPages;
await settings.goto();
await settings.totp.clickAdd();
await totp.enable(credentials);
await settings.signOut();
// Sync sign in
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`,
{ waitUntil: 'load' }
);
await login.login(credentials.email, credentials.password);
await login.setTotp(credentials.secret);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
});
});
test.describe('OAuth and Fx Desktop handshake', () => {
test('user signed into browser and OAuth login', async ({
target,
credentials,
}) => {
const { browser, page, login, relier, settings } = await newPagesForSync(
target
);
await page.goto(
target.contentServerUrl +
'?context=fx_desktop_v3&entrypoint=fxa%3Aenter_email&service=sync&action=email'
);
await login.login(credentials.email, credentials.password);
expect(await login.isSyncConnectedHeader()).toBe(true);
test.describe('severity-1 #smoke', () => {
test.describe('OAuth and Fx Desktop handshake', () => {
test('user signed into browser and OAuth login', async ({
target,
credentials,
}) => {
const { browser, page, login, relier, settings } = await newPagesForSync(
target
);
await page.goto(
target.contentServerUrl +
'?context=fx_desktop_v3&entrypoint=fxa%3Aenter_email&service=sync&action=email'
);
await login.login(credentials.email, credentials.password);
expect(await login.isSyncConnectedHeader()).toBe(true);
// Normally we wouldn't need this delay, but because we are
// disconnecting the sync service, we need to ensure that the device
// record and web channels have been sent and created.
await page.waitForTimeout(1000);
// Normally we wouldn't need this delay, but because we are
// disconnecting the sync service, we need to ensure that the device
// record and web channels have been sent and created.
await page.waitForTimeout(1000);
await relier.goto();
await relier.clickEmailFirst();
await relier.goto();
await relier.clickEmailFirst();
// User can sign in with cached credentials, no password needed.
await expect(await login.getPrefilledEmail()).toContain(credentials.email);
await expect(await login.isCachedLogin()).toBe(true);
// User can sign in with cached credentials, no password needed.
await expect(await login.getPrefilledEmail()).toContain(
credentials.email
);
await expect(await login.isCachedLogin()).toBe(true);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
await relier.signOut();
// Attempt to sign back in
await relier.clickEmailFirst();
// Attempt to sign back in
await relier.clickEmailFirst();
await expect(await login.getPrefilledEmail()).toContain(credentials.email);
await expect(await login.isCachedLogin()).toBe(true);
await expect(await login.getPrefilledEmail()).toContain(
credentials.email
);
await expect(await login.isCachedLogin()).toBe(true);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
// Disconnect sync otherwise we can have flaky tests.
await settings.disconnectSync(credentials);
// Disconnect sync otherwise we can have flaky tests.
await settings.disconnectSync(credentials);
expect(page.url()).toContain(login.url);
expect(page.url()).toContain(login.url);
await browser?.close();
await browser?.close();
});
});
});

Просмотреть файл

@ -10,128 +10,130 @@ let email, syncBrowserPages;
test.describe.configure({ mode: 'parallel' });
test.describe('Firefox Desktop Sync v3 sign up', () => {
test.beforeEach(async ({ target, pages: { login } }) => {
test.slow();
email = login.createEmail('sync{id}');
syncBrowserPages = await newPagesForSync(target);
});
test.describe('severity-1 #smoke', () => {
test.describe('Firefox Desktop Sync v3 sign up', () => {
test.beforeEach(async ({ target, pages: { login } }) => {
test.slow();
email = login.createEmail('sync{id}');
syncBrowserPages = await newPagesForSync(target);
});
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
test('sync sign up', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
test('sync sign up', async ({ target }) => {
const { page, login, connectAnotherDevice, signinTokenCode } =
syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`,
{ waitUntil: 'load' }
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync&action=email`,
{ waitUntil: 'load' }
);
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
// Verify the email is correct
expect(await login.getPrefilledEmail()).toMatch(email);
// Verify the email is correct
expect(await login.getPrefilledEmail()).toMatch(email);
// Passwords do not match should cause an error
await login.setPassword(password);
await login.confirmPassword(incorrectPassword);
await login.setAge('21');
await signinTokenCode.clickSubmitButton();
// Passwords do not match should cause an error
await login.setPassword(password);
await login.confirmPassword(incorrectPassword);
await login.setAge('21');
await signinTokenCode.clickSubmitButton();
// Verify the error message
expect(await login.getTooltipError()).toContain('Passwords do not match');
// Verify the error message
expect(await login.getTooltipError()).toContain('Passwords do not match');
// Fix the error
await login.confirmPassword(password);
await login.submit();
await login.fillOutSignUpCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
// Fix the error
await login.confirmPassword(password);
await login.submit();
await login.fillOutSignUpCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('coppa disabled', async ({ target }) => {
const { page, login, connectAnotherDevice } = syncBrowserPages;
const query = { coppa: 'false' };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`,
{ waitUntil: 'load' }
);
await login.setEmail(email);
await login.submit();
await login.setPassword(password);
await login.confirmPassword(password);
test('coppa disabled', async ({ target }) => {
const { page, login, connectAnotherDevice } = syncBrowserPages;
const query = { coppa: 'false' };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`,
{ waitUntil: 'load' }
);
await login.setEmail(email);
await login.submit();
await login.setPassword(password);
await login.confirmPassword(password);
// Age textbox is not on the page and click submit
await login.submit();
await login.fillOutSignUpCode(email);
expect(await connectAnotherDevice.fxaConnected.isEnabled()).toBeTruthy();
});
// Age textbox is not on the page and click submit
await login.submit();
await login.fillOutSignUpCode(email);
expect(await connectAnotherDevice.fxaConnected.isEnabled()).toBeTruthy();
});
test('email specified by relier, invalid', async ({ target }) => {
const { page, login } = syncBrowserPages;
const invalidEmail = 'invalid@@';
const query = { email: invalidEmail };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
expect(await login.getTooltipError()).toContain('Valid email required');
});
test('email specified by relier, invalid', async ({ target }) => {
const { page, login } = syncBrowserPages;
const invalidEmail = 'invalid@@';
const query = { email: invalidEmail };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
expect(await login.getTooltipError()).toContain('Valid email required');
});
test('email specified by relier, empty string', async ({ target }) => {
const { page, login } = syncBrowserPages;
const emptyEmail = '';
const query = { email: emptyEmail };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
expect(await login.getTooltipError()).toContain('Valid email required');
});
test('email specified by relier, empty string', async ({ target }) => {
const { page, login } = syncBrowserPages;
const emptyEmail = '';
const query = { email: emptyEmail };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
expect(await login.getTooltipError()).toContain('Valid email required');
});
test('email specified by relier, not registered', async ({ target }) => {
const { page, login } = syncBrowserPages;
const query = { email };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
test('email specified by relier, not registered', async ({ target }) => {
const { page, login } = syncBrowserPages;
const query = { email };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
// Verify user lands on the sign up password page
expect(await login.signUpPasswordHeader()).toBe(true);
// Verify user lands on the sign up password page
expect(await login.signUpPasswordHeader()).toBe(true);
// Verify the correct email is displayed
expect(await login.getPrefilledEmail()).toMatch(email);
});
// Verify the correct email is displayed
expect(await login.getPrefilledEmail()).toMatch(email);
});
test('email specified by relier, registered', async ({
credentials,
target,
}) => {
const { page, login } = syncBrowserPages;
const query = { email: credentials.email };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
test('email specified by relier, registered', async ({
credentials,
target,
}) => {
const { page, login } = syncBrowserPages;
const query = { email: credentials.email };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
// Verify user lands on the sign in password page
await login.waitForPasswordHeader();
// Verify user lands on the sign in password page
await login.waitForPasswordHeader();
// Verify the correct email is displayed
expect(await login.getPrefilledEmail()).toContain(credentials.email);
// Verify the correct email is displayed
expect(await login.getPrefilledEmail()).toContain(credentials.email);
});
});
});

Просмотреть файл

@ -12,217 +12,219 @@ let syncBrowserPages;
test.describe.configure({ mode: 'parallel' });
test.describe('Sync v3 sign up and CWTS', () => {
test.beforeEach(async ({ target }) => {
//Sync tests run a little slower and flake
test.slow();
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('sync{id}');
});
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
test('verify with signup code and CWTS', async ({ target }) => {
const { login, page, signinTokenCode, connectAnotherDevice } =
syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
test.describe('severity-1 #smoke', () => {
test.describe('Sync v3 sign up and CWTS', () => {
test.beforeEach(async ({ target }) => {
//Sync tests run a little slower and flake
test.slow();
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('sync{id}');
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
capabilities: {
choose_what_to_sync: true,
multiService: true,
engines: ['history'],
},
}
);
const eventDetailLinkAccount = createCustomEventDetail(
FirefoxCommand.LinkAccount,
{
ok: true,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.respondToWebChannelMessage(eventDetailLinkAccount);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
// The CWTS form is on the same signup page
await login.waitForCWTSEngineHeader();
expect(await login.isCWTSEngineBookmarks()).toBe(true);
expect(await login.isCWTSEngineHistory()).toBe(true);
expect(await login.isCWTSEnginePasswords()).toBe(true);
expect(await login.isCWTSEngineTabs()).toBe(true);
expect(await login.isCWTSEnginePrefs()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(false);
// Uncheck the passwords and history engines
await login.uncheckCWTSEngineHistory();
await login.uncheckCWTSEnginePasswords();
await signinTokenCode.clickSubmitButton();
await login.checkWebChannelMessage(FirefoxCommand.LinkAccount);
await login.fillOutSignUpCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('verify at CWTS', async ({ target }) => {
const { login, page, signinTokenCode, connectAnotherDevice } =
syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_58'],
test.afterEach(async () => {
await syncBrowserPages.browser?.close();
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
capabilities: {
multiService: false,
},
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`,
{
waitUntil: 'load',
}
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Verify the CWTS page and the checkboxes
expect(await login.isCWTSPageHeader()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(false);
expect(await login.isDoNotSync()).toBe(false);
expect(await login.isCWTSEngineCreditCards()).toBe(false);
await login.checkWebChannelMessage(FirefoxCommand.LinkAccount);
await login.noSuchWebChannelMessage(FirefoxCommand.Login);
await signinTokenCode.clickSubmitButton();
await login.fillOutSignUpCode(email);
await login.checkWebChannelMessage(FirefoxCommand.Login);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
test('verify with signup code and CWTS', async ({ target }) => {
const { login, page, signinTokenCode, connectAnotherDevice } =
syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_71'],
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
capabilities: {
choose_what_to_sync: true,
multiService: true,
engines: ['history'],
},
}
);
const eventDetailLinkAccount = createCustomEventDetail(
FirefoxCommand.LinkAccount,
{
ok: true,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.respondToWebChannelMessage(eventDetailLinkAccount);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
test('engines not supported', async ({ target }) => {
const { login, page, signinTokenCode } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_58'],
// The CWTS form is on the same signup page
await login.waitForCWTSEngineHeader();
expect(await login.isCWTSEngineBookmarks()).toBe(true);
expect(await login.isCWTSEngineHistory()).toBe(true);
expect(await login.isCWTSEnginePasswords()).toBe(true);
expect(await login.isCWTSEngineTabs()).toBe(true);
expect(await login.isCWTSEnginePrefs()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(false);
// Uncheck the passwords and history engines
await login.uncheckCWTSEngineHistory();
await login.uncheckCWTSEnginePasswords();
await signinTokenCode.clickSubmitButton();
await login.checkWebChannelMessage(FirefoxCommand.LinkAccount);
await login.fillOutSignUpCode(email);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Verify the CWTS page and the checkboxes
expect(await login.isCWTSPageHeader()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(false);
expect(await login.isCWTSEngineCreditCards()).toBe(false);
});
test('verify at CWTS', async ({ target }) => {
const { login, page, signinTokenCode, connectAnotherDevice } =
syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_58'],
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
capabilities: {
multiService: false,
},
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`,
{
waitUntil: 'load',
}
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
test('neither `creditcards` nor `addresses` supported', async ({
target,
}) => {
const { login, page, signinTokenCode } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_58'],
// Verify the CWTS page and the checkboxes
expect(await login.isCWTSPageHeader()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(false);
expect(await login.isDoNotSync()).toBe(false);
expect(await login.isCWTSEngineCreditCards()).toBe(false);
await login.checkWebChannelMessage(FirefoxCommand.LinkAccount);
await login.noSuchWebChannelMessage(FirefoxCommand.Login);
await signinTokenCode.clickSubmitButton();
await login.fillOutSignUpCode(email);
await login.checkWebChannelMessage(FirefoxCommand.Login);
expect(await connectAnotherDevice.fxaConnected.isVisible()).toBeTruthy();
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
engines: [],
},
signedInUser: null,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Verify the CWTS page and the checkboxes
expect(await login.isCWTSPageHeader()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(false);
expect(await login.isCWTSEngineCreditCards()).toBe(false);
});
test('engines not supported', async ({ target }) => {
const { login, page, signinTokenCode } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_58'],
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
signedInUser: null,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
test('`creditcards` and `addresses` supported', async ({ target }) => {
const { login, page, signinTokenCode } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_58'],
// Verify the CWTS page and the checkboxes
expect(await login.isCWTSPageHeader()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(false);
expect(await login.isCWTSEngineCreditCards()).toBe(false);
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
engines: ['creditcards', 'addresses'],
},
signedInUser: null,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Verify the CWTS page and the checkboxes
expect(await login.isCWTSPageHeader()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(true);
expect(await login.isCWTSEngineCreditCards()).toBe(true);
test('neither `creditcards` nor `addresses` supported', async ({
target,
}) => {
const { login, page, signinTokenCode } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_58'],
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
engines: [],
},
signedInUser: null,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Verify the CWTS page and the checkboxes
expect(await login.isCWTSPageHeader()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(false);
expect(await login.isCWTSEngineCreditCards()).toBe(false);
});
test('`creditcards` and `addresses` supported', async ({ target }) => {
const { login, page, signinTokenCode } = syncBrowserPages;
const query = new URLSearchParams({
forceUA: uaStrings['desktop_firefox_58'],
});
const eventDetailStatus = createCustomEventDetail(
FirefoxCommand.FxAStatus,
{
capabilities: {
engines: ['creditcards', 'addresses'],
},
signedInUser: null,
}
);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&automatedBrowser=true&${query.toString()}`
);
await login.respondToWebChannelMessage(eventDetailStatus);
await login.checkWebChannelMessage('fxaccounts:fxa_status');
await login.setEmail(email);
await signinTokenCode.clickSubmitButton();
await login.setPassword(password);
await login.confirmPassword(password);
await login.setAge('21');
await login.submit();
// Verify the CWTS page and the checkboxes
expect(await login.isCWTSPageHeader()).toBe(true);
expect(await login.isCWTSEngineAddresses()).toBe(true);
expect(await login.isCWTSEngineCreditCards()).toBe(true);
});
});
});

Просмотреть файл

@ -8,111 +8,113 @@ let email;
let email2;
let syncBrowserPages;
test.describe('sync signin cached', () => {
test.beforeEach(async ({ target }) => {
test.slow();//This test has steps for email rendering that runs slow on stage
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('sync{id}');
email2 = login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
test.describe('severity-2 #smoke', () => {
test.describe('sync signin cached', () => {
test.beforeEach(async ({ target }) => {
test.slow(); //This test has steps for email rendering that runs slow on stage
syncBrowserPages = await newPagesForSync(target);
const { login } = syncBrowserPages;
email = login.createEmail('sync{id}');
email2 = login.createEmail();
await target.auth.signUp(email, password, {
lang: 'en',
preVerified: 'true',
});
await target.auth.signUp(email2, password, {
lang: 'en',
preVerified: 'true',
});
});
await target.auth.signUp(email2, password, {
lang: 'en',
preVerified: 'true',
});
});
test.afterEach(async ({ target }) => {
test.slow();//The cleanup was timing out and exceeding 3000ms
await syncBrowserPages.browser?.close();
const emails = [email, email2];
for (const email of emails) {
if (email) {
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle any errors if needed
test.afterEach(async ({ target }) => {
test.slow(); //The cleanup was timing out and exceeding 3000ms
await syncBrowserPages.browser?.close();
const emails = [email, email2];
for (const email of emails) {
if (email) {
try {
await target.auth.accountDestroy(email, password);
} catch (e) {
// Handle any errors if needed
}
}
}
}
});
test('sign in on desktop then specify a different email on query parameter continues to cache desktop signin', async ({
target,
}) => {
const { page, login, connectAnotherDevice } = syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`
);
await login.fillOutEmailFirstSignIn(email, password);
//Verify sign up code header is visible
await login.waitForSignInCodeHeader();
const query = { email: email2 };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email2);
await login.setPassword(password);
await login.clickSubmit();
await connectAnotherDevice.clickNotNow();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Reset prefill and context
await login.clearSessionStorage();
//Testing to make sure cached signin comes back after a refresh
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
expect(await login.getPrefilledEmail()).toContain(email);
await login.useDifferentAccountLink();
await login.waitForEmailHeader();
});
test('sign in with desktop context then no context, desktop credentials should persist', async ({
target,
}) => {
const { page, login } = syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`
);
await login.fillOutEmailFirstSignIn(email, password);
test('sign in on desktop then specify a different email on query parameter continues to cache desktop signin', async ({
target,
}) => {
const { page, login, connectAnotherDevice } = syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`
);
await login.fillOutEmailFirstSignIn(email, password);
//Verify sign up code header is visible
await login.waitForSignInCodeHeader();
//Verify sign up code header is visible
await login.waitForSignInCodeHeader();
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
const query = { email: email2 };
const queryParam = new URLSearchParams(query);
await page.goto(
`${
target.contentServerUrl
}?context=fx_desktop_v3&service=sync&action=email&${queryParam.toString()}`
);
//Check prefilled email
expect(await login.getPrefilledEmail()).toContain(email2);
await login.setPassword(password);
await login.clickSubmit();
await connectAnotherDevice.clickNotNow();
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Reset prefill and context
await login.clearSessionStorage();
//Testing to make sure cached signin comes back after a refresh
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
expect(await login.getPrefilledEmail()).toContain(email);
await login.useDifferentAccountLink();
await login.waitForEmailHeader();
});
expect(await login.getPrefilledEmail()).toContain(email);
await login.useDifferentAccountLink();
await login.waitForEmailHeader();
await login.fillOutEmailFirstSignIn(email2, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
test('sign in with desktop context then no context, desktop credentials should persist', async ({
target,
}) => {
const { page, login } = syncBrowserPages;
await page.goto(
`${target.contentServerUrl}?context=fx_desktop_v3&service=sync`
);
await login.fillOutEmailFirstSignIn(email, password);
//Reset prefill and context
await login.clearSessionStorage();
//Verify sign up code header is visible
await login.waitForSignInCodeHeader();
//Testing to make sure cached signin comes back after a refresh
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
expect(await login.getPrefilledEmail()).toContain(email);
await login.useDifferentAccountLink();
await login.waitForEmailHeader();
await login.fillOutEmailFirstSignIn(email2, password);
//Verify logged in on Settings page
expect(await login.isUserLoggedIn()).toBe(true);
//Reset prefill and context
await login.clearSessionStorage();
//Testing to make sure cached signin comes back after a refresh
await page.goto(target.contentServerUrl, {
waitUntil: 'load',
});
expect(await login.getPrefilledEmail()).toContain(email);
await login.useDifferentAccountLink();
await login.waitForEmailHeader();
});
expect(await login.getPrefilledEmail()).toContain(email);
await login.useDifferentAccountLink();
await login.waitForEmailHeader();
});
});

Просмотреть файл

@ -5,45 +5,59 @@
import { test } from '../../lib/fixtures/standard';
import { authenticator } from 'otplib';
const GOOGLE_TEST_EMAIL = process.env.GOOGLE_TEST_EMAIL || 'fxalive2022@gmail.com';
const GOOGLE_TEST_EMAIL =
process.env.GOOGLE_TEST_EMAIL || 'fxalive2022@gmail.com';
const GOOGLE_TEST_PASSWORD = process.env.GOOGLE_TEST_PASSWORD;
const GOOGLE_TEST_2FA_SECRET = process.env.GOOGLE_TEST_2FA_SECRET;
test.describe('third party auth', () => {
test('Google signin to settings', async ({
target,
pages: { login, page },
}) => {
const shouldSkip = !GOOGLE_TEST_EMAIL || !GOOGLE_TEST_PASSWORD || !GOOGLE_TEST_2FA_SECRET;
test.skip(shouldSkip, 'Please contact FxA admin to get credentials for Google account');
test.slow();
await page.goto(
target.contentServerUrl + '?forceExperiment=thirdPartyAuth&forceExperimentGroup=treatment',
{ waitUntil: 'load' },
);
test.describe('severity-1 #smoke', () => {
test.describe('third party auth', () => {
test('Google signin to settings', async ({
target,
pages: { login, page },
}) => {
const shouldSkip =
!GOOGLE_TEST_EMAIL || !GOOGLE_TEST_PASSWORD || !GOOGLE_TEST_2FA_SECRET;
test.skip(
shouldSkip,
'Please contact FxA admin to get credentials for Google account'
);
test.slow();
await page.goto(
target.contentServerUrl +
'?forceExperiment=thirdPartyAuth&forceExperimentGroup=treatment',
{ waitUntil: 'load' }
);
await login.clickContinueWithGoogle();
await login.clickContinueWithGoogle();
await page.locator('input[type="email"]').fill(GOOGLE_TEST_EMAIL);
await page.getByText('Next').click();
await page.waitForURL(/v3\/signin\/challenge\/pwd/);
await page.locator('input[type="email"]').fill(GOOGLE_TEST_EMAIL);
await page.getByText('Next').click();
await page.waitForURL(/v3\/signin\/challenge\/pwd/);
await page.locator('input[type="password"]').fill(GOOGLE_TEST_PASSWORD);
await page.getByText('Next').click();
await page.locator('input[type="password"]').fill(GOOGLE_TEST_PASSWORD);
await page.getByText('Next').click();
let token = authenticator.generate(GOOGLE_TEST_2FA_SECRET);
await page.locator('#totpPin').fill(token);
await page.locator('#totpNext').getByRole('button', { name: 'Next' }).click();
let token = authenticator.generate(GOOGLE_TEST_2FA_SECRET);
await page.locator('#totpPin').fill(token);
await page
.locator('#totpNext')
.getByRole('button', { name: 'Next' })
.click();
const invalidCodeLocator = await page.getByText('Wrong code. Try again.');
if (await invalidCodeLocator.isVisible()) {
// Per chance the 2FA code expired, wait few seconds and try a new code
await page.waitForTimeout(5000);
token = authenticator.generate(GOOGLE_TEST_2FA_SECRET);
await page.locator('#totpPin').fill(token);
await page.locator('#totpNext').getByRole('button', { name: 'Next' }).click();
}
const invalidCodeLocator = await page.getByText('Wrong code. Try again.');
if (await invalidCodeLocator.isVisible()) {
// Per chance the 2FA code expired, wait few seconds and try a new code
await page.waitForTimeout(5000);
token = authenticator.generate(GOOGLE_TEST_2FA_SECRET);
await page.locator('#totpPin').fill(token);
await page
.locator('#totpNext')
.getByRole('button', { name: 'Next' })
.click();
}
await page.waitForURL(/settings/);
});
await page.waitForURL(/settings/);
});
});
});