use axum::extract::{Path, State}; use itertools::Itertools; use crate::{message::app, test::fixtures}; #[tokio::test] pub async fn delete_message() { // Set up the environment let app = fixtures::scratch_app().await; let sender = fixtures::identity::create(&app, &fixtures::now()).await; let conversation = fixtures::conversation::create(&app, &fixtures::now()).await; let message = fixtures::message::send(&app, &conversation, &sender.login, &fixtures::now()).await; // Send the request let response = super::handler( State(app.clone()), Path(message.id.clone()), fixtures::now(), sender, ) .await .expect("deleting a valid message succeeds"); // Verify the response assert_eq!(message.id, response.id); // Verify the semantics let snapshot = app.boot().snapshot().await.expect("boot always succeeds"); let deleted = snapshot .events .into_iter() .filter_map(fixtures::event::message) .filter_map(fixtures::event::message::deleted) .exactly_one() .expect("only one message has been deleted"); assert_eq!(response.id, deleted.id) } #[tokio::test] pub async fn delete_invalid_message_id() { // Set up the environment let app = fixtures::scratch_app().await; // Send the request let deleter = fixtures::identity::create(&app, &fixtures::now()).await; let message = fixtures::message::fictitious(); let super::Error(error) = super::handler( State(app.clone()), Path(message.clone()), fixtures::now(), deleter, ) .await .expect_err("deleting a nonexistent message fails"); // Verify the response assert!(matches!(error, app::DeleteError::MessageNotFound(id) if id == message)); } #[tokio::test] pub async fn delete_deleted() { // Set up the environment let app = fixtures::scratch_app().await; let sender = fixtures::user::create(&app, &fixtures::now()).await; let conversation = fixtures::conversation::create(&app, &fixtures::now()).await; let message = fixtures::message::send(&app, &conversation, &sender, &fixtures::now()).await; app.messages() .delete(&sender, &message.id, &fixtures::now()) .await .expect("deleting a recently-sent message succeeds"); // Send the request let deleter = fixtures::identity::create(&app, &fixtures::now()).await; let super::Error(error) = super::handler( State(app.clone()), Path(message.id.clone()), fixtures::now(), deleter, ) .await .expect_err("deleting a deleted message fails"); // Verify the response assert!(matches!(error, app::DeleteError::Deleted(id) if id == message.id)); } #[tokio::test] pub async fn delete_expired() { // Set up the environment let app = fixtures::scratch_app().await; let sender = fixtures::user::create(&app, &fixtures::ancient()).await; let conversation = fixtures::conversation::create(&app, &fixtures::ancient()).await; let message = fixtures::message::send(&app, &conversation, &sender, &fixtures::ancient()).await; app.messages() .expire(&fixtures::now()) .await .expect("expiring messages always succeeds"); // Send the request let deleter = fixtures::identity::create(&app, &fixtures::now()).await; let super::Error(error) = super::handler( State(app.clone()), Path(message.id.clone()), fixtures::now(), deleter, ) .await .expect_err("deleting an expired message fails"); // Verify the response assert!(matches!(error, app::DeleteError::Deleted(id) if id == message.id)); } #[tokio::test] pub async fn delete_purged() { // Set up the environment let app = fixtures::scratch_app().await; let sender = fixtures::user::create(&app, &fixtures::ancient()).await; let conversation = fixtures::conversation::create(&app, &fixtures::ancient()).await; let message = fixtures::message::send(&app, &conversation, &sender, &fixtures::ancient()).await; app.messages() .expire(&fixtures::old()) .await .expect("expiring messages always succeeds"); app.messages() .purge(&fixtures::now()) .await .expect("purging messages always succeeds"); // Send the request let deleter = fixtures::identity::create(&app, &fixtures::now()).await; let super::Error(error) = super::handler( State(app.clone()), Path(message.id.clone()), fixtures::now(), deleter, ) .await .expect_err("deleting a purged message fails"); // Verify the response assert!(matches!(error, app::DeleteError::MessageNotFound(id) if id == message.id)); } #[tokio::test] pub async fn delete_not_sender() { // Set up the environment let app = fixtures::scratch_app().await; let sender = fixtures::user::create(&app, &fixtures::now()).await; let conversation = fixtures::conversation::create(&app, &fixtures::now()).await; let message = fixtures::message::send(&app, &conversation, &sender, &fixtures::now()).await; // Send the request let deleter = fixtures::identity::create(&app, &fixtures::now()).await; let super::Error(error) = super::handler( State(app.clone()), Path(message.id.clone()), fixtures::now(), deleter.clone(), ) .await .expect_err("deleting a message someone else sent fails"); // Verify the response assert!( matches!(error, app::DeleteError::NotSender(error_sender) if deleter.login.id == error_sender) ); }