aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/front/controller
diff options
context:
space:
mode:
Diffstat (limited to 'tests/front/controller')
-rw-r--r--tests/front/controller/admin/PostBookmarkControllerTest.php652
1 files changed, 652 insertions, 0 deletions
diff --git a/tests/front/controller/admin/PostBookmarkControllerTest.php b/tests/front/controller/admin/PostBookmarkControllerTest.php
new file mode 100644
index 00000000..f00a15c9
--- /dev/null
+++ b/tests/front/controller/admin/PostBookmarkControllerTest.php
@@ -0,0 +1,652 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Config\ConfigManager;
10use Shaarli\Front\Exception\WrongTokenException;
11use Shaarli\Http\HttpAccess;
12use Shaarli\Security\SessionManager;
13use Shaarli\Thumbnailer;
14use Slim\Http\Request;
15use Slim\Http\Response;
16use Slim\Http\Uri;
17
18class PostBookmarkControllerTest extends TestCase
19{
20 use FrontAdminControllerMockHelper;
21
22 /** @var PostBookmarkController */
23 protected $controller;
24
25 public function setUp(): void
26 {
27 $this->createContainer();
28
29 $this->container->httpAccess = $this->createMock(HttpAccess::class);
30 $this->controller = new PostBookmarkController($this->container);
31 }
32
33 /**
34 * Test displaying add link page
35 */
36 public function testAddShaare(): void
37 {
38 $assignedVariables = [];
39 $this->assignTemplateVars($assignedVariables);
40
41 $request = $this->createMock(Request::class);
42 $response = new Response();
43
44 $result = $this->controller->addShaare($request, $response);
45
46 static::assertSame(200, $result->getStatusCode());
47 static::assertSame('addlink', (string) $result->getBody());
48
49 static::assertSame('Shaare a new link - Shaarli', $assignedVariables['pagetitle']);
50 }
51
52 /**
53 * Test displaying bookmark create form
54 * Ensure that every step of the standard workflow works properly.
55 */
56 public function testDisplayCreateFormWithUrl(): void
57 {
58 $this->container->environment = [
59 'HTTP_REFERER' => $referer = 'http://shaarli/subfolder/controller/?searchtag=abc'
60 ];
61
62 $assignedVariables = [];
63 $this->assignTemplateVars($assignedVariables);
64
65 $url = 'http://url.tld/other?part=3&utm_ad=pay#hash';
66 $expectedUrl = str_replace('&utm_ad=pay', '', $url);
67 $remoteTitle = 'Remote Title';
68 $remoteDesc = 'Sometimes the meta description is relevant.';
69 $remoteTags = 'abc def';
70
71 $request = $this->createMock(Request::class);
72 $request->method('getParam')->willReturnCallback(function (string $key) use ($url): ?string {
73 return $key === 'post' ? $url : null;
74 });
75 $response = new Response();
76
77 $this->container->httpAccess
78 ->expects(static::once())
79 ->method('getCurlDownloadCallback')
80 ->willReturnCallback(
81 function (&$charset, &$title, &$description, &$tags) use (
82 $remoteTitle,
83 $remoteDesc,
84 $remoteTags
85 ): callable {
86 return function () use (
87 &$charset,
88 &$title,
89 &$description,
90 &$tags,
91 $remoteTitle,
92 $remoteDesc,
93 $remoteTags
94 ): void {
95 $charset = 'ISO-8859-1';
96 $title = $remoteTitle;
97 $description = $remoteDesc;
98 $tags = $remoteTags;
99 };
100 }
101 )
102 ;
103 $this->container->httpAccess
104 ->expects(static::once())
105 ->method('getHttpResponse')
106 ->with($expectedUrl, 30, 4194304)
107 ->willReturnCallback(function($url, $timeout, $maxBytes, $callback): void {
108 $callback();
109 })
110 ;
111
112 $this->container->bookmarkService
113 ->expects(static::once())
114 ->method('bookmarksCountPerTag')
115 ->willReturn($tags = ['tag1' => 2, 'tag2' => 1])
116 ;
117
118 // Make sure that PluginManager hook is triggered
119 $this->container->pluginManager
120 ->expects(static::at(0))
121 ->method('executeHooks')
122 ->willReturnCallback(function (string $hook, array $data) use ($remoteTitle, $remoteDesc): array {
123 static::assertSame('render_editlink', $hook);
124 static::assertSame($remoteTitle, $data['link']['title']);
125 static::assertSame($remoteDesc, $data['link']['description']);
126
127 return $data;
128 })
129 ;
130
131 $result = $this->controller->displayCreateForm($request, $response);
132
133 static::assertSame(200, $result->getStatusCode());
134 static::assertSame('editlink', (string) $result->getBody());
135
136 static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']);
137
138 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
139 static::assertSame($remoteTitle, $assignedVariables['link']['title']);
140 static::assertSame($remoteDesc, $assignedVariables['link']['description']);
141 static::assertSame($remoteTags, $assignedVariables['link']['tags']);
142 static::assertFalse($assignedVariables['link']['private']);
143
144 static::assertTrue($assignedVariables['link_is_new']);
145 static::assertSame($referer, $assignedVariables['http_referer']);
146 static::assertSame($tags, $assignedVariables['tags']);
147 static::assertArrayHasKey('source', $assignedVariables);
148 static::assertArrayHasKey('default_private_links', $assignedVariables);
149 }
150
151 /**
152 * Test displaying bookmark create form
153 * Ensure all available query parameters are handled properly.
154 */
155 public function testDisplayCreateFormWithFullParameters(): void
156 {
157 $assignedVariables = [];
158 $this->assignTemplateVars($assignedVariables);
159
160 $parameters = [
161 'post' => 'http://url.tld/other?part=3&utm_ad=pay#hash',
162 'title' => 'Provided Title',
163 'description' => 'Provided description.',
164 'tags' => 'abc def',
165 'private' => '1',
166 'source' => 'apps',
167 ];
168 $expectedUrl = str_replace('&utm_ad=pay', '', $parameters['post']);
169
170 $request = $this->createMock(Request::class);
171 $request
172 ->method('getParam')
173 ->willReturnCallback(function (string $key) use ($parameters): ?string {
174 return $parameters[$key] ?? null;
175 });
176 $response = new Response();
177
178 $result = $this->controller->displayCreateForm($request, $response);
179
180 static::assertSame(200, $result->getStatusCode());
181 static::assertSame('editlink', (string) $result->getBody());
182
183 static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']);
184
185 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
186 static::assertSame($parameters['title'], $assignedVariables['link']['title']);
187 static::assertSame($parameters['description'], $assignedVariables['link']['description']);
188 static::assertSame($parameters['tags'], $assignedVariables['link']['tags']);
189 static::assertTrue($assignedVariables['link']['private']);
190 static::assertTrue($assignedVariables['link_is_new']);
191 static::assertSame($parameters['source'], $assignedVariables['source']);
192 }
193
194 /**
195 * Test displaying bookmark create form
196 * Without any parameter.
197 */
198 public function testDisplayCreateFormEmpty(): void
199 {
200 $assignedVariables = [];
201 $this->assignTemplateVars($assignedVariables);
202
203 $request = $this->createMock(Request::class);
204 $response = new Response();
205
206 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
207 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
208
209 $result = $this->controller->displayCreateForm($request, $response);
210
211 static::assertSame(200, $result->getStatusCode());
212 static::assertSame('editlink', (string) $result->getBody());
213 static::assertSame('', $assignedVariables['link']['url']);
214 static::assertSame('Note: ', $assignedVariables['link']['title']);
215 static::assertSame('', $assignedVariables['link']['description']);
216 static::assertSame('', $assignedVariables['link']['tags']);
217 static::assertFalse($assignedVariables['link']['private']);
218 static::assertTrue($assignedVariables['link_is_new']);
219 }
220
221 /**
222 * Test displaying bookmark create form
223 * URL not using HTTP protocol: do not try to retrieve the title
224 */
225 public function testDisplayCreateFormNotHttp(): void
226 {
227 $assignedVariables = [];
228 $this->assignTemplateVars($assignedVariables);
229
230 $url = 'magnet://kubuntu.torrent';
231 $request = $this->createMock(Request::class);
232 $request
233 ->method('getParam')
234 ->willReturnCallback(function (string $key) use ($url): ?string {
235 return $key === 'post' ? $url : null;
236 });
237 $response = new Response();
238
239 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
240 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
241
242 $result = $this->controller->displayCreateForm($request, $response);
243
244 static::assertSame(200, $result->getStatusCode());
245 static::assertSame('editlink', (string) $result->getBody());
246 static::assertSame($url, $assignedVariables['link']['url']);
247 static::assertTrue($assignedVariables['link_is_new']);
248 }
249
250 /**
251 * Test displaying bookmark create form
252 * When markdown formatter is enabled, the no markdown tag should be added to existing tags.
253 */
254 public function testDisplayCreateFormWithMarkdownEnabled(): void
255 {
256 $assignedVariables = [];
257 $this->assignTemplateVars($assignedVariables);
258
259 $this->container->conf = $this->createMock(ConfigManager::class);
260 $this->container->conf
261 ->expects(static::atLeastOnce())
262 ->method('get')->willReturnCallback(function (string $key): ?string {
263 if ($key === 'formatter') {
264 return 'markdown';
265 }
266
267 return $key;
268 })
269 ;
270
271 $request = $this->createMock(Request::class);
272 $response = new Response();
273
274 $result = $this->controller->displayCreateForm($request, $response);
275
276 static::assertSame(200, $result->getStatusCode());
277 static::assertSame('editlink', (string) $result->getBody());
278 static::assertSame(['nomarkdown' => 1], $assignedVariables['tags']);
279 }
280
281 /**
282 * Test displaying bookmark create form
283 * When an existing URL is submitted, we want to edit the existing link.
284 */
285 public function testDisplayCreateFormWithExistingUrl(): void
286 {
287 $assignedVariables = [];
288 $this->assignTemplateVars($assignedVariables);
289
290 $url = 'http://url.tld/other?part=3&utm_ad=pay#hash';
291 $expectedUrl = str_replace('&utm_ad=pay', '', $url);
292
293 $request = $this->createMock(Request::class);
294 $request
295 ->method('getParam')
296 ->willReturnCallback(function (string $key) use ($url): ?string {
297 return $key === 'post' ? $url : null;
298 });
299 $response = new Response();
300
301 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
302 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
303
304 $this->container->bookmarkService
305 ->expects(static::once())
306 ->method('findByUrl')
307 ->with($expectedUrl)
308 ->willReturn(
309 (new Bookmark())
310 ->setId($id = 23)
311 ->setUrl($expectedUrl)
312 ->setTitle($title = 'Bookmark Title')
313 ->setDescription($description = 'Bookmark description.')
314 ->setTags($tags = ['abc', 'def'])
315 ->setPrivate(true)
316 ->setCreated($createdAt = new \DateTime('2020-06-10 18:45:44'))
317 )
318 ;
319
320 $result = $this->controller->displayCreateForm($request, $response);
321
322 static::assertSame(200, $result->getStatusCode());
323 static::assertSame('editlink', (string) $result->getBody());
324
325 static::assertSame('Edit Shaare - Shaarli', $assignedVariables['pagetitle']);
326 static::assertFalse($assignedVariables['link_is_new']);
327
328 static::assertSame($id, $assignedVariables['link']['id']);
329 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
330 static::assertSame($title, $assignedVariables['link']['title']);
331 static::assertSame($description, $assignedVariables['link']['description']);
332 static::assertSame(implode(' ', $tags), $assignedVariables['link']['tags']);
333 static::assertTrue($assignedVariables['link']['private']);
334 static::assertSame($createdAt, $assignedVariables['link']['created']);
335 }
336
337 /**
338 * Test displaying bookmark edit form
339 * When an existing ID is provided, ensure that default workflow works properly.
340 */
341 public function testDisplayEditFormDefault(): void
342 {
343 $assignedVariables = [];
344 $this->assignTemplateVars($assignedVariables);
345
346 $id = 11;
347
348 $request = $this->createMock(Request::class);
349 $response = new Response();
350
351 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
352 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
353
354 $this->container->bookmarkService
355 ->expects(static::once())
356 ->method('get')
357 ->with($id)
358 ->willReturn(
359 (new Bookmark())
360 ->setId($id)
361 ->setUrl($url = 'http://domain.tld')
362 ->setTitle($title = 'Bookmark Title')
363 ->setDescription($description = 'Bookmark description.')
364 ->setTags($tags = ['abc', 'def'])
365 ->setPrivate(true)
366 ->setCreated($createdAt = new \DateTime('2020-06-10 18:45:44'))
367 )
368 ;
369
370 $result = $this->controller->displayEditForm($request, $response, ['id' => (string) $id]);
371
372 static::assertSame(200, $result->getStatusCode());
373 static::assertSame('editlink', (string) $result->getBody());
374
375 static::assertSame('Edit Shaare - Shaarli', $assignedVariables['pagetitle']);
376 static::assertFalse($assignedVariables['link_is_new']);
377
378 static::assertSame($id, $assignedVariables['link']['id']);
379 static::assertSame($url, $assignedVariables['link']['url']);
380 static::assertSame($title, $assignedVariables['link']['title']);
381 static::assertSame($description, $assignedVariables['link']['description']);
382 static::assertSame(implode(' ', $tags), $assignedVariables['link']['tags']);
383 static::assertTrue($assignedVariables['link']['private']);
384 static::assertSame($createdAt, $assignedVariables['link']['created']);
385 }
386
387 /**
388 * Test save a new bookmark
389 */
390 public function testSaveBookmark(): void
391 {
392 $id = 21;
393 $parameters = [
394 'lf_url' => 'http://url.tld/other?part=3#hash',
395 'lf_title' => 'Provided Title',
396 'lf_description' => 'Provided description.',
397 'lf_tags' => 'abc def',
398 'lf_private' => '1',
399 'returnurl' => 'http://shaarli.tld/subfolder/add-shaare'
400 ];
401
402 $request = $this->createMock(Request::class);
403 $request
404 ->method('getParam')
405 ->willReturnCallback(function (string $key) use ($parameters): ?string {
406 return $parameters[$key] ?? null;
407 })
408 ;
409 $request->method('getUri')->willReturnCallback(function (): Uri {
410 $uri = $this->createMock(Uri::class);
411 $uri->method('getBasePath')->willReturn('/subfolder');
412
413 return $uri;
414 });
415 $response = new Response();
416
417 $checkBookmark = function (Bookmark $bookmark) use ($parameters) {
418 static::assertSame($parameters['lf_url'], $bookmark->getUrl());
419 static::assertSame($parameters['lf_title'], $bookmark->getTitle());
420 static::assertSame($parameters['lf_description'], $bookmark->getDescription());
421 static::assertSame($parameters['lf_tags'], $bookmark->getTagsString());
422 static::assertTrue($bookmark->isPrivate());
423 };
424
425 $this->container->bookmarkService
426 ->expects(static::once())
427 ->method('addOrSet')
428 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void {
429 static::assertFalse($save);
430
431 $checkBookmark($bookmark);
432
433 $bookmark->setId($id);
434 })
435 ;
436 $this->container->bookmarkService
437 ->expects(static::once())
438 ->method('set')
439 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void {
440 static::assertTrue($save);
441
442 $checkBookmark($bookmark);
443
444 static::assertSame($id, $bookmark->getId());
445 })
446 ;
447
448 // Make sure that PluginManager hook is triggered
449 $this->container->pluginManager
450 ->expects(static::at(0))
451 ->method('executeHooks')
452 ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array {
453 static::assertSame('save_link', $hook);
454
455 static::assertSame($id, $data['id']);
456 static::assertSame($parameters['lf_url'], $data['url']);
457 static::assertSame($parameters['lf_title'], $data['title']);
458 static::assertSame($parameters['lf_description'], $data['description']);
459 static::assertSame($parameters['lf_tags'], $data['tags']);
460 static::assertTrue($data['private']);
461
462 return $data;
463 })
464 ;
465
466 $result = $this->controller->save($request, $response);
467
468 static::assertSame(302, $result->getStatusCode());
469 static::assertRegExp('@/subfolder/#\w{6}@', $result->getHeader('location')[0]);
470 }
471
472
473 /**
474 * Test save an existing bookmark
475 */
476 public function testSaveExistingBookmark(): void
477 {
478 $id = 21;
479 $parameters = [
480 'lf_id' => (string) $id,
481 'lf_url' => 'http://url.tld/other?part=3#hash',
482 'lf_title' => 'Provided Title',
483 'lf_description' => 'Provided description.',
484 'lf_tags' => 'abc def',
485 'lf_private' => '1',
486 'returnurl' => 'http://shaarli.tld/subfolder/?page=2'
487 ];
488
489 $request = $this->createMock(Request::class);
490 $request
491 ->method('getParam')
492 ->willReturnCallback(function (string $key) use ($parameters): ?string {
493 return $parameters[$key] ?? null;
494 })
495 ;
496 $request->method('getUri')->willReturnCallback(function (): Uri {
497 $uri = $this->createMock(Uri::class);
498 $uri->method('getBasePath')->willReturn('/subfolder');
499
500 return $uri;
501 });
502 $response = new Response();
503
504 $checkBookmark = function (Bookmark $bookmark) use ($parameters, $id) {
505 static::assertSame($id, $bookmark->getId());
506 static::assertSame($parameters['lf_url'], $bookmark->getUrl());
507 static::assertSame($parameters['lf_title'], $bookmark->getTitle());
508 static::assertSame($parameters['lf_description'], $bookmark->getDescription());
509 static::assertSame($parameters['lf_tags'], $bookmark->getTagsString());
510 static::assertTrue($bookmark->isPrivate());
511 };
512
513 $this->container->bookmarkService->expects(static::atLeastOnce())->method('exists')->willReturn(true);
514 $this->container->bookmarkService
515 ->expects(static::once())
516 ->method('get')
517 ->willReturn((new Bookmark())->setId($id)->setUrl('http://other.url'))
518 ;
519 $this->container->bookmarkService
520 ->expects(static::once())
521 ->method('addOrSet')
522 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void {
523 static::assertFalse($save);
524
525 $checkBookmark($bookmark);
526 })
527 ;
528 $this->container->bookmarkService
529 ->expects(static::once())
530 ->method('set')
531 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void {
532 static::assertTrue($save);
533
534 $checkBookmark($bookmark);
535
536 static::assertSame($id, $bookmark->getId());
537 })
538 ;
539
540 // Make sure that PluginManager hook is triggered
541 $this->container->pluginManager
542 ->expects(static::at(0))
543 ->method('executeHooks')
544 ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array {
545 static::assertSame('save_link', $hook);
546
547 static::assertSame($id, $data['id']);
548 static::assertSame($parameters['lf_url'], $data['url']);
549 static::assertSame($parameters['lf_title'], $data['title']);
550 static::assertSame($parameters['lf_description'], $data['description']);
551 static::assertSame($parameters['lf_tags'], $data['tags']);
552 static::assertTrue($data['private']);
553
554 return $data;
555 })
556 ;
557
558 $result = $this->controller->save($request, $response);
559
560 static::assertSame(302, $result->getStatusCode());
561 static::assertRegExp('@/subfolder/\?page=2#\w{6}@', $result->getHeader('location')[0]);
562 }
563
564 /**
565 * Test save a bookmark - try to retrieve the thumbnail
566 */
567 public function testSaveBookmarkWithThumbnail(): void
568 {
569 $parameters = ['lf_url' => 'http://url.tld/other?part=3#hash'];
570
571 $request = $this->createMock(Request::class);
572 $request
573 ->method('getParam')
574 ->willReturnCallback(function (string $key) use ($parameters): ?string {
575 return $parameters[$key] ?? null;
576 })
577 ;
578 $request->method('getUri')->willReturnCallback(function (): Uri {
579 $uri = $this->createMock(Uri::class);
580 $uri->method('getBasePath')->willReturn('/subfolder');
581
582 return $uri;
583 });
584 $response = new Response();
585
586 $this->container->conf = $this->createMock(ConfigManager::class);
587 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
588 return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default;
589 });
590
591 $this->container->thumbnailer = $this->createMock(Thumbnailer::class);
592 $this->container->thumbnailer
593 ->expects(static::once())
594 ->method('get')
595 ->with($parameters['lf_url'])
596 ->willReturn($thumb = 'http://thumb.url')
597 ;
598
599 $this->container->bookmarkService
600 ->expects(static::once())
601 ->method('addOrSet')
602 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($thumb): void {
603 static::assertSame($thumb, $bookmark->getThumbnail());
604 })
605 ;
606
607 $result = $this->controller->save($request, $response);
608
609 static::assertSame(302, $result->getStatusCode());
610 }
611
612 /**
613 * Change the password with a wrong existing password
614 */
615 public function testSaveBookmarkFromBookmarklet(): void
616 {
617 $parameters = ['source' => 'bookmarklet'];
618
619 $request = $this->createMock(Request::class);
620 $request
621 ->method('getParam')
622 ->willReturnCallback(function (string $key) use ($parameters): ?string {
623 return $parameters[$key] ?? null;
624 })
625 ;
626 $response = new Response();
627
628 $result = $this->controller->save($request, $response);
629
630 static::assertSame(200, $result->getStatusCode());
631 static::assertSame('<script>self.close();</script>', (string) $result->getBody());
632 }
633
634 /**
635 * Change the password with a wrong existing password
636 */
637 public function testSaveBookmarkWrongToken(): void
638 {
639 $this->container->sessionManager = $this->createMock(SessionManager::class);
640 $this->container->sessionManager->method('checkToken')->willReturn(false);
641
642 $this->container->bookmarkService->expects(static::never())->method('addOrSet');
643 $this->container->bookmarkService->expects(static::never())->method('set');
644
645 $request = $this->createMock(Request::class);
646 $response = new Response();
647
648 $this->expectException(WrongTokenException::class);
649
650 $this->controller->save($request, $response);
651 }
652}