From 13ca655f9bbdef5f183092e355e767de3b9694a6 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Wed, 6 May 2026 22:29:09 +0300 Subject: [PATCH] test SetFeaturedPost use case --- .../Post/UseCases/SetFeaturedPostTest.php | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 backend/tests/Unit/Post/UseCases/SetFeaturedPostTest.php diff --git a/backend/tests/Unit/Post/UseCases/SetFeaturedPostTest.php b/backend/tests/Unit/Post/UseCases/SetFeaturedPostTest.php new file mode 100644 index 0000000..0ec231f --- /dev/null +++ b/backend/tests/Unit/Post/UseCases/SetFeaturedPostTest.php @@ -0,0 +1,171 @@ +now = new DateTimeImmutable( + '2026-05-06T12:00:00', + new DateTimeZone('UTC'), + ); + $this->postRepo = new FakePostRepository; + $this->useCase = new SetFeaturedPost($this->postRepo); + } + + private function seedPost(): Post + { + return $this->postRepo->create(new CreatePostDto( + userId: 1, + title: 'A', + body: 'B', + createdAt: $this->now, + )); + } + + public function test_non_admin_throws_forbidden(): void + { + $post = $this->seedPost(); + $this->expectException(ForbiddenException::class); + $this->useCase->execute(new SetFeaturedPostRequest( + postId: $post->getId(), + slot: 1, + requesterIsAdmin: false, + )); + } + + public function test_invalid_slot_throws_bad_request(): void + { + $post = $this->seedPost(); + $this->expectException(BadRequestException::class); + $this->useCase->execute(new SetFeaturedPostRequest( + postId: $post->getId(), + slot: 3, + requesterIsAdmin: true, + )); + } + + public function test_zero_post_id_throws_bad_request(): void + { + $this->expectException(BadRequestException::class); + $this->useCase->execute(new SetFeaturedPostRequest( + postId: 0, + slot: 1, + requesterIsAdmin: true, + )); + } + + public function test_unknown_post_throws_domain_exception(): void + { + $this->expectException(DomainException::class); + $this->useCase->execute(new SetFeaturedPostRequest( + postId: 999, + slot: 1, + requesterIsAdmin: true, + )); + } + + public function test_admin_assigns_slot(): void + { + $post = $this->seedPost(); + + $this->useCase->execute(new SetFeaturedPostRequest( + postId: $post->getId(), + slot: 1, + requesterIsAdmin: true, + )); + + $reloaded = $this->postRepo->find($post->getId()); + $this->assertSame(1, $reloaded->getFeatureSlot()); + } + + public function test_assigning_same_slot_evicts_previous_post(): void + { + $first = $this->seedPost(); + $second = $this->seedPost(); + + $this->useCase->execute(new SetFeaturedPostRequest( + postId: $first->getId(), + slot: 1, + requesterIsAdmin: true, + )); + $this->useCase->execute(new SetFeaturedPostRequest( + postId: $second->getId(), + slot: 1, + requesterIsAdmin: true, + )); + + $this->assertNull( + $this->postRepo->find($first->getId())->getFeatureSlot(), + ); + $this->assertSame( + 1, + $this->postRepo->find($second->getId())->getFeatureSlot(), + ); + } + + public function test_two_posts_can_occupy_separate_slots(): void + { + $first = $this->seedPost(); + $second = $this->seedPost(); + + $this->useCase->execute(new SetFeaturedPostRequest( + postId: $first->getId(), + slot: 1, + requesterIsAdmin: true, + )); + $this->useCase->execute(new SetFeaturedPostRequest( + postId: $second->getId(), + slot: 2, + requesterIsAdmin: true, + )); + + $featured = $this->postRepo->findFeatured(); + $this->assertCount(2, $featured); + $this->assertSame(1, $featured[0]->getFeatureSlot()); + $this->assertSame(2, $featured[1]->getFeatureSlot()); + } + + public function test_moving_post_to_other_slot_clears_old_slot(): void + { + $post = $this->seedPost(); + + $this->useCase->execute(new SetFeaturedPostRequest( + postId: $post->getId(), + slot: 1, + requesterIsAdmin: true, + )); + $this->useCase->execute(new SetFeaturedPostRequest( + postId: $post->getId(), + slot: 2, + requesterIsAdmin: true, + )); + + $this->assertNull( + $this->postRepo->findByFeatureSlot(1), + ); + $this->assertSame( + $post->getId(), + $this->postRepo->findByFeatureSlot(2)->getId(), + ); + } +}