Skip to content

Commit 8ff331e

Browse files
authored
Improve observe tests (#592)
* Improve Observe Tests * p1 * px * px * px * px * cleanup * px * px * Prepare
1 parent 2de1cd5 commit 8ff331e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+450
-614
lines changed

.github/workflows/test-all.yml

Lines changed: 71 additions & 195 deletions
Large diffs are not rendered by default.

.github/workflows/test.yml

Lines changed: 42 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
name: Test on React
2-
env:
3-
BRANCH_NAME_RAW: ${{ github.head_ref || github.ref_name }}
42

53
on:
64
pull_request:
@@ -12,6 +10,7 @@ jobs:
1210
test:
1311
timeout-minutes: 60
1412
runs-on: ubuntu-24.04
13+
environment: ${{ matrix.testType }}
1514
strategy:
1615
fail-fast: false
1716
matrix:
@@ -20,33 +19,29 @@ jobs:
2019
configFile: playwright.config.complete.ts
2120
- testType: connect
2221
configFile: playwright.config.connect.ts
23-
env:
24-
PLAYWRIGHT_NUM_CORES: 4
25-
PLAYWRIGHT_TEST_URL: ${{ secrets.PLAYWRIGHT_TEST_URL }}
2622

27-
PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }}
28-
PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }}
29-
PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }}
23+
env:
24+
# ── Shared (hardcoded) ──
25+
PLAYWRIGHT_NUM_CORES: 4
26+
DEFAULT_CORBADO_BACKEND_API_BASIC_AUTH: ${{ secrets.DEFAULT_CORBADO_BACKEND_API_BASIC_AUTH }}
27+
28+
# ── "complete" environment secrets (empty on connect runners) ──
29+
PLAYWRIGHT_JWT_TOKEN: ${{ secrets.PLAYWRIGHT_JWT_TOKEN }}
30+
PLAYWRIGHT_GOOGLE_EMAIL: ${{ secrets.PLAYWRIGHT_GOOGLE_EMAIL }}
31+
PLAYWRIGHT_GOOGLE_PASSWORD: ${{ secrets.PLAYWRIGHT_GOOGLE_PASSWORD }}
3032
PLAYWRIGHT_GOOGLE_TOTP_SECRET: ${{ secrets.PLAYWRIGHT_GOOGLE_TOTP_SECRET }}
3133

32-
NEXT_PUBLIC_CORBADO_PROJECT_ID: ${{ secrets.NEXT_PUBLIC_CORBADO_PROJECT_ID }}
33-
NEXT_PUBLIC_CORBADO_FRONTEND_API_URL_SUFFIX: ${{ secrets.NEXT_PUBLIC_CORBADO_FRONTEND_API_URL_SUFFIX }}
34-
CORBADO_BACKEND_API_URL: ${{ secrets.CORBADO_BACKEND_API_URL }}
35-
CORBADO_BACKEND_API_BASIC_AUTH: ${{ secrets.CORBADO_BACKEND_API_BASIC_AUTH }}
36-
PLAYWRIGHT_CONNECT_PROJECT_ID: ${{ secrets.PLAYWRIGHT_CONNECT_PROJECT_ID }}
37-
PLAYWRIGHT_NGROK_AUTH_TOKEN: ${{ secrets.PLAYWRIGHT_NGROK_AUTH_TOKEN }}
38-
AWS_COGNITO_USER_POOL_ID: ${{ secrets.AWS_COGNITO_USER_POOL_ID }}
39-
NEXT_PUBLIC_AWS_COGNITO_USER_POOL_ID: ${{ secrets.AWS_COGNITO_USER_POOL_ID }}
40-
AWS_COGNITO_CLIENT_ID: ${{ secrets.AWS_COGNITO_CLIENT_ID }}
41-
NEXT_PUBLIC_AWS_COGNITO_CLIENT_ID: ${{ vars.NEXT_PUBLIC_AWS_COGNITO_CLIENT_ID }}
42-
AWS_COGNITO_CLIENT_SECRET: ${{ secrets.AWS_COGNITO_CLIENT_SECRET }}
43-
AWS_REGION: ${{ secrets.AWS_REGION }}
44-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_CONNECT_PLAYGROUND }}
45-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_CONNECT_PLAYGROUND }}
46-
47-
GITHUB_RUN_ID: ${{ github.run_id }}
48-
SLACK_BOT_USER_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_USER_OAUTH_TOKEN }}
49-
GITHUB_BRANCH_NAME: ${{ github.ref_name }}
34+
# ── "connect" environment secrets (empty on complete runners) ──
35+
NEXT_PUBLIC_AWS_COGNITO_USER_POOL_ID: ${{ secrets.AWS_COGNITO_USER_POOL_ID }}
36+
NEXT_PUBLIC_AWS_COGNITO_CLIENT_ID: ${{ vars.NEXT_PUBLIC_AWS_COGNITO_CLIENT_ID }}
37+
CORBADO_BACKEND_API_BASIC_AUTH: ${{ secrets.DEFAULT_CORBADO_BACKEND_API_BASIC_AUTH }}
38+
PLAYWRIGHT_NGROK_AUTH_TOKEN: ${{ secrets.PLAYWRIGHT_NGROK_AUTH_TOKEN }}
39+
AWS_COGNITO_USER_POOL_ID: ${{ secrets.AWS_COGNITO_USER_POOL_ID }}
40+
AWS_COGNITO_CLIENT_ID: ${{ secrets.AWS_COGNITO_CLIENT_ID }}
41+
AWS_COGNITO_CLIENT_SECRET: ${{ secrets.AWS_COGNITO_CLIENT_SECRET }}
42+
AWS_REGION: ${{ secrets.AWS_REGION }}
43+
AWS_ACCESS_KEY_ID: ${{ secrets.COGNITO_AWS_ACCESS_KEY_ID }}
44+
AWS_SECRET_ACCESS_KEY: ${{ secrets.COGNITO_AWS_SECRET_ACCESS_KEY }}
5045

