c48f0627cf
- 把 server-rs 与 apps/ai-game-creator-shell/src-tauri 两个 workspace 的 ts-rs 从 registry 固定到上游修复 commit fd8679ef20f866f747c046b30bd29c15e3d7a003(PR #491:已发布版 12.0.1 的 EnumAttr 不识别 deny_unknown_fields,只有 StructAttr 会静默忽略它),两个 Cargo.lock 同步改成 git 源 - 说明固定原因与退出条件:crates.io 最新仍是 12.0.1、GitHub 最新 tag 仍是 v12.0.0,等发布 > 12.0.1 后改回 registry 版本并删除 commit 固定 - 明确不使用 ts-rs 的 no-serde-warnings feature 消警:它会连同 deserialize_with 这类真实未支持的 serde 属性一起静默,掩盖 Rust 与 TS 绑定的漂移 - 保留 shared-contracts 的 Model3dMultiviewInputs enum 级 deny_unknown_fields(该属性一直由 serde 生效,告警只来自 ts-rs 的属性解析),注释改为写明不要为消警删属性、也不要改用 no-serde-warnings - 新增契约测试 tests/model3d_multiview_request_contract.rs:钉住 views/taskId 变体内部与请求体顶层拒绝未知字段,并覆盖 kind 与 camelCase 字段名解析 - 记录排障经验与决策:pitfalls.md 说明无 span 的告警不代表属性失效,decision-log.md 记录固定 commit、影响面与回退条件 - 验证:cargo check -p shared-contracts 与该 crate 的 cargo test 不再出现 deny_unknown_fields 告警且全绿;cargo test --locked -p shared-contracts model3d 加 prettier 后 packages/shared 的 model3d 绑定零 diff;AGC 的 cargo check --locked --bin genarrative-ai-game-creator-shell 不再出现该告警(AGC 侧仍保留 1 条既有的 deserialize_with 告警,与本改动无关);npm run check:encoding、npm run check:doc-index、git diff --check、cargo fmt --all --check 通过
79 lines
2.6 KiB
Rust
79 lines
2.6 KiB
Rust
use serde_json::json;
|
|
use shared_contracts::model3d::common::Model3dModelVersion;
|
|
use shared_contracts::model3d::multiview_to_model::{
|
|
Model3dMultiviewInputs, Model3dMultiviewToModelRequest,
|
|
};
|
|
|
|
#[test]
|
|
fn multiview_inputs_accepts_declared_fields_and_camel_case_tag() {
|
|
let inputs: Model3dMultiviewInputs = serde_json::from_value(json!({
|
|
"kind": "views",
|
|
"front": "front.png",
|
|
"left": "left.png"
|
|
}))
|
|
.expect("已声明字段应可反序列化");
|
|
|
|
match inputs {
|
|
Model3dMultiviewInputs::Views { front, left, .. } => {
|
|
assert_eq!(front, "front.png");
|
|
assert_eq!(left.as_deref(), Some("left.png"));
|
|
}
|
|
Model3dMultiviewInputs::TaskId { .. } => panic!("kind=views 不应解成 taskId 变体"),
|
|
}
|
|
|
|
let task: Model3dMultiviewInputs = serde_json::from_value(json!({
|
|
"kind": "taskId",
|
|
"taskId": "tripo-task-1"
|
|
}))
|
|
.expect("taskId 变体使用 camelCase 字段名");
|
|
|
|
assert!(matches!(task, Model3dMultiviewInputs::TaskId { .. }));
|
|
}
|
|
|
|
#[test]
|
|
fn multiview_inputs_reject_unknown_fields_inside_variants() {
|
|
// enum 级 `deny_unknown_fields` 由 serde 生效,ts-rs 12 无法在 TS 绑定里表达;
|
|
// 这条用例钉住该严格性,防止为消除 ts-rs 告警而把它改成非严格模式。
|
|
let error = serde_json::from_value::<Model3dMultiviewInputs>(json!({
|
|
"kind": "views",
|
|
"front": "front.png",
|
|
"left": "left.png",
|
|
"back": "back.png",
|
|
"right": "right.png",
|
|
"unexpected": true
|
|
}))
|
|
.expect_err("变体里出现未知字段应被拒绝");
|
|
|
|
assert!(
|
|
error.to_string().contains("unknown field"),
|
|
"未知字段错误应指出 unknown field,实际为:{error}"
|
|
);
|
|
|
|
let error = serde_json::from_value::<Model3dMultiviewInputs>(json!({
|
|
"kind": "taskId",
|
|
"taskId": "tripo-task-1",
|
|
"unexpected": true
|
|
}))
|
|
.expect_err("taskId 变体里出现未知字段应被拒绝");
|
|
|
|
assert!(
|
|
error.to_string().contains("unknown field"),
|
|
"未知字段错误应指出 unknown field,实际为:{error}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn multiview_request_rejects_unknown_top_level_fields() {
|
|
let error = serde_json::from_value::<Model3dMultiviewToModelRequest>(json!({
|
|
"inputs": { "kind": "taskId", "taskId": "tripo-task-1" },
|
|
"model": Model3dModelVersion::H31.as_str(),
|
|
"unexpected": true
|
|
}))
|
|
.expect_err("请求体顶层出现未知字段应被拒绝");
|
|
|
|
assert!(
|
|
error.to_string().contains("unknown field"),
|
|
"未知字段错误应指出 unknown field,实际为:{error}"
|
|
);
|
|
}
|