summaryrefslogtreecommitdiffhomepage
path: root/packages/app/e2e/actions.ts
diff options
context:
space:
mode:
authorLuke Parker <[email protected]>2026-03-12 17:35:26 +1000
committerGitHub <[email protected]>2026-03-12 17:35:26 +1000
commit328c6de80d51704c09bdd962df2ddf5b9d7c82ea (patch)
treebf6426b3afeb824feaae73aa22cfc20e6e0d438d /packages/app/e2e/actions.ts
parentc9c0318e0e5c2fcd80fc1c32a1ccfe360f182f90 (diff)
downloadopencode-328c6de80d51704c09bdd962df2ddf5b9d7c82ea.tar.gz
opencode-328c6de80d51704c09bdd962df2ddf5b9d7c82ea.zip
Fix terminal e2e flakiness with a real terminal driver (#17144)
Diffstat (limited to 'packages/app/e2e/actions.ts')
-rw-r--r--packages/app/e2e/actions.ts53
1 files changed, 53 insertions, 0 deletions
diff --git a/packages/app/e2e/actions.ts b/packages/app/e2e/actions.ts
index 86147dc65..f721e0a7c 100644
--- a/packages/app/e2e/actions.ts
+++ b/packages/app/e2e/actions.ts
@@ -3,6 +3,7 @@ import fs from "node:fs/promises"
import os from "node:os"
import path from "node:path"
import { execSync } from "node:child_process"
+import { terminalAttr, type E2EWindow } from "../src/testing/terminal"
import { createSdk, modKey, resolveDirectory, serverUrl } from "./utils"
import {
dropdownMenuTriggerSelector,
@@ -15,6 +16,7 @@ import {
listItemSelector,
listItemKeySelector,
listItemKeyStartsWithSelector,
+ terminalSelector,
workspaceItemSelector,
workspaceMenuTriggerSelector,
} from "./selectors"
@@ -28,6 +30,57 @@ export async function defocus(page: Page) {
.catch(() => undefined)
}
+async function terminalID(term: Locator) {
+ const id = await term.getAttribute(terminalAttr)
+ if (id) return id
+ throw new Error(`Active terminal missing ${terminalAttr}`)
+}
+
+async function terminalReady(page: Page, term?: Locator) {
+ const next = term ?? page.locator(terminalSelector).first()
+ const id = await terminalID(next)
+ return page.evaluate((id) => {
+ const state = (window as E2EWindow).__opencode_e2e?.terminal?.terminals?.[id]
+ return !!state?.connected && (state.settled ?? 0) > 0
+ }, id)
+}
+
+async function terminalHas(page: Page, input: { term?: Locator; token: string }) {
+ const next = input.term ?? page.locator(terminalSelector).first()
+ const id = await terminalID(next)
+ return page.evaluate(
+ (input) => {
+ const state = (window as E2EWindow).__opencode_e2e?.terminal?.terminals?.[input.id]
+ return state?.rendered.includes(input.token) ?? false
+ },
+ { id, token: input.token },
+ )
+}
+
+export async function waitTerminalReady(page: Page, input?: { term?: Locator; timeout?: number }) {
+ const term = input?.term ?? page.locator(terminalSelector).first()
+ const timeout = input?.timeout ?? 10_000
+ await expect(term).toBeVisible()
+ await expect(term.locator("textarea")).toHaveCount(1)
+ await expect
+ .poll(() => terminalReady(page, term), { timeout })
+ .toBe(true)
+}
+
+export async function runTerminal(page: Page, input: { cmd: string; token: string; term?: Locator; timeout?: number }) {
+ const term = input.term ?? page.locator(terminalSelector).first()
+ const timeout = input.timeout ?? 10_000
+ await waitTerminalReady(page, { term, timeout })
+ const textarea = term.locator("textarea")
+ await term.click()
+ await expect(textarea).toBeFocused()
+ await page.keyboard.type(input.cmd)
+ await page.keyboard.press("Enter")
+ await expect
+ .poll(() => terminalHas(page, { term, token: input.token }), { timeout })
+ .toBe(true)
+}
+
export async function openPalette(page: Page) {
await defocus(page)
await page.keyboard.press(`${modKey}+P`)