Migrate provider config tests to instance fixtures

Convert the first provider env/config/filtering tests to Effect-aware instance fixtures while keeping behavior unchanged and documenting neutral timing.
This commit is contained in:
Kit Langton 2026-05-18 13:22:59 -04:00 committed by GitHub
parent b039702e8c
commit 762850dfe5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 91 additions and 145 deletions

View File

@ -29,6 +29,12 @@ function rememberEnv(k: string) {
if (!originalEnv.has(k)) originalEnv.set(k, process.env[k]) if (!originalEnv.has(k)) originalEnv.set(k, process.env[k])
} }
const setProcessEnv = (k: string, v: string) =>
Effect.sync(() => {
rememberEnv(k)
process.env[k] = v
})
const set = (ctx: InstanceContext, k: string, v: string) => { const set = (ctx: InstanceContext, k: string, v: string) => {
rememberEnv(k) rememberEnv(k)
process.env[k] = v process.env[k] = v
@ -128,160 +134,99 @@ const alphaProviderConfig = {
}, },
} }
test("provider loaded from env variable", async () => { it.instance("provider loaded from env variable", () =>
await using tmp = await tmpdir({ Effect.gen(function* () {
init: async (dir) => { yield* setProcessEnv("ANTHROPIC_API_KEY", "test-api-key")
await Bun.write( const providers = yield* Provider.Service.use((provider) => provider.list())
path.join(dir, "opencode.json"), expect(providers[ProviderID.anthropic]).toBeDefined()
JSON.stringify({ // Provider should retain its connection source even if custom loaders
$schema: "https://opencode.ai/config.json", // merge additional options.
}), expect(providers[ProviderID.anthropic].source).toBe("env")
) expect(providers[ProviderID.anthropic].options.headers["anthropic-beta"]).toBeDefined()
}, }),
}) )
await withTestInstance({
directory: tmp.path,
fn: async (ctx) => {
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
const providers = await list(ctx)
expect(providers[ProviderID.anthropic]).toBeDefined()
// Provider should retain its connection source even if custom loaders
// merge additional options.
expect(providers[ProviderID.anthropic].source).toBe("env")
expect(providers[ProviderID.anthropic].options.headers["anthropic-beta"]).toBeDefined()
},
})
})
test("provider loaded from config with apiKey option", async () => { it.instance(
await using tmp = await tmpdir({ "provider loaded from config with apiKey option",
init: async (dir) => { Effect.gen(function* () {
await Bun.write( const providers = yield* Provider.Service.use((provider) => provider.list())
path.join(dir, "opencode.json"), expect(providers[ProviderID.anthropic]).toBeDefined()
JSON.stringify({ }),
$schema: "https://opencode.ai/config.json", {
provider: { config: {
anthropic: { provider: {
options: { anthropic: {
apiKey: "config-api-key", options: {
}, apiKey: "config-api-key",
},
}, },
}), },
) },
}, },
}) },
await withTestInstance({ )
directory: tmp.path,
fn: async (ctx) => {
const providers = await list(ctx)
expect(providers[ProviderID.anthropic]).toBeDefined()
},
})
})
test("disabled_providers excludes provider", async () => { it.instance(
await using tmp = await tmpdir({ "disabled_providers excludes provider",
init: async (dir) => { Effect.gen(function* () {
await Bun.write( yield* setProcessEnv("ANTHROPIC_API_KEY", "test-api-key")
path.join(dir, "opencode.json"), const providers = yield* Provider.Service.use((provider) => provider.list())
JSON.stringify({ expect(providers[ProviderID.anthropic]).toBeUndefined()
$schema: "https://opencode.ai/config.json", }),
disabled_providers: ["anthropic"], { config: { disabled_providers: ["anthropic"] } },
}), )
)
},
})
await withTestInstance({
directory: tmp.path,
fn: async (ctx) => {
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
const providers = await list(ctx)
expect(providers[ProviderID.anthropic]).toBeUndefined()
},
})
})
test("enabled_providers restricts to only listed providers", async () => { it.instance(
await using tmp = await tmpdir({ "enabled_providers restricts to only listed providers",
init: async (dir) => { Effect.gen(function* () {
await Bun.write( yield* setProcessEnv("ANTHROPIC_API_KEY", "test-api-key")
path.join(dir, "opencode.json"), yield* setProcessEnv("OPENAI_API_KEY", "test-openai-key")
JSON.stringify({ const providers = yield* Provider.Service.use((provider) => provider.list())
$schema: "https://opencode.ai/config.json", expect(providers[ProviderID.anthropic]).toBeDefined()
enabled_providers: ["anthropic"], expect(providers[ProviderID.openai]).toBeUndefined()
}), }),
) { config: { enabled_providers: ["anthropic"] } },
}, )
})
await withTestInstance({
directory: tmp.path,
fn: async (ctx) => {
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
await set(ctx, "OPENAI_API_KEY", "test-openai-key")
const providers = await list(ctx)
expect(providers[ProviderID.anthropic]).toBeDefined()
expect(providers[ProviderID.openai]).toBeUndefined()
},
})
})
test("model whitelist filters models for provider", async () => { it.instance(
await using tmp = await tmpdir({ "model whitelist filters models for provider",
init: async (dir) => { Effect.gen(function* () {
await Bun.write( yield* setProcessEnv("ANTHROPIC_API_KEY", "test-api-key")
path.join(dir, "opencode.json"), const providers = yield* Provider.Service.use((provider) => provider.list())
JSON.stringify({ expect(providers[ProviderID.anthropic]).toBeDefined()
$schema: "https://opencode.ai/config.json", const models = Object.keys(providers[ProviderID.anthropic].models)
provider: { expect(models).toContain("claude-sonnet-4-20250514")
anthropic: { expect(models.length).toBe(1)
whitelist: ["claude-sonnet-4-20250514"], }),
}, {
}, config: {
}), provider: {
) anthropic: {
whitelist: ["claude-sonnet-4-20250514"],
},
},
}, },
}) },
await withTestInstance({ )
directory: tmp.path,
fn: async (ctx) => {
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
const providers = await list(ctx)
expect(providers[ProviderID.anthropic]).toBeDefined()
const models = Object.keys(providers[ProviderID.anthropic].models)
expect(models).toContain("claude-sonnet-4-20250514")
expect(models.length).toBe(1)
},
})
})
test("model blacklist excludes specific models", async () => { it.instance(
await using tmp = await tmpdir({ "model blacklist excludes specific models",
init: async (dir) => { Effect.gen(function* () {
await Bun.write( yield* setProcessEnv("ANTHROPIC_API_KEY", "test-api-key")
path.join(dir, "opencode.json"), const providers = yield* Provider.Service.use((provider) => provider.list())
JSON.stringify({ expect(providers[ProviderID.anthropic]).toBeDefined()
$schema: "https://opencode.ai/config.json", const models = Object.keys(providers[ProviderID.anthropic].models)
provider: { expect(models).not.toContain("claude-sonnet-4-20250514")
anthropic: { }),
blacklist: ["claude-sonnet-4-20250514"], {
}, config: {
}, provider: {
}), anthropic: {
) blacklist: ["claude-sonnet-4-20250514"],
},
},
}, },
}) },
await withTestInstance({ )
directory: tmp.path,
fn: async (ctx) => {
await set(ctx, "ANTHROPIC_API_KEY", "test-api-key")
const providers = await list(ctx)
expect(providers[ProviderID.anthropic]).toBeDefined()
const models = Object.keys(providers[ProviderID.anthropic].models)
expect(models).not.toContain("claude-sonnet-4-20250514")
},
})
})
test("custom model alias via config", async () => { test("custom model alias via config", async () => {
await using tmp = await tmpdir({ await using tmp = await tmpdir({

View File

@ -68,6 +68,7 @@ Repeated setup work, long sleeps/timeouts, serial integration tests, filesystem/
| Session processor effect tests do not require repository state | Removed git setup from all processor-effect temp server fixtures | 12.500s | 9.230s | keep | Two targeted reruns passed after the change: 9.61s, 9.23s. | | Session processor effect tests do not require repository state | Removed git setup from all processor-effect temp server fixtures | 12.500s | 9.230s | keep | Two targeted reruns passed after the change: 9.61s, 9.23s. |
| HTTP listen PTY ticket tests restart the same listener topology twice | Folded directory-scoped ticket regression into the broader unsafe-ticket test | 7.051s | 6.170s | keep | Two targeted reruns passed after the change: 6.76s, 6.17s; still covers mint failure and successful same-directory upgrade. | | HTTP listen PTY ticket tests restart the same listener topology twice | Folded directory-scoped ticket regression into the broader unsafe-ticket test | 7.051s | 6.170s | keep | Two targeted reruns passed after the change: 6.76s, 6.17s; still covers mint failure and successful same-directory upgrade. |
| File watcher readiness can write before async native subscriptions are active | Retried short readiness writes and accepted symlink-realpath HEAD events | failed | 4.62s | keep | Three sequential focused watcher runs passed: 4.62s, 4.57s, 4.64s; full suite no longer failed in `watcher.test.ts`. | | File watcher readiness can write before async native subscriptions are active | Retried short readiness writes and accepted symlink-realpath HEAD events | failed | 4.62s | keep | Three sequential focused watcher runs passed: 4.62s, 4.57s, 4.64s; full suite no longer failed in `watcher.test.ts`. |
| First provider config/env/filtering block can use Effect-aware instance fixtures | Migrated six `tmpdir` + `withTestInstance` cases to `it.instance` | 6.06s | 6.07s | keep | Neutral timing, but removes manual config file writes and instance plumbing; use as the pattern for later provider slices. |
## Profiling Results ## Profiling Results