

























@@ -13,71 +13,99 @@ afterEach(() => {
1313vi.resetModules();
1414});
151516-describe("update-clawtributors", () => {
17-it("cancels stalled avatar probe body reads at the probe timeout", async () => {
18-const readme = [
19-"# Fixture",
20-"",
21-"Thanks to all clawtributors:",
22-"",
23-"<!-- clawtributors:start -->",
24-"<!-- clawtributors:end -->",
25-"",
26-].join("\n");
27-let writtenReadme = "";
28-vi.doMock("node:fs", () => ({
29-readFileSync: vi.fn((path: string) => {
30-if (path.endsWith("scripts/clawtributors-map.json")) {
31-return "{}\n";
32-}
33-if (path.endsWith("README.md")) {
34-return readme;
35-}
36-throw new Error(`unexpected read: ${path}`);
37-}),
38-writeFileSync: vi.fn((path: string, data: string) => {
39-if (path.endsWith("README.md")) {
40-writtenReadme = data;
41-return;
42-}
43-throw new Error(`unexpected write: ${path}`);
44-}),
45-}));
46-const contributor = {
47-login: "octo",
48-name: "Octo",
49-html_url: "https://github.com/octo",
50-avatar_url: "https://avatars.githubusercontent.com/u/1?v=4",
51-contributions: 3,
52-};
53-const execSync = vi.fn((cmd: string) => {
54-if (cmd === 'gh api "repos/openclaw/openclaw/contributors?per_page=100&anon=1" --paginate') {
55-return `${JSON.stringify([contributor])}\n`;
56-}
57-if (cmd === "git log --reverse --format=%aN%x1f%aE%x1f%aI --numstat") {
58-return "";
59-}
60-if (
61-cmd ===
62-"gh pr list -R openclaw/openclaw --state merged --limit 5000 --json author --jq '.[].author.login'"
63-) {
64-return "";
16+function mockClawtributorsFixture() {
17+const readme = [
18+"# Fixture",
19+"",
20+"Thanks to all clawtributors:",
21+"",
22+"<!-- clawtributors:start -->",
23+"<!-- clawtributors:end -->",
24+"",
25+].join("\n");
26+let writtenReadme = "";
27+vi.doMock("node:fs", () => ({
28+readFileSync: vi.fn((path: string) => {
29+if (path.endsWith("scripts/clawtributors-map.json")) {
30+return "{}\n";
6531}
66-if (cmd === "git rev-list --max-parents=0 HEAD") {
67-return "root-sha\n";
32+if (path.endsWith("README.md")) {
33+return readme;
6834}
69-if (cmd === "git log --format=%aI -1 root-sha") {
70-return "2024-01-01T00:00:00Z\n";
35+throw new Error(`unexpected read: ${path}`);
36+}),
37+writeFileSync: vi.fn((path: string, data: string) => {
38+if (path.endsWith("README.md")) {
39+writtenReadme = data;
40+return;
7141}
72-throw new Error(`unexpected command: ${cmd}`);
73-});
74-vi.doMock("node:child_process", () => ({
75-execFileSync: vi.fn(() => {
76-throw new Error("unexpected execFileSync");
77-}),
78- execSync,
79-}));
42+throw new Error(`unexpected write: ${path}`);
43+}),
44+}));
45+const contributor = {
46+login: "octo",
47+name: "Octo",
48+html_url: "https://github.com/octo",
49+avatar_url: "https://avatars.githubusercontent.com/u/1?v=4",
50+contributions: 3,
51+};
52+const execSync = vi.fn((cmd: string) => {
53+if (cmd === 'gh api "repos/openclaw/openclaw/contributors?per_page=100&anon=1" --paginate') {
54+return `${JSON.stringify([contributor])}\n`;
55+}
56+if (cmd === "git log --reverse --format=%aN%x1f%aE%x1f%aI --numstat") {
57+return "";
58+}
59+if (
60+cmd ===
61+"gh pr list -R openclaw/openclaw --state merged --limit 5000 --json author --jq '.[].author.login'"
62+) {
63+return "";
64+}
65+if (cmd === "git rev-list --max-parents=0 HEAD") {
66+return "root-sha\n";
67+}
68+if (cmd === "git log --format=%aI -1 root-sha") {
69+return "2024-01-01T00:00:00Z\n";
70+}
71+throw new Error(`unexpected command: ${cmd}`);
72+});
73+vi.doMock("node:child_process", () => ({
74+execFileSync: vi.fn(() => {
75+throw new Error("unexpected execFileSync");
76+}),
77+ execSync,
78+}));
79+return {
80+readWrittenReadme: () => writtenReadme,
81+};
82+}
83+84+async function importUpdateClawtributors() {
85+const scriptUrl = pathToFileURL(resolve(originalCwd, "scripts/update-clawtributors.ts")).href;
86+await import(`${scriptUrl}?case=${Date.now()}`);
87+}
808889+describe("update-clawtributors", () => {
90+it("rejects unsafe avatar probe content lengths before reading the body", async () => {
91+const fixture = mockClawtributorsFixture();
92+const arrayBuffer = vi.fn(async () => new ArrayBuffer(0));
93+vi.stubGlobal("fetch", (() =>
94+Promise.resolve({
95+ok: true,
96+headers: new Headers({ "content-length": "9007199254740992" }),
97+ arrayBuffer,
98+} as unknown as Response)) as typeof fetch);
99+vi.spyOn(console, "log").mockImplementation(() => undefined);
100+101+await importUpdateClawtributors();
102+103+expect(arrayBuffer).not.toHaveBeenCalled();
104+expect(fixture.readWrittenReadme()).toContain("https://github.com/octo");
105+});
106+107+it("cancels stalled avatar probe body reads at the probe timeout", async () => {
108+const fixture = mockClawtributorsFixture();
81109let signal: AbortSignal | undefined;
82110let canceled = false;
83111let markFetchStarted!: () => void;
@@ -104,8 +132,7 @@ describe("update-clawtributors", () => {
104132vi.spyOn(console, "log").mockImplementation(() => undefined);
105133106134vi.useFakeTimers();
107-const scriptUrl = pathToFileURL(resolve(originalCwd, "scripts/update-clawtributors.ts")).href;
108-const imported = import(`${scriptUrl}?case=${Date.now()}`);
135+const imported = importUpdateClawtributors();
109136110137await fetchStarted;
111138await vi.advanceTimersByTimeAsync(8000);
@@ -114,6 +141,6 @@ describe("update-clawtributors", () => {
114141115142expect(signal?.aborted).toBe(true);
116143expect(canceled).toBe(true);
117-expect(writtenReadme).toContain("https://github.com/octo");
144+expect(fixture.readWrittenReadme()).toContain("https://github.com/octo");
118145});
119146});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。