toasty-driver-integration-suite 0.5.0

Integration test suite for Toasty database drivers
Documentation
use crate::prelude::*;

#[driver_test(id(ID))]
pub async fn auto_uuid_v4(test: &mut Test) -> Result<()> {
    #[derive(toasty::Model)]
    struct Item {
        #[key]
        #[auto]
        id: ID,

        #[auto(uuid(v4))]
        auto_field: uuid::Uuid,
    }

    let mut db = test.setup_db(models!(Item)).await;

    let u = Item::create().exec(&mut db).await?;
    // Sanity check that it actually generated a UUID
    assert!(uuid::Uuid::parse_str(&u.auto_field.to_string()).is_ok());
    Ok(())
}

#[driver_test(id(ID))]
pub async fn auto_uuid_v7(test: &mut Test) -> Result<()> {
    #[derive(toasty::Model)]
    struct Item {
        #[key]
        #[auto]
        id: ID,

        #[auto(uuid(v7))]
        auto_field: uuid::Uuid,
    }

    let mut db = test.setup_db(models!(Item)).await;

    let u = Item::create().exec(&mut db).await?;
    // Sanity check that it actually generated a UUID
    assert!(uuid::Uuid::parse_str(&u.auto_field.to_string()).is_ok());
    Ok(())
}

#[driver_test(requires(auto_increment))]
pub async fn auto_increment_explicit(test: &mut Test) -> Result<()> {
    #[derive(toasty::Model)]
    struct Item {
        #[key]
        #[auto(increment)]
        auto_field: u32,
    }

    let mut db = test.setup_db(models!(Item)).await;

    for i in 1..10 {
        let u = Item::create().exec(&mut db).await?;
        assert_eq!(u.auto_field, i);
    }
    Ok(())
}

#[driver_test(id(ID), requires(auto_increment))]
pub async fn auto_increment_implicit(test: &mut Test) -> Result<()> {
    #[derive(toasty::Model)]
    struct Item {
        #[key]
        #[auto]
        auto_field: u32,
    }

    let mut db = test.setup_db(models!(Item)).await;

    for i in 1..10 {
        let u = Item::create().exec(&mut db).await?;
        assert_eq!(u.auto_field, i);
    }
    Ok(())
}

// Test that auto-increment with composite primary keys is rejected
// This only applies to numeric types since UUID uses a different auto strategy
#[driver_test(requires(auto_increment))]
pub async fn auto_increment_with_composite_key_errors(test: &mut Test) {
    #[derive(toasty::Model)]
    #[key(partition = user_id, local = id)]
    struct InvalidModel {
        #[auto(increment)]
        id: u64,

        user_id: u64,
    }

    // This should fail during schema setup
    let result = test.try_setup_db(models!(InvalidModel)).await;

    assert!(result.is_err(), "Expected schema setup to fail");
    let err = result.unwrap_err();
    assert!(
        err.to_string()
            .contains("cannot be used with composite primary keys"),
        "Expected error message about composite keys, got: {}",
        err
    );
}

// Foreign key IDs passed to assocations depend on the auto-increment ID generated by the database,
// we want to make sure this works.
#[driver_test(id(ID), requires(auto_increment))]
pub async fn auto_increment_with_associations(test: &mut Test) -> Result<()> {
    #[derive(toasty::Model)]
    struct Parent {
        #[key]
        #[auto(increment)]
        id: u32,

        #[has_many]
        children: toasty::HasMany<Child>,
    }

    #[derive(toasty::Model)]
    struct Child {
        #[key]
        #[auto(increment)]
        id: u32,

        #[index]
        parent_id: u32,

        #[belongs_to(key = parent_id, references = id)]
        #[allow(dead_code)]
        parent: toasty::BelongsTo<Parent>,
    }

    let mut db = test.setup_db(models!(Parent, Child)).await;

    for i in 1..10 {
        let u = Parent::create()
            .child(Child::create())
            .child(Child::create())
            .exec(&mut db)
            .await?;
        assert_eq!(u.id, i);
        assert_eq!(u.children.get()[0].parent_id, i);
        assert_eq!(u.children.get()[1].parent_id, i);
        assert_eq!(u.children.get()[0].id, i * 2 - 1);
        assert_eq!(u.children.get()[1].id, i * 2);
    }
    Ok(())
}