use db::Db; use domain::Role; use sqlx::PgPool; // Note: `server::create_user` opens its own DB connection by URL, but `#[sqlx::test]` // provisions a temporary database whose URL is not directly exposed. The test below // exercises the same building blocks that `server::create_user` composes — // `auth::hash_password` + `db::users::create_user` + `db::users::credentials_by_email` — // against the test pool, which fully validates the end-to-end bootstrap logic. #[sqlx::test(migrations = "../db/migrations")] async fn create_user_persists_and_password_verifies(pool: PgPool) { let db = Db::from_pool(pool.clone()); let hash = auth::hash_password("bootstrap-pw-123").unwrap(); let mut tx = db.pool().begin().await.unwrap(); db::users::create_user( &mut tx, domain::AuditActor::System, &domain::NewUser { email: domain::Email::parse("boss@example.com").unwrap(), password_hash: hash, role: Role::Admin, }, ) .await .unwrap(); tx.commit().await.unwrap(); let (user, stored_hash) = db::users::credentials_by_email(db.pool(), "boss@example.com") .await .unwrap() .unwrap(); assert_eq!(user.role, Role::Admin); assert!(auth::verify_password("bootstrap-pw-123", &stored_hash)); } #[tokio::test] async fn create_user_rejects_invalid_email() { // The email is parsed before the password is read or the DB is touched, so an // invalid email errors out without reaching the (unreachable) database URL. let err = server::create_user("postgres://unused", "not-an-email", Role::Admin) .await .unwrap_err(); assert!(err.to_string().contains("email"), "got: {err}"); }