Skip to content

Commit

Permalink
social login tests (#469)
Browse files Browse the repository at this point in the history
* add comments about manual test results to social login testcases

* add prod url to playground .env

* progress

* fix existing social login test

* prettier

* add social login tests

* prettier

* add comment about setting different timeout for microsoft social login tests
  • Loading branch information
aehnh authored Nov 26, 2024
1 parent 32b85e3 commit b526f21
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 44 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
"release:connect-web-js": "./release_connect_web_js.sh",
"test:e2e:local": "ts-node-esm ./scripts/e2eTests.ts",
"test:e2e:sdk": "lerna run e2e:sdk",
"test:e2e:ui:commitly": "lerna run e2e:ui:commitly",
"test:e2e:ui:nightly": "lerna run e2e:ui:nightly",
"test:e2e:ui": "lerna run e2e:ui",
"test:e2e:report": "lerna run e2e:report"
},
"devDependencies": {
Expand Down
3 changes: 1 addition & 2 deletions packages/tests-e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
"url": "git+https://github.com/corbado/javascript.git"
},
"scripts": {
"e2e:ui:commitly": "playwright test --config=playwright.config.ui.ts --project=commitly",
"e2e:ui:nightly": "playwright test --config=playwright.config.ui.ts --project=nightly",
"e2e:ui": "playwright test --config=playwright.config.ui.ts",
"e2e:report": "npx playwright show-report"
},
"bugs": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';

import type { SocialProviderType } from '../../utils/constants';
import { repeatSocialLogin, socialLogin } from './socialLogin';

