Files
edr-platform/apps/edr-freight-api/src/modules/routes/routes.duplicate.spec.ts
Marshal 9a1c8e5603 feat: add hazardous goods declaration feature
- Introduced HazardDeclarationPanel component to display dangerous goods declaration details.
- Updated URL constants to include CLEARANCE_PROCEED endpoint for re-requesting operations.
- Enhanced permissions to include hazardous approval roles for contract approvals.
- Integrated HazardDeclarationPanel into ContractRequestDetailPage and ContractClearanceDetailPage.
- Added proceedToOperation method in bookings service for handling operation re-requests.
- Updated contract forms and schemas to include hazard class and UN number fields.
- Implemented validation for hazardous contracts in the contract creation flow.
- Added expiry notice functionality for contracts nearing validity end.
- Created tests for expiry notice calculations and labels.
- Updated UI components to reflect hazardous cargo information and validation errors.
2026-07-25 21:10:09 +00:00

81 lines
2.5 KiB
TypeScript

import { ConflictException } from '@nestjs/common';
import type { DataSource } from 'typeorm';
import { RoutesService } from './routes.service';
import type { RoutesRepository } from './routes.repository';
type StopSeq = Array<{ yardId: string; sequenceNo: number }>;
/** DataSource stub whose Route repository returns the given existing routes. */
const serviceWith = (
existing: Array<{ id: string; milestones: StopSeq }>,
): RoutesService => {
const dataSource = {
getRepository: () => ({ find: async () => existing }),
} as unknown as DataSource;
return new RoutesService(dataSource, {} as RoutesRepository);
};
const assertNotDuplicate = (
service: RoutesService,
yardIds: string[],
excludeRouteId?: string,
): Promise<void> =>
(
service as unknown as {
assertNotDuplicate: (
m: Array<{ yardId: string }>,
id?: string,
) => Promise<void>;
}
).assertNotDuplicate(
yardIds.map((yardId) => ({ yardId })),
excludeRouteId,
);
describe('RoutesService duplicate guard', () => {
const addisAdamaDire: StopSeq = [
{ yardId: 'addis', sequenceNo: 1 },
{ yardId: 'adama', sequenceNo: 2 },
{ yardId: 'dire', sequenceNo: 3 },
];
it('rejects an identical stop sequence', async () => {
const service = serviceWith([{ id: 'r1', milestones: addisAdamaDire }]);
await expect(
assertNotDuplicate(service, ['addis', 'adama', 'dire']),
).rejects.toBeInstanceOf(ConflictException);
});
it('allows the same endpoints with a different corridor', async () => {
// Same origin + destination, but skipping Adama is a genuinely other route.
const service = serviceWith([{ id: 'r1', milestones: addisAdamaDire }]);
await expect(
assertNotDuplicate(service, ['addis', 'dire']),
).resolves.toBeUndefined();
});
it('does not flag the route being edited against itself', async () => {
const service = serviceWith([{ id: 'r1', milestones: addisAdamaDire }]);
await expect(
assertNotDuplicate(service, ['addis', 'adama', 'dire'], 'r1'),
).resolves.toBeUndefined();
});
it('compares stops by sequence, not storage order', async () => {
const shuffled: StopSeq = [
{ yardId: 'dire', sequenceNo: 3 },
{ yardId: 'addis', sequenceNo: 1 },
{ yardId: 'adama', sequenceNo: 2 },
];
const service = serviceWith([{ id: 'r1', milestones: shuffled }]);
await expect(
assertNotDuplicate(service, ['addis', 'adama', 'dire']),
).rejects.toBeInstanceOf(ConflictException);
});
});