| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- /** @jsxImportSource @opentui/solid */
- import { describe, expect, test } from "bun:test"
- import { testRender } from "@opentui/solid"
- import { onMount } from "solid-js"
- import { Global } from "@opencode-ai/core/global"
- import { ArgsProvider } from "../../../../src/cli/cmd/tui/context/args"
- import { ExitProvider } from "../../../../src/cli/cmd/tui/context/exit"
- import { KVProvider, useKV } from "../../../../src/cli/cmd/tui/context/kv"
- import { ProjectProvider } from "../../../../src/cli/cmd/tui/context/project"
- import { SDKProvider, type EventSource } from "../../../../src/cli/cmd/tui/context/sdk"
- import { SyncProvider, useSync } from "../../../../src/cli/cmd/tui/context/sync"
- import { tmpdir } from "../../../fixture/fixture"
- const worktree = "/tmp/opencode"
- const directory = `${worktree}/packages/opencode`
- async function wait(fn: () => boolean, timeout = 2000) {
- const start = Date.now()
- while (!fn()) {
- if (Date.now() - start > timeout) throw new Error("timed out waiting for condition")
- await Bun.sleep(10)
- }
- }
- function json(data: unknown) {
- return new Response(JSON.stringify(data), {
- headers: { "content-type": "application/json" },
- })
- }
- function eventSource(): EventSource {
- return {
- subscribe: async () => () => {},
- }
- }
- function createFetch() {
- const session = [] as URL[]
- const fetch = (async (input: RequestInfo | URL) => {
- const url = new URL(input instanceof Request ? input.url : String(input))
- if (url.pathname === "/session") session.push(url)
- switch (url.pathname) {
- case "/agent":
- case "/command":
- case "/experimental/workspace":
- case "/experimental/workspace/status":
- case "/formatter":
- case "/lsp":
- return json([])
- case "/config":
- case "/experimental/resource":
- case "/mcp":
- case "/provider/auth":
- case "/session/status":
- return json({})
- case "/config/providers":
- return json({ providers: {}, default: {} })
- case "/experimental/console":
- return json({ consoleManagedProviders: [], switchableOrgCount: 0 })
- case "/path":
- return json({ home: "", state: "", config: "", worktree, directory })
- case "/project/current":
- return json({ id: "proj_test" })
- case "/provider":
- return json({ all: [], default: {}, connected: [] })
- case "/session":
- return json([])
- case "/vcs":
- return json({ branch: "main" })
- }
- throw new Error(`unexpected request: ${url.pathname}`)
- }) as typeof globalThis.fetch
- return { fetch, session }
- }
- async function mount() {
- const calls = createFetch()
- let sync!: ReturnType<typeof useSync>
- let kv!: ReturnType<typeof useKV>
- let done!: () => void
- const ready = new Promise<void>((resolve) => {
- done = resolve
- })
- const app = await testRender(() => (
- <ArgsProvider>
- <ExitProvider>
- <KVProvider>
- <SDKProvider url="http://test" directory={directory} fetch={calls.fetch} events={eventSource()}>
- <ProjectProvider>
- <SyncProvider>
- <Probe
- onReady={(ctx) => {
- sync = ctx.sync
- kv = ctx.kv
- done()
- }}
- />
- </SyncProvider>
- </ProjectProvider>
- </SDKProvider>
- </KVProvider>
- </ExitProvider>
- </ArgsProvider>
- ))
- await ready
- await wait(() => sync.status === "complete")
- return { app, kv, sync, session: calls.session }
- }
- function Probe(props: { onReady: (ctx: { kv: ReturnType<typeof useKV>; sync: ReturnType<typeof useSync> }) => void }) {
- const kv = useKV()
- const sync = useSync()
- onMount(() => {
- props.onReady({ kv, sync })
- })
- return <box />
- }
- describe("tui sync", () => {
- test("refresh scopes sessions by default and lists project sessions when disabled", async () => {
- const previous = Global.Path.state
- await using tmp = await tmpdir()
- Global.Path.state = tmp.path
- await Bun.write(`${tmp.path}/kv.json`, "{}")
- const { app, kv, sync, session } = await mount()
- try {
- expect(kv.get("session_directory_filter_enabled", true)).toBe(true)
- expect(session.at(-1)?.searchParams.get("scope")).toBeNull()
- expect(session.at(-1)?.searchParams.get("path")).toBe("packages/opencode")
- kv.set("session_directory_filter_enabled", false)
- await sync.session.refresh()
- expect(session.at(-1)?.searchParams.get("scope")).toBe("project")
- expect(session.at(-1)?.searchParams.get("path")).toBeNull()
- } finally {
- app.renderer.destroy()
- Global.Path.state = previous
- }
- })
- })
|