]> BookStack Code Mirror - bookstack/blob - tests/References/ReferencesTest.php
Input WYSIWYG: Fixed existing tests, fixed empty description handling
[bookstack] / tests / References / ReferencesTest.php
1 <?php
2
3 namespace Tests\References;
4
5 use BookStack\App\Model;
6 use BookStack\Entities\Repos\PageRepo;
7 use BookStack\Entities\Tools\TrashCan;
8 use BookStack\References\Reference;
9 use Tests\TestCase;
10
11 class ReferencesTest extends TestCase
12 {
13     public function test_references_created_on_page_update()
14     {
15         $pageA = $this->entities->page();
16         $pageB = $this->entities->page();
17
18         $this->assertDatabaseMissing('references', ['from_id' => $pageA->id, 'from_type' => $pageA->getMorphClass()]);
19
20         $this->asEditor()->put($pageA->getUrl(), [
21             'name' => 'Reference test',
22             'html' => '<a href="' . $pageB->getUrl() . '">Testing</a>',
23         ]);
24
25         $this->assertDatabaseHas('references', [
26             'from_id'   => $pageA->id,
27             'from_type' => $pageA->getMorphClass(),
28             'to_id'     => $pageB->id,
29             'to_type'   => $pageB->getMorphClass(),
30         ]);
31     }
32
33     public function test_references_created_on_book_chapter_bookshelf_update()
34     {
35         $entities = [$this->entities->book(), $this->entities->chapter(), $this->entities->shelf()];
36         $shelf = $this->entities->shelf();
37
38         foreach ($entities as $entity) {
39             $entity->refresh();
40             $this->assertDatabaseMissing('references', ['from_id' => $entity->id, 'from_type' => $entity->getMorphClass()]);
41
42             $this->asEditor()->put($entity->getUrl(), [
43                 'name' => 'Reference test',
44                 'description_html' => '<a href="' . $shelf->getUrl() . '">Testing</a>',
45             ]);
46
47             $this->assertDatabaseHas('references', [
48                 'from_id'   => $entity->id,
49                 'from_type' => $entity->getMorphClass(),
50                 'to_id'     => $shelf->id,
51                 'to_type'   => $shelf->getMorphClass(),
52             ]);
53         }
54     }
55
56     public function test_references_deleted_on_page_delete()
57     {
58         $pageA = $this->entities->page();
59         $pageB = $this->entities->page();
60
61         $this->createReference($pageA, $pageB);
62         $this->createReference($pageB, $pageA);
63
64         $this->assertDatabaseHas('references', ['from_id' => $pageA->id, 'from_type' => $pageA->getMorphClass()]);
65         $this->assertDatabaseHas('references', ['to_id' => $pageA->id, 'to_type' => $pageA->getMorphClass()]);
66
67         app(PageRepo::class)->destroy($pageA);
68         app(TrashCan::class)->empty();
69
70         $this->assertDatabaseMissing('references', ['from_id' => $pageA->id, 'from_type' => $pageA->getMorphClass()]);
71         $this->assertDatabaseMissing('references', ['to_id' => $pageA->id, 'to_type' => $pageA->getMorphClass()]);
72     }
73
74     public function test_references_from_deleted_on_book_chapter_shelf_delete()
75     {
76         $entities = [$this->entities->chapter(), $this->entities->book(), $this->entities->shelf()];
77         $shelf = $this->entities->shelf();
78
79         foreach ($entities as $entity) {
80             $this->createReference($entity, $shelf);
81             $this->assertDatabaseHas('references', ['from_id' => $entity->id, 'from_type' => $entity->getMorphClass()]);
82
83             $this->asEditor()->delete($entity->getUrl());
84             app(TrashCan::class)->empty();
85
86             $this->assertDatabaseMissing('references', [
87                 'from_id'   => $entity->id,
88                 'from_type' => $entity->getMorphClass()
89             ]);
90         }
91     }
92
93     public function test_references_to_count_visible_on_entity_show_view()
94     {
95         $entities = $this->entities->all();
96         $otherPage = $this->entities->page();
97
98         $this->asEditor();
99         foreach ($entities as $entity) {
100             $this->createReference($entities['page'], $entity);
101         }
102
103         foreach ($entities as $entity) {
104             $resp = $this->get($entity->getUrl());
105             $resp->assertSee('Referenced by 1 item');
106             $resp->assertDontSee('Referenced by 1 items');
107         }
108
109         $this->createReference($otherPage, $entities['page']);
110         $resp = $this->get($entities['page']->getUrl());
111         $resp->assertSee('Referenced by 2 items');
112     }
113
114     public function test_references_to_visible_on_references_page()
115     {
116         $entities = $this->entities->all();
117         $this->asEditor();
118         foreach ($entities as $entity) {
119             $this->createReference($entities['page'], $entity);
120         }
121
122         foreach ($entities as $entity) {
123             $resp = $this->get($entity->getUrl('/references'));
124             $resp->assertSee('References');
125             $resp->assertSee($entities['page']->name);
126             $resp->assertDontSee('There are no tracked references');
127         }
128     }
129
130     public function test_reference_not_visible_if_view_permission_does_not_permit()
131     {
132         $page = $this->entities->page();
133         $pageB = $this->entities->page();
134         $this->createReference($pageB, $page);
135
136         $this->permissions->setEntityPermissions($pageB);
137
138         $this->asEditor()->get($page->getUrl('/references'))->assertDontSee($pageB->name);
139         $this->asAdmin()->get($page->getUrl('/references'))->assertSee($pageB->name);
140     }
141
142     public function test_reference_page_shows_empty_state_with_no_references()
143     {
144         $page = $this->entities->page();
145
146         $this->asEditor()
147             ->get($page->getUrl('/references'))
148             ->assertSee('There are no tracked references');
149     }
150
151     public function test_pages_leading_to_entity_updated_on_url_change()
152     {
153         $pageA = $this->entities->page();
154         $pageB = $this->entities->page();
155         $book = $this->entities->book();
156
157         foreach ([$pageA, $pageB] as $page) {
158             $page->html = '<a href="' . $book->getUrl() . '">Link</a>';
159             $page->save();
160             $this->createReference($page, $book);
161         }
162
163         $this->asEditor()->put($book->getUrl(), [
164             'name' => 'my updated book slugaroo',
165         ]);
166
167         foreach ([$pageA, $pageB] as $page) {
168             $page->refresh();
169             $this->assertStringContainsString('href="http://localhost/books/my-updated-book-slugaroo"', $page->html);
170             $this->assertDatabaseHas('page_revisions', [
171                 'page_id' => $page->id,
172                 'summary' => 'System auto-update of internal links',
173             ]);
174         }
175     }
176
177     public function test_pages_linking_to_other_page_updated_on_parent_book_url_change()
178     {
179         $bookPage = $this->entities->page();
180         $otherPage = $this->entities->page();
181         $book = $bookPage->book;
182
183         $otherPage->html = '<a href="' . $bookPage->getUrl() . '">Link</a>';
184         $otherPage->save();
185         $this->createReference($otherPage, $bookPage);
186
187         $this->asEditor()->put($book->getUrl(), [
188             'name' => 'my updated book slugaroo',
189         ]);
190
191         $otherPage->refresh();
192         $this->assertStringContainsString('href="http://localhost/books/my-updated-book-slugaroo/page/' . $bookPage->slug . '"', $otherPage->html);
193         $this->assertDatabaseHas('page_revisions', [
194             'page_id' => $otherPage->id,
195             'summary' => 'System auto-update of internal links',
196         ]);
197     }
198
199     public function test_pages_linking_to_chapter_updated_on_parent_book_url_change()
200     {
201         $bookChapter = $this->entities->chapter();
202         $otherPage = $this->entities->page();
203         $book = $bookChapter->book;
204
205         $otherPage->html = '<a href="' . $bookChapter->getUrl() . '">Link</a>';
206         $otherPage->save();
207         $this->createReference($otherPage, $bookChapter);
208
209         $this->asEditor()->put($book->getUrl(), [
210             'name' => 'my updated book slugaroo',
211         ]);
212
213         $otherPage->refresh();
214         $this->assertStringContainsString('href="http://localhost/books/my-updated-book-slugaroo/chapter/' . $bookChapter->slug . '"', $otherPage->html);
215         $this->assertDatabaseHas('page_revisions', [
216             'page_id' => $otherPage->id,
217             'summary' => 'System auto-update of internal links',
218         ]);
219     }
220
221     public function test_markdown_links_leading_to_entity_updated_on_url_change()
222     {
223         $page = $this->entities->page();
224         $book = $this->entities->book();
225
226         $bookUrl = $book->getUrl();
227         $markdown = '
228         [An awesome link](' . $bookUrl . ')
229         [An awesome link with query & hash](' . $bookUrl . '?test=yes#cats)
230         [An awesome link with path](' . $bookUrl . '/an/extra/trail)
231         [An awesome link with title](' . $bookUrl . ' "title")
232         [ref]: ' . $bookUrl . '?test=yes#dogs
233         [ref_without_space]:' . $bookUrl . '
234         [ref_with_title]: ' . $bookUrl . ' "title"';
235         $page->markdown = $markdown;
236         $page->save();
237         $this->createReference($page, $book);
238
239         $this->asEditor()->put($book->getUrl(), [
240             'name' => 'my updated book slugadoo',
241         ]);
242
243         $page->refresh();
244         $expected = str_replace($bookUrl, 'http://localhost/books/my-updated-book-slugadoo', $markdown);
245         $this->assertEquals($expected, $page->markdown);
246     }
247
248     public function test_description_links_from_book_chapter_shelf_updated_on_url_change()
249     {
250         $entities = [$this->entities->chapter(), $this->entities->book(), $this->entities->shelf()];
251         $shelf = $this->entities->shelf();
252         $this->asEditor();
253
254         foreach ($entities as $entity) {
255             $this->put($entity->getUrl(), [
256                 'name' => 'Reference test',
257                 'description_html' => '<a href="' . $shelf->getUrl() . '">Testing</a>',
258             ]);
259         }
260
261         $oldUrl = $shelf->getUrl();
262         $this->put($shelf->getUrl(), ['name' => 'My updated shelf link']);
263         $shelf->refresh();
264         $this->assertNotEquals($oldUrl, $shelf->getUrl());
265
266         foreach ($entities as $entity) {
267             $oldHtml = $entity->description_html;
268             $entity->refresh();
269             $this->assertNotEquals($oldHtml, $entity->description_html);
270             $this->assertStringContainsString($shelf->getUrl(), $entity->description_html);
271         }
272     }
273
274     protected function createReference(Model $from, Model $to)
275     {
276         (new Reference())->forceFill([
277             'from_type' => $from->getMorphClass(),
278             'from_id'   => $from->id,
279             'to_type'   => $to->getMorphClass(),
280             'to_id'     => $to->id,
281         ])->save();
282     }
283 }