mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 05:26:47 +00:00
724c88c201
A mechanical prettier --write over server/src, server/tests, server/scripts and shared/src with the workspaces' .prettierrc; nothing but layout and import order changes, and every file keeps the same set of imports. shared is formatted throughout and its format baseline is empty. The server baseline keeps the 35 files that Prettier would grow past their lint:size limit (they need a split first, which is not a formatting change), and the generated entity files stay as their generator writes them.
77 lines
3.2 KiB
TypeScript
77 lines
3.2 KiB
TypeScript
/**
|
|
* Boot migration: reservations.ingest_state.
|
|
*
|
|
* The column gates the two anonymous exports (ICS feed, shared trip) so an
|
|
* automated ingest can park a booking for review without publishing it. Every
|
|
* row that exists before the ALTER has to come out 'live', or the migration
|
|
* would empty a calendar subscription that works today.
|
|
*
|
|
* Ported off the legacy runner (Task 0 triage: PORT) onto the real
|
|
* `Migration20200101031900_reservations_an_automated_ingest_parked_for_review`:
|
|
* migrate to the step immediately before it, seed rows with raw SQL, apply
|
|
* just that one migration, assert. The replay case runs the migration class
|
|
* directly a second time (bypassing the Migrator's own "already applied, skip"
|
|
* bookkeeping) to prove the `addColumnIfMissing` guard is what the legacy
|
|
* test's schema_version rewind was really exercising.
|
|
*/
|
|
import { Migration20200101031900_reservations_an_automated_ingest_parked_for_review as TargetMigration } from '../../../src/db/migrations/Migration20200101031900_reservations_an_automated_ingest_parked_for_review';
|
|
import {
|
|
createMigrationOrm,
|
|
migrateTo,
|
|
pendingNames,
|
|
rawExec,
|
|
rawQuery,
|
|
runMigrationDirect,
|
|
} from '../../helpers/migration-step';
|
|
import type { MikroORM } from '@mikro-orm/sqlite';
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
|
|
const TARGET = 'Migration20200101031900_reservations_an_automated_ingest_parked_for_review';
|
|
|
|
async function ormWithSeededReservation(): Promise<MikroORM> {
|
|
const orm = await createMigrationOrm();
|
|
const names = await pendingNames(orm);
|
|
const idx = names.indexOf(TARGET);
|
|
expect(idx).toBeGreaterThan(0);
|
|
await migrateTo(orm, names[idx - 1]);
|
|
await rawExec(orm, "INSERT INTO users (id, username, email, password_hash) VALUES (1, 'u', 'u@example.test', 'x')");
|
|
await rawExec(orm, "INSERT INTO trips (id, user_id, title) VALUES (1, 1, 'T')");
|
|
await rawExec(orm, "INSERT INTO reservations (id, trip_id, title, type) VALUES (1, 1, 'Old Flight', 'flight')");
|
|
return orm;
|
|
}
|
|
|
|
describe('reservations ingest_state migration', () => {
|
|
it('MIGRATE-INGEST-001: every pre-existing row comes out live', async () => {
|
|
const orm = await ormWithSeededReservation();
|
|
try {
|
|
await migrateTo(orm, TARGET);
|
|
const rows = await rawQuery<{ ingest_state: string }>(orm, 'SELECT ingest_state FROM reservations WHERE id = 1');
|
|
expect(rows[0].ingest_state).toBe('live');
|
|
} finally {
|
|
await orm.close(true);
|
|
}
|
|
}, 30000);
|
|
|
|
it('MIGRATE-INGEST-002: running the migration twice is a no-op', async () => {
|
|
const orm = await ormWithSeededReservation();
|
|
try {
|
|
await migrateTo(orm, TARGET);
|
|
// Run the migration class directly a second time against a table that
|
|
// already has the column. Without the pragma_table_info guard the ALTER
|
|
// throws.
|
|
await runMigrationDirect(orm, TargetMigration);
|
|
|
|
const cols = await rawQuery(
|
|
orm,
|
|
"SELECT name FROM pragma_table_info('reservations') WHERE name = 'ingest_state'",
|
|
);
|
|
expect(cols).toHaveLength(1);
|
|
const rows = await rawQuery<{ ingest_state: string }>(orm, 'SELECT ingest_state FROM reservations WHERE id = 1');
|
|
expect(rows[0].ingest_state).toBe('live');
|
|
} finally {
|
|
await orm.close(true);
|
|
}
|
|
}, 30000);
|
|
});
|