From e661f2934e056c62c3e602739380b269627275d5 Mon Sep 17 00:00:00 2001 From: aehnh Date: Tue, 11 Feb 2025 14:14:50 +0100 Subject: [PATCH 1/8] change microsoft to google social login (tests) --- package-lock.json | 42 +++++++ packages/tests-e2e/package.json | 1 + .../LoginInitBlockModel.ts | 9 +- .../PasskeyAppendBlockModel.ts | 11 ++ .../SignupInitBlockModel.ts | 16 ++- .../models/corbado-auth-blocks/socialLogin.ts | 2 +- .../corbado-auth-general/socials.spec.ts | 54 +++++---- .../src/complete/utils/externalauth.ts | 107 ++++++++++++++++++ 8 files changed, 211 insertions(+), 31 deletions(-) create mode 100644 packages/tests-e2e/src/complete/utils/externalauth.ts diff --git a/package-lock.json b/package-lock.json index de599e2e2..3dd5c72ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8270,6 +8270,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/notp": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/notp/-/notp-2.0.5.tgz", + "integrity": "sha512-ZsZS0PYUa6ZE4K3yOGerBvaxCp4ePf6ZmkFbPeilcqz2Ui/lmXox7KlRt7XZkXzqUgXhFLkc09ixyVmFLCU3gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/parse-json": { "version": "4.0.2", "license": "MIT" @@ -19844,6 +19854,19 @@ "tslib": "^2.0.3" } }, + "node_modules/node-2fa": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/node-2fa/-/node-2fa-2.0.3.tgz", + "integrity": "sha512-PQldrOhjuoZyoydMvMSctllPN1ZPZ1/NwkEcgYwY9faVqE/OymxR+3awPpbWZxm6acLKqvmNqQmdqTsqYyflFw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/notp": "^2.0.0", + "notp": "^2.0.3", + "thirty-two": "1.0.2", + "tslib": "^2.1.0" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "dev": true, @@ -20050,6 +20073,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/notp": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/notp/-/notp-2.0.3.tgz", + "integrity": "sha512-oBig/2uqkjQ5AkBuw4QJYwkEWa/q+zHxI5/I5z6IeP2NT0alpJFsP/trrfCC+9xOAgQSZXssNi962kp5KBmypQ==", + "dev": true, + "engines": { + "node": "> v0.6.0" + } + }, "node_modules/npm-bundled": { "version": "3.0.1", "dev": true, @@ -25361,6 +25393,15 @@ "node": ">=0.8" } }, + "node_modules/thirty-two": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", + "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==", + "dev": true, + "engines": { + "node": ">=0.2.6" + } + }, "node_modules/throat": { "version": "6.0.2", "license": "MIT" @@ -27509,6 +27550,7 @@ "@playwright/test": "^1.47.0", "@types/node": "^20.10.5", "ngrok": "^5.0.0-beta.2", + "node-2fa": "^2.0.3", "playwright-slack-report": "^1.1.72" } }, diff --git a/packages/tests-e2e/package.json b/packages/tests-e2e/package.json index f302faeb5..aa87efa6b 100644 --- a/packages/tests-e2e/package.json +++ b/packages/tests-e2e/package.json @@ -25,6 +25,7 @@ "@playwright/test": "^1.47.0", "@types/node": "^20.10.5", "ngrok": "^5.0.0-beta.2", + "node-2fa": "^2.0.3", "playwright-slack-report": "^1.1.72" }, "dependencies": { diff --git a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts index dcf2e741d..b49bfd395 100644 --- a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts +++ b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts @@ -2,7 +2,8 @@ import type { Page } from '@playwright/test'; import { expect } from '@playwright/test'; import type { SocialProviderType } from '../../utils/constants'; -import { repeatSocialLogin, socialLogin } from './socialLogin'; +import { repeatSocialLogin, socialLoginDeprecated } from './socialLogin'; +import { socialLogin } from '../../utils/externalauth'; export class LoginInitBlockModel { page: Page; @@ -39,8 +40,12 @@ export class LoginInitBlockModel { await this.page.getByRole('button', { name: 'Continue' }).click(); } + async submitSocialGoogle(email: string, password: string, secret: string) { + await socialLogin(this.page, email, password, secret); + } + async submitSocialMicrosoft(email: string, password: string) { - await socialLogin(this.page, email, password); + await socialLoginDeprecated(this.page, email, password); } async resubmitSocialMicrosoft() { diff --git a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/PasskeyAppendBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/PasskeyAppendBlockModel.ts index 6c1e457e2..4ac9c0000 100644 --- a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/PasskeyAppendBlockModel.ts +++ b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/PasskeyAppendBlockModel.ts @@ -28,6 +28,17 @@ export class PasskeyAppendBlockModel { } } + async startPasskeyOperation2(complete: boolean) { + const operationTrigger = () => this.page.getByRole('button', { name: 'Create passkey' }).click(); + if (complete) { + await this.virtualAuthenticator.startAndCompletePasskeyOperation(operationTrigger); + } else { + await this.virtualAuthenticator.startAndCancelPasskeyOperation(operationTrigger, () => + expectScreen(this.page, ScreenNames.PasskeyError), + ); + } + } + async retryPasskeyOperation(complete: boolean) { const operationTrigger = () => this.page.getByRole('button', { name: 'Try again' }).click(); if (complete) { diff --git a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/SignupInitBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/SignupInitBlockModel.ts index d96de9c3a..fceb6120b 100644 --- a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/SignupInitBlockModel.ts +++ b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/SignupInitBlockModel.ts @@ -2,8 +2,8 @@ import type { Page } from '@playwright/test'; import { expect } from '@playwright/test'; import type { SocialProviderType } from '../../utils/constants'; +import { repeatSocialLogin, socialLogin } from '../../utils/externalauth'; import { getRandomIntegerN } from '../../utils/random'; -import { repeatSocialLogin, socialLogin } from './socialLogin'; export class SignupInitBlockModel { page: Page; @@ -53,14 +53,22 @@ export class SignupInitBlockModel { return this.page.getByRole('button', { name: 'Continue', exact: true }).click(); } - async submitSocialMicrosoft(email: string, password: string) { - await socialLogin(this.page, email, password); + async submitSocialGoogle(email: string, password: string, secret: string) { + await socialLogin(this.page, email, password, secret); } - async resubmitSocialMicrosoft() { + async resubmitSocialGoogle() { await repeatSocialLogin(this.page); } + // async submitSocialMicrosoft(email: string, password: string) { + // await socialLoginDeprecated(this.page, email, password); + // } + // + // async resubmitSocialMicrosoft() { + // await repeatSocialLogin(this.page); + // } + expectErrorMissingUsername(): Promise { return this.#expectError('Please enter a username.'); } diff --git a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts index 8362b852c..ccc2e0825 100644 --- a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts +++ b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts @@ -1,7 +1,7 @@ import type { Page } from '@playwright/test'; import { expect } from '@playwright/test'; -export const socialLogin = async (page: Page, email: string, password: string) => { +export const socialLoginDeprecated = async (page: Page, email: string, password: string) => { await page.getByTitle(`Continue with Microsoft`).click(); await expect(page.getByRole('heading', { level: 1 })).toHaveText('Sign in'); diff --git a/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts index 53833a6f5..c62e1a283 100644 --- a/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts +++ b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts @@ -69,20 +69,22 @@ test.describe('social logins', () => { test('signup with socials should be possible (account does not exist)', async ({ model }) => { await model.load(projectId, true, 'signup-init'); - const email = process.env.PLAYWRIGHT_MICROSOFT_EMAIL ?? ''; - const password = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? ''; + const email = process.env.PLAYWRIGHT_GOOGLE_EMAIL ?? ''; + const password = process.env.PLAYWRIGHT_GOOGLE_PASSWORD ?? ''; + const secret = process.env.PLAYWRIGHT_GOOGLE_TOTP_SECRET ?? ''; - await model.signupInit.submitSocialMicrosoft(email, password); - await model.expectScreen(ScreenNames.PasskeyAppend1); + await model.signupInit.submitSocialGoogle(email, password, secret); + await model.expectScreen(ScreenNames.PasskeyAppend2); }); 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 ?? ''; + const email = process.env.PLAYWRIGHT_GOOGLE_EMAIL ?? ''; + const password = process.env.PLAYWRIGHT_GOOGLE_PASSWORD ?? ''; + const secret = process.env.PLAYWRIGHT_GOOGLE_TOTP_SECRET ?? ''; - await model.signupInit.submitSocialMicrosoft(email, password); + await model.signupInit.submitSocialGoogle(email, password, secret); await model.expectScreen(ScreenNames.PasskeyAppend1); await model.passkeyAppend.startPasskeyOperation(true); await model.expectScreen(ScreenNames.End); @@ -90,7 +92,7 @@ test.describe('social logins', () => { await model.load(projectId, true, 'signup-init'); - await model.signupInit.resubmitSocialMicrosoft(); + await model.signupInit.resubmitSocialGoogle(); // TODO: should successfully log in, but gets redirected to login-init instead. await model.expectScreen(ScreenNames.End); }); @@ -101,8 +103,9 @@ test.describe('social logins', () => { }) => { await model.load(projectId, true, 'signup-init'); - const email = process.env.PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED ?? ''; - const password = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? ''; + const email = process.env.PLAYWRIGHT_GOOGLE_EMAIL ?? ''; + const password = process.env.PLAYWRIGHT_GOOGLE_PASSWORD ?? ''; + const secret = process.env.PLAYWRIGHT_GOOGLE_TOTP_SECRET ?? ''; await model.signupInit.fillEmail(email); await model.signupInit.submitPrimary(); @@ -112,7 +115,7 @@ test.describe('social logins', () => { await model.load(projectId, true, 'signup-init'); - await model.signupInit.submitSocialMicrosoft(email, password); + await model.signupInit.submitSocialGoogle(email, password, secret); await model.expectScreen(ScreenNames.InitLogin); }); @@ -120,28 +123,30 @@ test.describe('social logins', () => { // 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); + const email = process.env.PLAYWRIGHT_GOOGLE_EMAIL ?? ''; + const password = process.env.PLAYWRIGHT_GOOGLE_PASSWORD ?? ''; + const secret = process.env.PLAYWRIGHT_GOOGLE_TOTP_SECRET ?? ''; + await model.loginInit.submitSocialGoogle(email, password, secret); - await model.expectScreen(ScreenNames.PasskeyAppend1); + await model.expectScreen(ScreenNames.PasskeyAppend2); }); 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 ?? ''; + const email = process.env.PLAYWRIGHT_GOOGLE_EMAIL ?? ''; + const password = process.env.PLAYWRIGHT_GOOGLE_PASSWORD ?? ''; + const secret = process.env.PLAYWRIGHT_GOOGLE_TOTP_SECRET ?? ''; - await model.signupInit.submitSocialMicrosoft(email, password); - await model.expectScreen(ScreenNames.PasskeyAppend1); - await model.passkeyAppend.startPasskeyOperation(true); + await model.signupInit.submitSocialGoogle(email, password, secret); + await model.expectScreen(ScreenNames.PasskeyAppend2); + await model.passkeyAppend.startPasskeyOperation2(true); await model.expectScreen(ScreenNames.End); await model.logout(); await model.load(projectId, true, 'login-init'); - await model.signupInit.resubmitSocialMicrosoft(); + await model.signupInit.resubmitSocialGoogle(); await model.expectScreen(ScreenNames.End); }); @@ -151,8 +156,9 @@ test.describe('social logins', () => { }) => { await model.load(projectId, true, 'signup-init'); - const email = process.env.PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED ?? ''; - const password = process.env.PLAYWRIGHT_MICROSOFT_PASSWORD ?? ''; + const email = process.env.PLAYWRIGHT_GOOGLE_EMAIL ?? ''; + const password = process.env.PLAYWRIGHT_GOOGLE_PASSWORD ?? ''; + const secret = process.env.PLAYWRIGHT_GOOGLE_TOTP_SECRET ?? ''; await model.signupInit.fillEmail(email); await model.signupInit.submitPrimary(); @@ -162,7 +168,7 @@ test.describe('social logins', () => { await model.load(projectId, true, 'login-init'); - await model.signupInit.submitSocialMicrosoft(email, password); + await model.signupInit.submitSocialGoogle(email, password, secret); // TODO: should redirect to login-init screen, but gets successfully logged in insteaad. await model.expectScreen(ScreenNames.InitLogin); }); diff --git a/packages/tests-e2e/src/complete/utils/externalauth.ts b/packages/tests-e2e/src/complete/utils/externalauth.ts new file mode 100644 index 000000000..23e86f7c8 --- /dev/null +++ b/packages/tests-e2e/src/complete/utils/externalauth.ts @@ -0,0 +1,107 @@ +import type { Page } from '@playwright/test'; +import { expect } from '@playwright/test'; +import { generateToken } from 'node-2fa'; + +export const googleLogin = async (page: Page, gmail: string, password: string, secret: string) => { + await expect(page.getByRole('heading', { level: 1 })).toHaveText('Sign in'); + const idBox = page.getByLabel('Email or phone'); + await idBox.click(); + await idBox.fill(gmail); + await page.getByRole('button', { name: 'Next' }).click(); + + await expect(page.getByRole('heading', { level: 1 })).toHaveText('Welcome'); + const pwBox = page.getByLabel('Enter your password'); + await pwBox.click(); + await pwBox.fill(password); + await page.getByRole('button', { name: 'Next' }).click(); + + await expect(page.getByRole('heading', { level: 1 })).toHaveText('2-Step Verification'); + const codeBox = page.getByLabel('Enter code'); + await codeBox.click(); + const firstTOTP = generateTOTP(secret); + await codeBox.fill(firstTOTP); + await page.getByRole('button', { name: 'Next' }).click(); + try { + await page.getByRole('button', { name: 'Compose' }).waitFor(); + return; + } catch { + // TOTP failed, so the code must've been used during previous login. + // Wait for the next code. + const nextTOTP = await generateNextTOTP(firstTOTP, secret); + await codeBox.fill(nextTOTP); + await page.getByRole('button', { name: 'Next' }).click(); + await expect(page.getByRole('button', { name: 'Compose' })).toBeVisible(); + } +}; + +const generateNextTOTP = async (previousTOTP: string, secret: string) => { + const currentTOTP = generateTOTP(secret); + if (currentTOTP !== previousTOTP) { + return currentTOTP; + } + const timestamp = Math.floor(Date.now() / 1000); + console.log(timestamp); + const timeWindow = timestamp % 30; + console.log(timeWindow); + const waitTime = (30 - timeWindow) * 1000 + 1000; + console.log(waitTime); + await new Promise(resolve => setTimeout(resolve, waitTime)); + console.log(Math.floor(Date.now() / 1000)); + return generateTOTP(secret); +}; + +const generateTOTP = (secret: string) => { + console.log("Secret:", secret); + const result = generateToken(secret); + console.log("Result from generateToken:", result); + expect(result).not.toBeNull(); + + return result!.token; +}; + +export const getEmailOtpCode = async (page: Page, projectName = 'Corbado', loggedIn = false, gmail: string, password: string, secret: string) => { + if (loggedIn) { + // Wait for OTP code to arrive + await page.waitForTimeout(7000); + } + + const gmailPage = await page.context().newPage(); + await gmailPage.goto('https://mail.google.com'); + + if (!loggedIn) { + await googleLogin(gmailPage, gmail, password, secret); + } + + const inboxEntry = gmailPage.getByRole('link', { name: `is your ${projectName}` }).first(); + const emailTitle = await inboxEntry.innerText(); + + await gmailPage.close(); + + return emailTitle.split(' ')[0]; +} + +export const socialLogin = async (page: Page, gmail: string, password: string, secret: string) => { + const gmailPage = await page.context().newPage(); + await gmailPage.goto('https://mail.google.com'); + + await googleLogin(gmailPage, gmail, password, secret); + await gmailPage.close(); + + await page.getByRole('button', { name: 'Continue with Google' }).click(); + await expect(page.getByRole('heading')).toHaveText('Choose an account'); + + await page.getByRole('button', { name: 'Corbado Systemtest' }).click(); + await expect(page.getByRole('heading')).toHaveText('corbado-staging.io wants to access your Google Account'); + + await page.getByRole('button', { name: 'Allow' }).click(); +}; + +export const repeatSocialLogin = async (page: Page) => { + await page.getByRole('button', { name: 'Continue with Google' }).click(); + await expect(page.getByRole('heading')).toHaveText('Choose an account'); + + await page.getByRole('button', { name: 'Corbado Systemtest' }).click(); + await expect(page.getByRole('heading')).toHaveText('corbado-staging.io wants to access your Google Account'); + + await page.getByRole('button', { name: 'Allow' }).click(); +} From 198e2c508e562ab03d421e1b8bbc5855652506a5 Mon Sep 17 00:00:00 2001 From: aehnh Date: Tue, 11 Feb 2025 14:16:57 +0100 Subject: [PATCH 2/8] prettier --- .../src/complete/utils/externalauth.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/tests-e2e/src/complete/utils/externalauth.ts b/packages/tests-e2e/src/complete/utils/externalauth.ts index 23e86f7c8..bcdd10c99 100644 --- a/packages/tests-e2e/src/complete/utils/externalauth.ts +++ b/packages/tests-e2e/src/complete/utils/externalauth.ts @@ -51,15 +51,22 @@ const generateNextTOTP = async (previousTOTP: string, secret: string) => { }; const generateTOTP = (secret: string) => { - console.log("Secret:", secret); + console.log('Secret:', secret); const result = generateToken(secret); - console.log("Result from generateToken:", result); + console.log('Result from generateToken:', result); expect(result).not.toBeNull(); return result!.token; }; -export const getEmailOtpCode = async (page: Page, projectName = 'Corbado', loggedIn = false, gmail: string, password: string, secret: string) => { +export const getEmailOtpCode = async ( + page: Page, + projectName = 'Corbado', + loggedIn = false, + gmail: string, + password: string, + secret: string, +) => { if (loggedIn) { // Wait for OTP code to arrive await page.waitForTimeout(7000); @@ -78,7 +85,7 @@ export const getEmailOtpCode = async (page: Page, projectName = 'Corbado', logge await gmailPage.close(); return emailTitle.split(' ')[0]; -} +}; export const socialLogin = async (page: Page, gmail: string, password: string, secret: string) => { const gmailPage = await page.context().newPage(); @@ -104,4 +111,4 @@ export const repeatSocialLogin = async (page: Page) => { await expect(page.getByRole('heading')).toHaveText('corbado-staging.io wants to access your Google Account'); await page.getByRole('button', { name: 'Allow' }).click(); -} +}; From f06d2bd2b183ceace475b13e0612f498a67220ac Mon Sep 17 00:00:00 2001 From: aehnh Date: Tue, 11 Feb 2025 14:20:58 +0100 Subject: [PATCH 3/8] update workflow env vars --- .../workflows/deploy-playground-and-test.yml | 7 +++---- .github/workflows/test-all.yml | 21 ++++++++----------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/.github/workflows/deploy-playground-and-test.yml b/.github/workflows/deploy-playground-and-test.yml index d88c8bd94..cd3f649d0 100644 --- a/.github/workflows/deploy-playground-and-test.yml +++ b/.github/workflows/deploy-playground-and-test.yml @@ -182,10 +182,9 @@ jobs: env: PLAYWRIGHT_NUM_CORES: 4 PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} - PLAYWRIGHT_MICROSOFT_EMAIL: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL }} - PLAYWRIGHT_MICROSOFT_EMAIL_LINKED: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL_LINKED }} - PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED }} - PLAYWRIGHT_MICROSOFT_PASSWORD: ${{ secrets.PLAYWRIGHT_MICROSOFT_PASSWORD }} + PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }} + PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }} + PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secret.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} GITHUB_RUN_ID: ${{ github.run_id }} SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} GITHUB_BRANCH_NAME: ${{ github.ref_name }} diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 52941c765..2b2cb6d88 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -90,10 +90,9 @@ jobs: env: PLAYWRIGHT_NUM_CORES: 4 PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} - PLAYWRIGHT_MICROSOFT_EMAIL: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL }} - PLAYWRIGHT_MICROSOFT_EMAIL_LINKED: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL_LINKED }} - PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED }} - PLAYWRIGHT_MICROSOFT_PASSWORD: ${{ secrets.PLAYWRIGHT_MICROSOFT_PASSWORD }} + PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }} + PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }} + PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secret.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} GITHUB_RUN_ID: ${{ github.run_id }} SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} GITHUB_BRANCH_NAME: ${{ env.BRANCH_NAME_RAW }} @@ -138,10 +137,9 @@ jobs: env: PLAYWRIGHT_NUM_CORES: 4 PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} - PLAYWRIGHT_MICROSOFT_EMAIL: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL }} - PLAYWRIGHT_MICROSOFT_EMAIL_LINKED: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL_LINKED }} - PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED }} - PLAYWRIGHT_MICROSOFT_PASSWORD: ${{ secrets.PLAYWRIGHT_MICROSOFT_PASSWORD }} + PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }} + PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }} + PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secret.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} GITHUB_RUN_ID: ${{ github.run_id }} SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} GITHUB_BRANCH_NAME: ${{ env.BRANCH_NAME_RAW }} @@ -186,10 +184,9 @@ jobs: env: PLAYWRIGHT_NUM_CORES: 4 PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} - PLAYWRIGHT_MICROSOFT_EMAIL: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL }} - PLAYWRIGHT_MICROSOFT_EMAIL_LINKED: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL_LINKED }} - PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED: ${{ secrets.PLAYWRIGHT_MICROSOFT_EMAIL_UNLINKED }} - PLAYWRIGHT_MICROSOFT_PASSWORD: ${{ secrets.PLAYWRIGHT_MICROSOFT_PASSWORD }} + PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }} + PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }} + PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secret.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} GITHUB_RUN_ID: ${{ github.run_id }} SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} GITHUB_BRANCH_NAME: ${{ env.BRANCH_NAME_RAW }} From 22c4948ba356c61d01b09c52de7d3d552990b7b1 Mon Sep 17 00:00:00 2001 From: aehnh Date: Tue, 11 Feb 2025 14:38:05 +0100 Subject: [PATCH 4/8] clean up microsoft social login related code/data --- packages/tests-e2e/.env.complete.example | 6 ++-- .../LoginInitBlockModel.ts | 9 ------ .../models/corbado-auth-blocks/socialLogin.ts | 30 ------------------- 3 files changed, 3 insertions(+), 42 deletions(-) delete mode 100644 packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts diff --git a/packages/tests-e2e/.env.complete.example b/packages/tests-e2e/.env.complete.example index 430ecb9cf..7b0d36135 100644 --- a/packages/tests-e2e/.env.complete.example +++ b/packages/tests-e2e/.env.complete.example @@ -3,6 +3,6 @@ PLAYWRIGHT_TEST_URL=http://localhost:3000 DEVELOPERPANEL_API_URL=https://console.cloud.corbado-staging.io BACKEND_API_URL=https://backendapi.cloud.corbado-staging.io FRONTEND_API_URL_SUFFIX= -PLAYWRIGHT_JWT_TOKEN= -PLAYWRIGHT_MICROSOFT_EMAIL= -PLAYWRIGHT_MICROSOFT_PASSWORD= +PLAYWRIGHT_GOOGLE_EMAIL= +PLAYWRIGHT_GOOGLE_PASSWORD= +PLAYWRIGHT_GOOGLE_TOTP_SECRET= diff --git a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts index b49bfd395..0396a3caf 100644 --- a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts +++ b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts @@ -2,7 +2,6 @@ import type { Page } from '@playwright/test'; import { expect } from '@playwright/test'; import type { SocialProviderType } from '../../utils/constants'; -import { repeatSocialLogin, socialLoginDeprecated } from './socialLogin'; import { socialLogin } from '../../utils/externalauth'; export class LoginInitBlockModel { @@ -44,14 +43,6 @@ export class LoginInitBlockModel { await socialLogin(this.page, email, password, secret); } - async submitSocialMicrosoft(email: string, password: string) { - await socialLoginDeprecated(this.page, email, password); - } - - async resubmitSocialMicrosoft() { - await repeatSocialLogin(this.page); - } - submitPasskeyButton() { return this.page.locator('.cb-last-identifier').click(); } diff --git a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts deleted file mode 100644 index ccc2e0825..000000000 --- a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { Page } from '@playwright/test'; -import { expect } from '@playwright/test'; - -export const socialLoginDeprecated = 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.getByTestId('textButtonContainer').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(); -}; From 2b6f487de090e63d7d7d50a93e5da8b6e111d667 Mon Sep 17 00:00:00 2001 From: aehnh Date: Tue, 11 Feb 2025 14:41:25 +0100 Subject: [PATCH 5/8] fix workflow file --- .github/workflows/deploy-playground-and-test.yml | 2 +- .github/workflows/test-all.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-playground-and-test.yml b/.github/workflows/deploy-playground-and-test.yml index cd3f649d0..b5011e637 100644 --- a/.github/workflows/deploy-playground-and-test.yml +++ b/.github/workflows/deploy-playground-and-test.yml @@ -184,7 +184,7 @@ jobs: PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }} PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }} - PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secret.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} + PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secrets.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} GITHUB_RUN_ID: ${{ github.run_id }} SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} GITHUB_BRANCH_NAME: ${{ github.ref_name }} diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 2b2cb6d88..58eef61e6 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -92,7 +92,7 @@ jobs: PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }} PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }} - PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secret.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} + PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secrets.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} GITHUB_RUN_ID: ${{ github.run_id }} SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} GITHUB_BRANCH_NAME: ${{ env.BRANCH_NAME_RAW }} @@ -139,7 +139,7 @@ jobs: PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }} PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }} - PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secret.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} + PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secrets.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} GITHUB_RUN_ID: ${{ github.run_id }} SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} GITHUB_BRANCH_NAME: ${{ env.BRANCH_NAME_RAW }} @@ -186,7 +186,7 @@ jobs: PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }} PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }} - PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secret.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} + PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secrets.PLAYWRIGHT_GOOGLE_TOTP_SECRET }} GITHUB_RUN_ID: ${{ github.run_id }} SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} GITHUB_BRANCH_NAME: ${{ env.BRANCH_NAME_RAW }} From 05f345a9c51c9b65963aa9ffd527c3e533096cc5 Mon Sep 17 00:00:00 2001 From: aehnh Date: Tue, 11 Feb 2025 15:14:32 +0100 Subject: [PATCH 6/8] add workflow links to cloudwatch log --- .github/workflows/deploy-playground-and-test.yml | 4 ++-- .github/workflows/test-all.yml | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy-playground-and-test.yml b/.github/workflows/deploy-playground-and-test.yml index b5011e637..f71646042 100644 --- a/.github/workflows/deploy-playground-and-test.yml +++ b/.github/workflows/deploy-playground-and-test.yml @@ -210,7 +210,7 @@ jobs: TIME=$(xmllint --xpath 'string(/testsuites/@time)' test-results/results.xml) PASSED=$((TESTS - FAILURES - ERRORS - SKIPPED)) FAILED=$((FAILURES + ERRORS)) - SUMMARY="[Test Result] application=complete platform=react run_type=commitly execution_time=$TIME passed=$PASSED failed=$FAILED" + SUMMARY="[Test Result] application=complete platform=react run_type=commitly execution_time=$TIME passed=$PASSED failed=$FAILED link=https://github.com/corbado/javascript/actions/runs/${GITHUB_RUN_ID}" TIMESTAMP=$(date +%s000) LOG_EVENT_JSON="[{\"timestamp\":$TIMESTAMP,\"message\":\"$SUMMARY\"}]" aws logs put-log-events --log-group-name "test-results-board" --log-stream-name "$LOG_STREAM_NAME" --log-events "$LOG_EVENT_JSON" @@ -256,7 +256,7 @@ jobs: TIME=$(xmllint --xpath 'string(/testsuites/@time)' test-results/results.xml) PASSED=$((TESTS - FAILURES - ERRORS - SKIPPED)) FAILED=$((FAILURES + ERRORS)) - SUMMARY="[Test Result] application=connect platform=react run_type=commitly execution_time=$TIME passed=$PASSED failed=$FAILED" + SUMMARY="[Test Result] application=connect platform=react run_type=commitly execution_time=$TIME passed=$PASSED failed=$FAILED link=https://github.com/corbado/javascript/actions/runs/${GITHUB_RUN_ID}" TIMESTAMP=$(date +%s000) LOG_EVENT_JSON="[{\"timestamp\":$TIMESTAMP,\"message\":\"$SUMMARY\"}]" aws logs put-log-events --log-group-name "test-results-board" --log-stream-name "$LOG_STREAM_NAME" --log-events "$LOG_EVENT_JSON" diff --git a/.github/workflows/test-all.yml b/.github/workflows/test-all.yml index 58eef61e6..891642224 100644 --- a/.github/workflows/test-all.yml +++ b/.github/workflows/test-all.yml @@ -118,7 +118,7 @@ jobs: TIME=$(xmllint --xpath 'string(/testsuites/@time)' test-results/results.xml) PASSED=$((TESTS - FAILURES - ERRORS - SKIPPED)) FAILED=$((FAILURES + ERRORS)) - SUMMARY="[Test Result] application=complete platform=react run_type=nightly execution_time=$TIME passed=$PASSED failed=$FAILED" + SUMMARY="[Test Result] application=complete platform=react run_type=nightly execution_time=$TIME passed=$PASSED failed=$FAILED link=https://github.com/corbado/javascript/actions/runs/${GITHUB_RUN_ID}" TIMESTAMP=$(date +%s000) LOG_EVENT_JSON="[{\"timestamp\":$TIMESTAMP,\"message\":\"$SUMMARY\"}]" aws logs put-log-events --log-group-name "test-results-board" --log-stream-name "$LOG_STREAM_NAME" --log-events "$LOG_EVENT_JSON" @@ -165,7 +165,7 @@ jobs: TIME=$(xmllint --xpath 'string(/testsuites/@time)' test-results/results.xml) PASSED=$((TESTS - FAILURES - ERRORS - SKIPPED)) FAILED=$((FAILURES + ERRORS)) - SUMMARY="[Test Result] application=complete platform=web-js run_type=nightly execution_time=$TIME passed=$PASSED failed=$FAILED" + SUMMARY="[Test Result] application=complete platform=web-js run_type=nightly execution_time=$TIME passed=$PASSED failed=$FAILED link=https://github.com/corbado/javascript/actions/runs/${GITHUB_RUN_ID}" TIMESTAMP=$(date +%s000) LOG_EVENT_JSON="[{\"timestamp\":$TIMESTAMP,\"message\":\"$SUMMARY\"}]" aws logs put-log-events --log-group-name "test-results-board" --log-stream-name "$LOG_STREAM_NAME" --log-events "$LOG_EVENT_JSON" @@ -212,7 +212,7 @@ jobs: TIME=$(xmllint --xpath 'string(/testsuites/@time)' test-results/results.xml) PASSED=$((TESTS - FAILURES - ERRORS - SKIPPED)) FAILED=$((FAILURES + ERRORS)) - SUMMARY="[Test Result] application=complete platform=web-js-script run_type=nightly execution_time=$TIME passed=$PASSED failed=$FAILED" + SUMMARY="[Test Result] application=complete platform=web-js-script run_type=nightly execution_time=$TIME passed=$PASSED failed=$FAILED link=https://github.com/corbado/javascript/actions/runs/${GITHUB_RUN_ID}" TIMESTAMP=$(date +%s000) LOG_EVENT_JSON="[{\"timestamp\":$TIMESTAMP,\"message\":\"$SUMMARY\"}]" aws logs put-log-events --log-group-name "test-results-board" --log-stream-name "$LOG_STREAM_NAME" --log-events "$LOG_EVENT_JSON" @@ -258,7 +258,7 @@ jobs: TIME=$(xmllint --xpath 'string(/testsuites/@time)' test-results/results.xml) PASSED=$((TESTS - FAILURES - ERRORS - SKIPPED)) FAILED=$((FAILURES + ERRORS)) - SUMMARY="[Test Result] application=connect platform=react run_type=nightly execution_time=$TIME passed=$PASSED failed=$FAILED" + SUMMARY="[Test Result] application=connect platform=react run_type=nightly execution_time=$TIME passed=$PASSED failed=$FAILED link=https://github.com/corbado/javascript/actions/runs/${GITHUB_RUN_ID}" TIMESTAMP=$(date +%s000) LOG_EVENT_JSON="[{\"timestamp\":$TIMESTAMP,\"message\":\"$SUMMARY\"}]" aws logs put-log-events --log-group-name "test-results-board" --log-stream-name "$LOG_STREAM_NAME" --log-events "$LOG_EVENT_JSON" From 7b3dacc69de3e5ca1cf7da217ef23e43ec2daeb1 Mon Sep 17 00:00:00 2001 From: aehnh Date: Tue, 11 Feb 2025 16:21:48 +0100 Subject: [PATCH 7/8] increase total test timeout for social tests --- .../complete/scenarios/corbado-auth-general/socials.spec.ts | 3 ++- packages/tests-e2e/src/complete/utils/constants.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts index c62e1a283..1d24627b5 100644 --- a/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts +++ b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts @@ -5,7 +5,7 @@ import { IdentifierVerification, ScreenNames, socialOperationTimeout, - SocialProviderType, + SocialProviderType, socialTotalTimeout, } from '../../utils/constants'; import { createProjectNew, @@ -19,6 +19,7 @@ test.describe('social logins', () => { let projectId: string; // Microsoft social login requires longer timeout + test.describe.configure({ timeout: socialTotalTimeout }); test.use({ actionTimeout: socialOperationTimeout, navigationTimeout: socialOperationTimeout, diff --git a/packages/tests-e2e/src/complete/utils/constants.ts b/packages/tests-e2e/src/complete/utils/constants.ts index 8784af2bd..e348e74fd 100644 --- a/packages/tests-e2e/src/complete/utils/constants.ts +++ b/packages/tests-e2e/src/complete/utils/constants.ts @@ -56,6 +56,7 @@ export const emailLinkUrlToken = 'UaTwjBJwyDLMGVbR7WHh'; export const totalTimeout = process.env.CI ? 30000 : 40000; export const operationTimeout = process.env.CI ? 5000 : 7000; +export const socialTotalTimeout = 45000; export const socialOperationTimeout = 10000; export const waitAfterLoad = 600; // timeout to reduce flakiness due to repetitive reloads From 400453c06cd8358de47bbae16369da21598f6713 Mon Sep 17 00:00:00 2001 From: aehnh Date: Tue, 11 Feb 2025 17:01:34 +0100 Subject: [PATCH 8/8] prettier --- .../complete/scenarios/corbado-auth-general/socials.spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts index 1d24627b5..b6e880355 100644 --- a/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts +++ b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts @@ -5,7 +5,8 @@ import { IdentifierVerification, ScreenNames, socialOperationTimeout, - SocialProviderType, socialTotalTimeout, + SocialProviderType, + socialTotalTimeout, } from '../../utils/constants'; import { createProjectNew,