* feat(draw-image): add SVG template render engine * feat(draw-image): add opencode plugin and tool tests * test(draw-image): add vitest unit integration e2e suite * chore(draw-image): wire CI dependabot docs and ADR * docs(handoff): set PR number * docs(handoff): fix PR number placeholder in frontmatter * fix(ci): use tempfile and trailing newline in draw-image tests --------- Co-authored-by: opencode-agent <agent@opencode.local>
70 lines
No EOL
3 KiB
TypeScript
70 lines
No EOL
3 KiB
TypeScript
/**
|
|
* Tests for .opencode/tools/draw-image.ts — the draw-image custom tool.
|
|
*
|
|
* Mirror of tests/test_commit_tool.ts: the tool is a spawnSync wrapper
|
|
* around `node cli.ts render ...`. Runtime note: opencode ships a standalone
|
|
* binary with Bun bundled inside; there is no separate `bun` CLI on the host
|
|
* (CI runner uses node + pytest). The CI runs the equivalent Python tests in
|
|
* tests/test_draw_image_tool.py via the JS loader tests/_ts_loader.mjs
|
|
* (exec_stub_json mode for multi-arg tools). This file documents the intended
|
|
* TS-side test cases and is runnable under `bun test` once a bun runtime is
|
|
* available on the host.
|
|
*
|
|
* Test cases (mirror tests/test_draw_image_tool.py):
|
|
* - test_loader_can_load_tool — tool loads, declares args
|
|
* - test_valid_render — valid args + spawnSync exit 0 → JSON result
|
|
* - test_render_failure — spawnSync exit 1 → error string
|
|
* - test_execute_uses_cwd_from_context — cwd=context.worktree propagated
|
|
*/
|
|
|
|
import { describe, test, expect, mock } from "bun:test" with { type: "'bun-test'" }
|
|
import { spawnSync } from "child_process"
|
|
import path from "path"
|
|
|
|
const TOOL_SRC = path.resolve(import.meta.dir, "..", ".opencode", "tools", "draw-image.ts")
|
|
|
|
function ctx() {
|
|
return {
|
|
sessionID: "t", messageID: "t", agent: "t",
|
|
directory: ".", worktree: ".",
|
|
abort: new AbortController().signal,
|
|
metadata() {}, async ask() {},
|
|
}
|
|
}
|
|
|
|
describe("draw-image tool", () => {
|
|
test("test_valid_render — valid args + spawnSync exit 0 returns JSON", async () => {
|
|
const okResponse = '{"path":"/tmp/out.png","hash":"abc123","status":"rendered"}'
|
|
mock.module("child_process", () => ({
|
|
spawnSync: () => ({ status: 0, stdout: okResponse, stderr: "" }),
|
|
}))
|
|
const mod = await import(TOOL_SRC + "?t=" + Date.now())
|
|
const result = await mod.default.execute({ template: "cover", title: "Test" }, ctx())
|
|
expect(result).toContain("rendered")
|
|
expect(result).toContain("/tmp/out.png")
|
|
})
|
|
|
|
test("test_render_failure — spawnSync exit 1 returns error", async () => {
|
|
mock.module("child_process", () => ({
|
|
spawnSync: () => ({ status: 1, stdout: "", stderr: "render failed" }),
|
|
}))
|
|
const mod = await import(TOOL_SRC + "?t=" + Date.now())
|
|
const result = await mod.default.execute({ template: "cover", title: "Test" }, ctx())
|
|
expect(result).toContain("draw-image failed")
|
|
})
|
|
|
|
test("test_execute_uses_cwd_from_context — cwd propagated to spawnSync", async () => {
|
|
const okResponse = '{"path":"./out.png","hash":"abc","status":"rendered"}'
|
|
let capturedOpts: any = null
|
|
mock.module("child_process", () => ({
|
|
spawnSync: (_cmd: string, _args: string[], opts: any) => {
|
|
capturedOpts = opts
|
|
return { status: 0, stdout: okResponse, stderr: "" }
|
|
},
|
|
}))
|
|
const mod = await import(TOOL_SRC + "?t=" + Date.now())
|
|
await mod.default.execute({ template: "cover", title: "Test" }, ctx())
|
|
expect(capturedOpts).not.toBeNull()
|
|
expect(capturedOpts.cwd).toBe(".")
|
|
})
|
|
}) |