+ public function test_role_permission_removal()
+ {
+ // To cover issue fixed in f99c8ff99aee9beb8c692f36d4b84dc6e651e50a.
+ /** @var Page $page */
+ $page = Page::query()->first();
+ $viewerRole = Role::getRole('viewer');
+ $viewer = $this->getViewer();
+ $this->actingAs($viewer)->get($page->getUrl())->assertOk();
+
+ $this->asAdmin()->put('/settings/roles/' . $viewerRole->id, [
+ 'display_name' => $viewerRole->display_name,
+ 'description' => $viewerRole->description,
+ 'permission' => [],
+ ])->assertStatus(302);
+
+ $this->actingAs($viewer)->get($page->getUrl())->assertStatus(404);
+ }
+
+ public function test_empty_state_actions_not_visible_without_permission()
+ {
+ $admin = $this->getAdmin();
+ // Book links
+ $book = Book::factory()->create(['created_by' => $admin->id, 'updated_by' => $admin->id]);
+ $this->regenEntityPermissions($book);
+ $this->actingAs($this->getViewer())->get($book->getUrl())
+ ->assertDontSee('Create a new page')
+ ->assertDontSee('Add a chapter');
+
+ // Chapter links
+ $chapter = Chapter::factory()->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]);
+ $this->regenEntityPermissions($chapter);
+ $this->actingAs($this->getViewer())->get($chapter->getUrl())
+ ->assertDontSee('Create a new page')
+ ->assertDontSee('Sort the current book');
+ }
+
+ public function test_comment_create_permission()
+ {
+ $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+
+ $this->actingAs($this->user)
+ ->addComment($ownPage)
+ ->assertStatus(403);
+
+ $this->giveUserPermissions($this->user, ['comment-create-all']);
+
+ $this->actingAs($this->user)
+ ->addComment($ownPage)
+ ->assertOk();
+ }
+
+ public function test_comment_update_own_permission()
+ {
+ $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+ $this->giveUserPermissions($this->user, ['comment-create-all']);
+ $this->actingAs($this->user)->addComment($ownPage);
+ /** @var Comment $comment */
+ $comment = $ownPage->comments()->latest()->first();
+
+ // no comment-update-own
+ $this->actingAs($this->user)->updateComment($comment)->assertStatus(403);
+
+ $this->giveUserPermissions($this->user, ['comment-update-own']);
+
+ // now has comment-update-own
+ $this->actingAs($this->user)->updateComment($comment)->assertOk();
+ }
+
+ public function test_comment_update_all_permission()
+ {
+ /** @var Page $ownPage */
+ $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+ $this->asAdmin()->addComment($ownPage);
+ /** @var Comment $comment */
+ $comment = $ownPage->comments()->latest()->first();
+
+ // no comment-update-all
+ $this->actingAs($this->user)->updateComment($comment)->assertStatus(403);
+
+ $this->giveUserPermissions($this->user, ['comment-update-all']);
+
+ // now has comment-update-all
+ $this->actingAs($this->user)->updateComment($comment)->assertOk();
+ }
+
+ public function test_comment_delete_own_permission()
+ {
+ /** @var Page $ownPage */
+ $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+ $this->giveUserPermissions($this->user, ['comment-create-all']);
+ $this->actingAs($this->user)->addComment($ownPage);
+
+ /** @var Comment $comment */
+ $comment = $ownPage->comments()->latest()->first();
+
+ // no comment-delete-own
+ $this->actingAs($this->user)->deleteComment($comment)->assertStatus(403);
+
+ $this->giveUserPermissions($this->user, ['comment-delete-own']);
+
+ // now has comment-update-own
+ $this->actingAs($this->user)->deleteComment($comment)->assertOk();
+ }
+
+ public function test_comment_delete_all_permission()
+ {
+ /** @var Page $ownPage */
+ $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
+ $this->asAdmin()->addComment($ownPage);
+ /** @var Comment $comment */
+ $comment = $ownPage->comments()->latest()->first();
+
+ // no comment-delete-all
+ $this->actingAs($this->user)->deleteComment($comment)->assertStatus(403);
+
+ $this->giveUserPermissions($this->user, ['comment-delete-all']);
+
+ // now has comment-delete-all
+ $this->actingAs($this->user)->deleteComment($comment)->assertOk();
+ }
+
+ private function addComment(Page $page): TestResponse
+ {
+ $comment = Comment::factory()->make();
+
+ return $this->postJson("/comment/$page->id", $comment->only('text', 'html'));
+ }
+
+ private function updateComment(Comment $comment): TestResponse
+ {
+ $commentData = Comment::factory()->make();
+
+ return $this->putJson("/comment/{$comment->id}", $commentData->only('text', 'html'));
+ }
+
+ private function deleteComment(Comment $comment): TestResponse
+ {
+ return $this->json('DELETE', '/comment/' . $comment->id);
+ }