summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/testing
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/src/testing
parentc9c0318e0e5c2fcd80fc1c32a1ccfe360f182f90 (diff)
downloadopencode-328c6de80d51704c09bdd962df2ddf5b9d7c82ea.tar.gz
opencode-328c6de80d51704c09bdd962df2ddf5b9d7c82ea.zip
Fix terminal e2e flakiness with a real terminal driver (#17144)
Diffstat (limited to 'packages/app/src/testing')
-rw-r--r--packages/app/src/testing/terminal.ts64
1 files changed, 64 insertions, 0 deletions
diff --git a/packages/app/src/testing/terminal.ts b/packages/app/src/testing/terminal.ts
new file mode 100644
index 000000000..aa1974404
--- /dev/null
+++ b/packages/app/src/testing/terminal.ts
@@ -0,0 +1,64 @@
+export const terminalAttr = "data-pty-id"
+
+export type TerminalProbeState = {
+ connected: boolean
+ rendered: string
+ settled: number
+}
+
+export type E2EWindow = Window & {
+ __opencode_e2e?: {
+ terminal?: {
+ enabled?: boolean
+ terminals?: Record<string, TerminalProbeState>
+ }
+ }
+}
+
+const seed = (): TerminalProbeState => ({
+ connected: false,
+ rendered: "",
+ settled: 0,
+})
+
+const root = () => {
+ if (typeof window === "undefined") return
+ const state = (window as E2EWindow).__opencode_e2e?.terminal
+ if (!state?.enabled) return
+ state.terminals ??= {}
+ return state.terminals
+}
+
+export const terminalProbe = (id: string) => {
+ const set = (next: Partial<TerminalProbeState>) => {
+ const terms = root()
+ if (!terms) return
+ terms[id] = { ...(terms[id] ?? seed()), ...next }
+ }
+
+ return {
+ init() {
+ set(seed())
+ },
+ connect() {
+ set({ connected: true })
+ },
+ render(data: string) {
+ const terms = root()
+ if (!terms) return
+ const prev = terms[id] ?? seed()
+ terms[id] = { ...prev, rendered: prev.rendered + data }
+ },
+ settle() {
+ const terms = root()
+ if (!terms) return
+ const prev = terms[id] ?? seed()
+ terms[id] = { ...prev, settled: prev.settled + 1 }
+ },
+ drop() {
+ const terms = root()
+ if (!terms) return
+ delete terms[id]
+ },
+ }
+}