package com.baiyue.lastleg.dispatch; import org.junit.jupiter.api.Test; import org.yaml.snakeyaml.Yaml; import java.util.*; import static org.assertj.core.api.Assertions.*; /** 精确解析公开草稿合同,不以全文件字符串误匹配旧客户拆单协议。 */ class SmartDispatchOpenApiContractTest { /** 草稿端点、版本化请求和候选参数必须与冻结端口一致,旧standalone路由移除。 */ @Test void contractPublishesOwnedVersionedDraftProtocol()throws Exception { Map root; try(var input=getClass().getResourceAsStream("/openapi/overseas-business-v1.yaml")){root=new Yaml().load(input);} var paths=map(root.get("paths"));String base="/api/platform/v1/last-leg/dispatches"; assertThat(paths).doesNotContainKey(base+"/pre-arrange"); var expected=new LinkedHashMap(); expected.put("/drafts","DispatchCreateDraft");expected.put("/drafts/containers","DispatchCreateContainer"); expected.put("/drafts/snapshot","DispatchDraftSnapshot");expected.put("/draft-locks/lock","DispatchDraftSelection"); expected.put("/draft-locks/unlock","DispatchDraftSelection");expected.put("/draft-locks/release","DispatchDraftRelease"); expected.put("/drafts/pre-arrange","DispatchConvertDraft");expected.put("/drafts/{draftToken}/containers/{containerId}","DispatchReasonCommand"); var businessRequired=Map.of( "DispatchCreateDraft",List.of("warehouseId"),"DispatchCreateContainer",List.of("draftToken","capacity"), "DispatchDraftSelection",List.of("draftToken","draftContainerId","source"),"DispatchDraftSnapshot",List.of("draftToken","planIds","containers"), "DispatchDraftRelease",List.of("draftToken"),"DispatchConvertDraft",List.of("draftToken","groups")); var schemas=map(map(root.get("components")).get("schemas")); for(var item:expected.entrySet()){ String method=item.getKey().contains("{containerId}")?"delete":"post"; var operation=map(map(paths.get(base+item.getKey())).get(method)); var body=map(operation.get("requestBody"));assertThat(body.get("required")).isEqualTo(true); var schema=map(map(map(body.get("content")).get("application/json")).get("schema")); assertThat(schema.get("$ref")).isEqualTo("#/components/schemas/"+item.getValue()); var request=map(schemas.get(item.getValue()));var fields=map(request.get("properties")); assertThat(fields).doesNotContainKeys("customerId","planPalletIds","returnReceiptIds","expectedVersion"); assertThat(((List)request.get("required")).contains("idempotencyKey")).isTrue(); if(!item.getKey().equals("/drafts"))assertThat(((List)request.get("required")).contains("recordVersion")).isTrue(); assertThat(((List)request.get("required")).containsAll(businessRequired.getOrDefault(item.getValue(),List.of()))).isTrue(); } assertThat(map(paths.get(base+"/drafts"))).containsKey("get"); var candidate=map(map(paths.get(base+"/candidates")).get("get")); var parameterNames=((List)candidate.get("parameters")).stream().map(SmartDispatchOpenApiContractTest::map).map(p->p.get("name")).toList(); var warehouseParameter=((List)candidate.get("parameters")).stream().map(SmartDispatchOpenApiContractTest::map) .filter(p->"warehouseId".equals(p.get("name"))).findFirst().orElseThrow(); assertThat(warehouseParameter.get("required")).isEqualTo(false); assertThat(parameterNames).contains("warehouseId","destinationWarehouseCode","draftToken","page","size","warehouseTab").doesNotContain("customerId","fbaWarehouseCode"); assertThat(map(map(schemas.get("DispatchCandidateList")).get("properties")).keySet()) .containsExactlyInAnyOrder("candidates","snapshotAt","complete","total","page","size","pages"); var draft=map(map(schemas.get("DispatchDraft")).get("properties")); assertThat(draft.keySet()).containsExactlyInAnyOrder("draftToken","recordVersion","status","warehouseId","containers","sources","expiresAt"); var vehicle=map(map(schemas.get("DispatchDraftVehicle")).get("properties"));assertThat(vehicle.keySet()).containsExactlyInAnyOrder("draftContainerId","dispatch"); } /** 失败显示实际缺失节点,避免静默按空合同放过接口漂移。 */ @SuppressWarnings("unchecked") private static Map map(Object value){assertThat(value).isInstanceOf(Map.class);return (Map)value;} }