返回 CodeWhale
facts-drift.test.ts
根目录 / web / lib / facts-drift.test.ts
1 import { afterEach, describe, expect, it, vi } from "vitest";
2 import { deriveFactsFromRemote } from "./facts-drift";
3
4 const REVISION = "b".repeat(40);
5
6 function response(body: string, status = 200): Response {
7 return new Response(body, { status });
8 }
9
10 function installGitHubFixture(toolCountSource: string | null): void {
11 vi.stubGlobal(
12 "fetch",
13 vi.fn(async (input: string | URL | Request) => {
14 const url = String(input);
15 if (url.endsWith("/commits/main")) {
16 return response(
17 JSON.stringify({
18 sha: REVISION,
19 commit: { committer: { date: "2026-07-21T23:00:00Z" } },
20 }),
21 );
22 }
23 if (url.endsWith("/releases/latest")) {
24 return response(
25 JSON.stringify({
26 tag_name: "v0.9.0",
27 published_at: "2026-07-16T20:05:39Z",
28 html_url: "https://github.com/Hmbown/CodeWhale/releases/tag/v0.9.0",
29 }),
30 );
31 }
32 const rawPath = url.split(`/${REVISION}/`)[1];
33 const sources: Record<string, string> = {
34 "Cargo.toml": 'version = "0.9.2"\nmembers = ["crates/tui"]',
35 "crates/tui/src/config.rs":
36 'pub enum ApiProvider {\n Deepseek,\n}\nconst DEFAULT_TEXT_MODEL: &str = "remote-model";',
37 "crates/tui/src/config/models.rs": "",
38 "crates/tui/src/sandbox/mod.rs": `
39 pub const PUBLIC_SANDBOX_BACKENDS: &[&str] = &[
40 "seatbelt (macOS, when available)",
41 "bubblewrap (Linux, opt-in when installed)",
42 ];
43 `,
44 "npm/codewhale/package.json": JSON.stringify({ engines: { node: ">=18" } }),
45 LICENSE: "MIT License\n",
46 };
47 if (rawPath === "web/lib/facts.generated.ts") {
48 return toolCountSource === null ? response("not found", 404) : response(toolCountSource);
49 }
50 return rawPath && rawPath in sources
51 ? response(sources[rawPath])
52 : response("not found", 404);
53 }),
54 );
55 }
56
57 afterEach(() => {
58 vi.unstubAllGlobals();
59 });
60
61 describe("deriveFactsFromRemote", () => {
62 it("derives tool count and model rows from the same exact remote revision", async () => {
63 installGitHubFixture(
64 'export const FACTS: RepoFacts = {"toolCount":73,"models":[' +
65 '{"id":"deepseek-v4-pro","provider":"DeepSeek","contextWindow":1000000,' +
66 '"maxOutput":128000,"reasoning":true,"addedAt":"2026-07-01"}' +
67 "]};",
68 );
69
70 const facts = await deriveFactsFromRemote();
71
72 expect(facts?.sourceRevision).toBe(REVISION);
73 expect(facts?.version).toBe("0.9.2");
74 expect(facts?.toolCount).toBe(73);
75 expect(facts?.models).toEqual([
76 {
77 id: "deepseek-v4-pro",
78 provider: "DeepSeek",
79 contextWindow: 1000000,
80 maxOutput: 128000,
81 reasoning: true,
82 addedAt: "2026-07-01",
83 },
84 ]);
85 expect(facts?.sandboxBackends).toEqual([
86 "seatbelt (macOS, when available)",
87 "bubblewrap (Linux, opt-in when installed)",
88 ]);
89 const fetchMock = vi.mocked(fetch);
90 expect(
91 fetchMock.mock.calls.some(([input]) => String(input).includes("/contents/")),
92 ).toBe(false);
93 });
94
95 it("fails derivation when the exact revision has no valid tool count", async () => {
96 installGitHubFixture(null);
97
98 await expect(deriveFactsFromRemote()).resolves.toBeNull();
99 });
100
101 it("fails derivation when the exact revision has malformed model rows", async () => {
102 installGitHubFixture(
103 'export const FACTS: RepoFacts = {"toolCount":73,"models":[{"id":42}]};',
104 );
105
106 await expect(deriveFactsFromRemote()).resolves.toBeNull();
107 });
108 });
109
109 lines TYPESCRIPT