5146
steps:
5247
- name: Checkout code
@@ -59,7 +54,7 @@ jobs:
5954

6055
- name: Cache node modules
6156
id: cache-npm
62-
uses: actions/cache@v3
57+
uses: actions/cache@v4
6358
env:
6459
cache-name: cache-node-modules
6560
with:
@@ -86,23 +81,22 @@ jobs:
8681
8782
- name: Get installed Playwright version
8883
id: playwright-version
89-
run: echo "::set-output name=version::$(yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://')"
84+
run: echo "version=$(yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://')" >> "$GITHUB_OUTPUT"
9085

9186
- if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
9287
name: List the state of node modules
9388
continue-on-error: true
94-
run: |
95-
cd packages/tests-e2e
96-
npm list
89+
working-directory: packages/tests-e2e
90+
run: npm list
9791

9892
- name: Install dependencies
93+
working-directory: packages/tests-e2e
9994
run: |
100-
cd packages/tests-e2e
10195
npm install
10296
sudo apt-get update
10397
sudo apt-get install -y libxml2-utils
10498
105-
- uses: actions/cache@v3
99+
- uses: actions/cache@v4
106100
id: playwright-cache
107101
with:
108102
path: '~/.cache/ms-playwright'
@@ -112,26 +106,24 @@ jobs:
112106
113107
- name: Install Playwright's dependencies
114108
if: steps.playwright-cache.outputs.cache-hit != 'true'
115-
run: |
116-
cd packages/tests-e2e
117-
npx playwright install --with-deps
109+
working-directory: packages/tests-e2e
110+
run: npx playwright install --with-deps
118111

119-
- name: Create a log stream on AWS CloudWatch
112+
- name: Create CloudWatch log stream
120113
env:
121-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
122-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
114+
AWS_ACCESS_KEY_ID: ${{ vars.CLOUDWATCH_AWS_ACCESS_KEY_ID }}
115+
AWS_SECRET_ACCESS_KEY: ${{ secrets.CLOUDWATCH_AWS_SECRET_ACCESS_KEY }}
123116
AWS_REGION: ${{ secrets.AWS_REGION }}
124117
run: |
125118
TIMESTAMP=$(date +%s000)
126-
RANDOM_SUFFIX=$(head /dev/urandom | tr -dc a-z0-9 | head -c 6)
119+
RANDOM_SUFFIX=$(head /dev/urandom | tr -dc 'a-z0-9' | head -c 6)
127120
LOG_STREAM_NAME="javascript-${TIMESTAMP}-${RANDOM_SUFFIX}"
128-
echo "LOG_STREAM_NAME=$LOG_STREAM_NAME" >> $GITHUB_ENV
121+
echo "LOG_STREAM_NAME=$LOG_STREAM_NAME" >> "$GITHUB_ENV"
129122
aws logs create-log-stream --log-group-name "test-results-board" --log-stream-name "$LOG_STREAM_NAME"
130123
131124
- name: Run ${{ matrix.testType }} tests for react
132125
working-directory: packages/tests-e2e
133-
run: |
134-
npx playwright test --config=${{ matrix.configFile }}
126+
run: npx playwright test --config=${{ matrix.configFile }}
135127

