import { tap, expect } from '@git.zone/tstest/tapbundle'; import { SmartMigration, SmartMigrationError } from '../ts/index.js'; // Tests for the MigrationStepBuilder fluent chain. tap.test('step builder: registers a single step', async () => { const m = new SmartMigration({ targetVersion: '1.0.0', db: {} as any }); m.step('a').from('1.0.0').to('1.1.0').up(async () => {}); const steps = m.getRegisteredSteps(); expect(steps).toHaveLength(1); expect(steps[0].id).toEqual('a'); expect(steps[0].fromVersion).toEqual('1.0.0'); expect(steps[0].toVersion).toEqual('1.1.0'); expect(steps[0].isResumable).toBeFalse(); expect(steps[0].description).toBeUndefined(); }); tap.test('step builder: chains multiple steps via the parent', async () => { const m = new SmartMigration({ targetVersion: '2.0.0', db: {} as any }); m .step('a').from('1.0.0').to('1.1.0').up(async () => {}) .step('b').from('1.1.0').to('1.5.0').up(async () => {}) .step('c').from('1.5.0').to('2.0.0').up(async () => {}); expect(m.getRegisteredSteps()).toHaveLength(3); expect(m.getRegisteredSteps().map((s) => s.id)).toEqual(['a', 'b', 'c']); }); tap.test('step builder: stores description and resumable', async () => { const m = new SmartMigration({ targetVersion: '1.1.0', db: {} as any }); m .step('with-meta') .from('1.0.0') .to('1.1.0') .description('does important things') .resumable() .up(async () => {}); const step = m.getRegisteredSteps()[0]; expect(step.description).toEqual('does important things'); expect(step.isResumable).toBeTrue(); }); tap.test('step builder: requires .from() before .up()', async () => { const m = new SmartMigration({ targetVersion: '1.0.0', db: {} as any }); let caught: SmartMigrationError | undefined; try { (m.step('bad').to('1.1.0') as any).up(async () => {}); } catch (err) { caught = err as SmartMigrationError; } expect(caught).toBeInstanceOf(SmartMigrationError); expect(caught!.code).toEqual('STEP_MISSING_FROM'); }); tap.test('step builder: requires .to() before .up()', async () => { const m = new SmartMigration({ targetVersion: '1.0.0', db: {} as any }); let caught: SmartMigrationError | undefined; try { (m.step('bad').from('1.0.0') as any).up(async () => {}); } catch (err) { caught = err as SmartMigrationError; } expect(caught).toBeInstanceOf(SmartMigrationError); expect(caught!.code).toEqual('STEP_MISSING_TO'); }); tap.test('step builder: rejects non-function handler', async () => { const m = new SmartMigration({ targetVersion: '1.0.0', db: {} as any }); let caught: SmartMigrationError | undefined; try { (m.step('bad').from('1.0.0').to('1.1.0') as any).up('not-a-function'); } catch (err) { caught = err as SmartMigrationError; } expect(caught).toBeInstanceOf(SmartMigrationError); expect(caught!.code).toEqual('STEP_HANDLER_NOT_FUNCTION'); }); export default tap.start();