Skip to content

Commit b4d2fae

Browse files
committed
fix: e2e tests
1 parent 9317322 commit b4d2fae

File tree

7 files changed

+218
-35
lines changed

7 files changed

+218
-35
lines changed

.github/workflows/e2e.yml

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,67 @@ jobs:
3131
aztec-up 3.0.0-devnet.20251212
3232
aztec start --local-network &
3333
34+
- name: Wait for local network to be ready
35+
run: |
36+
echo "Waiting for Aztec node to be ready..."
37+
timeout 300 bash -c 'until curl -s http://localhost:8080/status > /dev/null 2>&1; do sleep 5; echo "Waiting..."; done'
38+
echo "Aztec node is ready!"
39+
3440
- name: Install dependencies
3541
run: yarn install
3642

3743
- name: Install Playwright Browsers
3844
run: yarn playwright install --with-deps
3945

40-
- name: Build
41-
run: yarn build
46+
- name: Build contracts
47+
run: yarn build-contracts
48+
49+
- name: Deploy contracts
50+
run: PROVER_ENABLED=false yarn deploy-contracts
51+
52+
- name: Build app (after deploy so env vars are available)
53+
run: yarn build-app
54+
55+
- name: Start static server
56+
run: |
57+
echo "Starting static server..."
58+
yarn serve:static &
59+
SERVER_PID=$!
60+
echo $SERVER_PID > server.pid
61+
echo "Server PID: $SERVER_PID"
62+
echo "Waiting for server to be ready..."
63+
timeout 60 bash -c 'until curl -sf http://127.0.0.1:3000 > /dev/null 2>&1; do sleep 2; echo "Waiting..."; done'
64+
echo "Server is up!"
65+
66+
- name: Run Playwright tests
67+
run: |
68+
echo "=== Starting Playwright tests ==="
69+
echo "Server status: $(curl --max-time 5 -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3000)"
70+
echo "Node status: $(curl --max-time 5 -s -o /dev/null -w '%{http_code}' http://localhost:8080/status)"
71+
echo "=== Running Playwright with xvfb-run ==="
72+
xvfb-run --auto-servernum -- npx playwright test --reporter=list --timeout=120000
73+
env:
74+
CI: true
75+
FORCE_COLOR: 1
76+
DEBUG: pw:browser*
77+
78+
- name: Upload Playwright traces
79+
uses: actions/upload-artifact@v4
80+
if: always()
81+
with:
82+
name: playwright-traces
83+
path: test-results/
84+
retention-days: 7
85+
86+
- name: Setup tmate session on failure
87+
if: failure()
88+
uses: mxschmitt/action-tmate@v3
89+
timeout-minutes: 15
4290

43-
- name: Run tests
44-
run: yarn test
91+
- name: Stop server
92+
if: always()
93+
run: |
94+
if [ -f server.pid ]; then
95+
kill $(cat server.pid) || true
96+
rm server.pid
97+
fi

