diff --git a/scripts/run-test-bucket.js b/scripts/run-test-bucket.js index 6d97a1ee..d6b29a7e 100644 --- a/scripts/run-test-bucket.js +++ b/scripts/run-test-bucket.js @@ -5,7 +5,7 @@ const path = require('node:path'); const { spawnSync } = require('node:child_process'); const rootDir = path.resolve(__dirname, '..'); -const candidateRoots = ['tests/unit', 'tests/integration', 'tests/npm']; +const candidateRoots = ['tests/unit', 'tests/integration', 'tests/npm', 'src']; // Add a `.ts` test to `slowTests` when ANY of these apply: // 1. It spawns a child process (CLI, bun test, node, gh, etc.). // 2. It binds a port, starts a server, or talks to localhost. diff --git a/src/cliproxy/__tests__/ai-provider-service-stable-id.test.ts b/src/cliproxy/__tests__/ai-provider-service-stable-id.test.ts index 77a0acae..e689b6f6 100644 --- a/src/cliproxy/__tests__/ai-provider-service-stable-id.test.ts +++ b/src/cliproxy/__tests__/ai-provider-service-stable-id.test.ts @@ -22,7 +22,7 @@ function readCliproxyConfig(homeDir: string): Record { } async function loadAiProviderService() { - return import(`../../../src/cliproxy/ai-providers/service?stable-id=${Date.now()}`); + return import(`../ai-providers/service?stable-id=${Date.now()}`); } describe('ai-provider service stable ids', () => { diff --git a/src/cliproxy/__tests__/model-config.test.js b/src/cliproxy/__tests__/model-config.test.js index edf0eda6..39c856d4 100644 --- a/src/cliproxy/__tests__/model-config.test.js +++ b/src/cliproxy/__tests__/model-config.test.js @@ -9,7 +9,7 @@ const path = require('path'); const os = require('os'); describe('Model Config', () => { - const modelConfig = require('../../../dist/cliproxy/model-config'); + const modelConfig = require('../../../dist/cliproxy/config/model-config'); const modelCatalog = require('../../../dist/cliproxy/model-catalog'); describe('hasUserSettings', () => { diff --git a/src/cliproxy/__tests__/session-tracker-port.test.js b/src/cliproxy/__tests__/session-tracker-port.test.js index e5a99d94..c5708d6c 100644 --- a/src/cliproxy/__tests__/session-tracker-port.test.js +++ b/src/cliproxy/__tests__/session-tracker-port.test.js @@ -30,7 +30,7 @@ const { getSessionLockPath, deleteSessionLockForPort, } = require('../../../dist/cliproxy/session-tracker'); -const { CLIPROXY_DEFAULT_PORT } = require('../../../dist/cliproxy/config-generator'); +const { CLIPROXY_DEFAULT_PORT } = require('../../../dist/cliproxy/config/config-generator'); const { setGlobalConfigDir } = require('../../../dist/utils/config-manager'); describe('Session Tracker Port-Specific', function () { diff --git a/src/cliproxy/accounts/__tests__/account-manager-discover.test.js b/src/cliproxy/accounts/__tests__/account-manager-discover.test.js index d98eaf79..31cc52a1 100644 --- a/src/cliproxy/accounts/__tests__/account-manager-discover.test.js +++ b/src/cliproxy/accounts/__tests__/account-manager-discover.test.js @@ -29,8 +29,8 @@ describe('Account Manager - discoverExistingAccounts', () => { process.env.CCS_HOME = testDir; // Clear cache and reload - must clear all modular submodules too - delete require.cache[require.resolve('../../../../dist/cliproxy/account-manager')]; - delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')]; + delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/account-manager')]; + delete require.cache[require.resolve('../../../../dist/cliproxy/config/config-generator')]; delete require.cache[require.resolve('../../../../dist/utils/config-manager')]; // Clear new modular structure (accounts/ and config/ submodules) delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/index')]; @@ -40,7 +40,7 @@ describe('Account Manager - discoverExistingAccounts', () => { delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/types')]; delete require.cache[require.resolve('../../../../dist/cliproxy/config/index')]; delete require.cache[require.resolve('../../../../dist/cliproxy/config/path-resolver')]; - accountManager = require('../../../../dist/cliproxy/account-manager'); + accountManager = require('../../../../dist/cliproxy/accounts/account-manager'); }); afterEach(() => { @@ -273,10 +273,10 @@ describe('Account Manager - discoverExistingAccounts', () => { }); // Reload module to clear in-memory cache (including all submodules) - delete require.cache[require.resolve('../../../../dist/cliproxy/account-manager')]; + delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/account-manager')]; delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/index')]; delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/registry')]; - accountManager = require('../../../../dist/cliproxy/account-manager'); + accountManager = require('../../../../dist/cliproxy/accounts/account-manager'); accountManager.discoverExistingAccounts(); const accounts = getAccountsFile(); @@ -357,10 +357,10 @@ describe('Account Manager - discoverExistingAccounts', () => { }); // Reload module to pick up pre-existing accounts.json (including all submodules) - delete require.cache[require.resolve('../../../../dist/cliproxy/account-manager')]; + delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/account-manager')]; delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/index')]; delete require.cache[require.resolve('../../../../dist/cliproxy/accounts/registry')]; - accountManager = require('../../../../dist/cliproxy/account-manager'); + accountManager = require('../../../../dist/cliproxy/accounts/account-manager'); accountManager.discoverExistingAccounts(); const accounts = getAccountsFile(); diff --git a/src/cliproxy/ai-providers/__tests__/codex-plan-compatibility-reconcile.test.ts b/src/cliproxy/ai-providers/__tests__/codex-plan-compatibility-reconcile.test.ts index 622bfdce..a72cacf4 100644 --- a/src/cliproxy/ai-providers/__tests__/codex-plan-compatibility-reconcile.test.ts +++ b/src/cliproxy/ai-providers/__tests__/codex-plan-compatibility-reconcile.test.ts @@ -39,7 +39,7 @@ function createCodexSettingsFixture(haikuModel: string = 'gpt-5.4-mini'): { } async function importCompatibilityModule(cacheTag: string) { - return import(`../../codex-plan-compatibility?${cacheTag}=${Date.now()}`); + return import(`../codex-plan-compatibility?${cacheTag}=${Date.now()}`); } const identity = (message: string) => message; diff --git a/src/cliproxy/ai-providers/__tests__/codex-reasoning-proxy.test.js b/src/cliproxy/ai-providers/__tests__/codex-reasoning-proxy.test.js index c77aa45b..c72ba662 100644 --- a/src/cliproxy/ai-providers/__tests__/codex-reasoning-proxy.test.js +++ b/src/cliproxy/ai-providers/__tests__/codex-reasoning-proxy.test.js @@ -4,7 +4,7 @@ const { buildCodexModelEffortMap, getEffortForModel, injectReasoningEffortIntoBody, -} = require('../../../../dist/cliproxy/codex-reasoning-proxy'); +} = require('../../../../dist/cliproxy/ai-providers/codex-reasoning-proxy'); describe('Codex Reasoning Proxy', () => { describe('buildCodexModelEffortMap', () => { diff --git a/src/cliproxy/ai-providers/__tests__/openai-compat-manager.test.js b/src/cliproxy/ai-providers/__tests__/openai-compat-manager.test.js index 2c854ae7..0b04c1dd 100644 --- a/src/cliproxy/ai-providers/__tests__/openai-compat-manager.test.js +++ b/src/cliproxy/ai-providers/__tests__/openai-compat-manager.test.js @@ -17,12 +17,14 @@ describe('openai-compat manager', () => { process.env.CCS_HOME = testDir; process.env.CCS_DIR = path.join(testDir, '.ccs'); - delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')]; - delete require.cache[require.resolve('../../../../dist/cliproxy/openai-compat-manager')]; + delete require.cache[require.resolve('../../../../dist/cliproxy/config/config-generator')]; + delete require.cache[ + require.resolve('../../../../dist/cliproxy/ai-providers/openai-compat-manager') + ]; delete require.cache[require.resolve('../../../../dist/utils/config-manager')]; - configGenerator = require('../../../../dist/cliproxy/config-generator'); - openAICompatManager = require('../../../../dist/cliproxy/openai-compat-manager'); + configGenerator = require('../../../../dist/cliproxy/config/config-generator'); + openAICompatManager = require('../../../../dist/cliproxy/ai-providers/openai-compat-manager'); }); afterEach(() => { diff --git a/src/cliproxy/auth/__tests__/auth-token-manager.test.js b/src/cliproxy/auth/__tests__/auth-token-manager.test.js index 8c30a462..711743f8 100644 --- a/src/cliproxy/auth/__tests__/auth-token-manager.test.js +++ b/src/cliproxy/auth/__tests__/auth-token-manager.test.js @@ -19,8 +19,8 @@ describe('Auth Token Manager', () => { beforeEach(() => { // Clear cache and reload - delete require.cache[require.resolve('../../../../dist/cliproxy/auth-token-manager')]; - const authTokenManager = require('../../../../dist/cliproxy/auth-token-manager'); + delete require.cache[require.resolve('../../../../dist/cliproxy/auth/auth-token-manager')]; + const authTokenManager = require('../../../../dist/cliproxy/auth/auth-token-manager'); generateSecureToken = authTokenManager.generateSecureToken; }); @@ -398,8 +398,8 @@ describe('Auth Token Manager', () => { let CCS_CONTROL_PANEL_SECRET; beforeEach(() => { - delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')]; - const configGenerator = require('../../../../dist/cliproxy/config-generator'); + delete require.cache[require.resolve('../../../../dist/cliproxy/config/config-generator')]; + const configGenerator = require('../../../../dist/cliproxy/config/config-generator'); CCS_INTERNAL_API_KEY = configGenerator.CCS_INTERNAL_API_KEY; CCS_CONTROL_PANEL_SECRET = configGenerator.CCS_CONTROL_PANEL_SECRET; }); diff --git a/src/cliproxy/auth/__tests__/gemini-refresh-delegation.test.ts b/src/cliproxy/auth/__tests__/gemini-refresh-delegation.test.ts index 7a89a416..f4ed977d 100644 --- a/src/cliproxy/auth/__tests__/gemini-refresh-delegation.test.ts +++ b/src/cliproxy/auth/__tests__/gemini-refresh-delegation.test.ts @@ -36,10 +36,10 @@ describe('Gemini refresh delegation', () => { it('treats Gemini as runtime-managed even when the local token lacks OAuth client metadata', async () => { const { getProviderAuthDir } = await import( - `../../../src/cliproxy/config-generator?gemini-delegation-config=${moduleVersion}` + `../../config/config-generator?gemini-delegation-config=${moduleVersion}` ); const { ensureTokenValid } = await import( - `../../../src/cliproxy/auth/token-manager?gemini-delegation-manager=${moduleVersion}` + `../token-manager?gemini-delegation-manager=${moduleVersion}` ); const authDir = getProviderAuthDir('gemini'); diff --git a/src/cliproxy/config/__tests__/backend-selection.test.js b/src/cliproxy/config/__tests__/backend-selection.test.js index 50e5f2df..5c547984 100644 --- a/src/cliproxy/config/__tests__/backend-selection.test.js +++ b/src/cliproxy/config/__tests__/backend-selection.test.js @@ -6,7 +6,7 @@ const assert = require('assert'); describe('Backend Selection', () => { - const platformDetector = require('../../../../dist/cliproxy/platform-detector'); + const platformDetector = require('../../../../dist/cliproxy/binary/platform-detector'); const types = require('../../../../dist/cliproxy/types'); describe('BACKEND_CONFIG', () => { diff --git a/src/cliproxy/config/__tests__/config-generator-port.test.js b/src/cliproxy/config/__tests__/config-generator-port.test.js index 7c19ffce..e8ccd4e2 100644 --- a/src/cliproxy/config/__tests__/config-generator-port.test.js +++ b/src/cliproxy/config/__tests__/config-generator-port.test.js @@ -26,7 +26,7 @@ const { deleteConfigForPort, deleteConfig, CLIPROXY_DEFAULT_PORT, -} = require('../../../../dist/cliproxy/config-generator'); +} = require('../../../../dist/cliproxy/config/config-generator'); describe('Config Generator Port', function () { let cliproxyDir; diff --git a/src/cliproxy/config/__tests__/config-generator.test.js b/src/cliproxy/config/__tests__/config-generator.test.js index 15d9bc37..9441d7ad 100644 --- a/src/cliproxy/config/__tests__/config-generator.test.js +++ b/src/cliproxy/config/__tests__/config-generator.test.js @@ -15,7 +15,7 @@ describe('Config Generator', () => { beforeEach(() => { // Clear the require cache to reload module with fresh mocks - delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')]; + delete require.cache[require.resolve('../../../../dist/cliproxy/config/config-generator')]; // Set up a temporary test directory as CCS_HOME mockCcsDir = '/test/home/.ccs'; @@ -174,8 +174,8 @@ describe('Config Generator', () => { beforeEach(() => { // Clear cache and reload module - delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')]; - const configGenerator = require('../../../../dist/cliproxy/config-generator'); + delete require.cache[require.resolve('../../../../dist/cliproxy/config/config-generator')]; + const configGenerator = require('../../../../dist/cliproxy/config/config-generator'); parseUserApiKeys = configGenerator.parseUserApiKeys; }); @@ -374,9 +374,9 @@ auth-dir: "/test" process.env.CCS_HOME = testDir; // Clear cache and reload module - delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')]; + delete require.cache[require.resolve('../../../../dist/cliproxy/config/config-generator')]; delete require.cache[require.resolve('../../../../dist/utils/config-manager')]; - const configGenerator = require('../../../../dist/cliproxy/config-generator'); + const configGenerator = require('../../../../dist/cliproxy/config/config-generator'); regenerateConfig = configGenerator.regenerateConfig; getCliproxyConfigPath = configGenerator.getCliproxyConfigPath; }); @@ -599,9 +599,9 @@ auth-dir: "${cliproxyDir.replace(/\\/g, '/')}/auth" originalCcsHome = process.env.CCS_HOME; process.env.CCS_HOME = testDir; - delete require.cache[require.resolve('../../../../dist/cliproxy/config-generator')]; + delete require.cache[require.resolve('../../../../dist/cliproxy/config/config-generator')]; delete require.cache[require.resolve('../../../../dist/utils/config-manager')]; - const configGenerator = require('../../../../dist/cliproxy/config-generator'); + const configGenerator = require('../../../../dist/cliproxy/config/config-generator'); regenerateConfig = configGenerator.regenerateConfig; }); diff --git a/src/cliproxy/executor/__tests__/variant-port-allocation.test.js b/src/cliproxy/executor/__tests__/variant-port-allocation.test.js index 242f8ff9..7b338d77 100644 --- a/src/cliproxy/executor/__tests__/variant-port-allocation.test.js +++ b/src/cliproxy/executor/__tests__/variant-port-allocation.test.js @@ -25,7 +25,7 @@ const { saveVariantLegacy, removeVariantFromLegacyConfig, } = require('../../../../dist/cliproxy/services/variant-config-adapter'); -const { CLIPROXY_DEFAULT_PORT } = require('../../../../dist/cliproxy/config-generator'); +const { CLIPROXY_DEFAULT_PORT } = require('../../../../dist/cliproxy/config/config-generator'); describe('Variant Port Allocation', function () { let configPath; diff --git a/src/cliproxy/executor/__tests__/variant-port-edge-cases.test.js b/src/cliproxy/executor/__tests__/variant-port-edge-cases.test.js index 63b691ef..ae78f623 100644 --- a/src/cliproxy/executor/__tests__/variant-port-edge-cases.test.js +++ b/src/cliproxy/executor/__tests__/variant-port-edge-cases.test.js @@ -38,7 +38,7 @@ const { deleteConfigForPort, configExists, generateConfig, -} = require('../../../../dist/cliproxy/config-generator'); +} = require('../../../../dist/cliproxy/config/config-generator'); describe('Variant Port Edge Cases', function () { let configPath; diff --git a/src/cliproxy/executor/__tests__/variant-port-integration.test.js b/src/cliproxy/executor/__tests__/variant-port-integration.test.js index 4936f971..9d7742c4 100644 --- a/src/cliproxy/executor/__tests__/variant-port-integration.test.js +++ b/src/cliproxy/executor/__tests__/variant-port-integration.test.js @@ -43,7 +43,7 @@ const { deleteConfigForPort, getConfigPathForPort, CLIPROXY_DEFAULT_PORT, -} = require('../../../../dist/cliproxy/config-generator'); +} = require('../../../../dist/cliproxy/config/config-generator'); describe('PR #184: Variant Port Isolation Integration', function () { let configPath; diff --git a/src/cliproxy/proxy/__tests__/proxy-config-resolver.test.js b/src/cliproxy/proxy/__tests__/proxy-config-resolver.test.js index 8eede5c1..8c384651 100644 --- a/src/cliproxy/proxy/__tests__/proxy-config-resolver.test.js +++ b/src/cliproxy/proxy/__tests__/proxy-config-resolver.test.js @@ -11,7 +11,7 @@ const { hasProxyFlags, PROXY_CLI_FLAGS, PROXY_ENV_VARS, -} = require('../../../../dist/cliproxy/proxy-config-resolver'); +} = require('../../../../dist/cliproxy/proxy/proxy-config-resolver'); describe('proxy-config-resolver', () => { describe('PROXY_CLI_FLAGS', () => { diff --git a/src/cliproxy/quota/__tests__/quota-fetcher-antigravity-failure.test.ts b/src/cliproxy/quota/__tests__/quota-fetcher-antigravity-failure.test.ts index 0cf2c4b1..ef60b0e7 100644 --- a/src/cliproxy/quota/__tests__/quota-fetcher-antigravity-failure.test.ts +++ b/src/cliproxy/quota/__tests__/quota-fetcher-antigravity-failure.test.ts @@ -31,8 +31,10 @@ describe('Antigravity quota failure metadata', () => { it('preserves entitlement evidence when project lookup fails before quota fetch', async () => { const moduleId = Date.now() + Math.random(); - const { fetchAccountQuota } = await import(`../../quota-fetcher?agy-early=${moduleId}`); - const { getProviderAuthDir } = await import(`../../config-generator?agy-config=${moduleId}`); + const { fetchAccountQuota } = await import(`../quota-fetcher?agy-early=${moduleId}`); + const { getProviderAuthDir } = await import( + `../../config/config-generator?agy-config=${moduleId}` + ); const fs = await import('node:fs'); const os = await import('node:os'); const path = await import('node:path'); @@ -83,10 +85,10 @@ describe('Antigravity quota failure metadata', () => { it('attaches entitlement evidence when project lookup returns an invalid 2xx payload', async () => { const moduleId = Date.now() + Math.random(); - const { fetchAccountQuota } = await import( - `../../quota-fetcher?agy-invalid-project=${moduleId}` + const { fetchAccountQuota } = await import(`../quota-fetcher?agy-invalid-project=${moduleId}`); + const { getProviderAuthDir } = await import( + `../../config/config-generator?agy-config=${moduleId}` ); - const { getProviderAuthDir } = await import(`../../config-generator?agy-config=${moduleId}`); const fs = await import('node:fs'); const os = await import('node:os'); const path = await import('node:path'); @@ -137,10 +139,10 @@ describe('Antigravity quota failure metadata', () => { it('preserves live tier evidence when quota fetch fails after a successful project lookup', async () => { const moduleId = Date.now() + Math.random(); - const { fetchAccountQuota } = await import( - `../../quota-fetcher?agy-invalid-models=${moduleId}` + const { fetchAccountQuota } = await import(`../quota-fetcher?agy-invalid-models=${moduleId}`); + const { getProviderAuthDir } = await import( + `../../config/config-generator?agy-config=${moduleId}` ); - const { getProviderAuthDir } = await import(`../../config-generator?agy-config=${moduleId}`); const fs = await import('node:fs'); const os = await import('node:os'); const path = await import('node:path'); diff --git a/src/cliproxy/quota/__tests__/quota-fetcher-gemini-cli.test.ts b/src/cliproxy/quota/__tests__/quota-fetcher-gemini-cli.test.ts index 34c4b32e..74c5f830 100644 --- a/src/cliproxy/quota/__tests__/quota-fetcher-gemini-cli.test.ts +++ b/src/cliproxy/quota/__tests__/quota-fetcher-gemini-cli.test.ts @@ -8,7 +8,7 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; import { afterEach, beforeEach, describe, expect, it } from 'bun:test'; -import { getCapturedFetchRequests, mockFetch, restoreFetch } from '../../../../tests/unit/mocks'; +import { getCapturedFetchRequests, mockFetch, restoreFetch } from '../../../../tests/mocks'; describe('Gemini CLI Quota Fetcher', () => { const GEMINI_QUOTA_URL = 'https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota'; diff --git a/src/cliproxy/services/__tests__/remote-token-uploader.test.ts b/src/cliproxy/services/__tests__/remote-token-uploader.test.ts index f9abacc3..f33fd8b1 100644 --- a/src/cliproxy/services/__tests__/remote-token-uploader.test.ts +++ b/src/cliproxy/services/__tests__/remote-token-uploader.test.ts @@ -8,7 +8,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'bun:test'; import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; -import { mockFetch, restoreFetch, getCapturedFetchRequests } from '../../../../tests/unit/mocks'; +import { mockFetch, restoreFetch, getCapturedFetchRequests } from '../../../../tests/mocks'; describe('remote-token-uploader', () => { let tempDir: string; diff --git a/tests/unit/scripts/run-test-bucket.test.js b/tests/unit/scripts/run-test-bucket.test.js index 0e1618cd..540fa1c7 100644 --- a/tests/unit/scripts/run-test-bucket.test.js +++ b/tests/unit/scripts/run-test-bucket.test.js @@ -32,6 +32,12 @@ describe('run-test-bucket', () => { expect(bucket.shouldForceSlow('tests/npm/cli.test.js')).toBe(true); }); + test('discovers colocated backend tests under src', () => { + const discovered = bucket.getDiscoveredTests(); + + expect(discovered).toContain('src/cliproxy/types/__tests__/types-backward-compat.test.ts'); + }); + test('keeps dist-independent javascript tests in the fast bucket', () => { expect(bucket.shouldForceSlow('tests/unit/flag-parsing-simple.test.js')).toBe(false); });