@@ -153,6 +153,42 @@ describe("scripts/test-report-utils runVitestJsonReport", () => {
|
153 | 153 | ); |
154 | 154 | }); |
155 | 155 | |
| 156 | +it("uses distinct default report paths when invocations share a clock tick", async () => { |
| 157 | +const { runVitestJsonReport } = await import("../../scripts/test-report-utils.mjs"); |
| 158 | +const reportPaths: string[] = []; |
| 159 | +const nowSpy = vi.spyOn(Date, "now").mockReturnValue(1234567890); |
| 160 | +spawnSyncMock.mockImplementation((_command: string, args: string[]) => { |
| 161 | +const outputFileIndex = args.indexOf("--outputFile") + 1; |
| 162 | +const outputFile = args[outputFileIndex]; |
| 163 | +reportPaths.push(outputFile); |
| 164 | +fs.writeFileSync(outputFile, `${JSON.stringify({ testResults: [] })}\n`, "utf8"); |
| 165 | +return { status: 0 }; |
| 166 | +}); |
| 167 | + |
| 168 | +try { |
| 169 | +runVitestJsonReport({ |
| 170 | +config: "test/vitest/vitest.unit.config.ts", |
| 171 | +}); |
| 172 | +runVitestJsonReport({ |
| 173 | +config: "test/vitest/vitest.unit.config.ts", |
| 174 | +}); |
| 175 | + |
| 176 | +expect(reportPaths).toHaveLength(2); |
| 177 | +expect(reportPaths[0]).not.toBe(reportPaths[1]); |
| 178 | +for (const reportPath of reportPaths) { |
| 179 | +expect(path.dirname(reportPath)).toBe(os.tmpdir()); |
| 180 | +expect(path.basename(reportPath)).toMatch( |
| 181 | +/^openclaw-vitest-report-\d+-1234567890-[0-9a-f-]+\.json$/u, |
| 182 | +); |
| 183 | +} |
| 184 | +} finally { |
| 185 | +nowSpy.mockRestore(); |
| 186 | +for (const reportPath of reportPaths) { |
| 187 | +fs.rmSync(reportPath, { force: true }); |
| 188 | +} |
| 189 | +} |
| 190 | +}); |
| 191 | + |
156 | 192 | it("fails when Vitest exits successfully without writing a JSON report", async () => { |
157 | 193 | const { runVitestJsonReport } = await import("../../scripts/test-report-utils.mjs"); |
158 | 194 | spawnSyncMock.mockReturnValue({ status: 0 }); |
|