后端:补充游玩上报端点与身份解析测试

- modules/game_distribution.rs:新增公开路由在未连接 SpacetimeDB 时可达、无需登录且 no-store 的断言
- 补 clientId 去空白/截断 128 字符与缺失 UA 回退的单测
This commit is contained in:
2026-10-03 18:25:15 +08:00
parent a5e681c0a5
commit b196c1150f
@@ -4179,4 +4179,53 @@ mod tests {
assert_eq!(generic.summary, "一款由陶泥儿创作的益智游戏");
assert_eq!(generic.category, "益智");
}
#[tokio::test]
async fn game_play_route_is_public_and_no_store_without_spacetime_connection() {
use axum::http::Request;
use tower::ServiceExt;
let app =
crate::app::build_router(AppState::new(crate::config::AppConfig::default()).unwrap());
let response = app
.oneshot(
Request::builder()
.method("POST")
.uri("/api/game-distribution/games/game_1/plays")
.header(header::CONTENT_TYPE, "application/json")
.body(Body::from(r#"{"clientId":"client-1"}"#))
.unwrap(),
)
.await
.unwrap();
// 未连接 SpacetimeDB 时公开可见性读取失败,但路由可达且不需要登录;只有确认公开后才计数。
assert_eq!(response.status(), StatusCode::BAD_GATEWAY);
assert_eq!(response.headers()[header::CACHE_CONTROL], "no-store");
}
#[test]
fn play_request_client_id_trims_limits_and_rejects_blank() {
assert_eq!(request_client_id(&Bytes::from_static(b"")), None);
assert_eq!(request_client_id(&Bytes::from_static(b"not json")), None);
assert_eq!(request_client_id(&Bytes::from_static(b"{}")), None);
assert_eq!(
request_client_id(&Bytes::from_static(br#"{"clientId":" abc "}"#)),
Some("abc".to_string())
);
assert_eq!(
request_client_id(&Bytes::from_static(br#"{"clientId":" "}"#)),
None
);
let long = "x".repeat(200);
let body = Bytes::from(format!(r#"{{"clientId":"{long}"}}"#));
assert_eq!(request_client_id(&body).unwrap().chars().count(), 128);
}
#[test]
fn play_report_user_agent_is_bounded_and_falls_back() {
assert_eq!(user_agent_tag(&HeaderMap::new()), "unknown");
let mut headers = HeaderMap::new();
headers.insert(header::USER_AGENT, " test-agent ".parse().unwrap());
assert_eq!(user_agent_tag(&headers), "test-agent");
}
}