paperclip / server /src /__tests__ /firm.test.ts
Leon4gr45's picture
Bundle paperclip + openviking into HF Docker Space
64648ce
Raw
History Blame Contribute Delete
4.42 kB
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
// Force the plain-text fallback path: point the CLI at a command that does not
// exist so detectCli() resolves to unavailable, and isolate the workspace root.
const tmpRoot = mkdtempSync(path.join(os.tmpdir(), "paperclip-firm-test-"));
process.env.PAPERCLIP_FIRM_HOME = tmpRoot;
process.env.PAPERCLIP_FIRM_CLI = "paperclip-nonexistent-firm-cli-xyz";
const { firmService } = await import("../services/firm.ts");
const { companyContextCache, COMPANY_SCOPE_KEY } = await import("../services/company-context-cache.ts");
const COMPANY = "11111111-1111-1111-1111-111111111111";
describe("firmService (plain-text fallback)", () => {
beforeAll(async () => {
// Prime CLI detection cache as unavailable.
const detection = await firmService().detectCli(true);
expect(detection.available).toBe(false);
});
afterAll(() => {
rmSync(tmpRoot, { recursive: true, force: true });
});
beforeEach(() => {
companyContextCache.clear();
});
it("ensureWorkspace is idempotent and records the company name", async () => {
const firm = firmService();
const first = await firm.ensureWorkspace(COMPANY, "Acme Inc");
expect(first.companyId).toBe(COMPANY);
expect(first.companyName).toBe("Acme Inc");
expect(await firm.isInitialized(COMPANY)).toBe(true);
const second = await firm.ensureWorkspace(COMPANY, "Acme Inc");
expect(second.createdAt).toBe(first.createdAt);
});
it("links projects and lists them", async () => {
const firm = firmService();
await firm.linkProject({ companyId: COMPANY, projectId: "proj-a", name: "Website", repoUrl: "https://example.com/web.git" });
await firm.linkProject({ companyId: COMPANY, projectId: "proj-b", name: "API" });
const records = await firm.listProjectRecords(COMPANY);
expect(records.map((r) => r.name).sort()).toEqual(["API", "Website"]);
expect(records.find((r) => r.projectId === "proj-a")?.repoUrl).toBe("https://example.com/web.git");
});
it("renders a snapshot from plain-text records and warms the cache", async () => {
const firm = firmService();
const meta = await firm.writeSnapshot(COMPANY);
expect(meta.cliUsed).toBe(false);
expect(meta.projectCount).toBe(2);
const contextFile = readFileSync(path.join(firm.companyFirmDir(COMPANY), "context.md"), "utf-8");
expect(contextFile).toContain("Acme Inc");
expect(contextFile).toContain("Website");
expect(contextFile).toContain("API");
// Snapshot wrote through to the warm cache.
expect(companyContextCache.peek(COMPANY, COMPANY_SCOPE_KEY)?.content).toContain("Website");
});
it("getContext returns warm content and is fresh right after a snapshot", async () => {
const firm = firmService();
await firm.writeSnapshot(COMPANY);
const ctx = await firm.getContext({ companyId: COMPANY });
expect(ctx).toContain("Acme Inc");
expect(await firm.isStale(COMPANY)).toBe(false);
});
it("getContext hydrates from disk on a cold cache", async () => {
const firm = firmService();
await firm.writeSnapshot(COMPANY);
companyContextCache.clear();
const ctx = await firm.getContext({ companyId: COMPANY });
expect(ctx).toContain("Acme Inc");
expect(companyContextCache.peek(COMPANY, COMPANY_SCOPE_KEY)?.content).toContain("Acme Inc");
});
it("getContext returns null for a company with no workspace", async () => {
const firm = firmService();
const ctx = await firm.getContext({ companyId: "no-such-company" });
expect(ctx).toBeNull();
});
it("isStale is true when there is no snapshot, and respects maxAge", async () => {
const firm = firmService();
const fresh = "22222222-2222-2222-2222-222222222222";
expect(await firm.isStale(fresh)).toBe(true);
await firm.ensureWorkspace(fresh, "Beta");
await firm.writeSnapshot(fresh);
// Far in the future relative to maxAge → stale.
expect(await firm.isStale(fresh, 1_000, Date.now() + 10_000)).toBe(true);
});
it("lists only initialized company workspaces", async () => {
const firm = firmService();
await firm.ensureWorkspace(COMPANY, "Acme Inc");
const ids = await firm.listInitializedCompanyIds();
expect(ids).toContain(COMPANY);
});
});