diff --git a/src/scripts/ci-changed-scope.test.ts b/src/scripts/ci-changed-scope.test.ts index 2de370a48..bd5c213bd 100644 --- a/src/scripts/ci-changed-scope.test.ts +++ b/src/scripts/ci-changed-scope.test.ts @@ -1,14 +1,29 @@ -import { createRequire } from "node:module"; -import { describe, expect, it } from "vitest"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { afterEach, describe, expect, it } from "vitest"; -const { detectChangedScope } = (await import("../../scripts/ci-changed-scope.mjs")) as unknown as { - detectChangedScope: (paths: string[]) => { - runNode: boolean; - runMacos: boolean; - runAndroid: boolean; - runWindows: boolean; +const { detectChangedScope, listChangedPaths } = + (await import("../../scripts/ci-changed-scope.mjs")) as unknown as { + detectChangedScope: (paths: string[]) => { + runNode: boolean; + runMacos: boolean; + runAndroid: boolean; + runWindows: boolean; + }; + listChangedPaths: (base: string, head?: string) => string[]; }; -}; + +const markerPaths: string[] = []; + +afterEach(() => { + for (const markerPath of markerPaths) { + try { + fs.unlinkSync(markerPath); + } catch {} + } + markerPaths.length = 0; +}); describe("detectChangedScope", () => { it("fails safe when no paths are provided", () => { @@ -88,4 +103,20 @@ describe("detectChangedScope", () => { runWindows: false, }); }); + + it("treats base and head as literal git args", () => { + const markerPath = path.join( + os.tmpdir(), + `openclaw-ci-changed-scope-${Date.now()}-${Math.random().toString(16).slice(2)}.tmp`, + ); + markerPaths.push(markerPath); + + const injectedBase = + process.platform === "win32" + ? `HEAD & echo injected > "${markerPath}" & rem` + : `HEAD; touch "${markerPath}" #`; + + expect(() => listChangedPaths(injectedBase, "HEAD")).toThrow(); + expect(fs.existsSync(markerPath)).toBe(false); + }); });