Skip to content

Commit 7b7cfc5

Browse files
committed
🤖 Fix Jest integration tests: remove preloading, optimize tokenizer
- Removed AI SDK provider preloading (no longer necessary, tests are stable) - Moved tokenizer loading from per-test (setupWorkspace) to beforeAll hook - Tokenizer takes 14s to load, was timing out 15s tests - Now loads once per test suite instead of once per test - Reverted createModel() back to simple ESM imports (Jest issue was in preload, not here) Generated with `cmux`
1 parent 4f282fe commit 7b7cfc5

File tree

3 files changed

+16
-42
lines changed

3 files changed

+16
-42
lines changed

src/services/aiService.ts

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -97,20 +97,12 @@ if (typeof globalFetchWithExtras.certificate === "function") {
9797
* In production, providers are lazy-loaded on first use to optimize startup time.
9898
* In tests, we preload them once during setup to ensure reliable concurrent execution.
9999
*/
100+
// eslint-disable-next-line @typescript-eslint/require-await
100101
export async function preloadAISDKProviders(): Promise<void> {
101-
// In Jest, skip preloading to avoid ESM import constraints; model code will lazy-load as needed
102-
if (process.env.JEST_WORKER_ID) return;
103-
// Prefer CJS require first; fall back to ESM if not available
104-
try {
105-
// eslint-disable-next-line @typescript-eslint/no-var-requires
106-
require("@ai-sdk/anthropic");
107-
// eslint-disable-next-line @typescript-eslint/no-var-requires
108-
require("@ai-sdk/openai");
109-
return;
110-
} catch {
111-
// Fallback for ESM-only environments
112-
await Promise.all([import("@ai-sdk/anthropic"), import("@ai-sdk/openai")]);
113-
}
102+
// No-op: Providers are lazy-loaded in createModel().
103+
// Preloading was previously used to avoid race conditions in concurrent tests,
104+
// but Jest concurrency has been stabilized elsewhere and this is no longer necessary.
105+
return;
114106
}
115107

116108
export class AIService extends EventEmitter {
@@ -263,17 +255,8 @@ export class AIService extends EventEmitter {
263255
? { "anthropic-beta": "context-1m-2025-08-07" }
264256
: existingHeaders;
265257

266-
// Lazy-load Anthropic provider to reduce startup time (CJS first for Jest)
267-
let createAnthropic: typeof import("@ai-sdk/anthropic").createAnthropic;
268-
try {
269-
// eslint-disable-next-line @typescript-eslint/no-var-requires
270-
({ createAnthropic } =
271-
require("@ai-sdk/anthropic") as typeof import("@ai-sdk/anthropic"));
272-
} catch {
273-
({ createAnthropic } = (await import(
274-
"@ai-sdk/anthropic"
275-
)) as typeof import("@ai-sdk/anthropic"));
276-
}
258+
// Lazy-load Anthropic provider to reduce startup time
259+
const { createAnthropic } = await import("@ai-sdk/anthropic");
277260
const provider = createAnthropic({ ...providerConfig, headers });
278261
return Ok(provider(modelId));
279262
}
@@ -364,14 +347,8 @@ export class AIService extends EventEmitter {
364347
: {}
365348
);
366349

367-
// Lazy-load OpenAI provider to reduce startup time (CJS first for Jest)
368-
let createOpenAI: typeof import("@ai-sdk/openai").createOpenAI;
369-
try {
370-
// eslint-disable-next-line @typescript-eslint/no-var-requires
371-
({ createOpenAI } = require("@ai-sdk/openai") as typeof import("@ai-sdk/openai"));
372-
} catch {
373-
({ createOpenAI } = (await import("@ai-sdk/openai")) as typeof import("@ai-sdk/openai"));
374-
}
350+
// Lazy-load OpenAI provider to reduce startup time
351+
const { createOpenAI } = await import("@ai-sdk/openai");
375352
const provider = createOpenAI({
376353
...providerConfig,
377354
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment

tests/ipcMain/sendMessage.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ describeIntegration("IpcMain sendMessage integration tests", () => {
4848
if (process.env.CI && typeof jest !== "undefined" && jest.retryTimes) {
4949
jest.retryTimes(3, { logErrorsBeforeRetry: true });
5050
}
51+
52+
// Load tokenizer modules once before all tests (takes ~14s)
53+
// This ensures accurate token counts for API calls without timing out individual tests
54+
beforeAll(async () => {
55+
const { loadTokenizerModules } = await import("../../src/utils/main/tokenizer");
56+
await loadTokenizerModules();
57+
}, 30000); // 30s timeout for tokenizer loading
5158
// Run tests for each provider concurrently
5259
describe.each(PROVIDER_CONFIGS)("%s:%s provider tests", (provider, model) => {
5360
test.concurrent(

tests/ipcMain/setup.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import { IpcMain } from "../../src/services/ipcMain";
99
import { IPC_CHANNELS } from "../../src/constants/ipc-constants";
1010
import { generateBranchName, createWorkspace } from "./helpers";
1111
import { shouldRunIntegrationTests, validateApiKeys, getApiKey } from "../testUtils";
12-
import { loadTokenizerModules } from "../../src/utils/main/tokenizer";
13-
import { preloadAISDKProviders } from "../../src/services/aiService";
1412

1513
export interface TestEnvironment {
1614
config: Config;
@@ -151,14 +149,6 @@ export async function setupWorkspace(
151149
}> {
152150
const { createTempGitRepo, cleanupTempGitRepo } = await import("./helpers");
153151

154-
// Preload tokenizer modules to ensure accurate token counts for API calls
155-
// Without this, tests would use /4 approximation which can cause API errors
156-
await loadTokenizerModules();
157-
158-
// Preload AI SDK providers to avoid race conditions with dynamic imports
159-
// in concurrent test environments
160-
await preloadAISDKProviders();
161-
162152
// Create dedicated temp git repo for this test
163153
const tempGitRepo = await createTempGitRepo();
164154

0 commit comments

Comments
 (0)