diff --git a/backend/tests/Unit/Post/UseCases/DeletePostTest.php b/backend/tests/Unit/Post/UseCases/DeletePostTest.php new file mode 100644 index 0000000..699c9d1 --- /dev/null +++ b/backend/tests/Unit/Post/UseCases/DeletePostTest.php @@ -0,0 +1,132 @@ +now = new DateTimeImmutable( + '2026-05-06T12:00:00', + new DateTimeZone('UTC') + ); + $this->postRepo = new FakePostRepository; + $this->useCase = new DeletePost($this->postRepo); + } + + private function seedPostByUser(int $userId): Post + { + return $this->postRepo->create(new CreatePostDto( + userId: $userId, + title: 'Some Post', + body: 'Some body.', + createdAt: $this->now, + )); + } + + public function test_zero_post_id_throws_bad_request(): void + { + $this->expectException(BadRequestException::class); + $this->useCase->execute(new DeletePostRequest( + postId: 0, + requesterId: 1, + requesterIsAdmin: false, + )); + } + + public function test_zero_requester_id_throws_bad_request(): void + { + $post = $this->seedPostByUser(1); + + $this->expectException(BadRequestException::class); + $this->useCase->execute(new DeletePostRequest( + postId: $post->getId(), + requesterId: 0, + requesterIsAdmin: false, + )); + } + + public function test_unknown_post_is_no_op(): void + { + $this->useCase->execute(new DeletePostRequest( + postId: 999, + requesterId: 1, + requesterIsAdmin: false, + )); + + // No exception thrown -> idempotent delete on missing post. + $this->assertNull($this->postRepo->find(999)); + } + + public function test_author_can_delete_own_post(): void + { + $post = $this->seedPostByUser(1); + + $this->useCase->execute(new DeletePostRequest( + postId: $post->getId(), + requesterId: 1, + requesterIsAdmin: false, + )); + + $this->assertNull($this->postRepo->find($post->getId())); + } + + public function test_admin_can_delete_anyones_post(): void + { + $post = $this->seedPostByUser(1); + + $this->useCase->execute(new DeletePostRequest( + postId: $post->getId(), + requesterId: 99, + requesterIsAdmin: true, + )); + + $this->assertNull($this->postRepo->find($post->getId())); + } + + public function test_other_user_cannot_delete_post(): void + { + $post = $this->seedPostByUser(1); + + $this->expectException(ForbiddenException::class); + $this->useCase->execute(new DeletePostRequest( + postId: $post->getId(), + requesterId: 2, + requesterIsAdmin: false, + )); + } + + public function test_forbidden_delete_does_not_remove_post(): void + { + $post = $this->seedPostByUser(1); + + try { + $this->useCase->execute(new DeletePostRequest( + postId: $post->getId(), + requesterId: 2, + requesterIsAdmin: false, + )); + } catch (ForbiddenException) { + // expected + } + + $this->assertNotNull($this->postRepo->find($post->getId())); + } +}