perf(test): reduce module reload churn in unit suites

This commit is contained in:
Peter Steinberger
2026-02-13 15:19:09 +00:00
parent 6c4c535813
commit faec6ccb1d
4 changed files with 18 additions and 64 deletions

View File

@@ -1,4 +1,6 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import * as authModule from "../agents/model-auth.js";
import { createVoyageEmbeddingProvider, normalizeVoyageModel } from "./embeddings-voyage.js";
vi.mock("../agents/model-auth.js", () => ({
resolveApiKeyForProvider: vi.fn(),
@@ -20,7 +22,6 @@ const createFetchMock = () =>
describe("voyage embedding provider", () => {
afterEach(() => {
vi.resetAllMocks();
vi.resetModules();
vi.unstubAllGlobals();
});
@@ -28,9 +29,6 @@ describe("voyage embedding provider", () => {
const fetchMock = createFetchMock();
vi.stubGlobal("fetch", fetchMock);
const { createVoyageEmbeddingProvider } = await import("./embeddings-voyage.js");
const authModule = await import("../agents/model-auth.js");
vi.mocked(authModule.resolveApiKeyForProvider).mockResolvedValue({
apiKey: "voyage-key-123",
mode: "api-key",
@@ -69,8 +67,6 @@ describe("voyage embedding provider", () => {
const fetchMock = createFetchMock();
vi.stubGlobal("fetch", fetchMock);
const { createVoyageEmbeddingProvider } = await import("./embeddings-voyage.js");
const result = await createVoyageEmbeddingProvider({
config: {} as never,
provider: "voyage",
@@ -103,9 +99,6 @@ describe("voyage embedding provider", () => {
})) as unknown as typeof fetch;
vi.stubGlobal("fetch", fetchMock);
const { createVoyageEmbeddingProvider } = await import("./embeddings-voyage.js");
const authModule = await import("../agents/model-auth.js");
vi.mocked(authModule.resolveApiKeyForProvider).mockResolvedValue({
apiKey: "voyage-key-123",
mode: "api-key",
@@ -131,7 +124,6 @@ describe("voyage embedding provider", () => {
});
it("normalizes model names", async () => {
const { normalizeVoyageModel } = await import("./embeddings-voyage.js");
expect(normalizeVoyageModel("voyage/voyage-large-2")).toBe("voyage-large-2");
expect(normalizeVoyageModel("voyage-4-large")).toBe("voyage-4-large");
expect(normalizeVoyageModel(" voyage-lite ")).toBe("voyage-lite");

View File

@@ -1,4 +1,4 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
import { DEFAULT_GEMINI_EMBEDDING_MODEL } from "./embeddings-gemini.js";
vi.mock("../agents/model-auth.js", () => ({
@@ -21,7 +21,6 @@ const createFetchMock = () =>
describe("embedding provider remote overrides", () => {
afterEach(() => {
vi.resetAllMocks();
vi.resetModules();
vi.unstubAllGlobals();
});
@@ -170,7 +169,6 @@ describe("embedding provider remote overrides", () => {
describe("embedding provider auto selection", () => {
afterEach(() => {
vi.resetAllMocks();
vi.resetModules();
vi.unstubAllGlobals();
});
@@ -266,6 +264,10 @@ describe("embedding provider auto selection", () => {
});
describe("embedding provider local fallback", () => {
beforeAll(() => {
vi.resetModules();
});
afterEach(() => {
vi.resetAllMocks();
vi.resetModules();

View File

@@ -1,7 +1,7 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { removeReactionSignal, sendReactionSignal } from "./send-reactions.js";
const rpcMock = vi.fn();
const loadSendReactions = async () => await import("./send-reactions.js");
vi.mock("../config/config.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../config/config.js")>();
@@ -28,11 +28,9 @@ vi.mock("./client.js", () => ({
describe("sendReactionSignal", () => {
beforeEach(() => {
rpcMock.mockReset().mockResolvedValue({ timestamp: 123 });
vi.resetModules();
});
it("uses recipients array and targetAuthor for uuid dms", async () => {
const { sendReactionSignal } = await loadSendReactions();
await sendReactionSignal("uuid:123e4567-e89b-12d3-a456-426614174000", 123, "🔥");
const params = rpcMock.mock.calls[0]?.[1] as Record<string, unknown>;
@@ -45,7 +43,6 @@ describe("sendReactionSignal", () => {
});
it("uses groupIds array and maps targetAuthorUuid", async () => {
const { sendReactionSignal } = await loadSendReactions();
await sendReactionSignal("", 123, "✅", {
groupId: "group-id",
targetAuthorUuid: "uuid:123e4567-e89b-12d3-a456-426614174000",
@@ -58,7 +55,6 @@ describe("sendReactionSignal", () => {
});
it("defaults targetAuthor to recipient for removals", async () => {
const { removeReactionSignal } = await loadSendReactions();
await removeReactionSignal("+15551230000", 456, "❌");
const params = rpcMock.mock.calls[0]?.[1] as Record<string, unknown>;

View File

@@ -1,5 +1,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import * as ssrf from "../../infra/net/ssrf.js";
import * as mediaStore from "../../media/store.js";
import { fetchWithSlackAuth, resolveSlackMedia, resolveSlackThreadHistory } from "./media.js";
// Store original fetch
const originalFetch = globalThis.fetch;
@@ -15,13 +17,9 @@ describe("fetchWithSlackAuth", () => {
afterEach(() => {
// Restore original fetch
globalThis.fetch = originalFetch;
vi.resetModules();
});
it("sends Authorization header on initial request with manual redirect", async () => {
// Import after mocking fetch
const { fetchWithSlackAuth } = await import("./media.js");
// Simulate direct 200 response (no redirect)
const mockResponse = new Response(Buffer.from("image data"), {
status: 200,
@@ -42,8 +40,6 @@ describe("fetchWithSlackAuth", () => {
});
it("rejects non-Slack hosts to avoid leaking tokens", async () => {
const { fetchWithSlackAuth } = await import("./media.js");
await expect(
fetchWithSlackAuth("https://example.com/test.jpg", "xoxb-test-token"),
).rejects.toThrow(/non-Slack host|non-Slack/i);
@@ -53,8 +49,6 @@ describe("fetchWithSlackAuth", () => {
});
it("follows redirects without Authorization header", async () => {
const { fetchWithSlackAuth } = await import("./media.js");
// First call: redirect response from Slack
const redirectResponse = new Response(null, {
status: 302,
@@ -89,8 +83,6 @@ describe("fetchWithSlackAuth", () => {
});
it("handles relative redirect URLs", async () => {
const { fetchWithSlackAuth } = await import("./media.js");
// Redirect with relative URL
const redirectResponse = new Response(null, {
status: 302,
@@ -113,8 +105,6 @@ describe("fetchWithSlackAuth", () => {
});
it("returns redirect response when no location header is provided", async () => {
const { fetchWithSlackAuth } = await import("./media.js");
// Redirect without location header
const redirectResponse = new Response(null, {
status: 302,
@@ -131,8 +121,6 @@ describe("fetchWithSlackAuth", () => {
});
it("returns 4xx/5xx responses directly without following", async () => {
const { fetchWithSlackAuth } = await import("./media.js");
const errorResponse = new Response("Not Found", {
status: 404,
});
@@ -146,8 +134,6 @@ describe("fetchWithSlackAuth", () => {
});
it("handles 301 permanent redirects", async () => {
const { fetchWithSlackAuth } = await import("./media.js");
const redirectResponse = new Response(null, {
status: 301,
headers: { location: "https://cdn.slack.com/new-url" },
@@ -185,20 +171,14 @@ describe("resolveSlackMedia", () => {
afterEach(() => {
globalThis.fetch = originalFetch;
vi.resetModules();
vi.restoreAllMocks();
});
it("prefers url_private_download over url_private", async () => {
// Mock the store module
vi.doMock("../../media/store.js", () => ({
saveMediaBuffer: vi.fn().mockResolvedValue({
path: "/tmp/test.jpg",
contentType: "image/jpeg",
}),
}));
const { resolveSlackMedia } = await import("./media.js");
vi.spyOn(mediaStore, "saveMediaBuffer").mockResolvedValue({
path: "/tmp/test.jpg",
contentType: "image/jpeg",
});
const mockResponse = new Response(Buffer.from("image data"), {
status: 200,
@@ -225,8 +205,6 @@ describe("resolveSlackMedia", () => {
});
it("returns null when download fails", async () => {
const { resolveSlackMedia } = await import("./media.js");
// Simulate a network error
mockFetch.mockRejectedValueOnce(new Error("Network error"));
@@ -240,8 +218,6 @@ describe("resolveSlackMedia", () => {
});
it("returns null when no files are provided", async () => {
const { resolveSlackMedia } = await import("./media.js");
const result = await resolveSlackMedia({
files: [],
token: "xoxb-test-token",
@@ -252,8 +228,6 @@ describe("resolveSlackMedia", () => {
});
it("skips files without url_private", async () => {
const { resolveSlackMedia } = await import("./media.js");
const result = await resolveSlackMedia({
files: [{ name: "test.jpg" }], // No url_private
token: "xoxb-test-token",
@@ -265,15 +239,10 @@ describe("resolveSlackMedia", () => {
});
it("falls through to next file when first file returns error", async () => {
// Mock the store module
vi.doMock("../../media/store.js", () => ({
saveMediaBuffer: vi.fn().mockResolvedValue({
path: "/tmp/test.jpg",
contentType: "image/jpeg",
}),
}));
const { resolveSlackMedia } = await import("./media.js");
vi.spyOn(mediaStore, "saveMediaBuffer").mockResolvedValue({
path: "/tmp/test.jpg",
contentType: "image/jpeg",
});
// First file: 404
const errorResponse = new Response("Not Found", { status: 404 });
@@ -301,7 +270,6 @@ describe("resolveSlackMedia", () => {
describe("resolveSlackThreadHistory", () => {
afterEach(() => {
vi.resetModules();
vi.restoreAllMocks();
});
@@ -324,7 +292,6 @@ describe("resolveSlackThreadHistory", () => {
})),
response_metadata: { next_cursor: "" },
});
const { resolveSlackThreadHistory } = await import("./media.js");
const client = {
conversations: { replies },
} as Parameters<typeof resolveSlackThreadHistory>[0]["client"];
@@ -375,7 +342,6 @@ describe("resolveSlackThreadHistory", () => {
],
response_metadata: { next_cursor: "" },
});
const { resolveSlackThreadHistory } = await import("./media.js");
const client = {
conversations: { replies },
} as Parameters<typeof resolveSlackThreadHistory>[0]["client"];
@@ -394,7 +360,6 @@ describe("resolveSlackThreadHistory", () => {
it("returns empty when limit is zero without calling Slack API", async () => {
const replies = vi.fn();
const { resolveSlackThreadHistory } = await import("./media.js");
const client = {
conversations: { replies },
} as Parameters<typeof resolveSlackThreadHistory>[0]["client"];
@@ -412,7 +377,6 @@ describe("resolveSlackThreadHistory", () => {
it("returns empty when Slack API throws", async () => {
const replies = vi.fn().mockRejectedValueOnce(new Error("slack down"));
const { resolveSlackThreadHistory } = await import("./media.js");
const client = {
conversations: { replies },
} as Parameters<typeof resolveSlackThreadHistory>[0]["client"];