use axum::{ extract::{Json, State}, http::StatusCode, }; use crate::{ login::{app, routes}, test::fixtures, }; #[tokio::test] async fn successful() { // Set up the environment let app = fixtures::scratch_app().await; let now = fixtures::now(); let login = fixtures::login::create_for_login(&app).await; let identity = fixtures::identity::logged_in(&app, &login, &now).await; let secret = fixtures::identity::secret(&identity); // Call the endpoint let (response_identity, response_status) = routes::on_logout( State(app.clone()), identity.clone(), Json(routes::LogoutRequest {}), ) .await .expect("logged out with a valid token"); // Verify the return value's basic structure assert!(response_identity.secret().is_none()); assert_eq!(StatusCode::NO_CONTENT, response_status); // Verify the semantics let error = app .logins() .validate(secret, &now) .await .expect_err("secret is invalid"); match error { app::ValidateError::InvalidToken => (), // should be invalid other => panic!("expected ValidateError::InvalidToken, got {other:#}"), } } #[tokio::test] async fn no_identity() { // Set up the environment let app = fixtures::scratch_app().await; // Call the endpoint let identity = fixtures::identity::not_logged_in(); let (identity, status) = routes::on_logout(State(app), identity, Json(routes::LogoutRequest {})) .await .expect("logged out with no token"); // Verify the return value's basic structure assert!(identity.secret().is_none()); assert_eq!(StatusCode::NO_CONTENT, status); } #[tokio::test] async fn invalid_token() { // Set up the environment let app = fixtures::scratch_app().await; // Call the endpoint let identity = fixtures::identity::fictitious(); let routes::LogoutError(error) = routes::on_logout(State(app), identity, Json(routes::LogoutRequest {})) .await .expect_err("logged out with an invalid token"); // Verify the return value's basic structure fixtures::error::expected!(error, app::ValidateError::InvalidToken); }