//! Integration test for the new job API //! //! This test demonstrates the complete job lifecycle and validates //! that all new API methods work correctly together. use hero_supervisor_openrpc_client::{SupervisorClient, JobBuilder, JobResult}; use std::time::Duration; use tokio::time::sleep; #[tokio::test] async fn test_complete_job_lifecycle() -> Result<(), Box> { // Skip test if supervisor is not running let client = match SupervisorClient::new("http://localhost:3030") { Ok(c) => c, Err(_) => { println!("Skipping integration test - supervisor not available"); return Ok(()); } }; // Test connection if client.discover().await.is_err() { println!("Skipping integration test - supervisor not responding"); return Ok(()); } let secret = "user-secret-456"; // Test 1: Create job let job = JobBuilder::new() .caller_id("integration_test") .context_id("test_lifecycle") .payload("echo 'Integration test job'") .executor("osis") .runner("osis_runner_1") .timeout(30) .build()?; let job_id = client.jobs_create(secret, job).await?; assert!(!job_id.is_empty()); // Test 2: Start job client.job_start(secret, &job_id).await?; // Test 3: Monitor status let mut attempts = 0; let max_attempts = 15; // 15 seconds max let mut final_status = String::new(); while attempts < max_attempts { let status = client.job_status(&job_id).await?; final_status = status.status.clone(); if final_status == "completed" || final_status == "failed" || final_status == "timeout" { break; } attempts += 1; sleep(Duration::from_secs(1)).await; } // Test 4: Get result let result = client.job_result(&job_id).await?; match result { JobResult::Success { success: _ } => { assert_eq!(final_status, "completed"); }, JobResult::Error { error: _ } => { assert!(final_status == "failed" || final_status == "timeout"); } } Ok(()) } #[tokio::test] async fn test_job_run_immediate() -> Result<(), Box> { let client = match SupervisorClient::new("http://localhost:3030") { Ok(c) => c, Err(_) => return Ok(()), // Skip if not available }; if client.discover().await.is_err() { return Ok(()); // Skip if not responding } let secret = "user-secret-456"; let job = JobBuilder::new() .caller_id("integration_test") .context_id("test_immediate") .payload("echo 'Immediate job test'") .executor("osis") .runner("osis_runner_1") .timeout(30) .build()?; // Test immediate execution let result = client.job_run(secret, job).await?; // Should get either success or error, but not panic match result { JobResult::Success { success } => { assert!(!success.is_empty()); }, JobResult::Error { error } => { assert!(!error.is_empty()); } } Ok(()) } #[tokio::test] async fn test_jobs_list() -> Result<(), Box> { let client = match SupervisorClient::new("http://localhost:3030") { Ok(c) => c, Err(_) => return Ok(()), // Skip if not available }; if client.discover().await.is_err() { return Ok(()); // Skip if not responding } // Test listing jobs let job_ids = client.jobs_list().await?; // Should return a vector (might be empty) assert!(job_ids.len() >= 0); Ok(()) } #[tokio::test] async fn test_authentication_errors() -> Result<(), Box> { let client = match SupervisorClient::new("http://localhost:3030") { Ok(c) => c, Err(_) => return Ok(()), // Skip if not available }; if client.discover().await.is_err() { return Ok(()); // Skip if not responding } let invalid_secret = "invalid-secret"; let job = JobBuilder::new() .caller_id("integration_test") .context_id("test_auth") .payload("echo 'Auth test'") .executor("osis") .runner("osis_runner_1") .timeout(30) .build()?; // Test that invalid secret fails let result = client.jobs_create(invalid_secret, job.clone()).await; assert!(result.is_err()); let result = client.job_run(invalid_secret, job.clone()).await; assert!(result.is_err()); let result = client.job_start(invalid_secret, "fake-job-id").await; assert!(result.is_err()); Ok(()) } #[tokio::test] async fn test_nonexistent_job_operations() -> Result<(), Box> { let client = match SupervisorClient::new("http://localhost:3030") { Ok(c) => c, Err(_) => return Ok(()), // Skip if not available }; if client.discover().await.is_err() { return Ok(()); // Skip if not responding } let fake_job_id = "nonexistent-job-id"; // Test operations on nonexistent job let result = client.job_status(fake_job_id).await; assert!(result.is_err()); let result = client.job_result(fake_job_id).await; assert!(result.is_err()); Ok(()) }