50 lines
4.0 KiB
Java
50 lines
4.0 KiB
Java
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<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();
|
|
}
|
|
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();
|
|
assertThat(parameterNames).contains("warehouseId","destinationWarehouseCode","draftToken").doesNotContain("customerId","fbaWarehouseCode");
|
|
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<String,Object> map(Object value){assertThat(value).isInstanceOf(Map.class);return (Map<String,Object>)value;}
|
|
}
|