use axum::extract::{Json, Path, State}; use crate::{ empty::Empty, invite::app::AcceptError, name::Name, test::{fixtures, verify}, }; #[tokio::test] async fn valid_invite() { // Set up the environment let app = fixtures::scratch_app().await; let issuer = fixtures::user::create(&app, &fixtures::now()).await; let invite = fixtures::invite::issue(&app, &issuer, &fixtures::now()).await; // Call the endpoint let (name, password) = fixtures::user::propose(); let identity = fixtures::cookie::not_logged_in(); let request = super::Request { name: name.clone(), password: password.clone(), }; let (identity, Empty) = super::handler( State(app.clone()), fixtures::now(), identity, Path(invite.id), Json(request), ) .await .expect("accepting a valid invite succeeds"); // Verify the response assert!(identity.secret().is_some()); // Verify that the issued token is valid verify::identity::valid_for_name(&app, &identity, &name).await; // Verify that the given credentials can log in let secret = app .tokens() .login(&name, &password, &fixtures::now()) .await .expect("credentials given on signup are valid"); verify::token::valid_for_name(&app, &secret, &name).await; } #[tokio::test] async fn nonexistent_invite() { // Set up the environment let app = fixtures::scratch_app().await; let invite = fixtures::invite::fictitious(); // Call the endpoint let (name, password) = fixtures::user::propose(); let identity = fixtures::cookie::not_logged_in(); let request = super::Request { name: name.clone(), password: password.clone(), }; let super::Error(error) = super::handler( State(app.clone()), fixtures::now(), identity, Path(invite.clone()), Json(request), ) .await .expect_err("accepting a nonexistent invite fails"); // Verify the response assert!(matches!(error, AcceptError::NotFound(error_id) if error_id == invite)); } #[tokio::test] async fn expired_invite() { // Set up the environment let app = fixtures::scratch_app().await; let issuer = fixtures::user::create(&app, &fixtures::ancient()).await; let invite = fixtures::invite::issue(&app, &issuer, &fixtures::ancient()).await; app.invites() .expire(&fixtures::now()) .await .expect("expiring invites never fails"); // Call the endpoint let (name, password) = fixtures::user::propose(); let identity = fixtures::cookie::not_logged_in(); let request = super::Request { name: name.clone(), password: password.clone(), }; let super::Error(error) = super::handler( State(app.clone()), fixtures::now(), identity, Path(invite.id.clone()), Json(request), ) .await .expect_err("accepting a nonexistent invite fails"); // Verify the response assert!(matches!(error, AcceptError::NotFound(error_id) if error_id == invite.id)); } #[tokio::test] async fn accepted_invite() { // Set up the environment let app = fixtures::scratch_app().await; let issuer = fixtures::user::create(&app, &fixtures::ancient()).await; let invite = fixtures::invite::issue(&app, &issuer, &fixtures::ancient()).await; let (name, password) = fixtures::user::propose(); app.invites() .accept(&invite.id, &name, &password, &fixtures::now()) .await .expect("accepting a valid invite succeeds"); // Call the endpoint let (name, password) = fixtures::user::propose(); let identity = fixtures::cookie::not_logged_in(); let request = super::Request { name: name.clone(), password: password.clone(), }; let super::Error(error) = super::handler( State(app.clone()), fixtures::now(), identity, Path(invite.id.clone()), Json(request), ) .await .expect_err("accepting a nonexistent invite fails"); // Verify the response assert!(matches!(error, AcceptError::NotFound(error_id) if error_id == invite.id)); } #[tokio::test] async fn conflicting_name() { // Set up the environment let app = fixtures::scratch_app().await; let issuer = fixtures::user::create(&app, &fixtures::ancient()).await; let invite = fixtures::invite::issue(&app, &issuer, &fixtures::ancient()).await; let existing_name = Name::from("rijksmuseum"); app.users() .create( &existing_name, &fixtures::user::propose_password(), &fixtures::now(), ) .await .expect("creating a user in an empty environment succeeds"); // Call the endpoint let conflicting_name = Name::from("r\u{0133}ksmuseum"); let password = fixtures::user::propose_password(); let identity = fixtures::cookie::not_logged_in(); let request = super::Request { name: conflicting_name.clone(), password: password.clone(), }; let super::Error(error) = super::handler( State(app.clone()), fixtures::now(), identity, Path(invite.id.clone()), Json(request), ) .await .expect_err("accepting a nonexistent invite fails"); // Verify the response assert!( matches!(error, AcceptError::DuplicateLogin(error_name) if error_name == conflicting_name) ); } #[tokio::test] async fn invalid_name() { // Set up the environment let app = fixtures::scratch_app().await; let issuer = fixtures::user::create(&app, &fixtures::now()).await; let invite = fixtures::invite::issue(&app, &issuer, &fixtures::now()).await; // Call the endpoint let name = fixtures::user::propose_invalid_name(); let password = fixtures::user::propose_password(); let identity = fixtures::cookie::not_logged_in(); let request = super::Request { name: name.clone(), password: password.clone(), }; let super::Error(error) = super::handler( State(app.clone()), fixtures::now(), identity, Path(invite.id), Json(request), ) .await .expect_err("using an invalid name should fail"); // Verify the response assert!(matches!(error, AcceptError::InvalidName(error_name) if name == error_name)); }