CI_DEBUG_CHANGELOG.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# CI Debug Changelog
2+
3+
## Attempt 9
4+
**Changes:**
5+
- Added `xvfb-run --auto-servernum --` prefix to Playwright command
6+
- Changed DEBUG to `pw:browser*` for browser-level debugging
7+
- Removed timeout wrapper to see actual Playwright output
8+
9+
**Hypothesis:** Headless browser needs X virtual framebuffer (xvfb) on Linux CI
10+
11+
---
12+
13+
## Attempt 8 - Playwright timed out
14+
**Changes:**
15+
- Added `--max-time 5` to curl commands to prevent hanging
16+
- Added `timeout 120` wrapper around entire Playwright command
17+
18+
**Result:** Server & node returned 200, but Playwright timed out with exit code 124 - no output at all!
19+
20+
---
21+
22+
## Attempt 7 - STUCK
23+
**Changes:**
24+
- Added diagnostic echo commands before/after Playwright
25+
- Check server status (curl) before running tests
26+
- Check Aztec node status before running tests
27+
- Added **short timeout (60s)** to force quick failure for debugging
28+
29+
**Result:** Still no output after 9+ minutes - even echo commands not visible
30+
31+
---
32+
33+
## Attempt 6 - STUCK
34+
**Changes:**
35+
- Simplified to **single browser (chromium)** in CI
36+
- Disabled `fullyParallel` in CI
37+
- Changed `yarn playwright` to `npx playwright` (avoid yarn wrapper issues)
38+
- Added `PLAYWRIGHT_BROWSERS_PATH: 0` env var
39+
40+
**Result:** Still no output from Playwright after 10+ minutes
41+
42+
---
43+
44+
## Attempt 5 - STUCK
45+
**Changes:**
46+
- Added `DEBUG: pw:api` env var for Playwright debug output
47+
- Added `--trace=on` flag to Playwright for trace recording
48+
- Added artifact upload for `test-results/` directory
49+
- Added **tmate SSH debugging** on failure (15 min timeout)
50+
51+
**Result:** Still no output from Playwright tests after 10+ minutes
52+
53+
---
54+
55+
## Attempt 4 - STUCK (tests still hanging)
56+
**Changes:**
57+
- Fixed config path: `-c ../serve.json` (path is relative to served directory `dist/`)
58+
59+
**Result:** Server started correctly with COOP/COEP headers, but Playwright tests still hang with no output
60+
61+
---
62+
63+
## Attempt 3 - FAILED
64+
**Changes:**
65+
- Added `serve.json` with COOP/COEP headers required for SharedArrayBuffer
66+
- Headers: `Cross-Origin-Opener-Policy: same-origin` and `Cross-Origin-Embedder-Policy: require-corp`
67+
68+
**Result:** Config path wrong - serve looked in `dist/serve.json` instead of project root
69+
70+
---
71+
72+
## Attempt 2 - STUCK
73+
**Changes:**
74+
- Fixed serve:static to use `dist` instead of `app/dist` (webpack outputs to `./dist/` by default)
75+
- Fixed clean script to remove `dist` instead of `app/dist`
76+
77+
**Result:** Server started successfully (no more 404), but Playwright tests hung with no output after 34+ minutes
78+
79+
---
80+
81+
## Attempt 1 (88ee488) - FAILED
82+
**Changes:**
83+
- Disabled Playwright webServer in CI (set to `undefined` when `process.env.CI`)
84+
- Start static server manually in workflow with retry loop (60s timeout)
85+
- Fixed build order: build-contracts -> deploy-contracts -> build-app
86+
- Server health check uses retry loop instead of single check
87+
88+
**Result:** Server started but returned 404 - wrong dist path!
89+
90+
---

