From 11c25fc78aa9740e1500811419f7c78bcbd3bd0f Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 23 Feb 2026 17:30:58 +0700 Subject: [PATCH] tests --- .../src/client/router_artcraft_client.rs | 6 + .../tests/artcraft_seedance_2p0.rs | 235 ++++++++++++++++++ 2 files changed, 241 insertions(+) create mode 100644 crates/lib/artcraft_router/tests/artcraft_seedance_2p0.rs diff --git a/crates/lib/artcraft_router/src/client/router_artcraft_client.rs b/crates/lib/artcraft_router/src/client/router_artcraft_client.rs index 09e04146e9..6a42e714ef 100644 --- a/crates/lib/artcraft_router/src/client/router_artcraft_client.rs +++ b/crates/lib/artcraft_router/src/client/router_artcraft_client.rs @@ -5,3 +5,9 @@ pub struct RouterArtcraftClient { pub(crate) api_host: ApiHost, pub(crate) credentials: StorytellerCredentialSet, } + +impl RouterArtcraftClient { + pub fn new(api_host: ApiHost, credentials: StorytellerCredentialSet) -> Self { + Self { api_host, credentials } + } +} diff --git a/crates/lib/artcraft_router/tests/artcraft_seedance_2p0.rs b/crates/lib/artcraft_router/tests/artcraft_seedance_2p0.rs new file mode 100644 index 0000000000..b5b80352e7 --- /dev/null +++ b/crates/lib/artcraft_router/tests/artcraft_seedance_2p0.rs @@ -0,0 +1,235 @@ +use artcraft_router::api::common_aspect_ratio::CommonAspectRatio; +use artcraft_router::api::common_video_model::CommonVideoModel; +use artcraft_router::api::image_ref::ImageRef; +use artcraft_router::api::provider::Provider; +use artcraft_router::client::request_mismatch_mitigation_strategy::RequestMismatchMitigationStrategy; +use artcraft_router::client::router_artcraft_client::RouterArtcraftClient; +use artcraft_router::client::router_client::RouterClient; +use artcraft_router::errors::artcraft_router_error::ArtcraftRouterError; +use artcraft_router::errors::client_error::ClientError; +use artcraft_router::generate::generate_video::begin_video_generation::begin_video_generation; +use artcraft_router::generate::generate_video::generate_video_request::GenerateVideoRequest; +use artcraft_router::generate::generate_video::video_generation_plan::VideoGenerationPlan; +use artcraft_api_defs::generate::video::multi_function::seedance_2p0_multi_function_video_gen::{ + Seedance2p0AspectRatio, Seedance2p0BatchCount, +}; +use storyteller_client::credentials::storyteller_credential_set::StorytellerCredentialSet; +use storyteller_client::credentials::storyteller_session_cookie::StorytellerSessionCookie; +use storyteller_client::utils::api_host::ApiHost; + +fn get_artcraft_client() -> RouterClient { + let cookies = std::fs::read_to_string("/Users/bt/Artcraft/credentials/artcraft_cookies.txt") + .expect("Failed to read /Users/bt/Artcraft/credentials/artcraft_cookies.txt"); + let credentials = StorytellerCredentialSet::initialize_with_just_cookie( + StorytellerSessionCookie::new(cookies.trim().to_string()), + ); + RouterClient::Artcraft(RouterArtcraftClient::new(ApiHost::Storyteller, credentials)) +} + +fn base_request() -> GenerateVideoRequest<'static> { + GenerateVideoRequest { + model: CommonVideoModel::Seedance2p0, + provider: Provider::Artcraft, + prompt: Some("a cat in space"), + start_frame: None, + end_frame: None, + reference_images: None, + resolution: None, + aspect_ratio: None, + duration_seconds: None, + video_batch_count: None, + request_mismatch_mitigation_strategy: RequestMismatchMitigationStrategy::ErrorOut, + idempotency_token: None, + } +} + +mod plan_tests { + use super::*; + + #[test] + fn aspect_ratio_direct_16x9() { + let request = GenerateVideoRequest { + aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), + ..base_request() + }; + let VideoGenerationPlan::ArtcraftSeedance2p0(plan) = begin_video_generation(&request).unwrap(); + assert!(matches!(plan.aspect_ratio, Some(Seedance2p0AspectRatio::Landscape16x9))); + } + + #[test] + fn aspect_ratio_direct_9x16() { + let request = GenerateVideoRequest { + aspect_ratio: Some(CommonAspectRatio::TallNineBySixteen), + ..base_request() + }; + let VideoGenerationPlan::ArtcraftSeedance2p0(plan) = begin_video_generation(&request).unwrap(); + assert!(matches!(plan.aspect_ratio, Some(Seedance2p0AspectRatio::Portrait9x16))); + } + + #[test] + fn aspect_ratio_direct_square() { + let request = GenerateVideoRequest { + aspect_ratio: Some(CommonAspectRatio::Square), + ..base_request() + }; + let VideoGenerationPlan::ArtcraftSeedance2p0(plan) = begin_video_generation(&request).unwrap(); + assert!(matches!(plan.aspect_ratio, Some(Seedance2p0AspectRatio::Square1x1))); + } + + #[test] + fn aspect_ratio_nearest_match_both_strategies() { + // WideThreeByTwo (AR 1.5) is nearest to Standard4x3 (1.33), not Landscape16x9 (1.78) + for strategy in [ + RequestMismatchMitigationStrategy::PayMoreUpgrade, + RequestMismatchMitigationStrategy::PayLessDowngrade, + ] { + let request = GenerateVideoRequest { + aspect_ratio: Some(CommonAspectRatio::WideThreeByTwo), + request_mismatch_mitigation_strategy: strategy, + ..base_request() + }; + let VideoGenerationPlan::ArtcraftSeedance2p0(plan) = begin_video_generation(&request).unwrap(); + assert!( + matches!(plan.aspect_ratio, Some(Seedance2p0AspectRatio::Standard4x3)), + "Expected Standard4x3 for WideThreeByTwo with {:?}", strategy, + ); + } + } + + #[test] + fn aspect_ratio_error_out_on_unsupported() { + let request = GenerateVideoRequest { + aspect_ratio: Some(CommonAspectRatio::WideThreeByTwo), + request_mismatch_mitigation_strategy: RequestMismatchMitigationStrategy::ErrorOut, + ..base_request() + }; + let result = begin_video_generation(&request); + assert!(matches!( + result, + Err(ArtcraftRouterError::Client(ClientError::ModelDoesNotSupportOption { .. })) + )); + } + + #[test] + fn batch_count_zero_is_always_error() { + for strategy in [ + RequestMismatchMitigationStrategy::ErrorOut, + RequestMismatchMitigationStrategy::PayMoreUpgrade, + RequestMismatchMitigationStrategy::PayLessDowngrade, + ] { + let request = GenerateVideoRequest { + video_batch_count: Some(0), + request_mismatch_mitigation_strategy: strategy, + ..base_request() + }; + let result = begin_video_generation(&request); + assert!( + matches!(result, Err(ArtcraftRouterError::Client(ClientError::UserRequestedZeroGenerations))), + "Expected UserRequestedZeroGenerations with {:?}", strategy, + ); + } + } + + #[test] + fn batch_count_direct_mapping() { + let VideoGenerationPlan::ArtcraftSeedance2p0(plan) = begin_video_generation( + &GenerateVideoRequest { video_batch_count: Some(1), ..base_request() } + ).unwrap(); + assert!(matches!(plan.batch_count, Seedance2p0BatchCount::One)); + + let VideoGenerationPlan::ArtcraftSeedance2p0(plan) = begin_video_generation( + &GenerateVideoRequest { video_batch_count: Some(2), ..base_request() } + ).unwrap(); + assert!(matches!(plan.batch_count, Seedance2p0BatchCount::Two)); + + let VideoGenerationPlan::ArtcraftSeedance2p0(plan) = begin_video_generation( + &GenerateVideoRequest { video_batch_count: Some(4), ..base_request() } + ).unwrap(); + assert!(matches!(plan.batch_count, Seedance2p0BatchCount::Four)); + } + + #[test] + fn batch_count_three_upgrade_rounds_to_four() { + let request = GenerateVideoRequest { + video_batch_count: Some(3), + request_mismatch_mitigation_strategy: RequestMismatchMitigationStrategy::PayMoreUpgrade, + ..base_request() + }; + let VideoGenerationPlan::ArtcraftSeedance2p0(plan) = begin_video_generation(&request).unwrap(); + assert!(matches!(plan.batch_count, Seedance2p0BatchCount::Four)); + } + + #[test] + fn batch_count_three_downgrade_rounds_to_two() { + let request = GenerateVideoRequest { + video_batch_count: Some(3), + request_mismatch_mitigation_strategy: RequestMismatchMitigationStrategy::PayLessDowngrade, + ..base_request() + }; + let VideoGenerationPlan::ArtcraftSeedance2p0(plan) = begin_video_generation(&request).unwrap(); + assert!(matches!(plan.batch_count, Seedance2p0BatchCount::Two)); + } + + #[test] + fn url_image_ref_returns_error() { + let request = GenerateVideoRequest { + start_frame: Some(ImageRef::Url("https://example.com/image.jpg")), + ..base_request() + }; + let result = begin_video_generation(&request); + assert!(matches!( + result, + Err(ArtcraftRouterError::Client(ClientError::ArtcraftOnlySupportsMediaTokens)) + )); + } +} + +mod real_requests { + use super::*; + + #[tokio::test] + #[ignore] // manually run — fires a real API request and incurs cost + async fn test_text_to_video_seedance_2p0() { + let client = get_artcraft_client(); + let request = GenerateVideoRequest { + aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), + video_batch_count: Some(1), + prompt: Some("a cat walking through a cyberpunk city at night"), + ..base_request() + }; + + let plan = begin_video_generation(&request).unwrap(); + let result = plan.generate_video(&client).await; + + println!("Result: {:?}", result); + let response = result.expect("generate_video request failed"); + println!("Job token: {:?}", response.inference_job_token); + println!("All job tokens: {:?}", response.all_inference_job_tokens); + + assert_eq!(1, 2); // NB: Intentional failure to inspect the response above. + } + + #[tokio::test] + #[ignore] // manually run — fires a real API request and incurs cost + async fn test_text_to_video_seedance_2p0_batch_two() { + let client = get_artcraft_client(); + let request = GenerateVideoRequest { + aspect_ratio: Some(CommonAspectRatio::Square), + video_batch_count: Some(2), + prompt: Some("a dog surfing a wave, cinematic"), + ..base_request() + }; + + let plan = begin_video_generation(&request).unwrap(); + let result = plan.generate_video(&client).await; + + println!("Result: {:?}", result); + let response = result.expect("generate_video request failed"); + println!("Job tokens ({} total):", response.all_inference_job_tokens.len()); + for token in &response.all_inference_job_tokens { + println!(" {:?}", token); + } + + assert_eq!(1, 2); // NB: Intentional failure to inspect the response above. + } +}