diff options
Diffstat (limited to 'tests/front/controller')
-rw-r--r-- | tests/front/controller/visitor/BookmarkListControllerTest.php | 448 |
1 files changed, 448 insertions, 0 deletions
diff --git a/tests/front/controller/visitor/BookmarkListControllerTest.php b/tests/front/controller/visitor/BookmarkListControllerTest.php new file mode 100644 index 00000000..5daaa2c4 --- /dev/null +++ b/tests/front/controller/visitor/BookmarkListControllerTest.php | |||
@@ -0,0 +1,448 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller\Visitor; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Shaarli\Bookmark\Bookmark; | ||
9 | use Shaarli\Bookmark\Exception\BookmarkNotFoundException; | ||
10 | use Shaarli\Config\ConfigManager; | ||
11 | use Shaarli\Security\LoginManager; | ||
12 | use Shaarli\Thumbnailer; | ||
13 | use Slim\Http\Request; | ||
14 | use Slim\Http\Response; | ||
15 | |||
16 | class BookmarkListControllerTest extends TestCase | ||
17 | { | ||
18 | use FrontControllerMockHelper; | ||
19 | |||
20 | /** @var BookmarkListController */ | ||
21 | protected $controller; | ||
22 | |||
23 | public function setUp(): void | ||
24 | { | ||
25 | $this->createContainer(); | ||
26 | |||
27 | $this->controller = new BookmarkListController($this->container); | ||
28 | } | ||
29 | |||
30 | /** | ||
31 | * Test rendering list of bookmarks with default parameters (first page). | ||
32 | */ | ||
33 | public function testIndexDefaultFirstPage(): void | ||
34 | { | ||
35 | $assignedVariables = []; | ||
36 | $this->assignTemplateVars($assignedVariables); | ||
37 | |||
38 | $request = $this->createMock(Request::class); | ||
39 | $response = new Response(); | ||
40 | |||
41 | $this->container->bookmarkService | ||
42 | ->expects(static::once()) | ||
43 | ->method('search') | ||
44 | ->with( | ||
45 | ['searchtags' => '', 'searchterm' => ''], | ||
46 | null, | ||
47 | false, | ||
48 | false | ||
49 | ) | ||
50 | ->willReturn([ | ||
51 | (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), | ||
52 | (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), | ||
53 | (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), | ||
54 | ] | ||
55 | ); | ||
56 | |||
57 | $this->container->sessionManager | ||
58 | ->method('getSessionParameter') | ||
59 | ->willReturnCallback(function (string $parameter, $default = null) { | ||
60 | if ('LINKS_PER_PAGE' === $parameter) { | ||
61 | return 2; | ||
62 | } | ||
63 | |||
64 | return $default; | ||
65 | }) | ||
66 | ; | ||
67 | |||
68 | $result = $this->controller->index($request, $response); | ||
69 | |||
70 | static::assertSame(200, $result->getStatusCode()); | ||
71 | static::assertSame('linklist', (string) $result->getBody()); | ||
72 | |||
73 | static::assertSame('Shaarli', $assignedVariables['pagetitle']); | ||
74 | static::assertSame('?page=2', $assignedVariables['previous_page_url']); | ||
75 | static::assertSame('', $assignedVariables['next_page_url']); | ||
76 | static::assertSame(2, $assignedVariables['page_max']); | ||
77 | static::assertSame('', $assignedVariables['search_tags']); | ||
78 | static::assertSame(3, $assignedVariables['result_count']); | ||
79 | static::assertSame(1, $assignedVariables['page_current']); | ||
80 | static::assertSame('', $assignedVariables['search_term']); | ||
81 | static::assertNull($assignedVariables['visibility']); | ||
82 | static::assertCount(2, $assignedVariables['links']); | ||
83 | |||
84 | $link = $assignedVariables['links'][0]; | ||
85 | |||
86 | static::assertSame(1, $link['id']); | ||
87 | static::assertSame('http://url1.tld', $link['url']); | ||
88 | static::assertSame('Title 1', $link['title']); | ||
89 | |||
90 | $link = $assignedVariables['links'][1]; | ||
91 | |||
92 | static::assertSame(2, $link['id']); | ||
93 | static::assertSame('http://url2.tld', $link['url']); | ||
94 | static::assertSame('Title 2', $link['title']); | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * Test rendering list of bookmarks with default parameters (second page). | ||
99 | */ | ||
100 | public function testIndexDefaultSecondPage(): void | ||
101 | { | ||
102 | $assignedVariables = []; | ||
103 | $this->assignTemplateVars($assignedVariables); | ||
104 | |||
105 | $request = $this->createMock(Request::class); | ||
106 | $request->method('getParam')->willReturnCallback(function (string $key) { | ||
107 | if ('page' === $key) { | ||
108 | return '2'; | ||
109 | } | ||
110 | |||
111 | return null; | ||
112 | }); | ||
113 | $response = new Response(); | ||
114 | |||
115 | $this->container->bookmarkService | ||
116 | ->expects(static::once()) | ||
117 | ->method('search') | ||
118 | ->with( | ||
119 | ['searchtags' => '', 'searchterm' => ''], | ||
120 | null, | ||
121 | false, | ||
122 | false | ||
123 | ) | ||
124 | ->willReturn([ | ||
125 | (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), | ||
126 | (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), | ||
127 | (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), | ||
128 | ]) | ||
129 | ; | ||
130 | |||
131 | $this->container->sessionManager | ||
132 | ->method('getSessionParameter') | ||
133 | ->willReturnCallback(function (string $parameter, $default = null) { | ||
134 | if ('LINKS_PER_PAGE' === $parameter) { | ||
135 | return 2; | ||
136 | } | ||
137 | |||
138 | return $default; | ||
139 | }) | ||
140 | ; | ||
141 | |||
142 | $result = $this->controller->index($request, $response); | ||
143 | |||
144 | static::assertSame(200, $result->getStatusCode()); | ||
145 | static::assertSame('linklist', (string) $result->getBody()); | ||
146 | |||
147 | static::assertSame('Shaarli', $assignedVariables['pagetitle']); | ||
148 | static::assertSame('', $assignedVariables['previous_page_url']); | ||
149 | static::assertSame('?page=1', $assignedVariables['next_page_url']); | ||
150 | static::assertSame(2, $assignedVariables['page_max']); | ||
151 | static::assertSame('', $assignedVariables['search_tags']); | ||
152 | static::assertSame(3, $assignedVariables['result_count']); | ||
153 | static::assertSame(2, $assignedVariables['page_current']); | ||
154 | static::assertSame('', $assignedVariables['search_term']); | ||
155 | static::assertNull($assignedVariables['visibility']); | ||
156 | static::assertCount(1, $assignedVariables['links']); | ||
157 | |||
158 | $link = $assignedVariables['links'][2]; | ||
159 | |||
160 | static::assertSame(3, $link['id']); | ||
161 | static::assertSame('http://url3.tld', $link['url']); | ||
162 | static::assertSame('Title 3', $link['title']); | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * Test rendering list of bookmarks with filters. | ||
167 | */ | ||
168 | public function testIndexDefaultWithFilters(): void | ||
169 | { | ||
170 | $assignedVariables = []; | ||
171 | $this->assignTemplateVars($assignedVariables); | ||
172 | |||
173 | $request = $this->createMock(Request::class); | ||
174 | $request->method('getParam')->willReturnCallback(function (string $key) { | ||
175 | if ('searchtags' === $key) { | ||
176 | return 'abc def'; | ||
177 | } | ||
178 | if ('searchterm' === $key) { | ||
179 | return 'ghi jkl'; | ||
180 | } | ||
181 | |||
182 | return null; | ||
183 | }); | ||
184 | $response = new Response(); | ||
185 | |||
186 | $this->container->sessionManager | ||
187 | ->method('getSessionParameter') | ||
188 | ->willReturnCallback(function (string $key, $default) { | ||
189 | if ('LINKS_PER_PAGE' === $key) { | ||
190 | return 2; | ||
191 | } | ||
192 | if ('visibility' === $key) { | ||
193 | return 'private'; | ||
194 | } | ||
195 | if ('untaggedonly' === $key) { | ||
196 | return true; | ||
197 | } | ||
198 | |||
199 | return $default; | ||
200 | }) | ||
201 | ; | ||
202 | |||
203 | $this->container->bookmarkService | ||
204 | ->expects(static::once()) | ||
205 | ->method('search') | ||
206 | ->with( | ||
207 | ['searchtags' => 'abc def', 'searchterm' => 'ghi jkl'], | ||
208 | 'private', | ||
209 | false, | ||
210 | true | ||
211 | ) | ||
212 | ->willReturn([ | ||
213 | (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), | ||
214 | (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), | ||
215 | (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), | ||
216 | ]) | ||
217 | ; | ||
218 | |||
219 | $result = $this->controller->index($request, $response); | ||
220 | |||
221 | static::assertSame(200, $result->getStatusCode()); | ||
222 | static::assertSame('linklist', (string) $result->getBody()); | ||
223 | |||
224 | static::assertSame('Search: ghi jkl [abc] [def] - Shaarli', $assignedVariables['pagetitle']); | ||
225 | static::assertSame('?page=2&searchterm=ghi+jkl&searchtags=abc+def', $assignedVariables['previous_page_url']); | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * Test displaying a permalink with valid parameters | ||
230 | */ | ||
231 | public function testPermalinkValid(): void | ||
232 | { | ||
233 | $hash = 'abcdef'; | ||
234 | |||
235 | $assignedVariables = []; | ||
236 | $this->assignTemplateVars($assignedVariables); | ||
237 | |||
238 | $request = $this->createMock(Request::class); | ||
239 | $response = new Response(); | ||
240 | |||
241 | $this->container->bookmarkService | ||
242 | ->expects(static::once()) | ||
243 | ->method('findByHash') | ||
244 | ->with($hash) | ||
245 | ->willReturn((new Bookmark())->setId(123)->setTitle('Title 1')->setUrl('http://url1.tld')) | ||
246 | ; | ||
247 | |||
248 | $result = $this->controller->permalink($request, $response, ['hash' => $hash]); | ||
249 | |||
250 | static::assertSame(200, $result->getStatusCode()); | ||
251 | static::assertSame('linklist', (string) $result->getBody()); | ||
252 | |||
253 | static::assertSame('Title 1 - Shaarli', $assignedVariables['pagetitle']); | ||
254 | static::assertCount(1, $assignedVariables['links']); | ||
255 | |||
256 | $link = $assignedVariables['links'][0]; | ||
257 | |||
258 | static::assertSame(123, $link['id']); | ||
259 | static::assertSame('http://url1.tld', $link['url']); | ||
260 | static::assertSame('Title 1', $link['title']); | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * Test displaying a permalink with an unknown small hash : renders a 404 template error | ||
265 | */ | ||
266 | public function testPermalinkNotFound(): void | ||
267 | { | ||
268 | $hash = 'abcdef'; | ||
269 | |||
270 | $assignedVariables = []; | ||
271 | $this->assignTemplateVars($assignedVariables); | ||
272 | |||
273 | $request = $this->createMock(Request::class); | ||
274 | $response = new Response(); | ||
275 | |||
276 | $this->container->bookmarkService | ||
277 | ->expects(static::once()) | ||
278 | ->method('findByHash') | ||
279 | ->with($hash) | ||
280 | ->willThrowException(new BookmarkNotFoundException()) | ||
281 | ; | ||
282 | |||
283 | $result = $this->controller->permalink($request, $response, ['hash' => $hash]); | ||
284 | |||
285 | static::assertSame(200, $result->getStatusCode()); | ||
286 | static::assertSame('404', (string) $result->getBody()); | ||
287 | |||
288 | static::assertSame( | ||
289 | 'The link you are trying to reach does not exist or has been deleted.', | ||
290 | $assignedVariables['error_message'] | ||
291 | ); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * Test getting link list with thumbnail updates. | ||
296 | * -> 2 thumbnails update, only 1 datastore write | ||
297 | */ | ||
298 | public function testThumbnailUpdateFromLinkList(): void | ||
299 | { | ||
300 | $request = $this->createMock(Request::class); | ||
301 | $response = new Response(); | ||
302 | |||
303 | $this->container->loginManager = $this->createMock(LoginManager::class); | ||
304 | $this->container->loginManager->method('isLoggedIn')->willReturn(true); | ||
305 | |||
306 | $this->container->conf = $this->createMock(ConfigManager::class); | ||
307 | $this->container->conf | ||
308 | ->method('get') | ||
309 | ->willReturnCallback(function (string $key, $default) { | ||
310 | return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default; | ||
311 | }) | ||
312 | ; | ||
313 | |||
314 | $this->container->thumbnailer = $this->createMock(Thumbnailer::class); | ||
315 | $this->container->thumbnailer | ||
316 | ->expects(static::exactly(2)) | ||
317 | ->method('get') | ||
318 | ->withConsecutive(['https://url2.tld'], ['https://url4.tld']) | ||
319 | ; | ||
320 | |||
321 | $this->container->bookmarkService | ||
322 | ->expects(static::once()) | ||
323 | ->method('search') | ||
324 | ->willReturn([ | ||
325 | (new Bookmark())->setId(1)->setUrl('https://url1.tld')->setTitle('Title 1')->setThumbnail(false), | ||
326 | $b1 = (new Bookmark())->setId(2)->setUrl('https://url2.tld')->setTitle('Title 2'), | ||
327 | (new Bookmark())->setId(3)->setUrl('https://url3.tld')->setTitle('Title 3')->setThumbnail(false), | ||
328 | $b2 = (new Bookmark())->setId(2)->setUrl('https://url4.tld')->setTitle('Title 4'), | ||
329 | (new Bookmark())->setId(2)->setUrl('ftp://url5.tld', ['ftp'])->setTitle('Title 5'), | ||
330 | ]) | ||
331 | ; | ||
332 | $this->container->bookmarkService | ||
333 | ->expects(static::exactly(2)) | ||
334 | ->method('set') | ||
335 | ->withConsecutive([$b1, false], [$b2, false]) | ||
336 | ; | ||
337 | $this->container->bookmarkService->expects(static::once())->method('save'); | ||
338 | |||
339 | $result = $this->controller->index($request, $response); | ||
340 | |||
341 | static::assertSame(200, $result->getStatusCode()); | ||
342 | static::assertSame('linklist', (string) $result->getBody()); | ||
343 | } | ||
344 | |||
345 | /** | ||
346 | * Test getting a permalink with thumbnail update. | ||
347 | */ | ||
348 | public function testThumbnailUpdateFromPermalink(): void | ||
349 | { | ||
350 | $request = $this->createMock(Request::class); | ||
351 | $response = new Response(); | ||
352 | |||
353 | $this->container->loginManager = $this->createMock(LoginManager::class); | ||
354 | $this->container->loginManager->method('isLoggedIn')->willReturn(true); | ||
355 | |||
356 | $this->container->conf = $this->createMock(ConfigManager::class); | ||
357 | $this->container->conf | ||
358 | ->method('get') | ||
359 | ->willReturnCallback(function (string $key, $default) { | ||
360 | return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default; | ||
361 | }) | ||
362 | ; | ||
363 | |||
364 | $this->container->thumbnailer = $this->createMock(Thumbnailer::class); | ||
365 | $this->container->thumbnailer->expects(static::once())->method('get')->withConsecutive(['https://url.tld']); | ||
366 | |||
367 | $this->container->bookmarkService | ||
368 | ->expects(static::once()) | ||
369 | ->method('findByHash') | ||
370 | ->willReturn($bookmark = (new Bookmark())->setId(2)->setUrl('https://url.tld')->setTitle('Title 1')) | ||
371 | ; | ||
372 | $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, true); | ||
373 | $this->container->bookmarkService->expects(static::never())->method('save'); | ||
374 | |||
375 | $result = $this->controller->permalink($request, $response, ['hash' => 'abc']); | ||
376 | |||
377 | static::assertSame(200, $result->getStatusCode()); | ||
378 | static::assertSame('linklist', (string) $result->getBody()); | ||
379 | } | ||
380 | |||
381 | /** | ||
382 | * Trigger legacy controller in link list controller: permalink | ||
383 | */ | ||
384 | public function testLegacyControllerPermalink(): void | ||
385 | { | ||
386 | $hash = 'abcdef'; | ||
387 | $this->container->environment['QUERY_STRING'] = $hash; | ||
388 | |||
389 | $request = $this->createMock(Request::class); | ||
390 | $response = new Response(); | ||
391 | |||
392 | $result = $this->controller->index($request, $response); | ||
393 | |||
394 | static::assertSame(302, $result->getStatusCode()); | ||
395 | static::assertSame('/subfolder/shaare/' . $hash, $result->getHeader('location')[0]); | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * Trigger legacy controller in link list controller: ?do= query parameter | ||
400 | */ | ||
401 | public function testLegacyControllerDoPage(): void | ||
402 | { | ||
403 | $request = $this->createMock(Request::class); | ||
404 | $request->method('getQueryParam')->with('do')->willReturn('picwall'); | ||
405 | $response = new Response(); | ||
406 | |||
407 | $result = $this->controller->index($request, $response); | ||
408 | |||
409 | static::assertSame(302, $result->getStatusCode()); | ||
410 | static::assertSame('/subfolder/picture-wall', $result->getHeader('location')[0]); | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * Trigger legacy controller in link list controller: ?do= query parameter with unknown legacy route | ||
415 | */ | ||
416 | public function testLegacyControllerUnknownDoPage(): void | ||
417 | { | ||
418 | $request = $this->createMock(Request::class); | ||
419 | $request->method('getQueryParam')->with('do')->willReturn('nope'); | ||
420 | $response = new Response(); | ||
421 | |||
422 | $result = $this->controller->index($request, $response); | ||
423 | |||
424 | static::assertSame(200, $result->getStatusCode()); | ||
425 | static::assertSame('linklist', (string) $result->getBody()); | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * Trigger legacy controller in link list controller: other GET route (e.g. ?post) | ||
430 | */ | ||
431 | public function testLegacyControllerGetParameter(): void | ||
432 | { | ||
433 | $request = $this->createMock(Request::class); | ||
434 | $request->method('getQueryParams')->willReturn(['post' => $url = 'http://url.tld']); | ||
435 | $response = new Response(); | ||
436 | |||
437 | $this->container->loginManager = $this->createMock(LoginManager::class); | ||
438 | $this->container->loginManager->method('isLoggedIn')->willReturn(true); | ||
439 | |||
440 | $result = $this->controller->index($request, $response); | ||
441 | |||
442 | static::assertSame(302, $result->getStatusCode()); | ||
443 | static::assertSame( | ||
444 | '/subfolder/admin/shaare?post=' . urlencode($url), | ||
445 | $result->getHeader('location')[0] | ||
446 | ); | ||
447 | } | ||
448 | } | ||