fix(tests): Add some tweaks to reduce flaky playwright tests

This commit is contained in:
Vijay Budhram 2023-03-31 16:08:26 -04:00
Родитель 503f99ea76
Коммит 6e45010bc4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: EBAEC5D86596C9EE
26 изменённых файлов: 215 добавлений и 226 удалений

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

@ -651,7 +651,7 @@ jobs:
default: large
parallelism:
type: integer
default: 8
default: 4
executor: functional-test-executor
resource_class: << parameters.resource_class >>
parallelism: << parameters.parallelism >>

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

@ -282,7 +282,7 @@ export class LoginPage extends BaseLayout {
}
async getTooltipError() {
return this.page.innerText(selectors.TOOLTIP);
return this.page.locator(selectors.TOOLTIP).innerText();
}
async unblock(email: string) {
@ -296,17 +296,14 @@ export class LoginPage extends BaseLayout {
}
async submit() {
return Promise.all([
this.page.locator(selectors.SUBMIT).click(),
this.page.waitForNavigation({ waitUntil: 'load' }),
]);
const waitForNavigation = this.page.waitForNavigation();
await this.page.locator(selectors.SUBMIT).click();
return waitForNavigation;
}
async clickForgotPassword() {
return Promise.all([
this.page.locator(selectors.LINK_RESET_PASSWORD).click(),
this.page.waitForNavigation({ waitUntil: 'networkidle' }),
]);
await this.page.locator(selectors.LINK_RESET_PASSWORD).click();
await this.page.waitForURL(/reset_password/);
}
async isSigninHeader() {
@ -360,10 +357,8 @@ export class LoginPage extends BaseLayout {
}
async clickDontHaveRecoveryKey() {
return Promise.all([
this.page.locator(selectors.LINK_LOST_RECOVERY_KEY).click(),
this.page.waitForNavigation(),
]);
await this.page.locator(selectors.LINK_LOST_RECOVERY_KEY).click();
await this.page.waitForURL(/complete_reset_password/);
}
setRecoveryKey(key: string) {
@ -375,19 +370,19 @@ export class LoginPage extends BaseLayout {
}
async setNewPassword(password: string) {
await this.page.fill(selectors.PASSWORD, password);
await this.page.fill(selectors.VPASSWORD, password);
await this.page.locator(selectors.PASSWORD).fill(password);
await this.page.locator(selectors.VPASSWORD).fill(password);
await this.submit();
}
async setTotp(secret: string) {
const code = await getCode(secret);
await this.page.fill(selectors.NUMBER_INPUT, code);
await this.page.locator(selectors.NUMBER_INPUT).fill(code);
await this.submit();
}
async getPrefilledEmail() {
return this.page.innerText(selectors.EMAIL_PREFILLED);
return this.page.locator(selectors.EMAIL_PREFILLED).innerText();
}
async getEmailInputElement() {
@ -395,11 +390,11 @@ export class LoginPage extends BaseLayout {
}
async getEmailInput() {
return this.page.inputValue(selectors.EMAIL);
return this.page.locator(selectors.EMAIL).inputValue();
}
async getPasswordInput() {
return this.page.inputValue(selectors.PASSWORD);
return this.page.locator(selectors.PASSWORD).inputValue();
}
async isCachedLogin() {
@ -416,7 +411,7 @@ export class LoginPage extends BaseLayout {
}
async getErrorMessage() {
return this.page.innerText(selectors.ERROR);
return this.page.locator(selectors.ERROR).innerText();
}
createEmail(template?: string) {

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

@ -38,10 +38,11 @@ export class SubscribePage extends BaseLayout {
'[data-testid="paypal-button-container"]'
);
await paypalButton.waitFor({ state: 'visible' });
const [paypalWindow] = await Promise.all([
this.page.waitForEvent('popup'),
this.page.locator('[data-testid="paypal-button-container"]').click(),
]);
const paypalWindowPromise = this.page.waitForEvent('popup');
await this.page.locator('[data-testid="paypal-button-container"]').click();
const paypalWindow = await paypalWindowPromise;
await paypalWindow.waitForLoadState('load');
await paypalWindow.waitForNavigation({
url: /checkoutnow/,

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

@ -1,4 +1,5 @@
import { BaseLayout } from './layout';
import { selectors } from './login';
export class RelierPage extends BaseLayout {
goto(query?: string) {
@ -27,25 +28,22 @@ export class RelierPage extends BaseLayout {
]);
}
clickEmailFirst() {
return Promise.all([
this.page.locator('button.email-first-button').click(),
this.page.waitForNavigation(),
]);
async clickEmailFirst() {
const waitForNavigation = this.page.waitForNavigation();
await this.page.locator('button.email-first-button').click();
return waitForNavigation;
}
clickSignIn() {
return Promise.all([
this.page.locator('button.sign-in-button.signin').click(),
this.page.waitForNavigation(),
]);
async clickSignIn() {
const waitForNavigation = this.page.waitForNavigation();
await this.page.locator('button.sign-in-button.signin').click();
return waitForNavigation;
}
clickForceAuth() {
return Promise.all([
this.page.locator('button.force-auth').click(),
this.page.waitForNavigation(),
]);
async clickForceAuth() {
const waitForNavigation = this.page.waitForNavigation();
await this.page.locator('button.force-auth').click();
return waitForNavigation;
}
clickChooseFlow() {
@ -53,27 +51,26 @@ export class RelierPage extends BaseLayout {
}
async clickSubscribe() {
await Promise.all([
this.page.getByRole('link', { name: 'Subscribe to Pro (USD)' }).click(),
this.page.waitForNavigation({ waitUntil: 'load' }),
]);
const waitForNavigation = this.page.waitForNavigation();
await this.page
.getByRole('link', { name: 'Subscribe to Pro (USD)' })
.click();
return waitForNavigation;
}
async clickSubscribe6Month() {
await Promise.all([
this.page
.getByRole('link', { name: 'Subscribe to Pro 6m (USD)' })
.click(),
this.page.waitForNavigation({ waitUntil: 'load' }),
]);
const waitForNavigation = this.page.waitForNavigation();
await this.page
.getByRole('link', { name: 'Subscribe to Pro 6m (USD)' })
.click();
return waitForNavigation;
}
async clickSubscribe12Month() {
await Promise.all([
this.page
.getByRole('link', { name: 'Subscribe to Pro 12m (USD)' })
.click(),
this.page.waitForNavigation({ waitUntil: 'load' }),
]);
const waitForNavigation = this.page.waitForNavigation();
await this.page
.getByRole('link', { name: 'Subscribe to Pro 12m (USD)' })
.click();
return waitForNavigation;
}
}

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

@ -53,8 +53,8 @@ export class ResetPasswordPage extends BaseLayout {
}
async resetNewPassword(password: string) {
await this.page.fill(selectors.PASSWORD, password);
await this.page.fill(selectors.VPASSWORD, password);
await this.page.locator(selectors.PASSWORD).fill(password);
await this.page.locator(selectors.VPASSWORD).fill(password);
await this.page.locator(selectors.SUBMIT).click();
}

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

@ -62,9 +62,8 @@ export abstract class SettingsLayout extends BaseLayout {
async signOut() {
await this.clickAvatarIcon();
await Promise.all([
this.clickSignOut(),
this.page.waitForURL(this.target.baseUrl, { waitUntil: 'load' }),
]);
const waitForURL = this.page.waitForURL(this.target.baseUrl);
await this.clickSignOut();
return waitForURL;
}
}

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

@ -13,19 +13,19 @@ export class RecoveryKeyPage extends SettingsLayout {
}
async invalidRecoveryKeyError() {
return this.page.innerText('#error-tooltip-159');
return this.page.locator('#error-tooltip-159').innerText();
}
setPassword(password: string) {
return this.page.fill('input[type=password]', password);
return this.page.locator('input[type=password]').fill(password);
}
async confirmRecoveryKey() {
return this.page.click('button[type=submit]');
return this.page.locator('button[type=submit]').click();
}
async clickLostRecoveryKey() {
return this.page.click('.lost-recovery-key');
return this.page.locator('.lost-recovery-key').click();
}
submit() {

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

@ -1,5 +1,5 @@
import { PlaywrightTestConfig, Project } from '@playwright/test';
import path from 'path';
import * as path from 'path';
import { TargetNames } from './lib/targets';
import { TestOptions, WorkerOptions } from './lib/fixtures/standard';
import { getFirefoxUserPrefs } from './lib/targets/firefoxUserPrefs';
@ -11,10 +11,20 @@ const CI = !!process.env.CI;
const DEBUG = !!process.env.DEBUG;
const SLOWMO = parseInt(process.env.PLAYWRIGHT_SLOWMO || '0');
let retries = 0,
workers = undefined,
maxFailures = 0;
if (CI) {
// Overall maxFailures is now dependent on the number of retries, workers
retries = 3;
workers = 2;
maxFailures = retries * workers * 2;
}
const config: PlaywrightTestConfig<TestOptions, WorkerOptions> = {
outputDir: path.resolve(__dirname, '../../artifacts/functional'),
forbidOnly: CI,
retries: CI ? 2 : 0,
retries,
testDir: 'tests',
use: {
viewport: { width: 1280, height: 720 },
@ -66,8 +76,8 @@ const config: PlaywrightTestConfig<TestOptions, WorkerOptions> = {
],
]
: 'list',
workers: CI ? 2 : undefined,
maxFailures: CI ? 3 : 0,
workers,
maxFailures,
};
export default config;

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

@ -4,5 +4,5 @@ DIR=$(dirname "$0")
cd "$DIR/../../../"
circleci tests glob "packages/functional-tests/tests/**/*.spec.ts" | circleci tests split --split-by=timings > tests-to-run.txt
circleci tests glob "packages/functional-tests/tests/**/*.spec.ts" | circleci tests split > tests-to-run.txt
yarn workspace functional-tests test $(cat tests-to-run.txt|awk -F"/" '{ print $NF }')

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

@ -9,7 +9,7 @@ test.describe('OAuth force auth', () => {
await relier.clickForceAuth();
// Email is prefilled
await expect(await login.page.innerText('#prefillEmail')).toMatch(
await expect(await login.page.innerText('#prefillEmail')).toContain(
credentials.email
);
await login.setPassword(credentials.password);

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

@ -1,6 +1,10 @@
import { test, expect } from '../../lib/fixtures/standard';
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 },

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

@ -14,23 +14,19 @@ const NEW_PASSWORD = 'notYourAveragePassW0Rd';
test.describe('reset password', () => {
test.beforeEach(async ({}, { project }) => {
test.slow(project.name !== 'local', 'email delivery can be slow');
test.slow();
});
test.skip('can reset password', async ({
page,
target,
credentials,
context,
}) => {
test('can reset password', async ({ page, target, credentials, context }) => {
await page.goto(getReactFeatureFlagUrl(target, '/reset_password'));
// Verify react page has been loaded
await page.waitForSelector('#root');
await page.locator('input').fill(credentials.email);
let waitForNavigation = page.waitForNavigation();
await page.locator('text="Begin reset"').click();
await page.waitForNavigation();
await waitForNavigation;
// Verify confirm password reset page elements
expect(
@ -71,34 +67,33 @@ test.describe('reset password', () => {
await diffPage.locator('input[name="newPassword"]').fill(NEW_PASSWORD);
await diffPage.locator('input[name="confirmPassword"]').fill(NEW_PASSWORD);
await Promise.all([
await diffPage.locator('text="Reset password"').click(),
await diffPage.waitForNavigation(),
]);
const pageWaitForNavigation = page.waitForNavigation();
const diffPageWaitForNavigation = diffPage.waitForNavigation();
await diffPage.locator('text="Reset password"').click();
await diffPageWaitForNavigation;
await pageWaitForNavigation;
expect(
await diffPage.locator('text="Your password has been reset"').isEnabled()
).toBeTruthy();
await diffPage.close();
// Attempt to login
await page.waitForNavigation();
expect(
await page.locator('text="Enter your email"').isEnabled()
).toBeTruthy();
await page.locator('input[type=email]').fill(credentials.email);
await Promise.all([
await page.locator('text="Sign up or sign in"').click(),
await page.waitForNavigation(),
]);
waitForNavigation = page.waitForNavigation();
await page.locator('text="Sign up or sign in"').click();
await waitForNavigation;
await page.locator('#password').fill(NEW_PASSWORD);
await Promise.all([
await page.locator('text="Sign in"').click(),
await page.waitForNavigation(),
]);
waitForNavigation = page.waitForNavigation();
await page.locator('text="Sign in"').click();
await waitForNavigation;
const settingsHeader = await page.locator('text=Settings');
expect(await settingsHeader.isEnabled()).toBeTruthy();

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

@ -22,7 +22,7 @@ test.describe('severity-1 #smoke', () => {
);
await page.goto(link, { waitUntil: 'networkidle' });
await login.setNewPassword(credentials.password);
expect(page.url()).toMatch(settings.url);
expect(page.url()).toContain(settings.url);
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293431

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

@ -9,7 +9,7 @@ test.describe('recovery key test', () => {
async ({ credentials, page, pages: { settings, recoveryKey } }) => {
// Generating and consuming recovery keys is a slow process
test.slow();
await settings.goto();
let status = await settings.recoveryKey.statusText();
expect(status).toEqual('Not Set');
@ -43,8 +43,6 @@ test.describe('recovery key test', () => {
page,
pages: { settings, recoveryKey, login },
}) => {
// Generating and consuming recovery keys is a slow process
test.slow();
let secondKey;
// Create new recovery key
@ -76,7 +74,9 @@ test.describe('recovery key test', () => {
await recoveryKey.confirmRecoveryKey();
// Verify the error
expect(await recoveryKey.invalidRecoveryKeyError()).toContain('Invalid account recovery key');
expect(await recoveryKey.invalidRecoveryKeyError()).toContain(
'Invalid account recovery key'
);
// Enter new recovery key
await login.setRecoveryKey(secondKey);
@ -149,7 +149,7 @@ test.describe('recovery key test', () => {
EmailType.recovery,
EmailHeader.link
);
await page.goto(link, { waitUntil: 'networkidle' });
await page.goto(link);
await login.setRecoveryKey(key);
await recoveryKey.confirmRecoveryKey();

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

@ -2,6 +2,11 @@ import { test, expect, newPagesForSync } 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();
});
// 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 ({
@ -108,7 +113,7 @@ test.describe('two step auth', () => {
await login.setCode(newCodes[0]);
await login.submit();
expect(page.url()).toMatch(settings.url);
expect(page.url()).toContain(settings.url);
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293460
@ -117,7 +122,6 @@ test.describe('two step auth', () => {
credentials,
pages: { page, login, settings, totp },
}, { project }) => {
test.slow(project.name !== 'local', 'non-local use more codes');
await settings.goto();
await settings.totp.clickAdd();
const { recoveryCodes } = await totp.enable(credentials);
@ -128,6 +132,7 @@ test.describe('two step auth', () => {
credentials.password,
recoveryCodes[i]
);
await login.page.waitForURL(/settings/);
await settings.signOut();
}
await login.login(
@ -135,12 +140,13 @@ test.describe('two step auth', () => {
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, { waitUntil: 'load' });
await page.goto(link);
const newCodes = await totp.getRecoveryCodes();
expect(newCodes.length).toEqual(recoveryCodes.length);
});

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

@ -11,62 +11,44 @@ test.describe('signup here', () => {
test.slow();
});
test('with an invalid email', async ({ target, page, pages: { login } }) => {
await page.goto(`${target.contentServerUrl}?email=invalid`, {
waitUntil: 'networkidle',
});
expect(await login.getErrorMessage()).toMatch('Invalid parameter: email');
});
test('with an empty email', async ({ target, page, pages: { login } }) => {
await page.goto(`${target.contentServerUrl}?email=`, {
waitUntil: 'networkidle',
});
expect(await login.getErrorMessage()).toMatch('Invalid parameter: email');
});
test('signup with email with leading whitespace on the email', async ({
test('with an invalid email, empty email query query param', async ({
target,
page,
pages: { login },
}) => {
const email = login.createEmail();
const emailWithoutSpace = email;
const emailWithSpace = ' ' + email;
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, false);
// Verify the confirm code header and the email
expect(await login.isSignUpCodeHeader()).toBe(true);
expect(await login.confirmEmail()).toMatch(emailWithoutSpace);
expect(await login.confirmEmail()).toContain(emailWithoutSpace);
// Need to clear the cache to get the new email
await login.clearCache();
await page.goto(target.contentServerUrl);
await login.fillOutEmailFirstSignIn(emailWithoutSpace, password);
// Verify the confirm code header
expect(await login.isSignUpCodeHeader()).toBe(true);
});
test('signup with email with trailing whitespace on the email', async ({
target,
page,
pages: { login },
}) => {
const email = login.createEmail();
const emailWithoutSpace = email;
const emailWithSpace = email + ' ';
await page.goto(target.contentServerUrl);
email = login.createEmail();
emailWithoutSpace = email;
emailWithSpace = email + ' ';
await login.fillOutFirstSignUp(emailWithSpace, password, false);
// Verify the confirm code header and the email
expect(await login.isSignUpCodeHeader()).toBe(true);
expect(await login.confirmEmail()).toMatch(emailWithoutSpace);
await login.clearCache();
await page.goto(target.contentServerUrl);
await login.fillOutEmailFirstSignIn(emailWithoutSpace, password);
// Verify the confirm code header
expect(await login.isSignUpCodeHeader()).toBe(true);
expect(await login.confirmEmail()).toContain(emailWithoutSpace);
});
test('signup with invalid email address', async ({
@ -79,35 +61,33 @@ test.describe('signup here', () => {
await login.clickSubmit();
// Verify the error
expect(await login.getTooltipError()).toMatch('Valid email required');
expect(await login.getTooltipError()).toContain('Valid email required');
});
test('coppa is empty', async ({ target, page, pages: { login } }) => {
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()).toMatch(
expect(await login.getTooltipError()).toContain(
'You must enter your age to sign up'
);
});
test('coppa too young', 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(password);
await login.setAge('12');
await login.clickSubmit();
// Verify the error
// Verify navigated to the cannot create account page
await page.waitForURL(/cannot_create_account/);
expect(await login.cannotCreateAccountHeader()).toBe(true);
});
@ -126,7 +106,7 @@ test.describe('signup here', () => {
await login.clickSubmit();
// Verify the error
expect(await login.getTooltipError()).toMatch('Passwords do not match');
expect(await login.getTooltipError()).toContain('Passwords do not match');
});
test('form prefill information is cleared after signup->sign out', async ({
@ -145,16 +125,16 @@ test.describe('signup here', () => {
// check the email address was cleared
expect(await login.isEmailHeader()).toBe(true);
expect(await login.getEmailInput()).toMatch('');
expect(await login.getEmailInput()).toContain('');
await login.setEmail(login.createEmail());
await login.clickSubmit();
// check the password was cleared
expect(await login.getPasswordInput()).toMatch('');
expect(await login.getPasswordInput()).toContain('');
});
test('signup via product page and redirect after confirm', async ({
test('signup via relier page and redirect after confirm', async ({
pages: { login, relier },
}) => {
const email = login.createEmail();

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

@ -50,7 +50,7 @@ test.describe('Sign up with code ', () => {
await login.fillOutFirstSignUp(email, PASSWORD, false);
await login.setCode('1234');
await signinTokenCode.clickSubmitButton();
expect(await login.getTooltipError()).toMatch(
expect(await login.getTooltipError()).toContain(
'Invalid or expired confirmation code'
);
});

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

@ -13,10 +13,7 @@ test.describe('redirect_to', () => {
async function engageRedirect(page, target, redirectTo) {
await page.goto(
`${target.contentServerUrl}/confirm_signup_code?redirect_to=${redirectTo}`,
{
waitUntil: 'networkidle',
}
`${target.contentServerUrl}/confirm_signup_code?redirect_to=${redirectTo}`
);
await page.click('button[type=submit]');
}
@ -51,8 +48,13 @@ test.describe('redirect_to', () => {
pages: { page },
}) => {
const redirectTo = `${target.contentServerUrl}/settings`;
await engageRedirect(page, target, redirectTo);
await page.waitForNavigation();
await page.goto(
`${target.contentServerUrl}/confirm_signup_code?redirect_to=${redirectTo}`
);
await page.click('button[type=submit]');
await page.waitForURL(/settings\?/);
expect(page.url().startsWith(redirectTo)).toBeTruthy();
});
});

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

@ -26,7 +26,7 @@ test.describe('severity-1 #smoke', () => {
await settings.disconnectSync(credentials);
expect(page.url()).toMatch(login.url);
expect(page.url()).toContain(login.url);
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293475
@ -70,7 +70,7 @@ test.describe('severity-3 #smoke', () => {
await page.goto('https://addons.mozilla.org/en-US/firefox/');
await Promise.all([page.click('text=Log in'), page.waitForNavigation()]);
await login.login(credentials.email, credentials.password);
expect(page.url()).toMatch(
expect(page.url()).toContain(
'https://addons.mozilla.org/en-US/firefox/users/edit'
);
await page.click('text=Delete My Profile');
@ -96,7 +96,7 @@ test.describe('severity-3 #smoke', () => {
page.waitForNavigation(),
]);
await login.login(credentials.email, credentials.password);
expect(page.url()).toMatch('https://getpocket.com/my-list');
expect(page.url()).toContain('https://getpocket.com/my-list');
await page.click('[aria-label="Open Account Menu"]');
await page.click('a:has-text("Log out")');
});
@ -114,7 +114,7 @@ test.describe('severity-3 #smoke', () => {
page.waitForNavigation(),
]);
await login.login(credentials.email, credentials.password);
expect(page.url()).toMatch('https://monitor.firefox.com/user/dashboard');
expect(page.url()).toContain('https://monitor.firefox.com/user/dashboard');
await page.click('#avatar-wrapper');
await Promise.all([
page.click('text=Sign Out'),
@ -149,49 +149,3 @@ test.describe('severity-3 #smoke', () => {
await expect(page.locator('text=Sign In/Up').first()).toBeVisible();
});
});
test.describe('OAuth and Fx Desktop handshake', () => {
test('user signed into browser and OAuth login', async ({
target,
credentials,
}) => {
const { page, login, settings, relier } = 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);
await relier.goto();
await relier.clickEmailFirst();
// User can sign in with cached credentials, no password needed.
await expect(await login.getPrefilledEmail()).toMatch(credentials.email);
await expect(await login.isCachedLogin()).toBe(true);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
// Attempt to sign back in
await relier.clickEmailFirst();
await expect(await login.getPrefilledEmail()).toMatch(credentials.email);
await expect(await login.isCachedLogin()).toBe(true);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
// Disconnect sync otherwise we can have flaky tests.
await settings.disconnectSync(credentials);
expect(page.url()).toMatch(login.url);
});
});

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

@ -13,7 +13,7 @@ test.describe('coupon test', () => {
await subscribe.addCouponCode('autoexpired');
// Verifying the correct error message
expect(await subscribe.couponErrorMessageText()).toMatch(
expect(await subscribe.couponErrorMessageText()).toContain(
'The code you entered has expired'
);
});
@ -27,7 +27,7 @@ test.describe('coupon test', () => {
await subscribe.addCouponCode('autoinvalid');
// Asserting that the code is invalid for a 6mo plan
expect(await subscribe.couponErrorMessageText()).toMatch(
expect(await subscribe.couponErrorMessageText()).toContain(
'The code you entered is invalid'
);
@ -53,7 +53,7 @@ test.describe('coupon test', () => {
await subscribe.addCouponCode('autoinvalid');
// Asserting that the code is invalid for a 6m plan
expect(await subscribe.couponErrorMessageText()).toMatch(
expect(await subscribe.couponErrorMessageText()).toContain(
'The code you entered is invalid'
);

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

@ -8,7 +8,7 @@ import { EmailHeader, EmailType } from '../../lib/email';
const password = 'passwordzxcv';
let email;
test.describe.skip('Firefox Desktop Sync v3 sign in', () => {
test.describe('Firefox Desktop Sync v3 sign in', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
email = login.createEmail('sync{id}');
@ -120,3 +120,49 @@ test.describe.skip('Firefox Desktop Sync v3 sign in', () => {
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 { page, login, settings, relier } = 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);
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);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
await relier.signOut();
// Attempt to sign back in
await relier.clickEmailFirst();
await expect(await login.getPrefilledEmail()).toContain(credentials.email);
await expect(await login.isCachedLogin()).toBe(true);
await login.submit();
expect(await relier.isLoggedIn()).toBe(true);
// Disconnect sync otherwise we can have flaky tests.
await settings.disconnectSync(credentials);
expect(page.url()).toContain(login.url);
});
});

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

@ -8,7 +8,7 @@ const password = 'passwordzxcv';
const incorrectPassword = 'password123';
let email;
test.describe.skip('Firefox Desktop Sync v3 sign up', () => {
test.describe('Firefox Desktop Sync v3 sign up', () => {
test.beforeEach(async ({ pages: { login } }) => {
test.slow();
email = login.createEmail('sync{id}');

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

@ -25,7 +25,7 @@ test.describe('Firefox Desktop Sync v3 reset password', () => {
EmailType.recovery,
EmailHeader.link
);
await page.goto(link, { waitUntil: 'load' });
await page.goto(link);
// Enter a short password
await resetPassword.resetNewPassword('pass');

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

@ -76,7 +76,7 @@ const execOptions = {
},
};
describe.skip('#integration - scripts/bulk-mailer', function () {
describe('#integration - scripts/bulk-mailer', function () {
this.timeout(10000);
let db, server;

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

@ -68,7 +68,7 @@ const execOptions = {
},
};
describe.skip('#integration - scripts/dump-users', function () {
describe('#integration - scripts/dump-users', function () {
this.timeout(10000);
let db, server;

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

@ -58,7 +58,7 @@ const account2Mock = createAccount(
const DB = require('../../lib/db')(config, log, Token, UnblockCode);
describe.skip('#integration - scripts/must-reset', async function () {
describe('#integration - scripts/must-reset', async function () {
this.timeout(30000);
let db, server;