app/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ document.addEventListener('DOMContentLoaded', async () => {
5656
// Get existing account
5757
displayStatusMessage('Checking for existing account...');
5858
const account = await wallet.connectExistingAccount();
59-
await displayAccount();
59+
displayAccount();
6060

6161
// Refresh tally if account exists
6262
if (account) {

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"node": ">=22.0.0"
88
},
99
"scripts": {
10-
"clean": "rm -rf app/dist contracts/target contracts/codegenCache.json",
10+
"clean": "rm -rf dist contracts/target contracts/codegenCache.json",
1111
"compile-contracts": "cd contracts && aztec compile",
1212
"codegen-contracts": "cd contracts && aztec codegen ./target -o ./target",
1313
"copy-artifacts": "mkdir -p app/artifacts && cp contracts/target/*.json contracts/target/*.ts app/artifacts",
@@ -17,6 +17,7 @@
1717
"build-app": "webpack --mode production",
1818
"build": "yarn build-contracts && yarn build-app",
1919
"serve": "webpack serve --mode production --port ${PORT:-3000}",
20+
"serve:static": "npx serve dist -l ${PORT:-3000} -c ../serve.json",
2021
"prep-test": "PROVER_ENABLED=false yarn deploy-contracts && yarn build-app",
2122
"test": "yarn prep-test && yarn playwright test",
2223
"lint": "prettier --check ./src"

playwright.config.ts

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ import { defineConfig, devices } from '@playwright/test';
55
*/
66
export default defineConfig({
77
testDir: './tests',
8-
fullyParallel: true,
8+
fullyParallel: !process.env.CI, // Disable parallel in CI
99
forbidOnly: !!process.env.CI,
10-
workers: process.env.PLAYWRIGHT_NUM_WORKERS
11-
? Number(process.env.PLAYWRIGHT_NUM_WORKERS)
12-
: 1,
10+
workers: 1, // Single worker
1311
reporter: 'list',
1412
use: {
1513
baseURL: 'http://127.0.0.1:3000',
@@ -18,25 +16,37 @@ export default defineConfig({
1816
timeout: 20_000,
1917
},
2018
timeout: 1_600_000,
21-
projects: [
22-
{
23-
name: 'webkit',
24-
use: { ...devices['Desktop Safari'] },
25-
},
26-
{
27-
name: 'chromium',
28-
use: { ...devices['Desktop Chrome'] },
29-
},
30-
{
31-
name: 'firefox',
32-
use: { ...devices['Desktop Firefox'] },
33-
},
34-
],
19+
// In CI, only run chromium to simplify debugging
20+
projects: process.env.CI
21+
? [
22+
{
23+
name: 'chromium',
24+
use: { ...devices['Desktop Chrome'] },
25+
},
26+
]
27+
: [
28+
{
29+
name: 'webkit',
30+
use: { ...devices['Desktop Safari'] },
31+
},
32+
{
33+
name: 'chromium',
34+
use: { ...devices['Desktop Chrome'] },
35+
},
36+
{
37+
name: 'firefox',
38+
use: { ...devices['Desktop Firefox'] },
39+
},
40+
],
3541

36-
webServer: {
37-
command: 'PORT=3000 yarn serve',
38-
url: 'http://127.0.0.1:3000',
39-
reuseExistingServer: !process.env.CI,
40-
timeout: 30_000,
41-
},
42+
// In CI, server is started manually in the workflow for better visibility
43+
// Locally, Playwright handles starting the dev server
44+
webServer: process.env.CI
45+
? undefined
46+
: {
47+
command: 'PORT=3000 yarn serve',
48+
url: 'http://127.0.0.1:3000',
49+
reuseExistingServer: true,
50+
timeout: 120_000,
51+
},
4252
});

serve.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"headers": [
3+
{
4+
"source": "**/*",
5+
"headers": [
6+
{
7+
"key": "Cross-Origin-Opener-Policy",
8+
"value": "same-origin"
9+
},
10+
{
11+
"key": "Cross-Origin-Embedder-Policy",
12+
"value": "require-corp"
13+
}
14+
]
15+
}
16+
]
17+
}

tests/e2e.spec.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,23 @@ const proofTimeout = 250_000;
66
test.beforeAll(async () => {
77
// Make sure the node is running
88
const nodeUrl = process.env.AZTEC_NODE_URL || 'http://localhost:8080';
9-
const nodeResp = await fetch(nodeUrl + '/status');
10-
if (!nodeResp.ok) {
11-
throw new Error(
12-
`Failed to connect to node. This test assumes you have a local network running at ${nodeUrl}.`
13-
);
9+
const controller = new AbortController();
10+
const timeoutId = setTimeout(() => controller.abort(), 30_000); // 30 second timeout
11+
12+
try {
13+
const nodeResp = await fetch(nodeUrl + '/status', { signal: controller.signal });
14+
clearTimeout(timeoutId);
15+
if (!nodeResp.ok) {
16+
throw new Error(
17+
`Failed to connect to node. This test assumes you have a local network running at ${nodeUrl}.`
18+
);
19+
}
20+
} catch (error) {
21+
clearTimeout(timeoutId);
22+
if (error.name === 'AbortError') {
23+
throw new Error(`Timeout connecting to node at ${nodeUrl}. Is the local network running?`);
24+
}
25+
throw error;
1426
}
1527
});
1628

0 commit comments

Comments
 (0)