Files
baiyue-firstleg/lastleg-service/src/test/java/com/baiyue/lastleg/dispatch/SmartDispatchOpenApiContractTest.java
T

52 lines
4.2 KiB
Java
Raw Normal View History

2026-08-21 11:43:03 +08:00
package com.baiyue.lastleg.dispatch;
import org.junit.jupiter.api.Test;
2026-10-19 17:56:36 +08:00
import org.yaml.snakeyaml.Yaml;
import java.util.*;
import static org.assertj.core.api.Assertions.*;
2026-08-21 11:43:03 +08:00
2026-10-19 17:56:36 +08:00
/** 精确解析公开草稿合同,不以全文件字符串误匹配旧客户拆单协议。 */
2026-08-21 11:43:03 +08:00
class SmartDispatchOpenApiContractTest {
2026-10-19 17:56:36 +08:00
/** 草稿端点、版本化请求和候选参数必须与冻结端口一致,旧standalone路由移除。 */
@Test void contractPublishesOwnedVersionedDraftProtocol()throws Exception {
Map<String,Object> 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<String,String>();
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();
2026-08-21 11:43:03 +08:00
}
2026-10-19 17:56:36 +08:00
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();
2026-10-21 07:53:31 +08:00
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");
2026-10-19 17:56:36 +08:00
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");
2026-08-21 11:43:03 +08:00
}
2026-10-19 17:56:36 +08:00
/** 失败显示实际缺失节点,避免静默按空合同放过接口漂移。 */
@SuppressWarnings("unchecked")
private static Map<String,Object> map(Object value){assertThat(value).isInstanceOf(Map.class);return (Map<String,Object>)value;}
2026-08-21 11:43:03 +08:00
}