From 3d9aba7b1f3185345ac58a51127ac32e8b669a50 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 17 Dec 2025 13:48:20 +0000 Subject: [PATCH] Mentions: Added coverage for mentions search endpoint --- .../CommentMentionNotificationHandler.php | 9 ++- tests/User/UserSearchTest.php | 67 +++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/app/Activity/Notifications/Handlers/CommentMentionNotificationHandler.php b/app/Activity/Notifications/Handlers/CommentMentionNotificationHandler.php index f7c833aee..50c8cb8ab 100644 --- a/app/Activity/Notifications/Handlers/CommentMentionNotificationHandler.php +++ b/app/Activity/Notifications/Handlers/CommentMentionNotificationHandler.php @@ -19,11 +19,13 @@ class CommentMentionNotificationHandler extends BaseNotificationHandler { public function handle(Activity $activity, Loggable|string $detail, User $user): void { - $page = $detail->entity; - if (!($detail instanceof Comment) || !($page instanceof Page)) { + if (!($detail instanceof Comment) || !($detail->entity instanceof Page)) { throw new \InvalidArgumentException("Detail for comment mention notifications must be a comment on a page"); } + /** @var Page $page */ + $page = $detail->entity; + $parser = new MentionParser(); $mentionedUserIds = $parser->parseUserIdsFromHtml($detail->html); $realMentionedUsers = User::whereIn('id', $mentionedUserIds)->get(); @@ -50,6 +52,9 @@ class CommentMentionNotificationHandler extends BaseNotificationHandler $this->sendNotificationToUserIds(CommentMentionNotification::class, $receivingNotificationsUserIds, $user, $detail, $page); } + /** + * @param Collection $mentionedUsers + */ protected function logMentions(Collection $mentionedUsers, Comment $comment, User $fromUser): void { $mentions = []; diff --git a/tests/User/UserSearchTest.php b/tests/User/UserSearchTest.php index 76efbf4af..25c7c6ee9 100644 --- a/tests/User/UserSearchTest.php +++ b/tests/User/UserSearchTest.php @@ -2,6 +2,7 @@ namespace Tests\User; +use BookStack\Permissions\Permission; use BookStack\Users\Models\User; use Tests\TestCase; @@ -62,4 +63,70 @@ class UserSearchTest extends TestCase $resp = $this->get('/search/users/select?search=a'); $this->assertPermissionError($resp); } + + public function test_mentions_search_matches_by_name() + { + $viewer = $this->users->viewer(); + $editor = $this->users->editor(); + + $resp = $this->actingAs($editor)->get('/search/users/mention?search=' . urlencode($viewer->name)); + + $resp->assertOk(); + $resp->assertSee($viewer->name); + $resp->assertDontSee($editor->name); + } + + public function test_mentions_search_does_not_match_by_email() + { + $viewer = $this->users->viewer(); + + $resp = $this->asEditor()->get('/search/users/mention?search=' . urlencode($viewer->email)); + + $resp->assertDontSee($viewer->name); + } + + public function test_mentions_search_requires_logged_in_user() + { + $this->setSettings(['app-public' => true]); + $guest = $this->users->guest(); + $this->permissions->grantUserRolePermissions($guest, [Permission::CommentCreateAll, Permission::CommentUpdateAll]); + + $resp = $this->get('/search/users/mention?search=a'); + $this->assertPermissionError($resp); + } + + public function test_mentions_search_requires_comment_create_or_update_permission() + { + $viewer = $this->users->viewer(); + $editor = $this->users->editor(); + + $resp = $this->actingAs($viewer)->get('/search/users/mention?search=' . urlencode($editor->name)); + $this->assertPermissionError($resp); + + $this->permissions->grantUserRolePermissions($viewer, [Permission::CommentCreateAll]); + + $resp = $this->actingAs($editor)->get('/search/users/mention?search=' . urlencode($viewer->name)); + $resp->assertOk(); + $resp->assertSee($viewer->name); + + $this->permissions->removeUserRolePermissions($viewer, [Permission::CommentCreateAll]); + $this->permissions->grantUserRolePermissions($viewer, [Permission::CommentUpdateAll]); + + $resp = $this->actingAs($editor)->get('/search/users/mention?search=' . urlencode($viewer->name)); + $resp->assertOk(); + $resp->assertSee($viewer->name); + } + + public function test_mentions_search_shows_first_by_name_without_search() + { + /** @var User $firstUser */ + $firstUser = User::query() + ->orderBy('name', 'asc') + ->first(); + + $resp = $this->asEditor()->get('/search/users/mention'); + + $resp->assertOk(); + $this->withHtml($resp)->assertElementContains('a[data-id]:first-child', $firstUser->name); + } }