//! WP-02: /api/jobs (run history, manual run). mod common; use axum::http::StatusCode; use common::{get, post, test_app_with_admin}; use serde_json::json; const ADMIN: &str = "admin@example.com"; const PW: &str = "admin-password-123"; #[tokio::test] async fn admin_runs_a_job_and_sees_it_in_the_list_with_log() { let app = test_app_with_admin().await; let token = common::login(&app, ADMIN, PW).await.access; let res = post( &app, "/api/jobs/run", json!({"kind": "package_refresh"}), Some(&token), ) .await; assert_eq!(res.status, StatusCode::ACCEPTED, "{}", res.json); let id = res.json["id"].as_str().unwrap().to_string(); assert_eq!(res.json["kind"], "package_refresh"); assert_eq!(res.json["triggered_by"], ADMIN); // the test handler finishes quickly let mut status = String::new(); for _ in 0..50 { let run = get(&app, &format!("/api/jobs/{id}"), Some(&token)).await; status = run.json["status"].as_str().unwrap().to_string(); if status != "running" { assert!(run.json["log"].as_str().unwrap().contains("packages")); break; } tokio::time::sleep(std::time::Duration::from_millis(20)).await; } assert_eq!(status, "success"); let list = get(&app, "/api/jobs?limit=10", Some(&token)).await; assert_eq!(list.json.as_array().unwrap().len(), 1); let kinds = get(&app, "/api/jobs/kinds", Some(&token)).await; assert!(kinds .json .as_array() .unwrap() .contains(&json!("package_refresh"))); } #[tokio::test] async fn unknown_kind_is_404_and_run_is_admin_only() { let app = test_app_with_admin().await; let admin = common::login(&app, ADMIN, PW).await.access; assert_eq!( post(&app, "/api/jobs/run", json!({"kind": "nope"}), Some(&admin)) .await .status, StatusCode::UNPROCESSABLE_ENTITY ); assert_eq!( post( &app, "/api/jobs/run", json!({"kind": "backup"}), Some(&admin) ) .await .status, StatusCode::NOT_FOUND ); post(&app, "/api/users", json!({"email": "u@x.de", "display_name": "U", "password": "user-password-123", "role": "user"}), Some(&admin)).await; let user = common::login(&app, "u@x.de", "user-password-123") .await .access; assert_eq!( post( &app, "/api/jobs/run", json!({"kind": "package_refresh"}), Some(&user) ) .await .status, StatusCode::FORBIDDEN ); assert_eq!( get(&app, "/api/jobs", Some(&user)).await.status, StatusCode::OK ); assert_eq!( get( &app, "/api/jobs/00000000-0000-0000-0000-000000000000", Some(&user) ) .await .status, StatusCode::NOT_FOUND ); }