From 93c8a8a72940ff51093ea01952185109c84c9b8f Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Fri, 15 May 2026 17:50:37 -0700 Subject: [PATCH] test: unit coverage for conductor-env-shim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactor lib/conductor-env-shim.ts to export promoteConductorEnv() so unit tests can manipulate env and call it directly (a bare side- effect IIFE on import isn't reachable from bun:test once cached). The on-import IIFE still runs — existing four-entry-point imports keep working unchanged. test/conductor-env-shim.test.ts covers all three branches: GSTACK_FOO present + FOO empty → promotion; FOO already set → no-overwrite; nothing in env → no-op. Co-Authored-By: Claude Opus 4.7 (1M context) --- lib/conductor-env-shim.ts | 10 ++++--- test/conductor-env-shim.test.ts | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 test/conductor-env-shim.test.ts diff --git a/lib/conductor-env-shim.ts b/lib/conductor-env-shim.ts index 7056525ec..f8804a1b9 100644 --- a/lib/conductor-env-shim.ts +++ b/lib/conductor-env-shim.ts @@ -7,8 +7,12 @@ * * Import this for its side effect: `import "../lib/conductor-env-shim";` */ -for (const key of ["ANTHROPIC_API_KEY", "OPENAI_API_KEY"] as const) { - if (!process.env[key] && process.env[`GSTACK_${key}`]) { - process.env[key] = process.env[`GSTACK_${key}`]; +export function promoteConductorEnv(): void { + for (const key of ["ANTHROPIC_API_KEY", "OPENAI_API_KEY"] as const) { + if (!process.env[key] && process.env[`GSTACK_${key}`]) { + process.env[key] = process.env[`GSTACK_${key}`]; + } } } + +promoteConductorEnv(); diff --git a/test/conductor-env-shim.test.ts b/test/conductor-env-shim.test.ts new file mode 100644 index 000000000..6435040a6 --- /dev/null +++ b/test/conductor-env-shim.test.ts @@ -0,0 +1,46 @@ +import { describe, test, expect, beforeEach, afterEach } from 'bun:test'; +import { promoteConductorEnv } from '../lib/conductor-env-shim'; + +describe('conductor-env-shim', () => { + const KEYS = ['ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'GSTACK_ANTHROPIC_API_KEY', 'GSTACK_OPENAI_API_KEY'] as const; + const saved: Record = {}; + + beforeEach(() => { + for (const k of KEYS) { + saved[k] = process.env[k]; + delete process.env[k]; + } + }); + + afterEach(() => { + for (const k of KEYS) { + if (saved[k] === undefined) delete process.env[k]; + else process.env[k] = saved[k]; + } + }); + + test('promotes GSTACK_ANTHROPIC_API_KEY to ANTHROPIC_API_KEY when canonical is empty', () => { + process.env.GSTACK_ANTHROPIC_API_KEY = 'sk-ant-test-123'; + promoteConductorEnv(); + expect(process.env.ANTHROPIC_API_KEY).toBe('sk-ant-test-123'); + }); + + test('promotes GSTACK_OPENAI_API_KEY to OPENAI_API_KEY when canonical is empty', () => { + process.env.GSTACK_OPENAI_API_KEY = 'sk-oai-test-456'; + promoteConductorEnv(); + expect(process.env.OPENAI_API_KEY).toBe('sk-oai-test-456'); + }); + + test('does not overwrite canonical when both canonical and GSTACK_-prefixed are set', () => { + process.env.ANTHROPIC_API_KEY = 'sk-ant-original'; + process.env.GSTACK_ANTHROPIC_API_KEY = 'sk-ant-prefixed'; + promoteConductorEnv(); + expect(process.env.ANTHROPIC_API_KEY).toBe('sk-ant-original'); + }); + + test('no-op when neither canonical nor GSTACK_-prefixed are set', () => { + promoteConductorEnv(); + expect(process.env.ANTHROPIC_API_KEY).toBeUndefined(); + expect(process.env.OPENAI_API_KEY).toBeUndefined(); + }); +});