diff --git a/tests/migrations.rs b/tests/migrations.rs new file mode 100644 index 0000000..f7989a4 --- /dev/null +++ b/tests/migrations.rs @@ -0,0 +1,62 @@ +use sqlx::migrate::Migrator; +use sqlx::sqlite::SqlitePoolOptions; +use sqlx::SqlitePool; + +static MIGRATOR: Migrator = sqlx::migrate!("./migrations"); + +async fn mem_pool() -> SqlitePool { + // NOTE: max_connections(1) is required because each :memory: connection + // creates a separate database + SqlitePoolOptions::new() + .max_connections(1) + .connect("sqlite::memory:") + .await + .expect("cannot open in-memory db") +} + +async fn user_tables(pool: &SqlitePool) -> Vec { + sqlx::query_scalar::<_, String>( + "SELECT name FROM sqlite_master + WHERE type = 'table' + AND name NOT LIKE '_sqlx%' + AND name NOT LIKE 'sqlite_%' + ORDER BY name", + ) + .fetch_all(pool) + .await + .expect("cannot query sqlite_master") +} + +#[tokio::test] +async fn migrations_up() { + let pool = mem_pool().await; + MIGRATOR.run(&pool).await.expect("migrations failed"); + + let tables = user_tables(&pool).await; + assert!(tables.contains(&"todos".to_string())); + assert!(tables.contains(&"todo_tags".to_string())); +} + +#[tokio::test] +async fn migrations_down() { + let pool = mem_pool().await; + MIGRATOR.run(&pool).await.expect("run failed"); + MIGRATOR.undo(&pool, 0).await.expect("undo failed"); + + let tables = user_tables(&pool).await; + assert!(tables.is_empty(), "tables should be gone after revert: {tables:?}"); +} + +#[tokio::test] +async fn migrations_round_trip() { + let pool = mem_pool().await; + + MIGRATOR.run(&pool).await.expect("first run failed"); + let tables_before = user_tables(&pool).await; + + MIGRATOR.undo(&pool, 0).await.expect("undo failed"); + MIGRATOR.run(&pool).await.expect("second run failed"); + let tables_after = user_tables(&pool).await; + + assert_eq!(tables_before, tables_after); +}