opencode/packages/opencode/test/plugin/meta.test.ts

88 lines
3.4 KiB
TypeScript

import { afterEach, describe, expect, test } from "bun:test"
import fs from "fs/promises"
import path from "path"
import { pathToFileURL } from "url"
import { tmpdir } from "../fixture/fixture"
const { PluginMeta } = await import("../../src/plugin/meta")
afterEach(() => {
delete process.env.OPENCODE_PLUGIN_META_FILE
})
describe("plugin.meta", () => {
test("tracks file plugin loads and changes", async () => {
await using tmp = await tmpdir<{ file: string }>({
init: async (dir) => {
const file = path.join(dir, "plugin.ts")
await Bun.write(file, "export default async () => ({})\n")
return { file }
},
})
process.env.OPENCODE_PLUGIN_META_FILE = path.join(tmp.path, "state", "plugin-meta.json")
const file = process.env.OPENCODE_PLUGIN_META_FILE!
const spec = pathToFileURL(tmp.extra.file).href
const one = await PluginMeta.touch(spec, spec)
expect(one.state).toBe("new")
expect(one.entry.source).toBe("file")
expect(one.entry.modified).toBeDefined()
const two = await PluginMeta.touch(spec, spec)
expect(two.state).toBe("same")
expect(two.entry.load_count).toBe(2)
await Bun.sleep(20)
await Bun.write(tmp.extra.file, "export default async () => ({ ok: true })\n")
const three = await PluginMeta.touch(spec, spec)
expect(three.state).toBe("changed")
expect(three.entry.load_count).toBe(3)
expect((three.entry.modified ?? 0) >= (one.entry.modified ?? 0)).toBe(true)
await expect(fs.readFile(file, "utf8")).rejects.toThrow()
await PluginMeta.persist()
const all = await PluginMeta.list()
expect(Object.values(all).some((item) => item.spec === spec && item.source === "file")).toBe(true)
const saved = JSON.parse(await fs.readFile(file, "utf8")) as Record<string, { spec: string; load_count: number }>
expect(Object.values(saved).some((item) => item.spec === spec && item.load_count === 3)).toBe(true)
})
test("tracks npm plugin versions", async () => {
await using tmp = await tmpdir<{ mod: string; pkg: string }>({
init: async (dir) => {
const mod = path.join(dir, "node_modules", "acme-plugin")
const pkg = path.join(mod, "package.json")
await fs.mkdir(mod, { recursive: true })
await Bun.write(pkg, JSON.stringify({ name: "acme-plugin", version: "1.0.0" }, null, 2))
return { mod, pkg }
},
})
process.env.OPENCODE_PLUGIN_META_FILE = path.join(tmp.path, "state", "plugin-meta.json")
const file = process.env.OPENCODE_PLUGIN_META_FILE!
const one = await PluginMeta.touch("acme-plugin@latest", tmp.extra.mod)
expect(one.state).toBe("new")
expect(one.entry.source).toBe("npm")
expect(one.entry.requested).toBe("latest")
expect(one.entry.version).toBe("1.0.0")
await Bun.write(tmp.extra.pkg, JSON.stringify({ name: "acme-plugin", version: "1.1.0" }, null, 2))
const two = await PluginMeta.touch("acme-plugin@latest", tmp.extra.mod)
expect(two.state).toBe("changed")
expect(two.entry.version).toBe("1.1.0")
expect(two.entry.load_count).toBe(2)
await PluginMeta.persist()
const all = await PluginMeta.list()
expect(Object.values(all).some((item) => item.name === "acme-plugin" && item.version === "1.1.0")).toBe(true)
const saved = JSON.parse(await fs.readFile(file, "utf8")) as Record<string, { name: string; version?: string }>
expect(Object.values(saved).some((item) => item.name === "acme-plugin" && item.version === "1.1.0")).toBe(true)
})
})