import { describe, it, expect } from 'vitest'; import { mergeProviderConfigPatch, ProviderConfigPatchSchema, CoderProvidersFileSchema, type CoderProvidersFile, } from '../provider-config.js'; describe('ProviderConfigPatchSchema', () => { it('accepts a per-provider override patch', () => { const parsed = ProviderConfigPatchSchema.safeParse({ providers: { goose: { enabled: false } } }); expect(parsed.success).toBe(true); }); it('accepts a null value (delete-the-override sentinel)', () => { const parsed = ProviderConfigPatchSchema.safeParse({ providers: { goose: null } }); expect(parsed.success).toBe(true); }); it('defaults providers to {} on an empty body', () => { const parsed = ProviderConfigPatchSchema.safeParse({}); expect(parsed.success).toBe(true); if (parsed.success) expect(parsed.data.providers).toEqual({}); }); it('rejects a malformed override (wrong field type)', () => { const parsed = ProviderConfigPatchSchema.safeParse({ providers: { goose: { enabled: 'yes' } } }); expect(parsed.success).toBe(false); }); it('rejects a non-object providers map', () => { const parsed = ProviderConfigPatchSchema.safeParse({ providers: 123 }); expect(parsed.success).toBe(false); }); }); describe('mergeProviderConfigPatch', () => { const current: CoderProvidersFile = { providers: { goose: { enabled: true, label: 'Goose' }, opencode: { enabled: true }, }, }; it('replaces an existing override object wholesale (not deep-merge)', () => { const merged = mergeProviderConfigPatch(current, { providers: { goose: { enabled: false } } }); // Whole override replaced — the prior `label` is gone, only `enabled` remains. expect(merged.providers.goose).toEqual({ enabled: false }); }); it('adds a brand-new override id', () => { const merged = mergeProviderConfigPatch(current, { providers: { 'amp-acp': { extends: 'acp', label: 'Amp', command: ['amp-acp'] } }, }); expect(merged.providers['amp-acp']).toEqual({ extends: 'acp', label: 'Amp', command: ['amp-acp'] }); }); it('deletes an override when the value is null', () => { const merged = mergeProviderConfigPatch(current, { providers: { goose: null } }); expect(merged.providers.goose).toBeUndefined(); expect(Object.keys(merged.providers)).toEqual(['opencode']); }); it('leaves ids absent from the patch untouched', () => { const merged = mergeProviderConfigPatch(current, { providers: { goose: { enabled: false } } }); expect(merged.providers.opencode).toEqual({ enabled: true }); }); it('does not mutate the input config', () => { const snapshot = JSON.parse(JSON.stringify(current)); mergeProviderConfigPatch(current, { providers: { goose: null, opencode: { enabled: false } } }); expect(current).toEqual(snapshot); }); it('empty patch returns an equivalent config', () => { const merged = mergeProviderConfigPatch(current, { providers: {} }); expect(merged).toEqual(current); }); }); describe('CoderProvidersFileSchema (validate-before-save guard)', () => { it('accepts a clean merged config', () => { const merged = mergeProviderConfigPatch( { providers: {} }, { providers: { goose: { enabled: false } } }, ); expect(CoderProvidersFileSchema.safeParse(merged).success).toBe(true); }); it('rejects a config carrying an invalid override (never written)', () => { // A merged object that somehow holds a bad override must fail validation // so the PATCH route returns 422 and never calls save(). const invalid = { providers: { goose: { enabled: 'nope' } } }; expect(CoderProvidersFileSchema.safeParse(invalid).success).toBe(false); }); });