Files
movies-diary/crates/application/tests/diary/delete_review_test.rs

154 lines
4.7 KiB
Rust

use domain::testing::{test_movie_with_year, test_review};
use std::sync::Arc;
use domain::{
ports::{MovieCommand, MovieQuery, ReviewRepository},
testing::{FakeDiaryQuery, InMemoryStore, NoopEventPublisher},
value_objects::{MovieId, UserId},
};
use application::{
diary::commands::DeleteReviewCommand, diary::delete_review, diary::deps::DeleteReviewDeps,
};
#[tokio::test]
async fn deleting_a_review_removes_it() {
let movies = InMemoryStore::new();
let reviews = Arc::clone(&movies);
let diary = FakeDiaryQuery::new();
let events = NoopEventPublisher::new();
let movie = test_movie_with_year("Terminator", 1984);
let user_id = UserId::from_uuid(uuid::Uuid::new_v4());
let review = test_review(movie.id(), &user_id, 4);
movies.upsert_movie(&movie).await.unwrap();
reviews.save_review(&review, &[]).await.unwrap();
diary.seed_history(movie.clone(), vec![]);
let deps = DeleteReviewDeps {
review: Arc::clone(&reviews) as _,
diary: diary.clone() as _,
movie_command: Arc::clone(&movies) as _,
event_publisher: Arc::clone(&events) as _,
};
delete_review::execute(
&deps,
DeleteReviewCommand {
review_id: review.id().value(),
requesting_user_id: user_id.value(),
},
)
.await
.unwrap();
assert_eq!(reviews.review_count(), 0, "review should be deleted");
assert!(
movies.get_movie_by_id(movie.id()).await.unwrap().is_none(),
"movie should be deleted when no reviews remain"
);
}
#[tokio::test]
async fn deleting_another_users_review_is_unauthorized() {
let reviews = InMemoryStore::new();
let diary = FakeDiaryQuery::new();
let movies = Arc::clone(&reviews);
let events = NoopEventPublisher::new();
let movie_id = MovieId::from_uuid(uuid::Uuid::new_v4());
let owner_id = UserId::from_uuid(uuid::Uuid::new_v4());
let other_id = uuid::Uuid::new_v4();
let review = test_review(&movie_id, &owner_id, 4);
reviews.save_review(&review, &[]).await.unwrap();
let deps = DeleteReviewDeps {
review: Arc::clone(&reviews) as _,
diary: diary as _,
movie_command: movies as _,
event_publisher: Arc::clone(&events) as _,
};
let result = delete_review::execute(
&deps,
DeleteReviewCommand {
review_id: review.id().value(),
requesting_user_id: other_id,
},
)
.await;
assert!(result.is_err(), "wrong user should not be able to delete");
assert_eq!(reviews.review_count(), 1, "review should still exist");
}
#[tokio::test]
async fn deleting_a_review_removes_it_and_records_its_event_together() {
let movies = InMemoryStore::new();
let diary = FakeDiaryQuery::new();
let events = NoopEventPublisher::new();
let movie = test_movie_with_year("Terminator", 1984);
let user_id = UserId::from_uuid(uuid::Uuid::new_v4());
let review = test_review(movie.id(), &user_id, 4);
movies.upsert_movie(&movie).await.unwrap();
movies.save_review(&review, &[]).await.unwrap();
diary.seed_history(movie.clone(), vec![review.clone()]);
let deps = DeleteReviewDeps {
review: Arc::clone(&movies) as _,
diary: diary.clone() as _,
movie_command: Arc::clone(&movies) as _,
event_publisher: Arc::clone(&events) as _,
};
delete_review::execute(
&deps,
DeleteReviewCommand {
review_id: review.id().value(),
requesting_user_id: user_id.value(),
},
)
.await
.unwrap();
assert_eq!(movies.review_count(), 0);
let recorded = movies.recorded_events();
assert_eq!(recorded.len(), 1);
assert!(matches!(
recorded[0],
domain::events::DomainEvent::ReviewDeleted { .. }
));
}
#[tokio::test]
async fn a_refused_delete_records_neither_the_removal_nor_its_event() {
let movies = InMemoryStore::new();
let diary = FakeDiaryQuery::new();
let events = NoopEventPublisher::new();
let user_id = UserId::from_uuid(uuid::Uuid::new_v4());
let review = test_review(&MovieId::generate(), &user_id, 4);
movies.save_review(&review, &[]).await.unwrap();
let deps = DeleteReviewDeps {
review: Arc::new(crate::edit_review_test::WriteRefusingReviews(Arc::clone(
&movies,
))),
diary: diary as _,
movie_command: Arc::clone(&movies) as _,
event_publisher: Arc::clone(&events) as _,
};
let result = delete_review::execute(
&deps,
DeleteReviewCommand {
review_id: review.id().value(),
requesting_user_id: user_id.value(),
},
)
.await;
assert!(result.is_err());
assert_eq!(movies.review_count(), 1);
assert!(movies.recorded_events().is_empty());
}