Files
anomalyco_opencode/packages/opencode/test/cli/tui/plugin-toggle.test.ts
T
Kit Langton 9f290d4381 effect(cli): kill TuiConfig/Installation/SessionCompaction facades
Remove makeRuntime + async facade exports from TuiConfig, Installation, and
SessionCompaction. Migrate production callers to AppRuntime.runPromise with
yielded services, and route tests through dedicated mockable hooks where
they previously spied on the facade.
2026-05-12 16:29:18 -04:00

199 lines
5.9 KiB
TypeScript

import { expect, spyOn, test } from "bun:test"
import fs from "fs/promises"
import path from "path"
import { pathToFileURL } from "url"
import { tmpdir } from "../../fixture/fixture"
import { createTuiPluginApi } from "../../fixture/tui-plugin"
import { createTuiResolvedConfig } from "../../fixture/tui-runtime"
const { TuiPluginRuntime } = await import("../../../src/cli/cmd/tui/plugin/runtime")
test("toggles plugin runtime state by exported id", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
const file = path.join(dir, "toggle-plugin.ts")
const spec = pathToFileURL(file).href
const marker = path.join(dir, "toggle.txt")
await Bun.write(
file,
`export default {
id: "demo.toggle",
tui: async (api, options) => {
const text = await Bun.file(options.marker).text().catch(() => "")
await Bun.write(options.marker, text + "start\\n")
api.lifecycle.onDispose(async () => {
const next = await Bun.file(options.marker).text().catch(() => "")
await Bun.write(options.marker, next + "stop\\n")
})
},
}
`,
)
return {
spec,
marker,
}
},
})
process.env.OPENCODE_PLUGIN_META_FILE = path.join(tmp.path, "plugin-meta.json")
const config = createTuiResolvedConfig({
plugin: [[tmp.extra.spec, { marker: tmp.extra.marker }]],
plugin_enabled: {
"demo.toggle": false,
},
plugin_origins: [
{
spec: [tmp.extra.spec, { marker: tmp.extra.marker }],
scope: "local",
source: path.join(tmp.path, "tui.json"),
},
],
})
const wait = spyOn(TuiPluginRuntime, "waitForDependencies").mockResolvedValue()
const cwd = spyOn(process, "cwd").mockImplementation(() => tmp.path)
const api = createTuiPluginApi()
try {
await TuiPluginRuntime.init({ api, config })
await expect(fs.readFile(tmp.extra.marker, "utf8")).rejects.toThrow()
expect(TuiPluginRuntime.list().find((item) => item.id === "demo.toggle")).toEqual({
id: "demo.toggle",
source: "file",
spec: tmp.extra.spec,
target: tmp.extra.spec,
enabled: false,
active: false,
})
await expect(TuiPluginRuntime.activatePlugin("demo.toggle")).resolves.toBe(true)
await expect(fs.readFile(tmp.extra.marker, "utf8")).resolves.toBe("start\n")
expect(api.kv.get("plugin_enabled", {})).toEqual({
"demo.toggle": true,
})
await expect(TuiPluginRuntime.deactivatePlugin("demo.toggle")).resolves.toBe(true)
await expect(fs.readFile(tmp.extra.marker, "utf8")).resolves.toBe("start\nstop\n")
expect(api.kv.get("plugin_enabled", {})).toEqual({
"demo.toggle": false,
})
await expect(TuiPluginRuntime.activatePlugin("missing.id")).resolves.toBe(false)
} finally {
await TuiPluginRuntime.dispose()
cwd.mockRestore()
wait.mockRestore()
delete process.env.OPENCODE_PLUGIN_META_FILE
}
})
test("kv plugin_enabled overrides tui config on startup", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
const file = path.join(dir, "startup-plugin.ts")
const spec = pathToFileURL(file).href
const marker = path.join(dir, "startup.txt")
await Bun.write(
file,
`export default {
id: "demo.startup",
tui: async (_api, options) => {
await Bun.write(options.marker, "on")
},
}
`,
)
return {
spec,
marker,
}
},
})
process.env.OPENCODE_PLUGIN_META_FILE = path.join(tmp.path, "plugin-meta.json")
const config = createTuiResolvedConfig({
plugin: [[tmp.extra.spec, { marker: tmp.extra.marker }]],
plugin_enabled: {
"demo.startup": false,
},
plugin_origins: [
{
spec: [tmp.extra.spec, { marker: tmp.extra.marker }],
scope: "local",
source: path.join(tmp.path, "tui.json"),
},
],
})
const wait = spyOn(TuiPluginRuntime, "waitForDependencies").mockResolvedValue()
const cwd = spyOn(process, "cwd").mockImplementation(() => tmp.path)
const api = createTuiPluginApi()
api.kv.set("plugin_enabled", {
"demo.startup": true,
})
try {
await TuiPluginRuntime.init({ api, config })
await expect(fs.readFile(tmp.extra.marker, "utf8")).resolves.toBe("on")
expect(TuiPluginRuntime.list().find((item) => item.id === "demo.startup")).toEqual({
id: "demo.startup",
source: "file",
spec: tmp.extra.spec,
target: tmp.extra.spec,
enabled: true,
active: true,
})
} finally {
await TuiPluginRuntime.dispose()
cwd.mockRestore()
wait.mockRestore()
delete process.env.OPENCODE_PLUGIN_META_FILE
}
})
test("loads disabled-by-default internal plugin inactive and activates on demand", async () => {
await using tmp = await tmpdir()
const config = createTuiResolvedConfig()
const wait = spyOn(TuiPluginRuntime, "waitForDependencies").mockResolvedValue()
const cwd = spyOn(process, "cwd").mockImplementation(() => tmp.path)
const api = createTuiPluginApi()
try {
await TuiPluginRuntime.init({ api, config })
expect(TuiPluginRuntime.list().find((item) => item.id === "internal:plugin-manager")).toMatchObject({
enabled: true,
active: true,
})
expect(TuiPluginRuntime.list().find((item) => item.id === "which-key")).toEqual({
id: "which-key",
source: "internal",
spec: "which-key",
target: "which-key",
enabled: false,
active: false,
})
await expect(TuiPluginRuntime.activatePlugin("which-key")).resolves.toBe(true)
expect(TuiPluginRuntime.list().find((item) => item.id === "which-key")).toEqual({
id: "which-key",
source: "internal",
spec: "which-key",
target: "which-key",
enabled: true,
active: true,
})
expect(api.kv.get("plugin_enabled", {})).toEqual({
"which-key": true,
})
} finally {
await TuiPluginRuntime.dispose()
cwd.mockRestore()
wait.mockRestore()
}
})