Notifications: Added testing to cover controls · LordSimal/BookStack@bc6e19b · GitHub
Skip to content

Commit bc6e19b

Browse files
committed
Notifications: Added testing to cover controls
1 parent 615741a commit bc6e19b

4 files changed

Lines changed: 175 additions & 1 deletion

File tree

app/Activity/Controllers/WatchController.php

Lines changed: 1 addition & 0 deletions

database/seeders/DummyContentSeeder.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public function run()
2727
// Create an editor user
2828
$editorUser = User::factory()->create();
2929
$editorRole = Role::getRole('editor');
30+
$additionalEditorPerms = ['receive-notifications'];
31+
$editorRole->permissions()->syncWithoutDetaching(RolePermission::whereIn('name', $additionalEditorPerms)->pluck('id'));
3032
$editorUser->attachRole($editorRole);
3133

3234
// Create a viewer user

tests/Activity/WatchTest.php

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
3+
namespace Tests\Activity;
4+
5+
use BookStack\Activity\Tools\UserEntityWatchOptions;
6+
use BookStack\Activity\WatchLevels;
7+
use BookStack\Entities\Models\Entity;
8+
use Tests\TestCase;
9+
10+
class WatchTest extends TestCase
11+
{
12+
public function test_watch_action_exists_on_entity_unless_active()
13+
{
14+
$editor = $this->users->editor();
15+
$this->actingAs($editor);
16+
17+
$entities = [$this->entities->book(), $this->entities->chapter(), $this->entities->page()];
18+
/** @var Entity $entity */
19+
foreach ($entities as $entity) {
20+
$resp = $this->get($entity->getUrl());
21+
$this->withHtml($resp)->assertElementContains('form[action$="/watching/update"] button.icon-list-item', 'Watch');
22+
23+
$watchOptions = new UserEntityWatchOptions($editor, $entity);
24+
$watchOptions->updateWatchLevel('comments');
25+
26+
$resp = $this->get($entity->getUrl());
27+
$this->withHtml($resp)->assertElementNotExists('form[action$="/watching/update"] button.icon-list-item');
28+
}
29+
}
30+
31+
public function test_watch_action_only_shows_with_permission()
32+
{
33+
$viewer = $this->users->viewer();
34+
$this->actingAs($viewer);
35+
36+
$entities = [$this->entities->book(), $this->entities->chapter(), $this->entities->page()];
37+
/** @var Entity $entity */
38+
foreach ($entities as $entity) {
39+
$resp = $this->get($entity->getUrl());
40+
$this->withHtml($resp)->assertElementNotExists('form[action$="/watching/update"] button.icon-list-item');
41+
}
42+
43+
$this->permissions->grantUserRolePermissions($viewer, ['receive-notifications']);
44+
45+
/** @var Entity $entity */
46+
foreach ($entities as $entity) {
47+
$resp = $this->get($entity->getUrl());
48+
$this->withHtml($resp)->assertElementExists('form[action$="/watching/update"] button.icon-list-item');
49+
}
50+
}
51+
52+
public function test_watch_update()
53+
{
54+
$editor = $this->users->editor();
55+
$book = $this->entities->book();
56+
57+
$this->actingAs($editor)->get($book->getUrl());
58+
$resp = $this->put('/watching/update', [
59+
'type' => get_class($book),
60+
'id' => $book->id,
61+
'level' => 'comments'
62+
]);
63+
64+
$resp->assertRedirect($book->getUrl());
65+
$this->assertSessionHas('success');
66+
$this->assertDatabaseHas('watches', [
67+
'watchable_id' => $book->id,
68+
'watchable_type' => $book->getMorphClass(),
69+
'user_id' => $editor->id,
70+
'level' => WatchLevels::COMMENTS,
71+
]);
72+
73+
$resp = $this->put('/watching/update', [
74+
'type' => get_class($book),
75+
'id' => $book->id,
76+
'level' => 'default'
77+
]);
78+
$resp->assertRedirect($book->getUrl());
79+
$this->assertDatabaseMissing('watches', [
80+
'watchable_id' => $book->id,
81+
'watchable_type' => $book->getMorphClass(),
82+
'user_id' => $editor->id,
83+
]);
84+
}
85+
86+
public function test_watch_detail_display_reflects_state()
87+
{
88+
$editor = $this->users->editor();
89+
$book = $this->entities->bookHasChaptersAndPages();
90+
$chapter = $book->chapters()->first();
91+
$page = $chapter->pages()->first();
92+
93+
(new UserEntityWatchOptions($editor, $book))->updateWatchLevel('updates');
94+
95+
$this->actingAs($editor)->get($book->getUrl())->assertSee('Watching new pages and updates');
96+
$this->get($chapter->getUrl())->assertSee('Watching via parent book');
97+
$this->get($page->getUrl())->assertSee('Watching via parent book');
98+
99+
(new UserEntityWatchOptions($editor, $chapter))->updateWatchLevel('comments');
100+
$this->get($chapter->getUrl())->assertSee('Watching new pages, updates & comments');
101+
$this->get($page->getUrl())->assertSee('Watching via parent chapter');
102+
103+
(new UserEntityWatchOptions($editor, $page))->updateWatchLevel('updates');
104+
$this->get($page->getUrl())->assertSee('Watching new pages and updates');
105+
}
106+
107+
public function test_watch_detail_ignore_indicator_cascades()
108+
{
109+
$editor = $this->users->editor();
110+
$book = $this->entities->bookHasChaptersAndPages();
111+
(new UserEntityWatchOptions($editor, $book))->updateWatchLevel('ignore');
112+
113+
$this->actingAs($editor)->get($book->getUrl())->assertSee('Ignoring notifications');
114+
$this->get($book->chapters()->first()->getUrl())->assertSee('Ignoring via parent book');
115+
$this->get($book->pages()->first()->getUrl())->assertSee('Ignoring via parent book');
116+
}
117+
118+
public function test_watch_option_menu_shows_current_active_state()
119+
{
120+
$editor = $this->users->editor();
121+
$book = $this->entities->book();
122+
$options = new UserEntityWatchOptions($editor, $book);
123+
124+
$respHtml = $this->withHtml($this->actingAs($editor)->get($book->getUrl()));
125+
$respHtml->assertElementNotExists('form[action$="/watching/update"] svg[data-icon="check-circle"]');
126+
127+
$options->updateWatchLevel('comments');
128+
$respHtml = $this->withHtml($this->actingAs($editor)->get($book->getUrl()));
129+
$respHtml->assertElementExists('form[action$="/watching/update"] button[value="comments"] svg[data-icon="check-circle"]');
130+
131+
$options->updateWatchLevel('ignore');
132+
$respHtml = $this->withHtml($this->actingAs($editor)->get($book->getUrl()));
133+
$respHtml->assertElementExists('form[action$="/watching/update"] button[value="ignore"] svg[data-icon="check-circle"]');
134+
}
135+
136+
public function test_watch_option_menu_limits_options_for_pages()
137+
{
138+
$editor = $this->users->editor();
139+
$book = $this->entities->bookHasChaptersAndPages();
140+
(new UserEntityWatchOptions($editor, $book))->updateWatchLevel('ignore');
141+
142+
$respHtml = $this->withHtml($this->actingAs($editor)->get($book->getUrl()));
143+
$respHtml->assertElementExists('form[action$="/watching/update"] button[name="level"][value="new"]');
144+
145+
$respHtml = $this->withHtml($this->get($book->pages()->first()->getUrl()));
146+
$respHtml->assertElementExists('form[action$="/watching/update"] button[name="level"][value="updates"]');
147+
$respHtml->assertElementNotExists('form[action$="/watching/update"] button[name="level"][value="new"]');
148+
}
149+
150+
// TODO - Guest user cannot see/set notifications
151+
// TODO - Actual notification testing
152+
}

tests/User/UserPreferencesTest.php

Lines changed: 20 additions & 1 deletion

0 commit comments

Comments
 (0)