136128
- uses: actions/upload-artifact@v4
137129
if: always()
@@ -140,21 +132,14 @@ jobs:
140132
path: packages/tests-e2e/playwright-report/
141133
retention-days: 30
142134

143-
- name: Send logs to AWS CloudWatch
135+
- name: Send results to CloudWatch
144136
if: always()
145137
env:
146-
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
147-
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
138+
AWS_ACCESS_KEY_ID: ${{ vars.CLOUDWATCH_AWS_ACCESS_KEY_ID }}
139+
AWS_SECRET_ACCESS_KEY: ${{ secrets.CLOUDWATCH_AWS_SECRET_ACCESS_KEY }}
148140
AWS_REGION: ${{ secrets.AWS_REGION }}
149141
run: |
150-
cd packages/tests-e2e
151-
TESTS=$(xmllint --xpath 'string(/testsuites/@tests)' test-results/results.xml)
152-
FAILURES=$(xmllint --xpath 'string(/testsuites/@failures)' test-results/results.xml)
153-
SKIPPED=$(xmllint --xpath 'string(/testsuites/@skipped)' test-results/results.xml)
154-
ERRORS=$(xmllint --xpath 'string(/testsuites/@errors)' test-results/results.xml)
155-
TIME=$(xmllint --xpath 'string(/testsuites/@time)' test-results/results.xml)
156-
PASSED=$((TESTS - FAILURES - ERRORS - SKIPPED))
157-
FAILED=$((FAILURES + ERRORS))
158-
TIMESTAMP=$(date +%s000)
159-
LOG_EVENT_JSON="[{\"timestamp\":$TIMESTAMP,\"message\":\"{\\\"application\\\":\\\"${{ matrix.testType }}\\\",\\\"platform\\\":\\\"react\\\",\\\"run_type\\\":\\\"commitly\\\",\\\"execution_time\\\":$TIME,\\\"passed\\\":$PASSED,\\\"failed\\\":$FAILED,\\\"link\\\":\\\"https://github.com/corbado/javascript/actions/runs/${GITHUB_RUN_ID}\\\"}\"}]"
160-
aws logs put-log-events --log-group-name "test-results-board" --log-stream-name "$LOG_STREAM_NAME" --log-events "$LOG_EVENT_JSON"
142+
bash scripts/cloudwatch-log.sh \
143+
"${{ matrix.testType }}" \
144+
"react" \
145+
"commitly"

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ packages/tests-e2e/.env.connect.local
3030

