Skip to content

Commit a5b1dc0

Browse files
Honaopencode
authored andcommitted
test: add regression coverage for sync plugin hooks (anomalyco#19589)
1 parent 0bc2f99 commit a5b1dc0

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { afterAll, afterEach, describe, expect, test } from "bun:test"
2+
import path from "path"
3+
import { pathToFileURL } from "url"
4+
import { tmpdir } from "../fixture/fixture"
5+
6+
const disableDefault = process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS
7+
process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS = "1"
8+
9+
const { Plugin } = await import("../../src/plugin/index")
10+
const { Instance } = await import("../../src/project/instance")
11+
12+
afterEach(async () => {
13+
await Instance.disposeAll()
14+
})
15+
16+
afterAll(() => {
17+
if (disableDefault === undefined) {
18+
delete process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS
19+
return
20+
}
21+
process.env.OPENCODE_DISABLE_DEFAULT_PLUGINS = disableDefault
22+
})
23+
24+
async function project(source: string) {
25+
return tmpdir({
26+
init: async (dir) => {
27+
const file = path.join(dir, "plugin.ts")
28+
await Bun.write(file, source)
29+
await Bun.write(
30+
path.join(dir, "opencode.json"),
31+
JSON.stringify(
32+
{
33+
$schema: "https://opencode.ai/config.json",
34+
plugin: [pathToFileURL(file).href],
35+
},
36+
null,
37+
2,
38+
),
39+
)
40+
},
41+
})
42+
}
43+
44+
describe("plugin.trigger", () => {
45+
test("runs synchronous hooks without crashing", async () => {
46+
await using tmp = await project(
47+
[
48+
"export default async () => ({",
49+
' "experimental.chat.system.transform": (_input, output) => {',
50+
' output.system.unshift("sync")',
51+
" },",
52+
"})",
53+
"",
54+
].join("\n"),
55+
)
56+
57+
const out = await Instance.provide({
58+
directory: tmp.path,
59+
fn: async () => {
60+
const out = { system: [] as string[] }
61+
await Plugin.trigger(
62+
"experimental.chat.system.transform",
63+
{
64+
model: {
65+
providerID: "anthropic",
66+
modelID: "claude-sonnet-4-6",
67+
} as any,
68+
},
69+
out,
70+
)
71+
return out
72+
},
73+
})
74+
75+
expect(out.system).toEqual(["sync"])
76+
})
77+
78+
test("awaits asynchronous hooks", async () => {
79+
await using tmp = await project(
80+
[
81+
"export default async () => ({",
82+
' "experimental.chat.system.transform": async (_input, output) => {',
83+
" await Bun.sleep(1)",
84+
' output.system.unshift("async")',
85+
" },",
86+
"})",
87+
"",
88+
].join("\n"),
89+
)
90+
91+
const out = await Instance.provide({
92+
directory: tmp.path,
93+
fn: async () => {
94+
const out = { system: [] as string[] }
95+
await Plugin.trigger(
96+
"experimental.chat.system.transform",
97+
{
98+
model: {
99+
providerID: "anthropic",
100+
modelID: "claude-sonnet-4-6",
101+
} as any,
102+
},
103+
out,
104+
)
105+
return out
106+
},
107+
})
108+
109+
expect(out.system).toEqual(["async"])
110+
})
111+
})

0 commit comments

Comments
 (0)