修正外部媒体序列契约
角色动作素材与项目资源创建请求强制提交完整序列字段 非角色动作类型禁止携带图片序列字段 增加两类请求的正反向 OpenAPI 契约测试
This commit is contained in:
@@ -2064,11 +2064,31 @@
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"imageSequenceFrames",
|
||||
"imageSequenceDurationMs"
|
||||
],
|
||||
"properties": {
|
||||
"generationInputs": {
|
||||
"$ref": "#/components/schemas/ExternalCharacterAnimationGenerationInputs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"else": {
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"imageSequenceFrames"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"imageSequenceDurationMs"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -2158,6 +2178,7 @@
|
||||
},
|
||||
"imageSequenceFrames": {
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/EditorImageSequenceFrame"
|
||||
}
|
||||
@@ -2189,11 +2210,31 @@
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"imageSequenceFrames",
|
||||
"imageSequenceDurationMs"
|
||||
],
|
||||
"properties": {
|
||||
"generationInputs": {
|
||||
"$ref": "#/components/schemas/ExternalCharacterAnimationGenerationInputs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"else": {
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{
|
||||
"required": [
|
||||
"imageSequenceFrames"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"imageSequenceDurationMs"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -2275,6 +2316,7 @@
|
||||
},
|
||||
"imageSequenceFrames": {
|
||||
"type": "array",
|
||||
"minItems": 2,
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/EditorImageSequenceFrame"
|
||||
}
|
||||
|
||||
@@ -1021,6 +1021,11 @@ fn serialize_external_editor_generation_inputs(
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const EXTERNAL_MEDIA_CREATE_REQUEST_SCHEMAS: [&str; 2] = [
|
||||
"ExternalEditorAssetCreateRequest",
|
||||
"ExternalEditorProjectResourceCreateRequest",
|
||||
];
|
||||
|
||||
fn external_generation_job_fixture(status: &str) -> ExternalGenerationJobRecord {
|
||||
ExternalGenerationJobRecord {
|
||||
job_id: "task-external-test".to_string(),
|
||||
@@ -1246,6 +1251,62 @@ mod tests {
|
||||
assert!(!unavailable.body_text().contains("ConnectDropped"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn external_openapi_character_animation_create_requires_complete_sequence_metadata() {
|
||||
let parsed: Value = serde_json::from_str(OPENAPI_JSON).expect("openapi json should parse");
|
||||
|
||||
for request_schema_name in EXTERNAL_MEDIA_CREATE_REQUEST_SCHEMAS {
|
||||
let request_schema = &parsed["components"]["schemas"][request_schema_name];
|
||||
let conditional = &request_schema["allOf"][0];
|
||||
assert_eq!(
|
||||
conditional["then"]["required"],
|
||||
json!(["imageSequenceFrames", "imageSequenceDurationMs"]),
|
||||
"{request_schema_name}"
|
||||
);
|
||||
assert_eq!(
|
||||
request_schema["properties"]["imageSequenceFrames"]["minItems"],
|
||||
json!(2),
|
||||
"{request_schema_name}"
|
||||
);
|
||||
assert_eq!(
|
||||
request_schema["properties"]["imageSequenceDurationMs"]["minimum"],
|
||||
json!(1),
|
||||
"{request_schema_name}"
|
||||
);
|
||||
assert_eq!(
|
||||
conditional["then"]["properties"]["generationInputs"]["$ref"],
|
||||
"#/components/schemas/ExternalCharacterAnimationGenerationInputs",
|
||||
"{request_schema_name}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn external_openapi_non_animation_create_forbids_sequence_metadata() {
|
||||
let parsed: Value = serde_json::from_str(OPENAPI_JSON).expect("openapi json should parse");
|
||||
|
||||
for request_schema_name in EXTERNAL_MEDIA_CREATE_REQUEST_SCHEMAS {
|
||||
let request_schema = &parsed["components"]["schemas"][request_schema_name];
|
||||
let conditional = &request_schema["allOf"][0];
|
||||
assert_eq!(
|
||||
conditional["if"]["required"],
|
||||
json!(["assetKind"]),
|
||||
"{request_schema_name}"
|
||||
);
|
||||
let forbidden_fields = conditional["else"]["not"]["anyOf"]
|
||||
.as_array()
|
||||
.expect("非角色动作分支必须逐项禁止序列字段")
|
||||
.iter()
|
||||
.filter_map(|schema| schema["required"][0].as_str())
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(
|
||||
forbidden_fields,
|
||||
["imageSequenceFrames", "imageSequenceDurationMs"],
|
||||
"{request_schema_name}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exported_openapi_json_contains_external_editor_routes_and_security() {
|
||||
let parsed: Value = serde_json::from_str(OPENAPI_JSON).expect("openapi json should parse");
|
||||
@@ -1270,19 +1331,12 @@ mod tests {
|
||||
.collect::<Vec<_>>(),
|
||||
legacy_runtime_fields
|
||||
);
|
||||
for request_schema in [
|
||||
"ExternalEditorAssetCreateRequest",
|
||||
"ExternalEditorProjectResourceCreateRequest",
|
||||
] {
|
||||
let conditional = &parsed["components"]["schemas"][request_schema]["allOf"][0];
|
||||
for request_schema in EXTERNAL_MEDIA_CREATE_REQUEST_SCHEMAS {
|
||||
assert_eq!(
|
||||
conditional["if"]["properties"]["assetKind"]["const"],
|
||||
parsed["components"]["schemas"][request_schema]["allOf"][0]["if"]["properties"]["assetKind"]
|
||||
["const"],
|
||||
"character-animation"
|
||||
);
|
||||
assert_eq!(
|
||||
conditional["then"]["properties"]["generationInputs"]["$ref"],
|
||||
"#/components/schemas/ExternalCharacterAnimationGenerationInputs"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
parsed["paths"]
|
||||
|
||||
Reference in New Issue
Block a user