import fs from "node:fs/promises"; import path from "node:path"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { createTestPluginApi } from "../../../test/helpers/plugins/plugin-api.js"; import type { OpenClawPluginApi } from "../api.js"; import type { DiffScreenshotter } from "./browser.js"; import { DEFAULT_DIFFS_TOOL_DEFAULTS } from "./config.js"; import { createDiffStoreHarness } from "./test-helpers.js"; const { renderDiffDocumentMock } = vi.hoisted(() => ({ renderDiffDocumentMock: vi.fn(), })); vi.mock("./render.js", () => ({ renderDiffDocument: renderDiffDocumentMock, })); describe("diffs tool rendered output guards", () => { let cleanupRootDir: () => Promise; let store: Awaited>["store"]; beforeEach(async () => { vi.resetModules(); renderDiffDocumentMock.mockReset(); ({ store, cleanup: cleanupRootDir } = await createDiffStoreHarness( "openclaw-diffs-tool-render-output-", )); }); afterEach(async () => { await cleanupRootDir(); }); it("accepts empty string image html for file output", async () => { renderDiffDocumentMock.mockResolvedValue({ title: "Text diff", fileCount: 1, inputKind: "before_after", imageHtml: "", }); const { createDiffsTool } = await import("./tool.js"); const screenshotter = createPngScreenshotter({ assertHtml: (html) => { expect(html).toBe(""); }, }); const tool = createDiffsTool({ api: createApi(), store, defaults: DEFAULT_DIFFS_TOOL_DEFAULTS, screenshotter, }); const result = await tool.execute?.("tool-empty-image-html", { before: "one\n", after: "two\n", mode: "file", }); expect(screenshotter.screenshotHtml).toHaveBeenCalledTimes(1); expect((result?.details as Record).filePath).toEqual(expect.any(String)); }); }); function createApi(): OpenClawPluginApi { return createTestPluginApi({ id: "diffs", name: "Diffs", description: "Diffs", source: "test", config: { gateway: { port: 18789, bind: "loopback", }, }, runtime: {} as OpenClawPluginApi["runtime"], }) as OpenClawPluginApi; } function createPngScreenshotter( params: { assertHtml?: (html: string) => void; } = {}, ): DiffScreenshotter { const screenshotHtml: DiffScreenshotter["screenshotHtml"] = vi.fn( async ({ html, outputPath }: { html: string; outputPath: string }) => { params.assertHtml?.(html); await fs.mkdir(path.dirname(outputPath), { recursive: true }); await fs.writeFile(outputPath, Buffer.from("png")); return outputPath; }, ); return { screenshotHtml, }; }