use crate::support::TestContextBuilder; use crate::support::register_command; use std::sync::Arc; use domain::ports::UserRepository; use domain::testing::InMemoryStore; use domain::value_objects::Email; use application::auth::{commands::RegisterCommand, deps::RegisterDeps, register}; fn cmd(email: &str) -> RegisterCommand { register_command(email, "alice") } #[tokio::test] async fn registering_creates_the_user() { let users = InMemoryStore::new(); let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _); let deps = RegisterDeps { user: b.user_repo.clone(), password_hasher: b.password_hasher.clone(), config: b.config.clone(), }; register::execute(&deps, cmd("alice@example.com")) .await .unwrap(); let email = Email::new("alice@example.com".into()).unwrap(); let user = users.find_by_email(&email).await.unwrap().unwrap(); assert_eq!(user.email().value(), "alice@example.com"); assert!(user.password_hash().value().starts_with("hashed:")); } #[tokio::test] async fn registering_with_a_duplicate_email_fails() { let users = InMemoryStore::new(); let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _); let deps = RegisterDeps { user: b.user_repo.clone(), password_hasher: b.password_hasher.clone(), config: b.config.clone(), }; register::execute(&deps, cmd("bob@example.com")) .await .unwrap(); let result = register::execute(&deps, cmd("bob@example.com")).await; assert!(result.is_err(), "duplicate email should fail"); } #[tokio::test] async fn registering_with_a_short_password_fails() { let b = TestContextBuilder::new(); let deps = RegisterDeps { user: b.user_repo.clone(), password_hasher: b.password_hasher.clone(), config: b.config.clone(), }; let result = register::execute( &deps, RegisterCommand { password: "short".to_string(), ..register_command("x@y.com", "testuser") }, ) .await; let err = result.unwrap_err().to_string(); assert!( err.contains("8 characters"), "expected password length error, got: {err}" ); }