fix: use dependency injection for image-downloader fs mocks
mock.module("fs/promises") on Linux Bun poisons the entire mock
tracking system — not just fs mocks, but ALL mock/spy assertions
(octokit mocks, spyOn(global, "fetch"), etc.) stop recording calls.
Replace with dependency injection: downloadCommentImages() now accepts
an optional fsDeps parameter. Tests pass mock mkdir/writeFile directly.
Production callers omit it and get real fs. No mock.module anywhere.
Fixes 18 test failures blocking CI on Forgejo Linux runners.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
6113a4ef2d
commit
a6b3c94004
3 files changed
+54
-16
No files matched your search
@@ -9,22 +9,10 @@ import {
|
||||
setSystemTime,
|
||||
} from "bun:test";
|
||||
|
||||
// Mock fs/promises at the module loader level. Bun hoists mock.module calls
|
||||
// before imports, so the source module's `import fs from "fs/promises"` gets
|
||||
// these mocks. This avoids cross-module jest.fn() tracking bugs on Linux Bun.
|
||||
const mockMkdir = mock(() => Promise.resolve(undefined as any));
|
||||
const mockWriteFile = mock(() => Promise.resolve(undefined as any));
|
||||
|
||||
mock.module("fs/promises", () => ({
|
||||
default: {
|
||||
mkdir: mockMkdir,
|
||||
writeFile: mockWriteFile,
|
||||
},
|
||||
}));
|
||||
|
||||
import {
|
||||
downloadCommentImages,
|
||||
type CommentWithImages,
|
||||
type FsDeps,
|
||||
} from "../src/github/utils/image-downloader";
|
||||
import type { Octokits } from "../src/github/api/client";
|
||||
|
||||
@@ -35,6 +23,14 @@ describe("downloadCommentImages", () => {
|
||||
let fetchSpy: any;
|
||||
let savedServerUrl: string | undefined;
|
||||
|
||||
// DI mocks for fs — avoids mock.module which poisons mock tracking on Linux Bun
|
||||
const mockMkdir = mock(() => Promise.resolve(undefined as any));
|
||||
const mockWriteFile = mock(() => Promise.resolve(undefined as any));
|
||||
const fsDeps: FsDeps = {
|
||||
mkdir: mockMkdir as any,
|
||||
writeFile: mockWriteFile as any,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
// Pin GITHUB_SERVER_URL so tests pass regardless of runner environment.
|
||||
// The image-downloader reads process.env directly at call time.
|
||||
@@ -88,7 +84,7 @@ describe("downloadCommentImages", () => {
|
||||
const mockOctokit = createMockOctokit();
|
||||
const comments: CommentWithImages[] = [];
|
||||
|
||||
await downloadCommentImages(mockOctokit, "owner", "repo", comments);
|
||||
await downloadCommentImages(mockOctokit, "owner", "repo", comments, fsDeps);
|
||||
|
||||
expect(mockMkdir).toHaveBeenCalledWith("/tmp/github-images", {
|
||||
recursive: true,
|
||||
@@ -110,6 +106,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(result.size).toBe(0);
|
||||
@@ -155,6 +152,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(mockOctokit.rest.issues.getComment).toHaveBeenCalledWith({
|
||||
@@ -217,6 +215,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(mockOctokit.rest.pulls.getReviewComment).toHaveBeenCalledWith({
|
||||
@@ -266,6 +265,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(mockOctokit.rest.pulls.getReview).toHaveBeenCalledWith({
|
||||
@@ -315,6 +315,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(mockOctokit.rest.issues.get).toHaveBeenCalledWith({
|
||||
@@ -365,6 +366,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(mockOctokit.rest.pulls.get).toHaveBeenCalledWith({
|
||||
@@ -418,6 +420,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(2);
|
||||
@@ -471,6 +474,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(1); // Only downloaded once
|
||||
@@ -506,6 +510,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(result.size).toBe(0);
|
||||
@@ -548,6 +553,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(result.size).toBe(0);
|
||||
@@ -579,6 +585,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(result.size).toBe(0);
|
||||
@@ -652,6 +659,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
expect(result.get(url)).toBe(
|
||||
`/tmp/github-images/image-${1704067200000 + callIndex}-0${ext}`,
|
||||
@@ -698,6 +706,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
||||
@@ -745,6 +754,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(mockOctokit.rest.issues.getComment).toHaveBeenCalledWith({
|
||||
@@ -811,6 +821,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(2);
|
||||
@@ -863,6 +874,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(2);
|
||||
@@ -911,6 +923,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(1); // Only downloaded once
|
||||
@@ -957,6 +970,7 @@ describe("downloadCommentImages", () => {
|
||||
"owner",
|
||||
"repo",
|
||||
comments,
|
||||
fsDeps,
|
||||
);
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
Reference in new issue
Block a user