rescript-openapi 0.1.0

Generate type-safe ReScript clients from OpenAPI specifications
Documentation
// SPDX-License-Identifier: PMPL-1.0-or-later
// SPDX-FileCopyrightText: 2025 Hyperpolymath

//! Snapshot tests for code generation

use rescript_openapi::{codegen, ir, parser};
use std::path::{Path, PathBuf};

fn generate_from_spec(spec_path: &str) -> (String, String, String) {
    let spec = parser::parse_spec(Path::new(spec_path)).expect("Failed to parse spec");
    let api = ir::lower(&spec).expect("Failed to lower spec");

    let config = codegen::Config {
        output_dir: PathBuf::from("/tmp"),
        module_prefix: "Api".to_string(),
        generate_schema: true,
        generate_client: true,
        unified_module: false,
        client_mode: codegen::ClientMode::Full,
        variant_mode: codegen::VariantMode::Polymorphic,
    };

    let types = codegen::types::generate(&api, &config).expect("Failed to generate types");
    let schema = codegen::schema::generate(&api, &config).expect("Failed to generate schema");
    let client = codegen::client::generate(&api, &config).expect("Failed to generate client");

    (types, schema, client)
}

#[test]
fn test_petstore_types() {
    let (types, _, _) = generate_from_spec("tests/fixtures/petstore.yaml");
    insta::assert_snapshot!("petstore_types", types);
}

#[test]
fn test_petstore_schema() {
    let (_, schema, _) = generate_from_spec("tests/fixtures/petstore.yaml");
    insta::assert_snapshot!("petstore_schema", schema);
}

#[test]
fn test_petstore_client() {
    let (_, _, client) = generate_from_spec("tests/fixtures/petstore.yaml");
    insta::assert_snapshot!("petstore_client", client);
}

#[test]
fn test_complex_types() {
    let (types, _, _) = generate_from_spec("tests/fixtures/complex.yaml");
    insta::assert_snapshot!("complex_types", types);
}

#[test]
fn test_complex_schema() {
    let (_, schema, _) = generate_from_spec("tests/fixtures/complex.yaml");
    insta::assert_snapshot!("complex_schema", schema);
}

#[test]
fn test_complex_client() {
    let (_, _, client) = generate_from_spec("tests/fixtures/complex.yaml");
    insta::assert_snapshot!("complex_client", client);
}

#[test]
fn test_recursive_types() {
    let (types, _, _) = generate_from_spec("tests/fixtures/recursive.yaml");
    insta::assert_snapshot!("recursive_types", types);
}

#[test]
fn test_datetime_mapping() {
    let (types, schema, _) = generate_from_spec("tests/fixtures/datetime.yaml");
    insta::assert_snapshot!("datetime_types", types);
    insta::assert_snapshot!("datetime_schema", schema);
}

#[test]
fn test_unified_module() {
    let spec = parser::parse_spec(Path::new("tests/fixtures/petstore.yaml")).expect("Failed to parse spec");
    let api_spec = ir::lower(&spec).expect("Failed to lower spec");

    let mut output = String::new();
    output.push_str("// SPDX-License-Identifier: PMPL-1.0-or-later\n");
    output.push_str("// Generated by rescript-openapi - DO NOT EDIT\n");
    output.push_str(&format!("// Source: {} v{}\n\n", api_spec.title, api_spec.version));
    output.push_str("open RescriptCore\n");
    output.push_str("module S = RescriptSchema.S\n\n");

    let config = codegen::Config {
        output_dir: PathBuf::from("/tmp"),
        module_prefix: "Api".to_string(),
        generate_schema: true,
        generate_client: true,
        unified_module: true,
        client_mode: codegen::ClientMode::Full,
        variant_mode: codegen::VariantMode::Polymorphic,
    };

    let sccs = codegen::schema::topological_sort_scc(&api_spec.types);
    for scc in sccs {
        output.push_str(&codegen::types::generate_scc(&scc, &config));
        for type_def in scc {
            output.push_str(&codegen::schema::generate_schema_only(type_def, &config));
            output.push('\n');
        }
        output.push('\n');
    }

    insta::assert_snapshot!("unified_module", output);
}

#[test]
fn test_streamlined_client() {
    let spec = parser::parse_spec(Path::new("tests/fixtures/petstore.yaml")).expect("Failed to parse spec");
    let api_spec = ir::lower(&spec).expect("Failed to lower spec");

    let config = codegen::Config {
        output_dir: PathBuf::from("/tmp"),
        module_prefix: "Api".to_string(),
        generate_schema: true,
        generate_client: true,
        unified_module: false,
        client_mode: codegen::ClientMode::FunctorOnly,
        variant_mode: codegen::VariantMode::Polymorphic,
    };

    let client = codegen::client::generate(&api_spec, &config).expect("Failed to generate client");
    insta::assert_snapshot!("streamlined_client", client);
}

#[test]
fn test_standard_variants() {
    let spec = parser::parse_spec(Path::new("tests/fixtures/petstore.yaml")).expect("Failed to parse spec");
    let api_spec = ir::lower(&spec).expect("Failed to lower spec");

    let config = codegen::Config {
        output_dir: PathBuf::from("/tmp"),
        module_prefix: "Api".to_string(),
        generate_schema: true,
        generate_client: true,
        unified_module: false,
        client_mode: codegen::ClientMode::Full,
        variant_mode: codegen::VariantMode::Standard,
    };

    let types = codegen::types::generate(&api_spec, &config).expect("Failed to generate types");
    let schema = codegen::schema::generate(&api_spec, &config).expect("Failed to generate schema");
    
    insta::assert_snapshot!("standard_variants_types", types);
    insta::assert_snapshot!("standard_variants_schema", schema);
}