feat(combat): add combat domain enums, entities, and encounter consumption field
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import 'reflect-metadata';
|
||||
import { getMetadataArgsStorage } from 'typeorm';
|
||||
import { Combat } from '../../combat/entities/combat.entity';
|
||||
import { CombatEvent } from '../../combat/entities/combat-event.entity';
|
||||
import { HuntEncounter } from '../../hunting/entities/hunt-encounter.entity';
|
||||
|
||||
describe('combat system schema', () => {
|
||||
it('maps Combat and CombatEvent relations with the documented onDelete behavior', () => {
|
||||
const metadata = getMetadataArgsStorage();
|
||||
|
||||
const relations = metadata.relations.filter(
|
||||
(relation) => relation.target === Combat || relation.target === CombatEvent,
|
||||
);
|
||||
|
||||
expect(
|
||||
relations.map((relation) => ({
|
||||
onDelete: relation.options.onDelete,
|
||||
propertyName: relation.propertyName,
|
||||
target: relation.target,
|
||||
})),
|
||||
).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'character', target: Combat }),
|
||||
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'huntEncounter', target: Combat }),
|
||||
expect.objectContaining({ onDelete: 'RESTRICT', propertyName: 'monster', target: Combat }),
|
||||
expect.objectContaining({ onDelete: 'CASCADE', propertyName: 'combat', target: CombatEvent }),
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('enforces one combat per hunt encounter via a unique index', () => {
|
||||
const metadata = getMetadataArgsStorage();
|
||||
const index = metadata.indices.find(
|
||||
(candidate) => candidate.target === Combat && candidate.columns?.includes('huntEncounterId'),
|
||||
);
|
||||
|
||||
expect(index).toBeDefined();
|
||||
const indexMetadata = index as typeof index & { options?: { unique?: boolean }; unique?: boolean };
|
||||
expect(indexMetadata?.options?.unique ?? indexMetadata?.unique).toBe(true);
|
||||
});
|
||||
|
||||
it('enforces ordered, unique event sequencing per combat', () => {
|
||||
const metadata = getMetadataArgsStorage();
|
||||
const index = metadata.indices.find(
|
||||
(candidate) =>
|
||||
candidate.target === CombatEvent &&
|
||||
candidate.columns?.includes('combatId') &&
|
||||
candidate.columns?.includes('sequence'),
|
||||
);
|
||||
|
||||
expect(index).toBeDefined();
|
||||
const indexMetadata = index as typeof index & { options?: { unique?: boolean }; unique?: boolean };
|
||||
expect(indexMetadata?.options?.unique ?? indexMetadata?.unique).toBe(true);
|
||||
});
|
||||
|
||||
it('adds a nullable consumedAt column to hunt_encounters to prevent reuse', () => {
|
||||
const metadata = getMetadataArgsStorage();
|
||||
const column = metadata.columns.find(
|
||||
(candidate) => candidate.target === HuntEncounter && candidate.propertyName === 'consumedAt',
|
||||
);
|
||||
|
||||
expect(column).toBeDefined();
|
||||
expect(column?.options.nullable).toBe(true);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user