]> BookStack Code Mirror - bookstack/blob - tests/Entity/BookTest.php
Applied StyleCI changes, added php/larastan to attribution
[bookstack] / tests / Entity / BookTest.php
1 <?php
2
3 namespace Tests\Entity;
4
5 use BookStack\Entities\Models\Book;
6 use Tests\TestCase;
7
8 class BookTest extends TestCase
9 {
10     public function test_create()
11     {
12         $book = Book::factory()->make([
13             'name' => 'My First Book',
14         ]);
15
16         $resp = $this->asEditor()->get('/books');
17         $resp->assertElementContains('a[href="' . url('/create-book') . '"]', 'Create New Book');
18
19         $resp = $this->get('/create-book');
20         $resp->assertElementContains('form[action="' . url('/books') . '"][method="POST"]', 'Save Book');
21
22         $resp = $this->post('/books', $book->only('name', 'description'));
23         $resp->assertRedirect('/books/my-first-book');
24
25         $resp = $this->get('/books/my-first-book');
26         $resp->assertSee($book->name);
27         $resp->assertSee($book->description);
28     }
29
30     public function test_create_uses_different_slugs_when_name_reused()
31     {
32         $book = Book::factory()->make([
33             'name' => 'My First Book',
34         ]);
35
36         $this->asEditor()->post('/books', $book->only('name', 'description'));
37         $this->asEditor()->post('/books', $book->only('name', 'description'));
38
39         $books = Book::query()->where('name', '=', $book->name)
40             ->orderBy('id', 'desc')
41             ->take(2)
42             ->get();
43
44         $this->assertMatchesRegularExpression('/my-first-book-[0-9a-zA-Z]{3}/', $books[0]->slug);
45         $this->assertEquals('my-first-book', $books[1]->slug);
46     }
47
48     public function test_update()
49     {
50         /** @var Book $book */
51         $book = Book::query()->first();
52         // Cheeky initial update to refresh slug
53         $this->asEditor()->put($book->getUrl(), ['name' => $book->name . '5', 'description' => $book->description]);
54         $book->refresh();
55
56         $newName = $book->name . ' Updated';
57         $newDesc = $book->description . ' with more content';
58
59         $resp = $this->get($book->getUrl('/edit'));
60         $resp->assertSee($book->name);
61         $resp->assertSee($book->description);
62         $resp->assertElementContains('form[action="' . $book->getUrl() . '"]', 'Save Book');
63
64         $resp = $this->put($book->getUrl(), ['name' => $newName, 'description' => $newDesc]);
65         $resp->assertRedirect($book->getUrl() . '-updated');
66
67         $resp = $this->get($book->getUrl() . '-updated');
68         $resp->assertSee($newName);
69         $resp->assertSee($newDesc);
70     }
71
72     public function test_delete()
73     {
74         $book = Book::query()->whereHas('pages')->whereHas('chapters')->first();
75         $this->assertNull($book->deleted_at);
76         $pageCount = $book->pages()->count();
77         $chapterCount = $book->chapters()->count();
78
79         $deleteViewReq = $this->asEditor()->get($book->getUrl('/delete'));
80         $deleteViewReq->assertSeeText('Are you sure you want to delete this book?');
81
82         $deleteReq = $this->delete($book->getUrl());
83         $deleteReq->assertRedirect(url('/books'));
84         $this->assertActivityExists('book_delete', $book);
85
86         $book->refresh();
87         $this->assertNotNull($book->deleted_at);
88
89         $this->assertTrue($book->pages()->count() === 0);
90         $this->assertTrue($book->chapters()->count() === 0);
91         $this->assertTrue($book->pages()->withTrashed()->count() === $pageCount);
92         $this->assertTrue($book->chapters()->withTrashed()->count() === $chapterCount);
93         $this->assertTrue($book->deletions()->count() === 1);
94
95         $redirectReq = $this->get($deleteReq->baseResponse->headers->get('location'));
96         $redirectReq->assertNotificationContains('Book Successfully Deleted');
97     }
98
99     public function test_cancel_on_create_page_leads_back_to_books_listing()
100     {
101         $resp = $this->asEditor()->get('/create-book');
102         $resp->assertElementContains('form a[href="' . url('/books') . '"]', 'Cancel');
103     }
104
105     public function test_cancel_on_edit_book_page_leads_back_to_book()
106     {
107         /** @var Book $book */
108         $book = Book::query()->first();
109         $resp = $this->asEditor()->get($book->getUrl('/edit'));
110         $resp->assertElementContains('form a[href="' . $book->getUrl() . '"]', 'Cancel');
111     }
112
113     public function test_next_previous_navigation_controls_show_within_book_content()
114     {
115         $book = Book::query()->first();
116         $chapter = $book->chapters->first();
117
118         $resp = $this->asEditor()->get($chapter->getUrl());
119         $resp->assertElementContains('#sibling-navigation', 'Next');
120         $resp->assertElementContains('#sibling-navigation', substr($chapter->pages[0]->name, 0, 20));
121
122         $resp = $this->get($chapter->pages[0]->getUrl());
123         $resp->assertElementContains('#sibling-navigation', substr($chapter->pages[1]->name, 0, 20));
124         $resp->assertElementContains('#sibling-navigation', 'Previous');
125         $resp->assertElementContains('#sibling-navigation', substr($chapter->name, 0, 20));
126     }
127
128     public function test_recently_viewed_books_updates_as_expected()
129     {
130         $books = Book::all()->take(2);
131
132         $this->asAdmin()->get('/books')
133             ->assertElementNotContains('#recents', $books[0]->name)
134             ->assertElementNotContains('#recents', $books[1]->name);
135
136         $this->get($books[0]->getUrl());
137         $this->get($books[1]->getUrl());
138
139         $this->get('/books')
140             ->assertElementContains('#recents', $books[0]->name)
141             ->assertElementContains('#recents', $books[1]->name);
142     }
143
144     public function test_popular_books_updates_upon_visits()
145     {
146         $books = Book::all()->take(2);
147
148         $this->asAdmin()->get('/books')
149             ->assertElementNotContains('#popular', $books[0]->name)
150             ->assertElementNotContains('#popular', $books[1]->name);
151
152         $this->get($books[0]->getUrl());
153         $this->get($books[1]->getUrl());
154         $this->get($books[0]->getUrl());
155
156         $this->get('/books')
157             ->assertElementContains('#popular .book:nth-child(1)', $books[0]->name)
158             ->assertElementContains('#popular .book:nth-child(2)', $books[1]->name);
159     }
160
161     public function test_books_view_shows_view_toggle_option()
162     {
163         /** @var Book $book */
164         $editor = $this->getEditor();
165         setting()->putUser($editor, 'books_view_type', 'list');
166
167         $resp = $this->actingAs($editor)->get('/books');
168         $resp->assertElementContains('form[action$="/settings/users/' . $editor->id . '/switch-books-view"]', 'Grid View');
169         $resp->assertElementExists('input[name="view_type"][value="grid"]');
170
171         $resp = $this->patch("/settings/users/{$editor->id}/switch-books-view", ['view_type' => 'grid']);
172         $resp->assertRedirect();
173         $this->assertEquals('grid', setting()->getUser($editor, 'books_view_type'));
174
175         $resp = $this->actingAs($editor)->get('/books');
176         $resp->assertElementContains('form[action$="/settings/users/' . $editor->id . '/switch-books-view"]', 'List View');
177         $resp->assertElementExists('input[name="view_type"][value="list"]');
178
179         $resp = $this->patch("/settings/users/{$editor->id}/switch-books-view", ['view_type' => 'list']);
180         $resp->assertRedirect();
181         $this->assertEquals('list', setting()->getUser($editor, 'books_view_type'));
182     }
183
184     public function test_slug_multi_byte_url_safe()
185     {
186         $book = $this->newBook([
187             'name' => 'информация',
188         ]);
189
190         $this->assertEquals('informaciya', $book->slug);
191
192         $book = $this->newBook([
193             'name' => '¿Qué?',
194         ]);
195
196         $this->assertEquals('que', $book->slug);
197     }
198
199     public function test_slug_format()
200     {
201         $book = $this->newBook([
202             'name' => 'PartA / PartB / PartC',
203         ]);
204
205         $this->assertEquals('parta-partb-partc', $book->slug);
206     }
207 }
Morty Proxy This is a proxified and sanitized view of the page, visit original site.