Files
stack/apps/gateway/src/database/database.module.1392.spec.ts
T
2026-08-24 23:11:50 +00:00

72 lines
2.6 KiB
TypeScript

import { describe, it, expect, vi } from 'vitest';
// The module under test imports @mosaicstack/db at module scope; we replace only the
// pieces DatabaseModule uses (partial mock — the real module also exports the
// schema the storage adapter's import chain needs) so the test pins the #1392
// contract (refuse to start on an incomplete schema) without a live database.
vi.mock('@mosaicstack/db', async (importOriginal) => {
const actual: object = await importOriginal();
return {
...actual,
createDb: vi.fn(),
createPgliteDb: vi.fn(),
getMigrationStatus: vi.fn(),
runPgliteMigrations: vi.fn(),
};
});
import { DatabaseModule } from './database.module.js';
import { getMigrationStatus } from '@mosaicstack/db';
import type { DbHandle } from '@mosaicstack/db';
import type { StorageAdapter } from '@mosaicstack/storage';
import type { MosaicConfig } from '@mosaicstack/config';
function makeModule(storageType: 'postgres' | 'pglite', tier: string) {
const storageAdapter = {
name: storageType,
migrate: vi.fn(),
close: vi.fn(),
} as unknown as StorageAdapter;
const handle = { close: vi.fn() } as unknown as DbHandle;
const config = {
tier,
storage: { type: storageType, url: 'postgresql://x' },
} as unknown as MosaicConfig;
return {
mod: new DatabaseModule(handle, storageAdapter, config),
storageAdapter,
};
}
describe('DatabaseModule.onModuleInit — #1392 schema verification', () => {
it('refuses to start when the postgres schema is incomplete', async () => {
const { mod, storageAdapter } = makeModule('postgres', 'standalone');
vi.mocked(getMigrationStatus).mockResolvedValue({
appliedCount: 15,
expectedCount: 17,
expectedLastTag: '0016_salty_morlocks',
complete: false,
});
await expect(mod.onModuleInit()).rejects.toThrow('Database schema incomplete: 15/17');
expect(storageAdapter.migrate).toHaveBeenCalled(); // migrations attempted first
});
it('starts normally when the schema is complete', async () => {
const { mod } = makeModule('postgres', 'standalone');
vi.mocked(getMigrationStatus).mockResolvedValue({
appliedCount: 17,
expectedCount: 17,
expectedLastTag: '0016_salty_morlocks',
complete: true,
});
await expect(mod.onModuleInit()).resolves.toBeUndefined();
});
it('does not verify postgres status for the local tier (PGlite migrates itself)', async () => {
const { mod } = makeModule('pglite', 'local');
vi.mocked(getMigrationStatus).mockClear();
await expect(mod.onModuleInit()).resolves.toBeUndefined();
expect(getMigrationStatus).not.toHaveBeenCalled();
});
});