From cbeedfce13d8b288faa53b325716906035b3240a Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 18 Dec 2024 15:29:18 +0100 Subject: [PATCH 01/10] reorganize test directory --- .github/workflows/e2e-test-commitly.yml | 2 +- .github/workflows/e2e-test-nightly.yml | 6 +- package-lock.json | 120 ++++++++++++++++++ packages/tests-e2e/README.md | 4 +- packages/tests-e2e/package.json | 3 +- ...ig.ui.ts => playwright.config.complete.ts} | 15 ++- .../tests-e2e/playwright.config.connect.ts | 67 ++++++++++ .../{ => complete}/fixtures/CorbadoAuth.ts | 0 .../{ => complete}/fixtures/PasskeyList.ts | 0 .../{ => complete}/models/CorbadoAuthModel.ts | 0 .../{ => complete}/models/PasskeyListModel.ts | 0 .../EmailVerifyBlockModel.ts | 0 .../LoginInitBlockModel.ts | 0 .../PasskeyAppendBlockModel.ts | 0 .../PasskeyVerifyBlockModel.ts | 0 .../PhoneVerifyBlockModel.ts | 0 .../SignupInitBlockModel.ts | 0 .../corbado-auth-blocks/expectScreen.ts | 0 .../models/corbado-auth-blocks/socialLogin.ts | 0 .../models/utils/VirtualAuthenticator.ts | 0 ...il-username-verification-at-signup.spec.ts | 0 .../email-verification-at-login.spec.ts | 0 .../email-verification-at-signup.spec.ts | 0 .../email-verification-none.spec.ts | 0 .../phone-verification-at-signup.spec.ts | 0 .../username.spec.ts | 0 .../email-link-verify-obfuscation.spec.ts | 0 .../email-otp-verify-general.spec.ts | 0 .../login-init-email.spec.ts | 0 .../login-init-no-public-signup.spec.ts | 0 .../phone-otp-verify-obfuscation.spec.ts | 0 .../corbado-auth-general/routing.spec.ts | 0 .../corbado-auth-general/signup-init.spec.ts | 0 .../corbado-auth-general/socials.spec.ts | 0 .../passkey-list-general/general.spec.ts | 0 .../src/{ => complete}/utils/constants.ts | 0 .../{ => complete}/utils/developerpanel.ts | 0 .../src/{ => complete}/utils/random.ts | 0 .../tests-e2e/src/connect/utils/constants.ts | 3 + 39 files changed, 206 insertions(+), 14 deletions(-) rename packages/tests-e2e/{playwright.config.ui.ts => playwright.config.complete.ts} (85%) create mode 100644 packages/tests-e2e/playwright.config.connect.ts rename packages/tests-e2e/src/{ => complete}/fixtures/CorbadoAuth.ts (100%) rename packages/tests-e2e/src/{ => complete}/fixtures/PasskeyList.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/CorbadoAuthModel.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/PasskeyListModel.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/corbado-auth-blocks/EmailVerifyBlockModel.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/corbado-auth-blocks/LoginInitBlockModel.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/corbado-auth-blocks/PasskeyAppendBlockModel.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/corbado-auth-blocks/PasskeyVerifyBlockModel.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/corbado-auth-blocks/PhoneVerifyBlockModel.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/corbado-auth-blocks/SignupInitBlockModel.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/corbado-auth-blocks/expectScreen.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/corbado-auth-blocks/socialLogin.ts (100%) rename packages/tests-e2e/src/{ => complete}/models/utils/VirtualAuthenticator.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-component-configs/email-username-verification-at-signup.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-component-configs/email-verification-at-login.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-component-configs/email-verification-at-signup.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-component-configs/email-verification-none.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-component-configs/phone-verification-at-signup.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-component-configs/username.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-general/email-link-verify-obfuscation.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-general/email-otp-verify-general.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-general/login-init-email.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-general/login-init-no-public-signup.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-general/phone-otp-verify-obfuscation.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-general/routing.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-general/signup-init.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/corbado-auth-general/socials.spec.ts (100%) rename packages/tests-e2e/src/{ui => complete/scenarios}/passkey-list-general/general.spec.ts (100%) rename packages/tests-e2e/src/{ => complete}/utils/constants.ts (100%) rename packages/tests-e2e/src/{ => complete}/utils/developerpanel.ts (100%) rename packages/tests-e2e/src/{ => complete}/utils/random.ts (100%) create mode 100644 packages/tests-e2e/src/connect/utils/constants.ts diff --git a/.github/workflows/e2e-test-commitly.yml b/.github/workflows/e2e-test-commitly.yml index b0b70b2a0..9c58dd2aa 100644 --- a/.github/workflows/e2e-test-commitly.yml +++ b/.github/workflows/e2e-test-commitly.yml @@ -70,7 +70,7 @@ jobs: cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') export PLAYWRIGHT_TEST_URL="https://$BRANCH_NAME.react.playground.corbado.io" - PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.ui.ts + PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.complete.ts env: PLAYWRIGHT_NUM_CORES: 4 PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} diff --git a/.github/workflows/e2e-test-nightly.yml b/.github/workflows/e2e-test-nightly.yml index a1f06dd59..213f5366b 100644 --- a/.github/workflows/e2e-test-nightly.yml +++ b/.github/workflows/e2e-test-nightly.yml @@ -69,7 +69,7 @@ jobs: cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') export PLAYWRIGHT_TEST_URL="https://$BRANCH_NAME.react.playground.corbado.io" - PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.ui.ts + PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.complete.ts env: PLAYWRIGHT_NUM_CORES: 4 PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} @@ -93,7 +93,7 @@ jobs: cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') export PLAYWRIGHT_TEST_URL="https://$BRANCH_NAME.web-js.playground.corbado.io" - PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.ui.ts + PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.complete.ts env: PLAYWRIGHT_NUM_CORES: 4 PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} @@ -117,7 +117,7 @@ jobs: cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') export PLAYWRIGHT_TEST_URL="https://$BRANCH_NAME.web-js-script.playground.corbado.io" - PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.ui.ts + PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.complete.ts env: PLAYWRIGHT_NUM_CORES: 4 PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }} diff --git a/package-lock.json b/package-lock.json index bff40f5f8..068058084 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27360,6 +27360,126 @@ "devDependencies": { "dotenv-webpack": "^8.0.1" } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz", + "integrity": "sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz", + "integrity": "sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz", + "integrity": "sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz", + "integrity": "sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz", + "integrity": "sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz", + "integrity": "sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz", + "integrity": "sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz", + "integrity": "sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } } } diff --git a/packages/tests-e2e/README.md b/packages/tests-e2e/README.md index 7cbb7412c..78fbe14ee 100644 --- a/packages/tests-e2e/README.md +++ b/packages/tests-e2e/README.md @@ -31,13 +31,13 @@ Now Playwright is ready to test the local Playground deployment. ```console $ cd packages/tests-e2e -$ npx playwright test --config=playwright.config.ui.ts --ui --project=nightly +$ npx playwright test --config=playwright.config.complete.ts --ui --project=nightly ``` ### From CLI ```console -npx playwright test --config=playwright.config.ui.ts --project=nightly +npx playwright test --config=playwright.config.complete.ts --project=nightly ``` Alternatively, you can do: diff --git a/packages/tests-e2e/package.json b/packages/tests-e2e/package.json index 6cbd6bce9..62a86f6b2 100644 --- a/packages/tests-e2e/package.json +++ b/packages/tests-e2e/package.json @@ -12,7 +12,8 @@ "url": "git+https://github.com/corbado/javascript.git" }, "scripts": { - "e2e:ui": "playwright test --config=playwright.config.ui.ts", + "e2e:complete": "playwright test --config=playwright.config.complete.ts", + "e2e:connect": "playwright test --config=playwright.config.connect.ts", "e2e:report": "npx playwright show-report" }, "bugs": { diff --git a/packages/tests-e2e/playwright.config.ui.ts b/packages/tests-e2e/playwright.config.complete.ts similarity index 85% rename from packages/tests-e2e/playwright.config.ui.ts rename to packages/tests-e2e/playwright.config.complete.ts index 67e90dec3..08e9016b2 100644 --- a/packages/tests-e2e/playwright.config.ui.ts +++ b/packages/tests-e2e/playwright.config.complete.ts @@ -2,7 +2,7 @@ import { defineConfig } from '@playwright/test'; import dotenv from 'dotenv'; import path from 'path'; -import { operationTimeout, totalTimeout } from './src/utils/constants'; +import { operationTimeout, totalTimeout } from './src/complete/utils/constants'; if (process.env.CI) { // I have no idea why process.env.PLAYWRIGHT_PROJECT_ID is set as the value in .env.local before @@ -14,7 +14,7 @@ if (process.env.CI) { } export default defineConfig({ - testDir: './src', + testDir: './src/complete', // fullyParallel: true, forbidOnly: !!process.env.CI, retries: 4, @@ -31,7 +31,7 @@ export default defineConfig({ [ '../../node_modules/playwright-slack-report/dist/src/SlackReporter.js', { - channels: ['corbado-javascript-tests'], + channels: ['corbado-tests'], sendResults: 'always', showInThread: true, meta: [ @@ -53,21 +53,22 @@ export default defineConfig({ actionTimeout: operationTimeout, // default: none navigationTimeout: operationTimeout, // default: none baseURL: process.env.PLAYWRIGHT_TEST_URL, - trace: 'retain-on-failure', screenshot: 'only-on-failure', + video: 'retain-on-failure', + trace: 'retain-on-failure', }, projects: [ { name: 'corbado-auth-general', - testMatch: ['ui/corbado-auth-general/*.ts'], + testMatch: ['scenarios/corbado-auth-general/*.ts'], }, { name: 'corbado-auth-component-configs', - testMatch: ['ui/corbado-auth-component-configs/*.ts'], + testMatch: ['scenarios/corbado-auth-component-configs/*.ts'], }, { name: 'passkey-list-general', - testMatch: ['ui/passkey-list-general/*.ts'], + testMatch: ['scenarios/passkey-list-general/*.ts'], }, ], }); diff --git a/packages/tests-e2e/playwright.config.connect.ts b/packages/tests-e2e/playwright.config.connect.ts new file mode 100644 index 000000000..8c9ff11c7 --- /dev/null +++ b/packages/tests-e2e/playwright.config.connect.ts @@ -0,0 +1,67 @@ +import { defineConfig } from '@playwright/test'; +import dotenv from 'dotenv'; +import path from 'path'; + +import { operationTimeout, totalTimeout } from './src/connect/utils/constants'; + +if (process.env.CI) { + dotenv.config({ path: path.resolve(__dirname, '.env.ci'), override: true }); +} else { + dotenv.config({ path: path.resolve(__dirname, '.env.local'), override: true }); +} + +export default defineConfig({ + testDir: './src/connect', + // fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: 4, + workers: process.env.CI + ? process.env.PLAYWRIGHT_NUM_CORES + ? parseInt(process.env.PLAYWRIGHT_NUM_CORES, 10) - 1 + : undefined + : undefined, + reporter: [ + [ + '../../node_modules/playwright-slack-report/dist/src/SlackReporter.js', + { + channels: ['corbado-tests'], + sendResults: 'always', + showInThread: true, + meta: [ + { + key: 'Test Run Info', + value: `https://github.com/corbado/javascript/actions/runs/${process.env.GITHUB_RUN_ID}`, + }, + { key: 'branch', value: `${process.env.GITHUB_BRANCH_NAME}` }, + ], + }, + ], + ['html'], + ], + timeout: totalTimeout, // default: 30000ms + expect: { + timeout: operationTimeout, // default: 5000ms + }, + use: { + actionTimeout: operationTimeout, // default: none + navigationTimeout: operationTimeout, // default: none + baseURL: process.env.PLAYWRIGHT_TEST_URL, + screenshot: 'only-on-failure', + video: 'retain-on-failure', + trace: 'retain-on-failure', + }, + projects: [ + { + name: 'corbado-auth-general', + testMatch: ['scenarios/corbado-auth-general/*.ts'], + }, + { + name: 'corbado-auth-component-configs', + testMatch: ['scenarios/corbado-auth-component-configs/*.ts'], + }, + { + name: 'passkey-list-general', + testMatch: ['scenarios/passkey-list-general/*.ts'], + }, + ], +}); diff --git a/packages/tests-e2e/src/fixtures/CorbadoAuth.ts b/packages/tests-e2e/src/complete/fixtures/CorbadoAuth.ts similarity index 100% rename from packages/tests-e2e/src/fixtures/CorbadoAuth.ts rename to packages/tests-e2e/src/complete/fixtures/CorbadoAuth.ts diff --git a/packages/tests-e2e/src/fixtures/PasskeyList.ts b/packages/tests-e2e/src/complete/fixtures/PasskeyList.ts similarity index 100% rename from packages/tests-e2e/src/fixtures/PasskeyList.ts rename to packages/tests-e2e/src/complete/fixtures/PasskeyList.ts diff --git a/packages/tests-e2e/src/models/CorbadoAuthModel.ts b/packages/tests-e2e/src/complete/models/CorbadoAuthModel.ts similarity index 100% rename from packages/tests-e2e/src/models/CorbadoAuthModel.ts rename to packages/tests-e2e/src/complete/models/CorbadoAuthModel.ts diff --git a/packages/tests-e2e/src/models/PasskeyListModel.ts b/packages/tests-e2e/src/complete/models/PasskeyListModel.ts similarity index 100% rename from packages/tests-e2e/src/models/PasskeyListModel.ts rename to packages/tests-e2e/src/complete/models/PasskeyListModel.ts diff --git a/packages/tests-e2e/src/models/corbado-auth-blocks/EmailVerifyBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/EmailVerifyBlockModel.ts similarity index 100% rename from packages/tests-e2e/src/models/corbado-auth-blocks/EmailVerifyBlockModel.ts rename to packages/tests-e2e/src/complete/models/corbado-auth-blocks/EmailVerifyBlockModel.ts diff --git a/packages/tests-e2e/src/models/corbado-auth-blocks/LoginInitBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts similarity index 100% rename from packages/tests-e2e/src/models/corbado-auth-blocks/LoginInitBlockModel.ts rename to packages/tests-e2e/src/complete/models/corbado-auth-blocks/LoginInitBlockModel.ts diff --git a/packages/tests-e2e/src/models/corbado-auth-blocks/PasskeyAppendBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/PasskeyAppendBlockModel.ts similarity index 100% rename from packages/tests-e2e/src/models/corbado-auth-blocks/PasskeyAppendBlockModel.ts rename to packages/tests-e2e/src/complete/models/corbado-auth-blocks/PasskeyAppendBlockModel.ts diff --git a/packages/tests-e2e/src/models/corbado-auth-blocks/PasskeyVerifyBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/PasskeyVerifyBlockModel.ts similarity index 100% rename from packages/tests-e2e/src/models/corbado-auth-blocks/PasskeyVerifyBlockModel.ts rename to packages/tests-e2e/src/complete/models/corbado-auth-blocks/PasskeyVerifyBlockModel.ts diff --git a/packages/tests-e2e/src/models/corbado-auth-blocks/PhoneVerifyBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/PhoneVerifyBlockModel.ts similarity index 100% rename from packages/tests-e2e/src/models/corbado-auth-blocks/PhoneVerifyBlockModel.ts rename to packages/tests-e2e/src/complete/models/corbado-auth-blocks/PhoneVerifyBlockModel.ts diff --git a/packages/tests-e2e/src/models/corbado-auth-blocks/SignupInitBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/SignupInitBlockModel.ts similarity index 100% rename from packages/tests-e2e/src/models/corbado-auth-blocks/SignupInitBlockModel.ts rename to packages/tests-e2e/src/complete/models/corbado-auth-blocks/SignupInitBlockModel.ts diff --git a/packages/tests-e2e/src/models/corbado-auth-blocks/expectScreen.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/expectScreen.ts similarity index 100% rename from packages/tests-e2e/src/models/corbado-auth-blocks/expectScreen.ts rename to packages/tests-e2e/src/complete/models/corbado-auth-blocks/expectScreen.ts diff --git a/packages/tests-e2e/src/models/corbado-auth-blocks/socialLogin.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts similarity index 100% rename from packages/tests-e2e/src/models/corbado-auth-blocks/socialLogin.ts rename to packages/tests-e2e/src/complete/models/corbado-auth-blocks/socialLogin.ts diff --git a/packages/tests-e2e/src/models/utils/VirtualAuthenticator.ts b/packages/tests-e2e/src/complete/models/utils/VirtualAuthenticator.ts similarity index 100% rename from packages/tests-e2e/src/models/utils/VirtualAuthenticator.ts rename to packages/tests-e2e/src/complete/models/utils/VirtualAuthenticator.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-component-configs/email-username-verification-at-signup.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/email-username-verification-at-signup.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-component-configs/email-username-verification-at-signup.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/email-username-verification-at-signup.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-component-configs/email-verification-at-login.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/email-verification-at-login.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-component-configs/email-verification-at-login.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/email-verification-at-login.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-component-configs/email-verification-at-signup.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/email-verification-at-signup.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-component-configs/email-verification-at-signup.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/email-verification-at-signup.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-component-configs/email-verification-none.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/email-verification-none.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-component-configs/email-verification-none.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/email-verification-none.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-component-configs/phone-verification-at-signup.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/phone-verification-at-signup.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-component-configs/phone-verification-at-signup.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/phone-verification-at-signup.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-component-configs/username.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/username.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-component-configs/username.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-component-configs/username.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-general/email-link-verify-obfuscation.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/email-link-verify-obfuscation.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-general/email-link-verify-obfuscation.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-general/email-link-verify-obfuscation.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-general/email-otp-verify-general.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/email-otp-verify-general.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-general/email-otp-verify-general.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-general/email-otp-verify-general.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-general/login-init-email.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/login-init-email.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-general/login-init-email.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-general/login-init-email.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-general/login-init-no-public-signup.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/login-init-no-public-signup.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-general/login-init-no-public-signup.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-general/login-init-no-public-signup.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-general/phone-otp-verify-obfuscation.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/phone-otp-verify-obfuscation.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-general/phone-otp-verify-obfuscation.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-general/phone-otp-verify-obfuscation.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-general/routing.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/routing.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-general/routing.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-general/routing.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-general/signup-init.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/signup-init.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-general/signup-init.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-general/signup-init.spec.ts diff --git a/packages/tests-e2e/src/ui/corbado-auth-general/socials.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/corbado-auth-general/socials.spec.ts rename to packages/tests-e2e/src/complete/scenarios/corbado-auth-general/socials.spec.ts diff --git a/packages/tests-e2e/src/ui/passkey-list-general/general.spec.ts b/packages/tests-e2e/src/complete/scenarios/passkey-list-general/general.spec.ts similarity index 100% rename from packages/tests-e2e/src/ui/passkey-list-general/general.spec.ts rename to packages/tests-e2e/src/complete/scenarios/passkey-list-general/general.spec.ts diff --git a/packages/tests-e2e/src/utils/constants.ts b/packages/tests-e2e/src/complete/utils/constants.ts similarity index 100% rename from packages/tests-e2e/src/utils/constants.ts rename to packages/tests-e2e/src/complete/utils/constants.ts diff --git a/packages/tests-e2e/src/utils/developerpanel.ts b/packages/tests-e2e/src/complete/utils/developerpanel.ts similarity index 100% rename from packages/tests-e2e/src/utils/developerpanel.ts rename to packages/tests-e2e/src/complete/utils/developerpanel.ts diff --git a/packages/tests-e2e/src/utils/random.ts b/packages/tests-e2e/src/complete/utils/random.ts similarity index 100% rename from packages/tests-e2e/src/utils/random.ts rename to packages/tests-e2e/src/complete/utils/random.ts diff --git a/packages/tests-e2e/src/connect/utils/constants.ts b/packages/tests-e2e/src/connect/utils/constants.ts new file mode 100644 index 000000000..69d5a83a6 --- /dev/null +++ b/packages/tests-e2e/src/connect/utils/constants.ts @@ -0,0 +1,3 @@ +export const totalTimeout = process.env.CI ? 30000 : 40000; +export const operationTimeout = process.env.CI ? 5000 : 7000; +export const socialOperationTimeout = 10000; From 091c90d0f4fd1db4d14301eec92e9d9665da6b41 Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 18 Dec 2024 19:37:04 +0100 Subject: [PATCH 02/10] testcode structure and hooks --- .gitignore | 3 +- .../tests-e2e/{.env.ci => .env.complete.ci} | 0 .../{.env.example => .env.complete.example} | 0 packages/tests-e2e/.env.connect.ci | 3 + packages/tests-e2e/.env.connect.example | 6 ++ packages/tests-e2e/package.json | 2 + .../tests-e2e/playwright.config.complete.ts | 4 +- .../tests-e2e/playwright.config.connect.ts | 22 +++-- .../src/complete/fixtures/CorbadoAuth.ts | 2 +- .../src/complete/fixtures/PasskeyList.ts | 2 +- .../src/complete/models/PasskeyListModel.ts | 8 +- .../EmailVerifyBlockModel.ts | 2 +- .../PasskeyAppendBlockModel.ts | 4 - .../SignupInitBlockModel.ts | 4 - .../login-init-no-public-signup.spec.ts | 2 +- .../src/connect/fixtures/BaseTest.ts | 18 ++++ .../src/connect/models/AppendModel.ts | 22 +++++ .../tests-e2e/src/connect/models/BaseModel.ts | 79 ++++++++++++++++ .../src/connect/models/SIgnupModel.ts | 20 ++++ .../src/connect/scenarios/append.spec.ts | 0 .../tests-e2e/src/connect/scenarios/hooks.ts | 69 ++++++++++++++ .../src/connect/scenarios/login.spec.ts | 12 +++ .../src/connect/scenarios/misc.spec.ts | 0 .../connect/scenarios/passkey-list.spec.ts | 0 .../tests-e2e/src/connect/utils/Constants.ts | 13 +++ .../src/connect/utils/ExpectScreen.ts | 31 ++++++ .../src/connect/utils/VirtualAuthenticator.ts | 94 +++++++++++++++++++ .../tests-e2e/src/connect/utils/constants.ts | 3 - 28 files changed, 394 insertions(+), 31 deletions(-) rename packages/tests-e2e/{.env.ci => .env.complete.ci} (100%) rename packages/tests-e2e/{.env.example => .env.complete.example} (100%) create mode 100644 packages/tests-e2e/.env.connect.ci create mode 100644 packages/tests-e2e/.env.connect.example create mode 100644 packages/tests-e2e/src/connect/fixtures/BaseTest.ts create mode 100644 packages/tests-e2e/src/connect/models/AppendModel.ts create mode 100644 packages/tests-e2e/src/connect/models/BaseModel.ts create mode 100644 packages/tests-e2e/src/connect/models/SIgnupModel.ts create mode 100644 packages/tests-e2e/src/connect/scenarios/append.spec.ts create mode 100644 packages/tests-e2e/src/connect/scenarios/hooks.ts create mode 100644 packages/tests-e2e/src/connect/scenarios/login.spec.ts create mode 100644 packages/tests-e2e/src/connect/scenarios/misc.spec.ts create mode 100644 packages/tests-e2e/src/connect/scenarios/passkey-list.spec.ts create mode 100644 packages/tests-e2e/src/connect/utils/Constants.ts create mode 100644 packages/tests-e2e/src/connect/utils/ExpectScreen.ts create mode 100644 packages/tests-e2e/src/connect/utils/VirtualAuthenticator.ts delete mode 100644 packages/tests-e2e/src/connect/utils/constants.ts diff --git a/.gitignore b/.gitignore index 2449d64f2..4b08410a6 100644 --- a/.gitignore +++ b/.gitignore @@ -24,7 +24,8 @@ packages/tests-e2e/blob-report packages/tests-e2e/all-blob-reports packages/tests-e2e/playwright/.cach/ packages/tests-e2e/test-states -packages/tests-e2e/.env.local +packages/tests-e2e/.env.complete.local +packages/tests-e2e/.env.connect.local .vercel # scripts diff --git a/packages/tests-e2e/.env.ci b/packages/tests-e2e/.env.complete.ci similarity index 100% rename from packages/tests-e2e/.env.ci rename to packages/tests-e2e/.env.complete.ci diff --git a/packages/tests-e2e/.env.example b/packages/tests-e2e/.env.complete.example similarity index 100% rename from packages/tests-e2e/.env.example rename to packages/tests-e2e/.env.complete.example diff --git a/packages/tests-e2e/.env.connect.ci b/packages/tests-e2e/.env.connect.ci new file mode 100644 index 000000000..636344bea --- /dev/null +++ b/packages/tests-e2e/.env.connect.ci @@ -0,0 +1,3 @@ +DEVELOPERPANEL_API_URL=https://console.cloud.corbado-staging.io +BACKEND_API_URL=https://backendapi.cloud.corbado-staging.io +FRONTEND_API_URL_SUFFIX=frontendapi.cloud.corbado-staging.io diff --git a/packages/tests-e2e/.env.connect.example b/packages/tests-e2e/.env.connect.example new file mode 100644 index 000000000..6f5490c95 --- /dev/null +++ b/packages/tests-e2e/.env.connect.example @@ -0,0 +1,6 @@ +# save to .env.local +PLAYWRIGHT_TEST_URL=https://develop.connect-next.playground.corbado.io +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= diff --git a/packages/tests-e2e/package.json b/packages/tests-e2e/package.json index 62a86f6b2..e70418723 100644 --- a/packages/tests-e2e/package.json +++ b/packages/tests-e2e/package.json @@ -13,7 +13,9 @@ }, "scripts": { "e2e:complete": "playwright test --config=playwright.config.complete.ts", + "e2e:complete:ui": "playwright test --config=playwright.config.complete.ts --ui", "e2e:connect": "playwright test --config=playwright.config.connect.ts", + "e2e:connect:ui": "playwright test --config=playwright.config.connect.ts --ui", "e2e:report": "npx playwright show-report" }, "bugs": { diff --git a/packages/tests-e2e/playwright.config.complete.ts b/packages/tests-e2e/playwright.config.complete.ts index 08e9016b2..79f2e8140 100644 --- a/packages/tests-e2e/playwright.config.complete.ts +++ b/packages/tests-e2e/playwright.config.complete.ts @@ -8,9 +8,9 @@ if (process.env.CI) { // I have no idea why process.env.PLAYWRIGHT_PROJECT_ID is set as the value in .env.local before // this point. This environment variable is not set in the workflow file (e2e-test.yml), so the // value should theoretically be undefined. For now the 'override' option fixes the issue. - dotenv.config({ path: path.resolve(__dirname, '.env.ci'), override: true }); + dotenv.config({ path: path.resolve(__dirname, '.env.complete.ci'), override: true }); } else { - dotenv.config({ path: path.resolve(__dirname, '.env.local'), override: true }); + dotenv.config({ path: path.resolve(__dirname, '.env.complete.local'), override: true }); } export default defineConfig({ diff --git a/packages/tests-e2e/playwright.config.connect.ts b/packages/tests-e2e/playwright.config.connect.ts index 8c9ff11c7..06fbb046c 100644 --- a/packages/tests-e2e/playwright.config.connect.ts +++ b/packages/tests-e2e/playwright.config.connect.ts @@ -2,12 +2,12 @@ import { defineConfig } from '@playwright/test'; import dotenv from 'dotenv'; import path from 'path'; -import { operationTimeout, totalTimeout } from './src/connect/utils/constants'; +import { operationTimeout, totalTimeout } from './src/connect/utils/Constants'; if (process.env.CI) { - dotenv.config({ path: path.resolve(__dirname, '.env.ci'), override: true }); + dotenv.config({ path: path.resolve(__dirname, '.env.connect.ci'), override: true }); } else { - dotenv.config({ path: path.resolve(__dirname, '.env.local'), override: true }); + dotenv.config({ path: path.resolve(__dirname, '.env.connect.local'), override: true }); } export default defineConfig({ @@ -52,16 +52,20 @@ export default defineConfig({ }, projects: [ { - name: 'corbado-auth-general', - testMatch: ['scenarios/corbado-auth-general/*.ts'], + name: 'login-component', + testMatch: ['scenarios/login.spec.ts'], }, { - name: 'corbado-auth-component-configs', - testMatch: ['scenarios/corbado-auth-component-configs/*.ts'], + name: 'append-component', + testMatch: ['scenarios/append.spec.ts'], }, { - name: 'passkey-list-general', - testMatch: ['scenarios/passkey-list-general/*.ts'], + name: 'passkey-list-component', + testMatch: ['scenarios/passkey-list.spec.ts'], }, + { + name: 'misc', + testMatch: ['scenarios/misc.spec.ts'], + } ], }); diff --git a/packages/tests-e2e/src/complete/fixtures/CorbadoAuth.ts b/packages/tests-e2e/src/complete/fixtures/CorbadoAuth.ts index 30dc8e57d..2cd1edf0e 100644 --- a/packages/tests-e2e/src/complete/fixtures/CorbadoAuth.ts +++ b/packages/tests-e2e/src/complete/fixtures/CorbadoAuth.ts @@ -4,7 +4,7 @@ import { CorbadoAuthModel } from '../models/CorbadoAuthModel'; import { VirtualAuthenticator } from '../models/utils/VirtualAuthenticator'; export const test = base.extend<{ model: CorbadoAuthModel }>({ - model: async ({ page }, use, testInfo) => { + model: async ({ page }, use) => { const virtualAuthenticator = new VirtualAuthenticator(); await virtualAuthenticator.initializeCDPSession(page); diff --git a/packages/tests-e2e/src/complete/fixtures/PasskeyList.ts b/packages/tests-e2e/src/complete/fixtures/PasskeyList.ts index 7de5c51b6..3082163e7 100644 --- a/packages/tests-e2e/src/complete/fixtures/PasskeyList.ts +++ b/packages/tests-e2e/src/complete/fixtures/PasskeyList.ts @@ -4,7 +4,7 @@ import { PasskeyListModel } from '../models/PasskeyListModel'; import { VirtualAuthenticator } from '../models/utils/VirtualAuthenticator'; export const passkeyListTest = test.extend<{ model: PasskeyListModel }>({ - model: async ({ page }, use, testInfo) => { + model: async ({ page }, use) => { const virtualAuthenticator = new VirtualAuthenticator(); await virtualAuthenticator.initializeCDPSession(page); diff --git a/packages/tests-e2e/src/complete/models/PasskeyListModel.ts b/packages/tests-e2e/src/complete/models/PasskeyListModel.ts index 5e92feb95..ac14fc440 100644 --- a/packages/tests-e2e/src/complete/models/PasskeyListModel.ts +++ b/packages/tests-e2e/src/complete/models/PasskeyListModel.ts @@ -1,12 +1,12 @@ import type { Page } from '@playwright/test'; import { expect } from '@playwright/test'; -import type { VirtualAuthenticator } from './utils/VirtualAuthenticator'; -import { SignupInitBlockModel } from './corbado-auth-blocks/SignupInitBlockModel'; -import { PasskeyAppendBlockModel } from './corbado-auth-blocks/PasskeyAppendBlockModel'; +import { ScreenNames } from '../utils/constants'; // The idea of this model is to only test on PasskeyList import { EmailVerifyBlockModel, OtpCodeType } from './corbado-auth-blocks/EmailVerifyBlockModel'; import { expectScreen } from './corbado-auth-blocks/expectScreen'; -import { ScreenNames } from '../utils/constants'; // The idea of this model is to only test on PasskeyList +import { PasskeyAppendBlockModel } from './corbado-auth-blocks/PasskeyAppendBlockModel'; +import { SignupInitBlockModel } from './corbado-auth-blocks/SignupInitBlockModel'; +import type { VirtualAuthenticator } from './utils/VirtualAuthenticator'; // The idea of this model is to only test on PasskeyList // We don't want to mix the test with other components (e.g. CorbadoAuthModel) diff --git a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/EmailVerifyBlockModel.ts b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/EmailVerifyBlockModel.ts index c5fa257a6..acb6916cb 100644 --- a/packages/tests-e2e/src/complete/models/corbado-auth-blocks/EmailVerifyBlockModel.ts +++ b/packages/tests-e2e/src/complete/models/corbado-auth-blocks/EmailVerifyBlockModel.ts @@ -1,4 +1,4 @@ -import type { BrowserContext, Page } from '@playwright/test'; +import type { Page } from '@playwright/test'; import { expect } from '@playwright/test'; import type { AuthType } from '../../utils/constants'; 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 8653dc549..6c1e457e2 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 @@ -17,10 +17,6 @@ export class PasskeyAppendBlockModel { return this.page.getByRole('button', { name: 'Log in' }).click(); } - fillFullName(value: string) { - return; - } - async startPasskeyOperation(complete: boolean) { const operationTrigger = () => this.page.getByRole('button', { name: 'Create account' }).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 f73a77ad5..d96de9c3a 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 @@ -49,10 +49,6 @@ export class SignupInitBlockModel { await elem.fill(value); } - fillFullName(value: string) { - return; - } - submitPrimary() { return this.page.getByRole('button', { name: 'Continue', exact: true }).click(); } diff --git a/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/login-init-no-public-signup.spec.ts b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/login-init-no-public-signup.spec.ts index fa8e24f8f..284c4f43d 100644 --- a/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/login-init-no-public-signup.spec.ts +++ b/packages/tests-e2e/src/complete/scenarios/corbado-auth-general/login-init-no-public-signup.spec.ts @@ -37,7 +37,7 @@ test.describe('login-init no public signup', () => { await expect(page.getByRole('button', { name: 'Sign up' })).toBeHidden(); }); - test('switch to signup should not be possible (hashCode)', async ({ model, page }) => { + test('switch to signup should not be possible (hashCode)', async ({ model }) => { await model.load(projectId, true, 'signup-init'); await model.expectScreen(ScreenNames.InitLogin); diff --git a/packages/tests-e2e/src/connect/fixtures/BaseTest.ts b/packages/tests-e2e/src/connect/fixtures/BaseTest.ts new file mode 100644 index 000000000..661b40d9b --- /dev/null +++ b/packages/tests-e2e/src/connect/fixtures/BaseTest.ts @@ -0,0 +1,18 @@ +import { test as base } from '@playwright/test'; + +import { BaseModel } from '../models/BaseModel'; +import { VirtualAuthenticator } from '../utils/VirtualAuthenticator'; + +export const test = base.extend<{ model: BaseModel }>({ + model: async ({ page }, use) => { + const authenticator = new VirtualAuthenticator(); + await authenticator.initializeCDPSession(page); + console.log('initialized'); + + const model = new BaseModel(page, authenticator); + + await use(model); + }, +}); + +export { expect } from '@playwright/test'; diff --git a/packages/tests-e2e/src/connect/models/AppendModel.ts b/packages/tests-e2e/src/connect/models/AppendModel.ts new file mode 100644 index 000000000..91dc79493 --- /dev/null +++ b/packages/tests-e2e/src/connect/models/AppendModel.ts @@ -0,0 +1,22 @@ +import type { Page } from '@playwright/test'; + +import type { VirtualAuthenticator } from '../utils/VirtualAuthenticator'; + +export class AppendModel { + page: Page; + authenticator: VirtualAuthenticator; + + constructor(page: Page, authenticator: VirtualAuthenticator) { + this.page = page; + this.authenticator = authenticator; + } + + async appendPasskey(): Promise { + const operationTrigger = () => this.page.getByRole('button', { name: 'Continue' }).click(); + await this.authenticator.startAndCompletePasskeyOperation(operationTrigger); + } + + confirmAppended(): Promise { + return this.page.getByRole('button', { name: 'Continue' }).click(); + } +} diff --git a/packages/tests-e2e/src/connect/models/BaseModel.ts b/packages/tests-e2e/src/connect/models/BaseModel.ts new file mode 100644 index 000000000..a47a89932 --- /dev/null +++ b/packages/tests-e2e/src/connect/models/BaseModel.ts @@ -0,0 +1,79 @@ +import type { Page } from '@playwright/test'; +import { expect } from '@playwright/test'; + +import { ScreenNames } from '../utils/Constants'; +import { expectScreen } from '../utils/ExpectScreen'; +import type { VirtualAuthenticator } from '../utils/VirtualAuthenticator'; +import { AppendModel } from './AppendModel'; +import { SignupModel } from './SIgnupModel'; + +export class BaseModel { + page: Page; + authenticator: VirtualAuthenticator; + signup: SignupModel; + append: AppendModel; + email = ''; + + constructor(page: Page, authenticator: VirtualAuthenticator) { + this.page = page; + this.authenticator = authenticator; + this.signup = new SignupModel(page); + this.append = new AppendModel(page, authenticator); + } + + addWebAuthn() { + return this.authenticator.addWebAuthn(); + } + + removeWebAuthn() { + return this.authenticator.removeWebAuthn(); + } + + loadSignup(withInvitationToken = true) { + if (withInvitationToken) { + return this.page.goto('/signup?invitationToken=inv-token-correct'); + } else { + return this.page.goto('/signup'); + } + } + + loadLogin(withInvitationToken = true) { + if (withInvitationToken) { + return this.page.goto('/login?invitationToken=inv-token-correct'); + } else { + return this.page.goto('/login'); + } + } + + expectScreen(screenName: ScreenNames) { + return expectScreen(this.page, screenName); + } + + async createUser() { + this.email = await this.signup.autofillCredentials(); + await this.signup.submit(); + await this.expectScreen(ScreenNames.PasskeyAppend); + await this.append.appendPasskey(); + await this.expectScreen(ScreenNames.PasskeyAppended); + await this.append.confirmAppended(); + } + + async deleteUser() { + const cookies = await this.page.context().cookies(); + const longSessionCookie = cookies.find(cookie => cookie.name === 'cbo_long_session'); + const longSessionCookieValue = longSessionCookie?.value; + + expect(longSessionCookieValue).toBeDefined(); + expect(process.env.FRONTEND_API_URL).toBeDefined(); + + const response = await fetch(`${process.env.FRONTEND_API_URL}/v2/me`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + Cookie: `cbo_long_session=${longSessionCookieValue}`, + }, + }); + + expect(response.ok).toBeTruthy(); + } +} diff --git a/packages/tests-e2e/src/connect/models/SIgnupModel.ts b/packages/tests-e2e/src/connect/models/SIgnupModel.ts new file mode 100644 index 000000000..6eea74e13 --- /dev/null +++ b/packages/tests-e2e/src/connect/models/SIgnupModel.ts @@ -0,0 +1,20 @@ +import type { Page } from '@playwright/test'; + +export class SignupModel { + page: Page; + + constructor(page: Page) { + this.page = page; + } + + async autofillCredentials(): Promise { + await this.page.getByRole('button', { name: 'auto' }).click(); + return await this.page.getByPlaceholder('Email').inputValue(); + } + + + + submit(): Promise { + return this.page.getByRole('button', { name: 'Sign up' }).click(); + } +} diff --git a/packages/tests-e2e/src/connect/scenarios/append.spec.ts b/packages/tests-e2e/src/connect/scenarios/append.spec.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/tests-e2e/src/connect/scenarios/hooks.ts b/packages/tests-e2e/src/connect/scenarios/hooks.ts new file mode 100644 index 000000000..79061fb6d --- /dev/null +++ b/packages/tests-e2e/src/connect/scenarios/hooks.ts @@ -0,0 +1,69 @@ +import type { + PlaywrightTestArgs, + PlaywrightTestOptions, + PlaywrightWorkerArgs, + PlaywrightWorkerOptions, + TestType, +} from '@playwright/test'; + +import type { BaseModel } from '../models/BaseModel'; +import { ScreenNames } from '../utils/Constants'; + +export function setupVirtualAuthenticator( + test: TestType< + PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, + PlaywrightWorkerArgs & PlaywrightWorkerOptions + >, +) { + test.beforeEach(async ({ model }) => { + console.log('adding'); + await model.addWebAuthn(); + console.log('added'); + }); + + test.afterEach(async ({ model }) => { + await model.removeWebAuthn(); + }); +} + +export function loadSignup( + test: TestType< + PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, + PlaywrightWorkerArgs & PlaywrightWorkerOptions + >, +) { + test.beforeEach(async ({ model }) => { + await model.loadSignup(); + }); +} + +export function loadLogin( + test: TestType< + PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, + PlaywrightWorkerArgs & PlaywrightWorkerOptions + >, +) { + test.beforeEach(async ({ model }) => { + await model.loadLogin(); + }); +} + +export function setupUser( + test: TestType< + PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, + PlaywrightWorkerArgs & PlaywrightWorkerOptions + >, +) { + test.beforeEach(async ({ model }) => { + console.log('creating'); + await model.page.waitForTimeout(1000); + await model.loadSignup(); + await model.expectScreen(ScreenNames.InitSignup); + await model.createUser(); + await model.expectScreen(ScreenNames.Home); + }); + + test.afterEach(async ({ model }) => { + await model.deleteUser(); + }); +} diff --git a/packages/tests-e2e/src/connect/scenarios/login.spec.ts b/packages/tests-e2e/src/connect/scenarios/login.spec.ts new file mode 100644 index 000000000..e54c3b183 --- /dev/null +++ b/packages/tests-e2e/src/connect/scenarios/login.spec.ts @@ -0,0 +1,12 @@ +import { test } from '../fixtures/BaseTest'; +import { ScreenNames } from '../utils/Constants'; +import { setupUser, setupVirtualAuthenticator } from './hooks'; + +test.describe('login component', () => { + setupVirtualAuthenticator(test); + setupUser(test); + + test('successful login with passkey', async ({ model }) => { + await model.expectScreen(ScreenNames.Home); + }); +}); diff --git a/packages/tests-e2e/src/connect/scenarios/misc.spec.ts b/packages/tests-e2e/src/connect/scenarios/misc.spec.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/tests-e2e/src/connect/scenarios/passkey-list.spec.ts b/packages/tests-e2e/src/connect/scenarios/passkey-list.spec.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/tests-e2e/src/connect/utils/Constants.ts b/packages/tests-e2e/src/connect/utils/Constants.ts new file mode 100644 index 000000000..d085fd968 --- /dev/null +++ b/packages/tests-e2e/src/connect/utils/Constants.ts @@ -0,0 +1,13 @@ +export enum ScreenNames { + InitSignup, + PasskeyAppend, + PasskeyAppended, + InitLogin, + Home, +} + +export const phone = '+4915121609839'; +export const password = 'asdfasdf'; + +export const totalTimeout = process.env.CI ? 30000 : 40000; +export const operationTimeout = 10000; diff --git a/packages/tests-e2e/src/connect/utils/ExpectScreen.ts b/packages/tests-e2e/src/connect/utils/ExpectScreen.ts new file mode 100644 index 000000000..4db229776 --- /dev/null +++ b/packages/tests-e2e/src/connect/utils/ExpectScreen.ts @@ -0,0 +1,31 @@ +import type { Page} from '@playwright/test'; +import { expect } from '@playwright/test'; + +import { ScreenNames } from './Constants'; + +export const expectScreen = async (page: Page, screenName: ScreenNames) => { + switch (screenName) { + case ScreenNames.InitSignup: + await expect(page.locator('div.font-bold.text-xl')).toHaveText('Signup'); + return; + + case ScreenNames.PasskeyAppend: + await expect(page.locator('.cb-connect-container').locator('.cb-append-header')).toHaveText('Simplify Your Login'); + return; + + case ScreenNames.PasskeyAppended: + await expect(page.locator('.cb-connect-container').locator('.cb-append-success-header')).toHaveText('Passkey Created Successfully'); + return; + + case ScreenNames.InitLogin: + await expect(page.locator('div.font-bold.text-xl')).toHaveText('Login'); + return; + + case ScreenNames.Home: + await expect(page.locator('div.font-bold.text-xl')).toHaveText('Home'); + return; + + default: + throw new Error('Invalid screen'); + } +} diff --git a/packages/tests-e2e/src/connect/utils/VirtualAuthenticator.ts b/packages/tests-e2e/src/connect/utils/VirtualAuthenticator.ts new file mode 100644 index 000000000..a771ecc86 --- /dev/null +++ b/packages/tests-e2e/src/connect/utils/VirtualAuthenticator.ts @@ -0,0 +1,94 @@ +import type { CDPSession, Page } from '@playwright/test'; + +import { operationTimeout } from './Constants'; + +export class VirtualAuthenticator { + #cdpClient: CDPSession | null = null; + #authenticatorId = ''; + + async initializeCDPSession(page: Page) { + this.#cdpClient = await page.context().newCDPSession(page); + } + + async addWebAuthn(passkeySupported = true) { + if (!this.#cdpClient) { + throw new Error('CDP client not initialized'); + } + + await this.#cdpClient.send('WebAuthn.enable'); + const result = await this.#cdpClient.send('WebAuthn.addVirtualAuthenticator', { + options: passkeySupported + ? { + protocol: 'ctap2', + transport: 'internal', + hasResidentKey: true, + hasUserVerification: true, + automaticPresenceSimulation: false, + } + : { + protocol: 'u2f', + transport: 'usb', + }, + }); + + this.#authenticatorId = result.authenticatorId; + } + + async removeWebAuthn() { + if (!this.#cdpClient) { + throw new Error('CDP client not initialized'); + } + + await this.#cdpClient.send('WebAuthn.removeVirtualAuthenticator', { + authenticatorId: this.#authenticatorId, + }); + } + + async startAndCompletePasskeyOperation(operationTrigger: () => Promise) { + if (!this.#cdpClient) { + throw new Error('CDP client not initialized'); + } + + const operationCompleted = new Promise(resolve => { + this.#cdpClient?.on('WebAuthn.credentialAdded', () => resolve()); + this.#cdpClient?.on('WebAuthn.credentialAsserted', () => resolve()); + }); + + const wait = new Promise(resolve => setTimeout(resolve, operationTimeout)); + await this.#setWebAuthnUserVerified(this.#cdpClient, this.#authenticatorId, true); + await this.#setWebAuthnAutomaticPresenceSimulation(this.#cdpClient, this.#authenticatorId, true); + + await operationTrigger(); + + await Promise.race([operationCompleted, wait.then(() => Promise.reject('Passkey input timeout'))]); + await this.#setWebAuthnAutomaticPresenceSimulation(this.#cdpClient, this.#authenticatorId, false); + } + + async startAndCancelPasskeyOperation(operationTrigger: () => Promise, postOperationCheck: () => Promise) { + if (!this.#cdpClient) { + throw new Error('CDP client not initialized'); + } + + await this.#setWebAuthnUserVerified(this.#cdpClient, this.#authenticatorId, false); + await this.#setWebAuthnAutomaticPresenceSimulation(this.#cdpClient, this.#authenticatorId, true); + + await operationTrigger(); + + await postOperationCheck(); + await this.#setWebAuthnAutomaticPresenceSimulation(this.#cdpClient, this.#authenticatorId, false); + } + + #setWebAuthnAutomaticPresenceSimulation(client: CDPSession, authenticatorId: string, automatic: boolean) { + return client.send('WebAuthn.setAutomaticPresenceSimulation', { + authenticatorId: authenticatorId, + enabled: automatic, + }); + } + + #setWebAuthnUserVerified(client: CDPSession, authenticatorId: string, isUserVerified: boolean) { + return client.send('WebAuthn.setUserVerified', { + authenticatorId, + isUserVerified, + }); + } +} diff --git a/packages/tests-e2e/src/connect/utils/constants.ts b/packages/tests-e2e/src/connect/utils/constants.ts deleted file mode 100644 index 69d5a83a6..000000000 --- a/packages/tests-e2e/src/connect/utils/constants.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const totalTimeout = process.env.CI ? 30000 : 40000; -export const operationTimeout = process.env.CI ? 5000 : 7000; -export const socialOperationTimeout = 10000; From a05aedf64a4095987936df18554529e38bacd72e Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 18 Dec 2024 19:49:33 +0100 Subject: [PATCH 03/10] prettier --- packages/tests-e2e/playwright.config.connect.ts | 2 +- packages/tests-e2e/src/connect/models/BaseModel.ts | 2 +- .../models/{SIgnupModel.ts => SignupModel.ts} | 2 -- packages/tests-e2e/src/connect/utils/ExpectScreen.ts | 12 ++++++++---- 4 files changed, 10 insertions(+), 8 deletions(-) rename packages/tests-e2e/src/connect/models/{SIgnupModel.ts => SignupModel.ts} (99%) diff --git a/packages/tests-e2e/playwright.config.connect.ts b/packages/tests-e2e/playwright.config.connect.ts index 06fbb046c..3e01e1a93 100644 --- a/packages/tests-e2e/playwright.config.connect.ts +++ b/packages/tests-e2e/playwright.config.connect.ts @@ -66,6 +66,6 @@ export default defineConfig({ { name: 'misc', testMatch: ['scenarios/misc.spec.ts'], - } + }, ], }); diff --git a/packages/tests-e2e/src/connect/models/BaseModel.ts b/packages/tests-e2e/src/connect/models/BaseModel.ts index a47a89932..b9dbefc77 100644 --- a/packages/tests-e2e/src/connect/models/BaseModel.ts +++ b/packages/tests-e2e/src/connect/models/BaseModel.ts @@ -5,7 +5,7 @@ import { ScreenNames } from '../utils/Constants'; import { expectScreen } from '../utils/ExpectScreen'; import type { VirtualAuthenticator } from '../utils/VirtualAuthenticator'; import { AppendModel } from './AppendModel'; -import { SignupModel } from './SIgnupModel'; +import { SignupModel } from './SignupModel'; export class BaseModel { page: Page; diff --git a/packages/tests-e2e/src/connect/models/SIgnupModel.ts b/packages/tests-e2e/src/connect/models/SignupModel.ts similarity index 99% rename from packages/tests-e2e/src/connect/models/SIgnupModel.ts rename to packages/tests-e2e/src/connect/models/SignupModel.ts index 6eea74e13..5b9cd1097 100644 --- a/packages/tests-e2e/src/connect/models/SIgnupModel.ts +++ b/packages/tests-e2e/src/connect/models/SignupModel.ts @@ -12,8 +12,6 @@ export class SignupModel { return await this.page.getByPlaceholder('Email').inputValue(); } - - submit(): Promise { return this.page.getByRole('button', { name: 'Sign up' }).click(); } diff --git a/packages/tests-e2e/src/connect/utils/ExpectScreen.ts b/packages/tests-e2e/src/connect/utils/ExpectScreen.ts index 4db229776..ae8d9c272 100644 --- a/packages/tests-e2e/src/connect/utils/ExpectScreen.ts +++ b/packages/tests-e2e/src/connect/utils/ExpectScreen.ts @@ -1,4 +1,4 @@ -import type { Page} from '@playwright/test'; +import type { Page } from '@playwright/test'; import { expect } from '@playwright/test'; import { ScreenNames } from './Constants'; @@ -10,11 +10,15 @@ export const expectScreen = async (page: Page, screenName: ScreenNames) => { return; case ScreenNames.PasskeyAppend: - await expect(page.locator('.cb-connect-container').locator('.cb-append-header')).toHaveText('Simplify Your Login'); + await expect(page.locator('.cb-connect-container').locator('.cb-append-header')).toHaveText( + 'Simplify Your Login', + ); return; case ScreenNames.PasskeyAppended: - await expect(page.locator('.cb-connect-container').locator('.cb-append-success-header')).toHaveText('Passkey Created Successfully'); + await expect(page.locator('.cb-connect-container').locator('.cb-append-success-header')).toHaveText( + 'Passkey Created Successfully', + ); return; case ScreenNames.InitLogin: @@ -28,4 +32,4 @@ export const expectScreen = async (page: Page, screenName: ScreenNames) => { default: throw new Error('Invalid screen'); } -} +}; From 785423cafdb6ba9e00918e71fa73354b4dbf760e Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 18 Dec 2024 19:55:55 +0100 Subject: [PATCH 04/10] remove logs --- packages/tests-e2e/src/connect/fixtures/BaseTest.ts | 1 - packages/tests-e2e/src/connect/scenarios/hooks.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/packages/tests-e2e/src/connect/fixtures/BaseTest.ts b/packages/tests-e2e/src/connect/fixtures/BaseTest.ts index 661b40d9b..19c5cbb73 100644 --- a/packages/tests-e2e/src/connect/fixtures/BaseTest.ts +++ b/packages/tests-e2e/src/connect/fixtures/BaseTest.ts @@ -7,7 +7,6 @@ export const test = base.extend<{ model: BaseModel }>({ model: async ({ page }, use) => { const authenticator = new VirtualAuthenticator(); await authenticator.initializeCDPSession(page); - console.log('initialized'); const model = new BaseModel(page, authenticator); diff --git a/packages/tests-e2e/src/connect/scenarios/hooks.ts b/packages/tests-e2e/src/connect/scenarios/hooks.ts index 79061fb6d..735e954aa 100644 --- a/packages/tests-e2e/src/connect/scenarios/hooks.ts +++ b/packages/tests-e2e/src/connect/scenarios/hooks.ts @@ -16,9 +16,7 @@ export function setupVirtualAuthenticator( >, ) { test.beforeEach(async ({ model }) => { - console.log('adding'); await model.addWebAuthn(); - console.log('added'); }); test.afterEach(async ({ model }) => { @@ -55,7 +53,6 @@ export function setupUser( >, ) { test.beforeEach(async ({ model }) => { - console.log('creating'); await model.page.waitForTimeout(1000); await model.loadSignup(); await model.expectScreen(ScreenNames.InitSignup); From 4cfc3a97760b189e4b91e5878e4ff0627317c0fb Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 18 Dec 2024 20:06:40 +0100 Subject: [PATCH 05/10] try setting webdriver=false in clientinformation --- packages/tests-e2e/src/connect/scenarios/hooks.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/tests-e2e/src/connect/scenarios/hooks.ts b/packages/tests-e2e/src/connect/scenarios/hooks.ts index 735e954aa..819be8793 100644 --- a/packages/tests-e2e/src/connect/scenarios/hooks.ts +++ b/packages/tests-e2e/src/connect/scenarios/hooks.ts @@ -52,8 +52,13 @@ export function setupUser( PlaywrightWorkerArgs & PlaywrightWorkerOptions >, ) { - test.beforeEach(async ({ model }) => { - await model.page.waitForTimeout(1000); + test.beforeEach(async ({ context, model }) => { + // setting webdriver as false still leads to fallback + // await context.addInitScript(() => { + // Object.defineProperty(navigator, 'webdriver', { + // get: () => false, + // }); + // }); await model.loadSignup(); await model.expectScreen(ScreenNames.InitSignup); await model.createUser(); From 27ead96c5091ff20b9417be8d71b4ef724ee0282 Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 8 Jan 2025 13:00:09 +0100 Subject: [PATCH 06/10] login functionality tests --- package-lock.json | 240 +++++++++--------- .../src/connect/models/AppendModel.ts | 4 + .../tests-e2e/src/connect/models/BaseModel.ts | 79 +++--- .../tests-e2e/src/connect/models/HomeModel.ts | 17 ++ .../src/connect/models/LoginModel.ts | 43 ++++ .../tests-e2e/src/connect/scenarios/hooks.ts | 32 ++- .../src/connect/scenarios/login.spec.ts | 52 +++- .../tests-e2e/src/connect/utils/Constants.ts | 4 +- .../src/connect/utils/ExpectScreen.ts | 20 +- 9 files changed, 313 insertions(+), 178 deletions(-) create mode 100644 packages/tests-e2e/src/connect/models/HomeModel.ts create mode 100644 packages/tests-e2e/src/connect/models/LoginModel.ts diff --git a/package-lock.json b/package-lock.json index 4ad715a1e..25c01a4f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5209,6 +5209,126 @@ "node": ">= 10" } }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz", + "integrity": "sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz", + "integrity": "sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz", + "integrity": "sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz", + "integrity": "sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz", + "integrity": "sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz", + "integrity": "sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz", + "integrity": "sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz", + "integrity": "sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "license": "MIT", @@ -27350,126 +27470,6 @@ "devDependencies": { "dotenv-webpack": "^8.0.1" } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.4.tgz", - "integrity": "sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.4.tgz", - "integrity": "sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.4.tgz", - "integrity": "sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.4.tgz", - "integrity": "sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.4.tgz", - "integrity": "sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.4.tgz", - "integrity": "sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.4.tgz", - "integrity": "sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.4.tgz", - "integrity": "sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } } } } diff --git a/packages/tests-e2e/src/connect/models/AppendModel.ts b/packages/tests-e2e/src/connect/models/AppendModel.ts index 91dc79493..f17b0c7f9 100644 --- a/packages/tests-e2e/src/connect/models/AppendModel.ts +++ b/packages/tests-e2e/src/connect/models/AppendModel.ts @@ -19,4 +19,8 @@ export class AppendModel { confirmAppended(): Promise { return this.page.getByRole('button', { name: 'Continue' }).click(); } + + skipAppend(): Promise { + return this.page.locator('.cb-append-skip').click(); + } } diff --git a/packages/tests-e2e/src/connect/models/BaseModel.ts b/packages/tests-e2e/src/connect/models/BaseModel.ts index b9dbefc77..21e42047c 100644 --- a/packages/tests-e2e/src/connect/models/BaseModel.ts +++ b/packages/tests-e2e/src/connect/models/BaseModel.ts @@ -1,24 +1,29 @@ import type { Page } from '@playwright/test'; -import { expect } from '@playwright/test'; import { ScreenNames } from '../utils/Constants'; import { expectScreen } from '../utils/ExpectScreen'; import type { VirtualAuthenticator } from '../utils/VirtualAuthenticator'; import { AppendModel } from './AppendModel'; +import { HomeModel } from './HomeModel'; +import { LoginModel } from './LoginModel'; import { SignupModel } from './SignupModel'; export class BaseModel { page: Page; authenticator: VirtualAuthenticator; signup: SignupModel; + login: LoginModel; append: AppendModel; + home: HomeModel; email = ''; constructor(page: Page, authenticator: VirtualAuthenticator) { this.page = page; this.authenticator = authenticator; this.signup = new SignupModel(page); + this.login = new LoginModel(page, authenticator); this.append = new AppendModel(page, authenticator); + this.home = new HomeModel(page); } addWebAuthn() { @@ -29,51 +34,53 @@ export class BaseModel { return this.authenticator.removeWebAuthn(); } - loadSignup(withInvitationToken = true) { - if (withInvitationToken) { - return this.page.goto('/signup?invitationToken=inv-token-correct'); - } else { - return this.page.goto('/signup'); - } + loadInvitationToken() { + return this.page.goto('/login?invitationToken=inv-token-correct'); } - loadLogin(withInvitationToken = true) { - if (withInvitationToken) { - return this.page.goto('/login?invitationToken=inv-token-correct'); - } else { - return this.page.goto('/login'); - } + loadSignup() { + return this.page.goto('/signup'); + } + + loadLogin() { + return this.page.goto('/login'); } expectScreen(screenName: ScreenNames) { return expectScreen(this.page, screenName); } - async createUser() { + async createUser(invited: boolean, append: boolean) { this.email = await this.signup.autofillCredentials(); await this.signup.submit(); - await this.expectScreen(ScreenNames.PasskeyAppend); - await this.append.appendPasskey(); - await this.expectScreen(ScreenNames.PasskeyAppended); - await this.append.confirmAppended(); + if (invited) { + await this.expectScreen(ScreenNames.PasskeyAppend); + if (append) { + await this.append.appendPasskey(); + await this.expectScreen(ScreenNames.PasskeyAppended); + await this.append.confirmAppended(); + } else { + await this.append.skipAppend(); + } + } } - async deleteUser() { - const cookies = await this.page.context().cookies(); - const longSessionCookie = cookies.find(cookie => cookie.name === 'cbo_long_session'); - const longSessionCookieValue = longSessionCookie?.value; - - expect(longSessionCookieValue).toBeDefined(); - expect(process.env.FRONTEND_API_URL).toBeDefined(); - - const response = await fetch(`${process.env.FRONTEND_API_URL}/v2/me`, { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - Cookie: `cbo_long_session=${longSessionCookieValue}`, - }, - }); - - expect(response.ok).toBeTruthy(); - } + // async deleteUser() { + // const cookies = await this.page.context().cookies(); + // const longSessionCookie = cookies.find(cookie => cookie.name === 'cbo_long_session'); + // const longSessionCookieValue = longSessionCookie?.value; + // + // expect(longSessionCookieValue).toBeDefined(); + // expect(process.env.FRONTEND_API_URL).toBeDefined(); + // + // const response = await fetch(`${process.env.FRONTEND_API_URL}/v2/me`, { + // method: 'DELETE', + // headers: { + // 'Content-Type': 'application/json', + // Cookie: `cbo_long_session=${longSessionCookieValue}`, + // }, + // }); + // + // expect(response.ok).toBeTruthy(); + // } } diff --git a/packages/tests-e2e/src/connect/models/HomeModel.ts b/packages/tests-e2e/src/connect/models/HomeModel.ts new file mode 100644 index 000000000..d412a4cd1 --- /dev/null +++ b/packages/tests-e2e/src/connect/models/HomeModel.ts @@ -0,0 +1,17 @@ +import type { Page } from '@playwright/test'; + +export class HomeModel { + page: Page; + + constructor(page: Page) { + this.page = page; + } + + logout(): Promise { + return this.page.getByRole('button', { name: 'Logout' }).click(); + } + + gotoPasskeyList(): Promise { + return this.page.getByRole('button', { name: 'Passkey List' }).click(); + } +} diff --git a/packages/tests-e2e/src/connect/models/LoginModel.ts b/packages/tests-e2e/src/connect/models/LoginModel.ts new file mode 100644 index 000000000..eed6e05c3 --- /dev/null +++ b/packages/tests-e2e/src/connect/models/LoginModel.ts @@ -0,0 +1,43 @@ +import { expect } from '@playwright/test'; +import type { Page } from '@playwright/test'; + +import type { VirtualAuthenticator } from '../utils/VirtualAuthenticator'; + +export class LoginModel { + page: Page; + authenticator: VirtualAuthenticator; + + constructor(page: Page, authenticator: VirtualAuthenticator) { + this.page = page; + this.authenticator = authenticator; + } + + submitPasskeyButton(): Promise { + const operationTrigger = () => this.page.locator('.cb-passkey-button').click(); + return this.authenticator.startAndCompletePasskeyOperation(operationTrigger); + } + + removePasskeyButton(): Promise { + return this.page.locator('.cb-switch').click(); + } + + async submitEmail(email: string, withPasskey: boolean): Promise { + await this.page.getByLabel('Email address').fill(email); + if (withPasskey) { + const operationTrigger = () => this.page.getByRole('button', { name: 'Login' }).click(); + await this.authenticator.startAndCompletePasskeyOperation(operationTrigger); + } else { + await this.page.getByRole('button', { name: 'Login' }).click(); + } + } + + async submitFallbackCredentials(email: string, password: string, emailAutofilled = false): Promise { + if (emailAutofilled) { + await expect(this.page.getByPlaceholder('Email')).toHaveValue(email); + } else { + await this.page.getByPlaceholder('Email').fill(email); + } + await this.page.getByPlaceholder('Password').fill(password); + await this.page.getByRole('button', { name: 'Login' }).click(); + } +} diff --git a/packages/tests-e2e/src/connect/scenarios/hooks.ts b/packages/tests-e2e/src/connect/scenarios/hooks.ts index 819be8793..2b1eafdf2 100644 --- a/packages/tests-e2e/src/connect/scenarios/hooks.ts +++ b/packages/tests-e2e/src/connect/scenarios/hooks.ts @@ -24,6 +24,17 @@ export function setupVirtualAuthenticator( }); } +// export function loadInvitationToken( +// test: TestType< +// PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, +// PlaywrightWorkerArgs & PlaywrightWorkerOptions +// >, +// ) { +// test.beforeEach(async ({ model }) => { +// await model.loadInvitationToken(); +// }); +// } + export function loadSignup( test: TestType< PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, @@ -50,22 +61,19 @@ export function setupUser( test: TestType< PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, PlaywrightWorkerArgs & PlaywrightWorkerOptions - >, + >, invited = true, append = true, ) { - test.beforeEach(async ({ context, model }) => { - // setting webdriver as false still leads to fallback - // await context.addInitScript(() => { - // Object.defineProperty(navigator, 'webdriver', { - // get: () => false, - // }); - // }); + test.beforeEach(async ({ model }) => { + if (invited) { + await model.loadInvitationToken(); + } await model.loadSignup(); await model.expectScreen(ScreenNames.InitSignup); - await model.createUser(); + await model.createUser(invited, append); await model.expectScreen(ScreenNames.Home); }); - test.afterEach(async ({ model }) => { - await model.deleteUser(); - }); + // test.afterEach(async ({ model }) => { + // await model.deleteUser(); + // }); } diff --git a/packages/tests-e2e/src/connect/scenarios/login.spec.ts b/packages/tests-e2e/src/connect/scenarios/login.spec.ts index e54c3b183..230229727 100644 --- a/packages/tests-e2e/src/connect/scenarios/login.spec.ts +++ b/packages/tests-e2e/src/connect/scenarios/login.spec.ts @@ -1,12 +1,58 @@ import { test } from '../fixtures/BaseTest'; -import { ScreenNames } from '../utils/Constants'; +import { password, ScreenNames } from '../utils/Constants'; import { setupUser, setupVirtualAuthenticator } from './hooks'; -test.describe('login component', () => { +test.describe('login component (without invitation token)', () => { + setupUser(test, false); + + test('successful login with credentials', async ({ model }) => { + await model.home.logout(); + await model.expectScreen(ScreenNames.InitLoginFallback); + + await model.login.submitFallbackCredentials(model.email, password); + await model.expectScreen(ScreenNames.Home); + }); +}); + +test.describe('login component (with invitation token, without passkeys)', () => { setupVirtualAuthenticator(test); - setupUser(test); + setupUser(test, true, false); + + test('successful login with credentials', async ({ model }) => { + await model.home.logout(); + await model.expectScreen(ScreenNames.InitLogin); + + await model.login.submitEmail(model.email, false); + await model.expectScreen(ScreenNames.InitLoginFallback); + + await model.login.submitFallbackCredentials(model.email, password, true); + await model.expectScreen(ScreenNames.PasskeyAppend); + + await model.append.skipAppend(); + await model.expectScreen(ScreenNames.Home); + }); +}); + +test.describe('login component (with invitation token, with passkeys)', () => { + setupVirtualAuthenticator(test); + setupUser(test, true, true); + + test('successful login with passkey (one-tap)', async ({ model }) => { + await model.home.logout(); + await model.expectScreen(ScreenNames.InitLoginOneTap); + + await model.login.submitPasskeyButton(); + await model.expectScreen(ScreenNames.Home); + }); test('successful login with passkey', async ({ model }) => { + await model.home.logout(); + await model.expectScreen(ScreenNames.InitLoginOneTap); + + await model.login.removePasskeyButton(); + await model.expectScreen(ScreenNames.InitLogin); + + await model.login.submitEmail(model.email, true); await model.expectScreen(ScreenNames.Home); }); }); diff --git a/packages/tests-e2e/src/connect/utils/Constants.ts b/packages/tests-e2e/src/connect/utils/Constants.ts index d085fd968..0799d6662 100644 --- a/packages/tests-e2e/src/connect/utils/Constants.ts +++ b/packages/tests-e2e/src/connect/utils/Constants.ts @@ -1,8 +1,10 @@ export enum ScreenNames { InitSignup, + InitLogin, + InitLoginFallback, + InitLoginOneTap, PasskeyAppend, PasskeyAppended, - InitLogin, Home, } diff --git a/packages/tests-e2e/src/connect/utils/ExpectScreen.ts b/packages/tests-e2e/src/connect/utils/ExpectScreen.ts index ae8d9c272..8919f1109 100644 --- a/packages/tests-e2e/src/connect/utils/ExpectScreen.ts +++ b/packages/tests-e2e/src/connect/utils/ExpectScreen.ts @@ -9,22 +9,30 @@ export const expectScreen = async (page: Page, screenName: ScreenNames) => { await expect(page.locator('div.font-bold.text-xl')).toHaveText('Signup'); return; + case ScreenNames.InitLogin: + await expect(page.locator('div.cb-connect-login').getByRole('textbox', { name: 'Email address' })).toBeVisible(); + return; + + case ScreenNames.InitLoginFallback: + await expect(page.locator('div.font-bold.text-xl')).toHaveText('Login'); + return; + + case ScreenNames.InitLoginOneTap: + await expect(page.locator('div.cb-connect-login')).toContainText('Welcome back'); + return; + case ScreenNames.PasskeyAppend: - await expect(page.locator('.cb-connect-container').locator('.cb-append-header')).toHaveText( + await expect(page.locator('.cb-connect-container').locator('.cb-append-header')).toContainText( 'Simplify Your Login', ); return; case ScreenNames.PasskeyAppended: - await expect(page.locator('.cb-connect-container').locator('.cb-append-success-header')).toHaveText( + await expect(page.locator('.cb-connect-container').locator('.cb-append-success-header')).toContainText( 'Passkey Created Successfully', ); return; - case ScreenNames.InitLogin: - await expect(page.locator('div.font-bold.text-xl')).toHaveText('Login'); - return; - case ScreenNames.Home: await expect(page.locator('div.font-bold.text-xl')).toHaveText('Home'); return; From 59e95703d4a496dcb7a458d39a2e83b07b3ed843 Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 8 Jan 2025 14:14:11 +0100 Subject: [PATCH 07/10] append and passkey-list functionality tests --- .../tests-e2e/src/connect/models/BaseModel.ts | 3 ++ .../src/connect/models/PasskeyListModel.ts | 34 +++++++++++++++++++ .../src/connect/scenarios/append.spec.ts | 17 ++++++++++ .../tests-e2e/src/connect/scenarios/hooks.ts | 34 ++++++++++++++++++- .../connect/scenarios/passkey-list.spec.ts | 16 +++++++++ .../tests-e2e/src/connect/utils/Constants.ts | 1 + .../src/connect/utils/ExpectScreen.ts | 4 +++ 7 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 packages/tests-e2e/src/connect/models/PasskeyListModel.ts diff --git a/packages/tests-e2e/src/connect/models/BaseModel.ts b/packages/tests-e2e/src/connect/models/BaseModel.ts index 21e42047c..996225a3c 100644 --- a/packages/tests-e2e/src/connect/models/BaseModel.ts +++ b/packages/tests-e2e/src/connect/models/BaseModel.ts @@ -6,6 +6,7 @@ import type { VirtualAuthenticator } from '../utils/VirtualAuthenticator'; import { AppendModel } from './AppendModel'; import { HomeModel } from './HomeModel'; import { LoginModel } from './LoginModel'; +import { PasskeyListModel } from './PasskeyListModel'; import { SignupModel } from './SignupModel'; export class BaseModel { @@ -15,6 +16,7 @@ export class BaseModel { login: LoginModel; append: AppendModel; home: HomeModel; + passkeyList: PasskeyListModel; email = ''; constructor(page: Page, authenticator: VirtualAuthenticator) { @@ -24,6 +26,7 @@ export class BaseModel { this.login = new LoginModel(page, authenticator); this.append = new AppendModel(page, authenticator); this.home = new HomeModel(page); + this.passkeyList = new PasskeyListModel(page, authenticator); } addWebAuthn() { diff --git a/packages/tests-e2e/src/connect/models/PasskeyListModel.ts b/packages/tests-e2e/src/connect/models/PasskeyListModel.ts new file mode 100644 index 000000000..01c1c6c17 --- /dev/null +++ b/packages/tests-e2e/src/connect/models/PasskeyListModel.ts @@ -0,0 +1,34 @@ +import type { Page } from '@playwright/test'; +import { expect } from '@playwright/test'; + +import type { VirtualAuthenticator } from '../utils/VirtualAuthenticator'; + +export class PasskeyListModel { + page: Page; + authenticator: VirtualAuthenticator; + + constructor(page: Page, authenticator: VirtualAuthenticator) { + this.page = page; + this.authenticator = authenticator; + } + + expectPasskeys(n: number) { + return expect(this.page.locator('.cb-passkey-list-item')).toHaveCount(n); + } + + async deletePasskey(index: number) { + await this.page.locator('.cb-passkey-list-item-delete-icon').nth(index).click(); + await this.page.getByRole('button', { name: 'Delete' }).click(); + } + + async appendPasskey(complete: boolean) { + const operationTrigger = () => this.page.getByRole('button', { name: 'Add a passkey' }).click(); + if (complete) { + await this.authenticator.startAndCompletePasskeyOperation(operationTrigger); + } else { + await this.authenticator.startAndCancelPasskeyOperation(operationTrigger, () => + expect(this.page.locator('.cb-notification-text')).toHaveText('You have cancelled setting up your passkey. Please try again.'), + ); + } + } +} diff --git a/packages/tests-e2e/src/connect/scenarios/append.spec.ts b/packages/tests-e2e/src/connect/scenarios/append.spec.ts index e69de29bb..9afd56cc3 100644 --- a/packages/tests-e2e/src/connect/scenarios/append.spec.ts +++ b/packages/tests-e2e/src/connect/scenarios/append.spec.ts @@ -0,0 +1,17 @@ +import { test } from '../fixtures/BaseTest'; +import { ScreenNames } from '../utils/Constants'; +import { loadPasskeyAppend, setupUser, setupVirtualAuthenticator } from './hooks'; + +test.describe('append component', () => { + setupVirtualAuthenticator(test); + setupUser(test, true, false); + loadPasskeyAppend(test); + + test('successful passkey append on login', async ({ model }) => { + await model.append.appendPasskey(); + await model.expectScreen(ScreenNames.PasskeyAppended); + + await model.append.confirmAppended(); + await model.expectScreen(ScreenNames.Home); + }); +}); diff --git a/packages/tests-e2e/src/connect/scenarios/hooks.ts b/packages/tests-e2e/src/connect/scenarios/hooks.ts index 2b1eafdf2..b735b6ac9 100644 --- a/packages/tests-e2e/src/connect/scenarios/hooks.ts +++ b/packages/tests-e2e/src/connect/scenarios/hooks.ts @@ -7,7 +7,7 @@ import type { } from '@playwright/test'; import type { BaseModel } from '../models/BaseModel'; -import { ScreenNames } from '../utils/Constants'; +import { password, ScreenNames } from '../utils/Constants'; export function setupVirtualAuthenticator( test: TestType< @@ -77,3 +77,35 @@ export function setupUser( // await model.deleteUser(); // }); } + +// assumes that setupUser(test, true, false) has been called right before +export function loadPasskeyAppend( + test: TestType< + PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, + PlaywrightWorkerArgs & PlaywrightWorkerOptions + >, +) { + test.beforeEach(async ({ model }) => { + await model.home.logout(); + await model.expectScreen(ScreenNames.InitLogin); + + await model.login.submitEmail(model.email, false); + await model.expectScreen(ScreenNames.InitLoginFallback); + + await model.login.submitFallbackCredentials(model.email, password, true); + await model.expectScreen(ScreenNames.PasskeyAppend); + }); +} + +// assumes that setupUser(test, true, true) has been called right before +export function loadPasskeyList( + test: TestType< + PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, + PlaywrightWorkerArgs & PlaywrightWorkerOptions + >, +) { + test.beforeEach(async ({ model }) => { + await model.home.gotoPasskeyList(); + await model.expectScreen(ScreenNames.PasskeyList); + }); +} diff --git a/packages/tests-e2e/src/connect/scenarios/passkey-list.spec.ts b/packages/tests-e2e/src/connect/scenarios/passkey-list.spec.ts index e69de29bb..1d102baae 100644 --- a/packages/tests-e2e/src/connect/scenarios/passkey-list.spec.ts +++ b/packages/tests-e2e/src/connect/scenarios/passkey-list.spec.ts @@ -0,0 +1,16 @@ +import { test } from '../fixtures/BaseTest'; +import { loadPasskeyList, setupUser, setupVirtualAuthenticator } from './hooks'; + +test.describe('passkey-list component', () => { + setupVirtualAuthenticator(test); + setupUser(test, true, true); + loadPasskeyList(test); + + test('list, delete, append passkey', async ({ model }) => { + await model.passkeyList.expectPasskeys(1); + await model.passkeyList.deletePasskey(0); + await model.passkeyList.expectPasskeys(0); + await model.passkeyList.appendPasskey(true); + await model.passkeyList.expectPasskeys(1); + }); +}); diff --git a/packages/tests-e2e/src/connect/utils/Constants.ts b/packages/tests-e2e/src/connect/utils/Constants.ts index 0799d6662..3b3a444d4 100644 --- a/packages/tests-e2e/src/connect/utils/Constants.ts +++ b/packages/tests-e2e/src/connect/utils/Constants.ts @@ -6,6 +6,7 @@ export enum ScreenNames { PasskeyAppend, PasskeyAppended, Home, + PasskeyList, } export const phone = '+4915121609839'; diff --git a/packages/tests-e2e/src/connect/utils/ExpectScreen.ts b/packages/tests-e2e/src/connect/utils/ExpectScreen.ts index 8919f1109..a27179fb8 100644 --- a/packages/tests-e2e/src/connect/utils/ExpectScreen.ts +++ b/packages/tests-e2e/src/connect/utils/ExpectScreen.ts @@ -37,6 +37,10 @@ export const expectScreen = async (page: Page, screenName: ScreenNames) => { await expect(page.locator('div.font-bold.text-xl')).toHaveText('Home'); return; + case ScreenNames.PasskeyList: + await expect(page.locator('.cb-connect-passkey-list')).toBeVisible(); + return; + default: throw new Error('Invalid screen'); } From ff5763ec21b17987a8cd6f42662c21f17a1e57ca Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 8 Jan 2025 15:03:10 +0100 Subject: [PATCH 08/10] add react connect to nightly test runs --- .github/workflows/e2e-test-nightly.yml | 31 +++++++++++++++++++++----- packages/tests-e2e/.env.connect.ci | 6 ++--- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/.github/workflows/e2e-test-nightly.yml b/.github/workflows/e2e-test-nightly.yml index 213f5366b..d8e095e11 100644 --- a/.github/workflows/e2e-test-nightly.yml +++ b/.github/workflows/e2e-test-nightly.yml @@ -64,7 +64,7 @@ jobs: cd packages/tests-e2e npx playwright install --with-deps - - name: Install and run E2E Test for react + - name: Run Complete Tests for react run: | cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') @@ -84,11 +84,11 @@ jobs: - uses: actions/upload-artifact@v4 if: always() with: - name: playwright-report-react + name: playwright-report-complete-react path: packages/tests-e2e/playwright-report/ retention-days: 30 - - name: Install and run E2E Test for web-js + - name: Run Complete Tests for web-js run: | cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') @@ -108,11 +108,11 @@ jobs: - uses: actions/upload-artifact@v4 if: always() with: - name: playwright-report-web-js + name: playwright-report-complete-web-js path: packages/tests-e2e/playwright-report/ retention-days: 30 - - name: Install and run E2E Test for web-js-script + - name: Run Complete Tests for web-js-script run: | cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') @@ -132,6 +132,25 @@ jobs: - uses: actions/upload-artifact@v4 if: always() with: - name: playwright-report-web-js-script + name: playwright-report-complete-web-js-script + path: packages/tests-e2e/playwright-report/ + retention-days: 30 + + - name: Run Connect Tests for react + run: | + cd packages/tests-e2e + BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') + export PLAYWRIGHT_TEST_URL="https://$BRANCH_NAME.connect-next.playground.corbado.io" + PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.connect.ts + env: + PLAYWRIGHT_NUM_CORES: 4 + GITHUB_RUN_ID: ${{ github.run_id }} + SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} + GITHUB_BRANCH_NAME: ${{ env.BRANCH_NAME_RAW }} + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report-connect-react path: packages/tests-e2e/playwright-report/ retention-days: 30 diff --git a/packages/tests-e2e/.env.connect.ci b/packages/tests-e2e/.env.connect.ci index 636344bea..d49ab9346 100644 --- a/packages/tests-e2e/.env.connect.ci +++ b/packages/tests-e2e/.env.connect.ci @@ -1,3 +1,3 @@ -DEVELOPERPANEL_API_URL=https://console.cloud.corbado-staging.io -BACKEND_API_URL=https://backendapi.cloud.corbado-staging.io -FRONTEND_API_URL_SUFFIX=frontendapi.cloud.corbado-staging.io +#DEVELOPERPANEL_API_URL=https://console.cloud.corbado-staging.io +#BACKEND_API_URL=https://backendapi.cloud.corbado-staging.io +#FRONTEND_API_URL_SUFFIX=frontendapi.cloud.corbado-staging.io From 419519e1c140b17142e606b8f8f224596778f1a7 Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 8 Jan 2025 15:05:23 +0100 Subject: [PATCH 09/10] prettier --- packages/tests-e2e/src/connect/models/PasskeyListModel.ts | 4 +++- packages/tests-e2e/src/connect/scenarios/hooks.ts | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/tests-e2e/src/connect/models/PasskeyListModel.ts b/packages/tests-e2e/src/connect/models/PasskeyListModel.ts index 01c1c6c17..52f47392e 100644 --- a/packages/tests-e2e/src/connect/models/PasskeyListModel.ts +++ b/packages/tests-e2e/src/connect/models/PasskeyListModel.ts @@ -27,7 +27,9 @@ export class PasskeyListModel { await this.authenticator.startAndCompletePasskeyOperation(operationTrigger); } else { await this.authenticator.startAndCancelPasskeyOperation(operationTrigger, () => - expect(this.page.locator('.cb-notification-text')).toHaveText('You have cancelled setting up your passkey. Please try again.'), + expect(this.page.locator('.cb-notification-text')).toHaveText( + 'You have cancelled setting up your passkey. Please try again.', + ), ); } } diff --git a/packages/tests-e2e/src/connect/scenarios/hooks.ts b/packages/tests-e2e/src/connect/scenarios/hooks.ts index b735b6ac9..eaa287ded 100644 --- a/packages/tests-e2e/src/connect/scenarios/hooks.ts +++ b/packages/tests-e2e/src/connect/scenarios/hooks.ts @@ -61,7 +61,9 @@ export function setupUser( test: TestType< PlaywrightTestArgs & PlaywrightTestOptions & { model: BaseModel }, PlaywrightWorkerArgs & PlaywrightWorkerOptions - >, invited = true, append = true, + >, + invited = true, + append = true, ) { test.beforeEach(async ({ model }) => { if (invited) { From 522e46788445457af3ad980303349c82869cf7f4 Mon Sep 17 00:00:00 2001 From: aehnh Date: Wed, 8 Jan 2025 15:44:33 +0100 Subject: [PATCH 10/10] add connect tests to commitly runs --- .github/workflows/e2e-test-commitly.yml | 23 +++++++++++++++++++++-- .github/workflows/e2e-test-nightly.yml | 8 ++++---- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/.github/workflows/e2e-test-commitly.yml b/.github/workflows/e2e-test-commitly.yml index 9c58dd2aa..ccfc611ca 100644 --- a/.github/workflows/e2e-test-commitly.yml +++ b/.github/workflows/e2e-test-commitly.yml @@ -65,7 +65,7 @@ jobs: cd packages/tests-e2e npx playwright install --with-deps - - name: Install and run E2E Test for react + - name: Run Complete tests for react run: | cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') @@ -85,6 +85,25 @@ jobs: - uses: actions/upload-artifact@v4 if: always() with: - name: playwright-report + name: playwright-report-complete-react + path: packages/tests-e2e/playwright-report/ + retention-days: 30 + + - name: Run Connect tests for react + run: | + cd packages/tests-e2e + BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') + export PLAYWRIGHT_TEST_URL="https://$BRANCH_NAME.connect-next.playground.corbado.io" + PLAYWRIGHT_TEST_URL=$PLAYWRIGHT_TEST_URL npx playwright test --config=playwright.config.connect.ts + env: + PLAYWRIGHT_NUM_CORES: 4 + GITHUB_RUN_ID: ${{ github.run_id }} + SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }} + GITHUB_BRANCH_NAME: ${{ env.BRANCH_NAME_RAW }} + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report-connect-react path: packages/tests-e2e/playwright-report/ retention-days: 30 diff --git a/.github/workflows/e2e-test-nightly.yml b/.github/workflows/e2e-test-nightly.yml index d8e095e11..5250c1979 100644 --- a/.github/workflows/e2e-test-nightly.yml +++ b/.github/workflows/e2e-test-nightly.yml @@ -64,7 +64,7 @@ jobs: cd packages/tests-e2e npx playwright install --with-deps - - name: Run Complete Tests for react + - name: Run Complete tests for react run: | cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') @@ -88,7 +88,7 @@ jobs: path: packages/tests-e2e/playwright-report/ retention-days: 30 - - name: Run Complete Tests for web-js + - name: Run Complete tests for web-js run: | cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') @@ -112,7 +112,7 @@ jobs: path: packages/tests-e2e/playwright-report/ retention-days: 30 - - name: Run Complete Tests for web-js-script + - name: Run Complete tests for web-js-script run: | cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-') @@ -136,7 +136,7 @@ jobs: path: packages/tests-e2e/playwright-report/ retention-days: 30 - - name: Run Connect Tests for react + - name: Run Connect tests for react run: | cd packages/tests-e2e BRANCH_NAME=$(echo $BRANCH_NAME_RAW | tr '/_' '-')