mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-13 01:31:22 +03:00
test(tui): isolate app fixture state (#52512)
This commit is contained in:
committed by
GitHub
Unverified
parent
08c15ec1cd
commit
b73e75fb6a
@@ -2,7 +2,6 @@ import { expect, test } from "bun:test"
|
||||
import { EmbeddedTerminalRenderable } from "@opentui/core"
|
||||
import { createTestRenderer } from "@opentui/core/testing"
|
||||
import { Effect, FileSystem } from "effect"
|
||||
import { AppNodeBuilder } from "@opencode/core/effect/app-node-builder"
|
||||
import { Global } from "@opencode/util/global"
|
||||
import path from "node:path"
|
||||
import { createEventStream, createFetch, directory, json } from "./fixture/tui-client"
|
||||
@@ -216,6 +215,7 @@ test.each(["dismissed", "refreshing"])(
|
||||
)
|
||||
|
||||
test("SIGHUP clears title and disposes scoped resources once", async () => {
|
||||
await using state = await tmpdir()
|
||||
const setup = await createTestRenderer({ width: 80, height: 24, useThread: false })
|
||||
const titles: string[] = []
|
||||
let started!: () => void
|
||||
@@ -243,7 +243,7 @@ test("SIGHUP clears title and disposes scoped resources once", async () => {
|
||||
terminalHandoff: async () => ({ renderer: setup.renderer, mode: "dark", complete: () => {} }),
|
||||
args: {},
|
||||
log: () => {},
|
||||
}).pipe(Effect.provide(AppNodeBuilder.build(Global.node)), Effect.provide(FileSystem.layerNoop({}))),
|
||||
}).pipe(Effect.provide(Global.layerWith({ state: state.path })), Effect.provide(FileSystem.layerNoop({}))),
|
||||
)
|
||||
await ready
|
||||
process.emit("SIGHUP")
|
||||
@@ -259,6 +259,7 @@ test("SIGHUP clears title and disposes scoped resources once", async () => {
|
||||
})
|
||||
|
||||
test("session lifecycle updates the terminal title and prints the epilogue after cleanup", async () => {
|
||||
await using state = await tmpdir()
|
||||
const setup = await createTestRenderer({ width: 80, height: 24, useThread: false })
|
||||
let initialTitle!: () => void
|
||||
const initialTitleSet = new Promise<void>((resolve) => {
|
||||
@@ -319,7 +320,7 @@ test("session lifecycle updates the terminal title and prints the epilogue after
|
||||
terminalHandoff: async () => ({ renderer: setup.renderer, mode: "dark", complete: () => {} }),
|
||||
args: { sessionID: "dummy" },
|
||||
log: () => {},
|
||||
}).pipe(Effect.provide(AppNodeBuilder.build(Global.node)), Effect.provide(FileSystem.layerNoop({}))),
|
||||
}).pipe(Effect.provide(Global.layerWith({ state: state.path })), Effect.provide(FileSystem.layerNoop({}))),
|
||||
)
|
||||
|
||||
await initialTitleSet
|
||||
@@ -345,6 +346,7 @@ test("session lifecycle updates the terminal title and prints the epilogue after
|
||||
})
|
||||
|
||||
test("session title generated while an untitled session is loading remains visible", async () => {
|
||||
await using state = await tmpdir()
|
||||
const setup = await createTestRenderer({ width: 80, height: 24, useThread: false })
|
||||
const titles: string[] = []
|
||||
const setTitle = setup.renderer.setTerminalTitle.bind(setup.renderer)
|
||||
@@ -393,7 +395,7 @@ test("session title generated while an untitled session is loading remains visib
|
||||
terminalHandoff: async () => ({ renderer: setup.renderer, mode: "dark", complete: () => {} }),
|
||||
args: { sessionID: "dummy" },
|
||||
log: () => {},
|
||||
}).pipe(Effect.provide(AppNodeBuilder.build(Global.node)), Effect.provide(FileSystem.layerNoop({}))),
|
||||
}).pipe(Effect.provide(Global.layerWith({ state: state.path })), Effect.provide(FileSystem.layerNoop({}))),
|
||||
)
|
||||
|
||||
await sessionRequested.promise
|
||||
@@ -802,6 +804,7 @@ test("keeps assistant footer metrics current after prepend, same-length refresh,
|
||||
})
|
||||
|
||||
test("session startup prompt is submitted exactly once", async () => {
|
||||
await using state = await tmpdir()
|
||||
const setup = await createTestRenderer({ width: 80, height: 24, useThread: false })
|
||||
const events = createEventStream()
|
||||
const cwd = process.cwd()
|
||||
@@ -855,7 +858,7 @@ test("session startup prompt is submitted exactly once", async () => {
|
||||
terminalHandoff: async () => ({ renderer: setup.renderer, mode: "dark", complete: () => {} }),
|
||||
args: { sessionID: "dummy", prompt: "RESUME_READY" },
|
||||
log: () => {},
|
||||
}).pipe(Effect.provide(AppNodeBuilder.build(Global.node)), Effect.provide(FileSystem.layerNoop({}))),
|
||||
}).pipe(Effect.provide(Global.layerWith({ state: state.path })), Effect.provide(FileSystem.layerNoop({}))),
|
||||
)
|
||||
|
||||
await Promise.race([
|
||||
@@ -1344,6 +1347,7 @@ test("ctrl+c dismisses autocomplete and shell mode before exiting", async () =>
|
||||
test.skipIf(process.platform === "win32").each(["manual", "select"] as const)(
|
||||
"selection copy and pane management respect %s mode in the prompt and terminal pane",
|
||||
async (copy) => {
|
||||
await using state = await tmpdir()
|
||||
const setup = await createTestRenderer({ width: 100, height: 30, useThread: false, kittyKeyboard: true })
|
||||
setup.renderer.start()
|
||||
const ready = Promise.withResolvers<void>()
|
||||
@@ -1426,7 +1430,7 @@ test.skipIf(process.platform === "win32").each(["manual", "select"] as const)(
|
||||
args: { sessionID: session.id },
|
||||
terminalHandoff: async () => ({ renderer: setup.renderer, mode: "dark", complete: ready.resolve }),
|
||||
log: () => {},
|
||||
}).pipe(Effect.provide(AppNodeBuilder.build(Global.node)), Effect.provide(FileSystem.layerNoop({}))),
|
||||
}).pipe(Effect.provide(Global.layerWith({ state: state.path })), Effect.provide(FileSystem.layerNoop({}))),
|
||||
)
|
||||
|
||||
await ready.promise
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { createTestRenderer } from "@opentui/core/testing"
|
||||
import { Effect, FileSystem } from "effect"
|
||||
import { AppNodeBuilder } from "@opencode/core/effect/app-node-builder"
|
||||
import { Global } from "@opencode/util/global"
|
||||
import type { TuiInput } from "../../src/app"
|
||||
import type { Config } from "../../src/config"
|
||||
import { tmpdir } from "./fixture"
|
||||
import { createEventStream, createFetch, type FetchHandler } from "./tui-client"
|
||||
|
||||
export async function createAppFixture(
|
||||
@@ -17,6 +17,7 @@ export async function createAppFixture(
|
||||
} = {},
|
||||
) {
|
||||
const { run } = await import("../../src/app")
|
||||
const state = input.state ? undefined : await tmpdir()
|
||||
const setup = await createTestRenderer({
|
||||
width: input.width ?? 100,
|
||||
height: input.height ?? 30,
|
||||
@@ -38,7 +39,7 @@ export async function createAppFixture(
|
||||
args: input.args ?? {},
|
||||
log: () => {},
|
||||
}).pipe(
|
||||
Effect.provide(input.state ? Global.layerWith({ state: input.state }) : AppNodeBuilder.build(Global.node)),
|
||||
Effect.provide(Global.layerWith({ state: input.state ?? state?.path })),
|
||||
Effect.provide(FileSystem.layerNoop({})),
|
||||
),
|
||||
)
|
||||
@@ -52,6 +53,7 @@ export async function createAppFixture(
|
||||
await task
|
||||
} finally {
|
||||
await server.stop()
|
||||
await state?.[Symbol.asyncDispose]()
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user