// tests/common/mod.rs use dotenvy::dotenv; // --- CHANGE 1: Add Alphanumeric to the use statement --- use rand::distr::Alphanumeric; use rand::Rng; use sqlx::{postgres::PgPoolOptions, Connection, Executor, PgConnection, PgPool}; use std::env; // (The get_database_url and get_root_connection functions remain the same) fn get_database_url() -> String { dotenv().ok(); env::var("TEST_DATABASE_URL").expect("TEST_DATABASE_URL must be set") } async fn get_root_connection() -> PgConnection { PgConnection::connect(&get_database_url()) .await .expect("Failed to create root connection to test database") } /// The primary test setup function. /// Creates a new, unique schema and returns a connection pool that is scoped to that schema. /// This is the key to test isolation. pub async fn setup_isolated_db() -> PgPool { let mut root_conn = get_root_connection().await; // Make schema names more unique - include timestamp + random let schema_name = format!( "test_{}_{}", std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(), rand::thread_rng() .sample_iter(&Alphanumeric) .take(8) .map(char::from) .collect::() .to_lowercase() ); root_conn .execute(format!("CREATE SCHEMA \"{}\"", schema_name).as_str()) .await .unwrap_or_else(|_| panic!("Failed to create schema: {}", schema_name)); root_conn .execute("CREATE SCHEMA IF NOT EXISTS \"default\"") .await .unwrap(); let pool = PgPoolOptions::new() .max_connections(5) .after_connect(move |conn, _meta| { let schema_name = schema_name.clone(); Box::pin(async move { conn.execute(format!("SET search_path TO \"{}\", \"default\", \"public\"", schema_name).as_str()) .await?; Ok(()) }) }) .connect(&get_database_url()) .await .expect("Failed to create isolated pool"); sqlx::migrate!() .run(&pool) .await .expect("Migrations failed in isolated schema"); sqlx::query!( r#" INSERT INTO schemas (name) VALUES ('default') ON CONFLICT (name) DO NOTHING "# ) .execute(&pool) .await .expect("Failed to insert test profile in isolated schema"); pool }