From 39f3b2babd43d65546f1f71388596d354047316d Mon Sep 17 00:00:00 2001 From: Kevin Codex Date: Mon, 6 Apr 2026 19:50:31 +0800 Subject: [PATCH] test: isolate latest main suite regressions (#427) --- src/utils/model/modelOptions.github.test.ts | 25 +++- src/utils/providerProfiles.test.ts | 137 ++++++++++++++------ 2 files changed, 122 insertions(+), 40 deletions(-) diff --git a/src/utils/model/modelOptions.github.test.ts b/src/utils/model/modelOptions.github.test.ts index 6a96aeaf..340e99c5 100644 --- a/src/utils/model/modelOptions.github.test.ts +++ b/src/utils/model/modelOptions.github.test.ts @@ -1,6 +1,6 @@ -import { afterEach, expect, test } from 'bun:test' +import { afterEach, expect, mock, test } from 'bun:test' -import { getModelOptions } from './modelOptions.js' +import { saveGlobalConfig } from '../config.js' const originalEnv = { CLAUDE_CODE_USE_GITHUB: process.env.CLAUDE_CODE_USE_GITHUB, @@ -25,9 +25,27 @@ afterEach(() => { process.env.OPENAI_BASE_URL = originalEnv.OPENAI_BASE_URL process.env.ANTHROPIC_CUSTOM_MODEL_OPTION = originalEnv.ANTHROPIC_CUSTOM_MODEL_OPTION + saveGlobalConfig(current => ({ + ...current, + additionalModelOptionsCache: [], + additionalModelOptionsCacheScope: undefined, + openaiAdditionalModelOptionsCache: [], + openaiAdditionalModelOptionsCacheByProfile: {}, + providerProfiles: [], + activeProviderProfileId: undefined, + })) }) -test('GitHub provider exposes only default + GitHub model in /model options', () => { +async function importFreshModelOptionsModule() { + mock.restore() + mock.module('./providers.js', () => ({ + getAPIProvider: () => 'github', + })) + const nonce = `${Date.now()}-${Math.random()}` + return import(`./modelOptions.js?ts=${nonce}`) +} + +test('GitHub provider exposes only default + GitHub model in /model options', async () => { process.env.CLAUDE_CODE_USE_GITHUB = '1' delete process.env.CLAUDE_CODE_USE_OPENAI delete process.env.CLAUDE_CODE_USE_GEMINI @@ -38,6 +56,7 @@ test('GitHub provider exposes only default + GitHub model in /model options', () process.env.OPENAI_MODEL = 'github:copilot' delete process.env.ANTHROPIC_CUSTOM_MODEL_OPTION + const { getModelOptions } = await importFreshModelOptionsModule() const options = getModelOptions(false) const nonDefault = options.filter(option => option.value !== null) diff --git a/src/utils/providerProfiles.test.ts b/src/utils/providerProfiles.test.ts index 95d7d459..40521960 100644 --- a/src/utils/providerProfiles.test.ts +++ b/src/utils/providerProfiles.test.ts @@ -1,15 +1,6 @@ -import { afterEach, describe, expect, test } from 'bun:test' +import { afterEach, describe, expect, mock, test } from 'bun:test' -import { saveGlobalConfig, type ProviderProfile } from './config.js' -import { getAPIProvider } from './model/providers.js' -import { - applyActiveProviderProfileFromConfig, - applyProviderProfileToProcessEnv, - deleteProviderProfile, - getProviderProfiles, - getProviderPresetDefaults, - persistActiveProviderProfileModel, -} from './providerProfiles.js' +import type { ProviderProfile } from './config.js' const originalEnv = { ...process.env } @@ -31,6 +22,34 @@ const RESTORED_KEYS = [ 'ANTHROPIC_API_KEY', ] as const +type MockConfigState = { + providerProfiles: ProviderProfile[] + activeProviderProfileId?: string + openaiAdditionalModelOptionsCache: unknown[] + openaiAdditionalModelOptionsCacheByProfile: Record + additionalModelOptionsCache?: unknown[] + additionalModelOptionsCacheScope?: string +} + +function createMockConfigState(): MockConfigState { + return { + providerProfiles: [], + activeProviderProfileId: undefined, + openaiAdditionalModelOptionsCache: [], + openaiAdditionalModelOptionsCacheByProfile: {}, + additionalModelOptionsCache: [], + additionalModelOptionsCacheScope: undefined, + } +} + +let mockConfigState: MockConfigState = createMockConfigState() + +function saveMockGlobalConfig( + updater: (current: MockConfigState) => MockConfigState, +): void { + mockConfigState = updater(mockConfigState) +} + afterEach(() => { for (const key of RESTORED_KEYS) { if (originalEnv[key] === undefined) { @@ -40,15 +59,30 @@ afterEach(() => { } } - saveGlobalConfig(current => ({ - ...current, - providerProfiles: [], - activeProviderProfileId: undefined, - openaiAdditionalModelOptionsCache: [], - openaiAdditionalModelOptionsCacheByProfile: {}, - })) + mock.restore() + mockConfigState = createMockConfigState() }) +async function importFreshProviderProfileModules() { + mock.restore() + mock.module('./config.js', () => ({ + getGlobalConfig: () => mockConfigState, + saveGlobalConfig: ( + updater: (current: MockConfigState) => MockConfigState, + ) => { + mockConfigState = updater(mockConfigState) + }, + })) + const nonce = `${Date.now()}-${Math.random()}` + const providers = await import(`./model/providers.js?ts=${nonce}`) + const providerProfiles = await import(`./providerProfiles.js?ts=${nonce}`) + + return { + ...providers, + ...providerProfiles, + } +} + function buildProfile(overrides: Partial = {}): ProviderProfile { return { id: 'provider_test', @@ -61,7 +95,9 @@ function buildProfile(overrides: Partial = {}): ProviderProfile } describe('applyProviderProfileToProcessEnv', () => { - test('openai profile clears competing gemini/github flags', () => { + test('openai profile clears competing gemini/github flags', async () => { + const { applyProviderProfileToProcessEnv, getAPIProvider } = + await importFreshProviderProfileModules() process.env.CLAUDE_CODE_USE_GEMINI = '1' process.env.CLAUDE_CODE_USE_GITHUB = '1' @@ -76,7 +112,9 @@ describe('applyProviderProfileToProcessEnv', () => { expect(getAPIProvider()).toBe('openai') }) - test('anthropic profile clears competing gemini/github flags', () => { + test('anthropic profile clears competing gemini/github flags', async () => { + const { applyProviderProfileToProcessEnv, getAPIProvider } = + await importFreshProviderProfileModules() process.env.CLAUDE_CODE_USE_GEMINI = '1' process.env.CLAUDE_CODE_USE_GITHUB = '1' @@ -96,7 +134,9 @@ describe('applyProviderProfileToProcessEnv', () => { }) describe('applyActiveProviderProfileFromConfig', () => { - test('does not override explicit startup provider selection', () => { + test('does not override explicit startup provider selection', async () => { + const { applyActiveProviderProfileFromConfig } = + await importFreshProviderProfileModules() process.env.CLAUDE_CODE_USE_OPENAI = '1' process.env.OPENAI_BASE_URL = 'http://localhost:11434/v1' process.env.OPENAI_MODEL = 'qwen2.5:3b' @@ -117,7 +157,9 @@ describe('applyActiveProviderProfileFromConfig', () => { expect(process.env.OPENAI_MODEL).toBe('qwen2.5:3b') }) - test('does not override explicit startup selection when profile marker is stale', () => { + test('does not override explicit startup selection when profile marker is stale', async () => { + const { applyActiveProviderProfileFromConfig } = + await importFreshProviderProfileModules() process.env.CLAUDE_CODE_PROVIDER_PROFILE_ENV_APPLIED = '1' process.env.CLAUDE_CODE_USE_OPENAI = '1' process.env.OPENAI_BASE_URL = 'http://localhost:11434/v1' @@ -140,7 +182,9 @@ describe('applyActiveProviderProfileFromConfig', () => { expect(process.env.OPENAI_MODEL).toBe('qwen2.5:3b') }) - test('re-applies active profile when profile-managed env drifts', () => { + test('re-applies active profile when profile-managed env drifts', async () => { + const { applyActiveProviderProfileFromConfig, applyProviderProfileToProcessEnv } = + await importFreshProviderProfileModules() applyProviderProfileToProcessEnv( buildProfile({ id: 'saved_openai', @@ -168,7 +212,9 @@ describe('applyActiveProviderProfileFromConfig', () => { expect(process.env.OPENAI_BASE_URL).toBe('http://192.168.33.108:11434/v1') }) - test('does not re-apply active profile when flags conflict with current provider', () => { + test('does not re-apply active profile when flags conflict with current provider', async () => { + const { applyActiveProviderProfileFromConfig, applyProviderProfileToProcessEnv } = + await importFreshProviderProfileModules() applyProviderProfileToProcessEnv( buildProfile({ id: 'saved_openai', @@ -196,7 +242,9 @@ describe('applyActiveProviderProfileFromConfig', () => { expect(process.env.OPENAI_MODEL).toBe('github:copilot') }) - test('applies active profile when no explicit provider is selected', () => { + test('applies active profile when no explicit provider is selected', async () => { + const { applyActiveProviderProfileFromConfig } = + await importFreshProviderProfileModules() delete process.env.CLAUDE_CODE_USE_OPENAI delete process.env.CLAUDE_CODE_USE_GEMINI delete process.env.CLAUDE_CODE_USE_GITHUB @@ -226,17 +274,22 @@ describe('applyActiveProviderProfileFromConfig', () => { }) describe('persistActiveProviderProfileModel', () => { - test('updates active profile model and current env for profile-managed sessions', () => { + test('updates active profile model and current env for profile-managed sessions', async () => { + const { + applyProviderProfileToProcessEnv, + getProviderProfiles, + persistActiveProviderProfileModel, + } = await importFreshProviderProfileModules() const activeProfile = buildProfile({ id: 'saved_openai', baseUrl: 'http://192.168.33.108:11434/v1', model: 'kimi-k2.5:cloud', }) - saveGlobalConfig(current => ({ - ...current, - providerProfiles: [activeProfile], - activeProviderProfileId: activeProfile.id, + saveMockGlobalConfig(current => ({ + ...current, + providerProfiles: [activeProfile], + activeProviderProfileId: activeProfile.id, })) applyProviderProfileToProcessEnv(activeProfile) @@ -255,13 +308,17 @@ describe('persistActiveProviderProfileModel', () => { expect(saved?.model).toBe('minimax-m2.5:cloud') }) - test('does not mutate process env when session is not profile-managed', () => { + test('does not mutate process env when session is not profile-managed', async () => { + const { + getProviderProfiles, + persistActiveProviderProfileModel, + } = await importFreshProviderProfileModules() const activeProfile = buildProfile({ id: 'saved_openai', model: 'kimi-k2.5:cloud', }) - saveGlobalConfig(current => ({ + saveMockGlobalConfig(current => ({ ...current, providerProfiles: [activeProfile], activeProviderProfileId: activeProfile.id, @@ -283,7 +340,8 @@ describe('persistActiveProviderProfileModel', () => { }) describe('getProviderPresetDefaults', () => { - test('ollama preset defaults to a local Ollama model', () => { + test('ollama preset defaults to a local Ollama model', async () => { + const { getProviderPresetDefaults } = await importFreshProviderProfileModules() delete process.env.OPENAI_MODEL const defaults = getProviderPresetDefaults('ollama') @@ -294,7 +352,11 @@ describe('getProviderPresetDefaults', () => { }) describe('deleteProviderProfile', () => { - test('deleting final profile clears provider env when active profile applied it', () => { + test('deleting final profile clears provider env when active profile applied it', async () => { + const { + applyProviderProfileToProcessEnv, + deleteProviderProfile, + } = await importFreshProviderProfileModules() applyProviderProfileToProcessEnv( buildProfile({ id: 'only_profile', @@ -304,7 +366,7 @@ describe('deleteProviderProfile', () => { }), ) - saveGlobalConfig(current => ({ + saveMockGlobalConfig(current => ({ ...current, providerProfiles: [buildProfile({ id: 'only_profile' })], activeProviderProfileId: 'only_profile', @@ -334,12 +396,13 @@ describe('deleteProviderProfile', () => { expect(process.env.ANTHROPIC_API_KEY).toBeUndefined() }) - test('deleting final profile preserves explicit startup provider env', () => { + test('deleting final profile preserves explicit startup provider env', async () => { + const { deleteProviderProfile } = await importFreshProviderProfileModules() process.env.CLAUDE_CODE_USE_OPENAI = '1' process.env.OPENAI_BASE_URL = 'http://localhost:11434/v1' process.env.OPENAI_MODEL = 'qwen2.5:3b' - saveGlobalConfig(current => ({ + saveMockGlobalConfig(current => ({ ...current, providerProfiles: [buildProfile({ id: 'only_profile' })], activeProviderProfileId: 'only_profile',