audb-codegen 0.1.11

Code generation for AuDB compile-time database applications
//! Integration tests for code generation

use audb::schema::{Field, Schema, SchemaFormat, Type};
use audb_codegen::SchemaGenerator;

#[test]
fn test_generated_code_structure() {
    let mut schema = Schema::new("User".to_string(), SchemaFormat::Native);
    schema.add_field(Field::new("id".to_string(), Type::EntityId));
    schema.add_field(Field::new("name".to_string(), Type::String));
    schema.add_field(Field::new("age".to_string(), Type::Integer));

    let generator = SchemaGenerator::new();
    let code = generator.generate(&schema);
    let code_str = code.to_string();

    // Verify struct declaration
    assert!(code_str.contains("pub struct User"));

    // Verify derives
    assert!(code_str.contains("Debug"));
    assert!(code_str.contains("Clone"));
    assert!(code_str.contains("serde :: Serialize"));
    assert!(code_str.contains("serde :: Deserialize"));

    // Verify fields
    assert!(code_str.contains("pub id"));
    assert!(code_str.contains("pub name"));
    assert!(code_str.contains("pub age"));
}

#[test]
fn test_generated_types() {
    let mut schema = Schema::new("TestTypes".to_string(), SchemaFormat::Native);
    schema.add_field(Field::new("text".to_string(), Type::String));
    schema.add_field(Field::new("number".to_string(), Type::Integer));
    schema.add_field(Field::new("decimal".to_string(), Type::Float));
    schema.add_field(Field::new("flag".to_string(), Type::Boolean));
    schema.add_field(Field::new("uid".to_string(), Type::EntityId));

    let generator = SchemaGenerator::new();
    let code = generator.generate(&schema);
    let code_str = code.to_string();

    assert!(code_str.contains("String"));
    assert!(code_str.contains("i64"));
    assert!(code_str.contains("f64"));
    assert!(code_str.contains("bool"));
    assert!(code_str.contains("uuid :: Uuid"));
}

#[test]
fn test_optional_fields() {
    let mut schema = Schema::new("Profile".to_string(), SchemaFormat::Native);

    let mut required_field = Field::new("id".to_string(), Type::EntityId);
    required_field.nullable = false;
    schema.add_field(required_field);

    let mut optional_field = Field::new("bio".to_string(), Type::String);
    optional_field.nullable = true;
    schema.add_field(optional_field);

    let generator = SchemaGenerator::new();
    let code = generator.generate(&schema);
    let code_str = code.to_string();

    // Required field should not have Option
    assert!(code_str.contains("pub id : uuid :: Uuid"));

    // Optional field should have Option
    assert!(code_str.contains("pub bio : Option < String >"));
}

#[test]
fn test_nested_types() {
    let mut schema = Schema::new("Post".to_string(), SchemaFormat::Native);

    schema.add_field(Field::new(
        "tags".to_string(),
        Type::Vec(Box::new(Type::String)),
    ));

    schema.add_field(Field::new(
        "author".to_string(),
        Type::Custom("User".to_string()),
    ));

    let generator = SchemaGenerator::new();
    let code = generator.generate(&schema);
    let code_str = code.to_string();

    assert!(code_str.contains("Vec < String >"));
    assert!(code_str.contains("User"));
}

#[test]
fn test_multiple_schemas() {
    let mut user = Schema::new("User".to_string(), SchemaFormat::Native);
    user.add_field(Field::new("id".to_string(), Type::EntityId));
    user.add_field(Field::new("name".to_string(), Type::String));

    let mut post = Schema::new("Post".to_string(), SchemaFormat::Native);
    post.add_field(Field::new("id".to_string(), Type::EntityId));
    post.add_field(Field::new("title".to_string(), Type::String));
    post.add_field(Field::new(
        "author".to_string(),
        Type::Custom("User".to_string()),
    ));

    let generator = SchemaGenerator::new();
    let code = generator.generate_all(&[&user, &post]);
    let code_str = code.to_string();

    assert!(code_str.contains("pub struct User"));
    assert!(code_str.contains("pub struct Post"));
    assert!(code_str.contains("author : User"));
}

#[test]
fn test_doc_comments() {
    let mut schema = Schema::new("User".to_string(), SchemaFormat::Native);
    schema.doc_comment = Some("Represents a user in the system".to_string());

    let mut field = Field::new("id".to_string(), Type::EntityId);
    field.doc_comment = Some("Unique identifier".to_string());
    schema.add_field(field);

    let generator = SchemaGenerator::new();
    let code = generator.generate(&schema);
    let code_str = code.to_string();

    assert!(code_str.contains("Represents a user in the system"));
    assert!(code_str.contains("Unique identifier"));
}

#[test]
fn test_custom_derives() {
    let mut schema = Schema::new("Entity".to_string(), SchemaFormat::Native);
    schema.add_field(Field::new("id".to_string(), Type::EntityId));

    let mut generator = SchemaGenerator::new();
    generator.add_derive("PartialEq".to_string());
    generator.add_derive("Eq".to_string());
    generator.add_derive("Hash".to_string());

    let code = generator.generate(&schema);
    let code_str = code.to_string();

    assert!(code_str.contains("PartialEq"));
    assert!(code_str.contains("Eq"));
    assert!(code_str.contains("Hash"));
}

#[test]
fn test_without_serde() {
    let mut schema = Schema::new("Simple".to_string(), SchemaFormat::Native);
    schema.add_field(Field::new("value".to_string(), Type::String));

    let mut generator = SchemaGenerator::new();
    generator.with_serde = false;

    let code = generator.generate(&schema);
    let code_str = code.to_string();

    assert!(!code_str.contains("serde"));
    assert!(code_str.contains("Debug"));
    assert!(code_str.contains("Clone"));
}