import { tap, expect } from '@git.zone/tstest/tapbundle'; import { makeTestDb } from './helpers/services.js'; import type * as smartdata from '@push.rocks/smartdata'; import { SmartMigration } from '../ts/index.js'; // Shared db across the file. Each test uses a unique ledgerName for isolation. // Note: the fresh-install detector checks for any non-reserved collection, so // tests that explicitly create user data must clean it up after themselves // (or other tests would no longer see "fresh"). For simplicity, the // not-fresh test runs LAST and we don't bother cleaning up after it. let db: smartdata.SmartdataDb; let cleanup: () => Promise; tap.test('setup: connect shared db', async () => { const r = await makeTestDb('freshinstall'); db = r.db; cleanup = r.cleanup; }); tap.test('freshInstall: jumps to freshInstallVersion when DB is empty', async () => { // Database is empty (only the SmartdataEasyStore collection may exist // from previous tests' ledgers, which is whitelisted by isFreshInstall()). const m = new SmartMigration({ targetVersion: '5.0.0', db, ledgerName: 'jump', freshInstallVersion: '5.0.0', }); let stepCalled = false; m .step('a').from('1.0.0').to('2.0.0').up(async () => { stepCalled = true; }) .step('b').from('2.0.0').to('5.0.0').up(async () => { stepCalled = true; }); const r = await m.run(); expect(stepCalled).toBeFalse(); expect(r.currentVersionAfter).toEqual('5.0.0'); expect(r.wasFreshInstall).toBeTrue(); expect(r.stepsApplied).toHaveLength(0); }); tap.test('freshInstall: without freshInstallVersion, starts from earliest step', async () => { // Even with freshInstallVersion unset, the db is still empty of user // collections, so the runner should start from the first step's `from` // version and run all steps in order. const m = new SmartMigration({ targetVersion: '2.0.0', db, ledgerName: 'no_freshversion' }); const log: string[] = []; m .step('a').from('1.0.0').to('1.5.0').up(async () => { log.push('a'); }) .step('b').from('1.5.0').to('2.0.0').up(async () => { log.push('b'); }); const r = await m.run(); expect(log).toEqual(['a', 'b']); expect(r.currentVersionAfter).toEqual('2.0.0'); }); tap.test('freshInstall: runs steps when DB has user collections (not fresh)', async () => { // Pre-seed the DB with a user collection so isFreshInstall() returns false. await db.mongoDb.collection('users_pre').insertOne({ name: 'preexisting' }); const m = new SmartMigration({ targetVersion: '2.0.0', db, ledgerName: 'not_fresh', freshInstallVersion: '2.0.0', }); let aCalled = false; m.step('a').from('1.0.0').to('2.0.0').up(async () => { aCalled = true; }); const r = await m.run(); expect(aCalled).toBeTrue(); expect(r.wasFreshInstall).toBeFalse(); expect(r.currentVersionAfter).toEqual('2.0.0'); }); tap.test('cleanup: close shared db', async () => { await cleanup(); }); export default tap.start();