mod common; use common::{client, login_admin, register_customer, spawn_app}; use serial_test::serial; #[tokio::test] #[serial] async fn register_login_me_happy_path() { let app = spawn_app().await; let (token, user_id) = register_customer(&app, "alice").await; let res = client() .get(app.url("/api/auth/me")) .bearer_auth(&token) .send() .await .unwrap(); assert_eq!(res.status(), 200); let me: serde_json::Value = res.json().await.unwrap(); assert_eq!(me["id"], user_id); assert_eq!(me["role"], "customer"); assert!(me.get("password_hash").is_none(), "hash must not leak"); } #[tokio::test] #[serial] async fn duplicate_email_conflict() { let app = spawn_app().await; let email = format!("dup-{}@test.local", uuid::Uuid::new_v4()); for expected in [201, 409] { let res = client() .post(app.url("/api/auth/register")) .json(&serde_json::json!({ "email": email, "password": "password123", "display_name": "dup", })) .send() .await .unwrap(); assert_eq!(res.status(), expected); } } #[tokio::test] #[serial] async fn wrong_password_unauthorized() { let app = spawn_app().await; let email = format!("wp-{}@test.local", uuid::Uuid::new_v4()); client() .post(app.url("/api/auth/register")) .json(&serde_json::json!({ "email": email, "password": "password123", "display_name": "wp", })) .send() .await .unwrap(); let res = client() .post(app.url("/api/auth/login")) .json(&serde_json::json!({ "email": email, "password": "wrong-password" })) .send() .await .unwrap(); assert_eq!(res.status(), 401); } #[tokio::test] #[serial] async fn me_requires_token() { let app = spawn_app().await; let res = client().get(app.url("/api/auth/me")).send().await.unwrap(); assert_eq!(res.status(), 401); } #[tokio::test] #[serial] async fn seeded_admin_can_login() { let app = spawn_app().await; let token = login_admin(&app).await; let res = client() .get(app.url("/api/auth/me")) .bearer_auth(token) .send() .await .unwrap(); let me: serde_json::Value = res.json().await.unwrap(); assert_eq!(me["role"], "platform_admin"); }