From 2906c6bb45ae113ade59dea90a53986039ad45de Mon Sep 17 00:00:00 2001 From: Hagernesh Date: Mon, 20 Jul 2026 07:06:19 +0000 Subject: [PATCH] test(train-scheduling): cover the checkpoint backdating guard on the DTO The IsNotBackdated validator was covered in isolation, but not on the DTO that actually carries it. Asserts a backdated occurredAt is rejected, that "now" passes, and that omitting the field still validates so the service can stamp it. Co-Authored-By: Claude Opus 4.8 --- .../dto/record-checkpoint.dto.spec.ts | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 apps/edr-freight-api/src/modules/train-scheduling/dto/record-checkpoint.dto.spec.ts diff --git a/apps/edr-freight-api/src/modules/train-scheduling/dto/record-checkpoint.dto.spec.ts b/apps/edr-freight-api/src/modules/train-scheduling/dto/record-checkpoint.dto.spec.ts new file mode 100644 index 000000000..58cf5da12 --- /dev/null +++ b/apps/edr-freight-api/src/modules/train-scheduling/dto/record-checkpoint.dto.spec.ts @@ -0,0 +1,37 @@ +import { plainToInstance } from 'class-transformer'; +import { validate } from 'class-validator'; + +import { RecordCheckpointDto } from './record-checkpoint.dto'; + +const validateBody = (body: Record) => + validate(plainToInstance(RecordCheckpointDto, body)); + +describe('RecordCheckpointDto', () => { + // The final checkpoint arrives the schedule, so a backdated one rewrites the + // journey after the fact. No UI sends occurredAt; the endpoint still accepts it. + it('rejects a backdated occurredAt', async () => { + const errors = await validateBody({ + sequenceNo: 3, + occurredAt: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(), + }); + + expect(errors).toHaveLength(1); + expect(errors[0].property).toBe('occurredAt'); + expect(errors[0].constraints).toHaveProperty('IsNotBackdated'); + }); + + it('accepts occurredAt of now', async () => { + const errors = await validateBody({ + sequenceNo: 3, + occurredAt: new Date().toISOString(), + }); + + expect(errors).toHaveLength(0); + }); + + it('accepts a body that omits occurredAt, leaving the service to stamp it', async () => { + const errors = await validateBody({ sequenceNo: 0 }); + + expect(errors).toHaveLength(0); + }); +});