test(renown): pin the migration's backfill and constraint statement ordering
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -134,6 +134,7 @@ export class CreateRenownAndReputation1791000000000 implements MigrationInterfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query('DROP INDEX "IDX_turn_in_definitions_key"');
|
||||||
await queryRunner.query('DROP TABLE "turn_in_definitions"');
|
await queryRunner.query('DROP TABLE "turn_in_definitions"');
|
||||||
|
|
||||||
await queryRunner.query(
|
await queryRunner.query(
|
||||||
|
|||||||
@@ -32,22 +32,29 @@ describe('CreateRenownAndReputation1791000000000', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('clamps existing level into the 1-15 Renown range before dropping it', async () => {
|
it('backfills renown from level BEFORE dropping the level column', async () => {
|
||||||
const up = await runUp();
|
const up = await runUp();
|
||||||
|
|
||||||
expect(up).toEqual(
|
const backfillIndex = up.findIndex((sql) => sql.includes('LEAST(GREATEST("level", 1), 15)'));
|
||||||
expect.arrayContaining([expect.stringContaining('LEAST(GREATEST("level", 1), 15)')]),
|
const dropLevelIndex = up.findIndex((sql) => sql.includes('DROP COLUMN "level"'));
|
||||||
);
|
|
||||||
|
expect(backfillIndex).toBeGreaterThanOrEqual(0);
|
||||||
|
expect(dropLevelIndex).toBeGreaterThanOrEqual(0);
|
||||||
|
// Reversing these two would silently discard every character's progression.
|
||||||
|
expect(backfillIndex).toBeLessThan(dropLevelIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('enforces the renown range at the database level', async () => {
|
it('adds the renown range constraint only AFTER the backfill has populated valid values', async () => {
|
||||||
const up = await runUp();
|
const up = await runUp();
|
||||||
|
|
||||||
expect(up).toEqual(
|
const backfillIndex = up.findIndex((sql) => sql.includes('LEAST(GREATEST("level", 1), 15)'));
|
||||||
expect.arrayContaining([
|
const constraintIndex = up.findIndex((sql) => sql.includes('CHK_characters_renown'));
|
||||||
expect.stringContaining('CHK_characters_renown'),
|
|
||||||
]),
|
expect(backfillIndex).toBeGreaterThanOrEqual(0);
|
||||||
);
|
expect(constraintIndex).toBeGreaterThanOrEqual(0);
|
||||||
|
// ADD CONSTRAINT validates the whole table; running it before the backfill
|
||||||
|
// would only pass by coincidence of the column DEFAULT being in range.
|
||||||
|
expect(backfillIndex).toBeLessThan(constraintIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('drops required_level from item_definitions', async () => {
|
it('drops required_level from item_definitions', async () => {
|
||||||
@@ -125,10 +132,15 @@ describe('CreateRenownAndReputation1791000000000', () => {
|
|||||||
expect.stringContaining('ALTER TABLE "characters" DROP COLUMN "renown"'),
|
expect.stringContaining('ALTER TABLE "characters" DROP COLUMN "renown"'),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
// The dropped turn_in_definitions table must be the very first statement
|
const turnInDropIndex = down.findIndex((sql) => sql.includes('DROP TABLE "turn_in_definitions"'));
|
||||||
// in down() -- it's the last thing up() created, and it has FK
|
const reputationFactionsDropIndex = down.findIndex((sql) =>
|
||||||
// dependencies on reputation_factions/item_definitions that must be
|
sql.includes('DROP TABLE "reputation_factions"'),
|
||||||
// gone before those tables can be touched.
|
);
|
||||||
expect(down[0]).toContain('DROP TABLE "turn_in_definitions"');
|
|
||||||
|
expect(turnInDropIndex).toBeGreaterThanOrEqual(0);
|
||||||
|
expect(reputationFactionsDropIndex).toBeGreaterThanOrEqual(0);
|
||||||
|
// turn_in_definitions has FK dependencies on reputation_factions and
|
||||||
|
// item_definitions that must be gone before those tables are touched.
|
||||||
|
expect(turnInDropIndex).toBeLessThan(reputationFactionsDropIndex);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user