update api, fix tests and examples

This commit is contained in:
Timur Gordon
2025-08-27 10:07:53 +02:00
parent 767c66fb6a
commit ef17d36300
42 changed files with 2984 additions and 781 deletions

230
src/openrpc/tests.rs Normal file
View File

@@ -0,0 +1,230 @@
//! Tests for the new job API methods
#[cfg(test)]
mod job_api_tests {
use super::super::*;
use crate::supervisor::{Supervisor, SupervisorBuilder};
use crate::job::{Job, JobBuilder};
use std::sync::Arc;
use tokio::sync::Mutex;
use serde_json::json;
async fn create_test_supervisor() -> Arc<Mutex<Supervisor>> {
let supervisor = SupervisorBuilder::new()
.redis_url("redis://localhost:6379")
.namespace("test_job_api")
.build()
.await
.unwrap_or_else(|_| Supervisor::default());
let mut supervisor = supervisor;
supervisor.add_admin_secret("test-admin-secret".to_string());
supervisor.add_user_secret("test-user-secret".to_string());
Arc::new(Mutex::new(supervisor))
}
fn create_test_job() -> Job {
JobBuilder::new()
.id("test-job-123".to_string())
.caller_id("test-client".to_string())
.context_id("test-context".to_string())
.script("print('Hello World')".to_string())
.script_type(crate::job::ScriptType::Osis)
.timeout(30)
.build()
.unwrap()
}
#[tokio::test]
async fn test_jobs_create() {
let supervisor = create_test_supervisor().await;
let job = create_test_job();
let params = RunJobParams {
secret: "test-user-secret".to_string(),
job: job.clone(),
};
let result = supervisor.jobs_create(params).await;
assert!(result.is_ok());
let job_id = result.unwrap();
assert_eq!(job_id, job.id);
}
#[tokio::test]
async fn test_jobs_create_invalid_secret() {
let supervisor = create_test_supervisor().await;
let job = create_test_job();
let params = RunJobParams {
secret: "invalid-secret".to_string(),
job,
};
let result = supervisor.jobs_create(params).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_jobs_list() {
let supervisor = create_test_supervisor().await;
let result = supervisor.jobs_list().await;
// Should not error even if Redis is not available (will return empty list or error)
// The important thing is that the method signature works
assert!(result.is_ok() || result.is_err());
}
#[tokio::test]
async fn test_job_run_success_format() {
let supervisor = create_test_supervisor().await;
let job = create_test_job();
let params = RunJobParams {
secret: "test-user-secret".to_string(),
job,
};
let result = supervisor.job_run(params).await;
// The result should be a JobResult enum
match result {
Ok(JobResult::Success { success: _ }) => {
// Success case - job executed and returned output
},
Ok(JobResult::Error { error: _ }) => {
// Error case - job failed but method worked
},
Err(_) => {
// Method error (authentication, etc.)
// This is acceptable for testing without actual runners
}
}
}
#[tokio::test]
async fn test_job_start() {
let supervisor = create_test_supervisor().await;
let params = StartJobParams {
secret: "test-user-secret".to_string(),
job_id: "test-job-123".to_string(),
};
let result = supervisor.job_start(params).await;
// Should fail gracefully if job doesn't exist
assert!(result.is_err() || result.is_ok());
}
#[tokio::test]
async fn test_job_start_invalid_secret() {
let supervisor = create_test_supervisor().await;
let params = StartJobParams {
secret: "invalid-secret".to_string(),
job_id: "test-job-123".to_string(),
};
let result = supervisor.job_start(params).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_job_status() {
let supervisor = create_test_supervisor().await;
let result = supervisor.job_status("test-job-123".to_string()).await;
// Should return error for non-existent job
assert!(result.is_err());
}
#[tokio::test]
async fn test_job_result() {
let supervisor = create_test_supervisor().await;
let result = supervisor.job_result("test-job-123".to_string()).await;
// Should return error for non-existent job
assert!(result.is_err());
}
#[test]
fn test_job_result_enum_serialization() {
let success_result = JobResult::Success {
success: "Job completed successfully".to_string(),
};
let serialized = serde_json::to_string(&success_result).unwrap();
assert!(serialized.contains("success"));
assert!(serialized.contains("Job completed successfully"));
let error_result = JobResult::Error {
error: "Job failed with error".to_string(),
};
let serialized = serde_json::to_string(&error_result).unwrap();
assert!(serialized.contains("error"));
assert!(serialized.contains("Job failed with error"));
}
#[test]
fn test_job_status_response_serialization() {
let status_response = JobStatusResponse {
job_id: "test-job-123".to_string(),
status: "running".to_string(),
created_at: "2023-01-01T00:00:00Z".to_string(),
started_at: Some("2023-01-01T00:00:05Z".to_string()),
completed_at: None,
};
let serialized = serde_json::to_string(&status_response).unwrap();
assert!(serialized.contains("test-job-123"));
assert!(serialized.contains("running"));
assert!(serialized.contains("2023-01-01T00:00:00Z"));
assert!(serialized.contains("2023-01-01T00:00:05Z"));
let deserialized: JobStatusResponse = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized.job_id, "test-job-123");
assert_eq!(deserialized.status, "running");
assert_eq!(deserialized.started_at, Some("2023-01-01T00:00:05Z".to_string()));
assert_eq!(deserialized.completed_at, None);
}
#[test]
fn test_start_job_params_serialization() {
let params = StartJobParams {
secret: "test-secret".to_string(),
job_id: "job-123".to_string(),
};
let serialized = serde_json::to_string(&params).unwrap();
assert!(serialized.contains("test-secret"));
assert!(serialized.contains("job-123"));
let deserialized: StartJobParams = serde_json::from_str(&serialized).unwrap();
assert_eq!(deserialized.secret, "test-secret");
assert_eq!(deserialized.job_id, "job-123");
}
#[test]
fn test_method_naming_convention() {
// Test that method names follow the jobs./job. convention
// These should be the actual method names in the trait
let jobs_methods = vec!["jobs.create", "jobs.list"];
let job_methods = vec!["job.run", "job.start", "job.status", "job.result"];
// Verify naming convention
for method in jobs_methods {
assert!(method.starts_with("jobs."));
}
for method in job_methods {
assert!(method.starts_with("job."));
}
}
}