From ac9e9cddff1ec0aa3e23144e956ac2e0262160ae Mon Sep 17 00:00:00 2001 From: Vlad Mocanu Date: Thu, 26 Feb 2026 09:33:15 +0200 Subject: [PATCH] fix: replace mock.module with spyOn to stop cross-file test pollution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mock.module("image-downloader") in forgejo-data-fetcher.test.ts replaced the module in Bun's registry globally for the entire process. When Bun's non-deterministic file ordering ran this file BEFORE image-downloader.test.ts, the image-downloader tests imported a stubbed module instead of the real one, breaking all 18 tests. This was the root cause of the CI failures that persisted through 5 previous fix attempts. spyOn patches the live module export per-test and is auto-restored by Bun after each test — no cross-file pollution regardless of execution order. Co-Authored-By: Claude Opus 4.6 --- test/forgejo-data-fetcher.test.ts | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/forgejo-data-fetcher.test.ts b/test/forgejo-data-fetcher.test.ts index aeeb494..dd658c3 100644 --- a/test/forgejo-data-fetcher.test.ts +++ b/test/forgejo-data-fetcher.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, jest, mock } from "bun:test"; +import { beforeEach, describe, expect, it, jest, spyOn } from "bun:test"; import { fetchForgejoData, mapFileStatus, @@ -8,11 +8,12 @@ import { } from "../src/forgejo/data/fetcher"; import type { Octokits } from "../src/github/api/client"; import type { GitHubReviewComment } from "../src/github/types"; - -// Mock image downloader — returns empty map (no-op on Forgejo) -mock.module("../src/github/utils/image-downloader", () => ({ - downloadCommentImages: jest.fn().mockResolvedValue(new Map()), -})); +// Import the module namespace so spyOn can patch the export directly. +// This avoids mock.module() which replaces the module in Bun's registry +// globally for the entire process — poisoning other test files +// (like image-downloader.test.ts) that import the same module. +// spyOn is auto-restored after each test, so no cross-file pollution. +import * as imageDownloaderModule from "../src/github/utils/image-downloader"; // Helper to build a mock Octokits with REST methods function createMockOctokits({ @@ -125,6 +126,15 @@ const mockIssueRestResponse = { }; describe("fetchForgejoData", () => { + // Stub downloadCommentImages per-test — returns empty Map (no-op on Forgejo). + // spyOn patches the live module export and is auto-restored after each test, + // unlike mock.module which persists for the entire Bun process. + beforeEach(() => { + spyOn(imageDownloaderModule, "downloadCommentImages").mockResolvedValue( + new Map(), + ); + }); + describe("PR data fetching", () => { it("should fetch PR details, files, commits, comments, and reviews in parallel then per-review comments", async () => { const mockOctokits = createMockOctokits({