Spaces:
Paused
Paused
Download api/tests/e2e_settings.rs from stremio-db/a: direct link, hf CLI and curl.
- Browser
- Download file 25.1 kB
-
https://huggingface.co/spaces/stremio-db/a/resolve/main/api/tests/e2e_settings.rs
- Command line
-
hf download hf://spaces/stremio-db/a/api/tests/e2e_settings.rs
-
curl -L -o e2e_settings.rs https://huggingface.co/spaces/stremio-db/a/resolve/main/api/tests/e2e_settings.rs
25.1 kB
| mod common; | |
| use axum::body::Body; | |
| use axum::http::{Request, StatusCode}; | |
| use http_body_util::BodyExt; | |
| use serde_json::{json, Value}; | |
| use tower::ServiceExt; | |
| fn authed_request(method: &str, uri: &str, token: &str, body: Option<Value>) -> Request<Body> { | |
| let mut builder = Request::builder() | |
| .method(method) | |
| .uri(uri) | |
| .header("authorization", format!("Bearer {token}")) | |
| .header("content-type", "application/json"); | |
| match body { | |
| Some(b) => builder.body(Body::from(b.to_string())).unwrap(), | |
| None => builder.body(Body::empty()).unwrap(), | |
| } | |
| } | |
| async fn parse_json(res: axum::http::Response<Body>) -> Value { | |
| let body = res.into_body().collect().await.unwrap().to_bytes(); | |
| serde_json::from_slice(&body).unwrap() | |
| } | |
| async fn create_api_key(app: &axum::Router, token: &str) -> (i32, String) { | |
| let req = authed_request("POST", "/api/keys", token, Some(json!({"name":"e2e-test"}))); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let json = parse_json(res).await; | |
| (json["id"].as_i64().unwrap() as i32, json["key"].as_str().unwrap().to_string()) | |
| } | |
| // --- Auth enforcement --- | |
| async fn global_settings_get_requires_auth() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let req = Request::builder() | |
| .uri("/api/admin/settings") | |
| .body(Body::empty()) | |
| .unwrap(); | |
| let res = app.oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::UNAUTHORIZED); | |
| } | |
| async fn global_settings_put_requires_auth() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let req = Request::builder() | |
| .method("PUT") | |
| .uri("/api/admin/settings") | |
| .header("content-type", "application/json") | |
| .body(Body::from(json!({"image_source": "t"}).to_string())) | |
| .unwrap(); | |
| let res = app.oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::UNAUTHORIZED); | |
| } | |
| async fn per_key_settings_endpoints_require_auth() { | |
| let (app, _state) = common::setup_test_app().await; | |
| for (method, uri) in [ | |
| ("GET", "/api/keys/1/settings"), | |
| ("PUT", "/api/keys/1/settings"), | |
| ("DELETE", "/api/keys/1/settings"), | |
| ] { | |
| let body = if method == "PUT" { | |
| Body::from(json!({"image_source": "t"}).to_string()) | |
| } else { | |
| Body::empty() | |
| }; | |
| let mut builder = Request::builder().method(method).uri(uri); | |
| if method == "PUT" { | |
| builder = builder.header("content-type", "application/json"); | |
| } | |
| let req = builder.body(body).unwrap(); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!( | |
| res.status(), | |
| StatusCode::UNAUTHORIZED, | |
| "{method} {uri} should require admin auth" | |
| ); | |
| } | |
| } | |
| async fn self_service_settings_endpoints_require_auth() { | |
| let (app, _state) = common::setup_test_app().await; | |
| for (method, uri) in [ | |
| ("GET", "/api/key/me/settings"), | |
| ("PUT", "/api/key/me/settings"), | |
| ("DELETE", "/api/key/me/settings"), | |
| ] { | |
| let body = if method == "PUT" { | |
| Body::from(json!({"image_source": "t"}).to_string()) | |
| } else { | |
| Body::empty() | |
| }; | |
| let mut builder = Request::builder().method(method).uri(uri); | |
| if method == "PUT" { | |
| builder = builder.header("content-type", "application/json"); | |
| } | |
| let req = builder.body(body).unwrap(); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!( | |
| res.status(), | |
| StatusCode::UNAUTHORIZED, | |
| "{method} {uri} should require API key auth" | |
| ); | |
| } | |
| } | |
| // --- Cross-key isolation via admin endpoints --- | |
| async fn per_key_settings_are_isolated_between_keys() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| // Create two API keys | |
| let (key_a_id, _) = create_api_key(&app, &token).await; | |
| let (key_b_id, _) = create_api_key(&app, &token).await; | |
| // Customize key A's settings | |
| let update = json!({ | |
| "image_source": "f", | |
| "lang": "ja", | |
| "ratings_limit": 1, | |
| "ratings_order": "imdb", | |
| }); | |
| let req = authed_request("PUT", &format!("/api/keys/{key_a_id}/settings"), &token, Some(update)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| // Key B should still have defaults | |
| let req = authed_request("GET", &format!("/api/keys/{key_b_id}/settings"), &token, None); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let settings = parse_json(res).await; | |
| assert_eq!(settings["is_default"], true, "key B should not be affected by key A's settings"); | |
| assert_eq!(settings["image_source"], "t"); | |
| // Key A should have its custom settings | |
| let req = authed_request("GET", &format!("/api/keys/{key_a_id}/settings"), &token, None); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let settings = parse_json(res).await; | |
| assert_eq!(settings["is_default"], false); | |
| assert_eq!(settings["image_source"], "f"); | |
| assert_eq!(settings["lang"], "ja"); | |
| } | |
| // --- Global settings round-trip --- | |
| async fn global_settings_round_trip_all_fields() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| // Update global settings with non-default values | |
| let update = json!({ | |
| "image_source": "f", | |
| "lang": "de", | |
| "textless": true, | |
| "ratings_limit": 5, | |
| "ratings_order": "imdb,rt,mc,tmdb,trakt,mal,lb,rta", | |
| "ratings_exclude": "rt,mc", | |
| "poster_position": "tl", | |
| "logo_ratings_limit": 2, | |
| "backdrop_ratings_limit": 7, | |
| "poster_badge_style": "v", | |
| "logo_badge_style": "h", | |
| "backdrop_badge_style": "h", | |
| "poster_label_style": "t", | |
| "logo_label_style": "i", | |
| "backdrop_label_style": "o", | |
| "poster_badge_direction": "h", | |
| "poster_badge_size": "xl", | |
| "logo_badge_size": "xs", | |
| "backdrop_badge_size": "l", | |
| }); | |
| let req = authed_request("PUT", "/api/admin/settings", &token, Some(update.clone())); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| // Read them back | |
| let req = authed_request("GET", "/api/admin/settings", &token, None); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let settings = parse_json(res).await; | |
| assert_eq!(settings["image_source"], "f"); | |
| assert_eq!(settings["lang"], "de"); | |
| assert_eq!(settings["textless"], true); | |
| assert_eq!(settings["ratings_limit"], 5); | |
| assert_eq!(settings["ratings_order"], "imdb,rt,mc,tmdb,trakt,mal,lb,rta"); | |
| assert_eq!(settings["ratings_exclude"], "rt,mc"); | |
| assert_eq!(settings["poster_position"], "tl"); | |
| assert_eq!(settings["logo_ratings_limit"], 2); | |
| assert_eq!(settings["backdrop_ratings_limit"], 7); | |
| assert_eq!(settings["poster_badge_style"], "v"); | |
| assert_eq!(settings["logo_badge_style"], "h"); | |
| assert_eq!(settings["backdrop_badge_style"], "h"); | |
| assert_eq!(settings["poster_label_style"], "t"); | |
| assert_eq!(settings["logo_label_style"], "i"); | |
| assert_eq!(settings["backdrop_label_style"], "o"); | |
| assert_eq!(settings["poster_badge_direction"], "h"); | |
| assert_eq!(settings["poster_badge_size"], "xl"); | |
| assert_eq!(settings["logo_badge_size"], "xs"); | |
| assert_eq!(settings["backdrop_badge_size"], "l"); | |
| } | |
| // --- Per-key settings round-trip --- | |
| async fn per_key_settings_round_trip() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let (key_id, _raw_key) = create_api_key(&app, &token).await; | |
| // Read defaults (should be global/default) | |
| let req = authed_request("GET", &format!("/api/keys/{key_id}/settings"), &token, None); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let defaults = parse_json(res).await; | |
| assert_eq!(defaults["is_default"], true); | |
| assert_eq!(defaults["poster_badge_size"], "m"); | |
| // Set per-key overrides | |
| let update = json!({ | |
| "image_source": "t", | |
| "ratings_limit": 1, | |
| "ratings_order": "tmdb", | |
| "ratings_exclude": "lb,mal", | |
| "poster_position": "r", | |
| "logo_ratings_limit": 4, | |
| "backdrop_ratings_limit": 6, | |
| "poster_badge_style": "h", | |
| "logo_badge_style": "v", | |
| "backdrop_badge_style": "v", | |
| "poster_label_style": "o", | |
| "logo_label_style": "o", | |
| "backdrop_label_style": "t", | |
| "poster_badge_direction": "v", | |
| "poster_badge_size": "s", | |
| "logo_badge_size": "l", | |
| "backdrop_badge_size": "xl", | |
| }); | |
| let req = authed_request("PUT", &format!("/api/keys/{key_id}/settings"), &token, Some(update)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| // Read back — should reflect per-key values | |
| let req = authed_request("GET", &format!("/api/keys/{key_id}/settings"), &token, None); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let settings = parse_json(res).await; | |
| assert_eq!(settings["is_default"], false); | |
| assert_eq!(settings["ratings_limit"], 1); | |
| assert_eq!(settings["ratings_exclude"], "lb,mal"); | |
| assert_eq!(settings["poster_position"], "r"); | |
| assert_eq!(settings["poster_badge_style"], "h"); | |
| assert_eq!(settings["logo_badge_style"], "v"); | |
| assert_eq!(settings["poster_label_style"], "o"); | |
| assert_eq!(settings["poster_badge_direction"], "v"); | |
| assert_eq!(settings["poster_badge_size"], "s"); | |
| assert_eq!(settings["logo_badge_size"], "l"); | |
| assert_eq!(settings["backdrop_badge_size"], "xl"); | |
| assert_eq!(settings["logo_ratings_limit"], 4); | |
| assert_eq!(settings["backdrop_ratings_limit"], 6); | |
| } | |
| // --- Per-key reset falls back to global --- | |
| async fn per_key_reset_falls_back_to_global() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let (key_id, _raw_key) = create_api_key(&app, &token).await; | |
| // Set global to something non-default | |
| let global = json!({ | |
| "image_source": "f", | |
| "ratings_limit": 7, | |
| "ratings_order": "rt,imdb", | |
| "poster_position": "bl", | |
| "poster_badge_style": "v", | |
| }); | |
| let req = authed_request("PUT", "/api/admin/settings", &token, Some(global)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| // Set per-key override | |
| let per_key = json!({ | |
| "image_source": "t", | |
| "ratings_limit": 2, | |
| "ratings_order": "tmdb", | |
| "poster_badge_style": "h", | |
| }); | |
| let req = authed_request("PUT", &format!("/api/keys/{key_id}/settings"), &token, Some(per_key)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| // Delete per-key settings | |
| let req = authed_request("DELETE", &format!("/api/keys/{key_id}/settings"), &token, None); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| // Invalidate settings cache to force fresh load | |
| _state.settings_cache.invalidate(&key_id).await; | |
| // Read back — should reflect global values | |
| let req = authed_request("GET", &format!("/api/keys/{key_id}/settings"), &token, None); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let settings = parse_json(res).await; | |
| assert_eq!(settings["is_default"], true); | |
| assert_eq!(settings["image_source"], "f"); | |
| assert_eq!(settings["ratings_limit"], 7); | |
| assert_eq!(settings["poster_position"], "bl"); | |
| assert_eq!(settings["poster_badge_style"], "v"); | |
| } | |
| // --- Self-service settings round-trip --- | |
| async fn self_service_settings_round_trip() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let api_key_token = common::setup_api_key_session(&app).await; | |
| // Read defaults | |
| let req = Request::builder() | |
| .uri("/api/key/me/settings") | |
| .header("authorization", format!("Bearer {api_key_token}")) | |
| .body(Body::empty()) | |
| .unwrap(); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let defaults = parse_json(res).await; | |
| assert_eq!(defaults["is_default"], true); | |
| // Update own settings | |
| let update = json!({ | |
| "image_source": "t", | |
| "ratings_limit": 4, | |
| "ratings_order": "imdb,tmdb,rt,mc", | |
| "poster_position": "tc", | |
| "poster_badge_style": "h", | |
| "logo_badge_style": "h", | |
| "backdrop_badge_style": "h", | |
| "poster_label_style": "t", | |
| "logo_label_style": "t", | |
| "backdrop_label_style": "t", | |
| "poster_badge_direction": "h", | |
| "poster_badge_size": "l", | |
| "logo_badge_size": "s", | |
| "backdrop_badge_size": "xs", | |
| }); | |
| let req = Request::builder() | |
| .method("PUT") | |
| .uri("/api/key/me/settings") | |
| .header("authorization", format!("Bearer {api_key_token}")) | |
| .header("content-type", "application/json") | |
| .body(Body::from(update.to_string())) | |
| .unwrap(); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| // Read back | |
| let req = Request::builder() | |
| .uri("/api/key/me/settings") | |
| .header("authorization", format!("Bearer {api_key_token}")) | |
| .body(Body::empty()) | |
| .unwrap(); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let settings = parse_json(res).await; | |
| assert_eq!(settings["is_default"], false); | |
| assert_eq!(settings["ratings_limit"], 4); | |
| assert_eq!(settings["poster_position"], "tc"); | |
| assert_eq!(settings["poster_badge_style"], "h"); | |
| assert_eq!(settings["poster_badge_direction"], "h"); | |
| assert_eq!(settings["poster_badge_size"], "l"); | |
| assert_eq!(settings["logo_badge_size"], "s"); | |
| assert_eq!(settings["backdrop_badge_size"], "xs"); | |
| // Reset own settings | |
| let req = Request::builder() | |
| .method("DELETE") | |
| .uri("/api/key/me/settings") | |
| .header("authorization", format!("Bearer {api_key_token}")) | |
| .body(Body::empty()) | |
| .unwrap(); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| // Invalidate cache | |
| _state.settings_cache.invalidate_all(); | |
| // Read back — should be defaults again | |
| let req = Request::builder() | |
| .uri("/api/key/me/settings") | |
| .header("authorization", format!("Bearer {api_key_token}")) | |
| .body(Body::empty()) | |
| .unwrap(); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| let settings = parse_json(res).await; | |
| assert_eq!(settings["is_default"], true); | |
| } | |
| // --- Validation: global settings rejects invalid values --- | |
| async fn global_settings_rejects_invalid_ratings_limit() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let update = json!({ | |
| "image_source": "t", | |
| "ratings_limit": 11, | |
| }); | |
| let req = authed_request("PUT", "/api/admin/settings", &token, Some(update)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::BAD_REQUEST); | |
| } | |
| async fn global_settings_rejects_invalid_lang() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let update = json!({ | |
| "image_source": "t", | |
| "lang": "x", | |
| }); | |
| let req = authed_request("PUT", "/api/admin/settings", &token, Some(update)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::BAD_REQUEST); | |
| } | |
| async fn global_settings_rejects_invalid_ratings_order() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let update = json!({ | |
| "image_source": "t", | |
| "ratings_order": "bogus", | |
| }); | |
| let req = authed_request("PUT", "/api/admin/settings", &token, Some(update)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::BAD_REQUEST); | |
| } | |
| async fn global_settings_rejects_invalid_ratings_exclude() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let update = json!({ | |
| "image_source": "t", | |
| "ratings_exclude": "bogus", | |
| }); | |
| let req = authed_request("PUT", "/api/admin/settings", &token, Some(update)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::BAD_REQUEST); | |
| } | |
| async fn global_ratings_exclude_propagates_to_free_key_renders() { | |
| // A global ratings_exclude must change what the free key renders (and its | |
| // cache key), proving exclusion flows through the global settings path. | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let update = json!({ "image_source": "t", "ratings_exclude": "rt" }); | |
| let req = authed_request("PUT", "/api/admin/settings", &token, Some(update)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| // Read back via the admin GET to confirm persistence. | |
| let req = authed_request("GET", "/api/admin/settings", &token, None); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| let settings = parse_json(res).await; | |
| assert_eq!(settings["ratings_exclude"], "rt"); | |
| } | |
| async fn global_settings_rejects_invalid_badge_style() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let update = json!({ | |
| "image_source": "t", | |
| "poster_badge_style": "z", | |
| }); | |
| let req = authed_request("PUT", "/api/admin/settings", &token, Some(update)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| // Invalid enum values fail at deserialization (422) rather than validation (400) | |
| assert_eq!(res.status(), StatusCode::UNPROCESSABLE_ENTITY); | |
| } | |
| async fn per_key_settings_rejects_invalid_logo_ratings_limit() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let (key_id, _) = create_api_key(&app, &token).await; | |
| let update = json!({ | |
| "image_source": "t", | |
| "logo_ratings_limit": 11, | |
| }); | |
| let req = authed_request("PUT", &format!("/api/keys/{key_id}/settings"), &token, Some(update)); | |
| let res = app.clone().oneshot(req).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::BAD_REQUEST); | |
| } | |
| // --- Preview generates different images for different badge styles --- | |
| async fn preview_badge_style_produces_different_images() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let res_h = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/poster?ratings_limit=3&badge_style=h", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res_h.status(), StatusCode::OK); | |
| let body_h = res_h.into_body().collect().await.unwrap().to_bytes(); | |
| let res_v = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/poster?ratings_limit=3&badge_style=v", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res_v.status(), StatusCode::OK); | |
| let body_v = res_v.into_body().collect().await.unwrap().to_bytes(); | |
| // Both valid JPEGs | |
| assert_eq!(body_h[0], 0xFF); | |
| assert_eq!(body_v[0], 0xFF); | |
| // Different badge styles should produce different images | |
| assert_ne!(body_h, body_v); | |
| } | |
| async fn preview_label_style_produces_different_images() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let res_text = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/poster?ratings_limit=3&label_style=t", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res_text.status(), StatusCode::OK); | |
| let body_text = res_text.into_body().collect().await.unwrap().to_bytes(); | |
| let res_icon = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/poster?ratings_limit=3&label_style=i", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res_icon.status(), StatusCode::OK); | |
| let body_icon = res_icon.into_body().collect().await.unwrap().to_bytes(); | |
| assert_eq!(body_text[0], 0xFF); | |
| assert_eq!(body_icon[0], 0xFF); | |
| assert_ne!(body_text, body_icon); | |
| } | |
| async fn preview_badge_size_produces_different_images() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let res_s = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/poster?ratings_limit=3&badge_size=xs", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res_s.status(), StatusCode::OK); | |
| let body_s = res_s.into_body().collect().await.unwrap().to_bytes(); | |
| let res_xl = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/poster?ratings_limit=3&badge_size=xl", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res_xl.status(), StatusCode::OK); | |
| let body_xl = res_xl.into_body().collect().await.unwrap().to_bytes(); | |
| assert_eq!(body_s[0], 0xFF); | |
| assert_eq!(body_xl[0], 0xFF); | |
| assert_ne!(body_s, body_xl); | |
| } | |
| // --- Logo/Backdrop preview endpoints --- | |
| async fn preview_logo_returns_png() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let res = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/logo?ratings_limit=2&badge_style=h", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| assert_eq!(res.headers().get("content-type").unwrap(), "image/png"); | |
| let body = res.into_body().collect().await.unwrap().to_bytes(); | |
| assert!(&body[..4] == &[0x89, b'P', b'N', b'G'], "should be valid PNG"); | |
| } | |
| async fn preview_backdrop_returns_jpeg() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let res = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/backdrop?ratings_limit=2&badge_style=v", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| assert_eq!(res.headers().get("content-type").unwrap(), "image/jpeg"); | |
| let body = res.into_body().collect().await.unwrap().to_bytes(); | |
| assert_eq!(body[0], 0xFF); | |
| assert_eq!(body[1], 0xD8); | |
| } | |
| async fn preview_logo_badge_size_accepted() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let res = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/logo?badge_size=l&label_style=t", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| } | |
| async fn preview_backdrop_badge_size_accepted() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let res = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/backdrop?badge_size=xs&label_style=o", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res.status(), StatusCode::OK); | |
| } | |
| // --- E2E: Settings affect image generation --- | |
| async fn preview_reflects_badge_direction_change() { | |
| let (app, _state) = common::setup_test_app().await; | |
| let token = common::setup_admin(&app).await; | |
| let res_default = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/poster?ratings_limit=3&badge_direction=d&position=l", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res_default.status(), StatusCode::OK); | |
| let body_default = res_default.into_body().collect().await.unwrap().to_bytes(); | |
| let res_h = app.clone().oneshot( | |
| authed_request("GET", "/api/admin/preview/poster?ratings_limit=3&badge_direction=h&position=l", &token, None), | |
| ).await.unwrap(); | |
| assert_eq!(res_h.status(), StatusCode::OK); | |
| let body_h = res_h.into_body().collect().await.unwrap().to_bytes(); | |
| assert_eq!(body_default[0], 0xFF); | |
| assert_eq!(body_h[0], 0xFF); | |
| // direction=d with position=l resolves to vertical, while direction=h is horizontal — different images | |
| assert_ne!(body_default, body_h); | |
| } | |