import { describe, expect, test } from 'bun:test' import { join } from 'node:path' import type { AnimaConfig } from './config' /** * BACKWARD-COMPAT FREEZE TEST for `anima.config.ts`. * * Imports a FROZEN minimal config a real user could have written at an older * release (v0.5.0-era: only `network` set, every other field absent) and * asserts the CURRENT `defineConfig` resolves it to a fully-defaulted * AnimaConfig. This is the same decode `findAndLoadConfig` performs internally * (`(await import(path)).default`). If a future change makes a then-optional * field REQUIRED, or drops a default, importing the frozen fixture fails -> * CI red, instead of bricking the first user who upgrades with an old config. * * The fixture lives at test/fixtures/compat/anima-config-v0.5.0.fixture.ts and * is immutable. A newer config shape adds a NEW fixture file. (It is named * `*.fixture.ts` rather than `anima.config.ts` because `.gitignore` ignores the * literal `anima.config.ts`; the bytes are otherwise identical.) */ const FIXTURE = join( import.meta.dir, '../../../test/fixtures/compat/anima-config-v0.5.0.fixture.ts', ) describe('config backward-compat (frozen fixture)', () => { test('FROZEN v0.5.0-era minimal config resolves all required fields with defaults', async () => { const mod = (await import(FIXTURE)) as { default: AnimaConfig } const config = mod.default expect(config).toBeDefined() // The one field the user actually wrote. expect(config.network).toBe('0g-mainnet') // Every required field must coalesce to a default (the upgrade contract). expect(config.storage).toEqual({ network: '0g-mainnet' }) expect(config.identity).toEqual({ iNFT: null, operator: null, agent: null }) expect(config.brain).toEqual({ provider: null, model: null }) expect(config.plugins).toEqual(['onchain', 'comms', 'system']) expect(config.tools).toEqual({}) expect(config.imports).toEqual({ claudeCode: true }) }) test('FROZEN config: optional fields absent in the source still coalesce to defaults', async () => { const mod = (await import(FIXTURE)) as { default: AnimaConfig } const config = mod.default // None of these were in the fixture source; defineConfig must fill them. expect(config.operator).toBeNull() expect(config.subname).toBeNull() expect(config.approvals).toEqual({ mode: 'prompt', allowlist: [] }) expect(config.skills).toEqual({ disabled: [] }) expect(config.prompt).toEqual({ append: null }) expect(config.deployTarget).toBe('local') expect(config.sandbox).toEqual({ mode: 'none' }) }) })