test(agents): share pdf tool test setup

This commit is contained in:
Vincent Koc
2026-04-12 10:44:01 +01:00
parent a1279f012b
commit b4f5c748c3
3 changed files with 41 additions and 61 deletions

View File

@@ -1,35 +1,10 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { OpenClawConfig } from "../../config/config.js";
import { resolvePdfModelConfigForTool } from "./pdf-tool.model-config.js";
import { resetPdfToolAuthEnv, withTempPdfAgentDir } from "./pdf-tool.test-support.js";
const ANTHROPIC_PDF_MODEL = "anthropic/claude-opus-4-6";
async function withTempAgentDir<T>(run: (agentDir: string) => Promise<T>): Promise<T> {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-pdf-"));
try {
return await run(agentDir);
} finally {
await fs.rm(agentDir, { recursive: true, force: true });
}
}
function resetAuthEnv() {
vi.stubEnv("OPENAI_API_KEY", "");
vi.stubEnv("ANTHROPIC_API_KEY", "");
vi.stubEnv("ANTHROPIC_OAUTH_TOKEN", "");
vi.stubEnv("GEMINI_API_KEY", "");
vi.stubEnv("GOOGLE_API_KEY", "");
vi.stubEnv("MINIMAX_API_KEY", "");
vi.stubEnv("ZAI_API_KEY", "");
vi.stubEnv("Z_AI_API_KEY", "");
vi.stubEnv("COPILOT_GITHUB_TOKEN", "");
vi.stubEnv("GH_TOKEN", "");
vi.stubEnv("GITHUB_TOKEN", "");
}
function withDefaultModel(primary: string): OpenClawConfig {
return {
agents: { defaults: { model: { primary } } },
@@ -38,7 +13,7 @@ function withDefaultModel(primary: string): OpenClawConfig {
describe("resolvePdfModelConfigForTool", () => {
beforeEach(() => {
resetAuthEnv();
resetPdfToolAuthEnv();
});
afterEach(() => {
@@ -46,14 +21,14 @@ describe("resolvePdfModelConfigForTool", () => {
});
it("returns null without any auth", async () => {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
const cfg = withDefaultModel("openai/gpt-5.4");
expect(resolvePdfModelConfigForTool({ cfg, agentDir })).toBeNull();
});
});
it("prefers explicit pdfModel config", async () => {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
const cfg = {
agents: {
defaults: {
@@ -69,7 +44,7 @@ describe("resolvePdfModelConfigForTool", () => {
});
it("falls back to imageModel config when no pdfModel set", async () => {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
const cfg = {
agents: {
defaults: {
@@ -85,7 +60,7 @@ describe("resolvePdfModelConfigForTool", () => {
});
it("prefers anthropic when available for native PDF support", async () => {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
vi.stubEnv("ANTHROPIC_API_KEY", "anthropic-test");
vi.stubEnv("OPENAI_API_KEY", "openai-test");
const cfg = withDefaultModel("openai/gpt-5.4");
@@ -94,7 +69,7 @@ describe("resolvePdfModelConfigForTool", () => {
});
it("uses anthropic primary when provider is anthropic", async () => {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
vi.stubEnv("ANTHROPIC_API_KEY", "anthropic-test");
const cfg = withDefaultModel(ANTHROPIC_PDF_MODEL);
expect(resolvePdfModelConfigForTool({ cfg, agentDir })?.primary).toBe(ANTHROPIC_PDF_MODEL);

View File

@@ -0,0 +1,27 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { vi } from "vitest";
export async function withTempPdfAgentDir<T>(run: (agentDir: string) => Promise<T>): Promise<T> {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-pdf-"));
try {
return await run(agentDir);
} finally {
await fs.rm(agentDir, { recursive: true, force: true });
}
}
export function resetPdfToolAuthEnv(): void {
vi.stubEnv("OPENAI_API_KEY", "");
vi.stubEnv("ANTHROPIC_API_KEY", "");
vi.stubEnv("ANTHROPIC_OAUTH_TOKEN", "");
vi.stubEnv("GEMINI_API_KEY", "");
vi.stubEnv("GOOGLE_API_KEY", "");
vi.stubEnv("MINIMAX_API_KEY", "");
vi.stubEnv("ZAI_API_KEY", "");
vi.stubEnv("Z_AI_API_KEY", "");
vi.stubEnv("COPILOT_GITHUB_TOKEN", "");
vi.stubEnv("GH_TOKEN", "");
vi.stubEnv("GITHUB_TOKEN", "");
}

View File

@@ -9,6 +9,7 @@ import * as modelAuth from "../model-auth.js";
import * as modelsConfig from "../models-config.js";
import * as modelDiscovery from "../pi-model-discovery.js";
import * as pdfNativeProviders from "./pdf-native-providers.js";
import { resetPdfToolAuthEnv, withTempPdfAgentDir } from "./pdf-tool.test-support.js";
const completeMock = vi.hoisted(() => vi.fn());
@@ -31,15 +32,6 @@ async function loadCreatePdfTool() {
return createPdfTool;
}
async function withTempAgentDir<T>(run: (agentDir: string) => Promise<T>): Promise<T> {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-pdf-"));
try {
return await run(agentDir);
} finally {
await fs.rm(agentDir, { recursive: true, force: true });
}
}
const ANTHROPIC_PDF_MODEL = "anthropic/claude-opus-4-6";
const OPENAI_PDF_MODEL = "openai/gpt-5.4-mini";
const FAKE_PDF_MEDIA = {
@@ -66,27 +58,13 @@ type PdfToolInstance = ReturnType<typeof requirePdfTool>;
async function withConfiguredPdfTool(
run: (tool: PdfToolInstance, agentDir: string) => Promise<void>,
) {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
const cfg = withPdfModel(ANTHROPIC_PDF_MODEL);
const tool = requirePdfTool((await loadCreatePdfTool())({ config: cfg, agentDir }));
await run(tool, agentDir);
});
}
function resetAuthEnv() {
vi.stubEnv("OPENAI_API_KEY", "");
vi.stubEnv("ANTHROPIC_API_KEY", "");
vi.stubEnv("ANTHROPIC_OAUTH_TOKEN", "");
vi.stubEnv("GEMINI_API_KEY", "");
vi.stubEnv("GOOGLE_API_KEY", "");
vi.stubEnv("MINIMAX_API_KEY", "");
vi.stubEnv("ZAI_API_KEY", "");
vi.stubEnv("Z_AI_API_KEY", "");
vi.stubEnv("COPILOT_GITHUB_TOKEN", "");
vi.stubEnv("GH_TOKEN", "");
vi.stubEnv("GITHUB_TOKEN", "");
}
function withPdfModel(primary: string): OpenClawConfig {
return {
agents: { defaults: { pdfModel: { primary } } },
@@ -132,7 +110,7 @@ describe("createPdfTool", () => {
const priorFetch = global.fetch;
beforeEach(() => {
resetAuthEnv();
resetPdfToolAuthEnv();
completeMock.mockReset();
});
@@ -177,7 +155,7 @@ describe("createPdfTool", () => {
});
it("respects fsPolicy.workspaceOnly for non-sandbox pdf paths", async () => {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-pdf-ws-"));
const outsideDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-pdf-out-"));
try {
@@ -217,7 +195,7 @@ describe("createPdfTool", () => {
});
it("uses native PDF path without eager extraction", async () => {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
await stubPdfToolInfra(agentDir, { provider: "anthropic", input: ["text", "document"] });
vi.spyOn(pdfNativeProviders, "anthropicAnalyzePdf").mockResolvedValue("native summary");
const extractSpy = vi.spyOn(pdfExtractModule, "extractPdfContent");
@@ -238,7 +216,7 @@ describe("createPdfTool", () => {
});
it("rejects pages parameter for native PDF providers", async () => {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
await stubPdfToolInfra(agentDir, { provider: "anthropic", input: ["text", "document"] });
const cfg = withPdfModel(ANTHROPIC_PDF_MODEL);
const tool = requirePdfTool((await loadCreatePdfTool())({ config: cfg, agentDir }));
@@ -254,7 +232,7 @@ describe("createPdfTool", () => {
});
it("uses extraction fallback for non-native models", async () => {
await withTempAgentDir(async (agentDir) => {
await withTempPdfAgentDir(async (agentDir) => {
await stubPdfToolInfra(agentDir, { provider: "openai", input: ["text"] });
const extractSpy = vi.spyOn(pdfExtractModule, "extractPdfContent").mockResolvedValue({
text: "Extracted content",