]> BookStack Code Mirror - bookstack/blob - tests/Entity/BookShelfTest.php
Fixed canonical redirects on non-root url app instances
[bookstack] / tests / Entity / BookShelfTest.php
1 <?php namespace Tests\Entity;
2
3 use BookStack\Auth\User;
4 use BookStack\Entities\Book;
5 use BookStack\Entities\Bookshelf;
6 use BookStack\Uploads\Image;
7 use Illuminate\Support\Str;
8 use Tests\TestCase;
9 use Tests\Uploads\UsesImages;
10
11 class BookShelfTest extends TestCase
12 {
13
14     use UsesImages;
15
16     public function test_shelves_shows_in_header_if_have_view_permissions()
17     {
18         $viewer = $this->getViewer();
19         $resp = $this->actingAs($viewer)->get('/');
20         $resp->assertElementContains('header', 'Shelves');
21
22         $viewer->roles()->delete();
23         $this->giveUserPermissions($viewer);
24         $resp = $this->actingAs($viewer)->get('/');
25         $resp->assertElementNotContains('header', 'Shelves');
26
27         $this->giveUserPermissions($viewer, ['bookshelf-view-all']);
28         $resp = $this->actingAs($viewer)->get('/');
29         $resp->assertElementContains('header', 'Shelves');
30
31         $viewer->roles()->delete();
32         $this->giveUserPermissions($viewer, ['bookshelf-view-own']);
33         $resp = $this->actingAs($viewer)->get('/');
34         $resp->assertElementContains('header', 'Shelves');
35     }
36
37     public function test_shelves_shows_in_header_if_have_any_shelve_view_permission()
38     {
39         $user = factory(User::class)->create();
40         $this->giveUserPermissions($user, ['image-create-all']);
41         $shelf = Bookshelf::first();
42         $userRole = $user->roles()->first();
43
44         $resp = $this->actingAs($user)->get('/');
45         $resp->assertElementNotContains('header', 'Shelves');
46
47         $this->setEntityRestrictions($shelf, ['view'], [$userRole]);
48
49         $resp = $this->get('/');
50         $resp->assertElementContains('header', 'Shelves');
51     }
52
53     public function test_shelves_page_contains_create_link()
54     {
55         $resp = $this->asEditor()->get('/shelves');
56         $resp->assertElementContains('a', 'New Shelf');
57     }
58
59     public function test_book_not_visible_in_shelf_list_view_if_user_cant_view_shelf()
60     {
61         config()->set([
62             'app.views.bookshelves' => 'list',
63         ]);
64         $shelf = Bookshelf::query()->first();
65         $book = $shelf->books()->first();
66
67         $resp = $this->asEditor()->get('/shelves');
68         $resp->assertSee($book->name);
69         $resp->assertSee($book->getUrl());
70
71         $this->setEntityRestrictions($book, []);
72
73         $resp = $this->asEditor()->get('/shelves');
74         $resp->assertDontSee($book->name);
75         $resp->assertDontSee($book->getUrl());
76     }
77
78     public function test_shelves_create()
79     {
80         $booksToInclude = Book::take(2)->get();
81         $shelfInfo = [
82             'name' => 'My test book' . Str::random(4),
83             'description' => 'Test book description ' . Str::random(10)
84         ];
85         $resp = $this->asEditor()->post('/shelves', array_merge($shelfInfo, [
86             'books' => $booksToInclude->implode('id', ','),
87             'tags' => [
88                 [
89                     'name' => 'Test Category',
90                     'value' => 'Test Tag Value',
91                 ]
92             ],
93         ]));
94         $resp->assertRedirect();
95         $editorId = $this->getEditor()->id;
96         $this->assertDatabaseHas('bookshelves', array_merge($shelfInfo, ['created_by' => $editorId, 'updated_by' => $editorId]));
97
98         $shelf = Bookshelf::where('name', '=', $shelfInfo['name'])->first();
99         $shelfPage = $this->get($shelf->getUrl());
100         $shelfPage->assertSee($shelfInfo['name']);
101         $shelfPage->assertSee($shelfInfo['description']);
102         $shelfPage->assertElementContains('.tag-item', 'Test Category');
103         $shelfPage->assertElementContains('.tag-item', 'Test Tag Value');
104
105         $this->assertDatabaseHas('bookshelves_books', ['bookshelf_id' => $shelf->id, 'book_id' => $booksToInclude[0]->id]);
106         $this->assertDatabaseHas('bookshelves_books', ['bookshelf_id' => $shelf->id, 'book_id' => $booksToInclude[1]->id]);
107     }
108
109     public function test_shelves_create_sets_cover_image()
110     {
111         $shelfInfo = [
112             'name' => 'My test book' . Str::random(4),
113             'description' => 'Test book description ' . Str::random(10)
114         ];
115
116         $imageFile = $this->getTestImage('shelf-test.png');
117         $resp = $this->asEditor()->call('POST', '/shelves', $shelfInfo, [], ['image' => $imageFile]);
118         $resp->assertRedirect();
119
120         $lastImage = Image::query()->orderByDesc('id')->firstOrFail();
121         $shelf = Bookshelf::query()->where('name', '=', $shelfInfo['name'])->first();
122         $this->assertDatabaseHas('bookshelves', [
123             'id' => $shelf->id,
124             'image_id' => $lastImage->id,
125         ]);
126         $this->assertEquals($lastImage->id, $shelf->cover->id);
127     }
128
129     public function test_shelf_view()
130     {
131         $shelf = Bookshelf::first();
132         $resp = $this->asEditor()->get($shelf->getUrl());
133         $resp->assertStatus(200);
134         $resp->assertSeeText($shelf->name);
135         $resp->assertSeeText($shelf->description);
136
137         foreach ($shelf->books as $book) {
138             $resp->assertSee($book->name);
139         }
140     }
141
142     public function test_shelf_view_shows_action_buttons()
143     {
144         $shelf = Bookshelf::first();
145         $resp = $this->asAdmin()->get($shelf->getUrl());
146         $resp->assertSee($shelf->getUrl('/create-book'));
147         $resp->assertSee($shelf->getUrl('/edit'));
148         $resp->assertSee($shelf->getUrl('/permissions'));
149         $resp->assertSee($shelf->getUrl('/delete'));
150         $resp->assertElementContains('a', 'New Book');
151         $resp->assertElementContains('a', 'Edit');
152         $resp->assertElementContains('a', 'Permissions');
153         $resp->assertElementContains('a', 'Delete');
154
155         $resp = $this->asEditor()->get($shelf->getUrl());
156         $resp->assertDontSee($shelf->getUrl('/permissions'));
157     }
158
159     public function test_shelf_edit()
160     {
161         $shelf = Bookshelf::first();
162         $resp = $this->asEditor()->get($shelf->getUrl('/edit'));
163         $resp->assertSeeText('Edit Bookshelf');
164
165         $booksToInclude = Book::take(2)->get();
166         $shelfInfo = [
167             'name' => 'My test book' . Str::random(4),
168             'description' => 'Test book description ' . Str::random(10)
169         ];
170
171         $resp = $this->asEditor()->put($shelf->getUrl(), array_merge($shelfInfo, [
172             'books' => $booksToInclude->implode('id', ','),
173             'tags' => [
174                 [
175                     'name' => 'Test Category',
176                     'value' => 'Test Tag Value',
177                 ]
178             ],
179         ]));
180         $shelf = Bookshelf::find($shelf->id);
181         $resp->assertRedirect($shelf->getUrl());
182         $this->assertSessionHas('success');
183
184         $editorId = $this->getEditor()->id;
185         $this->assertDatabaseHas('bookshelves', array_merge($shelfInfo, ['id' => $shelf->id, 'created_by' => $editorId, 'updated_by' => $editorId]));
186
187         $shelfPage = $this->get($shelf->getUrl());
188         $shelfPage->assertSee($shelfInfo['name']);
189         $shelfPage->assertSee($shelfInfo['description']);
190         $shelfPage->assertElementContains('.tag-item', 'Test Category');
191         $shelfPage->assertElementContains('.tag-item', 'Test Tag Value');
192
193         $this->assertDatabaseHas('bookshelves_books', ['bookshelf_id' => $shelf->id, 'book_id' => $booksToInclude[0]->id]);
194         $this->assertDatabaseHas('bookshelves_books', ['bookshelf_id' => $shelf->id, 'book_id' => $booksToInclude[1]->id]);
195     }
196
197     public function test_shelf_create_new_book()
198     {
199         $shelf = Bookshelf::first();
200         $resp = $this->asEditor()->get($shelf->getUrl('/create-book'));
201
202         $resp->assertSee('Create New Book');
203         $resp->assertSee($shelf->getShortName());
204
205         $testName = 'Test Book in Shelf Name';
206
207         $createBookResp = $this->asEditor()->post($shelf->getUrl('/create-book'), [
208             'name' => $testName,
209             'description' => 'Book in shelf description'
210         ]);
211         $createBookResp->assertRedirect();
212
213         $newBook = Book::query()->orderBy('id', 'desc')->first();
214         $this->assertDatabaseHas('bookshelves_books', [
215             'bookshelf_id' => $shelf->id,
216             'book_id' => $newBook->id,
217         ]);
218
219         $resp = $this->asEditor()->get($shelf->getUrl());
220         $resp->assertSee($testName);
221     }
222
223     public function test_shelf_delete()
224     {
225         $shelf = Bookshelf::first();
226         $resp = $this->asEditor()->get($shelf->getUrl('/delete'));
227         $resp->assertSeeText('Delete Bookshelf');
228         $resp->assertSee("action=\"{$shelf->getUrl()}\"");
229
230         $resp = $this->delete($shelf->getUrl());
231         $resp->assertRedirect('/shelves');
232         $this->assertDatabaseMissing('bookshelves', ['id' => $shelf->id]);
233         $this->assertDatabaseMissing('bookshelves_books', ['bookshelf_id' => $shelf->id]);
234         $this->assertSessionHas('success');
235     }
236
237     public function test_shelf_copy_permissions()
238     {
239         $shelf = Bookshelf::first();
240         $resp = $this->asAdmin()->get($shelf->getUrl('/permissions'));
241         $resp->assertSeeText('Copy Permissions');
242         $resp->assertSee("action=\"{$shelf->getUrl('/copy-permissions')}\"");
243
244         $child = $shelf->books()->first();
245         $editorRole = $this->getEditor()->roles()->first();
246         $this->assertFalse(boolval($child->restricted), "Child book should not be restricted by default");
247         $this->assertTrue($child->permissions()->count() === 0, "Child book should have no permissions by default");
248
249         $this->setEntityRestrictions($shelf, ['view', 'update'], [$editorRole]);
250         $resp = $this->post($shelf->getUrl('/copy-permissions'));
251         $child = $shelf->books()->first();
252
253         $resp->assertRedirect($shelf->getUrl());
254         $this->assertTrue(boolval($child->restricted), "Child book should now be restricted");
255         $this->assertTrue($child->permissions()->count() === 2, "Child book should have copied permissions");
256         $this->assertDatabaseHas('entity_permissions', ['restrictable_id' => $child->id, 'action' => 'view', 'role_id' => $editorRole->id]);
257         $this->assertDatabaseHas('entity_permissions', ['restrictable_id' => $child->id, 'action' => 'update', 'role_id' => $editorRole->id]);
258     }
259
260     public function test_bookshelves_show_in_breadcrumbs_if_in_context()
261     {
262         $shelf = Bookshelf::first();
263         $shelfBook = $shelf->books()->first();
264         $shelfPage = $shelfBook->pages()->first();
265         $this->asAdmin();
266
267         $bookVisit = $this->get($shelfBook->getUrl());
268         $bookVisit->assertElementNotContains('.breadcrumbs', 'Shelves');
269         $bookVisit->assertElementNotContains('.breadcrumbs', $shelf->getShortName());
270
271         $this->get($shelf->getUrl());
272         $bookVisit = $this->get($shelfBook->getUrl());
273         $bookVisit->assertElementContains('.breadcrumbs', 'Shelves');
274         $bookVisit->assertElementContains('.breadcrumbs', $shelf->getShortName());
275
276         $pageVisit = $this->get($shelfPage->getUrl());
277         $pageVisit->assertElementContains('.breadcrumbs', 'Shelves');
278         $pageVisit->assertElementContains('.breadcrumbs', $shelf->getShortName());
279
280         $this->get('/books');
281         $pageVisit = $this->get($shelfPage->getUrl());
282         $pageVisit->assertElementNotContains('.breadcrumbs', 'Shelves');
283         $pageVisit->assertElementNotContains('.breadcrumbs', $shelf->getShortName());
284     }
285
286     public function test_bookshelves_show_on_book()
287     {
288         // Create shelf
289         $shelfInfo = [
290             'name' => 'My test shelf' . Str::random(4),
291             'description' => 'Test shelf description ' . Str::random(10)
292         ];
293
294         $this->asEditor()->post('/shelves', $shelfInfo);
295         $shelf = Bookshelf::where('name', '=', $shelfInfo['name'])->first();
296
297         // Create book and add to shelf
298         $this->asEditor()->post($shelf->getUrl('/create-book'), [
299             'name' => 'Test book name',
300             'description' => 'Book in shelf description'
301         ]);
302
303         $newBook = Book::query()->orderBy('id', 'desc')->first();
304
305         $resp = $this->asEditor()->get($newBook->getUrl());
306         $resp->assertElementContains('.tri-layout-left-contents', $shelfInfo['name']);
307
308         // Remove shelf
309         $this->delete($shelf->getUrl());
310
311         $resp = $this->asEditor()->get($newBook->getUrl());
312         $resp->assertDontSee($shelfInfo['name']);
313     }
314 }