优化
This commit is contained in:
+41
-49
@@ -1,57 +1,49 @@
|
||||
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.*;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/** 精确解析公开草稿合同,不以全文件字符串误匹配旧客户拆单协议。 */
|
||||
class SmartDispatchOpenApiContractTest {
|
||||
@Test
|
||||
void contractDocumentsOnlyCandidateAndPreArrangeSmartDispatchWrites() throws Exception {
|
||||
String yaml;
|
||||
try (var input = getClass().getResourceAsStream("/openapi/overseas-business-v1.yaml")) {
|
||||
yaml = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
||||
/** 草稿端点、版本化请求和候选参数必须与冻结端口一致,旧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();
|
||||
}
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/candidates:"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/pre-arrange:"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/drafts/pre-arrange:"));
|
||||
assertTrue(yaml.contains("required: [draftToken, groups]"));
|
||||
assertTrue(yaml.contains("required: [draftContainerId, planPalletIds, returnReceiptIds]"));
|
||||
assertTrue(yaml.contains("SmartDispatchDraftGroupResult:"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/draft-locks/lock:"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/draft-locks/unlock:"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/draft-locks/release:"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/drafts:"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/drafts/snapshot:"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/drafts/containers:"));
|
||||
assertTrue(yaml.contains("/api/platform/v1/last-leg/dispatches/drafts/{draftToken}/containers/{containerId}:"));
|
||||
assertTrue(yaml.contains("draftContainerId:"));
|
||||
assertTrue(yaml.contains("SmartDispatchDraftContainer:"));
|
||||
assertTrue(yaml.contains("capacity: { type: integer, enum: [15, 30] }"));
|
||||
assertTrue(yaml.contains("SmartDispatchDraft:"));
|
||||
assertTrue(yaml.contains("platform:overseas-warehouse:inbound-order:list"));
|
||||
assertTrue(yaml.contains("platform:overseas-warehouse:inbound-order:smart-dispatch"));
|
||||
assertTrue(yaml.contains("SmartDispatchPreArrange"));
|
||||
assertTrue(yaml.contains("SmartDispatchCandidate"));
|
||||
assertTrue(yaml.contains("overseasWarehouseCode: { type: string, nullable: true, description: 实际海外接柜仓编码"));
|
||||
assertTrue(yaml.contains("grossWeightKg: { type: number, nullable: true, description: 候选托盘分摊毛重"));
|
||||
assertTrue(yaml.contains("禁止使用体积重替代"));
|
||||
String preArrangeSchema = yaml.substring(yaml.indexOf(" SmartDispatchPreArrange:"),
|
||||
yaml.indexOf(" SmartDispatchDraftPallet:"));
|
||||
String updateSchema = yaml.substring(yaml.indexOf(" DispatchUpdate:"),
|
||||
yaml.indexOf(" DeliveryTransfer:"));
|
||||
assertFalse(preArrangeSchema.contains("route:"));
|
||||
assertFalse(updateSchema.contains("route:"));
|
||||
assertTrue(updateSchema.contains("departAt: { type: string, format: date-time, nullable: true }"));
|
||||
assertTrue(yaml.contains("name: planIds"));
|
||||
String planIdsParameter = yaml.substring(yaml.indexOf("name: planIds"),
|
||||
yaml.indexOf("name: orderNo", yaml.indexOf("name: planIds")));
|
||||
assertTrue(planIdsParameter.contains("required: false"));
|
||||
String dispatchContract = yaml.substring(yaml.indexOf("/api/platform/v1/last-leg/dispatches:"),
|
||||
yaml.indexOf("/api/platform/v1/last-leg/outbound-orders:"));
|
||||
assertFalse(dispatchContract.contains("name: customerId"));
|
||||
assertFalse(yaml.contains("/api/platform/v1/last-leg/dispatches/{dispatchNo}/depart:"));
|
||||
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;}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user