Files
TREK/shared/src/assignment/assignment.schema.spec.ts
T
2026-10-04 12:59:55 +02:00

85 lines
3.9 KiB
TypeScript

import {
assignmentCreateRequestSchema,
assignmentEndDayRequestSchema,
assignmentMoveRequestSchema,
assignmentParticipantsRequestSchema,
assignmentSchema,
assignmentTransportRequestSchema,
} from './assignment.schema';
import { describe, it, expect } from 'vitest';
describe('assignment Tours read-model merge', () => {
const ordinary = { id: 1, day_id: 2, place_id: 3, order_index: 0, place: { id: 3, name: 'Place' } };
it('keeps ordinary and legacy track places non-Tours without a facet identity', () => {
expect(assignmentSchema.parse(ordinary).tour_place_id).toBeUndefined();
const legacy = assignmentSchema.parse({ ...ordinary, tour_place_id: null, tour_route_geometry: null });
expect(legacy.tour_place_id).toBeNull();
expect(legacy.tour_route_geometry).toBeNull();
});
it('preserves nullable Tour fields, exclusion and incoming/outgoing segment modes', () => {
const fields = {
tour_place_id: 3,
tour_route_geometry: '[[48,11],[49,12]]',
route_excluded: true,
leg_transport_mode: 'walking',
incoming_leg_transport_mode: 'cycling',
};
expect(assignmentSchema.parse({ ...ordinary, ...fields })).toMatchObject(fields);
expect(assignmentSchema.parse({ ...ordinary, tour_place_id: null, tour_route_geometry: null })).toMatchObject({
tour_place_id: null,
tour_route_geometry: null,
});
});
it('does not copy read-only joined Tours fields into create or move requests', () => {
const joined = { tour_place_id: 3, tour_route_geometry: '[[48,11],[49,12]]' };
expect(assignmentCreateRequestSchema.parse({ place_id: 3, ...joined })).toEqual({ place_id: 3 });
expect(assignmentMoveRequestSchema.parse({ new_day_id: 2, ...joined })).toEqual({ new_day_id: 2 });
});
});
it('requires a boolean for an explicit day end', () => {
expect(assignmentEndDayRequestSchema.parse({ end_day: true })).toEqual({ end_day: true });
expect(assignmentEndDayRequestSchema.parse({ end_day: false })).toEqual({ end_day: false });
for (const end_day of [1, 'true', null, undefined]) {
expect(assignmentEndDayRequestSchema.safeParse({ end_day }).success).toBe(false);
}
});
describe('assignmentCreateRequestSchema', () => {
it('requires a place_id; notes optional/nullable', () => {
expect(assignmentCreateRequestSchema.safeParse({ place_id: 2 }).success).toBe(true);
expect(assignmentCreateRequestSchema.safeParse({ place_id: '2', notes: null }).success).toBe(true);
expect(assignmentCreateRequestSchema.safeParse({}).success).toBe(false);
});
});
describe('assignmentMoveRequestSchema', () => {
it('requires new_day_id; order_index optional/nullable', () => {
expect(assignmentMoveRequestSchema.safeParse({ new_day_id: 4 }).success).toBe(true);
expect(assignmentMoveRequestSchema.safeParse({ new_day_id: 4, order_index: 0 }).success).toBe(true);
// The client api sends `order_index: null` when no insert position is given.
expect(assignmentMoveRequestSchema.safeParse({ new_day_id: 4, order_index: null }).success).toBe(true);
expect(assignmentMoveRequestSchema.safeParse({}).success).toBe(false);
});
});
describe('assignmentTransportRequestSchema', () => {
it('accepts a mode, an explicit null, and an absent key (legacy `?? null`)', () => {
expect(assignmentTransportRequestSchema.safeParse({ transport_mode: 'cycling' }).success).toBe(true);
expect(assignmentTransportRequestSchema.safeParse({ transport_mode: null }).success).toBe(true);
expect(assignmentTransportRequestSchema.safeParse({}).success).toBe(true);
expect(assignmentTransportRequestSchema.safeParse({ transport_mode: 5 }).success).toBe(false);
});
});
describe('assignmentParticipantsRequestSchema', () => {
it('requires a numeric user_ids array', () => {
expect(assignmentParticipantsRequestSchema.safeParse({ user_ids: [1, 2] }).success).toBe(true);
expect(assignmentParticipantsRequestSchema.safeParse({ user_ids: 'no' }).success).toBe(false);
});
});