//! Model listing and management endpoints use crate::ApiResult; /// Model information #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct ModelInfo { /// Model ID pub id: String, /// Model name pub name: String, /// Model description pub description: Option, /// Model status pub status: String, } /// List available models pub async fn list_models() -> ApiResult>> { // GREEN phase: Minimal implementation to make test pass let models = vec![ModelInfo { id: "default-model".to_string(), name: "Default Model".to_string(), description: Some("A default model for testing".to_string()), status: "ready".to_string(), }]; Ok(axum::Json(models)) } #[cfg(test)] mod tests { use super::*; use axum::{Router, http::StatusCode, routing::get}; use axum_test::TestServer; /// RED PHASE: This test should fail initially #[tokio::test] async fn test_models_list_endpoint() { // Arrange: Create a test server with models list route let app = Router::new().route("/v1/models", get(list_models)); let server = TestServer::new(app).unwrap(); // Act: Make request to models endpoint let response = server.get("/v1/models").await; // Assert: Should return 200 OK with proper model list response.assert_status(StatusCode::OK); let models: Vec = response.json(); // Verify we get at least one model back assert!(!models.is_empty(), "Should return at least one model"); // Verify model structure let first_model = &models[0]; assert!(!first_model.id.is_empty()); assert!(!first_model.name.is_empty()); assert_eq!(first_model.status, "ready"); } #[test] fn test_model_info_serialization() { let model = ModelInfo { id: "model-123".to_string(), name: "Test Model".to_string(), description: Some("A test model".to_string()), status: "ready".to_string(), }; let json = serde_json::to_string(&model).unwrap(); assert!(json.contains("model-123")); } }