clawspec-core 0.1.0

Core library for generating OpenAPI specifications from tests
Documentation

Clawspec Core

Generate OpenAPI specifications from your HTTP client test code.

This crate provides two main ways to generate OpenAPI documentation:

  • [ApiClient] - Direct HTTP client for fine-grained control
  • TestClient - Test server integration with automatic lifecycle management

Quick Start

Using ApiClient directly

use clawspec_core::ApiClient;
# use serde::Deserialize;
# use utoipa::ToSchema;
# #[derive(Deserialize, ToSchema)]
# struct User { id: u32, name: String }

# #[tokio::main]
# async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = ApiClient::builder()
    .with_host("api.example.com")
    .build()?;

// Make requests - schemas are captured automatically  
let user: User = client
    .get("/users/123")?
    .await?  // ← Direct await using IntoFuture
    .as_json()  // ← Important: Must consume result for OpenAPI generation!
    .await?;

// Generate OpenAPI specification
let spec = client.collected_openapi().await;
# Ok(())
# }

Using TestClient with a test server

For a complete working example, see the axum example.

use clawspec_core::test_client::{TestClient, TestServer};
use std::net::TcpListener;

# #[derive(Debug)]
# struct MyServer;
# impl TestServer for MyServer {
#     type Error = std::io::Error;
#     async fn launch(&self, listener: TcpListener) -> Result<(), Self::Error> {
#         Ok(())
#     }
# }
#[tokio::test]
async fn test_api() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = TestClient::start(MyServer).await?;
    
    // Test your API
    let response = client.get("/users")?.await?.as_json::<serde_json::Value>().await?;
    
    // Write OpenAPI spec
    client.write_openapi("api.yml").await?;
    Ok(())
}

Working with Parameters

use clawspec_core::{ApiClient, CallPath, CallQuery, CallHeaders, ParamValue};

# async fn example(client: &mut ApiClient) -> Result<(), Box<dyn std::error::Error>> {
// Path parameters
let mut path = CallPath::from("/users/{id}");
path.add_param("id", ParamValue::new(123));

// Query parameters
let query = CallQuery::new()
    .add_param("page", ParamValue::new(1))
    .add_param("limit", ParamValue::new(10));

// Headers
let headers = CallHeaders::new()
    .add_header("Authorization", "Bearer token");

// Direct await with parameters:
let response = client
    .get(path)?
    .with_query(query)
    .with_headers(headers)
    .await?;  // Direct await using IntoFuture
# Ok(())
# }

Status Code Validation

By default, requests expect status codes in the range 200-499 (inclusive of 200, exclusive of 500). You can customize this behavior:

use clawspec_core::{ApiClient, expected_status_codes};

# async fn example(client: &mut ApiClient) -> Result<(), Box<dyn std::error::Error>> {
// Single codes
client.post("/users")?
    .with_expected_status_codes(expected_status_codes!(201, 202))
    
    .await?;

// Ranges
client.get("/health")?
    .with_expected_status_codes(expected_status_codes!(200-299))
    
    .await?;
# Ok(())
# }

Schema Registration

use clawspec_core::{ApiClient, register_schemas};
# use serde::Deserialize;
# use utoipa::ToSchema;

#[derive(Deserialize, ToSchema)]
struct CreateUser { name: String, email: String }

#[derive(Deserialize, ToSchema)]
struct ErrorResponse { code: String, message: String }

# fn example(client: &mut ApiClient) {
// Register schemas for complete documentation
register_schemas!(client, CreateUser, ErrorResponse);
# }

Error Handling

The library provides two main error types:

  • [ApiClientError] - HTTP client errors (network, parsing, validation)
  • TestAppError - Test server lifecycle errors

See Also

  • [ApiClient] - HTTP client with OpenAPI collection
  • [ApiCall] - Request builder with parameter support
  • [test_client] - Test server integration module
  • [ExpectedStatusCodes] - Status code validation

Re-exports

All commonly used types are re-exported from the crate root for convenience.