//! WP-11: POST /api/system/upgrade 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"; async fn wait_done(app: &axum::Router, token: &str, id: &str) -> serde_json::Value { for _ in 0..100 { let r = get(app, &format!("/api/jobs/{id}"), Some(token)).await; if r.json["status"] != "running" { return r.json; } tokio::time::sleep(std::time::Duration::from_millis(30)).await; } panic!("job did not finish"); } #[tokio::test] async fn admin_upgrades_selected_packages_and_log_shows_output() { let app = test_app_with_admin().await; let token = common::login(&app, ADMIN, PW).await.access; let res = post( &app, "/api/system/upgrade", json!({"packages": ["openssl", "curl"]}), Some(&token), ) .await; assert_eq!(res.status, StatusCode::ACCEPTED, "{}", res.json); assert_eq!(res.json["kind"], "package_upgrade"); let run = wait_done(&app, &token, res.json["id"].as_str().unwrap()).await; assert_eq!(run["status"], "success", "{}", run["log"]); let log = run["log"].as_str().unwrap(); assert!(log.contains("openssl curl"), "{log}"); assert!(log.contains("Setting up"), "{log}"); // inventory was refreshed afterwards let inv = get(&app, "/api/system/inventory", Some(&token)).await; assert!(inv.json["refreshed_at"].is_string()); } #[tokio::test] async fn upgrade_all_validation_and_permissions() { let app = test_app_with_admin().await; let admin = common::login(&app, ADMIN, PW).await.access; let res = post( &app, "/api/system/upgrade", json!({"packages": []}), Some(&admin), ) .await; assert_eq!(res.status, StatusCode::ACCEPTED); wait_done(&app, &admin, res.json["id"].as_str().unwrap()).await; let res = post( &app, "/api/system/upgrade", json!({"packages": ["bad name"]}), Some(&admin), ) .await; assert_eq!(res.status, StatusCode::UNPROCESSABLE_ENTITY); 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/system/upgrade", json!({"packages": []}), Some(&user) ) .await .status, StatusCode::FORBIDDEN ); }