export class LoginInitBlockModel {
page: Page;
Expand Down Expand Up @@ -38,6 +39,14 @@ export class LoginInitBlockModel {
await this.page.getByRole('button', { name: 'Continue' }).click();
}

async submitSocialMicrosoft(email: string, password: string) {
await socialLogin(this.page, email, password);
}

async resubmitSocialMicrosoft() {
await repeatSocialLogin(this.page);
}

submitPasskeyButton() {
return this.page.locator('.cb-last-identifier').click();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { expect } from '@playwright/test';

import type { SocialProviderType } from '../../utils/constants';
import { getRandomIntegerN } from '../../utils/random';
import { repeatSocialLogin, socialLogin } from './socialLogin';

export class SignupInitBlockModel {
page: Page;
Expand Down Expand Up @@ -53,31 +54,15 @@ export class SignupInitBlockModel {
}

submitPrimary() {
return this.page.getByRole('button', { name: 'Continue' }).click();
return this.page.getByRole('button', { name: 'Continue', exact: true }).click();
}

async submitSocialMicrosoft() {
const microsoftEmail = process.env.PLAYWRIGHT_MICROSOFT_EMAIL ?? '';
const microsoftPassword = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? '';

await this.page.getByTitle(`Continue with Microsoft`).click();
await expect(this.page.getByRole('heading', { level: 1 })).toHaveText('Sign in');

await this.page.getByRole('textbox', { name: 'email' }).click();
await this.page.getByRole('textbox', { name: 'email' }).fill(microsoftEmail);
await expect(this.page.getByRole('textbox', { name: 'email' })).toHaveValue(microsoftEmail);

await this.page.getByRole('button', { name: 'Next' }).click();
await expect(this.page.getByRole('heading', { level: 1 })).toHaveText('Enter password');

await this.page.getByPlaceholder('Password').click();
await this.page.getByPlaceholder('Password').fill(microsoftPassword);
await expect(this.page.getByPlaceholder('Password')).toHaveValue(microsoftPassword);

await this.page.getByRole('button', { name: 'Sign in' }).click();
await expect(this.page.getByRole('heading', { level: 1 })).toHaveText('Stay signed in?');
async submitSocialMicrosoft(email: string, password: string) {
await socialLogin(this.page, email, password);
}

await this.page.getByRole('button', { name: 'No' }).click();
async resubmitSocialMicrosoft() {
await repeatSocialLogin(this.page);
}

expectErrorMissingUsername(): Promise<void> {
Expand Down
30 changes: 30 additions & 0 deletions packages/tests-e2e/src/models/corbado-auth-blocks/socialLogin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type { Page } from '@playwright/test';
import { expect } from '@playwright/test';

export const socialLogin = async (page: Page, email: string, password: string) => {
await page.getByTitle(`Continue with Microsoft`).click();
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Sign in');

await page.getByRole('textbox', { name: 'email' }).click();
await page.getByRole('textbox', { name: 'email' }).fill(email);
await expect(page.getByRole('textbox', { name: 'email' })).toHaveValue(email);

await page.getByRole('button', { name: 'Next' }).click();
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Enter password');

await page.getByPlaceholder('Password').click();
await page.getByPlaceholder('Password').fill(password);
await expect(page.getByPlaceholder('Password')).toHaveValue(password);

await page.getByRole('button', { name: 'Sign in' }).click();
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Stay signed in?');

await page.getByRole('button', { name: 'No' }).click();
};

export const repeatSocialLogin = async (page: Page) => {
await page.getByTitle(`Continue with Microsoft`).click();
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Let this app access your info? (1 of 1 apps)');

await page.getByRole('button', { name: 'Accept' }).click();
};
108 changes: 94 additions & 14 deletions packages/tests-e2e/src/ui/corbado-auth-general/socials.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
IdentifierType,
IdentifierVerification,
ScreenNames,
socialOperationTimeout,
SocialProviderType,
} from '../../utils/constants';
import {
Expand All @@ -17,13 +18,19 @@ import {
test.describe('social logins', () => {
let projectId: string;

test.beforeAll(async () => {
// Microsoft social login requires longer timeout
test.use({
actionTimeout: socialOperationTimeout,
navigationTimeout: socialOperationTimeout,
});

test.beforeEach(async () => {
projectId = await createProjectNew();

await setComponentConfig(
projectId,
[
makeIdentifier(IdentifierType.Email, IdentifierEnforceVerification.Signup, true, [
makeIdentifier(IdentifierType.Email, IdentifierEnforceVerification.None, true, [
IdentifierVerification.EmailOtp,
]),
],
Expand All @@ -35,7 +42,7 @@ test.describe('social logins', () => {
);
});

test.afterAll(async () => {
test.afterEach(async () => {
await deleteProjectNew(projectId);
});

Expand All @@ -59,29 +66,102 @@ test.describe('social logins', () => {
);
});

// this covers signup + login
test.skip('signup with socials should be possible (account does not exist)', async ({ model }) => {
test('signup with socials should be possible (account does not exist)', async ({ model }) => {
await model.load(projectId, true, 'signup-init');

await model.signupInit.submitSocialMicrosoft();
const email = process.env.PLAYWRIGHT_MICROSOFT_EMAIL ?? '';
const password = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? '';

await model.signupInit.submitSocialMicrosoft(email, password);
await model.expectScreen(ScreenNames.PasskeyAppend1);
});

test.skip('signup with social should be possible (account exists, social has been linked)', async ({ model }) => {
await model.load(projectId, true, 'signup-init');

const email = process.env.PLAYWRIGHT_MICROSOFT_EMAIL_LINKED ?? '';
const password = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? '';

await model.signupInit.submitSocialMicrosoft(email, password);
await model.expectScreen(ScreenNames.PasskeyAppend1);
await model.passkeyAppend.startPasskeyOperation(true);
await model.expectScreen(ScreenNames.End);
await model.logout();
});

test.skip('signup with social should be possible (account exists, social has been linked)', async ({ model }) => {});
await model.load(projectId, true, 'signup-init');

await model.signupInit.resubmitSocialMicrosoft();
// TODO: should successfully log in, but gets redirected to login-init instead.
await model.expectScreen(ScreenNames.End);
});

// in that case only identifier based login should be possible
test.skip('signup with social should not be possible (account exists, social has not been linked)', async ({
model,
}) => {});
test('signup with social should not be possible (account exists, social has not been linked)', async ({ model }) => {
await model.load(projectId, true, 'signup-init');

const email = process.env.PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED ?? '';
const password = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? '';

await model.signupInit.fillEmail(email);
await model.signupInit.submitPrimary();
await model.passkeyAppend.startPasskeyOperation(true);
await model.expectScreen(ScreenNames.End);
await model.logout();

await model.load(projectId, true, 'signup-init');

await model.signupInit.submitSocialMicrosoft(email, password);
await model.expectScreen(ScreenNames.InitLogin);
});

test('login with social should be possible (account does not exist)', async ({ model }) => {
// redirects to passkey append screen
await model.load(projectId, true, 'login-init');

const email = process.env.PLAYWRIGHT_MICROSOFT_EMAIL ?? '';
const password = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? '';
await model.loginInit.submitSocialMicrosoft(email, password);

await model.expectScreen(ScreenNames.PasskeyAppend1);
});

test('login with social should be possible (account exists, social has been linked)', async ({ model }) => {
await model.load(projectId, true, 'signup-init');

const email = process.env.PLAYWRIGHT_MICROSOFT_EMAIL_LINKED ?? '';
const password = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? '';

await model.signupInit.submitSocialMicrosoft(email, password);
await model.expectScreen(ScreenNames.PasskeyAppend1);
await model.passkeyAppend.startPasskeyOperation(true);
await model.expectScreen(ScreenNames.End);
await model.logout();

test.skip('login with social should be possible (account does not exist)', async ({ model }) => {});
await model.load(projectId, true, 'login-init');

test.skip('login with social should be possible (account exists, social has been linked)', async ({ model }) => {});
await model.signupInit.resubmitSocialMicrosoft();
await model.expectScreen(ScreenNames.End);
});

// in that case only identifier based login should be possible
test.skip('login with social should not be possible (account exists, social has not been linked)', async ({
model,
}) => {});
}) => {
await model.load(projectId, true, 'signup-init');

const email = process.env.PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED ?? '';
const password = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? '';

await model.signupInit.fillEmail(email);
await model.signupInit.submitPrimary();
await model.passkeyAppend.startPasskeyOperation(true);
await model.expectScreen(ScreenNames.End);
await model.logout();

await model.load(projectId, true, 'login-init');

await model.signupInit.submitSocialMicrosoft(email, password);
// TODO: should redirect to login-init screen, but gets successfully logged in insteaad.
await model.expectScreen(ScreenNames.InitLogin);
});
});
3 changes: 2 additions & 1 deletion packages/tests-e2e/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,9 @@ export enum AuthType {

export const emailLinkUrlToken = 'UaTwjBJwyDLMGVbR7WHh';

export const operationTimeout = process.env.CI ? 3000 : 5000;
export const totalTimeout = process.env.CI ? 20000 : 30000;
export const operationTimeout = process.env.CI ? 3000 : 5000;
export const socialOperationTimeout = 10000;
export const waitAfterLoad = 600; // timeout to reduce flakiness due to repetitive reloads

export enum SocialProviderType {
Expand Down
6 changes: 3 additions & 3 deletions playground/react/.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
REACT_APP_CORBADO_PROJECT_ID_ManualTesting=pro-3652881945085154854
REACT_APP_CORBADO_PROJECT_ID_LocalDevelopment=pro-2
# REACT_APP_CORBADO_FRONTEND_API_URL_SUFFIX=frontendapi.corbado.io

# REACT_APP_CORBADO_FRONTEND_API_URL_SUFFIX=frontendapi.cloud.corbado-staging.io
REACT_APP_CORBADO_FRONTEND_API_URL_SUFFIX=frontendapi.corbado-dev.io
REACT_APP_CORBADO_FRONTEND_API_URL_SUFFIX=frontendapi.cloud.corbado-staging.io
# REACT_APP_CORBADO_FRONTEND_API_URL_SUFFIX=frontendapi.corbado-dev.io
# REACT_APP_CORBADO_FRONTEND_API_URL_SUFFIX=frontendapi.corbado.io

0 comments on commit b526f21

Please sign in to comment.