修复AGC Native测试夹具
固定普通 JSON Provider mock 为非流式 为平台账号画布与视觉门禁测试安装隔离会话 同步现役路由、默认配置与提示词断言
This commit is contained in:
@@ -7,7 +7,13 @@ pub(crate) async fn request_llm_game_draft_with_client(
|
||||
short_memory: &str,
|
||||
long_memory: &str,
|
||||
) -> Result<LlmGameDraft, String> {
|
||||
let llm = GameCreatorLlmConfig::default();
|
||||
// This helper exercises the one-shot OpenAI-compatible response fixture.
|
||||
// Streaming has its own response-stream coverage; keeping this explicit
|
||||
// prevents the production default from making the mock parse JSON as SSE.
|
||||
let llm = GameCreatorLlmConfig {
|
||||
stream: false,
|
||||
..GameCreatorLlmConfig::default()
|
||||
};
|
||||
request_generator_game_draft_with_client(
|
||||
client,
|
||||
&llm,
|
||||
|
||||
@@ -1217,6 +1217,11 @@ async fn visual_specialists_reject_overriding_their_fixed_image_contract() {
|
||||
|
||||
#[test]
|
||||
fn design_foundation_rejects_scene_image_stale_run_and_stale_sha_visual_proofs() {
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"visual-semantic-gate-test-user",
|
||||
"visual-semantic-gate-test-key",
|
||||
"https://dev.genarrative.world",
|
||||
);
|
||||
let _config_guard = crate::tests::write_test_local_config(
|
||||
r#"{"editorApi":{"apiKey":"visual-semantic-gate-test-key"}}"#.to_string(),
|
||||
);
|
||||
@@ -1608,6 +1613,11 @@ async fn canvas_replacement_rejects_parent_run_that_terminates_during_external_r
|
||||
request_sender,
|
||||
generation_release_receiver,
|
||||
);
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"canvas-replacement-user",
|
||||
"editor-runtime-key",
|
||||
&canvas_base_url,
|
||||
);
|
||||
init_local_game_project_at(&root, "project-canvas-repair-atomic", "月光厨房")
|
||||
.expect("project init");
|
||||
register_canvas_visual_asset_fixture(&root, "assets/art-spec.png", "icon-spec");
|
||||
@@ -1800,7 +1810,7 @@ async fn canvas_replacement_rejects_parent_run_that_terminates_during_external_r
|
||||
let captured = request_receiver
|
||||
.recv_timeout(Duration::from_secs(15))
|
||||
.expect("canvas request before generation response");
|
||||
if captured.starts_with("POST /api/external/v1/editor/icon-spritesheets/generations ") {
|
||||
if captured.starts_with("POST /api/editor/icon-spritesheets/generations ") {
|
||||
saw_generation_request = true;
|
||||
break;
|
||||
}
|
||||
@@ -2231,6 +2241,11 @@ fn gui_and_cli_autonomous_runs_still_allow_publish_delegates() {
|
||||
|
||||
#[test]
|
||||
fn visual_specialist_delegations_require_image_artifacts_but_read_only_work_allows_none() {
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"visual-delegation-contract-user",
|
||||
"visual-delegation-contract-key",
|
||||
"https://dev.genarrative.world",
|
||||
);
|
||||
let _config_guard = crate::tests::write_test_local_config(
|
||||
r#"{"editorApi":{"apiKey":"visual-delegation-contract-key"}}"#.to_string(),
|
||||
);
|
||||
|
||||
@@ -38,6 +38,11 @@ fn project_supervisor_runtime_id_is_normalized_and_collected() {
|
||||
|
||||
#[test]
|
||||
fn visual_specialist_prompts_require_real_registered_image_deliveries() {
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"visual-prompt-test-user",
|
||||
"visual-prompt-test-key",
|
||||
"https://dev.genarrative.world",
|
||||
);
|
||||
let _config_guard = crate::tests::write_test_local_config(
|
||||
r#"{"editorApi":{"apiKey":"visual-prompt-test-key"}}"#.to_string(),
|
||||
);
|
||||
@@ -154,6 +159,11 @@ fn visual_prompts_degrade_to_text_contracts_without_editor_api_key() {
|
||||
#[tokio::test]
|
||||
async fn project_supervisor_prompts_are_total_control_and_reject_isolated_template() {
|
||||
let planning_prompt = {
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"supervisor-prompt-test-user",
|
||||
"supervisor-prompt-test-key",
|
||||
"https://dev.genarrative.world",
|
||||
);
|
||||
let _config_guard = crate::tests::write_test_local_config(
|
||||
r#"{"editorApi":{"apiKey":"supervisor-prompt-test-key"}}"#.to_string(),
|
||||
);
|
||||
@@ -307,7 +317,7 @@ fn project_supervisor_llm_config_prefers_specific_patch_and_falls_back_to_legacy
|
||||
assert_eq!(specialist.api_key, "global-key");
|
||||
assert_eq!(specialist.base_url, "https://global.example.test/v1");
|
||||
assert_eq!(specialist.model, "global-model");
|
||||
assert!(!specialist.stream);
|
||||
assert!(specialist.stream);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -531,7 +531,7 @@ fn runtime_config_read_returns_defaults_when_file_is_missing() {
|
||||
result.config.llm.reasoning_effort,
|
||||
DEFAULT_GAME_CREATOR_LLM_REASONING_EFFORT
|
||||
);
|
||||
assert!(!result.config.llm.stream);
|
||||
assert!(result.config.llm.stream);
|
||||
assert!(!result.config.llm.web_search_enabled);
|
||||
assert_eq!(
|
||||
result.config.llm.context_window_tokens,
|
||||
|
||||
@@ -1230,6 +1230,14 @@ pub(crate) fn write_test_local_config(content: String) -> TestConfigGuard {
|
||||
config
|
||||
.entry("agentMode")
|
||||
.or_insert_with(|| serde_json::json!(GAME_CREATOR_AGENT_MODE_PROVIDER));
|
||||
let llm = config.entry("llm").or_insert_with(|| serde_json::json!({}));
|
||||
if !llm.is_object() {
|
||||
*llm = serde_json::json!({});
|
||||
}
|
||||
llm.as_object_mut()
|
||||
.expect("test config LLM value must be an object")
|
||||
.entry("stream")
|
||||
.or_insert_with(|| serde_json::json!(false));
|
||||
}
|
||||
serde_json::to_vec_pretty(&config).expect("serialize explicit Provider test config")
|
||||
}
|
||||
@@ -1243,6 +1251,27 @@ pub(crate) fn write_test_local_config(content: String) -> TestConfigGuard {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_local_config_defaults_mock_provider_to_non_streaming_and_preserves_explicit_stream() {
|
||||
let guard =
|
||||
write_test_local_config(r#"{"agentMode":"codex_cli","llm":{"stream":true}}"#.to_string());
|
||||
let explicit_stream = serde_json::from_slice::<serde_json::Value>(
|
||||
&fs::read(test_local_config_path()).expect("read explicit streaming test config"),
|
||||
)
|
||||
.expect("parse explicit streaming test config");
|
||||
assert_eq!(explicit_stream["agentMode"], "codex_cli");
|
||||
assert_eq!(explicit_stream["llm"]["stream"], true);
|
||||
drop(guard);
|
||||
|
||||
let _guard = write_test_local_config(r#"{"agentLlm":{}}"#.to_string());
|
||||
let defaulted = serde_json::from_slice::<serde_json::Value>(
|
||||
&fs::read(test_local_config_path()).expect("read defaulted mock provider test config"),
|
||||
)
|
||||
.expect("parse defaulted mock provider test config");
|
||||
assert_eq!(defaulted["agentMode"], GAME_CREATOR_AGENT_MODE_PROVIDER);
|
||||
assert_eq!(defaulted["llm"]["stream"], false);
|
||||
}
|
||||
|
||||
fn use_test_runtime_config_dir(path: PathBuf) -> TestRuntimeConfigDirGuard {
|
||||
let lock = TEST_CONFIG_LOCK
|
||||
.lock()
|
||||
@@ -3103,17 +3132,23 @@ fn spawn_mock_external_canvas_api_server_with_capture_and_generation_gate(
|
||||
let normalized_request = request.to_ascii_lowercase();
|
||||
let (status, content_type, body) = if request
|
||||
.starts_with("GET /api/external/v1/editor/projects ")
|
||||
|| request.starts_with("GET /api/editor/projects ")
|
||||
{
|
||||
assert!(normalized_request.contains("authorization: bearer "));
|
||||
("200 OK", "application/json", projects_body.as_bytes().to_vec())
|
||||
} else if request.starts_with("GET /api/external/v1/editor/assets/library ") {
|
||||
} else if request.starts_with("GET /api/external/v1/editor/assets/library ")
|
||||
|| request.starts_with("GET /api/editor/assets/library ")
|
||||
{
|
||||
assert!(normalized_request.contains("authorization: bearer "));
|
||||
("200 OK", "application/json", library_body.as_bytes().to_vec())
|
||||
} else if request.starts_with("GET /api/external/v1/editor/projects/canvas-project-1 ")
|
||||
|| request.starts_with("GET /api/editor/projects/canvas-project-1 ")
|
||||
{
|
||||
assert!(normalized_request.contains("authorization: bearer "));
|
||||
("200 OK", "application/json", project_body.as_bytes().to_vec())
|
||||
} else if request.starts_with("POST /api/external/v1/editor/images/generations ") {
|
||||
} else if request.starts_with("POST /api/external/v1/editor/images/generations ")
|
||||
|| request.starts_with("POST /api/editor/images/generations ")
|
||||
{
|
||||
assert!(normalized_request.contains("authorization: bearer "));
|
||||
let idempotency_key = request
|
||||
.lines()
|
||||
@@ -3134,6 +3169,7 @@ fn spawn_mock_external_canvas_api_server_with_capture_and_generation_gate(
|
||||
)
|
||||
} else if request
|
||||
.starts_with("POST /api/external/v1/editor/icon-spritesheets/generations ")
|
||||
|| request.starts_with("POST /api/editor/icon-spritesheets/generations ")
|
||||
{
|
||||
assert!(normalized_request.contains("authorization: bearer "));
|
||||
let idempotency_key = request
|
||||
@@ -3155,6 +3191,8 @@ fn spawn_mock_external_canvas_api_server_with_capture_and_generation_gate(
|
||||
)
|
||||
} else if request.starts_with(
|
||||
"GET /api/external/v1/generations/task-external-fixture-1 ",
|
||||
) || request.starts_with(
|
||||
"GET /api/runtime/external-generation/jobs/task-external-fixture-1 ",
|
||||
) {
|
||||
assert!(normalized_request.contains("authorization: bearer "));
|
||||
if let Some(gate) = generation_response_gate.take() {
|
||||
@@ -3196,11 +3234,15 @@ fn spawn_mock_external_canvas_api_server_with_capture_and_generation_gate(
|
||||
)
|
||||
} else if request.starts_with(
|
||||
"GET /api/external/v1/assets/read-url?objectKey=generated%2Fcanvas%2Fhero.png ",
|
||||
) || request.starts_with(
|
||||
"GET /api/assets/read-url?objectKey=generated%2Fcanvas%2Fhero.png ",
|
||||
) {
|
||||
assert!(normalized_request.contains("authorization: bearer "));
|
||||
("200 OK", "application/json", read_body.as_bytes().to_vec())
|
||||
} else if request.starts_with(
|
||||
"GET /api/external/v1/assets/read-url?objectKey=generated%2Fcanvas%2Fspritesheet.png ",
|
||||
) || request.starts_with(
|
||||
"GET /api/assets/read-url?objectKey=generated%2Fcanvas%2Fspritesheet.png ",
|
||||
) {
|
||||
assert!(normalized_request.contains("authorization: bearer "));
|
||||
(
|
||||
@@ -3211,6 +3253,8 @@ fn spawn_mock_external_canvas_api_server_with_capture_and_generation_gate(
|
||||
} else if let Some(index) = (0..4).find(|index| {
|
||||
request.starts_with(&format!(
|
||||
"GET /api/external/v1/assets/read-url?objectKey=generated%2Fcanvas%2Fspritesheet-slice-{index}.png "
|
||||
)) || request.starts_with(&format!(
|
||||
"GET /api/assets/read-url?objectKey=generated%2Fcanvas%2Fspritesheet-slice-{index}.png "
|
||||
))
|
||||
}) {
|
||||
assert!(normalized_request.contains("authorization: bearer "));
|
||||
@@ -3285,7 +3329,10 @@ fn spawn_mock_external_canvas_generation_failure_server() -> String {
|
||||
.contains("authorization: bearer "));
|
||||
let (status, body) = match index {
|
||||
0 => {
|
||||
assert!(request.starts_with("GET /api/external/v1/editor/projects "));
|
||||
assert!(
|
||||
request.starts_with("GET /api/external/v1/editor/projects ")
|
||||
|| request.starts_with("GET /api/editor/projects ")
|
||||
);
|
||||
(
|
||||
"200 OK",
|
||||
serde_json::json!({
|
||||
@@ -3298,7 +3345,10 @@ fn spawn_mock_external_canvas_generation_failure_server() -> String {
|
||||
)
|
||||
}
|
||||
1 => {
|
||||
assert!(request.starts_with("GET /api/external/v1/editor/assets/library "));
|
||||
assert!(
|
||||
request.starts_with("GET /api/external/v1/editor/assets/library ")
|
||||
|| request.starts_with("GET /api/editor/assets/library ")
|
||||
);
|
||||
(
|
||||
"200 OK",
|
||||
serde_json::json!({
|
||||
@@ -3311,7 +3361,10 @@ fn spawn_mock_external_canvas_generation_failure_server() -> String {
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
assert!(request.starts_with("POST /api/external/v1/editor/images/generations "));
|
||||
assert!(
|
||||
request.starts_with("POST /api/external/v1/editor/images/generations ")
|
||||
|| request.starts_with("POST /api/editor/images/generations ")
|
||||
);
|
||||
(
|
||||
"500 Internal Server Error",
|
||||
"{\"error\":\"generation failed\"}".to_string(),
|
||||
|
||||
@@ -651,6 +651,11 @@ async fn background_agent_runtime_can_generate_platform_art_asset() {
|
||||
let config_dir = unique_project_path();
|
||||
let (canvas_sender, canvas_receiver) = mpsc::channel();
|
||||
let canvas_base_url = spawn_mock_external_canvas_generation_api_server(Some(canvas_sender));
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"background-art-user",
|
||||
"editor-runtime-key",
|
||||
&canvas_base_url,
|
||||
);
|
||||
init_local_game_project_at(&root, "project-1", "月光厨房").expect("project init");
|
||||
register_canvas_visual_asset_fixture(&root, "assets/art-spec.png", "icon-spec");
|
||||
write_project_permission_policy_at(
|
||||
@@ -688,6 +693,7 @@ async fn background_agent_runtime_can_generate_platform_art_asset() {
|
||||
config_dir.join(GAME_CREATOR_CONFIG_FILE_NAME),
|
||||
serde_json::json!({
|
||||
"agentMode": "provider",
|
||||
"llm": { "stream": false },
|
||||
"editorApi": {
|
||||
"baseUrl": canvas_base_url,
|
||||
"apiKey": "editor-runtime-key"
|
||||
@@ -835,14 +841,12 @@ async fn background_agent_runtime_can_generate_platform_art_asset() {
|
||||
.collect::<Vec<_>>();
|
||||
let generation_request = canvas_requests
|
||||
.iter()
|
||||
.find(|request| {
|
||||
request.starts_with("POST /api/external/v1/editor/icon-spritesheets/generations ")
|
||||
})
|
||||
.find(|request| request.starts_with("POST /api/editor/icon-spritesheets/generations "))
|
||||
.expect("canvas generation request");
|
||||
assert_eq!(
|
||||
canvas_requests
|
||||
.iter()
|
||||
.filter(|request| request.starts_with("POST /api/external/v1/editor/"))
|
||||
.filter(|request| request.starts_with("POST /api/editor/"))
|
||||
.count(),
|
||||
1,
|
||||
"queued/running polling must not submit generation again"
|
||||
@@ -850,7 +854,7 @@ async fn background_agent_runtime_can_generate_platform_art_asset() {
|
||||
assert_eq!(
|
||||
canvas_requests
|
||||
.iter()
|
||||
.filter(|request| request.starts_with("GET /api/external/v1/generations/"))
|
||||
.filter(|request| request.starts_with("GET /api/runtime/external-generation/jobs/"))
|
||||
.count(),
|
||||
3,
|
||||
"fixture should exercise queued, running, and completed states"
|
||||
@@ -889,6 +893,11 @@ async fn canonical_art_spec_and_ui_requests_use_the_shared_reference_chain() {
|
||||
let (request_sender, request_receiver) = mpsc::channel();
|
||||
let canvas_base_url =
|
||||
spawn_mock_external_canvas_generation_api_server(Some(request_sender));
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"canonical-art-user",
|
||||
"editor-runtime-key",
|
||||
&canvas_base_url,
|
||||
);
|
||||
fs::create_dir_all(config_dir).expect("create runtime config dir");
|
||||
fs::write(
|
||||
config_dir.join(GAME_CREATOR_CONFIG_FILE_NAME),
|
||||
@@ -938,7 +947,7 @@ async fn canonical_art_spec_and_ui_requests_use_the_shared_reference_chain() {
|
||||
},
|
||||
)
|
||||
.await;
|
||||
assert!(spec_request.starts_with("POST /api/external/v1/editor/images/generations "));
|
||||
assert!(spec_request.starts_with("POST /api/editor/images/generations "));
|
||||
assert!(spec_request.contains(r#""kind":"spec""#));
|
||||
assert!(spec_request.contains(r#""assetKind":"icon-spec""#));
|
||||
assert!(spec_request.contains(r#""referenceImageSrcs":[]"#));
|
||||
@@ -958,7 +967,7 @@ async fn canonical_art_spec_and_ui_requests_use_the_shared_reference_chain() {
|
||||
},
|
||||
)
|
||||
.await;
|
||||
assert!(ui_request.starts_with("POST /api/external/v1/editor/images/generations "));
|
||||
assert!(ui_request.starts_with("POST /api/editor/images/generations "));
|
||||
assert!(ui_request.contains(r#""kind":"ui-design""#));
|
||||
assert!(ui_request.contains(r#""referenceImageSrcs":["resource-icon-spec"]"#));
|
||||
|
||||
@@ -977,6 +986,11 @@ async fn platform_art_external_request_does_not_hold_project_lock_or_overwrite_m
|
||||
request_sender,
|
||||
generation_release_receiver,
|
||||
);
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"project-lock-art-user",
|
||||
"editor-runtime-key",
|
||||
&canvas_base_url,
|
||||
);
|
||||
init_local_game_project_at(&root, "project-canvas-request-lock", "月光厨房")
|
||||
.expect("project init");
|
||||
register_canvas_visual_asset_fixture(&root, "assets/art-spec.png", "icon-spec");
|
||||
@@ -1025,7 +1039,7 @@ async fn platform_art_external_request_does_not_hold_project_lock_or_overwrite_m
|
||||
let captured = request_receiver
|
||||
.recv_timeout(Duration::from_secs(15))
|
||||
.expect("canvas request before generation response");
|
||||
if captured.starts_with("POST /api/external/v1/editor/icon-spritesheets/generations ") {
|
||||
if captured.starts_with("POST /api/editor/icon-spritesheets/generations ") {
|
||||
saw_generation_request = true;
|
||||
break;
|
||||
}
|
||||
@@ -1871,6 +1885,11 @@ fn import_canvas_export_zip_copies_files_and_registers_assets() {
|
||||
async fn sync_canvas_project_assets_downloads_external_resources() {
|
||||
let root = unique_project_path();
|
||||
let base_url = spawn_mock_external_canvas_api_server();
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"canvas-sync-user",
|
||||
"test-editor-api-key",
|
||||
&base_url,
|
||||
);
|
||||
|
||||
let result = sync_canvas_project_assets_at(
|
||||
&root,
|
||||
@@ -1918,6 +1937,11 @@ async fn generate_platform_art_asset_downloads_and_registers_external_image() {
|
||||
let root = unique_project_path();
|
||||
let config_dir = unique_project_path();
|
||||
let base_url = spawn_mock_external_canvas_generation_api_server(None);
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"platform-art-user",
|
||||
"editor-unit-key",
|
||||
&base_url,
|
||||
);
|
||||
init_local_game_project_at(&root, "project-platform-art", "未命名游戏原型")
|
||||
.expect("project init");
|
||||
fs::create_dir_all(&config_dir).expect("runtime config dir");
|
||||
@@ -1998,6 +2022,11 @@ async fn platform_art_generation_step_falls_back_without_leaking_editor_key() {
|
||||
.expect("project init");
|
||||
let config_dir = unique_project_path();
|
||||
let base_url = spawn_mock_external_canvas_generation_failure_server();
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"platform-art-fallback-user",
|
||||
"editor-fallback-secret",
|
||||
&base_url,
|
||||
);
|
||||
fs::create_dir_all(&config_dir).expect("runtime config dir");
|
||||
fs::write(
|
||||
config_dir.join(GAME_CREATOR_CONFIG_FILE_NAME),
|
||||
|
||||
@@ -6729,6 +6729,7 @@ async fn agent_loop_writes_spec_findings_and_retries_generator() {
|
||||
api_key: "test-key".to_string(),
|
||||
base_url,
|
||||
model: "mock-game-model".to_string(),
|
||||
stream: false,
|
||||
..GameCreatorLlmConfig::default()
|
||||
},
|
||||
..GameCreatorAppConfig::default()
|
||||
|
||||
@@ -982,6 +982,11 @@ async fn provider_retry_final_reply_thinking_only_response_retries_before_handof
|
||||
|
||||
#[test]
|
||||
fn visual_specialist_finalization_requires_existing_registered_canvas_image() {
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"visual-finalization-test-user",
|
||||
"visual-finalization-test-key",
|
||||
"https://dev.genarrative.world",
|
||||
);
|
||||
let _config_guard = crate::tests::write_test_local_config(
|
||||
r#"{"editorApi":{"apiKey":"visual-finalization-test-key"}}"#.to_string(),
|
||||
);
|
||||
|
||||
@@ -2184,6 +2184,11 @@ fn static_smoke_failure_receipt_round_trips_owner_diagnostic_from_agent_db() {
|
||||
|
||||
#[test]
|
||||
fn seed_refresh_downgrades_completed_visual_tasks_when_registered_file_is_missing() {
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"visual-seed-refresh-test-user",
|
||||
"visual-seed-refresh-test-key",
|
||||
"https://dev.genarrative.world",
|
||||
);
|
||||
let _config_guard = crate::tests::write_test_local_config(
|
||||
r#"{"editorApi":{"apiKey":"visual-seed-refresh-test-key"}}"#.to_string(),
|
||||
);
|
||||
|
||||
+5
-1
@@ -467,7 +467,11 @@ fn autonomous_visual_gate_degrades_to_text_without_key_and_requires_images_with_
|
||||
Some(&GameCreationAppTaskStatus::Completed)
|
||||
);
|
||||
|
||||
write_autonomous_editor_api_config_for_test(&config_dir, "editor-runtime-test-key");
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"autonomous-visual-gate-test-user",
|
||||
"autonomous-visual-gate-test-key",
|
||||
"https://dev.genarrative.world",
|
||||
);
|
||||
let with_key_missing_images = autonomous_seed_task_statuses_for_test(&root);
|
||||
assert_eq!(
|
||||
with_key_missing_images.get("art-director"),
|
||||
|
||||
@@ -3851,6 +3851,11 @@ async fn background_task_recovers_when_assistant_message_cannot_persist() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn task_update_requires_registered_visual_asset_before_completion() {
|
||||
let _platform_session = crate::platform_session::install_test_platform_session(
|
||||
"visual-task-update-test-user",
|
||||
"visual-task-update-test-key",
|
||||
"https://dev.genarrative.world",
|
||||
);
|
||||
let _config_guard = crate::tests::write_test_local_config(
|
||||
r#"{"editorApi":{"apiKey":"visual-task-update-test-key"}}"#.to_string(),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user