diff options
Diffstat (limited to 'tests/front/controller/visitor')
9 files changed, 1938 insertions, 0 deletions
diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php new file mode 100644 index 00000000..6ff769fc --- /dev/null +++ b/tests/front/controller/visitor/DailyControllerTest.php | |||
@@ -0,0 +1,497 @@ | |||
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\Feed\CachedPage; | ||
10 | use Slim\Http\Request; | ||
11 | use Slim\Http\Response; | ||
12 | |||
13 | class DailyControllerTest extends TestCase | ||
14 | { | ||
15 | use FrontControllerMockHelper; | ||
16 | |||
17 | /** @var DailyController */ | ||
18 | protected $controller; | ||
19 | |||
20 | public function setUp(): void | ||
21 | { | ||
22 | $this->createContainer(); | ||
23 | |||
24 | $this->controller = new DailyController($this->container); | ||
25 | DailyController::$DAILY_RSS_NB_DAYS = 2; | ||
26 | } | ||
27 | |||
28 | public function testValidIndexControllerInvokeDefault(): void | ||
29 | { | ||
30 | $this->createValidContainerMockSet(); | ||
31 | |||
32 | $currentDay = new \DateTimeImmutable('2020-05-13'); | ||
33 | |||
34 | $request = $this->createMock(Request::class); | ||
35 | $request->method('getQueryParam')->willReturn($currentDay->format('Ymd')); | ||
36 | $response = new Response(); | ||
37 | |||
38 | // Save RainTPL assigned variables | ||
39 | $assignedVariables = []; | ||
40 | $this->assignTemplateVars($assignedVariables); | ||
41 | |||
42 | // Links dataset: 2 links with thumbnails | ||
43 | $this->container->bookmarkService | ||
44 | ->expects(static::once()) | ||
45 | ->method('days') | ||
46 | ->willReturnCallback(function () use ($currentDay): array { | ||
47 | return [ | ||
48 | '20200510', | ||
49 | $currentDay->format('Ymd'), | ||
50 | '20200516', | ||
51 | ]; | ||
52 | }) | ||
53 | ; | ||
54 | $this->container->bookmarkService | ||
55 | ->expects(static::once()) | ||
56 | ->method('filterDay') | ||
57 | ->willReturnCallback(function (): array { | ||
58 | return [ | ||
59 | (new Bookmark()) | ||
60 | ->setId(1) | ||
61 | ->setUrl('http://url.tld') | ||
62 | ->setTitle(static::generateContent(50)) | ||
63 | ->setDescription(static::generateContent(500)) | ||
64 | , | ||
65 | (new Bookmark()) | ||
66 | ->setId(2) | ||
67 | ->setUrl('http://url2.tld') | ||
68 | ->setTitle(static::generateContent(50)) | ||
69 | ->setDescription(static::generateContent(500)) | ||
70 | , | ||
71 | (new Bookmark()) | ||
72 | ->setId(3) | ||
73 | ->setUrl('http://url3.tld') | ||
74 | ->setTitle(static::generateContent(50)) | ||
75 | ->setDescription(static::generateContent(500)) | ||
76 | , | ||
77 | ]; | ||
78 | }) | ||
79 | ; | ||
80 | |||
81 | // Make sure that PluginManager hook is triggered | ||
82 | $this->container->pluginManager | ||
83 | ->expects(static::at(0)) | ||
84 | ->method('executeHooks') | ||
85 | ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { | ||
86 | static::assertSame('render_daily', $hook); | ||
87 | |||
88 | static::assertArrayHasKey('linksToDisplay', $data); | ||
89 | static::assertCount(3, $data['linksToDisplay']); | ||
90 | static::assertSame(1, $data['linksToDisplay'][0]['id']); | ||
91 | static::assertSame($currentDay->getTimestamp(), $data['day']); | ||
92 | static::assertSame('20200510', $data['previousday']); | ||
93 | static::assertSame('20200516', $data['nextday']); | ||
94 | |||
95 | static::assertArrayHasKey('loggedin', $param); | ||
96 | |||
97 | return $data; | ||
98 | }) | ||
99 | ; | ||
100 | |||
101 | $result = $this->controller->index($request, $response); | ||
102 | |||
103 | static::assertSame(200, $result->getStatusCode()); | ||
104 | static::assertSame('daily', (string) $result->getBody()); | ||
105 | static::assertSame( | ||
106 | 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', | ||
107 | $assignedVariables['pagetitle'] | ||
108 | ); | ||
109 | static::assertEquals($currentDay, $assignedVariables['dayDate']); | ||
110 | static::assertEquals($currentDay->getTimestamp(), $assignedVariables['day']); | ||
111 | static::assertCount(3, $assignedVariables['linksToDisplay']); | ||
112 | |||
113 | $link = $assignedVariables['linksToDisplay'][0]; | ||
114 | |||
115 | static::assertSame(1, $link['id']); | ||
116 | static::assertSame('http://url.tld', $link['url']); | ||
117 | static::assertNotEmpty($link['title']); | ||
118 | static::assertNotEmpty($link['description']); | ||
119 | static::assertNotEmpty($link['formatedDescription']); | ||
120 | |||
121 | $link = $assignedVariables['linksToDisplay'][1]; | ||
122 | |||
123 | static::assertSame(2, $link['id']); | ||
124 | static::assertSame('http://url2.tld', $link['url']); | ||
125 | static::assertNotEmpty($link['title']); | ||
126 | static::assertNotEmpty($link['description']); | ||
127 | static::assertNotEmpty($link['formatedDescription']); | ||
128 | |||
129 | $link = $assignedVariables['linksToDisplay'][2]; | ||
130 | |||
131 | static::assertSame(3, $link['id']); | ||
132 | static::assertSame('http://url3.tld', $link['url']); | ||
133 | static::assertNotEmpty($link['title']); | ||
134 | static::assertNotEmpty($link['description']); | ||
135 | static::assertNotEmpty($link['formatedDescription']); | ||
136 | |||
137 | static::assertCount(3, $assignedVariables['cols']); | ||
138 | static::assertCount(1, $assignedVariables['cols'][0]); | ||
139 | static::assertCount(1, $assignedVariables['cols'][1]); | ||
140 | static::assertCount(1, $assignedVariables['cols'][2]); | ||
141 | |||
142 | $link = $assignedVariables['cols'][0][0]; | ||
143 | |||
144 | static::assertSame(1, $link['id']); | ||
145 | static::assertSame('http://url.tld', $link['url']); | ||
146 | static::assertNotEmpty($link['title']); | ||
147 | static::assertNotEmpty($link['description']); | ||
148 | static::assertNotEmpty($link['formatedDescription']); | ||
149 | |||
150 | $link = $assignedVariables['cols'][1][0]; | ||
151 | |||
152 | static::assertSame(2, $link['id']); | ||
153 | static::assertSame('http://url2.tld', $link['url']); | ||
154 | static::assertNotEmpty($link['title']); | ||
155 | static::assertNotEmpty($link['description']); | ||
156 | static::assertNotEmpty($link['formatedDescription']); | ||
157 | |||
158 | $link = $assignedVariables['cols'][2][0]; | ||
159 | |||
160 | static::assertSame(3, $link['id']); | ||
161 | static::assertSame('http://url3.tld', $link['url']); | ||
162 | static::assertNotEmpty($link['title']); | ||
163 | static::assertNotEmpty($link['description']); | ||
164 | static::assertNotEmpty($link['formatedDescription']); | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * Daily page - test that everything goes fine with no future or past bookmarks | ||
169 | */ | ||
170 | public function testValidIndexControllerInvokeNoFutureOrPast(): void | ||
171 | { | ||
172 | $this->createValidContainerMockSet(); | ||
173 | |||
174 | $currentDay = new \DateTimeImmutable('2020-05-13'); | ||
175 | |||
176 | $request = $this->createMock(Request::class); | ||
177 | $response = new Response(); | ||
178 | |||
179 | // Save RainTPL assigned variables | ||
180 | $assignedVariables = []; | ||
181 | $this->assignTemplateVars($assignedVariables); | ||
182 | |||
183 | // Links dataset: 2 links with thumbnails | ||
184 | $this->container->bookmarkService | ||
185 | ->expects(static::once()) | ||
186 | ->method('days') | ||
187 | ->willReturnCallback(function () use ($currentDay): array { | ||
188 | return [ | ||
189 | $currentDay->format($currentDay->format('Ymd')), | ||
190 | ]; | ||
191 | }) | ||
192 | ; | ||
193 | $this->container->bookmarkService | ||
194 | ->expects(static::once()) | ||
195 | ->method('filterDay') | ||
196 | ->willReturnCallback(function (): array { | ||
197 | return [ | ||
198 | (new Bookmark()) | ||
199 | ->setId(1) | ||
200 | ->setUrl('http://url.tld') | ||
201 | ->setTitle(static::generateContent(50)) | ||
202 | ->setDescription(static::generateContent(500)) | ||
203 | , | ||
204 | ]; | ||
205 | }) | ||
206 | ; | ||
207 | |||
208 | // Make sure that PluginManager hook is triggered | ||
209 | $this->container->pluginManager | ||
210 | ->expects(static::at(0)) | ||
211 | ->method('executeHooks') | ||
212 | ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { | ||
213 | static::assertSame('render_daily', $hook); | ||
214 | |||
215 | static::assertArrayHasKey('linksToDisplay', $data); | ||
216 | static::assertCount(1, $data['linksToDisplay']); | ||
217 | static::assertSame(1, $data['linksToDisplay'][0]['id']); | ||
218 | static::assertSame($currentDay->getTimestamp(), $data['day']); | ||
219 | static::assertEmpty($data['previousday']); | ||
220 | static::assertEmpty($data['nextday']); | ||
221 | |||
222 | static::assertArrayHasKey('loggedin', $param); | ||
223 | |||
224 | return $data; | ||
225 | }); | ||
226 | |||
227 | $result = $this->controller->index($request, $response); | ||
228 | |||
229 | static::assertSame(200, $result->getStatusCode()); | ||
230 | static::assertSame('daily', (string) $result->getBody()); | ||
231 | static::assertSame( | ||
232 | 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', | ||
233 | $assignedVariables['pagetitle'] | ||
234 | ); | ||
235 | static::assertCount(1, $assignedVariables['linksToDisplay']); | ||
236 | |||
237 | $link = $assignedVariables['linksToDisplay'][0]; | ||
238 | static::assertSame(1, $link['id']); | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * Daily page - test that height adjustment in columns is working | ||
243 | */ | ||
244 | public function testValidIndexControllerInvokeHeightAdjustment(): void | ||
245 | { | ||
246 | $this->createValidContainerMockSet(); | ||
247 | |||
248 | $currentDay = new \DateTimeImmutable('2020-05-13'); | ||
249 | |||
250 | $request = $this->createMock(Request::class); | ||
251 | $response = new Response(); | ||
252 | |||
253 | // Save RainTPL assigned variables | ||
254 | $assignedVariables = []; | ||
255 | $this->assignTemplateVars($assignedVariables); | ||
256 | |||
257 | // Links dataset: 2 links with thumbnails | ||
258 | $this->container->bookmarkService | ||
259 | ->expects(static::once()) | ||
260 | ->method('days') | ||
261 | ->willReturnCallback(function () use ($currentDay): array { | ||
262 | return [ | ||
263 | $currentDay->format($currentDay->format('Ymd')), | ||
264 | ]; | ||
265 | }) | ||
266 | ; | ||
267 | $this->container->bookmarkService | ||
268 | ->expects(static::once()) | ||
269 | ->method('filterDay') | ||
270 | ->willReturnCallback(function (): array { | ||
271 | return [ | ||
272 | (new Bookmark())->setId(1)->setUrl('http://url.tld')->setTitle('title'), | ||
273 | (new Bookmark()) | ||
274 | ->setId(2) | ||
275 | ->setUrl('http://url.tld') | ||
276 | ->setTitle(static::generateContent(50)) | ||
277 | ->setDescription(static::generateContent(5000)) | ||
278 | , | ||
279 | (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'), | ||
280 | (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'), | ||
281 | (new Bookmark())->setId(5)->setUrl('http://url.tld')->setTitle('title'), | ||
282 | (new Bookmark())->setId(6)->setUrl('http://url.tld')->setTitle('title'), | ||
283 | (new Bookmark())->setId(7)->setUrl('http://url.tld')->setTitle('title'), | ||
284 | ]; | ||
285 | }) | ||
286 | ; | ||
287 | |||
288 | // Make sure that PluginManager hook is triggered | ||
289 | $this->container->pluginManager | ||
290 | ->expects(static::at(0)) | ||
291 | ->method('executeHooks') | ||
292 | ->willReturnCallback(function (string $hook, array $data, array $param): array { | ||
293 | return $data; | ||
294 | }) | ||
295 | ; | ||
296 | |||
297 | $result = $this->controller->index($request, $response); | ||
298 | |||
299 | static::assertSame(200, $result->getStatusCode()); | ||
300 | static::assertSame('daily', (string) $result->getBody()); | ||
301 | static::assertCount(7, $assignedVariables['linksToDisplay']); | ||
302 | |||
303 | $columnIds = function (array $column): array { | ||
304 | return array_map(function (array $item): int { return $item['id']; }, $column); | ||
305 | }; | ||
306 | |||
307 | static::assertSame([1, 4, 6], $columnIds($assignedVariables['cols'][0])); | ||
308 | static::assertSame([2], $columnIds($assignedVariables['cols'][1])); | ||
309 | static::assertSame([3, 5, 7], $columnIds($assignedVariables['cols'][2])); | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * Daily page - no bookmark | ||
314 | */ | ||
315 | public function testValidIndexControllerInvokeNoBookmark(): void | ||
316 | { | ||
317 | $this->createValidContainerMockSet(); | ||
318 | |||
319 | $request = $this->createMock(Request::class); | ||
320 | $response = new Response(); | ||
321 | |||
322 | // Save RainTPL assigned variables | ||
323 | $assignedVariables = []; | ||
324 | $this->assignTemplateVars($assignedVariables); | ||
325 | |||
326 | // Links dataset: 2 links with thumbnails | ||
327 | $this->container->bookmarkService | ||
328 | ->expects(static::once()) | ||
329 | ->method('days') | ||
330 | ->willReturnCallback(function (): array { | ||
331 | return []; | ||
332 | }) | ||
333 | ; | ||
334 | $this->container->bookmarkService | ||
335 | ->expects(static::once()) | ||
336 | ->method('filterDay') | ||
337 | ->willReturnCallback(function (): array { | ||
338 | return []; | ||
339 | }) | ||
340 | ; | ||
341 | |||
342 | // Make sure that PluginManager hook is triggered | ||
343 | $this->container->pluginManager | ||
344 | ->expects(static::at(0)) | ||
345 | ->method('executeHooks') | ||
346 | ->willReturnCallback(function (string $hook, array $data, array $param): array { | ||
347 | return $data; | ||
348 | }) | ||
349 | ; | ||
350 | |||
351 | $result = $this->controller->index($request, $response); | ||
352 | |||
353 | static::assertSame(200, $result->getStatusCode()); | ||
354 | static::assertSame('daily', (string) $result->getBody()); | ||
355 | static::assertCount(0, $assignedVariables['linksToDisplay']); | ||
356 | static::assertSame('Today', $assignedVariables['dayDesc']); | ||
357 | static::assertEquals((new \DateTime())->setTime(0, 0)->getTimestamp(), $assignedVariables['day']); | ||
358 | static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']); | ||
359 | } | ||
360 | |||
361 | /** | ||
362 | * Daily RSS - default behaviour | ||
363 | */ | ||
364 | public function testValidRssControllerInvokeDefault(): void | ||
365 | { | ||
366 | $this->createValidContainerMockSet(); | ||
367 | |||
368 | $dates = [ | ||
369 | new \DateTimeImmutable('2020-05-17'), | ||
370 | new \DateTimeImmutable('2020-05-15'), | ||
371 | new \DateTimeImmutable('2020-05-13'), | ||
372 | ]; | ||
373 | |||
374 | $request = $this->createMock(Request::class); | ||
375 | $response = new Response(); | ||
376 | |||
377 | $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ | ||
378 | (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), | ||
379 | (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), | ||
380 | (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), | ||
381 | (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'), | ||
382 | ]); | ||
383 | |||
384 | $this->container->pageCacheManager | ||
385 | ->expects(static::once()) | ||
386 | ->method('getCachePage') | ||
387 | ->willReturnCallback(function (): CachedPage { | ||
388 | $cachedPage = $this->createMock(CachedPage::class); | ||
389 | $cachedPage->expects(static::once())->method('cache')->with('dailyrss'); | ||
390 | |||
391 | return $cachedPage; | ||
392 | } | ||
393 | ); | ||
394 | |||
395 | // Save RainTPL assigned variables | ||
396 | $assignedVariables = []; | ||
397 | $this->assignTemplateVars($assignedVariables); | ||
398 | |||
399 | $result = $this->controller->rss($request, $response); | ||
400 | |||
401 | static::assertSame(200, $result->getStatusCode()); | ||
402 | static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); | ||
403 | static::assertSame('dailyrss', (string) $result->getBody()); | ||
404 | static::assertSame('Shaarli', $assignedVariables['title']); | ||
405 | static::assertSame('http://shaarli', $assignedVariables['index_url']); | ||
406 | static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); | ||
407 | static::assertFalse($assignedVariables['hide_timestamps']); | ||
408 | static::assertCount(2, $assignedVariables['days']); | ||
409 | |||
410 | $day = $assignedVariables['days'][$dates[0]->format('Ymd')]; | ||
411 | |||
412 | static::assertEquals($dates[0], $day['date']); | ||
413 | static::assertSame($dates[0]->format(\DateTime::RSS), $day['date_rss']); | ||
414 | static::assertSame(format_date($dates[0], false), $day['date_human']); | ||
415 | static::assertSame('http://shaarli/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']); | ||
416 | static::assertCount(1, $day['links']); | ||
417 | static::assertSame(1, $day['links'][0]['id']); | ||
418 | static::assertSame('http://domain.tld/1', $day['links'][0]['url']); | ||
419 | static::assertEquals($dates[0], $day['links'][0]['created']); | ||
420 | |||
421 | $day = $assignedVariables['days'][$dates[1]->format('Ymd')]; | ||
422 | |||
423 | static::assertEquals($dates[1], $day['date']); | ||
424 | static::assertSame($dates[1]->format(\DateTime::RSS), $day['date_rss']); | ||
425 | static::assertSame(format_date($dates[1], false), $day['date_human']); | ||
426 | static::assertSame('http://shaarli/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']); | ||
427 | static::assertCount(2, $day['links']); | ||
428 | |||
429 | static::assertSame(2, $day['links'][0]['id']); | ||
430 | static::assertSame('http://domain.tld/2', $day['links'][0]['url']); | ||
431 | static::assertEquals($dates[1], $day['links'][0]['created']); | ||
432 | static::assertSame(3, $day['links'][1]['id']); | ||
433 | static::assertSame('http://domain.tld/3', $day['links'][1]['url']); | ||
434 | static::assertEquals($dates[1], $day['links'][1]['created']); | ||
435 | } | ||
436 | |||
437 | /** | ||
438 | * Daily RSS - trigger cache rendering | ||
439 | */ | ||
440 | public function testValidRssControllerInvokeTriggerCache(): void | ||
441 | { | ||
442 | $this->createValidContainerMockSet(); | ||
443 | |||
444 | $request = $this->createMock(Request::class); | ||
445 | $response = new Response(); | ||
446 | |||
447 | $this->container->pageCacheManager->method('getCachePage')->willReturnCallback(function (): CachedPage { | ||
448 | $cachedPage = $this->createMock(CachedPage::class); | ||
449 | $cachedPage->method('cachedVersion')->willReturn('this is cache!'); | ||
450 | |||
451 | return $cachedPage; | ||
452 | }); | ||
453 | |||
454 | $this->container->bookmarkService->expects(static::never())->method('search'); | ||
455 | |||
456 | $result = $this->controller->rss($request, $response); | ||
457 | |||
458 | static::assertSame(200, $result->getStatusCode()); | ||
459 | static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); | ||
460 | static::assertSame('this is cache!', (string) $result->getBody()); | ||
461 | } | ||
462 | |||
463 | /** | ||
464 | * Daily RSS - No bookmark | ||
465 | */ | ||
466 | public function testValidRssControllerInvokeNoBookmark(): void | ||
467 | { | ||
468 | $this->createValidContainerMockSet(); | ||
469 | |||
470 | $request = $this->createMock(Request::class); | ||
471 | $response = new Response(); | ||
472 | |||
473 | $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([]); | ||
474 | |||
475 | // Save RainTPL assigned variables | ||
476 | $assignedVariables = []; | ||
477 | $this->assignTemplateVars($assignedVariables); | ||
478 | |||
479 | $result = $this->controller->rss($request, $response); | ||
480 | |||
481 | static::assertSame(200, $result->getStatusCode()); | ||
482 | static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); | ||
483 | static::assertSame('dailyrss', (string) $result->getBody()); | ||
484 | static::assertSame('Shaarli', $assignedVariables['title']); | ||
485 | static::assertSame('http://shaarli', $assignedVariables['index_url']); | ||
486 | static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); | ||
487 | static::assertFalse($assignedVariables['hide_timestamps']); | ||
488 | static::assertCount(0, $assignedVariables['days']); | ||
489 | } | ||
490 | |||
491 | protected static function generateContent(int $length): string | ||
492 | { | ||
493 | // bin2hex(random_bytes) generates string twice as long as given parameter | ||
494 | $length = (int) ceil($length / 2); | ||
495 | return bin2hex(random_bytes($length)); | ||
496 | } | ||
497 | } | ||
diff --git a/tests/front/controller/visitor/FeedControllerTest.php b/tests/front/controller/visitor/FeedControllerTest.php new file mode 100644 index 00000000..fd4679ea --- /dev/null +++ b/tests/front/controller/visitor/FeedControllerTest.php | |||
@@ -0,0 +1,151 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller\Visitor; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Shaarli\Feed\FeedBuilder; | ||
9 | use Slim\Http\Request; | ||
10 | use Slim\Http\Response; | ||
11 | |||
12 | class FeedControllerTest extends TestCase | ||
13 | { | ||
14 | use FrontControllerMockHelper; | ||
15 | |||
16 | /** @var FeedController */ | ||
17 | protected $controller; | ||
18 | |||
19 | public function setUp(): void | ||
20 | { | ||
21 | $this->createContainer(); | ||
22 | |||
23 | $this->container->feedBuilder = $this->createMock(FeedBuilder::class); | ||
24 | |||
25 | $this->controller = new FeedController($this->container); | ||
26 | } | ||
27 | |||
28 | /** | ||
29 | * Feed Controller - RSS default behaviour | ||
30 | */ | ||
31 | public function testDefaultRssController(): void | ||
32 | { | ||
33 | $this->createValidContainerMockSet(); | ||
34 | |||
35 | $request = $this->createMock(Request::class); | ||
36 | $response = new Response(); | ||
37 | |||
38 | $this->container->feedBuilder->expects(static::once())->method('setLocale'); | ||
39 | $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); | ||
40 | $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); | ||
41 | |||
42 | // Save RainTPL assigned variables | ||
43 | $assignedVariables = []; | ||
44 | $this->assignTemplateVars($assignedVariables); | ||
45 | |||
46 | $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); | ||
47 | |||
48 | // Make sure that PluginManager hook is triggered | ||
49 | $this->container->pluginManager | ||
50 | ->expects(static::at(0)) | ||
51 | ->method('executeHooks') | ||
52 | ->willReturnCallback(function (string $hook, array $data, array $param): void { | ||
53 | static::assertSame('render_feed', $hook); | ||
54 | static::assertSame('data', $data['content']); | ||
55 | |||
56 | static::assertArrayHasKey('loggedin', $param); | ||
57 | static::assertSame('rss', $param['target']); | ||
58 | }) | ||
59 | ; | ||
60 | |||
61 | $result = $this->controller->rss($request, $response); | ||
62 | |||
63 | static::assertSame(200, $result->getStatusCode()); | ||
64 | static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); | ||
65 | static::assertSame('feed.rss', (string) $result->getBody()); | ||
66 | static::assertSame('data', $assignedVariables['content']); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * Feed Controller - ATOM default behaviour | ||
71 | */ | ||
72 | public function testDefaultAtomController(): void | ||
73 | { | ||
74 | $this->createValidContainerMockSet(); | ||
75 | |||
76 | $request = $this->createMock(Request::class); | ||
77 | $response = new Response(); | ||
78 | |||
79 | $this->container->feedBuilder->expects(static::once())->method('setLocale'); | ||
80 | $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); | ||
81 | $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); | ||
82 | |||
83 | // Save RainTPL assigned variables | ||
84 | $assignedVariables = []; | ||
85 | $this->assignTemplateVars($assignedVariables); | ||
86 | |||
87 | $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); | ||
88 | |||
89 | // Make sure that PluginManager hook is triggered | ||
90 | $this->container->pluginManager | ||
91 | ->expects(static::at(0)) | ||
92 | ->method('executeHooks') | ||
93 | ->willReturnCallback(function (string $hook, array $data, array $param): void { | ||
94 | static::assertSame('render_feed', $hook); | ||
95 | static::assertSame('data', $data['content']); | ||
96 | |||
97 | static::assertArrayHasKey('loggedin', $param); | ||
98 | static::assertSame('atom', $param['target']); | ||
99 | }) | ||
100 | ; | ||
101 | |||
102 | $result = $this->controller->atom($request, $response); | ||
103 | |||
104 | static::assertSame(200, $result->getStatusCode()); | ||
105 | static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); | ||
106 | static::assertSame('feed.atom', (string) $result->getBody()); | ||
107 | static::assertSame('data', $assignedVariables['content']); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Feed Controller - ATOM with parameters | ||
112 | */ | ||
113 | public function testAtomControllerWithParameters(): void | ||
114 | { | ||
115 | $this->createValidContainerMockSet(); | ||
116 | |||
117 | $request = $this->createMock(Request::class); | ||
118 | $request->method('getParams')->willReturn(['parameter' => 'value']); | ||
119 | $response = new Response(); | ||
120 | |||
121 | // Save RainTPL assigned variables | ||
122 | $assignedVariables = []; | ||
123 | $this->assignTemplateVars($assignedVariables); | ||
124 | |||
125 | $this->container->feedBuilder | ||
126 | ->method('buildData') | ||
127 | ->with('atom', ['parameter' => 'value']) | ||
128 | ->willReturn(['content' => 'data']) | ||
129 | ; | ||
130 | |||
131 | // Make sure that PluginManager hook is triggered | ||
132 | $this->container->pluginManager | ||
133 | ->expects(static::at(0)) | ||
134 | ->method('executeHooks') | ||
135 | ->willReturnCallback(function (string $hook, array $data, array $param): void { | ||
136 | static::assertSame('render_feed', $hook); | ||
137 | static::assertSame('data', $data['content']); | ||
138 | |||
139 | static::assertArrayHasKey('loggedin', $param); | ||
140 | static::assertSame('atom', $param['target']); | ||
141 | }) | ||
142 | ; | ||
143 | |||
144 | $result = $this->controller->atom($request, $response); | ||
145 | |||
146 | static::assertSame(200, $result->getStatusCode()); | ||
147 | static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); | ||
148 | static::assertSame('feed.atom', (string) $result->getBody()); | ||
149 | static::assertSame('data', $assignedVariables['content']); | ||
150 | } | ||
151 | } | ||
diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php new file mode 100644 index 00000000..bc3266b5 --- /dev/null +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php | |||
@@ -0,0 +1,114 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller\Visitor; | ||
6 | |||
7 | use PHPUnit\Framework\MockObject\MockObject; | ||
8 | use Shaarli\Bookmark\BookmarkServiceInterface; | ||
9 | use Shaarli\Config\ConfigManager; | ||
10 | use Shaarli\Container\ShaarliTestContainer; | ||
11 | use Shaarli\Formatter\BookmarkFormatter; | ||
12 | use Shaarli\Formatter\BookmarkRawFormatter; | ||
13 | use Shaarli\Formatter\FormatterFactory; | ||
14 | use Shaarli\Plugin\PluginManager; | ||
15 | use Shaarli\Render\PageBuilder; | ||
16 | use Shaarli\Render\PageCacheManager; | ||
17 | use Shaarli\Security\LoginManager; | ||
18 | use Shaarli\Security\SessionManager; | ||
19 | |||
20 | /** | ||
21 | * Trait FrontControllerMockHelper | ||
22 | * | ||
23 | * Helper trait used to initialize the ShaarliContainer and mock its services for controller tests. | ||
24 | * | ||
25 | * @property ShaarliTestContainer $container | ||
26 | * @package Shaarli\Front\Controller | ||
27 | */ | ||
28 | trait FrontControllerMockHelper | ||
29 | { | ||
30 | /** @var ShaarliTestContainer */ | ||
31 | protected $container; | ||
32 | |||
33 | /** | ||
34 | * Mock the container instance | ||
35 | */ | ||
36 | protected function createContainer(): void | ||
37 | { | ||
38 | $this->container = $this->createMock(ShaarliTestContainer::class); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * Initialize container's services used by tests | ||
43 | */ | ||
44 | protected function createValidContainerMockSet(): void | ||
45 | { | ||
46 | $this->container->loginManager = $this->createMock(LoginManager::class); | ||
47 | |||
48 | // Config | ||
49 | $this->container->conf = $this->createMock(ConfigManager::class); | ||
50 | $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { | ||
51 | return $default; | ||
52 | }); | ||
53 | |||
54 | // PageBuilder | ||
55 | $this->container->pageBuilder = $this->createMock(PageBuilder::class); | ||
56 | $this->container->pageBuilder | ||
57 | ->method('render') | ||
58 | ->willReturnCallback(function (string $template): string { | ||
59 | return $template; | ||
60 | }) | ||
61 | ; | ||
62 | |||
63 | // Plugin Manager | ||
64 | $this->container->pluginManager = $this->createMock(PluginManager::class); | ||
65 | |||
66 | // BookmarkService | ||
67 | $this->container->bookmarkService = $this->createMock(BookmarkServiceInterface::class); | ||
68 | |||
69 | // Formatter | ||
70 | $this->container->formatterFactory = $this->createMock(FormatterFactory::class); | ||
71 | $this->container->formatterFactory | ||
72 | ->method('getFormatter') | ||
73 | ->willReturnCallback(function (): BookmarkFormatter { | ||
74 | return new BookmarkRawFormatter($this->container->conf, true); | ||
75 | }) | ||
76 | ; | ||
77 | |||
78 | // CacheManager | ||
79 | $this->container->pageCacheManager = $this->createMock(PageCacheManager::class); | ||
80 | |||
81 | // SessionManager | ||
82 | $this->container->sessionManager = $this->createMock(SessionManager::class); | ||
83 | |||
84 | // $_SERVER | ||
85 | $this->container->environment = [ | ||
86 | 'SERVER_NAME' => 'shaarli', | ||
87 | 'SERVER_PORT' => '80', | ||
88 | 'REQUEST_URI' => '/daily-rss', | ||
89 | ]; | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * Pass a reference of an array which will be populated by `pageBuilder->assign` calls during execution. | ||
94 | * | ||
95 | * @param mixed $variables Array reference to populate. | ||
96 | */ | ||
97 | protected function assignTemplateVars(array &$variables): void | ||
98 | { | ||
99 | $this->container->pageBuilder | ||
100 | ->expects(static::atLeastOnce()) | ||
101 | ->method('assign') | ||
102 | ->willReturnCallback(function ($key, $value) use (&$variables) { | ||
103 | $variables[$key] = $value; | ||
104 | |||
105 | return $this; | ||
106 | }) | ||
107 | ; | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Force to be used in PHPUnit context. | ||
112 | */ | ||
113 | protected abstract function createMock($originalClassName): MockObject; | ||
114 | } | ||
diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php new file mode 100644 index 00000000..9d223316 --- /dev/null +++ b/tests/front/controller/visitor/LoginControllerTest.php | |||
@@ -0,0 +1,144 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller\Visitor; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Shaarli\Config\ConfigManager; | ||
9 | use Shaarli\Front\Exception\LoginBannedException; | ||
10 | use Slim\Http\Request; | ||
11 | use Slim\Http\Response; | ||
12 | |||
13 | class LoginControllerTest extends TestCase | ||
14 | { | ||
15 | use FrontControllerMockHelper; | ||
16 | |||
17 | /** @var LoginController */ | ||
18 | protected $controller; | ||
19 | |||
20 | public function setUp(): void | ||
21 | { | ||
22 | $this->createContainer(); | ||
23 | |||
24 | $this->controller = new LoginController($this->container); | ||
25 | } | ||
26 | |||
27 | public function testValidControllerInvoke(): void | ||
28 | { | ||
29 | $this->createValidContainerMockSet(); | ||
30 | |||
31 | $request = $this->createMock(Request::class); | ||
32 | $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); | ||
33 | $response = new Response(); | ||
34 | |||
35 | $assignedVariables = []; | ||
36 | $this->container->pageBuilder | ||
37 | ->method('assign') | ||
38 | ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { | ||
39 | $assignedVariables[$key] = $value; | ||
40 | |||
41 | return $this; | ||
42 | }) | ||
43 | ; | ||
44 | |||
45 | $this->container->loginManager->method('canLogin')->willReturn(true); | ||
46 | |||
47 | $result = $this->controller->index($request, $response); | ||
48 | |||
49 | static::assertInstanceOf(Response::class, $result); | ||
50 | static::assertSame(200, $result->getStatusCode()); | ||
51 | static::assertSame('loginform', (string) $result->getBody()); | ||
52 | |||
53 | static::assertSame('> referer', $assignedVariables['returnurl']); | ||
54 | static::assertSame(true, $assignedVariables['remember_user_default']); | ||
55 | static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); | ||
56 | } | ||
57 | |||
58 | public function testValidControllerInvokeWithUserName(): void | ||
59 | { | ||
60 | $this->createValidContainerMockSet(); | ||
61 | |||
62 | $request = $this->createMock(Request::class); | ||
63 | $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); | ||
64 | $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); | ||
65 | $response = new Response(); | ||
66 | |||
67 | $assignedVariables = []; | ||
68 | $this->container->pageBuilder | ||
69 | ->method('assign') | ||
70 | ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { | ||
71 | $assignedVariables[$key] = $value; | ||
72 | |||
73 | return $this; | ||
74 | }) | ||
75 | ; | ||
76 | |||
77 | $this->container->loginManager->expects(static::once())->method('canLogin')->willReturn(true); | ||
78 | |||
79 | $result = $this->controller->index($request, $response); | ||
80 | |||
81 | static::assertInstanceOf(Response::class, $result); | ||
82 | static::assertSame(200, $result->getStatusCode()); | ||
83 | static::assertSame('loginform', (string) $result->getBody()); | ||
84 | |||
85 | static::assertSame('myUser>', $assignedVariables['username']); | ||
86 | static::assertSame('> referer', $assignedVariables['returnurl']); | ||
87 | static::assertSame(true, $assignedVariables['remember_user_default']); | ||
88 | static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); | ||
89 | } | ||
90 | |||
91 | public function testLoginControllerWhileLoggedIn(): void | ||
92 | { | ||
93 | $this->createValidContainerMockSet(); | ||
94 | |||
95 | $request = $this->createMock(Request::class); | ||
96 | $response = new Response(); | ||
97 | |||
98 | $this->container->loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true); | ||
99 | |||
100 | $result = $this->controller->index($request, $response); | ||
101 | |||
102 | static::assertInstanceOf(Response::class, $result); | ||
103 | static::assertSame(302, $result->getStatusCode()); | ||
104 | static::assertSame(['./'], $result->getHeader('Location')); | ||
105 | } | ||
106 | |||
107 | public function testLoginControllerOpenShaarli(): void | ||
108 | { | ||
109 | $this->createValidContainerMockSet(); | ||
110 | |||
111 | $request = $this->createMock(Request::class); | ||
112 | $response = new Response(); | ||
113 | |||
114 | $conf = $this->createMock(ConfigManager::class); | ||
115 | $conf->method('get')->willReturnCallback(function (string $parameter, $default) { | ||
116 | if ($parameter === 'security.open_shaarli') { | ||
117 | return true; | ||
118 | } | ||
119 | return $default; | ||
120 | }); | ||
121 | $this->container->conf = $conf; | ||
122 | |||
123 | $result = $this->controller->index($request, $response); | ||
124 | |||
125 | static::assertInstanceOf(Response::class, $result); | ||
126 | static::assertSame(302, $result->getStatusCode()); | ||
127 | static::assertSame(['./'], $result->getHeader('Location')); | ||
128 | } | ||
129 | |||
130 | public function testLoginControllerWhileBanned(): void | ||
131 | { | ||
132 | $this->createValidContainerMockSet(); | ||
133 | |||
134 | $request = $this->createMock(Request::class); | ||
135 | $response = new Response(); | ||
136 | |||
137 | $this->container->loginManager->method('isLoggedIn')->willReturn(false); | ||
138 | $this->container->loginManager->method('canLogin')->willReturn(false); | ||
139 | |||
140 | $this->expectException(LoginBannedException::class); | ||
141 | |||
142 | $this->controller->index($request, $response); | ||
143 | } | ||
144 | } | ||
diff --git a/tests/front/controller/visitor/OpenSearchControllerTest.php b/tests/front/controller/visitor/OpenSearchControllerTest.php new file mode 100644 index 00000000..52475318 --- /dev/null +++ b/tests/front/controller/visitor/OpenSearchControllerTest.php | |||
@@ -0,0 +1,46 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller\Visitor; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Slim\Http\Request; | ||
9 | use Slim\Http\Response; | ||
10 | |||
11 | class OpenSearchControllerTest extends TestCase | ||
12 | { | ||
13 | use FrontControllerMockHelper; | ||
14 | |||
15 | /** @var OpenSearchController */ | ||
16 | protected $controller; | ||
17 | |||
18 | public function setUp(): void | ||
19 | { | ||
20 | $this->createContainer(); | ||
21 | |||
22 | $this->controller = new OpenSearchController($this->container); | ||
23 | } | ||
24 | |||
25 | public function testOpenSearchController(): void | ||
26 | { | ||
27 | $this->createValidContainerMockSet(); | ||
28 | |||
29 | $request = $this->createMock(Request::class); | ||
30 | $response = new Response(); | ||
31 | |||
32 | // Save RainTPL assigned variables | ||
33 | $assignedVariables = []; | ||
34 | $this->assignTemplateVars($assignedVariables); | ||
35 | |||
36 | $result = $this->controller->index($request, $response); | ||
37 | |||
38 | static::assertSame(200, $result->getStatusCode()); | ||
39 | static::assertStringContainsString( | ||
40 | 'application/opensearchdescription+xml', | ||
41 | $result->getHeader('Content-Type')[0] | ||
42 | ); | ||
43 | static::assertSame('opensearch', (string) $result->getBody()); | ||
44 | static::assertSame('http://shaarli', $assignedVariables['serverurl']); | ||
45 | } | ||
46 | } | ||
diff --git a/tests/front/controller/visitor/PictureWallControllerTest.php b/tests/front/controller/visitor/PictureWallControllerTest.php new file mode 100644 index 00000000..7ac842cb --- /dev/null +++ b/tests/front/controller/visitor/PictureWallControllerTest.php | |||
@@ -0,0 +1,125 @@ | |||
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\Config\ConfigManager; | ||
10 | use Shaarli\Front\Exception\ThumbnailsDisabledException; | ||
11 | use Shaarli\Thumbnailer; | ||
12 | use Slim\Http\Request; | ||
13 | use Slim\Http\Response; | ||
14 | |||
15 | class PictureWallControllerTest extends TestCase | ||
16 | { | ||
17 | use FrontControllerMockHelper; | ||
18 | |||
19 | /** @var PictureWallController */ | ||
20 | protected $controller; | ||
21 | |||
22 | public function setUp(): void | ||
23 | { | ||
24 | $this->createContainer(); | ||
25 | |||
26 | $this->controller = new PictureWallController($this->container); | ||
27 | } | ||
28 | |||
29 | public function testValidControllerInvokeDefault(): void | ||
30 | { | ||
31 | $this->createValidContainerMockSet(); | ||
32 | |||
33 | $request = $this->createMock(Request::class); | ||
34 | $request->expects(static::once())->method('getQueryParams')->willReturn([]); | ||
35 | $response = new Response(); | ||
36 | |||
37 | // ConfigManager: thumbnails are enabled | ||
38 | $this->container->conf = $this->createMock(ConfigManager::class); | ||
39 | $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { | ||
40 | if ($parameter === 'thumbnails.mode') { | ||
41 | return Thumbnailer::MODE_COMMON; | ||
42 | } | ||
43 | |||
44 | return $default; | ||
45 | }); | ||
46 | |||
47 | // Save RainTPL assigned variables | ||
48 | $assignedVariables = []; | ||
49 | $this->assignTemplateVars($assignedVariables); | ||
50 | |||
51 | // Links dataset: 2 links with thumbnails | ||
52 | $this->container->bookmarkService | ||
53 | ->expects(static::once()) | ||
54 | ->method('search') | ||
55 | ->willReturnCallback(function (array $parameters, ?string $visibility): array { | ||
56 | // Visibility is set through the container, not the call | ||
57 | static::assertNull($visibility); | ||
58 | |||
59 | // No query parameters | ||
60 | if (count($parameters) === 0) { | ||
61 | return [ | ||
62 | (new Bookmark())->setId(1)->setUrl('http://url.tld')->setThumbnail('thumb1'), | ||
63 | (new Bookmark())->setId(2)->setUrl('http://url2.tld'), | ||
64 | (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setThumbnail('thumb2'), | ||
65 | ]; | ||
66 | } | ||
67 | }) | ||
68 | ; | ||
69 | |||
70 | // Make sure that PluginManager hook is triggered | ||
71 | $this->container->pluginManager | ||
72 | ->expects(static::at(0)) | ||
73 | ->method('executeHooks') | ||
74 | ->willReturnCallback(function (string $hook, array $data, array $param): array { | ||
75 | static::assertSame('render_picwall', $hook); | ||
76 | static::assertArrayHasKey('linksToDisplay', $data); | ||
77 | static::assertCount(2, $data['linksToDisplay']); | ||
78 | static::assertSame(1, $data['linksToDisplay'][0]['id']); | ||
79 | static::assertSame(3, $data['linksToDisplay'][1]['id']); | ||
80 | static::assertArrayHasKey('loggedin', $param); | ||
81 | |||
82 | return $data; | ||
83 | }); | ||
84 | |||
85 | $result = $this->controller->index($request, $response); | ||
86 | |||
87 | static::assertSame(200, $result->getStatusCode()); | ||
88 | static::assertSame('picwall', (string) $result->getBody()); | ||
89 | static::assertSame('Picture wall - Shaarli', $assignedVariables['pagetitle']); | ||
90 | static::assertCount(2, $assignedVariables['linksToDisplay']); | ||
91 | |||
92 | $link = $assignedVariables['linksToDisplay'][0]; | ||
93 | |||
94 | static::assertSame(1, $link['id']); | ||
95 | static::assertSame('http://url.tld', $link['url']); | ||
96 | static::assertSame('thumb1', $link['thumbnail']); | ||
97 | |||
98 | $link = $assignedVariables['linksToDisplay'][1]; | ||
99 | |||
100 | static::assertSame(3, $link['id']); | ||
101 | static::assertSame('http://url3.tld', $link['url']); | ||
102 | static::assertSame('thumb2', $link['thumbnail']); | ||
103 | } | ||
104 | |||
105 | public function testControllerWithThumbnailsDisabled(): void | ||
106 | { | ||
107 | $this->expectException(ThumbnailsDisabledException::class); | ||
108 | |||
109 | $this->createValidContainerMockSet(); | ||
110 | |||
111 | $request = $this->createMock(Request::class); | ||
112 | $response = new Response(); | ||
113 | |||
114 | // ConfigManager: thumbnails are disabled | ||
115 | $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { | ||
116 | if ($parameter === 'thumbnails.mode') { | ||
117 | return Thumbnailer::MODE_NONE; | ||
118 | } | ||
119 | |||
120 | return $default; | ||
121 | }); | ||
122 | |||
123 | $this->controller->index($request, $response); | ||
124 | } | ||
125 | } | ||
diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php new file mode 100644 index 00000000..e2e88da3 --- /dev/null +++ b/tests/front/controller/visitor/ShaarliPublicControllerTest.php | |||
@@ -0,0 +1,239 @@ | |||
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\BookmarkFilter; | ||
9 | use Slim\Http\Request; | ||
10 | use Slim\Http\Response; | ||
11 | use Slim\Http\Uri; | ||
12 | |||
13 | /** | ||
14 | * Class ShaarliControllerTest | ||
15 | * | ||
16 | * This class is used to test default behavior of ShaarliController abstract class. | ||
17 | * It uses a dummy non abstract controller. | ||
18 | */ | ||
19 | class ShaarliControllerTest extends TestCase | ||
20 | { | ||
21 | use FrontControllerMockHelper; | ||
22 | |||
23 | /** @var LoginController */ | ||
24 | protected $controller; | ||
25 | |||
26 | /** @var mixed[] List of variable assigned to the template */ | ||
27 | protected $assignedValues; | ||
28 | |||
29 | /** @var Request */ | ||
30 | protected $request; | ||
31 | |||
32 | public function setUp(): void | ||
33 | { | ||
34 | $this->createContainer(); | ||
35 | |||
36 | $this->controller = new class($this->container) extends ShaarliVisitorController | ||
37 | { | ||
38 | public function assignView(string $key, $value): ShaarliVisitorController | ||
39 | { | ||
40 | return parent::assignView($key, $value); | ||
41 | } | ||
42 | |||
43 | public function render(string $template): string | ||
44 | { | ||
45 | return parent::render($template); | ||
46 | } | ||
47 | |||
48 | public function redirectFromReferer( | ||
49 | Request $request, | ||
50 | Response $response, | ||
51 | array $loopTerms = [], | ||
52 | array $clearParams = [] | ||
53 | ): Response { | ||
54 | return parent::redirectFromReferer($request, $response, $loopTerms, $clearParams); | ||
55 | } | ||
56 | }; | ||
57 | $this->assignedValues = []; | ||
58 | |||
59 | $this->request = $this->createMock(Request::class); | ||
60 | $this->request->method('getUri')->willReturnCallback(function (): Uri { | ||
61 | $uri = $this->createMock(Uri::class); | ||
62 | $uri->method('getBasePath')->willReturn('/subfolder'); | ||
63 | |||
64 | return $uri; | ||
65 | }); | ||
66 | } | ||
67 | |||
68 | public function testAssignView(): void | ||
69 | { | ||
70 | $this->createValidContainerMockSet(); | ||
71 | |||
72 | $this->assignTemplateVars($this->assignedValues); | ||
73 | |||
74 | $self = $this->controller->assignView('variableName', 'variableValue'); | ||
75 | |||
76 | static::assertInstanceOf(ShaarliVisitorController::class, $self); | ||
77 | static::assertSame('variableValue', $this->assignedValues['variableName']); | ||
78 | } | ||
79 | |||
80 | public function testRender(): void | ||
81 | { | ||
82 | $this->createValidContainerMockSet(); | ||
83 | |||
84 | $this->assignTemplateVars($this->assignedValues); | ||
85 | |||
86 | $this->container->bookmarkService | ||
87 | ->method('count') | ||
88 | ->willReturnCallback(function (string $visibility): int { | ||
89 | return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; | ||
90 | }) | ||
91 | ; | ||
92 | |||
93 | $this->container->pluginManager | ||
94 | ->method('executeHooks') | ||
95 | ->willReturnCallback(function (string $hook, array &$data, array $params): array { | ||
96 | return $data[$hook] = $params; | ||
97 | }); | ||
98 | $this->container->pluginManager->method('getErrors')->willReturn(['error']); | ||
99 | |||
100 | $this->container->loginManager->method('isLoggedIn')->willReturn(true); | ||
101 | |||
102 | $render = $this->controller->render('templateName'); | ||
103 | |||
104 | static::assertSame('templateName', $render); | ||
105 | |||
106 | static::assertSame(10, $this->assignedValues['linkcount']); | ||
107 | static::assertSame(5, $this->assignedValues['privateLinkcount']); | ||
108 | static::assertSame(['error'], $this->assignedValues['plugin_errors']); | ||
109 | |||
110 | static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); | ||
111 | static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); | ||
112 | static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); | ||
113 | static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); | ||
114 | static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); | ||
115 | static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * Test redirectFromReferer() - Default behaviour | ||
120 | */ | ||
121 | public function testRedirectFromRefererDefault(): void | ||
122 | { | ||
123 | $this->createValidContainerMockSet(); | ||
124 | |||
125 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | ||
126 | |||
127 | $response = new Response(); | ||
128 | |||
129 | $result = $this->controller->redirectFromReferer($this->request, $response); | ||
130 | |||
131 | static::assertSame(302, $result->getStatusCode()); | ||
132 | static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); | ||
133 | } | ||
134 | |||
135 | /** | ||
136 | * Test redirectFromReferer() - With a loop term not matched in the referer | ||
137 | */ | ||
138 | public function testRedirectFromRefererWithUnmatchedLoopTerm(): void | ||
139 | { | ||
140 | $this->createValidContainerMockSet(); | ||
141 | |||
142 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | ||
143 | |||
144 | $response = new Response(); | ||
145 | |||
146 | $result = $this->controller->redirectFromReferer($this->request, $response, ['nope']); | ||
147 | |||
148 | static::assertSame(302, $result->getStatusCode()); | ||
149 | static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default | ||
154 | */ | ||
155 | public function testRedirectFromRefererWithMatchingLoopTermInPath(): void | ||
156 | { | ||
157 | $this->createValidContainerMockSet(); | ||
158 | |||
159 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | ||
160 | |||
161 | $response = new Response(); | ||
162 | |||
163 | $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'controller']); | ||
164 | |||
165 | static::assertSame(302, $result->getStatusCode()); | ||
166 | static::assertSame(['/subfolder'], $result->getHeader('location')); | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default | ||
171 | */ | ||
172 | public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void | ||
173 | { | ||
174 | $this->createValidContainerMockSet(); | ||
175 | |||
176 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | ||
177 | |||
178 | $response = new Response(); | ||
179 | |||
180 | $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'other']); | ||
181 | |||
182 | static::assertSame(302, $result->getStatusCode()); | ||
183 | static::assertSame(['/subfolder'], $result->getHeader('location')); | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * Test redirectFromReferer() - With a loop term matching the referer in its query value | ||
188 | * -> we do not block redirection for query parameter values. | ||
189 | */ | ||
190 | public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void | ||
191 | { | ||
192 | $this->createValidContainerMockSet(); | ||
193 | |||
194 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | ||
195 | |||
196 | $response = new Response(); | ||
197 | |||
198 | $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'param']); | ||
199 | |||
200 | static::assertSame(302, $result->getStatusCode()); | ||
201 | static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * Test redirectFromReferer() - With a loop term matching the referer in its domain name | ||
206 | * -> we do not block redirection for shaarli's hosts | ||
207 | */ | ||
208 | public function testRedirectFromRefererWithLoopTermInDomain(): void | ||
209 | { | ||
210 | $this->createValidContainerMockSet(); | ||
211 | |||
212 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | ||
213 | |||
214 | $response = new Response(); | ||
215 | |||
216 | $result = $this->controller->redirectFromReferer($this->request, $response, ['shaarli']); | ||
217 | |||
218 | static::assertSame(302, $result->getStatusCode()); | ||
219 | static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); | ||
220 | } | ||
221 | |||
222 | /** | ||
223 | * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param | ||
224 | * -> the param should be cleared before checking if it matches the redir loop terms | ||
225 | */ | ||
226 | public function testRedirectFromRefererWithMatchingClearedParam(): void | ||
227 | { | ||
228 | $this->createValidContainerMockSet(); | ||
229 | |||
230 | $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; | ||
231 | |||
232 | $response = new Response(); | ||
233 | |||
234 | $result = $this->controller->redirectFromReferer($this->request, $response, ['query'], ['query']); | ||
235 | |||
236 | static::assertSame(302, $result->getStatusCode()); | ||
237 | static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location')); | ||
238 | } | ||
239 | } | ||
diff --git a/tests/front/controller/visitor/TagCloudControllerTest.php b/tests/front/controller/visitor/TagCloudControllerTest.php new file mode 100644 index 00000000..e636d496 --- /dev/null +++ b/tests/front/controller/visitor/TagCloudControllerTest.php | |||
@@ -0,0 +1,381 @@ | |||
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\BookmarkFilter; | ||
9 | use Slim\Http\Request; | ||
10 | use Slim\Http\Response; | ||
11 | |||
12 | class TagCloudControllerTest extends TestCase | ||
13 | { | ||
14 | use FrontControllerMockHelper; | ||
15 | |||
16 | /** @var TagCloudController */ | ||
17 | protected $controller; | ||
18 | |||
19 | public function setUp(): void | ||
20 | { | ||
21 | $this->createContainer(); | ||
22 | |||
23 | $this->controller = new TagCloudController($this->container); | ||
24 | } | ||
25 | |||
26 | /** | ||
27 | * Tag Cloud - default parameters | ||
28 | */ | ||
29 | public function testValidCloudControllerInvokeDefault(): void | ||
30 | { | ||
31 | $this->createValidContainerMockSet(); | ||
32 | |||
33 | $allTags = [ | ||
34 | 'ghi' => 1, | ||
35 | 'abc' => 3, | ||
36 | 'def' => 12, | ||
37 | ]; | ||
38 | $expectedOrder = ['abc', 'def', 'ghi']; | ||
39 | |||
40 | $request = $this->createMock(Request::class); | ||
41 | $response = new Response(); | ||
42 | |||
43 | // Save RainTPL assigned variables | ||
44 | $assignedVariables = []; | ||
45 | $this->assignTemplateVars($assignedVariables); | ||
46 | |||
47 | $this->container->bookmarkService | ||
48 | ->expects(static::once()) | ||
49 | ->method('bookmarksCountPerTag') | ||
50 | ->with([], null) | ||
51 | ->willReturnCallback(function () use ($allTags): array { | ||
52 | return $allTags; | ||
53 | }) | ||
54 | ; | ||
55 | |||
56 | // Make sure that PluginManager hook is triggered | ||
57 | $this->container->pluginManager | ||
58 | ->expects(static::at(0)) | ||
59 | ->method('executeHooks') | ||
60 | ->willReturnCallback(function (string $hook, array $data, array $param): array { | ||
61 | static::assertSame('render_tagcloud', $hook); | ||
62 | static::assertSame('', $data['search_tags']); | ||
63 | static::assertCount(3, $data['tags']); | ||
64 | |||
65 | static::assertArrayHasKey('loggedin', $param); | ||
66 | |||
67 | return $data; | ||
68 | }) | ||
69 | ; | ||
70 | |||
71 | $result = $this->controller->cloud($request, $response); | ||
72 | |||
73 | static::assertSame(200, $result->getStatusCode()); | ||
74 | static::assertSame('tag.cloud', (string) $result->getBody()); | ||
75 | static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); | ||
76 | |||
77 | static::assertSame('', $assignedVariables['search_tags']); | ||
78 | static::assertCount(3, $assignedVariables['tags']); | ||
79 | static::assertSame($expectedOrder, array_keys($assignedVariables['tags'])); | ||
80 | |||
81 | foreach ($allTags as $tag => $count) { | ||
82 | static::assertArrayHasKey($tag, $assignedVariables['tags']); | ||
83 | static::assertSame($count, $assignedVariables['tags'][$tag]['count']); | ||
84 | static::assertGreaterThan(0, $assignedVariables['tags'][$tag]['size']); | ||
85 | static::assertLessThan(5, $assignedVariables['tags'][$tag]['size']); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * Tag Cloud - Additional parameters: | ||
91 | * - logged in | ||
92 | * - visibility private | ||
93 | * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) | ||
94 | */ | ||
95 | public function testValidCloudControllerInvokeWithParameters(): void | ||
96 | { | ||
97 | $this->createValidContainerMockSet(); | ||
98 | |||
99 | $request = $this->createMock(Request::class); | ||
100 | $request | ||
101 | ->method('getQueryParam') | ||
102 | ->with() | ||
103 | ->willReturnCallback(function (string $key): ?string { | ||
104 | if ('searchtags' === $key) { | ||
105 | return 'ghi def'; | ||
106 | } | ||
107 | |||
108 | return null; | ||
109 | }) | ||
110 | ; | ||
111 | $response = new Response(); | ||
112 | |||
113 | // Save RainTPL assigned variables | ||
114 | $assignedVariables = []; | ||
115 | $this->assignTemplateVars($assignedVariables); | ||
116 | |||
117 | $this->container->loginManager->method('isLoggedin')->willReturn(true); | ||
118 | $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); | ||
119 | |||
120 | $this->container->bookmarkService | ||
121 | ->expects(static::once()) | ||
122 | ->method('bookmarksCountPerTag') | ||
123 | ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) | ||
124 | ->willReturnCallback(function (): array { | ||
125 | return ['abc' => 3]; | ||
126 | }) | ||
127 | ; | ||
128 | |||
129 | // Make sure that PluginManager hook is triggered | ||
130 | $this->container->pluginManager | ||
131 | ->expects(static::at(0)) | ||
132 | ->method('executeHooks') | ||
133 | ->willReturnCallback(function (string $hook, array $data, array $param): array { | ||
134 | static::assertSame('render_tagcloud', $hook); | ||
135 | static::assertSame('ghi def', $data['search_tags']); | ||
136 | static::assertCount(1, $data['tags']); | ||
137 | |||
138 | static::assertArrayHasKey('loggedin', $param); | ||
139 | |||
140 | return $data; | ||
141 | }) | ||
142 | ; | ||
143 | |||
144 | $result = $this->controller->cloud($request, $response); | ||
145 | |||
146 | static::assertSame(200, $result->getStatusCode()); | ||
147 | static::assertSame('tag.cloud', (string) $result->getBody()); | ||
148 | static::assertSame('ghi def - Tag cloud - Shaarli', $assignedVariables['pagetitle']); | ||
149 | |||
150 | static::assertSame('ghi def', $assignedVariables['search_tags']); | ||
151 | static::assertCount(1, $assignedVariables['tags']); | ||
152 | |||
153 | static::assertArrayHasKey('abc', $assignedVariables['tags']); | ||
154 | static::assertSame(3, $assignedVariables['tags']['abc']['count']); | ||
155 | static::assertGreaterThan(0, $assignedVariables['tags']['abc']['size']); | ||
156 | static::assertLessThan(5, $assignedVariables['tags']['abc']['size']); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * Tag Cloud - empty | ||
161 | */ | ||
162 | public function testEmptyCloud(): void | ||
163 | { | ||
164 | $this->createValidContainerMockSet(); | ||
165 | |||
166 | $request = $this->createMock(Request::class); | ||
167 | $response = new Response(); | ||
168 | |||
169 | // Save RainTPL assigned variables | ||
170 | $assignedVariables = []; | ||
171 | $this->assignTemplateVars($assignedVariables); | ||
172 | |||
173 | $this->container->bookmarkService | ||
174 | ->expects(static::once()) | ||
175 | ->method('bookmarksCountPerTag') | ||
176 | ->with([], null) | ||
177 | ->willReturnCallback(function (array $parameters, ?string $visibility): array { | ||
178 | return []; | ||
179 | }) | ||
180 | ; | ||
181 | |||
182 | // Make sure that PluginManager hook is triggered | ||
183 | $this->container->pluginManager | ||
184 | ->expects(static::at(0)) | ||
185 | ->method('executeHooks') | ||
186 | ->willReturnCallback(function (string $hook, array $data, array $param): array { | ||
187 | static::assertSame('render_tagcloud', $hook); | ||
188 | static::assertSame('', $data['search_tags']); | ||
189 | static::assertCount(0, $data['tags']); | ||
190 | |||
191 | static::assertArrayHasKey('loggedin', $param); | ||
192 | |||
193 | return $data; | ||
194 | }) | ||
195 | ; | ||
196 | |||
197 | $result = $this->controller->cloud($request, $response); | ||
198 | |||
199 | static::assertSame(200, $result->getStatusCode()); | ||
200 | static::assertSame('tag.cloud', (string) $result->getBody()); | ||
201 | static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); | ||
202 | |||
203 | static::assertSame('', $assignedVariables['search_tags']); | ||
204 | static::assertCount(0, $assignedVariables['tags']); | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * Tag List - Default sort is by usage DESC | ||
209 | */ | ||
210 | public function testValidListControllerInvokeDefault(): void | ||
211 | { | ||
212 | $this->createValidContainerMockSet(); | ||
213 | |||
214 | $allTags = [ | ||
215 | 'def' => 12, | ||
216 | 'abc' => 3, | ||
217 | 'ghi' => 1, | ||
218 | ]; | ||
219 | |||
220 | $request = $this->createMock(Request::class); | ||
221 | $response = new Response(); | ||
222 | |||
223 | // Save RainTPL assigned variables | ||
224 | $assignedVariables = []; | ||
225 | $this->assignTemplateVars($assignedVariables); | ||
226 | |||
227 | $this->container->bookmarkService | ||
228 | ->expects(static::once()) | ||
229 | ->method('bookmarksCountPerTag') | ||
230 | ->with([], null) | ||
231 | ->willReturnCallback(function () use ($allTags): array { | ||
232 | return $allTags; | ||
233 | }) | ||
234 | ; | ||
235 | |||
236 | // Make sure that PluginManager hook is triggered | ||
237 | $this->container->pluginManager | ||
238 | ->expects(static::at(0)) | ||
239 | ->method('executeHooks') | ||
240 | ->willReturnCallback(function (string $hook, array $data, array $param): array { | ||
241 | static::assertSame('render_taglist', $hook); | ||
242 | static::assertSame('', $data['search_tags']); | ||
243 | static::assertCount(3, $data['tags']); | ||
244 | |||
245 | static::assertArrayHasKey('loggedin', $param); | ||
246 | |||
247 | return $data; | ||
248 | }) | ||
249 | ; | ||
250 | |||
251 | $result = $this->controller->list($request, $response); | ||
252 | |||
253 | static::assertSame(200, $result->getStatusCode()); | ||
254 | static::assertSame('tag.list', (string) $result->getBody()); | ||
255 | static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); | ||
256 | |||
257 | static::assertSame('', $assignedVariables['search_tags']); | ||
258 | static::assertCount(3, $assignedVariables['tags']); | ||
259 | |||
260 | foreach ($allTags as $tag => $count) { | ||
261 | static::assertSame($count, $assignedVariables['tags'][$tag]); | ||
262 | } | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * Tag List - Additional parameters: | ||
267 | * - logged in | ||
268 | * - visibility private | ||
269 | * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) | ||
270 | * - sort alphabetically | ||
271 | */ | ||
272 | public function testValidListControllerInvokeWithParameters(): void | ||
273 | { | ||
274 | $this->createValidContainerMockSet(); | ||
275 | |||
276 | $request = $this->createMock(Request::class); | ||
277 | $request | ||
278 | ->method('getQueryParam') | ||
279 | ->with() | ||
280 | ->willReturnCallback(function (string $key): ?string { | ||
281 | if ('searchtags' === $key) { | ||
282 | return 'ghi def'; | ||
283 | } elseif ('sort' === $key) { | ||
284 | return 'alpha'; | ||
285 | } | ||
286 | |||
287 | return null; | ||
288 | }) | ||
289 | ; | ||
290 | $response = new Response(); | ||
291 | |||
292 | // Save RainTPL assigned variables | ||
293 | $assignedVariables = []; | ||
294 | $this->assignTemplateVars($assignedVariables); | ||
295 | |||
296 | $this->container->loginManager->method('isLoggedin')->willReturn(true); | ||
297 | $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); | ||
298 | |||
299 | $this->container->bookmarkService | ||
300 | ->expects(static::once()) | ||
301 | ->method('bookmarksCountPerTag') | ||
302 | ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) | ||
303 | ->willReturnCallback(function (): array { | ||
304 | return ['abc' => 3]; | ||
305 | }) | ||
306 | ; | ||
307 | |||
308 | // Make sure that PluginManager hook is triggered | ||
309 | $this->container->pluginManager | ||
310 | ->expects(static::at(0)) | ||
311 | ->method('executeHooks') | ||
312 | ->willReturnCallback(function (string $hook, array $data, array $param): array { | ||
313 | static::assertSame('render_taglist', $hook); | ||
314 | static::assertSame('ghi def', $data['search_tags']); | ||
315 | static::assertCount(1, $data['tags']); | ||
316 | |||
317 | static::assertArrayHasKey('loggedin', $param); | ||
318 | |||
319 | return $data; | ||
320 | }) | ||
321 | ; | ||
322 | |||
323 | $result = $this->controller->list($request, $response); | ||
324 | |||
325 | static::assertSame(200, $result->getStatusCode()); | ||
326 | static::assertSame('tag.list', (string) $result->getBody()); | ||
327 | static::assertSame('ghi def - Tag list - Shaarli', $assignedVariables['pagetitle']); | ||
328 | |||
329 | static::assertSame('ghi def', $assignedVariables['search_tags']); | ||
330 | static::assertCount(1, $assignedVariables['tags']); | ||
331 | static::assertSame(3, $assignedVariables['tags']['abc']); | ||
332 | } | ||
333 | |||
334 | /** | ||
335 | * Tag List - empty | ||
336 | */ | ||
337 | public function testEmptyList(): void | ||
338 | { | ||
339 | $this->createValidContainerMockSet(); | ||
340 | |||
341 | $request = $this->createMock(Request::class); | ||
342 | $response = new Response(); | ||
343 | |||
344 | // Save RainTPL assigned variables | ||
345 | $assignedVariables = []; | ||
346 | $this->assignTemplateVars($assignedVariables); | ||
347 | |||
348 | $this->container->bookmarkService | ||
349 | ->expects(static::once()) | ||
350 | ->method('bookmarksCountPerTag') | ||
351 | ->with([], null) | ||
352 | ->willReturnCallback(function (array $parameters, ?string $visibility): array { | ||
353 | return []; | ||
354 | }) | ||
355 | ; | ||
356 | |||
357 | // Make sure that PluginManager hook is triggered | ||
358 | $this->container->pluginManager | ||
359 | ->expects(static::at(0)) | ||
360 | ->method('executeHooks') | ||
361 | ->willReturnCallback(function (string $hook, array $data, array $param): array { | ||
362 | static::assertSame('render_taglist', $hook); | ||
363 | static::assertSame('', $data['search_tags']); | ||
364 | static::assertCount(0, $data['tags']); | ||
365 | |||
366 | static::assertArrayHasKey('loggedin', $param); | ||
367 | |||
368 | return $data; | ||
369 | }) | ||
370 | ; | ||
371 | |||
372 | $result = $this->controller->list($request, $response); | ||
373 | |||
374 | static::assertSame(200, $result->getStatusCode()); | ||
375 | static::assertSame('tag.list', (string) $result->getBody()); | ||
376 | static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); | ||
377 | |||
378 | static::assertSame('', $assignedVariables['search_tags']); | ||
379 | static::assertCount(0, $assignedVariables['tags']); | ||
380 | } | ||
381 | } | ||
diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php new file mode 100644 index 00000000..9a2b1f71 --- /dev/null +++ b/tests/front/controller/visitor/TagControllerTest.php | |||
@@ -0,0 +1,241 @@ | |||
1 | <?php | ||
2 | |||
3 | declare(strict_types=1); | ||
4 | |||
5 | namespace Shaarli\Front\Controller\Visitor; | ||
6 | |||
7 | use PHPUnit\Framework\TestCase; | ||
8 | use Slim\Http\Request; | ||
9 | use Slim\Http\Response; | ||
10 | |||
11 | class TagControllerTest extends TestCase | ||
12 | { | ||
13 | use FrontControllerMockHelper; | ||
14 | |||
15 | /** @var TagController */ protected $controller; | ||
16 | |||
17 | public function setUp(): void | ||
18 | { | ||
19 | $this->createContainer(); | ||
20 | |||
21 | $this->controller = new TagController($this->container); | ||
22 | } | ||
23 | |||
24 | public function testAddTagWithReferer(): void | ||
25 | { | ||
26 | $this->createValidContainerMockSet(); | ||
27 | |||
28 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; | ||
29 | |||
30 | $request = $this->createMock(Request::class); | ||
31 | $response = new Response(); | ||
32 | |||
33 | $tags = ['newTag' => 'abc']; | ||
34 | |||
35 | $result = $this->controller->addTag($request, $response, $tags); | ||
36 | |||
37 | static::assertInstanceOf(Response::class, $result); | ||
38 | static::assertSame(302, $result->getStatusCode()); | ||
39 | static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); | ||
40 | } | ||
41 | |||
42 | public function testAddTagWithRefererAndExistingSearch(): void | ||
43 | { | ||
44 | $this->createValidContainerMockSet(); | ||
45 | |||
46 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; | ||
47 | |||
48 | $request = $this->createMock(Request::class); | ||
49 | $response = new Response(); | ||
50 | |||
51 | $tags = ['newTag' => 'abc']; | ||
52 | |||
53 | $result = $this->controller->addTag($request, $response, $tags); | ||
54 | |||
55 | static::assertInstanceOf(Response::class, $result); | ||
56 | static::assertSame(302, $result->getStatusCode()); | ||
57 | static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); | ||
58 | } | ||
59 | |||
60 | public function testAddTagWithoutRefererAndExistingSearch(): void | ||
61 | { | ||
62 | $this->createValidContainerMockSet(); | ||
63 | |||
64 | $request = $this->createMock(Request::class); | ||
65 | $response = new Response(); | ||
66 | |||
67 | $tags = ['newTag' => 'abc']; | ||
68 | |||
69 | $result = $this->controller->addTag($request, $response, $tags); | ||
70 | |||
71 | static::assertInstanceOf(Response::class, $result); | ||
72 | static::assertSame(302, $result->getStatusCode()); | ||
73 | static::assertSame(['./?searchtags=abc'], $result->getHeader('location')); | ||
74 | } | ||
75 | |||
76 | public function testAddTagRemoveLegacyQueryParam(): void | ||
77 | { | ||
78 | $this->createValidContainerMockSet(); | ||
79 | |||
80 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; | ||
81 | |||
82 | $request = $this->createMock(Request::class); | ||
83 | $response = new Response(); | ||
84 | |||
85 | $tags = ['newTag' => 'abc']; | ||
86 | |||
87 | $result = $this->controller->addTag($request, $response, $tags); | ||
88 | |||
89 | static::assertInstanceOf(Response::class, $result); | ||
90 | static::assertSame(302, $result->getStatusCode()); | ||
91 | static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); | ||
92 | } | ||
93 | |||
94 | public function testAddTagResetPagination(): void | ||
95 | { | ||
96 | $this->createValidContainerMockSet(); | ||
97 | |||
98 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; | ||
99 | |||
100 | $request = $this->createMock(Request::class); | ||
101 | $response = new Response(); | ||
102 | |||
103 | $tags = ['newTag' => 'abc']; | ||
104 | |||
105 | $result = $this->controller->addTag($request, $response, $tags); | ||
106 | |||
107 | static::assertInstanceOf(Response::class, $result); | ||
108 | static::assertSame(302, $result->getStatusCode()); | ||
109 | static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); | ||
110 | } | ||
111 | |||
112 | public function testAddTagWithRefererAndEmptySearch(): void | ||
113 | { | ||
114 | $this->createValidContainerMockSet(); | ||
115 | |||
116 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; | ||
117 | |||
118 | $request = $this->createMock(Request::class); | ||
119 | $response = new Response(); | ||
120 | |||
121 | $tags = ['newTag' => 'abc']; | ||
122 | |||
123 | $result = $this->controller->addTag($request, $response, $tags); | ||
124 | |||
125 | static::assertInstanceOf(Response::class, $result); | ||
126 | static::assertSame(302, $result->getStatusCode()); | ||
127 | static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); | ||
128 | } | ||
129 | |||
130 | public function testAddTagWithoutNewTagWithReferer(): void | ||
131 | { | ||
132 | $this->createValidContainerMockSet(); | ||
133 | |||
134 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; | ||
135 | |||
136 | $request = $this->createMock(Request::class); | ||
137 | $response = new Response(); | ||
138 | |||
139 | $result = $this->controller->addTag($request, $response, []); | ||
140 | |||
141 | static::assertInstanceOf(Response::class, $result); | ||
142 | static::assertSame(302, $result->getStatusCode()); | ||
143 | static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); | ||
144 | } | ||
145 | |||
146 | public function testAddTagWithoutNewTagWithoutReferer(): void | ||
147 | { | ||
148 | $this->createValidContainerMockSet(); | ||
149 | |||
150 | $request = $this->createMock(Request::class); | ||
151 | $response = new Response(); | ||
152 | |||
153 | $result = $this->controller->addTag($request, $response, []); | ||
154 | |||
155 | static::assertInstanceOf(Response::class, $result); | ||
156 | static::assertSame(302, $result->getStatusCode()); | ||
157 | static::assertSame(['./'], $result->getHeader('location')); | ||
158 | } | ||
159 | |||
160 | public function testRemoveTagWithoutMatchingTag(): void | ||
161 | { | ||
162 | $this->createValidContainerMockSet(); | ||
163 | |||
164 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; | ||
165 | |||
166 | $request = $this->createMock(Request::class); | ||
167 | $response = new Response(); | ||
168 | |||
169 | $tags = ['tag' => 'abc']; | ||
170 | |||
171 | $result = $this->controller->removeTag($request, $response, $tags); | ||
172 | |||
173 | static::assertInstanceOf(Response::class, $result); | ||
174 | static::assertSame(302, $result->getStatusCode()); | ||
175 | static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); | ||
176 | } | ||
177 | |||
178 | public function testRemoveTagWithoutTagsearch(): void | ||
179 | { | ||
180 | $this->createValidContainerMockSet(); | ||
181 | |||
182 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; | ||
183 | |||
184 | $request = $this->createMock(Request::class); | ||
185 | $response = new Response(); | ||
186 | |||
187 | $tags = ['tag' => 'abc']; | ||
188 | |||
189 | $result = $this->controller->removeTag($request, $response, $tags); | ||
190 | |||
191 | static::assertInstanceOf(Response::class, $result); | ||
192 | static::assertSame(302, $result->getStatusCode()); | ||
193 | static::assertSame(['/controller/'], $result->getHeader('location')); | ||
194 | } | ||
195 | |||
196 | public function testRemoveTagWithoutReferer(): void | ||
197 | { | ||
198 | $this->createValidContainerMockSet(); | ||
199 | |||
200 | $request = $this->createMock(Request::class); | ||
201 | $response = new Response(); | ||
202 | |||
203 | $tags = ['tag' => 'abc']; | ||
204 | |||
205 | $result = $this->controller->removeTag($request, $response, $tags); | ||
206 | |||
207 | static::assertInstanceOf(Response::class, $result); | ||
208 | static::assertSame(302, $result->getStatusCode()); | ||
209 | static::assertSame(['./'], $result->getHeader('location')); | ||
210 | } | ||
211 | |||
212 | public function testRemoveTagWithoutTag(): void | ||
213 | { | ||
214 | $this->createValidContainerMockSet(); | ||
215 | |||
216 | $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc']; | ||
217 | |||
218 | $request = $this->createMock(Request::class); | ||
219 | $response = new Response(); | ||
220 | |||
221 | $result = $this->controller->removeTag($request, $response, []); | ||
222 | |||
223 | static::assertInstanceOf(Response::class, $result); | ||
224 | static::assertSame(302, $result->getStatusCode()); | ||
225 | static::assertSame(['/controller/?searchtag=abc'], $result->getHeader('location')); | ||
226 | } | ||
227 | |||
228 | public function testRemoveTagWithoutTagWithoutReferer(): void | ||
229 | { | ||
230 | $this->createValidContainerMockSet(); | ||
231 | |||
232 | $request = $this->createMock(Request::class); | ||
233 | $response = new Response(); | ||
234 | |||
235 | $result = $this->controller->removeTag($request, $response, []); | ||
236 | |||
237 | static::assertInstanceOf(Response::class, $result); | ||
238 | static::assertSame(302, $result->getStatusCode()); | ||
239 | static::assertSame(['./'], $result->getHeader('location')); | ||
240 | } | ||
241 | } | ||