]> BookStack Code Mirror - bookstack/blob - tests/Entity/EntitySearchTest.php
Fixed issues preventing breadcrumb navigation menus from opening
[bookstack] / tests / Entity / EntitySearchTest.php
1 <?php namespace Tests;
2
3 use BookStack\Actions\Tag;
4 use BookStack\Entities\Book;
5 use BookStack\Entities\Bookshelf;
6 use BookStack\Entities\Chapter;
7 use BookStack\Entities\Page;
8
9 class EntitySearchTest extends TestCase
10 {
11
12     public function test_page_search()
13     {
14         $book = Book::all()->first();
15         $page = $book->pages->first();
16
17         $search = $this->asEditor()->get('/search?term=' . urlencode($page->name));
18         $search->assertSee('Search Results');
19         $search->assertSee($page->name);
20     }
21
22     public function test_bookshelf_search()
23     {
24         $shelf = Bookshelf::first();
25         $search = $this->asEditor()->get('/search?term=' . urlencode(mb_substr($shelf->name, 0, 3)) . '  {type:bookshelf}');
26         $search->assertStatus(200);
27         $search->assertSee($shelf->name);
28     }
29
30     public function test_invalid_page_search()
31     {
32         $resp = $this->asEditor()->get('/search?term=' . urlencode('<p>test</p>'));
33         $resp->assertSee('Search Results');
34         $resp->assertStatus(200);
35         $this->get('/search?term=cat+-')->assertStatus(200);
36     }
37
38     public function test_empty_search_shows_search_page()
39     {
40         $res = $this->asEditor()->get('/search');
41         $res->assertStatus(200);
42     }
43
44     public function test_searching_accents_and_small_terms()
45     {
46         $page = $this->newPage(['name' => 'My new test quaffleachits', 'html' => 'some áéííúü¿¡ test content a2 orange dog']);
47         $this->asEditor();
48
49         $accentSearch = $this->get('/search?term=' . urlencode('áéíí'));
50         $accentSearch->assertStatus(200)->assertSee($page->name);
51
52         $smallSearch = $this->get('/search?term=' . urlencode('a2'));
53         $smallSearch->assertStatus(200)->assertSee($page->name);
54     }
55
56     public function test_book_search()
57     {
58         $book = Book::first();
59         $page = $book->pages->last();
60         $chapter = $book->chapters->last();
61
62         $pageTestResp = $this->asEditor()->get('/search/book/' . $book->id . '?term=' . urlencode($page->name));
63         $pageTestResp->assertSee($page->name);
64
65         $chapterTestResp = $this->asEditor()->get('/search/book/' . $book->id . '?term=' . urlencode($chapter->name));
66         $chapterTestResp->assertSee($chapter->name);
67     }
68
69     public function test_chapter_search()
70     {
71         $chapter = Chapter::has('pages')->first();
72         $page = $chapter->pages[0];
73
74         $pageTestResp = $this->asEditor()->get('/search/chapter/' . $chapter->id . '?term=' . urlencode($page->name));
75         $pageTestResp->assertSee($page->name);
76     }
77
78     public function test_tag_search()
79     {
80         $newTags = [
81             new Tag([
82                 'name' => 'animal',
83                 'value' => 'cat'
84             ]),
85             new Tag([
86                 'name' => 'color',
87                 'value' => 'red'
88             ])
89         ];
90
91         $pageA = Page::first();
92         $pageA->tags()->saveMany($newTags);
93
94         $pageB = Page::all()->last();
95         $pageB->tags()->create(['name' => 'animal', 'value' => 'dog']);
96
97         $this->asEditor();
98         $tNameSearch = $this->get('/search?term=%5Banimal%5D');
99         $tNameSearch->assertSee($pageA->name)->assertSee($pageB->name);
100
101         $tNameSearch2 = $this->get('/search?term=%5Bcolor%5D');
102         $tNameSearch2->assertSee($pageA->name)->assertDontSee($pageB->name);
103
104         $tNameValSearch = $this->get('/search?term=%5Banimal%3Dcat%5D');
105         $tNameValSearch->assertSee($pageA->name)->assertDontSee($pageB->name);
106     }
107
108     public function test_exact_searches()
109     {
110         $page = $this->newPage(['name' => 'My new test page', 'html' => 'this is a story about an orange donkey']);
111
112         $exactSearchA = $this->asEditor()->get('/search?term=' . urlencode('"story about an orange"'));
113         $exactSearchA->assertStatus(200)->assertSee($page->name);
114
115         $exactSearchB = $this->asEditor()->get('/search?term=' . urlencode('"story not about an orange"'));
116         $exactSearchB->assertStatus(200)->assertDontSee($page->name);
117     }
118
119     public function test_search_filters()
120     {
121         $page = $this->newPage(['name' => 'My new test quaffleachits', 'html' => 'this is about an orange donkey danzorbhsing']);
122         $this->asEditor();
123         $editorId = $this->getEditor()->id;
124
125         // Viewed filter searches
126         $this->get('/search?term=' . urlencode('danzorbhsing {not_viewed_by_me}'))->assertSee($page->name);
127         $this->get('/search?term=' . urlencode('danzorbhsing {viewed_by_me}'))->assertDontSee($page->name);
128         $this->get($page->getUrl());
129         $this->get('/search?term=' . urlencode('danzorbhsing {not_viewed_by_me}'))->assertDontSee($page->name);
130         $this->get('/search?term=' . urlencode('danzorbhsing {viewed_by_me}'))->assertSee($page->name);
131
132         // User filters
133         $this->get('/search?term=' . urlencode('danzorbhsing {created_by:me}'))->assertDontSee($page->name);
134         $this->get('/search?term=' . urlencode('danzorbhsing {updated_by:me}'))->assertDontSee($page->name);
135         $this->get('/search?term=' . urlencode('danzorbhsing {updated_by:'.$editorId.'}'))->assertDontSee($page->name);
136         $page->created_by = $editorId;
137         $page->save();
138         $this->get('/search?term=' . urlencode('danzorbhsing {created_by:me}'))->assertSee($page->name);
139         $this->get('/search?term=' . urlencode('danzorbhsing {created_by:'.$editorId.'}'))->assertSee($page->name);
140         $this->get('/search?term=' . urlencode('danzorbhsing {updated_by:me}'))->assertDontSee($page->name);
141         $page->updated_by = $editorId;
142         $page->save();
143         $this->get('/search?term=' . urlencode('danzorbhsing {updated_by:me}'))->assertSee($page->name);
144         $this->get('/search?term=' . urlencode('danzorbhsing {updated_by:'.$editorId.'}'))->assertSee($page->name);
145
146         // Content filters
147         $this->get('/search?term=' . urlencode('{in_name:danzorbhsing}'))->assertDontSee($page->name);
148         $this->get('/search?term=' . urlencode('{in_body:danzorbhsing}'))->assertSee($page->name);
149         $this->get('/search?term=' . urlencode('{in_name:test quaffleachits}'))->assertSee($page->name);
150         $this->get('/search?term=' . urlencode('{in_body:test quaffleachits}'))->assertDontSee($page->name);
151
152         // Restricted filter
153         $this->get('/search?term=' . urlencode('danzorbhsing {is_restricted}'))->assertDontSee($page->name);
154         $page->restricted = true;
155         $page->save();
156         $this->get('/search?term=' . urlencode('danzorbhsing {is_restricted}'))->assertSee($page->name);
157
158         // Date filters
159         $this->get('/search?term=' . urlencode('danzorbhsing {updated_after:2037-01-01}'))->assertDontSee($page->name);
160         $this->get('/search?term=' . urlencode('danzorbhsing {updated_before:2037-01-01}'))->assertSee($page->name);
161         $page->updated_at = '2037-02-01';
162         $page->save();
163         $this->get('/search?term=' . urlencode('danzorbhsing {updated_after:2037-01-01}'))->assertSee($page->name);
164         $this->get('/search?term=' . urlencode('danzorbhsing {updated_before:2037-01-01}'))->assertDontSee($page->name);
165
166         $this->get('/search?term=' . urlencode('danzorbhsing {created_after:2037-01-01}'))->assertDontSee($page->name);
167         $this->get('/search?term=' . urlencode('danzorbhsing {created_before:2037-01-01}'))->assertSee($page->name);
168         $page->created_at = '2037-02-01';
169         $page->save();
170         $this->get('/search?term=' . urlencode('danzorbhsing {created_after:2037-01-01}'))->assertSee($page->name);
171         $this->get('/search?term=' . urlencode('danzorbhsing {created_before:2037-01-01}'))->assertDontSee($page->name);
172     }
173
174     public function test_ajax_entity_search()
175     {
176         $page = $this->newPage(['name' => 'my ajax search test', 'html' => 'ajax test']);
177         $notVisitedPage = Page::first();
178
179         // Visit the page to make popular
180         $this->asEditor()->get($page->getUrl());
181
182         $normalSearch = $this->get('/ajax/search/entities?term=' . urlencode($page->name));
183         $normalSearch->assertSee($page->name);
184
185         $bookSearch = $this->get('/ajax/search/entities?types=book&term=' . urlencode($page->name));
186         $bookSearch->assertDontSee($page->name);
187
188         $defaultListTest = $this->get('/ajax/search/entities');
189         $defaultListTest->assertSee($page->name);
190         $defaultListTest->assertDontSee($notVisitedPage->name);
191     }
192
193     public function test_ajax_entity_serach_shows_breadcrumbs()
194     {
195         $chapter = Chapter::first();
196         $page = $chapter->pages->first();
197         $this->asEditor();
198
199         $pageSearch = $this->get('/ajax/search/entities?term=' . urlencode($page->name));
200         $pageSearch->assertSee($page->name);
201         $pageSearch->assertSee($chapter->getShortName(42));
202         $pageSearch->assertSee($page->book->getShortName(42));
203
204         $chapterSearch = $this->get('/ajax/search/entities?term=' . urlencode($chapter->name));
205         $chapterSearch->assertSee($chapter->name);
206         $chapterSearch->assertSee($chapter->book->getShortName(42));
207     }
208
209     public function test_sibling_search_for_pages()
210     {
211         $chapter = Chapter::query()->with('pages')->first();
212         $this->assertGreaterThan(2, count($chapter->pages), 'Ensure we\'re testing with at least 1 sibling');
213         $page = $chapter->pages->first();
214
215         $search = $this->actingAs($this->getViewer())->get("/search/entity/siblings?entity_id={$page->id}&entity_type=page");
216         $search->assertSuccessful();
217         foreach ($chapter->pages as $page) {
218             $search->assertSee($page->name);
219         }
220
221         $search->assertDontSee($chapter->name);
222     }
223
224     public function test_sibling_search_for_pages_without_chapter()
225     {
226         $page = Page::query()->where('chapter_id', '=', 0)->firstOrFail();
227         $bookChildren = $page->book->getDirectChildren();
228         $this->assertGreaterThan(2, count($bookChildren), 'Ensure we\'re testing with at least 1 sibling');
229
230         $search = $this->actingAs($this->getViewer())->get("/search/entity/siblings?entity_id={$page->id}&entity_type=page");
231         $search->assertSuccessful();
232         foreach ($bookChildren as $child) {
233             $search->assertSee($child->name);
234         }
235
236         $search->assertDontSee($page->book->name);
237     }
238
239     public function test_sibling_search_for_chapters()
240     {
241         $chapter = Chapter::query()->firstOrFail();
242         $bookChildren = $chapter->book->getDirectChildren();
243         $this->assertGreaterThan(2, count($bookChildren), 'Ensure we\'re testing with at least 1 sibling');
244
245         $search = $this->actingAs($this->getViewer())->get("/search/entity/siblings?entity_id={$chapter->id}&entity_type=chapter");
246         $search->assertSuccessful();
247         foreach ($bookChildren as $child) {
248             $search->assertSee($child->name);
249         }
250
251         $search->assertDontSee($chapter->book->name);
252     }
253
254     public function test_sibling_search_for_books()
255     {
256         $books = Book::query()->take(10)->get();
257         $book = $books->first();
258         $this->assertGreaterThan(2, count($books), 'Ensure we\'re testing with at least 1 sibling');
259
260         $search = $this->actingAs($this->getViewer())->get("/search/entity/siblings?entity_id={$book->id}&entity_type=book");
261         $search->assertSuccessful();
262         foreach ($books as $expectedBook) {
263             $search->assertSee($expectedBook->name);
264         }
265     }
266
267     public function test_sibling_search_for_shelves()
268     {
269         $shelves = Bookshelf::query()->take(10)->get();
270         $shelf = $shelves->first();
271         $this->assertGreaterThan(2, count($shelves), 'Ensure we\'re testing with at least 1 sibling');
272
273         $search = $this->actingAs($this->getViewer())->get("/search/entity/siblings?entity_id={$shelf->id}&entity_type=bookshelf");
274         $search->assertSuccessful();
275         foreach ($shelves as $expectedShelf) {
276             $search->assertSee($expectedShelf->name);
277         }
278     }
279 }