2023-08-16 03:08:27 +08:00
< ? php
namespace Tests\Activity ;
2023-09-01 23:30:37 +08:00
use BookStack\Activity\ActivityType ;
use BookStack\Activity\Models\Comment ;
use BookStack\Activity\Notifications\Messages\BaseActivityNotification ;
2023-08-16 23:02:00 +08:00
use BookStack\Activity\Notifications\Messages\CommentCreationNotification ;
use BookStack\Activity\Notifications\Messages\PageCreationNotification ;
use BookStack\Activity\Notifications\Messages\PageUpdateNotification ;
2023-09-01 23:30:37 +08:00
use BookStack\Activity\Tools\ActivityLogger ;
2023-08-16 03:08:27 +08:00
use BookStack\Activity\Tools\UserEntityWatchOptions ;
use BookStack\Activity\WatchLevels ;
use BookStack\Entities\Models\Entity ;
2023-08-16 23:02:00 +08:00
use BookStack\Settings\UserNotificationPreferences ;
2024-12-13 05:45:52 +08:00
use Illuminate\Contracts\Notifications\Dispatcher ;
use Illuminate\Support\Facades\Mail ;
2023-08-16 23:02:00 +08:00
use Illuminate\Support\Facades\Notification ;
2023-08-16 03:08:27 +08:00
use Tests\TestCase ;
class WatchTest extends TestCase
{
public function test_watch_action_exists_on_entity_unless_active ()
{
$editor = $this -> users -> editor ();
$this -> actingAs ( $editor );
$entities = [ $this -> entities -> book (), $this -> entities -> chapter (), $this -> entities -> page ()];
/** @var Entity $entity */
foreach ( $entities as $entity ) {
$resp = $this -> get ( $entity -> getUrl ());
$this -> withHtml ( $resp ) -> assertElementContains ( 'form[action$="/watching/update"] button.icon-list-item' , 'Watch' );
$watchOptions = new UserEntityWatchOptions ( $editor , $entity );
2023-08-18 01:10:34 +08:00
$watchOptions -> updateLevelByValue ( WatchLevels :: COMMENTS );
2023-08-16 03:08:27 +08:00
$resp = $this -> get ( $entity -> getUrl ());
$this -> withHtml ( $resp ) -> assertElementNotExists ( 'form[action$="/watching/update"] button.icon-list-item' );
}
}
public function test_watch_action_only_shows_with_permission ()
{
$viewer = $this -> users -> viewer ();
$this -> actingAs ( $viewer );
$entities = [ $this -> entities -> book (), $this -> entities -> chapter (), $this -> entities -> page ()];
/** @var Entity $entity */
foreach ( $entities as $entity ) {
$resp = $this -> get ( $entity -> getUrl ());
$this -> withHtml ( $resp ) -> assertElementNotExists ( 'form[action$="/watching/update"] button.icon-list-item' );
}
$this -> permissions -> grantUserRolePermissions ( $viewer , [ 'receive-notifications' ]);
/** @var Entity $entity */
foreach ( $entities as $entity ) {
$resp = $this -> get ( $entity -> getUrl ());
$this -> withHtml ( $resp ) -> assertElementExists ( 'form[action$="/watching/update"] button.icon-list-item' );
}
}
public function test_watch_update ()
{
$editor = $this -> users -> editor ();
$book = $this -> entities -> book ();
2023-12-10 20:37:21 +08:00
$resp = $this -> actingAs ( $editor ) -> put ( '/watching/update' , [
2023-09-10 22:18:31 +08:00
'type' => $book -> getMorphClass (),
2023-08-16 03:08:27 +08:00
'id' => $book -> id ,
'level' => 'comments'
]);
$resp -> assertRedirect ( $book -> getUrl ());
$this -> assertSessionHas ( 'success' );
$this -> assertDatabaseHas ( 'watches' , [
'watchable_id' => $book -> id ,
'watchable_type' => $book -> getMorphClass (),
'user_id' => $editor -> id ,
'level' => WatchLevels :: COMMENTS ,
]);
$resp = $this -> put ( '/watching/update' , [
2023-09-10 22:18:31 +08:00
'type' => $book -> getMorphClass (),
2023-08-16 03:08:27 +08:00
'id' => $book -> id ,
'level' => 'default'
]);
$resp -> assertRedirect ( $book -> getUrl ());
$this -> assertDatabaseMissing ( 'watches' , [
'watchable_id' => $book -> id ,
'watchable_type' => $book -> getMorphClass (),
'user_id' => $editor -> id ,
]);
}
2023-08-16 23:02:00 +08:00
public function test_watch_update_fails_for_guest ()
{
$this -> setSettings ([ 'app-public' => 'true' ]);
$guest = $this -> users -> guest ();
$this -> permissions -> grantUserRolePermissions ( $guest , [ 'receive-notifications' ]);
$book = $this -> entities -> book ();
$resp = $this -> put ( '/watching/update' , [
2023-09-10 22:18:31 +08:00
'type' => $book -> getMorphClass (),
2023-08-16 23:02:00 +08:00
'id' => $book -> id ,
'level' => 'comments'
]);
$this -> assertPermissionError ( $resp );
2023-08-17 21:59:28 +08:00
$guest -> unsetRelations ();
2023-08-16 23:02:00 +08:00
}
2023-08-16 03:08:27 +08:00
public function test_watch_detail_display_reflects_state ()
{
$editor = $this -> users -> editor ();
$book = $this -> entities -> bookHasChaptersAndPages ();
$chapter = $book -> chapters () -> first ();
$page = $chapter -> pages () -> first ();
2023-08-18 01:10:34 +08:00
( new UserEntityWatchOptions ( $editor , $book )) -> updateLevelByValue ( WatchLevels :: UPDATES );
2023-08-16 03:08:27 +08:00
$this -> actingAs ( $editor ) -> get ( $book -> getUrl ()) -> assertSee ( 'Watching new pages and updates' );
$this -> get ( $chapter -> getUrl ()) -> assertSee ( 'Watching via parent book' );
$this -> get ( $page -> getUrl ()) -> assertSee ( 'Watching via parent book' );
2023-08-18 01:10:34 +08:00
( new UserEntityWatchOptions ( $editor , $chapter )) -> updateLevelByValue ( WatchLevels :: COMMENTS );
2023-08-16 03:08:27 +08:00
$this -> get ( $chapter -> getUrl ()) -> assertSee ( 'Watching new pages, updates & comments' );
$this -> get ( $page -> getUrl ()) -> assertSee ( 'Watching via parent chapter' );
2023-08-18 01:10:34 +08:00
( new UserEntityWatchOptions ( $editor , $page )) -> updateLevelByValue ( WatchLevels :: UPDATES );
2023-08-16 03:08:27 +08:00
$this -> get ( $page -> getUrl ()) -> assertSee ( 'Watching new pages and updates' );
}
public function test_watch_detail_ignore_indicator_cascades ()
{
$editor = $this -> users -> editor ();
$book = $this -> entities -> bookHasChaptersAndPages ();
2023-08-18 01:10:34 +08:00
( new UserEntityWatchOptions ( $editor , $book )) -> updateLevelByValue ( WatchLevels :: IGNORE );
2023-08-16 03:08:27 +08:00
$this -> actingAs ( $editor ) -> get ( $book -> getUrl ()) -> assertSee ( 'Ignoring notifications' );
$this -> get ( $book -> chapters () -> first () -> getUrl ()) -> assertSee ( 'Ignoring via parent book' );
$this -> get ( $book -> pages () -> first () -> getUrl ()) -> assertSee ( 'Ignoring via parent book' );
}
public function test_watch_option_menu_shows_current_active_state ()
{
$editor = $this -> users -> editor ();
$book = $this -> entities -> book ();
$options = new UserEntityWatchOptions ( $editor , $book );
$respHtml = $this -> withHtml ( $this -> actingAs ( $editor ) -> get ( $book -> getUrl ()));
$respHtml -> assertElementNotExists ( 'form[action$="/watching/update"] svg[data-icon="check-circle"]' );
2023-08-18 01:10:34 +08:00
$options -> updateLevelByValue ( WatchLevels :: COMMENTS );
2023-08-16 03:08:27 +08:00
$respHtml = $this -> withHtml ( $this -> actingAs ( $editor ) -> get ( $book -> getUrl ()));
$respHtml -> assertElementExists ( 'form[action$="/watching/update"] button[value="comments"] svg[data-icon="check-circle"]' );
2023-08-18 01:10:34 +08:00
$options -> updateLevelByValue ( WatchLevels :: IGNORE );
2023-08-16 03:08:27 +08:00
$respHtml = $this -> withHtml ( $this -> actingAs ( $editor ) -> get ( $book -> getUrl ()));
$respHtml -> assertElementExists ( 'form[action$="/watching/update"] button[value="ignore"] svg[data-icon="check-circle"]' );
}
public function test_watch_option_menu_limits_options_for_pages ()
{
$editor = $this -> users -> editor ();
$book = $this -> entities -> bookHasChaptersAndPages ();
2023-08-18 01:10:34 +08:00
( new UserEntityWatchOptions ( $editor , $book )) -> updateLevelByValue ( WatchLevels :: IGNORE );
2023-08-16 03:08:27 +08:00
$respHtml = $this -> withHtml ( $this -> actingAs ( $editor ) -> get ( $book -> getUrl ()));
$respHtml -> assertElementExists ( 'form[action$="/watching/update"] button[name="level"][value="new"]' );
$respHtml = $this -> withHtml ( $this -> get ( $book -> pages () -> first () -> getUrl ()));
$respHtml -> assertElementExists ( 'form[action$="/watching/update"] button[name="level"][value="updates"]' );
$respHtml -> assertElementNotExists ( 'form[action$="/watching/update"] button[name="level"][value="new"]' );
}
2023-08-16 23:02:00 +08:00
public function test_notify_own_page_changes ()
{
$editor = $this -> users -> editor ();
$entities = $this -> entities -> createChainBelongingToUser ( $editor );
$prefs = new UserNotificationPreferences ( $editor );
$prefs -> updateFromSettingsArray ([ 'own-page-changes' => 'true' ]);
$notifications = Notification :: fake ();
$this -> asAdmin ();
$this -> entities -> updatePage ( $entities [ 'page' ], [ 'name' => 'My updated page' , 'html' => 'Hello' ]);
$notifications -> assertSentTo ( $editor , PageUpdateNotification :: class );
}
public function test_notify_own_page_comments ()
{
$editor = $this -> users -> editor ();
$entities = $this -> entities -> createChainBelongingToUser ( $editor );
$prefs = new UserNotificationPreferences ( $editor );
$prefs -> updateFromSettingsArray ([ 'own-page-comments' => 'true' ]);
$notifications = Notification :: fake ();
$this -> asAdmin () -> post ( " /comment/ { $entities [ 'page' ] -> id } " , [
2024-01-31 22:22:04 +08:00
'html' => '<p>My new comment</p>'
2023-08-16 23:02:00 +08:00
]);
$notifications -> assertSentTo ( $editor , CommentCreationNotification :: class );
}
public function test_notify_comment_replies ()
{
$editor = $this -> users -> editor ();
$entities = $this -> entities -> createChainBelongingToUser ( $editor );
$prefs = new UserNotificationPreferences ( $editor );
$prefs -> updateFromSettingsArray ([ 'comment-replies' => 'true' ]);
2023-09-15 20:38:02 +08:00
// Create some existing comments to pad IDs to help potentially error
// on mis-identification of parent via ids used.
Comment :: factory () -> count ( 5 )
-> for ( $entities [ 'page' ], 'entity' )
-> create ([ 'created_by' => $this -> users -> admin () -> id ]);
2023-08-16 23:02:00 +08:00
$notifications = Notification :: fake ();
$this -> actingAs ( $editor ) -> post ( " /comment/ { $entities [ 'page' ] -> id } " , [
2024-01-31 22:22:04 +08:00
'html' => '<p>My new comment</p>'
2023-08-16 23:02:00 +08:00
]);
2023-09-15 20:38:02 +08:00
$comment = $entities [ 'page' ] -> comments () -> orderBy ( 'id' , 'desc' ) -> first ();
2023-08-16 23:02:00 +08:00
$this -> asAdmin () -> post ( " /comment/ { $entities [ 'page' ] -> id } " , [
2024-01-31 22:22:04 +08:00
'html' => '<p>My new comment response</p>' ,
2023-09-15 20:38:02 +08:00
'parent_id' => $comment -> local_id ,
2023-08-16 23:02:00 +08:00
]);
$notifications -> assertSentTo ( $editor , CommentCreationNotification :: class );
}
public function test_notify_watch_parent_book_ignore ()
{
$editor = $this -> users -> editor ();
$entities = $this -> entities -> createChainBelongingToUser ( $editor );
$watches = new UserEntityWatchOptions ( $editor , $entities [ 'book' ]);
$prefs = new UserNotificationPreferences ( $editor );
2023-08-18 01:10:34 +08:00
$watches -> updateLevelByValue ( WatchLevels :: IGNORE );
2023-08-16 23:02:00 +08:00
$prefs -> updateFromSettingsArray ([ 'own-page-changes' => 'true' , 'own-page-comments' => true ]);
$notifications = Notification :: fake ();
$this -> asAdmin () -> post ( " /comment/ { $entities [ 'page' ] -> id } " , [
'text' => 'My new comment response' ,
]);
$this -> entities -> updatePage ( $entities [ 'page' ], [ 'name' => 'My updated page' , 'html' => 'Hello' ]);
$notifications -> assertNothingSent ();
}
public function test_notify_watch_parent_book_comments ()
{
$notifications = Notification :: fake ();
$editor = $this -> users -> editor ();
$admin = $this -> users -> admin ();
$entities = $this -> entities -> createChainBelongingToUser ( $editor );
$watches = new UserEntityWatchOptions ( $editor , $entities [ 'book' ]);
2023-08-18 01:10:34 +08:00
$watches -> updateLevelByValue ( WatchLevels :: COMMENTS );
2023-08-16 23:02:00 +08:00
// Comment post
$this -> actingAs ( $admin ) -> post ( " /comment/ { $entities [ 'page' ] -> id } " , [
2024-01-31 22:22:04 +08:00
'html' => '<p>My new comment response</p>' ,
2023-08-16 23:02:00 +08:00
]);
$notifications -> assertSentTo ( $editor , function ( CommentCreationNotification $notification ) use ( $editor , $admin , $entities ) {
$mail = $notification -> toMail ( $editor );
2023-09-02 22:39:45 +08:00
$mailContent = html_entity_decode ( strip_tags ( $mail -> render ()), ENT_QUOTES );
2023-08-16 23:02:00 +08:00
return $mail -> subject === 'New comment on page: ' . $entities [ 'page' ] -> getShortName ()
&& str_contains ( $mailContent , 'View Comment' )
&& str_contains ( $mailContent , 'Page Name: ' . $entities [ 'page' ] -> name )
2023-11-14 18:31:44 +08:00
&& str_contains ( $mailContent , 'Page Path: ' . $entities [ 'book' ] -> getShortName ( 24 ) . ' > ' . $entities [ 'chapter' ] -> getShortName ( 24 ))
2023-08-16 23:02:00 +08:00
&& str_contains ( $mailContent , 'Commenter: ' . $admin -> name )
&& str_contains ( $mailContent , 'Comment: My new comment response' );
});
}
public function test_notify_watch_parent_book_updates ()
{
$notifications = Notification :: fake ();
$editor = $this -> users -> editor ();
$admin = $this -> users -> admin ();
$entities = $this -> entities -> createChainBelongingToUser ( $editor );
$watches = new UserEntityWatchOptions ( $editor , $entities [ 'book' ]);
2023-08-18 01:10:34 +08:00
$watches -> updateLevelByValue ( WatchLevels :: UPDATES );
2023-08-16 23:02:00 +08:00
$this -> actingAs ( $admin );
$this -> entities -> updatePage ( $entities [ 'page' ], [ 'name' => 'Updated page' , 'html' => 'new page content' ]);
2023-11-14 18:31:44 +08:00
$notifications -> assertSentTo ( $editor , function ( PageUpdateNotification $notification ) use ( $editor , $admin , $entities ) {
2023-08-16 23:02:00 +08:00
$mail = $notification -> toMail ( $editor );
2023-09-02 22:39:45 +08:00
$mailContent = html_entity_decode ( strip_tags ( $mail -> render ()), ENT_QUOTES );
2023-08-16 23:02:00 +08:00
return $mail -> subject === 'Updated page: Updated page'
&& str_contains ( $mailContent , 'View Page' )
&& str_contains ( $mailContent , 'Page Name: Updated page' )
2023-11-14 18:31:44 +08:00
&& str_contains ( $mailContent , 'Page Path: ' . $entities [ 'book' ] -> getShortName ( 24 ) . ' > ' . $entities [ 'chapter' ] -> getShortName ( 24 ))
2023-08-16 23:02:00 +08:00
&& str_contains ( $mailContent , 'Updated By: ' . $admin -> name )
&& str_contains ( $mailContent , 'you won\'t be sent notifications for further edits to this page by the same editor' );
});
// Test debounce
$notifications = Notification :: fake ();
$this -> entities -> updatePage ( $entities [ 'page' ], [ 'name' => 'Updated page' , 'html' => 'new page content' ]);
$notifications -> assertNothingSentTo ( $editor );
}
public function test_notify_watch_parent_book_new ()
{
$notifications = Notification :: fake ();
$editor = $this -> users -> editor ();
$admin = $this -> users -> admin ();
$entities = $this -> entities -> createChainBelongingToUser ( $editor );
$watches = new UserEntityWatchOptions ( $editor , $entities [ 'book' ]);
2023-08-18 01:10:34 +08:00
$watches -> updateLevelByValue ( WatchLevels :: NEW );
2023-08-16 23:02:00 +08:00
$this -> actingAs ( $admin ) -> get ( $entities [ 'chapter' ] -> getUrl ( '/create-page' ));
$page = $entities [ 'chapter' ] -> pages () -> where ( 'draft' , '=' , true ) -> first ();
$this -> post ( $page -> getUrl (), [ 'name' => 'My new page' , 'html' => 'My new page content' ]);
2023-11-14 18:31:44 +08:00
$notifications -> assertSentTo ( $editor , function ( PageCreationNotification $notification ) use ( $editor , $admin , $entities ) {
2023-08-16 23:02:00 +08:00
$mail = $notification -> toMail ( $editor );
2023-09-02 22:39:45 +08:00
$mailContent = html_entity_decode ( strip_tags ( $mail -> render ()), ENT_QUOTES );
2023-08-16 23:02:00 +08:00
return $mail -> subject === 'New page: My new page'
&& str_contains ( $mailContent , 'View Page' )
&& str_contains ( $mailContent , 'Page Name: My new page' )
2023-11-14 18:31:44 +08:00
&& str_contains ( $mailContent , 'Page Path: ' . $entities [ 'book' ] -> getShortName ( 24 ) . ' > ' . $entities [ 'chapter' ] -> getShortName ( 24 ))
2023-08-16 23:02:00 +08:00
&& str_contains ( $mailContent , 'Created By: ' . $admin -> name );
});
}
2023-08-18 00:57:31 +08:00
2023-09-01 23:30:37 +08:00
public function test_notifications_sent_in_right_language ()
{
$editor = $this -> users -> editor ();
$admin = $this -> users -> admin ();
setting () -> putUser ( $editor , 'language' , 'de' );
$entities = $this -> entities -> createChainBelongingToUser ( $editor );
$watches = new UserEntityWatchOptions ( $editor , $entities [ 'book' ]);
$watches -> updateLevelByValue ( WatchLevels :: COMMENTS );
$activities = [
ActivityType :: PAGE_CREATE => $entities [ 'page' ],
ActivityType :: PAGE_UPDATE => $entities [ 'page' ],
2023-10-31 23:50:56 +08:00
ActivityType :: COMMENT_CREATE => Comment :: factory () -> make ([
'entity_id' => $entities [ 'page' ] -> id ,
'entity_type' => $entities [ 'page' ] -> getMorphClass (),
]),
2023-09-01 23:30:37 +08:00
];
$notifications = Notification :: fake ();
$logger = app () -> make ( ActivityLogger :: class );
$this -> actingAs ( $admin );
foreach ( $activities as $activityType => $detail ) {
$logger -> add ( $activityType , $detail );
}
$sent = $notifications -> sentNotifications ()[ get_class ( $editor )][ $editor -> id ];
$this -> assertCount ( 3 , $sent );
foreach ( $sent as $notificationInfo ) {
$notification = $notificationInfo [ 0 ][ 'notification' ];
$this -> assertInstanceOf ( BaseActivityNotification :: class , $notification );
$mail = $notification -> toMail ( $editor );
2023-09-02 22:39:45 +08:00
$mailContent = html_entity_decode ( strip_tags ( $mail -> render ()), ENT_QUOTES );
2023-09-01 23:30:37 +08:00
$this -> assertStringContainsString ( 'Name der Seite:' , $mailContent );
$this -> assertStringContainsString ( 'Diese Benachrichtigung wurde' , $mailContent );
$this -> assertStringContainsString ( 'Sollte es beim Anklicken der Schaltfläche' , $mailContent );
}
}
2024-12-13 05:45:52 +08:00
public function test_failed_notifications_dont_block_and_log_errors ()
{
$logger = $this -> withTestLogger ();
$editor = $this -> users -> editor ();
$admin = $this -> users -> admin ();
$page = $this -> entities -> page ();
$book = $page -> book ;
$activityLogger = app () -> make ( ActivityLogger :: class );
$watches = new UserEntityWatchOptions ( $editor , $book );
$watches -> updateLevelByValue ( WatchLevels :: UPDATES );
$mockDispatcher = $this -> mock ( Dispatcher :: class );
$mockDispatcher -> shouldReceive ( 'send' ) -> once ()
-> andThrow ( \Exception :: class , 'Failed to connect to mail server' );
$this -> actingAs ( $admin );
$activityLogger -> add ( ActivityType :: PAGE_UPDATE , $page );
$this -> assertTrue ( $logger -> hasErrorThatContains ( " Failed to send email notification to user [id: { $editor -> id } ] with error: Failed to connect to mail server " ));
}
2023-08-18 00:57:31 +08:00
public function test_notifications_not_sent_if_lacking_view_permission_for_related_item ()
{
$notifications = Notification :: fake ();
$editor = $this -> users -> editor ();
$page = $this -> entities -> page ();
$watches = new UserEntityWatchOptions ( $editor , $page );
2023-08-18 01:10:34 +08:00
$watches -> updateLevelByValue ( WatchLevels :: COMMENTS );
2023-08-18 00:57:31 +08:00
$this -> permissions -> disableEntityInheritedPermissions ( $page );
$this -> asAdmin () -> post ( " /comment/ { $page -> id } " , [
2024-01-31 22:22:04 +08:00
'html' => '<p>My new comment response</p>' ,
2023-08-18 00:57:31 +08:00
]) -> assertOk ();
$notifications -> assertNothingSentTo ( $editor );
}
2023-09-03 21:19:43 +08:00
public function test_watches_deleted_on_user_delete ()
{
$editor = $this -> users -> editor ();
$page = $this -> entities -> page ();
$watches = new UserEntityWatchOptions ( $editor , $page );
$watches -> updateLevelByValue ( WatchLevels :: COMMENTS );
$this -> assertDatabaseHas ( 'watches' , [ 'user_id' => $editor -> id ]);
$this -> asAdmin () -> delete ( $editor -> getEditUrl ());
$this -> assertDatabaseMissing ( 'watches' , [ 'user_id' => $editor -> id ]);
}
public function test_watches_deleted_on_item_delete ()
{
$editor = $this -> users -> editor ();
$page = $this -> entities -> page ();
$watches = new UserEntityWatchOptions ( $editor , $page );
$watches -> updateLevelByValue ( WatchLevels :: COMMENTS );
$this -> assertDatabaseHas ( 'watches' , [ 'watchable_type' => 'page' , 'watchable_id' => $page -> id ]);
$this -> entities -> destroy ( $page );
$this -> assertDatabaseMissing ( 'watches' , [ 'watchable_type' => 'page' , 'watchable_id' => $page -> id ]);
}
2023-11-14 18:31:44 +08:00
public function test_page_path_in_notifications_limited_by_permissions ()
{
$chapter = $this -> entities -> chapterHasPages ();
$page = $chapter -> pages () -> first ();
$book = $chapter -> book ;
$notification = new PageCreationNotification ( $page , $this -> users -> editor ());
$viewer = $this -> users -> viewer ();
$viewerRole = $viewer -> roles () -> first ();
$content = html_entity_decode ( strip_tags ( $notification -> toMail ( $viewer ) -> render ()), ENT_QUOTES );
$this -> assertStringContainsString ( 'Page Path: ' . $book -> getShortName ( 24 ) . ' > ' . $chapter -> getShortName ( 24 ), $content );
$this -> permissions -> setEntityPermissions ( $page , [ 'view' ], [ $viewerRole ]);
$this -> permissions -> setEntityPermissions ( $chapter , [], [ $viewerRole ]);
$content = html_entity_decode ( strip_tags ( $notification -> toMail ( $viewer ) -> render ()), ENT_QUOTES );
$this -> assertStringContainsString ( 'Page Path: ' . $book -> getShortName ( 24 ), $content );
$this -> assertStringNotContainsString ( ' > ' . $chapter -> getShortName ( 24 ), $content );
$this -> permissions -> setEntityPermissions ( $book , [], [ $viewerRole ]);
$content = html_entity_decode ( strip_tags ( $notification -> toMail ( $viewer ) -> render ()), ENT_QUOTES );
$this -> assertStringNotContainsString ( 'Page Path:' , $content );
$this -> assertStringNotContainsString ( $book -> getShortName ( 24 ), $content );
$this -> assertStringNotContainsString ( $chapter -> getShortName ( 24 ), $content );
}
2023-08-16 03:08:27 +08:00
}