use crate::harness::{SiteBuilder, TestServer, test_config_with_site}; #[tokio::test] async fn concurrent_build_gets_queued() { let dir = tempfile::tempdir().unwrap().keep(); let site = SiteBuilder::new("my-site", "https://example.com/repo.git", "secret-token").build(); let server = TestServer::start(test_config_with_site(dir, site)).await; // Pre-inject a build in progress via AppState server .state .build_scheduler .in_progress .lock() .unwrap() .insert("my-site".to_owned()); let resp = TestServer::client() .post(server.url("/my-site")) .header("Authorization", "Bearer secret-token") .send() .await .unwrap(); assert_eq!(resp.status().as_u16(), 202); let body = resp.text().await.unwrap(); let json: serde_json::Value = serde_json::from_str(&body).unwrap(); assert_eq!(json["status"], "queued"); } #[tokio::test] async fn concurrent_build_queue_collapse() { let dir = tempfile::tempdir().unwrap().keep(); let site = SiteBuilder::new("my-site", "https://example.com/repo.git", "secret-token").build(); let server = TestServer::start(test_config_with_site(dir, site)).await; // Pre-inject a build in progress and a queued rebuild server .state .build_scheduler .in_progress .lock() .unwrap() .insert("my-site".to_owned()); server .state .build_scheduler .queued .lock() .unwrap() .insert("my-site".to_owned()); // Third request should collapse (202, no body) let resp = TestServer::client() .post(server.url("/my-site")) .header("Authorization", "Bearer secret-token") .send() .await .unwrap(); assert_eq!(resp.status().as_u16(), 202); let body = resp.text().await.unwrap(); assert!(body.is_empty()); } #[tokio::test] async fn concurrent_different_sites_both_accepted() { let dir = tempfile::tempdir().unwrap().keep(); let sites = vec![ SiteBuilder::new("site-one", "https://example.com/one.git", "token-one").build(), SiteBuilder::new("site-two", "https://example.com/two.git", "token-two").build(), ]; let config = crate::harness::test_config_with_sites(dir, sites); let server = TestServer::start(config).await; // First site — accepted let resp1 = TestServer::client() .post(server.url("/site-one")) .header("Authorization", "Bearer token-one") .send() .await .unwrap(); assert_eq!(resp1.status().as_u16(), 202); // Second site — also accepted (different build lock) let resp2 = TestServer::client() .post(server.url("/site-two")) .header("Authorization", "Bearer token-two") .send() .await .unwrap(); assert_eq!(resp2.status().as_u16(), 202); } #[tokio::test] async fn build_in_progress_checked_after_auth() { let dir = tempfile::tempdir().unwrap().keep(); let site = SiteBuilder::new("my-site", "https://example.com/repo.git", "secret-token").build(); let server = TestServer::start(test_config_with_site(dir, site)).await; // Pre-mark site as building server .state .build_scheduler .in_progress .lock() .unwrap() .insert("my-site".to_owned()); // Request with wrong token should return 401 (auth checked before build status) let resp = TestServer::client() .post(server.url("/my-site")) .header("Authorization", "Bearer wrong-token") .send() .await .unwrap(); assert_eq!(resp.status().as_u16(), 401); }