3131
# scripts
3232
scripts/*.sh
33-
.env*.local
33+
!scripts/cloudwatch-log.sh
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
12
DEVELOPERPANEL_API_URL=https://console.cloud.corbado-staging.io
2-
CORBADO_BACKEND_API_URL=https://backendapi.cloud.corbado-staging.io
3-
CORBADO_BACKEND_API_BASIC_AUTH=
43
FRONTEND_API_URL_SUFFIX=frontendapi.cloud.corbado-staging.io
5-
PLAYWRIGHT_COMPLETE_OBSERVE_PROJECT_ID=
4+
5+
NEXT_PUBLIC_DEFAULT_CORBADO_PROJECT_ID=pro-4505536417832482032
6+
NEXT_PUBLIC_CORBADO_FRONTEND_API_URL_SUFFIX=frontendapi.cloud.corbado-staging.io
7+
CORBADO_BACKEND_API_URL=https://backendapi.cloud.corbado-staging.io

packages/tests-e2e/.env.complete.example

Lines changed: 0 additions & 10 deletions
This file was deleted.

packages/tests-e2e/.env.connect.ci

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
DEVELOPERPANEL_API_URL=https://console.cloud.corbado-staging.io
2+
3+
NEXT_PUBLIC_CORBADO_PROJECT_ID=pro-4641896612641727554
4+
NEXT_PUBLIC_CORBADO_FRONTEND_API_URL_SUFFIX=frontendapi.cloud.corbado-staging.io
15
CORBADO_BACKEND_API_URL=https://backendapi.cloud.corbado-staging.io
2-
#DEVELOPERPANEL_API_URL=https://console.cloud.corbado-staging.io
3-
#FRONTEND_API_URL_SUFFIX=frontendapi.cloud.corbado-staging.io

packages/tests-e2e/.env.connect.example

Lines changed: 0 additions & 6 deletions
This file was deleted.

packages/tests-e2e/README.md

Lines changed: 53 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,74 @@
1-
# `tests-e2e`
1+
# tests-e2e
22

3-
This package currently contains all the end-to-end tests for testing the React package. We plan to extend the tests for other packages of Corbado JavaScript Library.
3+
End-to-end tests for the Corbado JavaScript SDK, using Playwright.
44

5-
## Running Tests Locally
5+
## Overview
66

7-
Playground is locally run within Playwright for both Complete and Connect tests. For reference look at `utils/playground.ts`.
7+
### Playground applications
88

9-
This means that tests can simply be run with a single command. The command depends on whether you want to run it headless or with UI.
9+
Each SDK has a corresponding **playground application** in `playground/`:
1010

11-
### Headless
11+
| Playground | SDK | Framework |
12+
| -------------------------- | ------------------------------ | -------------- |
13+
| `playground/react` | `@corbado/react` | Vite + React |
14+
| `playground/web-js` | `@corbado/web-js` | Vite (vanilla) |
15+
| `playground/web-js-script` | `@corbado/web-js` (script tag) | Vite (vanilla) |
16+
| `playground/connect-next` | `@corbado/connect-react` | Next.js |
1217

13-
```
14-
cd packages/tests-e2e
15-
npm run e2e:complete
16-
npm run e2e:connect
17-
```
18+
Playgrounds serve two purposes:
1819

19-
### With UI
20+
1. **Manual testing** — each playground can be started locally (`npm run dev`) and is deployed automatically to Vercel on every push. This gives a quick way to verify SDK behaviour in a real browser without writing tests.
21+
2. **Automated testing** — Playwright tests run _on top of_ these playgrounds. The `globalSetup` in each test suite installs dependencies, builds the playground, and spawns it on a random port before tests start. No manual playground setup is needed.
2022

21-
```
23+
### Test suites
24+
25+
Because multiple playgrounds can expose the same SDK surface, a single Playwright suite can be **reused across different playground apps**. For example, the three Complete playgrounds (`react`, `web-js`, `web-js-script`) all render the same auth UI component, so they share the same test suite — only the playground that gets spawned changes.
26+
27+
There are two test suites:
28+
29+
- **Complete** — tests the full Corbado auth UI component (signup, login, passkey list, social login, observe). By default runs against the React playground; in the nightly workflow it also runs against `web-js` and `web-js-script`.
30+
- **Connect** — tests the Corbado Connect passkey integration (login, append, network blocking). Runs against the Next.js playground that talks to AWS Cognito.
31+
32+
Each suite has its own Playwright config (`playwright.config.complete.ts` / `playwright.config.connect.ts`) and env files.
33+
34+
## Running locally
35+
36+
### 1. Set up env files
37+
38+
Copy the example files and fill in the secrets:
39+
40+
```bash
2241
cd packages/tests-e2e
23-
npm run e2e:complete:ui
24-
npm run e2e:connect:ui
42+
cp .env.complete.example .env.complete.local
43+
cp .env.connect.example .env.connect.local
2544
```
2645

27-
## Generating JWT Token
46+
Edit `.env.complete.local` and `.env.connect.local` with the required values. See the [Environment variables](#environment-variables) section below.
2847

29-
The following is the script used to generate the JWT token.
48+
### 2. Run tests
3049

3150
```bash
32-
#!/bin/bash
33-
34-
PRIVATE_KEY_PATH="private.pem"
35-
KID="pki-..."
36-
ISS="https://auth.corbado-dev.com"
37-
USER_ID="usr-..."
38-
USER_NAME="systemtest"
39-
USER_EMAIL="anders.choi+systemtest@corbado.com"
40-
41-
NOW=$( date +%s )
42-
IAT=${NOW}
43-
EXP=$((${NOW} + 3000000)) # after around 34 days
44-
NBF=$((${NOW} - 10)) # 10 seconds ago
45-
HEADER_RAW='{"alg":"RS256","kid":"'"${KID}"'","typ":"JWT"}'
46-
HEADER=$( echo -n "${HEADER_RAW}" | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n' )
47-
PAYLOAD_RAW='{"iss":"'"${ISS}"'","sub":"'"${USER_ID}"'","exp":'"${EXP}"',"nbf":'"${NBF}"',"iat":'"${IAT}"',"name":"'"${USER_NAME}"'","orig":"'"${USER_EMAIL}"'","email":"'"${USER_EMAIL}"'","version":2}'
48-
PAYLOAD=$( echo -n "${PAYLOAD_RAW}" | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n' )
49-
HEADER_PAYLOAD="${HEADER}.${PAYLOAD}"
50-
SIGNATURE=$( openssl dgst -sha256 -sign ${PRIVATE_KEY_PATH} <(echo -n "${HEADER_PAYLOAD}") | openssl base64 | tr -d '=' | tr '/+' '_-' | tr -d '\n' )
51-
JWT="${HEADER_PAYLOAD}.${SIGNATURE}"
52-
53-
echo $JWT
51+
cd packages/tests-e2e
52+
53+
# Headless
54+
npm run e2e:complete
55+
npm run e2e:connect
56+
57+
# With Playwright UI
58+
npm run e2e:complete:ui
59+
npm run e2e:connect:ui
5460
```
5561

56-
The first segment of the script contains all the information that must be extracted from the backend deployment.
62+
## Running in CI
63+
64+
### Workflows
5765

58-
As evident in the script, the token is valid for around 34 days. The token is intended to be renewed monthly using this script. For rewnewal, it is not necessary to extract all the information in the first segment.
66+
| Workflow | Trigger | What it does |
67+
| -------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------- |
68+
| `test.yml` | PR + push to develop | Runs Complete and Connect tests for **react** platform only (matrix) |
69+
| `test-all.yml` | Nightly schedule (3x/day) + manual | Runs Complete tests for **react, web-js, web-js-script** + Connect tests for **react** (matrix, parallel) |
5970

60-
## Authoring rules (connect2)
71+
## Authoring rules (connect)
6172

6273
- Knowledge about page structure lives in `/models` only. Scenarios call model methods, not raw selectors.
6374
- All passkey authenticator interactions flow through `VirtualAuthenticator`.

packages/tests-e2e/playwright.config.complete.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ export default defineConfig({
6666
// ],
6767
['html'],
6868
['junit', { outputFile: 'test-results/results.xml' }],
69+
['./src/complete/utils/log-reporter.ts'],
6970
],
7071
timeout: totalTimeout, // default: 30000ms
7172
expect: {
@@ -74,7 +75,6 @@ export default defineConfig({
7475
use: {
7576
actionTimeout: operationTimeout, // default: none
7677
navigationTimeout: operationTimeout, // default: none
77-
// baseURL: process.env.PLAYWRIGHT_TEST_URL,
7878
screenshot: 'only-on-failure',
7979
video: 'retain-on-failure',
8080
trace: 'retain-on-failure',
@@ -92,10 +92,14 @@ export default defineConfig({
9292
name: 'passkey-list-general',
9393
testMatch: ['scenarios/passkey-list-general/*.ts'],
9494
},
95-
//{
96-
// name: 'observe',
97-
// testMatch: ['scenarios/observe/*.ts'],
98-
//},
95+
...(!process.env.CI
96+
? [
97+
{
98+
name: 'observe',
99+
testMatch: ['scenarios/observe/*.ts'],
100+
},
101+
]
102+
: []),
99103
],
100104
globalSetup: 'src/complete/utils/playground.ts',
101105
});

packages/tests-e2e/src/complete/models/CorbadoAuthModel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class CorbadoAuthModel {
3737
async load(projectId: string, port: number, passkeySupport?: boolean, hashCode?: string) {
3838
this.projectId = projectId;
3939

40-
let url = `${process.env.PLAYWRIGHT_TEST_URL}:${port.toString()}/${this.projectId}/auth`;
40+
let url = `http://localhost:${port.toString()}/${this.projectId}/auth`;
4141
if (hashCode) {
4242
url += `#${hashCode}`;
4343
}

0 commit comments

Comments
 (0)