import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' const read = (path) => readFileSync(new URL(path, import.meta.url), 'utf8') const oceanService = read('../../firstleg/src/main/java/com/baiyue/firstleg/oceanbooking/service/OceanBookingService.java') const oceanOpenApi = read('../../firstleg/src/main/resources/openapi/ocean-bookings-v1.yaml') const containerDtos = read('../../firstleg/src/main/java/com/baiyue/firstleg/dto/ContainerDtos.java') const containerService = read('../../firstleg/src/main/java/com/baiyue/firstleg/service/ContainerService.java') const fixture = read('phase3-container-loading.mjs') const fullEntry = read('../admin-test-env-acceptance.mjs') test('booking is an editable DRAFT aggregate and RELEASED is immutable', () => { assert.match(oceanService, /OPERATIONAL_LIST_STATUSES\s*=\s*Set\.of\([\s\S]*DRAFT[\s\S]*RELEASED/) assert.match(oceanOpenApi, /Create an editable DRAFT/) assert.match(oceanOpenApi, /Replace a DRAFT/) assert.match(oceanOpenApi, /Delete a DRAFT; RELEASED is immutable/) assert.doesNotMatch(oceanOpenApi, /CHANGE_PENDING|CANCELLED/) }) test('booking requirements never carry real container numbers or create allocations', () => { assert.match(oceanOpenApi, /containerRequirements/) assert.match(oceanOpenApi, /ContainerRequirementRequest/) assert.match(oceanOpenApi, /quantity/) assert.match(oceanOpenApi, /no containerNo, container row, or allocation is created/) assert.doesNotMatch(oceanOpenApi.match(/ContainerRequirementRequest:[\s\S]*?ReleaseRequest:/)?.[0] || '', /containerNo/) }) test('port link mutates the simulation through the frozen four-field request', () => { assert.match(containerDtos, /OceanBookingLinkRequest\(@NotNull @Positive Long oceanBookingId,[\s\S]*Long requirementId,[\s\S]*String containerNo,[\s\S]*Integer expectedVersion/) assert.match(containerService, /request\.oceanBookingId\(\)/) assert.match(containerService, /request\.requirementId\(\)/) assert.match(containerService, /request\.containerNo\(\)/) assert.match(containerService, /["']RELEASED["']\.equals\(booking\.getStatus\(\)\)/) assert.doesNotMatch(fixture, /realContainerBookingId/) assert.match(fixture, /oceanBookingId: bookingId, requirementId: id\(requirement\.id\), containerNo: realContainerNo/) }) test('HTTP fixture keeps simulation and plan identities and creates allocation at link', () => { assert.match(fixture, /关联前后内部柜次、计划和排货明细身份稳定/) assert.match(fixture, /订舱 allocation 原子创建并指向稳定模拟柜身份/) assert.match(fixture, /已消费订舱需求拒绝再次关联/) assert.match(fixture, /RELEASED 订舱进入正式列表/) }) test('default full acceptance keeps the linked simulation before PDA and finalize', () => { const loading = fullEntry.indexOf("'phase3-container-loading'") const pda = fullEntry.indexOf("'phase3-pda-convergence'") const finalize = fullEntry.indexOf("'phase3-loading-finalize'") assert.ok(loading >= 0 && pda > loading && finalize > pda) })