test(app): windows e2e

This commit is contained in:
Adam
2026-01-20 09:34:05 -06:00
parent 1d6f650f53
commit 1ac0980c80
2 changed files with 93 additions and 7 deletions

View File

@@ -8,7 +8,29 @@ on:
workflow_dispatch:
jobs:
test:
runs-on: blacksmith-4vcpu-ubuntu-2404
name: test (${{ matrix.settings.name }})
strategy:
fail-fast: false
matrix:
settings:
- name: linux
host: blacksmith-4vcpu-ubuntu-2404
playwright: bunx playwright install --with-deps
workdir: .
command: |
git config --global user.email "bot@opencode.ai"
git config --global user.name "opencode"
bun turbo typecheck
bun turbo test
- name: windows
host: windows-latest
playwright: bunx playwright install
workdir: packages/app
command: bun test:e2e
runs-on: ${{ matrix.settings.host }}
defaults:
run:
shell: bash
steps:
- name: Checkout repository
uses: actions/checkout@v4
@@ -20,7 +42,7 @@ jobs:
- name: Install Playwright browsers
working-directory: packages/app
run: bunx playwright install --with-deps
run: ${{ matrix.settings.playwright }}
- name: Seed opencode data
working-directory: packages/opencode
@@ -67,11 +89,8 @@ jobs:
exit 1
- name: run
run: |
git config --global user.email "bot@opencode.ai"
git config --global user.name "opencode"
bun turbo typecheck
bun turbo test
working-directory: ${{ matrix.settings.workdir }}
run: ${{ matrix.settings.command }}
env:
CI: true
MODELS_DEV_API_JSON: ${{ github.workspace }}/packages/opencode/test/tool/fixtures/models-api.json

View File

@@ -0,0 +1,67 @@
import { test, expect } from "./fixtures"
import { promptSelector } from "./utils"
function sessionIDFromUrl(url: string) {
const match = /\/session\/([^/?#]+)/.exec(url)
return match?.[1]
}
test("can send a prompt and receive a reply", async ({ page, sdk, gotoSession }) => {
test.setTimeout(120_000)
const pageErrors: string[] = []
const onPageError = (err: Error) => {
pageErrors.push(err.message)
}
page.on("pageerror", onPageError)
await gotoSession()
const token = `E2E_OK_${Date.now()}`
const prompt = page.locator(promptSelector)
await prompt.click()
await page.keyboard.type(`Reply with exactly: ${token}`)
await page.keyboard.press("Enter")
await expect(page).toHaveURL(/\/session\/[^/?#]+/, { timeout: 30_000 })
const sessionID = (() => {
const id = sessionIDFromUrl(page.url())
if (!id) throw new Error(`Failed to parse session id from url: ${page.url()}`)
return id
})()
try {
await expect
.poll(
async () => {
const messages = await sdk.session.messages({ sessionID, limit: 50 }).then((r) => r.data ?? [])
const assistant = messages
.slice()
.reverse()
.find((m) => m.info.role === "assistant")
return (
assistant?.parts
.filter((p) => p.type === "text")
.map((p) => p.text)
.join("\n") ?? ""
)
},
{ timeout: 90_000 },
)
.toContain(token)
const reply = page.locator('[data-component="text-part"]').filter({ hasText: token }).first()
await expect(reply).toBeVisible({ timeout: 90_000 })
} finally {
page.off("pageerror", onPageError)
await sdk.session.delete({ sessionID }).catch(() => undefined)
}
if (pageErrors.length > 0) {
throw new Error(`Page error(s):\n${pageErrors.join("\n")}`)
}
})