test(jimeng): cover body assembly and poll parameters

Round out request-body validation and pin the polling parameters:
- all five allowed aspect ratios and both frame counts build
- prompt + image_urls together both land in the video body
- whitespace-only prompt is dropped but an image still satisfies one-of
- optional video fields are omitted when absent
- default poll interval/timeout values (image 2s/120s, video 8s/600s)
This commit is contained in:
boos
2026-06-23 14:22:43 +08:00
parent bf16139695
commit d956b3f9f4
+97
View File
@@ -384,4 +384,101 @@ mod tests {
Err(JimengError::Disabled)
));
}
#[test]
fn video_body_accepts_all_allowed_aspect_ratios() {
for ratio in ALLOWED_ASPECT_RATIOS {
let req = VideoRequest {
prompt: Some("x".into()),
image_urls: vec![],
frames: 121,
aspect_ratio: Some(ratio.to_string()),
seed: None,
};
let body = build_video_body(&req)
.unwrap_or_else(|e| panic!("ratio {ratio} should be allowed: {e:?}"));
assert_eq!(body["aspect_ratio"], ratio);
}
}
#[test]
fn video_body_accepts_both_frame_counts() {
for frames in ALLOWED_FRAMES {
let req = VideoRequest {
prompt: Some("x".into()),
image_urls: vec![],
frames,
aspect_ratio: None,
seed: None,
};
let body = build_video_body(&req)
.unwrap_or_else(|e| panic!("frames {frames} should be allowed: {e:?}"));
assert_eq!(body["frames"], frames);
}
}
#[test]
fn video_body_includes_prompt_and_image_together() {
// Both inputs supplied (image-to-video with a guiding prompt): both end
// up in the body.
let req = VideoRequest {
prompt: Some("a dragon".into()),
image_urls: vec!["https://x/a.jpg".into(), "https://x/b.jpg".into()],
frames: 241,
aspect_ratio: Some("9:16".into()),
seed: Some(42),
};
let body = build_video_body(&req).unwrap();
assert_eq!(body["prompt"], "a dragon");
assert_eq!(body["image_urls"][1], "https://x/b.jpg");
assert_eq!(body["frames"], 241);
assert_eq!(body["seed"], 42);
}
#[test]
fn video_body_drops_whitespace_prompt_but_keeps_image() {
// A whitespace-only prompt is not a real prompt: it must not be written
// to the body, yet the image alone satisfies the "one of" requirement.
let req = VideoRequest {
prompt: Some(" ".into()),
image_urls: vec!["https://x/a.jpg".into()],
frames: 121,
aspect_ratio: None,
seed: None,
};
let body = build_video_body(&req).unwrap();
let obj = body.as_object().unwrap();
assert!(!obj.contains_key("prompt"), "blank prompt must be omitted");
assert_eq!(body["image_urls"][0], "https://x/a.jpg");
}
#[test]
fn video_body_omits_absent_optional_fields() {
let req = VideoRequest {
prompt: Some("x".into()),
image_urls: vec![],
frames: 121,
aspect_ratio: None,
seed: None,
};
let body = build_video_body(&req).unwrap();
let obj = body.as_object().unwrap();
assert!(!obj.contains_key("aspect_ratio"));
assert!(!obj.contains_key("seed"));
assert!(!obj.contains_key("image_urls"));
}
#[test]
fn default_poll_parameters_differ_image_vs_video() {
// The submit→poll state machine reads interval/timeout from config; lock
// the shipped defaults so a regression in JimengConfig is caught here.
let cfg = JimengConfig::default();
assert_eq!(cfg.image_poll_interval_secs, 2);
assert_eq!(cfg.image_timeout_secs, 120);
assert_eq!(cfg.video_poll_interval_secs, 8);
assert_eq!(cfg.video_timeout_secs, 600);
// Video is the longer-running capability: bigger interval and timeout.
assert!(cfg.video_poll_interval_secs > cfg.image_poll_interval_secs);
assert!(cfg.video_timeout_secs > cfg.image_timeout_secs);
}
}