ci: nightly browser suite; fix stale session-id extraction in browser tests

WIP: the suite still has failures on a clean master that are not fixed here.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Devvyn
2026-10-06 09:20:55 +08:00
co-authored by Claude Sonnet 5.5
parent ac94f339ac
commit ab7e89873f
4 changed files with 75 additions and 6 deletions
+61
View File
@@ -0,0 +1,61 @@
name: Browser suite
# The per-push CI gate deliberately skips the Playwright-driven suite (config/test-suites.ts),
# which has twice let two PRs that conflict semantically merge green. This job runs it on a
# schedule and on demand, so a browser-only regression (the Shift+Enter keypress bug was one)
# is caught within a day instead of by a user. It is NOT a merge gate: a red run means "look",
# and it never blocks a push or a PR.
#
# Needs: chromium (installed below), tmux, and the live server the tests start themselves.
# Not run here: test:mobile (per-machine PNG baselines), test:perf (wall-clock), and
# codex-predictive-echo (needs a real, authenticated codex binary).
on:
schedule:
- cron: '17 3 * * *'
workflow_dispatch:
permissions:
contents: read
jobs:
browser:
name: Playwright browser suite
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Install tmux
run: |
if ! command -v tmux >/dev/null; then
sudo apt-get update -qq
sudo apt-get install -y tmux
fi
- name: Install chromium
run: npx playwright install --with-deps chromium
- name: Run the browser suite
run: npm run test:browser -- --exclude test/codex-predictive-echo.test.ts
- name: Keep the failure artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: browser-suite-results
path: |
test-results/
screenshots-echo-diag/
if-no-files-found: ignore
retention-days: 7
+2
View File
@@ -219,6 +219,8 @@ jobs:
run: npx vitest run
working-directory: packages/xterm-zerolag-input
# The browser suite also runs nightly (and on demand) in .github/workflows/browser-suite.yml;
# that job is informational and never gates a push or a PR.
# Note: three suites are excluded from CI, each with its own local runner:
# npm run test:browser Playwright + chromium (+ a live server, and a real
# codex binary for codex-predictive-echo)
+10 -5
View File
@@ -123,7 +123,8 @@ describe('OpenCode session initial resize', () => {
body: JSON.stringify({ workingDir: '/tmp', name: 'oc-resize-test' }),
});
const data = await res.json();
return data.id ?? data.session?.id;
// POST /api/sessions answers in the { success, data: { session } } envelope.
return data.data?.session?.id ?? data.id ?? data.session?.id;
});
expect(sessionId).toBeTruthy();
@@ -168,7 +169,8 @@ describe('OpenCode session initial resize', () => {
body: JSON.stringify({ workingDir: '/tmp', name: 'oc-earlyret-test' }),
});
const data = await res.json();
return data.id ?? data.session?.id;
// POST /api/sessions answers in the { success, data: { session } } envelope.
return data.data?.session?.id ?? data.id ?? data.session?.id;
});
expect(sessionId).toBeTruthy();
@@ -219,7 +221,8 @@ describe('OpenCode session initial resize', () => {
body: JSON.stringify({ workingDir: '/tmp', name: 'oc-refresh-test' }),
});
const data = await res.json();
return data.id ?? data.session?.id;
// POST /api/sessions answers in the { success, data: { session } } envelope.
return data.data?.session?.id ?? data.id ?? data.session?.id;
});
expect(sessionId).toBeTruthy();
@@ -287,7 +290,8 @@ describe('OpenCode close modal text', () => {
body: JSON.stringify({ workingDir: '/tmp', name: 'oc-close-test', mode: 'opencode' }),
});
const data = await res.json();
return data.id ?? data.session?.id;
// POST /api/sessions answers in the { success, data: { session } } envelope.
return data.data?.session?.id ?? data.id ?? data.session?.id;
});
expect(sessionId).toBeTruthy();
@@ -329,7 +333,8 @@ describe('OpenCode close modal text', () => {
body: JSON.stringify({ workingDir: '/tmp', name: 'cc-close-test' }),
});
const data = await res.json();
return data.id ?? data.session?.id;
// POST /api/sessions answers in the { success, data: { session } } envelope.
return data.data?.session?.id ?? data.id ?? data.session?.id;
});
expect(sessionId).toBeTruthy();
+2 -1
View File
@@ -69,7 +69,8 @@ async function createSession(page: Page, name: string): Promise<string> {
body: JSON.stringify({ workingDir: '/tmp', name: n }),
});
const data = await res.json();
return data.id ?? data.session?.id;
// POST /api/sessions answers in the { success, data: { session } } envelope.
return data.data?.session?.id ?? data.id ?? data.session?.id;
}, name);
return result as string;
}