migs 0.1.2

A SQL migration script collection library with compile-time registration
Documentation
//! Integration tests for the migs macro library

use migs::{collect, migs, Migs};

// Register some test migrations with explicit scope
migs!(path = "tests/migrations/001_init.sql", scope = "init");
migs!(path = "tests/migrations/002_indexes.sql", scope = "indexes");
migs!(
    sql = "INSERT INTO {{table}} (name) VALUES ('test')",
    scope = "seed"
);
migs!(
    sql = "UPDATE {{table}} SET name = 'updated' WHERE id = {{id}}",
    scope = "update"
);

// Register some test migrations WITHOUT scope (should default to "init")
migs!(path = "tests/migrations/001_init.sql");
migs!(sql = "SELECT 1 FROM {{table}}");

#[test]
fn test_collect_returns_all_scripts() {
    let scripts: Vec<&Migs> = collect!();

    // We should have 6 registered scripts (4 with explicit scope + 2 without)
    assert!(!scripts.is_empty(), "Should have registered scripts");
    assert_eq!(scripts.len(), 6, "Should have exactly 6 registered scripts");
}

#[test]
fn test_scripts_have_correct_scopes() {
    let scripts: Vec<&Migs> = collect!();

    let scopes: Vec<&str> = scripts.iter().map(|s| s.scope).collect();

    // Check for explicit scopes
    assert!(scopes.contains(&"init"), "Should have init scope");
    assert!(scopes.contains(&"indexes"), "Should have indexes scope");
    assert!(scopes.contains(&"seed"), "Should have seed scope");
    assert!(scopes.contains(&"update"), "Should have update scope");
}

#[test]
fn test_default_scope_is_init() {
    let scripts: Vec<&Migs> = collect!();

    // Count how many scripts have the "init" scope
    // We have: 1 explicit "init" + 2 without scope (defaults to "init") = 3 total
    let init_scripts: Vec<_> = scripts.iter().filter(|s| s.scope == "init").collect();
    assert_eq!(
        init_scripts.len(),
        3,
        "Should have 3 scripts with 'init' scope (1 explicit + 2 default)"
    );
}

#[test]
fn test_scripts_have_correct_sources() {
    let scripts: Vec<&Migs> = collect!();

    // Find the file-based scripts
    let file_scripts: Vec<_> = scripts
        .iter()
        .filter(|s| s.source.starts_with("tests/migrations/"))
        .collect();
    assert_eq!(file_scripts.len(), 3, "Should have 3 file-based scripts");

    // Find the inline scripts
    let inline_scripts: Vec<_> = scripts.iter().filter(|s| s.source == "<inline>").collect();
    assert_eq!(inline_scripts.len(), 3, "Should have 3 inline scripts");
}

#[test]
fn test_scripts_have_content() {
    let scripts: Vec<&Migs> = collect!();

    for script in &scripts {
        assert!(!script.content.is_empty(), "Script should have content");
    }

    // Check that the init script has CREATE TABLE
    let init_scripts: Vec<_> = scripts.iter().filter(|s| s.scope == "init").collect();
    assert!(
        !init_scripts.is_empty(),
        "Should have at least one init script"
    );

    // At least one of the init scripts should have CREATE TABLE
    let has_create_table = init_scripts
        .iter()
        .any(|s| s.content.contains("CREATE TABLE"));
    assert!(
        has_create_table,
        "At least one init script should contain CREATE TABLE"
    );
}

#[test]
fn test_inline_sql_has_placeholders() {
    let scripts: Vec<&Migs> = collect!();

    // Find the seed script
    let seed_script = scripts
        .iter()
        .find(|s| s.scope == "seed")
        .expect("Should find seed script");

    assert!(
        seed_script.content.contains("{{table}}"),
        "Seed script should have {{table}} placeholder"
    );
}

#[test]
fn test_default_scope_script_has_placeholder() {
    let scripts: Vec<&Migs> = collect!();

    // Find the default scope script (the one without explicit scope but with sql)
    let default_sql_script = scripts
        .iter()
        .find(|s| {
            s.scope == "init" && s.source == "<inline>" && s.content == "SELECT 1 FROM {{table}}"
        })
        .expect("Should find default scope inline script");

    assert_eq!(
        default_sql_script.scope, "init",
        "Default scope should be 'init'"
    );
    assert!(
        default_sql_script.content.contains("{{table}}"),
        "Should have placeholder"
    );
}