阶段5:完成账号态与 External 态语义回归
新增账号态主站路径、标记、Bearer、幂等键和异步轮询回归断言。 新增 External Key 态自定义 apiBaseUrl 与 External v1 路径请求捕获测试。 锁定 generationInputs.source、单次提交和结果未知不重试语义。 更新 Issue 226 实施方案与分阶段验收计划,记录阶段 5 完成。
This commit is contained in:
@@ -993,6 +993,37 @@ async fn background_agent_runtime_can_generate_platform_art_asset() {
|
||||
.iter()
|
||||
.find(|request| request.starts_with("POST /api/editor/icon-spritesheets/generations "))
|
||||
.expect("canvas generation request");
|
||||
let request_header = |request: &str, expected_name: &str| {
|
||||
request.lines().find_map(|line| {
|
||||
let (name, value) = line.split_once(':')?;
|
||||
name.eq_ignore_ascii_case(expected_name)
|
||||
.then(|| value.trim().to_string())
|
||||
})
|
||||
};
|
||||
let main_site_requests = canvas_requests
|
||||
.iter()
|
||||
.filter(|request| {
|
||||
request.starts_with("GET /api/editor/")
|
||||
|| request.starts_with("POST /api/editor/")
|
||||
|| request.starts_with("GET /api/assets/")
|
||||
|| request.starts_with("POST /api/assets/")
|
||||
|| request.starts_with("GET /api/runtime/")
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
assert!(!main_site_requests.is_empty());
|
||||
assert!(main_site_requests.iter().all(|request| {
|
||||
request
|
||||
.to_ascii_lowercase()
|
||||
.contains("x-genarrative-client: agc")
|
||||
}));
|
||||
assert_eq!(
|
||||
request_header(generation_request, "authorization"),
|
||||
Some("Bearer editor-runtime-key".to_string())
|
||||
);
|
||||
let generation_idempotency_key =
|
||||
request_header(generation_request, "idempotency-key").expect("generation idempotency key");
|
||||
assert!(uuid::Uuid::parse_str(&generation_idempotency_key).is_ok());
|
||||
assert!(generation_request.contains(r#""source":"ai-game-creator-client""#));
|
||||
assert_eq!(
|
||||
canvas_requests
|
||||
.iter()
|
||||
@@ -1011,6 +1042,14 @@ async fn background_agent_runtime_can_generate_platform_art_asset() {
|
||||
3,
|
||||
"fixture should exercise queued, running, and completed states"
|
||||
);
|
||||
assert!(canvas_requests
|
||||
.iter()
|
||||
.filter(|request| request.starts_with("GET /api/runtime/external-generation/jobs/"))
|
||||
.all(|request| {
|
||||
request
|
||||
.to_ascii_lowercase()
|
||||
.contains("x-genarrative-client: agc")
|
||||
}));
|
||||
for expected in [
|
||||
r#""referenceId":"resource-icon-spec""#,
|
||||
r#""iconDescriptions":"#,
|
||||
@@ -2121,6 +2160,55 @@ async fn sync_canvas_project_assets_downloads_external_resources() {
|
||||
fs::remove_dir_all(root).ok();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn sync_canvas_project_assets_with_developer_key_uses_external_route_and_marker() {
|
||||
let _platform_session = crate::platform_session::clear_test_platform_session();
|
||||
let root = unique_project_path();
|
||||
let (request_sender, request_receiver) = mpsc::channel();
|
||||
let base_url = spawn_mock_external_canvas_api_server_with_capture(3, Some(request_sender));
|
||||
let api_key = "tnr_sk_phase5_fixture";
|
||||
let result = crate::assets::with_external_editor_api_credentials(
|
||||
crate::assets::external_editor_api_credentials_for_test(
|
||||
base_url.clone(),
|
||||
api_key.to_string(),
|
||||
),
|
||||
sync_canvas_project_assets_at(
|
||||
&root,
|
||||
"canvas-project-1",
|
||||
Some(base_url.clone()),
|
||||
Some(api_key.to_string()),
|
||||
),
|
||||
)
|
||||
.await
|
||||
.expect("developer key canvas project sync");
|
||||
|
||||
assert_eq!(result.canvas_project_id, "canvas-project-1");
|
||||
let requests = request_receiver.try_iter().collect::<Vec<_>>();
|
||||
assert_eq!(requests.len(), 3);
|
||||
let project_request = requests
|
||||
.iter()
|
||||
.find(|request| request.starts_with("GET /api/external/v1/editor/projects/"))
|
||||
.expect("External v1 project request");
|
||||
let read_url_request = requests
|
||||
.iter()
|
||||
.find(|request| request.starts_with("GET /api/external/v1/assets/read-url?"))
|
||||
.expect("External v1 read URL request");
|
||||
for request in [project_request, read_url_request] {
|
||||
let normalized = request.to_ascii_lowercase();
|
||||
assert!(normalized.contains("x-genarrative-client: agc"));
|
||||
assert!(normalized.contains("authorization: bearer tnr_sk_phase5_fixture"));
|
||||
}
|
||||
let signed_download = requests
|
||||
.iter()
|
||||
.find(|request| request.starts_with("GET /signed/"))
|
||||
.expect("signed media download request");
|
||||
assert!(!signed_download
|
||||
.to_ascii_lowercase()
|
||||
.contains("x-genarrative-client:"));
|
||||
|
||||
fs::remove_dir_all(root).ok();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn generate_platform_art_asset_downloads_and_registers_external_image() {
|
||||
let root = unique_project_path();
|
||||
|
||||
Reference in New Issue
Block a user