aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2020-08-27 10:27:34 +0200
committerGitHub <noreply@github.com>2020-08-27 10:27:34 +0200
commitaf41d5ab5d2bd3ba64d052c997bc6afa6966a63c (patch)
tree8fad2829c55f94022e359fa8914e11f80a2afc2a /tests
parentb8e3630f2ecd142d397b1b062a346a667bb78595 (diff)
parent0c6fdbe12bbbb336348666b14b82096f24d5858b (diff)
downloadShaarli-af41d5ab5d2bd3ba64d052c997bc6afa6966a63c.tar.gz
Shaarli-af41d5ab5d2bd3ba64d052c997bc6afa6966a63c.tar.zst
Shaarli-af41d5ab5d2bd3ba64d052c997bc6afa6966a63c.zip
Merge pull request #1511 from ArthurHoaro/wip-slim-routing
Diffstat (limited to 'tests')
-rw-r--r--tests/api/controllers/links/GetLinkIdTest.php2
-rw-r--r--tests/api/controllers/links/GetLinksTest.php2
-rw-r--r--tests/api/controllers/links/PostLinkTest.php4
-rw-r--r--tests/api/controllers/links/PutLinkTest.php4
-rw-r--r--tests/bookmark/BookmarkFileServiceTest.php33
-rw-r--r--tests/bookmark/BookmarkInitializerTest.php14
-rw-r--r--tests/bookmark/BookmarkTest.php4
-rw-r--r--tests/bookmark/LinkUtilsTest.php4
-rw-r--r--tests/bootstrap.php13
-rw-r--r--tests/config/ConfigPluginTest.php16
-rw-r--r--tests/container/ContainerBuilderTest.php34
-rw-r--r--tests/container/ShaarliTestContainer.php42
-rw-r--r--tests/feed/CachedPageTest.php6
-rw-r--r--tests/feed/FeedBuilderTest.php83
-rw-r--r--tests/formatter/BookmarkDefaultFormatterTest.php4
-rw-r--r--tests/formatter/BookmarkMarkdownFormatterTest.php4
-rw-r--r--tests/front/ShaarliAdminMiddlewareTest.php100
-rw-r--r--tests/front/ShaarliMiddlewareTest.php161
-rw-r--r--tests/front/controller/LoginControllerTest.php178
-rw-r--r--tests/front/controller/ShaarliControllerTest.php116
-rw-r--r--tests/front/controller/admin/ConfigureControllerTest.php252
-rw-r--r--tests/front/controller/admin/ExportControllerTest.php163
-rw-r--r--tests/front/controller/admin/FrontAdminControllerMockHelper.php56
-rw-r--r--tests/front/controller/admin/ImportControllerTest.php148
-rw-r--r--tests/front/controller/admin/LogoutControllerTest.php51
-rw-r--r--tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php47
-rw-r--r--tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php418
-rw-r--r--tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php376
-rw-r--r--tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php315
-rw-r--r--tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php155
-rw-r--r--tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php145
-rw-r--r--tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php282
-rw-r--r--tests/front/controller/admin/ManageTagControllerTest.php272
-rw-r--r--tests/front/controller/admin/PasswordControllerTest.php203
-rw-r--r--tests/front/controller/admin/PluginsControllerTest.php204
-rw-r--r--tests/front/controller/admin/SessionFilterControllerTest.php177
-rw-r--r--tests/front/controller/admin/ShaarliAdminControllerTest.php184
-rw-r--r--tests/front/controller/admin/ThumbnailsControllerTest.php154
-rw-r--r--tests/front/controller/admin/TokenControllerTest.php41
-rw-r--r--tests/front/controller/admin/ToolsControllerTest.php69
-rw-r--r--tests/front/controller/visitor/BookmarkListControllerTest.php448
-rw-r--r--tests/front/controller/visitor/DailyControllerTest.php476
-rw-r--r--tests/front/controller/visitor/ErrorControllerTest.php70
-rw-r--r--tests/front/controller/visitor/FeedControllerTest.php145
-rw-r--r--tests/front/controller/visitor/FrontControllerMockHelper.php119
-rw-r--r--tests/front/controller/visitor/InstallControllerTest.php262
-rw-r--r--tests/front/controller/visitor/LoginControllerTest.php404
-rw-r--r--tests/front/controller/visitor/OpenSearchControllerTest.php44
-rw-r--r--tests/front/controller/visitor/PictureWallControllerTest.php121
-rw-r--r--tests/front/controller/visitor/PublicSessionFilterControllerTest.php122
-rw-r--r--tests/front/controller/visitor/ShaarliVisitorControllerTest.php215
-rw-r--r--tests/front/controller/visitor/TagCloudControllerTest.php369
-rw-r--r--tests/front/controller/visitor/TagControllerTest.php215
-rw-r--r--tests/http/HttpUtils/IndexUrlTest.php32
-rw-r--r--tests/legacy/LegacyControllerTest.php99
-rw-r--r--tests/legacy/LegacyLinkDBTest.php1
-rw-r--r--tests/legacy/LegacyRouterTest.php (renamed from tests/RouterTest.php)243
-rw-r--r--tests/netscape/BookmarkExportTest.php69
-rw-r--r--tests/netscape/BookmarkImportTest.php68
-rw-r--r--tests/plugins/PluginAddlinkTest.php10
-rw-r--r--tests/plugins/PluginPlayvideosTest.php6
-rw-r--r--tests/plugins/PluginPubsubhubbubTest.php6
-rw-r--r--tests/plugins/PluginQrcodeTest.php4
-rw-r--r--tests/plugins/resources/hashtags.md10
-rw-r--r--tests/plugins/resources/hashtags.raw10
-rw-r--r--tests/plugins/resources/markdown.html33
-rw-r--r--tests/plugins/resources/markdown.md34
-rw-r--r--tests/render/PageCacheManagerTest.php (renamed from tests/feed/CacheTest.php)39
-rw-r--r--tests/security/LoginManagerTest.php30
-rw-r--r--tests/security/SessionManagerTest.php71
-rw-r--r--tests/updater/UpdaterTest.php59
-rw-r--r--tests/utils/ReferenceLinkDB.php8
72 files changed, 7645 insertions, 733 deletions
diff --git a/tests/api/controllers/links/GetLinkIdTest.php b/tests/api/controllers/links/GetLinkIdTest.php
index c26411ac..8bb81dc8 100644
--- a/tests/api/controllers/links/GetLinkIdTest.php
+++ b/tests/api/controllers/links/GetLinkIdTest.php
@@ -102,7 +102,7 @@ class GetLinkIdTest extends \PHPUnit\Framework\TestCase
102 $this->assertEquals($id, $data['id']); 102 $this->assertEquals($id, $data['id']);
103 103
104 // Check link elements 104 // Check link elements
105 $this->assertEquals('http://domain.tld/?WDWyig', $data['url']); 105 $this->assertEquals('http://domain.tld/shaare/WDWyig', $data['url']);
106 $this->assertEquals('WDWyig', $data['shorturl']); 106 $this->assertEquals('WDWyig', $data['shorturl']);
107 $this->assertEquals('Link title: @website', $data['title']); 107 $this->assertEquals('Link title: @website', $data['title']);
108 $this->assertEquals( 108 $this->assertEquals(
diff --git a/tests/api/controllers/links/GetLinksTest.php b/tests/api/controllers/links/GetLinksTest.php
index 4e2d55ac..d02e6fad 100644
--- a/tests/api/controllers/links/GetLinksTest.php
+++ b/tests/api/controllers/links/GetLinksTest.php
@@ -109,7 +109,7 @@ class GetLinksTest extends \PHPUnit\Framework\TestCase
109 109
110 // Check first element fields 110 // Check first element fields
111 $first = $data[2]; 111 $first = $data[2];
112 $this->assertEquals('http://domain.tld/?WDWyig', $first['url']); 112 $this->assertEquals('http://domain.tld/shaare/WDWyig', $first['url']);
113 $this->assertEquals('WDWyig', $first['shorturl']); 113 $this->assertEquals('WDWyig', $first['shorturl']);
114 $this->assertEquals('Link title: @website', $first['title']); 114 $this->assertEquals('Link title: @website', $first['title']);
115 $this->assertEquals( 115 $this->assertEquals(
diff --git a/tests/api/controllers/links/PostLinkTest.php b/tests/api/controllers/links/PostLinkTest.php
index b2dd09eb..4e791a04 100644
--- a/tests/api/controllers/links/PostLinkTest.php
+++ b/tests/api/controllers/links/PostLinkTest.php
@@ -131,8 +131,8 @@ class PostLinkTest extends TestCase
131 $this->assertEquals(self::NB_FIELDS_LINK, count($data)); 131 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
132 $this->assertEquals(43, $data['id']); 132 $this->assertEquals(43, $data['id']);
133 $this->assertRegExp('/[\w_-]{6}/', $data['shorturl']); 133 $this->assertRegExp('/[\w_-]{6}/', $data['shorturl']);
134 $this->assertEquals('http://domain.tld/?' . $data['shorturl'], $data['url']); 134 $this->assertEquals('http://domain.tld/shaare/' . $data['shorturl'], $data['url']);
135 $this->assertEquals('?' . $data['shorturl'], $data['title']); 135 $this->assertEquals('/shaare/' . $data['shorturl'], $data['title']);
136 $this->assertEquals('', $data['description']); 136 $this->assertEquals('', $data['description']);
137 $this->assertEquals([], $data['tags']); 137 $this->assertEquals([], $data['tags']);
138 $this->assertEquals(true, $data['private']); 138 $this->assertEquals(true, $data['private']);
diff --git a/tests/api/controllers/links/PutLinkTest.php b/tests/api/controllers/links/PutLinkTest.php
index cb63742e..302cac0f 100644
--- a/tests/api/controllers/links/PutLinkTest.php
+++ b/tests/api/controllers/links/PutLinkTest.php
@@ -114,8 +114,8 @@ class PutLinkTest extends \PHPUnit\Framework\TestCase
114 $this->assertEquals(self::NB_FIELDS_LINK, count($data)); 114 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
115 $this->assertEquals($id, $data['id']); 115 $this->assertEquals($id, $data['id']);
116 $this->assertEquals('WDWyig', $data['shorturl']); 116 $this->assertEquals('WDWyig', $data['shorturl']);
117 $this->assertEquals('http://domain.tld/?WDWyig', $data['url']); 117 $this->assertEquals('http://domain.tld/shaare/WDWyig', $data['url']);
118 $this->assertEquals('?WDWyig', $data['title']); 118 $this->assertEquals('/shaare/WDWyig', $data['title']);
119 $this->assertEquals('', $data['description']); 119 $this->assertEquals('', $data['description']);
120 $this->assertEquals([], $data['tags']); 120 $this->assertEquals([], $data['tags']);
121 $this->assertEquals(true, $data['private']); 121 $this->assertEquals(true, $data['private']);
diff --git a/tests/bookmark/BookmarkFileServiceTest.php b/tests/bookmark/BookmarkFileServiceTest.php
index 4900d41d..7b1906d3 100644
--- a/tests/bookmark/BookmarkFileServiceTest.php
+++ b/tests/bookmark/BookmarkFileServiceTest.php
@@ -200,7 +200,7 @@ class BookmarkFileServiceTest extends TestCase
200 200
201 $bookmark = $this->privateLinkDB->get(43); 201 $bookmark = $this->privateLinkDB->get(43);
202 $this->assertEquals(43, $bookmark->getId()); 202 $this->assertEquals(43, $bookmark->getId());
203 $this->assertRegExp('/\?[\w\-]{6}/', $bookmark->getUrl()); 203 $this->assertRegExp('#/shaare/[\w\-]{6}#', $bookmark->getUrl());
204 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl()); 204 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl());
205 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle()); 205 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle());
206 $this->assertEmpty($bookmark->getDescription()); 206 $this->assertEmpty($bookmark->getDescription());
@@ -216,7 +216,7 @@ class BookmarkFileServiceTest extends TestCase
216 216
217 $bookmark = $this->privateLinkDB->get(43); 217 $bookmark = $this->privateLinkDB->get(43);
218 $this->assertEquals(43, $bookmark->getId()); 218 $this->assertEquals(43, $bookmark->getId());
219 $this->assertRegExp('/\?[\w\-]{6}/', $bookmark->getUrl()); 219 $this->assertRegExp('#/shaare/[\w\-]{6}#', $bookmark->getUrl());
220 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl()); 220 $this->assertRegExp('/[\w\-]{6}/', $bookmark->getShortUrl());
221 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle()); 221 $this->assertEquals($bookmark->getUrl(), $bookmark->getTitle());
222 $this->assertEmpty($bookmark->getDescription()); 222 $this->assertEmpty($bookmark->getDescription());
@@ -340,7 +340,7 @@ class BookmarkFileServiceTest extends TestCase
340 340
341 $bookmark = $this->privateLinkDB->get(42); 341 $bookmark = $this->privateLinkDB->get(42);
342 $this->assertEquals(42, $bookmark->getId()); 342 $this->assertEquals(42, $bookmark->getId());
343 $this->assertEquals('?WDWyig', $bookmark->getUrl()); 343 $this->assertEquals('/shaare/WDWyig', $bookmark->getUrl());
344 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl()); 344 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl());
345 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle()); 345 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle());
346 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription()); 346 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription());
@@ -359,7 +359,7 @@ class BookmarkFileServiceTest extends TestCase
359 359
360 $bookmark = $this->privateLinkDB->get(42); 360 $bookmark = $this->privateLinkDB->get(42);
361 $this->assertEquals(42, $bookmark->getId()); 361 $this->assertEquals(42, $bookmark->getId());
362 $this->assertEquals('?WDWyig', $bookmark->getUrl()); 362 $this->assertEquals('/shaare/WDWyig', $bookmark->getUrl());
363 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl()); 363 $this->assertEquals('1eYJ1Q', $bookmark->getShortUrl());
364 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle()); 364 $this->assertEquals('Note: I have a big ID but an old date', $bookmark->getTitle());
365 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription()); 365 $this->assertEquals('Used to test bookmarks reordering.', $bookmark->getDescription());
@@ -816,7 +816,6 @@ class BookmarkFileServiceTest extends TestCase
816 ); 816 );
817 $this->assertEquals( 817 $this->assertEquals(
818 [ 818 [
819 'web' => 4,
820 'cartoon' => 2, 819 'cartoon' => 2,
821 'gnu' => 1, 820 'gnu' => 1,
822 'dev' => 1, 821 'dev' => 1,
@@ -833,7 +832,6 @@ class BookmarkFileServiceTest extends TestCase
833 ); 832 );
834 $this->assertEquals( 833 $this->assertEquals(
835 [ 834 [
836 'web' => 1,
837 'html' => 1, 835 'html' => 1,
838 'w3c' => 1, 836 'w3c' => 1,
839 'css' => 1, 837 'css' => 1,
@@ -894,35 +892,35 @@ class BookmarkFileServiceTest extends TestCase
894 public function testFilterHashValid() 892 public function testFilterHashValid()
895 { 893 {
896 $request = smallHash('20150310_114651'); 894 $request = smallHash('20150310_114651');
897 $this->assertEquals( 895 $this->assertSame(
898 1, 896 $request,
899 count($this->publicLinkDB->findByHash($request)) 897 $this->publicLinkDB->findByHash($request)->getShortUrl()
900 ); 898 );
901 $request = smallHash('20150310_114633' . 8); 899 $request = smallHash('20150310_114633' . 8);
902 $this->assertEquals( 900 $this->assertSame(
903 1, 901 $request,
904 count($this->publicLinkDB->findByHash($request)) 902 $this->publicLinkDB->findByHash($request)->getShortUrl()
905 ); 903 );
906 } 904 }
907 905
908 /** 906 /**
909 * Test filterHash() with an invalid smallhash. 907 * Test filterHash() with an invalid smallhash.
910 *
911 * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException
912 */ 908 */
913 public function testFilterHashInValid1() 909 public function testFilterHashInValid1()
914 { 910 {
911 $this->expectException(BookmarkNotFoundException::class);
912
915 $request = 'blabla'; 913 $request = 'blabla';
916 $this->publicLinkDB->findByHash($request); 914 $this->publicLinkDB->findByHash($request);
917 } 915 }
918 916
919 /** 917 /**
920 * Test filterHash() with an empty smallhash. 918 * Test filterHash() with an empty smallhash.
921 *
922 * @expectedException \Shaarli\Bookmark\Exception\BookmarkNotFoundException
923 */ 919 */
924 public function testFilterHashInValid() 920 public function testFilterHashInValid()
925 { 921 {
922 $this->expectException(BookmarkNotFoundException::class);
923
926 $this->publicLinkDB->findByHash(''); 924 $this->publicLinkDB->findByHash('');
927 } 925 }
928 926
@@ -968,7 +966,6 @@ class BookmarkFileServiceTest extends TestCase
968 public function testCountLinkPerTagAllWithFilter() 966 public function testCountLinkPerTagAllWithFilter()
969 { 967 {
970 $expected = [ 968 $expected = [
971 'gnu' => 2,
972 'hashtag' => 2, 969 'hashtag' => 2,
973 '-exclude' => 1, 970 '-exclude' => 1,
974 '.hidden' => 1, 971 '.hidden' => 1,
@@ -991,7 +988,6 @@ class BookmarkFileServiceTest extends TestCase
991 public function testCountLinkPerTagPublicWithFilter() 988 public function testCountLinkPerTagPublicWithFilter()
992 { 989 {
993 $expected = [ 990 $expected = [
994 'gnu' => 2,
995 'hashtag' => 2, 991 'hashtag' => 2,
996 '-exclude' => 1, 992 '-exclude' => 1,
997 '.hidden' => 1, 993 '.hidden' => 1,
@@ -1015,7 +1011,6 @@ class BookmarkFileServiceTest extends TestCase
1015 { 1011 {
1016 $expected = [ 1012 $expected = [
1017 'cartoon' => 1, 1013 'cartoon' => 1,
1018 'dev' => 1,
1019 'tag1' => 1, 1014 'tag1' => 1,
1020 'tag2' => 1, 1015 'tag2' => 1,
1021 'tag3' => 1, 1016 'tag3' => 1,
diff --git a/tests/bookmark/BookmarkInitializerTest.php b/tests/bookmark/BookmarkInitializerTest.php
index d23eb069..3906cc7f 100644
--- a/tests/bookmark/BookmarkInitializerTest.php
+++ b/tests/bookmark/BookmarkInitializerTest.php
@@ -3,7 +3,6 @@
3namespace Shaarli\Bookmark; 3namespace Shaarli\Bookmark;
4 4
5use PHPUnit\Framework\TestCase; 5use PHPUnit\Framework\TestCase;
6use ReferenceLinkDB;
7use Shaarli\Config\ConfigManager; 6use Shaarli\Config\ConfigManager;
8use Shaarli\History; 7use Shaarli\History;
9 8
@@ -54,9 +53,9 @@ class BookmarkInitializerTest extends TestCase
54 } 53 }
55 54
56 /** 55 /**
57 * Test initialize() with an empty data store. 56 * Test initialize() with a data store containing bookmarks.
58 */ 57 */
59 public function testInitializeEmptyDataStore() 58 public function testInitializeNotEmptyDataStore(): void
60 { 59 {
61 $refDB = new \ReferenceLinkDB(); 60 $refDB = new \ReferenceLinkDB();
62 $refDB->write(self::$testDatastore); 61 $refDB->write(self::$testDatastore);
@@ -79,6 +78,8 @@ class BookmarkInitializerTest extends TestCase
79 ); 78 );
80 $this->assertFalse($bookmark->isPrivate()); 79 $this->assertFalse($bookmark->isPrivate());
81 80
81 $this->bookmarkService->save();
82
82 // Reload from file 83 // Reload from file
83 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true); 84 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true);
84 $this->assertEquals($refDB->countLinks() + 2, $this->bookmarkService->count()); 85 $this->assertEquals($refDB->countLinks() + 2, $this->bookmarkService->count());
@@ -97,10 +98,13 @@ class BookmarkInitializerTest extends TestCase
97 } 98 }
98 99
99 /** 100 /**
100 * Test initialize() with a data store containing bookmarks. 101 * Test initialize() with an a non existent datastore file .
101 */ 102 */
102 public function testInitializeNotEmptyDataStore() 103 public function testInitializeNonExistentDataStore(): void
103 { 104 {
105 $this->conf->set('resource.datastore', static::$testDatastore . '_empty');
106 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true);
107
104 $this->initializer->initialize(); 108 $this->initializer->initialize();
105 109
106 $this->assertEquals(2, $this->bookmarkService->count()); 110 $this->assertEquals(2, $this->bookmarkService->count());
diff --git a/tests/bookmark/BookmarkTest.php b/tests/bookmark/BookmarkTest.php
index 9a3bbbfc..4b6a3c07 100644
--- a/tests/bookmark/BookmarkTest.php
+++ b/tests/bookmark/BookmarkTest.php
@@ -124,8 +124,8 @@ class BookmarkTest extends TestCase
124 $this->assertEquals(1, $bookmark->getId()); 124 $this->assertEquals(1, $bookmark->getId());
125 $this->assertEquals('abc', $bookmark->getShortUrl()); 125 $this->assertEquals('abc', $bookmark->getShortUrl());
126 $this->assertEquals($date, $bookmark->getCreated()); 126 $this->assertEquals($date, $bookmark->getCreated());
127 $this->assertEquals('?abc', $bookmark->getUrl()); 127 $this->assertEquals('/shaare/abc', $bookmark->getUrl());
128 $this->assertEquals('?abc', $bookmark->getTitle()); 128 $this->assertEquals('/shaare/abc', $bookmark->getTitle());
129 $this->assertEquals('', $bookmark->getDescription()); 129 $this->assertEquals('', $bookmark->getDescription());
130 $this->assertEquals([], $bookmark->getTags()); 130 $this->assertEquals([], $bookmark->getTags());
131 $this->assertEquals('', $bookmark->getTagsString()); 131 $this->assertEquals('', $bookmark->getTagsString());
diff --git a/tests/bookmark/LinkUtilsTest.php b/tests/bookmark/LinkUtilsTest.php
index 591976f2..7d4a7b89 100644
--- a/tests/bookmark/LinkUtilsTest.php
+++ b/tests/bookmark/LinkUtilsTest.php
@@ -3,8 +3,6 @@
3namespace Shaarli\Bookmark; 3namespace Shaarli\Bookmark;
4 4
5use PHPUnit\Framework\TestCase; 5use PHPUnit\Framework\TestCase;
6use ReferenceLinkDB;
7use Shaarli\Config\ConfigManager;
8 6
9require_once 'tests/utils/CurlUtils.php'; 7require_once 'tests/utils/CurlUtils.php';
10 8
@@ -491,7 +489,7 @@ class LinkUtilsTest extends TestCase
491 */ 489 */
492 private function getHashtagLink($hashtag, $index = '') 490 private function getHashtagLink($hashtag, $index = '')
493 { 491 {
494 $hashtagLink = '<a href="' . $index . '?addtag=$1" title="Hashtag $1">#$1</a>'; 492 $hashtagLink = '<a href="' . $index . './add-tag/$1" title="Hashtag $1">#$1</a>';
495 return str_replace('$1', $hashtag, $hashtagLink); 493 return str_replace('$1', $hashtag, $hashtagLink);
496 } 494 }
497} 495}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 0afbcba6..d4ddedd5 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -18,7 +18,14 @@ require_once 'application/bookmark/LinkUtils.php';
18require_once 'application/Utils.php'; 18require_once 'application/Utils.php';
19require_once 'application/http/UrlUtils.php'; 19require_once 'application/http/UrlUtils.php';
20require_once 'application/http/HttpUtils.php'; 20require_once 'application/http/HttpUtils.php';
21require_once 'application/feed/Cache.php'; 21require_once 'tests/container/ShaarliTestContainer.php';
22require_once 'tests/utils/ReferenceLinkDB.php'; 22require_once 'tests/front/controller/visitor/FrontControllerMockHelper.php';
23require_once 'tests/utils/ReferenceHistory.php'; 23require_once 'tests/front/controller/admin/FrontAdminControllerMockHelper.php';
24require_once 'tests/updater/DummyUpdater.php';
24require_once 'tests/utils/FakeBookmarkService.php'; 25require_once 'tests/utils/FakeBookmarkService.php';
26require_once 'tests/utils/FakeConfigManager.php';
27require_once 'tests/utils/ReferenceHistory.php';
28require_once 'tests/utils/ReferenceLinkDB.php';
29require_once 'tests/utils/ReferenceSessionIdHashes.php';
30
31\ReferenceSessionIdHashes::genAllHashes();
diff --git a/tests/config/ConfigPluginTest.php b/tests/config/ConfigPluginTest.php
index d7a70e68..b2cc0045 100644
--- a/tests/config/ConfigPluginTest.php
+++ b/tests/config/ConfigPluginTest.php
@@ -2,6 +2,7 @@
2namespace Shaarli\Config; 2namespace Shaarli\Config;
3 3
4use Shaarli\Config\Exception\PluginConfigOrderException; 4use Shaarli\Config\Exception\PluginConfigOrderException;
5use Shaarli\Plugin\PluginManager;
5 6
6require_once 'application/config/ConfigPlugin.php'; 7require_once 'application/config/ConfigPlugin.php';
7 8
@@ -17,23 +18,30 @@ class ConfigPluginTest extends \PHPUnit\Framework\TestCase
17 */ 18 */
18 public function testSavePluginConfigValid() 19 public function testSavePluginConfigValid()
19 { 20 {
20 $data = array( 21 $data = [
21 'order_plugin1' => 2, // no plugin related 22 'order_plugin1' => 2, // no plugin related
22 'plugin2' => 0, // new - at the end 23 'plugin2' => 0, // new - at the end
23 'plugin3' => 0, // 2nd 24 'plugin3' => 0, // 2nd
24 'order_plugin3' => 8, 25 'order_plugin3' => 8,
25 'plugin4' => 0, // 1st 26 'plugin4' => 0, // 1st
26 'order_plugin4' => 5, 27 'order_plugin4' => 5,
27 ); 28 ];
28 29
29 $expected = array( 30 $expected = [
30 'plugin3', 31 'plugin3',
31 'plugin4', 32 'plugin4',
32 'plugin2', 33 'plugin2',
33 ); 34 ];
35
36 mkdir($path = __DIR__ . '/folder');
37 PluginManager::$PLUGINS_PATH = $path;
38 array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, $expected);
34 39
35 $out = save_plugin_config($data); 40 $out = save_plugin_config($data);
36 $this->assertEquals($expected, $out); 41 $this->assertEquals($expected, $out);
42
43 array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, $expected);
44 rmdir($path);
37 } 45 }
38 46
39 /** 47 /**
diff --git a/tests/container/ContainerBuilderTest.php b/tests/container/ContainerBuilderTest.php
index 9b97ed6d..fa77bf31 100644
--- a/tests/container/ContainerBuilderTest.php
+++ b/tests/container/ContainerBuilderTest.php
@@ -7,10 +7,19 @@ namespace Shaarli\Container;
7use PHPUnit\Framework\TestCase; 7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\BookmarkServiceInterface; 8use Shaarli\Bookmark\BookmarkServiceInterface;
9use Shaarli\Config\ConfigManager; 9use Shaarli\Config\ConfigManager;
10use Shaarli\Feed\FeedBuilder;
11use Shaarli\Formatter\FormatterFactory;
10use Shaarli\History; 12use Shaarli\History;
13use Shaarli\Http\HttpAccess;
14use Shaarli\Netscape\NetscapeBookmarkUtils;
15use Shaarli\Plugin\PluginManager;
11use Shaarli\Render\PageBuilder; 16use Shaarli\Render\PageBuilder;
17use Shaarli\Render\PageCacheManager;
18use Shaarli\Security\CookieManager;
12use Shaarli\Security\LoginManager; 19use Shaarli\Security\LoginManager;
13use Shaarli\Security\SessionManager; 20use Shaarli\Security\SessionManager;
21use Shaarli\Thumbnailer;
22use Shaarli\Updater\Updater;
14 23
15class ContainerBuilderTest extends TestCase 24class ContainerBuilderTest extends TestCase
16{ 25{
@@ -26,13 +35,24 @@ class ContainerBuilderTest extends TestCase
26 /** @var ContainerBuilder */ 35 /** @var ContainerBuilder */
27 protected $containerBuilder; 36 protected $containerBuilder;
28 37
38 /** @var CookieManager */
39 protected $cookieManager;
40
29 public function setUp(): void 41 public function setUp(): void
30 { 42 {
31 $this->conf = new ConfigManager('tests/utils/config/configJson'); 43 $this->conf = new ConfigManager('tests/utils/config/configJson');
32 $this->sessionManager = $this->createMock(SessionManager::class); 44 $this->sessionManager = $this->createMock(SessionManager::class);
45 $this->cookieManager = $this->createMock(CookieManager::class);
46
33 $this->loginManager = $this->createMock(LoginManager::class); 47 $this->loginManager = $this->createMock(LoginManager::class);
48 $this->loginManager->method('isLoggedIn')->willReturn(true);
34 49
35 $this->containerBuilder = new ContainerBuilder($this->conf, $this->sessionManager, $this->loginManager); 50 $this->containerBuilder = new ContainerBuilder(
51 $this->conf,
52 $this->sessionManager,
53 $this->cookieManager,
54 $this->loginManager
55 );
36 } 56 }
37 57
38 public function testBuildContainer(): void 58 public function testBuildContainer(): void
@@ -41,9 +61,21 @@ class ContainerBuilderTest extends TestCase
41 61
42 static::assertInstanceOf(ConfigManager::class, $container->conf); 62 static::assertInstanceOf(ConfigManager::class, $container->conf);
43 static::assertInstanceOf(SessionManager::class, $container->sessionManager); 63 static::assertInstanceOf(SessionManager::class, $container->sessionManager);
64 static::assertInstanceOf(CookieManager::class, $container->cookieManager);
44 static::assertInstanceOf(LoginManager::class, $container->loginManager); 65 static::assertInstanceOf(LoginManager::class, $container->loginManager);
45 static::assertInstanceOf(History::class, $container->history); 66 static::assertInstanceOf(History::class, $container->history);
46 static::assertInstanceOf(BookmarkServiceInterface::class, $container->bookmarkService); 67 static::assertInstanceOf(BookmarkServiceInterface::class, $container->bookmarkService);
47 static::assertInstanceOf(PageBuilder::class, $container->pageBuilder); 68 static::assertInstanceOf(PageBuilder::class, $container->pageBuilder);
69 static::assertInstanceOf(PluginManager::class, $container->pluginManager);
70 static::assertInstanceOf(FormatterFactory::class, $container->formatterFactory);
71 static::assertInstanceOf(PageCacheManager::class, $container->pageCacheManager);
72 static::assertInstanceOf(FeedBuilder::class, $container->feedBuilder);
73 static::assertInstanceOf(Thumbnailer::class, $container->thumbnailer);
74 static::assertInstanceOf(HttpAccess::class, $container->httpAccess);
75 static::assertInstanceOf(NetscapeBookmarkUtils::class, $container->netscapeBookmarkUtils);
76 static::assertInstanceOf(Updater::class, $container->updater);
77
78 // Set by the middleware
79 static::assertNull($container->basePath);
48 } 80 }
49} 81}
diff --git a/tests/container/ShaarliTestContainer.php b/tests/container/ShaarliTestContainer.php
new file mode 100644
index 00000000..7dbe914c
--- /dev/null
+++ b/tests/container/ShaarliTestContainer.php
@@ -0,0 +1,42 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Container;
6
7use PHPUnit\Framework\MockObject\MockObject;
8use Shaarli\Bookmark\BookmarkServiceInterface;
9use Shaarli\Config\ConfigManager;
10use Shaarli\Feed\FeedBuilder;
11use Shaarli\Formatter\FormatterFactory;
12use Shaarli\History;
13use Shaarli\Http\HttpAccess;
14use Shaarli\Plugin\PluginManager;
15use Shaarli\Render\PageBuilder;
16use Shaarli\Render\PageCacheManager;
17use Shaarli\Security\LoginManager;
18use Shaarli\Security\SessionManager;
19use Shaarli\Thumbnailer;
20
21/**
22 * Test helper allowing auto-completion for MockObjects.
23 *
24 * @property mixed[] $environment $_SERVER automatically injected by Slim
25 * @property MockObject|ConfigManager $conf
26 * @property MockObject|SessionManager $sessionManager
27 * @property MockObject|LoginManager $loginManager
28 * @property MockObject|string $webPath
29 * @property MockObject|History $history
30 * @property MockObject|BookmarkServiceInterface $bookmarkService
31 * @property MockObject|PageBuilder $pageBuilder
32 * @property MockObject|PluginManager $pluginManager
33 * @property MockObject|FormatterFactory $formatterFactory
34 * @property MockObject|PageCacheManager $pageCacheManager
35 * @property MockObject|FeedBuilder $feedBuilder
36 * @property MockObject|Thumbnailer $thumbnailer
37 * @property MockObject|HttpAccess $httpAccess
38 */
39class ShaarliTestContainer extends ShaarliContainer
40{
41
42}
diff --git a/tests/feed/CachedPageTest.php b/tests/feed/CachedPageTest.php
index 363028a2..2e716432 100644
--- a/tests/feed/CachedPageTest.php
+++ b/tests/feed/CachedPageTest.php
@@ -11,7 +11,7 @@ class CachedPageTest extends \PHPUnit\Framework\TestCase
11{ 11{
12 // test cache directory 12 // test cache directory
13 protected static $testCacheDir = 'sandbox/pagecache'; 13 protected static $testCacheDir = 'sandbox/pagecache';
14 protected static $url = 'http://shaar.li/?do=atom'; 14 protected static $url = 'http://shaar.li/feed/atom';
15 protected static $filename; 15 protected static $filename;
16 16
17 /** 17 /**
@@ -42,8 +42,8 @@ class CachedPageTest extends \PHPUnit\Framework\TestCase
42 { 42 {
43 new CachedPage(self::$testCacheDir, '', true); 43 new CachedPage(self::$testCacheDir, '', true);
44 new CachedPage(self::$testCacheDir, '', false); 44 new CachedPage(self::$testCacheDir, '', false);
45 new CachedPage(self::$testCacheDir, 'http://shaar.li/?do=rss', true); 45 new CachedPage(self::$testCacheDir, 'http://shaar.li/feed/rss', true);
46 new CachedPage(self::$testCacheDir, 'http://shaar.li/?do=atom', false); 46 new CachedPage(self::$testCacheDir, 'http://shaar.li/feed/atom', false);
47 $this->addToAssertionCount(1); 47 $this->addToAssertionCount(1);
48 } 48 }
49 49
diff --git a/tests/feed/FeedBuilderTest.php b/tests/feed/FeedBuilderTest.php
index 54671891..5c2aaedb 100644
--- a/tests/feed/FeedBuilderTest.php
+++ b/tests/feed/FeedBuilderTest.php
@@ -65,23 +65,6 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
65 } 65 }
66 66
67 /** 67 /**
68 * Test GetTypeLanguage().
69 */
70 public function testGetTypeLanguage()
71 {
72 $feedBuilder = new FeedBuilder(null, self::$formatter, FeedBuilder::$FEED_ATOM, null, null, false);
73 $feedBuilder->setLocale(self::$LOCALE);
74 $this->assertEquals(self::$ATOM_LANGUAGUE, $feedBuilder->getTypeLanguage());
75 $feedBuilder = new FeedBuilder(null, self::$formatter, FeedBuilder::$FEED_RSS, null, null, false);
76 $feedBuilder->setLocale(self::$LOCALE);
77 $this->assertEquals(self::$RSS_LANGUAGE, $feedBuilder->getTypeLanguage());
78 $feedBuilder = new FeedBuilder(null, self::$formatter, FeedBuilder::$FEED_ATOM, null, null, false);
79 $this->assertEquals('en', $feedBuilder->getTypeLanguage());
80 $feedBuilder = new FeedBuilder(null, self::$formatter, FeedBuilder::$FEED_RSS, null, null, false);
81 $this->assertEquals('en-en', $feedBuilder->getTypeLanguage());
82 }
83
84 /**
85 * Test buildData with RSS feed. 68 * Test buildData with RSS feed.
86 */ 69 */
87 public function testRSSBuildData() 70 public function testRSSBuildData()
@@ -89,13 +72,11 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
89 $feedBuilder = new FeedBuilder( 72 $feedBuilder = new FeedBuilder(
90 self::$bookmarkService, 73 self::$bookmarkService,
91 self::$formatter, 74 self::$formatter,
92 FeedBuilder::$FEED_RSS, 75 static::$serverInfo,
93 self::$serverInfo,
94 null,
95 false 76 false
96 ); 77 );
97 $feedBuilder->setLocale(self::$LOCALE); 78 $feedBuilder->setLocale(self::$LOCALE);
98 $data = $feedBuilder->buildData(); 79 $data = $feedBuilder->buildData(FeedBuilder::$FEED_RSS, null);
99 // Test headers (RSS) 80 // Test headers (RSS)
100 $this->assertEquals(self::$RSS_LANGUAGE, $data['language']); 81 $this->assertEquals(self::$RSS_LANGUAGE, $data['language']);
101 $this->assertRegExp('/Wed, 03 Aug 2016 09:30:33 \+\d{4}/', $data['last_update']); 82 $this->assertRegExp('/Wed, 03 Aug 2016 09:30:33 \+\d{4}/', $data['last_update']);
@@ -109,15 +90,15 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
109 $link = $data['links'][array_keys($data['links'])[2]]; 90 $link = $data['links'][array_keys($data['links'])[2]];
110 $this->assertEquals(41, $link['id']); 91 $this->assertEquals(41, $link['id']);
111 $this->assertEquals(DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); 92 $this->assertEquals(DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
112 $this->assertEquals('http://host.tld/?WDWyig', $link['guid']); 93 $this->assertEquals('http://host.tld/shaare/WDWyig', $link['guid']);
113 $this->assertEquals('http://host.tld/?WDWyig', $link['url']); 94 $this->assertEquals('http://host.tld/shaare/WDWyig', $link['url']);
114 $this->assertRegExp('/Tue, 10 Mar 2015 11:46:51 \+\d{4}/', $link['pub_iso_date']); 95 $this->assertRegExp('/Tue, 10 Mar 2015 11:46:51 \+\d{4}/', $link['pub_iso_date']);
115 $pub = DateTime::createFromFormat(DateTime::RSS, $link['pub_iso_date']); 96 $pub = DateTime::createFromFormat(DateTime::RSS, $link['pub_iso_date']);
116 $up = DateTime::createFromFormat(DateTime::ATOM, $link['up_iso_date']); 97 $up = DateTime::createFromFormat(DateTime::ATOM, $link['up_iso_date']);
117 $this->assertEquals($pub, $up); 98 $this->assertEquals($pub, $up);
118 $this->assertContains('Stallman has a beard', $link['description']); 99 $this->assertContains('Stallman has a beard', $link['description']);
119 $this->assertContains('Permalink', $link['description']); 100 $this->assertContains('Permalink', $link['description']);
120 $this->assertContains('http://host.tld/?WDWyig', $link['description']); 101 $this->assertContains('http://host.tld/shaare/WDWyig', $link['description']);
121 $this->assertEquals(1, count($link['taglist'])); 102 $this->assertEquals(1, count($link['taglist']));
122 $this->assertEquals('sTuff', $link['taglist'][0]); 103 $this->assertEquals('sTuff', $link['taglist'][0]);
123 104
@@ -140,13 +121,11 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
140 $feedBuilder = new FeedBuilder( 121 $feedBuilder = new FeedBuilder(
141 self::$bookmarkService, 122 self::$bookmarkService,
142 self::$formatter, 123 self::$formatter,
143 FeedBuilder::$FEED_ATOM, 124 static::$serverInfo,
144 self::$serverInfo,
145 null,
146 false 125 false
147 ); 126 );
148 $feedBuilder->setLocale(self::$LOCALE); 127 $feedBuilder->setLocale(self::$LOCALE);
149 $data = $feedBuilder->buildData(); 128 $data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
150 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); 129 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
151 $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['last_update']); 130 $this->assertRegExp('/2016-08-03T09:30:33\+\d{2}:\d{2}/', $data['last_update']);
152 $link = $data['links'][array_keys($data['links'])[2]]; 131 $link = $data['links'][array_keys($data['links'])[2]];
@@ -166,13 +145,11 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
166 $feedBuilder = new FeedBuilder( 145 $feedBuilder = new FeedBuilder(
167 self::$bookmarkService, 146 self::$bookmarkService,
168 self::$formatter, 147 self::$formatter,
169 FeedBuilder::$FEED_ATOM, 148 static::$serverInfo,
170 self::$serverInfo,
171 $criteria,
172 false 149 false
173 ); 150 );
174 $feedBuilder->setLocale(self::$LOCALE); 151 $feedBuilder->setLocale(self::$LOCALE);
175 $data = $feedBuilder->buildData(); 152 $data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, $criteria);
176 $this->assertEquals(1, count($data['links'])); 153 $this->assertEquals(1, count($data['links']));
177 $link = array_shift($data['links']); 154 $link = array_shift($data['links']);
178 $this->assertEquals(41, $link['id']); 155 $this->assertEquals(41, $link['id']);
@@ -190,13 +167,11 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
190 $feedBuilder = new FeedBuilder( 167 $feedBuilder = new FeedBuilder(
191 self::$bookmarkService, 168 self::$bookmarkService,
192 self::$formatter, 169 self::$formatter,
193 FeedBuilder::$FEED_ATOM, 170 static::$serverInfo,
194 self::$serverInfo,
195 $criteria,
196 false 171 false
197 ); 172 );
198 $feedBuilder->setLocale(self::$LOCALE); 173 $feedBuilder->setLocale(self::$LOCALE);
199 $data = $feedBuilder->buildData(); 174 $data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, $criteria);
200 $this->assertEquals(3, count($data['links'])); 175 $this->assertEquals(3, count($data['links']));
201 $link = $data['links'][array_keys($data['links'])[2]]; 176 $link = $data['links'][array_keys($data['links'])[2]];
202 $this->assertEquals(41, $link['id']); 177 $this->assertEquals(41, $link['id']);
@@ -211,29 +186,27 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
211 $feedBuilder = new FeedBuilder( 186 $feedBuilder = new FeedBuilder(
212 self::$bookmarkService, 187 self::$bookmarkService,
213 self::$formatter, 188 self::$formatter,
214 FeedBuilder::$FEED_ATOM, 189 static::$serverInfo,
215 self::$serverInfo,
216 null,
217 false 190 false
218 ); 191 );
219 $feedBuilder->setLocale(self::$LOCALE); 192 $feedBuilder->setLocale(self::$LOCALE);
220 $feedBuilder->setUsePermalinks(true); 193 $feedBuilder->setUsePermalinks(true);
221 $data = $feedBuilder->buildData(); 194 $data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
222 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); 195 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
223 $this->assertTrue($data['usepermalinks']); 196 $this->assertTrue($data['usepermalinks']);
224 // First link is a permalink 197 // First link is a permalink
225 $link = $data['links'][array_keys($data['links'])[2]]; 198 $link = $data['links'][array_keys($data['links'])[2]];
226 $this->assertEquals(41, $link['id']); 199 $this->assertEquals(41, $link['id']);
227 $this->assertEquals(DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20150310_114651'), $link['created']); 200 $this->assertEquals(DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20150310_114651'), $link['created']);
228 $this->assertEquals('http://host.tld/?WDWyig', $link['guid']); 201 $this->assertEquals('http://host.tld/shaare/WDWyig', $link['guid']);
229 $this->assertEquals('http://host.tld/?WDWyig', $link['url']); 202 $this->assertEquals('http://host.tld/shaare/WDWyig', $link['url']);
230 $this->assertContains('Direct link', $link['description']); 203 $this->assertContains('Direct link', $link['description']);
231 $this->assertContains('http://host.tld/?WDWyig', $link['description']); 204 $this->assertContains('http://host.tld/shaare/WDWyig', $link['description']);
232 // Second link is a direct link 205 // Second link is a direct link
233 $link = $data['links'][array_keys($data['links'])[3]]; 206 $link = $data['links'][array_keys($data['links'])[3]];
234 $this->assertEquals(8, $link['id']); 207 $this->assertEquals(8, $link['id']);
235 $this->assertEquals(DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20150310_114633'), $link['created']); 208 $this->assertEquals(DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20150310_114633'), $link['created']);
236 $this->assertEquals('http://host.tld/?RttfEw', $link['guid']); 209 $this->assertEquals('http://host.tld/shaare/RttfEw', $link['guid']);
237 $this->assertEquals('https://static.fsf.org/nosvn/faif-2.0.pdf', $link['url']); 210 $this->assertEquals('https://static.fsf.org/nosvn/faif-2.0.pdf', $link['url']);
238 $this->assertContains('Direct link', $link['description']); 211 $this->assertContains('Direct link', $link['description']);
239 $this->assertContains('https://static.fsf.org/nosvn/faif-2.0.pdf', $link['description']); 212 $this->assertContains('https://static.fsf.org/nosvn/faif-2.0.pdf', $link['description']);
@@ -247,14 +220,12 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
247 $feedBuilder = new FeedBuilder( 220 $feedBuilder = new FeedBuilder(
248 self::$bookmarkService, 221 self::$bookmarkService,
249 self::$formatter, 222 self::$formatter,
250 FeedBuilder::$FEED_ATOM, 223 static::$serverInfo,
251 self::$serverInfo,
252 null,
253 false 224 false
254 ); 225 );
255 $feedBuilder->setLocale(self::$LOCALE); 226 $feedBuilder->setLocale(self::$LOCALE);
256 $feedBuilder->setHideDates(true); 227 $feedBuilder->setHideDates(true);
257 $data = $feedBuilder->buildData(); 228 $data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
258 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); 229 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
259 $this->assertFalse($data['show_dates']); 230 $this->assertFalse($data['show_dates']);
260 231
@@ -262,14 +233,12 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
262 $feedBuilder = new FeedBuilder( 233 $feedBuilder = new FeedBuilder(
263 self::$bookmarkService, 234 self::$bookmarkService,
264 self::$formatter, 235 self::$formatter,
265 FeedBuilder::$FEED_ATOM, 236 static::$serverInfo,
266 self::$serverInfo,
267 null,
268 true 237 true
269 ); 238 );
270 $feedBuilder->setLocale(self::$LOCALE); 239 $feedBuilder->setLocale(self::$LOCALE);
271 $feedBuilder->setHideDates(true); 240 $feedBuilder->setHideDates(true);
272 $data = $feedBuilder->buildData(); 241 $data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
273 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links'])); 242 $this->assertEquals(ReferenceLinkDB::$NB_LINKS_TOTAL, count($data['links']));
274 $this->assertTrue($data['show_dates']); 243 $this->assertTrue($data['show_dates']);
275 } 244 }
@@ -289,13 +258,11 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
289 $feedBuilder = new FeedBuilder( 258 $feedBuilder = new FeedBuilder(
290 self::$bookmarkService, 259 self::$bookmarkService,
291 self::$formatter, 260 self::$formatter,
292 FeedBuilder::$FEED_ATOM,
293 $serverInfo, 261 $serverInfo,
294 null,
295 false 262 false
296 ); 263 );
297 $feedBuilder->setLocale(self::$LOCALE); 264 $feedBuilder->setLocale(self::$LOCALE);
298 $data = $feedBuilder->buildData(); 265 $data = $feedBuilder->buildData(FeedBuilder::$FEED_ATOM, null);
299 266
300 $this->assertEquals( 267 $this->assertEquals(
301 'http://host.tld:8080/~user/shaarli/index.php?do=feed', 268 'http://host.tld:8080/~user/shaarli/index.php?do=feed',
@@ -304,8 +271,8 @@ class FeedBuilderTest extends \PHPUnit\Framework\TestCase
304 271
305 // Test first link (note link) 272 // Test first link (note link)
306 $link = $data['links'][array_keys($data['links'])[2]]; 273 $link = $data['links'][array_keys($data['links'])[2]];
307 $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['guid']); 274 $this->assertEquals('http://host.tld:8080/~user/shaarli/shaare/WDWyig', $link['guid']);
308 $this->assertEquals('http://host.tld:8080/~user/shaarli/?WDWyig', $link['url']); 275 $this->assertEquals('http://host.tld:8080/~user/shaarli/shaare/WDWyig', $link['url']);
309 $this->assertContains('http://host.tld:8080/~user/shaarli/?addtag=hashtag', $link['description']); 276 $this->assertContains('http://host.tld:8080/~user/shaarli/./add-tag/hashtag', $link['description']);
310 } 277 }
311} 278}
diff --git a/tests/formatter/BookmarkDefaultFormatterTest.php b/tests/formatter/BookmarkDefaultFormatterTest.php
index 382a560e..cf48b00b 100644
--- a/tests/formatter/BookmarkDefaultFormatterTest.php
+++ b/tests/formatter/BookmarkDefaultFormatterTest.php
@@ -123,7 +123,7 @@ class BookmarkDefaultFormatterTest extends TestCase
123 $description[0] = 'This a &lt;strong&gt;description&lt;/strong&gt;<br />'; 123 $description[0] = 'This a &lt;strong&gt;description&lt;/strong&gt;<br />';
124 $url = 'https://sub.domain.tld?query=here&amp;for=real#hash'; 124 $url = 'https://sub.domain.tld?query=here&amp;for=real#hash';
125 $description[1] = 'text <a href="'. $url .'">'. $url .'</a> more text<br />'; 125 $description[1] = 'text <a href="'. $url .'">'. $url .'</a> more text<br />';
126 $description[2] = 'Also, there is an <a href="?addtag=hashtag" '. 126 $description[2] = 'Also, there is an <a href="./add-tag/hashtag" '.
127 'title="Hashtag hashtag">#hashtag</a> added<br />'; 127 'title="Hashtag hashtag">#hashtag</a> added<br />';
128 $description[3] = '&nbsp; &nbsp; A &nbsp;N &nbsp;D KEEP &nbsp; &nbsp; '. 128 $description[3] = '&nbsp; &nbsp; A &nbsp;N &nbsp;D KEEP &nbsp; &nbsp; '.
129 'SPACES &nbsp; &nbsp;! &nbsp; <br />'; 129 'SPACES &nbsp; &nbsp;! &nbsp; <br />';
@@ -148,7 +148,7 @@ class BookmarkDefaultFormatterTest extends TestCase
148 $this->assertEquals($root . $short, $link['url']); 148 $this->assertEquals($root . $short, $link['url']);
149 $this->assertEquals($root . $short, $link['real_url']); 149 $this->assertEquals($root . $short, $link['real_url']);
150 $this->assertEquals( 150 $this->assertEquals(
151 'Text <a href="'. $root .'?addtag=hashtag" title="Hashtag hashtag">'. 151 'Text <a href="'. $root .'./add-tag/hashtag" title="Hashtag hashtag">'.
152 '#hashtag</a> more text', 152 '#hashtag</a> more text',
153 $link['description'] 153 $link['description']
154 ); 154 );
diff --git a/tests/formatter/BookmarkMarkdownFormatterTest.php b/tests/formatter/BookmarkMarkdownFormatterTest.php
index f1f12c04..3e72d1ee 100644
--- a/tests/formatter/BookmarkMarkdownFormatterTest.php
+++ b/tests/formatter/BookmarkMarkdownFormatterTest.php
@@ -125,7 +125,7 @@ class BookmarkMarkdownFormatterTest extends TestCase
125 $description .= 'This a &lt;strong&gt;description&lt;/strong&gt;<br />'. PHP_EOL; 125 $description .= 'This a &lt;strong&gt;description&lt;/strong&gt;<br />'. PHP_EOL;
126 $url = 'https://sub.domain.tld?query=here&amp;for=real#hash'; 126 $url = 'https://sub.domain.tld?query=here&amp;for=real#hash';
127 $description .= 'text <a href="'. $url .'">'. $url .'</a> more text<br />'. PHP_EOL; 127 $description .= 'text <a href="'. $url .'">'. $url .'</a> more text<br />'. PHP_EOL;
128 $description .= 'Also, there is an <a href="?addtag=hashtag">#hashtag</a> added<br />'. PHP_EOL; 128 $description .= 'Also, there is an <a href="./add-tag/hashtag">#hashtag</a> added<br />'. PHP_EOL;
129 $description .= 'A N D KEEP SPACES ! '; 129 $description .= 'A N D KEEP SPACES ! ';
130 $description .= '</p></div>'; 130 $description .= '</p></div>';
131 131
@@ -146,7 +146,7 @@ class BookmarkMarkdownFormatterTest extends TestCase
146 $this->formatter->addContextData('index_url', $root = 'https://domain.tld/hithere/'); 146 $this->formatter->addContextData('index_url', $root = 'https://domain.tld/hithere/');
147 147
148 $description = '<div class="markdown"><p>'; 148 $description = '<div class="markdown"><p>';
149 $description .= 'Text <a href="'. $root .'?addtag=hashtag">#hashtag</a> more text'; 149 $description .= 'Text <a href="'. $root .'./add-tag/hashtag">#hashtag</a> more text';
150 $description .= '</p></div>'; 150 $description .= '</p></div>';
151 151
152 $link = $this->formatter->format($bookmark); 152 $link = $this->formatter->format($bookmark);
diff --git a/tests/front/ShaarliAdminMiddlewareTest.php b/tests/front/ShaarliAdminMiddlewareTest.php
new file mode 100644
index 00000000..7451330b
--- /dev/null
+++ b/tests/front/ShaarliAdminMiddlewareTest.php
@@ -0,0 +1,100 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Config\ConfigManager;
9use Shaarli\Container\ShaarliContainer;
10use Shaarli\Security\LoginManager;
11use Shaarli\Updater\Updater;
12use Slim\Http\Request;
13use Slim\Http\Response;
14use Slim\Http\Uri;
15
16class ShaarliAdminMiddlewareTest extends TestCase
17{
18 protected const TMP_MOCK_FILE = '.tmp';
19
20 /** @var ShaarliContainer */
21 protected $container;
22
23 /** @var ShaarliMiddleware */
24 protected $middleware;
25
26 public function setUp(): void
27 {
28 $this->container = $this->createMock(ShaarliContainer::class);
29
30 touch(static::TMP_MOCK_FILE);
31
32 $this->container->conf = $this->createMock(ConfigManager::class);
33 $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE);
34
35 $this->container->loginManager = $this->createMock(LoginManager::class);
36 $this->container->updater = $this->createMock(Updater::class);
37
38 $this->container->environment = ['REQUEST_URI' => 'http://shaarli/subfolder/path'];
39
40 $this->middleware = new ShaarliAdminMiddleware($this->container);
41 }
42
43 public function tearDown(): void
44 {
45 unlink(static::TMP_MOCK_FILE);
46 }
47
48 /**
49 * Try to access an admin controller while logged out -> redirected to login page.
50 */
51 public function testMiddlewareWhileLoggedOut(): void
52 {
53 $this->container->loginManager->expects(static::once())->method('isLoggedIn')->willReturn(false);
54
55 $request = $this->createMock(Request::class);
56 $request->method('getUri')->willReturnCallback(function (): Uri {
57 $uri = $this->createMock(Uri::class);
58 $uri->method('getBasePath')->willReturn('/subfolder');
59
60 return $uri;
61 });
62
63 $response = new Response();
64
65 /** @var Response $result */
66 $result = $this->middleware->__invoke($request, $response, function () {});
67
68 static::assertSame(302, $result->getStatusCode());
69 static::assertSame(
70 '/subfolder/login?returnurl=' . urlencode('http://shaarli/subfolder/path'),
71 $result->getHeader('location')[0]
72 );
73 }
74
75 /**
76 * Process controller while logged in.
77 */
78 public function testMiddlewareWhileLoggedIn(): void
79 {
80 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
81
82 $request = $this->createMock(Request::class);
83 $request->method('getUri')->willReturnCallback(function (): Uri {
84 $uri = $this->createMock(Uri::class);
85 $uri->method('getBasePath')->willReturn('/subfolder');
86
87 return $uri;
88 });
89
90 $response = new Response();
91 $controller = function (Request $request, Response $response): Response {
92 return $response->withStatus(418); // I'm a tea pot
93 };
94
95 /** @var Response $result */
96 $result = $this->middleware->__invoke($request, $response, $controller);
97
98 static::assertSame(418, $result->getStatusCode());
99 }
100}
diff --git a/tests/front/ShaarliMiddlewareTest.php b/tests/front/ShaarliMiddlewareTest.php
index 80974f37..05aa34a9 100644
--- a/tests/front/ShaarliMiddlewareTest.php
+++ b/tests/front/ShaarliMiddlewareTest.php
@@ -8,12 +8,19 @@ use PHPUnit\Framework\TestCase;
8use Shaarli\Config\ConfigManager; 8use Shaarli\Config\ConfigManager;
9use Shaarli\Container\ShaarliContainer; 9use Shaarli\Container\ShaarliContainer;
10use Shaarli\Front\Exception\LoginBannedException; 10use Shaarli\Front\Exception\LoginBannedException;
11use Shaarli\Front\Exception\UnauthorizedException;
11use Shaarli\Render\PageBuilder; 12use Shaarli\Render\PageBuilder;
13use Shaarli\Render\PageCacheManager;
14use Shaarli\Security\LoginManager;
15use Shaarli\Updater\Updater;
12use Slim\Http\Request; 16use Slim\Http\Request;
13use Slim\Http\Response; 17use Slim\Http\Response;
18use Slim\Http\Uri;
14 19
15class ShaarliMiddlewareTest extends TestCase 20class ShaarliMiddlewareTest extends TestCase
16{ 21{
22 protected const TMP_MOCK_FILE = '.tmp';
23
17 /** @var ShaarliContainer */ 24 /** @var ShaarliContainer */
18 protected $container; 25 protected $container;
19 26
@@ -23,12 +30,37 @@ class ShaarliMiddlewareTest extends TestCase
23 public function setUp(): void 30 public function setUp(): void
24 { 31 {
25 $this->container = $this->createMock(ShaarliContainer::class); 32 $this->container = $this->createMock(ShaarliContainer::class);
33
34 touch(static::TMP_MOCK_FILE);
35
36 $this->container->conf = $this->createMock(ConfigManager::class);
37 $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE);
38
39 $this->container->loginManager = $this->createMock(LoginManager::class);
40
41 $this->container->environment = ['REQUEST_URI' => 'http://shaarli/subfolder/path'];
42
26 $this->middleware = new ShaarliMiddleware($this->container); 43 $this->middleware = new ShaarliMiddleware($this->container);
27 } 44 }
28 45
46 public function tearDown(): void
47 {
48 unlink(static::TMP_MOCK_FILE);
49 }
50
51 /**
52 * Test middleware execution with valid controller call
53 */
29 public function testMiddlewareExecution(): void 54 public function testMiddlewareExecution(): void
30 { 55 {
31 $request = $this->createMock(Request::class); 56 $request = $this->createMock(Request::class);
57 $request->method('getUri')->willReturnCallback(function (): Uri {
58 $uri = $this->createMock(Uri::class);
59 $uri->method('getBasePath')->willReturn('/subfolder');
60
61 return $uri;
62 });
63
32 $response = new Response(); 64 $response = new Response();
33 $controller = function (Request $request, Response $response): Response { 65 $controller = function (Request $request, Response $response): Response {
34 return $response->withStatus(418); // I'm a tea pot 66 return $response->withStatus(418); // I'm a tea pot
@@ -41,9 +73,20 @@ class ShaarliMiddlewareTest extends TestCase
41 static::assertSame(418, $result->getStatusCode()); 73 static::assertSame(418, $result->getStatusCode());
42 } 74 }
43 75
44 public function testMiddlewareExecutionWithException(): void 76 /**
77 * Test middleware execution with controller throwing a known front exception.
78 * The exception should be thrown to be later handled by the error handler.
79 */
80 public function testMiddlewareExecutionWithFrontException(): void
45 { 81 {
46 $request = $this->createMock(Request::class); 82 $request = $this->createMock(Request::class);
83 $request->method('getUri')->willReturnCallback(function (): Uri {
84 $uri = $this->createMock(Uri::class);
85 $uri->method('getBasePath')->willReturn('/subfolder');
86
87 return $uri;
88 });
89
47 $response = new Response(); 90 $response = new Response();
48 $controller = function (): void { 91 $controller = function (): void {
49 $exception = new LoginBannedException(); 92 $exception = new LoginBannedException();
@@ -57,14 +100,122 @@ class ShaarliMiddlewareTest extends TestCase
57 }); 100 });
58 $this->container->pageBuilder = $pageBuilder; 101 $this->container->pageBuilder = $pageBuilder;
59 102
60 $conf = $this->createMock(ConfigManager::class); 103 $this->expectException(LoginBannedException::class);
61 $this->container->conf = $conf; 104
105 $this->middleware->__invoke($request, $response, $controller);
106 }
107
108 /**
109 * Test middleware execution with controller throwing a not authorized exception
110 * The middle should send a redirection response to the login page.
111 */
112 public function testMiddlewareExecutionWithUnauthorizedException(): void
113 {
114 $request = $this->createMock(Request::class);
115 $request->method('getUri')->willReturnCallback(function (): Uri {
116 $uri = $this->createMock(Uri::class);
117 $uri->method('getBasePath')->willReturn('/subfolder');
118
119 return $uri;
120 });
121
122 $response = new Response();
123 $controller = function (): void {
124 throw new UnauthorizedException();
125 };
126
127 /** @var Response $result */
128 $result = $this->middleware->__invoke($request, $response, $controller);
129
130 static::assertSame(302, $result->getStatusCode());
131 static::assertSame(
132 '/subfolder/login?returnurl=' . urlencode('http://shaarli/subfolder/path'),
133 $result->getHeader('location')[0]
134 );
135 }
136
137 /**
138 * Test middleware execution with controller throwing a not authorized exception.
139 * The exception should be thrown to be later handled by the error handler.
140 */
141 public function testMiddlewareExecutionWithServerException(): void
142 {
143 $request = $this->createMock(Request::class);
144 $request->method('getUri')->willReturnCallback(function (): Uri {
145 $uri = $this->createMock(Uri::class);
146 $uri->method('getBasePath')->willReturn('/subfolder');
147
148 return $uri;
149 });
150
151 $dummyException = new class() extends \Exception {};
152
153 $response = new Response();
154 $controller = function () use ($dummyException): void {
155 throw $dummyException;
156 };
157
158 $parameters = [];
159 $this->container->pageBuilder = $this->createMock(PageBuilder::class);
160 $this->container->pageBuilder->method('render')->willReturnCallback(function (string $message): string {
161 return $message;
162 });
163 $this->container->pageBuilder
164 ->method('assign')
165 ->willReturnCallback(function (string $key, string $value) use (&$parameters): void {
166 $parameters[$key] = $value;
167 })
168 ;
169
170 $this->expectException(get_class($dummyException));
171
172 $this->middleware->__invoke($request, $response, $controller);
173 }
174
175 public function testMiddlewareExecutionWithUpdates(): void
176 {
177 $request = $this->createMock(Request::class);
178 $request->method('getUri')->willReturnCallback(function (): Uri {
179 $uri = $this->createMock(Uri::class);
180 $uri->method('getBasePath')->willReturn('/subfolder');
181
182 return $uri;
183 });
184
185 $response = new Response();
186 $controller = function (Request $request, Response $response): Response {
187 return $response->withStatus(418); // I'm a tea pot
188 };
189
190 $this->container->loginManager = $this->createMock(LoginManager::class);
191 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
192
193 $this->container->conf = $this->createMock(ConfigManager::class);
194 $this->container->conf->method('get')->willReturnCallback(function (string $key): string {
195 return $key;
196 });
197 $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE);
198
199 $this->container->pageCacheManager = $this->createMock(PageCacheManager::class);
200 $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches');
201
202 $this->container->updater = $this->createMock(Updater::class);
203 $this->container->updater
204 ->expects(static::once())
205 ->method('update')
206 ->willReturn(['update123'])
207 ;
208 $this->container->updater->method('getDoneUpdates')->willReturn($updates = ['update123', 'other']);
209 $this->container->updater
210 ->expects(static::once())
211 ->method('writeUpdates')
212 ->with('resource.updates', $updates)
213 ;
62 214
63 /** @var Response $result */ 215 /** @var Response $result */
64 $result = $this->middleware->__invoke($request, $response, $controller); 216 $result = $this->middleware->__invoke($request, $response, $controller);
65 217
66 static::assertInstanceOf(Response::class, $result); 218 static::assertInstanceOf(Response::class, $result);
67 static::assertSame(401, $result->getStatusCode()); 219 static::assertSame(418, $result->getStatusCode());
68 static::assertContains('error', (string) $result->getBody());
69 } 220 }
70} 221}
diff --git a/tests/front/controller/LoginControllerTest.php b/tests/front/controller/LoginControllerTest.php
deleted file mode 100644
index 8cf8ece7..00000000
--- a/tests/front/controller/LoginControllerTest.php
+++ /dev/null
@@ -1,178 +0,0 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\BookmarkServiceInterface;
9use Shaarli\Config\ConfigManager;
10use Shaarli\Container\ShaarliContainer;
11use Shaarli\Front\Exception\LoginBannedException;
12use Shaarli\Plugin\PluginManager;
13use Shaarli\Render\PageBuilder;
14use Shaarli\Security\LoginManager;
15use Slim\Http\Request;
16use Slim\Http\Response;
17
18class LoginControllerTest extends TestCase
19{
20 /** @var ShaarliContainer */
21 protected $container;
22
23 /** @var LoginController */
24 protected $controller;
25
26 public function setUp(): void
27 {
28 $this->container = $this->createMock(ShaarliContainer::class);
29 $this->controller = new LoginController($this->container);
30 }
31
32 public function testValidControllerInvoke(): void
33 {
34 $this->createValidContainerMockSet();
35
36 $request = $this->createMock(Request::class);
37 $request->expects(static::once())->method('getServerParam')->willReturn('> referer');
38 $response = new Response();
39
40 $assignedVariables = [];
41 $this->container->pageBuilder
42 ->method('assign')
43 ->willReturnCallback(function ($key, $value) use (&$assignedVariables) {
44 $assignedVariables[$key] = $value;
45
46 return $this;
47 })
48 ;
49
50 $result = $this->controller->index($request, $response);
51
52 static::assertInstanceOf(Response::class, $result);
53 static::assertSame(200, $result->getStatusCode());
54 static::assertSame('loginform', (string) $result->getBody());
55
56 static::assertSame('&gt; referer', $assignedVariables['returnurl']);
57 static::assertSame(true, $assignedVariables['remember_user_default']);
58 static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']);
59 }
60
61 public function testValidControllerInvokeWithUserName(): void
62 {
63 $this->createValidContainerMockSet();
64
65 $request = $this->createMock(Request::class);
66 $request->expects(static::once())->method('getServerParam')->willReturn('> referer');
67 $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>');
68 $response = new Response();
69
70 $assignedVariables = [];
71 $this->container->pageBuilder
72 ->method('assign')
73 ->willReturnCallback(function ($key, $value) use (&$assignedVariables) {
74 $assignedVariables[$key] = $value;
75
76 return $this;
77 })
78 ;
79
80 $result = $this->controller->index($request, $response);
81
82 static::assertInstanceOf(Response::class, $result);
83 static::assertSame(200, $result->getStatusCode());
84 static::assertSame('loginform', (string) $result->getBody());
85
86 static::assertSame('myUser&gt;', $assignedVariables['username']);
87 static::assertSame('&gt; referer', $assignedVariables['returnurl']);
88 static::assertSame(true, $assignedVariables['remember_user_default']);
89 static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']);
90 }
91
92 public function testLoginControllerWhileLoggedIn(): void
93 {
94 $request = $this->createMock(Request::class);
95 $response = new Response();
96
97 $loginManager = $this->createMock(LoginManager::class);
98 $loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true);
99 $this->container->loginManager = $loginManager;
100
101 $result = $this->controller->index($request, $response);
102
103 static::assertInstanceOf(Response::class, $result);
104 static::assertSame(302, $result->getStatusCode());
105 static::assertSame(['./'], $result->getHeader('Location'));
106 }
107
108 public function testLoginControllerOpenShaarli(): void
109 {
110 $this->createValidContainerMockSet();
111
112 $request = $this->createMock(Request::class);
113 $response = new Response();
114
115 $conf = $this->createMock(ConfigManager::class);
116 $conf->method('get')->willReturnCallback(function (string $parameter, $default) {
117 if ($parameter === 'security.open_shaarli') {
118 return true;
119 }
120 return $default;
121 });
122 $this->container->conf = $conf;
123
124 $result = $this->controller->index($request, $response);
125
126 static::assertInstanceOf(Response::class, $result);
127 static::assertSame(302, $result->getStatusCode());
128 static::assertSame(['./'], $result->getHeader('Location'));
129 }
130
131 public function testLoginControllerWhileBanned(): void
132 {
133 $this->createValidContainerMockSet();
134
135 $request = $this->createMock(Request::class);
136 $response = new Response();
137
138 $loginManager = $this->createMock(LoginManager::class);
139 $loginManager->method('isLoggedIn')->willReturn(false);
140 $loginManager->method('canLogin')->willReturn(false);
141 $this->container->loginManager = $loginManager;
142
143 $this->expectException(LoginBannedException::class);
144
145 $this->controller->index($request, $response);
146 }
147
148 protected function createValidContainerMockSet(): void
149 {
150 // User logged out
151 $loginManager = $this->createMock(LoginManager::class);
152 $loginManager->method('isLoggedIn')->willReturn(false);
153 $loginManager->method('canLogin')->willReturn(true);
154 $this->container->loginManager = $loginManager;
155
156 // Config
157 $conf = $this->createMock(ConfigManager::class);
158 $conf->method('get')->willReturnCallback(function (string $parameter, $default) {
159 return $default;
160 });
161 $this->container->conf = $conf;
162
163 // PageBuilder
164 $pageBuilder = $this->createMock(PageBuilder::class);
165 $pageBuilder
166 ->method('render')
167 ->willReturnCallback(function (string $template): string {
168 return $template;
169 })
170 ;
171 $this->container->pageBuilder = $pageBuilder;
172
173 $pluginManager = $this->createMock(PluginManager::class);
174 $this->container->pluginManager = $pluginManager;
175 $bookmarkService = $this->createMock(BookmarkServiceInterface::class);
176 $this->container->bookmarkService = $bookmarkService;
177 }
178}
diff --git a/tests/front/controller/ShaarliControllerTest.php b/tests/front/controller/ShaarliControllerTest.php
deleted file mode 100644
index 6fa3feb9..00000000
--- a/tests/front/controller/ShaarliControllerTest.php
+++ /dev/null
@@ -1,116 +0,0 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\BookmarkFilter;
9use Shaarli\Bookmark\BookmarkServiceInterface;
10use Shaarli\Container\ShaarliContainer;
11use Shaarli\Plugin\PluginManager;
12use Shaarli\Render\PageBuilder;
13use Shaarli\Security\LoginManager;
14
15/**
16 * Class ShaarliControllerTest
17 *
18 * This class is used to test default behavior of ShaarliController abstract class.
19 * It uses a dummy non abstract controller.
20 */
21class ShaarliControllerTest extends TestCase
22{
23 /** @var ShaarliContainer */
24 protected $container;
25
26 /** @var LoginController */
27 protected $controller;
28
29 /** @var mixed[] List of variable assigned to the template */
30 protected $assignedValues;
31
32 public function setUp(): void
33 {
34 $this->container = $this->createMock(ShaarliContainer::class);
35 $this->controller = new class($this->container) extends ShaarliController
36 {
37 public function assignView(string $key, $value): ShaarliController
38 {
39 return parent::assignView($key, $value);
40 }
41
42 public function render(string $template): string
43 {
44 return parent::render($template);
45 }
46 };
47 $this->assignedValues = [];
48 }
49
50 public function testAssignView(): void
51 {
52 $this->createValidContainerMockSet();
53
54 $self = $this->controller->assignView('variableName', 'variableValue');
55
56 static::assertInstanceOf(ShaarliController::class, $self);
57 static::assertSame('variableValue', $this->assignedValues['variableName']);
58 }
59
60 public function testRender(): void
61 {
62 $this->createValidContainerMockSet();
63
64 $render = $this->controller->render('templateName');
65
66 static::assertSame('templateName', $render);
67
68 static::assertSame(10, $this->assignedValues['linkcount']);
69 static::assertSame(5, $this->assignedValues['privateLinkcount']);
70 static::assertSame(['error'], $this->assignedValues['plugin_errors']);
71
72 static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']);
73 static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']);
74 static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']);
75 static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']);
76 static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']);
77 static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']);
78 }
79
80 protected function createValidContainerMockSet(): void
81 {
82 $pageBuilder = $this->createMock(PageBuilder::class);
83 $pageBuilder
84 ->method('assign')
85 ->willReturnCallback(function (string $key, $value): void {
86 $this->assignedValues[$key] = $value;
87 });
88 $pageBuilder
89 ->method('render')
90 ->willReturnCallback(function (string $template): string {
91 return $template;
92 });
93 $this->container->pageBuilder = $pageBuilder;
94
95 $bookmarkService = $this->createMock(BookmarkServiceInterface::class);
96 $bookmarkService
97 ->method('count')
98 ->willReturnCallback(function (string $visibility): int {
99 return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10;
100 });
101 $this->container->bookmarkService = $bookmarkService;
102
103 $pluginManager = $this->createMock(PluginManager::class);
104 $pluginManager
105 ->method('executeHooks')
106 ->willReturnCallback(function (string $hook, array &$data, array $params): array {
107 return $data[$hook] = $params;
108 });
109 $pluginManager->method('getErrors')->willReturn(['error']);
110 $this->container->pluginManager = $pluginManager;
111
112 $loginManager = $this->createMock(LoginManager::class);
113 $loginManager->method('isLoggedIn')->willReturn(true);
114 $this->container->loginManager = $loginManager;
115 }
116}
diff --git a/tests/front/controller/admin/ConfigureControllerTest.php b/tests/front/controller/admin/ConfigureControllerTest.php
new file mode 100644
index 00000000..f2f84bac
--- /dev/null
+++ b/tests/front/controller/admin/ConfigureControllerTest.php
@@ -0,0 +1,252 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Config\ConfigManager;
9use Shaarli\Front\Exception\WrongTokenException;
10use Shaarli\Security\SessionManager;
11use Shaarli\Thumbnailer;
12use Slim\Http\Request;
13use Slim\Http\Response;
14
15class ConfigureControllerTest extends TestCase
16{
17 use FrontAdminControllerMockHelper;
18
19 /** @var ConfigureController */
20 protected $controller;
21
22 public function setUp(): void
23 {
24 $this->createContainer();
25
26 $this->controller = new ConfigureController($this->container);
27 }
28
29 /**
30 * Test displaying configure page - it should display all config variables
31 */
32 public function testIndex(): void
33 {
34 $assignedVariables = [];
35 $this->assignTemplateVars($assignedVariables);
36
37 $request = $this->createMock(Request::class);
38 $response = new Response();
39
40 $this->container->conf = $this->createMock(ConfigManager::class);
41 $this->container->conf->method('get')->willReturnCallback(function (string $key) {
42 return $key;
43 });
44
45 $result = $this->controller->index($request, $response);
46
47 static::assertSame(200, $result->getStatusCode());
48 static::assertSame('configure', (string) $result->getBody());
49
50 static::assertSame('Configure - general.title', $assignedVariables['pagetitle']);
51 static::assertSame('general.title', $assignedVariables['title']);
52 static::assertSame('resource.theme', $assignedVariables['theme']);
53 static::assertEmpty($assignedVariables['theme_available']);
54 static::assertSame(['default', 'markdown'], $assignedVariables['formatter_available']);
55 static::assertNotEmpty($assignedVariables['continents']);
56 static::assertNotEmpty($assignedVariables['cities']);
57 static::assertSame('general.retrieve_description', $assignedVariables['retrieve_description']);
58 static::assertSame('privacy.default_private_links', $assignedVariables['private_links_default']);
59 static::assertSame('security.session_protection_disabled', $assignedVariables['session_protection_disabled']);
60 static::assertSame('feed.rss_permalinks', $assignedVariables['enable_rss_permalinks']);
61 static::assertSame('updates.check_updates', $assignedVariables['enable_update_check']);
62 static::assertSame('privacy.hide_public_links', $assignedVariables['hide_public_links']);
63 static::assertSame('api.enabled', $assignedVariables['api_enabled']);
64 static::assertSame('api.secret', $assignedVariables['api_secret']);
65 static::assertCount(4, $assignedVariables['languages']);
66 static::assertArrayHasKey('gd_enabled', $assignedVariables);
67 static::assertSame('thumbnails.mode', $assignedVariables['thumbnails_mode']);
68 }
69
70 /**
71 * Test posting a new config - make sure that everything is saved properly, without errors.
72 */
73 public function testSaveNewConfig(): void
74 {
75 $session = [];
76 $this->assignSessionVars($session);
77
78 $parameters = [
79 'token' => 'token',
80 'continent' => 'Europe',
81 'city' => 'Moscow',
82 'title' => 'Shaarli',
83 'titleLink' => './',
84 'retrieveDescription' => 'on',
85 'theme' => 'vintage',
86 'disablesessionprotection' => null,
87 'privateLinkByDefault' => true,
88 'enableRssPermalinks' => true,
89 'updateCheck' => false,
90 'hidePublicLinks' => 'on',
91 'enableApi' => 'on',
92 'apiSecret' => 'abcdef',
93 'formatter' => 'markdown',
94 'language' => 'fr',
95 'enableThumbnails' => Thumbnailer::MODE_NONE,
96 ];
97
98 $parametersConfigMapping = [
99 'general.timezone' => $parameters['continent'] . '/' . $parameters['city'],
100 'general.title' => $parameters['title'],
101 'general.header_link' => $parameters['titleLink'],
102 'general.retrieve_description' => !!$parameters['retrieveDescription'],
103 'resource.theme' => $parameters['theme'],
104 'security.session_protection_disabled' => !!$parameters['disablesessionprotection'],
105 'privacy.default_private_links' => !!$parameters['privateLinkByDefault'],
106 'feed.rss_permalinks' => !!$parameters['enableRssPermalinks'],
107 'updates.check_updates' => !!$parameters['updateCheck'],
108 'privacy.hide_public_links' => !!$parameters['hidePublicLinks'],
109 'api.enabled' => !!$parameters['enableApi'],
110 'api.secret' => $parameters['apiSecret'],
111 'formatter' => $parameters['formatter'],
112 'translation.language' => $parameters['language'],
113 'thumbnails.mode' => $parameters['enableThumbnails'],
114 ];
115
116 $request = $this->createMock(Request::class);
117 $request
118 ->expects(static::atLeastOnce())
119 ->method('getParam')->willReturnCallback(function (string $key) use ($parameters) {
120 if (false === array_key_exists($key, $parameters)) {
121 static::fail('unknown key: ' . $key);
122 }
123
124 return $parameters[$key];
125 }
126 );
127
128 $response = new Response();
129
130 $this->container->conf = $this->createMock(ConfigManager::class);
131 $this->container->conf
132 ->expects(static::atLeastOnce())
133 ->method('set')
134 ->willReturnCallback(function (string $key, $value) use ($parametersConfigMapping): void {
135 if (false === array_key_exists($key, $parametersConfigMapping)) {
136 static::fail('unknown key: ' . $key);
137 }
138
139 static::assertSame($parametersConfigMapping[$key], $value);
140 }
141 );
142
143 $result = $this->controller->save($request, $response);
144 static::assertSame(302, $result->getStatusCode());
145 static::assertSame(['/subfolder/admin/configure'], $result->getHeader('Location'));
146
147 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
148 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
149 static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
150 static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
151 }
152
153 /**
154 * Test posting a new config - wrong token.
155 */
156 public function testSaveNewConfigWrongToken(): void
157 {
158 $this->container->sessionManager = $this->createMock(SessionManager::class);
159 $this->container->sessionManager->method('checkToken')->willReturn(false);
160
161 $this->container->conf->expects(static::never())->method('set');
162 $this->container->conf->expects(static::never())->method('write');
163
164 $request = $this->createMock(Request::class);
165 $response = new Response();
166
167 $this->expectException(WrongTokenException::class);
168
169 $this->controller->save($request, $response);
170 }
171
172 /**
173 * Test posting a new config - thumbnail activation.
174 */
175 public function testSaveNewConfigThumbnailsActivation(): void
176 {
177 $session = [];
178 $this->assignSessionVars($session);
179
180 $request = $this->createMock(Request::class);
181 $request
182 ->expects(static::atLeastOnce())
183 ->method('getParam')->willReturnCallback(function (string $key) {
184 if ('enableThumbnails' === $key) {
185 return Thumbnailer::MODE_ALL;
186 }
187
188 return $key;
189 })
190 ;
191 $response = new Response();
192
193 $result = $this->controller->save($request, $response);
194
195 static::assertSame(302, $result->getStatusCode());
196 static::assertSame(['/subfolder/admin/configure'], $result->getHeader('Location'));
197
198 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
199 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
200 static::assertStringContainsString(
201 'You have enabled or changed thumbnails mode',
202 $session[SessionManager::KEY_WARNING_MESSAGES][0]
203 );
204 static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
205 static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
206 }
207
208 /**
209 * Test posting a new config - thumbnail activation.
210 */
211 public function testSaveNewConfigThumbnailsAlreadyActive(): void
212 {
213 $session = [];
214 $this->assignSessionVars($session);
215
216 $request = $this->createMock(Request::class);
217 $request
218 ->expects(static::atLeastOnce())
219 ->method('getParam')->willReturnCallback(function (string $key) {
220 if ('enableThumbnails' === $key) {
221 return Thumbnailer::MODE_ALL;
222 }
223
224 return $key;
225 })
226 ;
227 $response = new Response();
228
229 $this->container->conf = $this->createMock(ConfigManager::class);
230 $this->container->conf
231 ->expects(static::atLeastOnce())
232 ->method('get')
233 ->willReturnCallback(function (string $key): string {
234 if ('thumbnails.mode' === $key) {
235 return Thumbnailer::MODE_ALL;
236 }
237
238 return $key;
239 })
240 ;
241
242 $result = $this->controller->save($request, $response);
243
244 static::assertSame(302, $result->getStatusCode());
245 static::assertSame(['/subfolder/admin/configure'], $result->getHeader('Location'));
246
247 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
248 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
249 static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
250 static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
251 }
252}
diff --git a/tests/front/controller/admin/ExportControllerTest.php b/tests/front/controller/admin/ExportControllerTest.php
new file mode 100644
index 00000000..50d9e378
--- /dev/null
+++ b/tests/front/controller/admin/ExportControllerTest.php
@@ -0,0 +1,163 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Formatter\BookmarkFormatter;
10use Shaarli\Formatter\BookmarkRawFormatter;
11use Shaarli\Netscape\NetscapeBookmarkUtils;
12use Shaarli\Security\SessionManager;
13use Slim\Http\Request;
14use Slim\Http\Response;
15
16class ExportControllerTest extends TestCase
17{
18 use FrontAdminControllerMockHelper;
19
20 /** @var ExportController */
21 protected $controller;
22
23 public function setUp(): void
24 {
25 $this->createContainer();
26
27 $this->controller = new ExportController($this->container);
28 }
29
30 /**
31 * Test displaying export page
32 */
33 public function testIndex(): void
34 {
35 $assignedVariables = [];
36 $this->assignTemplateVars($assignedVariables);
37
38 $request = $this->createMock(Request::class);
39 $response = new Response();
40
41 $result = $this->controller->index($request, $response);
42
43 static::assertSame(200, $result->getStatusCode());
44 static::assertSame('export', (string) $result->getBody());
45
46 static::assertSame('Export - Shaarli', $assignedVariables['pagetitle']);
47 }
48
49 /**
50 * Test posting an export request
51 */
52 public function testExportDefault(): void
53 {
54 $assignedVariables = [];
55 $this->assignTemplateVars($assignedVariables);
56
57 $parameters = [
58 'selection' => 'all',
59 'prepend_note_url' => 'on',
60 ];
61
62 $request = $this->createMock(Request::class);
63 $request->method('getParam')->willReturnCallback(function (string $key) use ($parameters) {
64 return $parameters[$key] ?? null;
65 });
66 $response = new Response();
67
68 $bookmarks = [
69 (new Bookmark())->setUrl('http://link1.tld')->setTitle('Title 1'),
70 (new Bookmark())->setUrl('http://link2.tld')->setTitle('Title 2'),
71 ];
72
73 $this->container->netscapeBookmarkUtils = $this->createMock(NetscapeBookmarkUtils::class);
74 $this->container->netscapeBookmarkUtils
75 ->expects(static::once())
76 ->method('filterAndFormat')
77 ->willReturnCallback(
78 function (
79 BookmarkFormatter $formatter,
80 string $selection,
81 bool $prependNoteUrl,
82 string $indexUrl
83 ) use ($parameters, $bookmarks): array {
84 static::assertInstanceOf(BookmarkRawFormatter::class, $formatter);
85 static::assertSame($parameters['selection'], $selection);
86 static::assertTrue($prependNoteUrl);
87 static::assertSame('http://shaarli', $indexUrl);
88
89 return $bookmarks;
90 }
91 )
92 ;
93
94 $result = $this->controller->export($request, $response);
95
96 static::assertSame(200, $result->getStatusCode());
97 static::assertSame('export.bookmarks', (string) $result->getBody());
98 static::assertSame(['text/html; charset=utf-8'], $result->getHeader('content-type'));
99 static::assertRegExp(
100 '/attachment; filename=bookmarks_all_[\d]{8}_[\d]{6}\.html/',
101 $result->getHeader('content-disposition')[0]
102 );
103
104 static::assertNotEmpty($assignedVariables['date']);
105 static::assertSame(PHP_EOL, $assignedVariables['eol']);
106 static::assertSame('all', $assignedVariables['selection']);
107 static::assertSame($bookmarks, $assignedVariables['links']);
108 }
109
110 /**
111 * Test posting an export request - without selection parameter
112 */
113 public function testExportSelectionMissing(): void
114 {
115 $request = $this->createMock(Request::class);
116 $response = new Response();
117
118 $this->container->sessionManager
119 ->expects(static::once())
120 ->method('setSessionParameter')
121 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Please select an export mode.'])
122 ;
123
124 $result = $this->controller->export($request, $response);
125
126 static::assertSame(302, $result->getStatusCode());
127 static::assertSame(['/subfolder/admin/export'], $result->getHeader('location'));
128 }
129
130 /**
131 * Test posting an export request - without selection parameter
132 */
133 public function testExportErrorEncountered(): void
134 {
135 $parameters = [
136 'selection' => 'all',
137 ];
138
139 $request = $this->createMock(Request::class);
140 $request->method('getParam')->willReturnCallback(function (string $key) use ($parameters) {
141 return $parameters[$key] ?? null;
142 });
143 $response = new Response();
144
145 $this->container->netscapeBookmarkUtils = $this->createMock(NetscapeBookmarkUtils::class);
146 $this->container->netscapeBookmarkUtils
147 ->expects(static::once())
148 ->method('filterAndFormat')
149 ->willThrowException(new \Exception($message = 'error message'));
150 ;
151
152 $this->container->sessionManager
153 ->expects(static::once())
154 ->method('setSessionParameter')
155 ->with(SessionManager::KEY_ERROR_MESSAGES, [$message])
156 ;
157
158 $result = $this->controller->export($request, $response);
159
160 static::assertSame(302, $result->getStatusCode());
161 static::assertSame(['/subfolder/admin/export'], $result->getHeader('location'));
162 }
163}
diff --git a/tests/front/controller/admin/FrontAdminControllerMockHelper.php b/tests/front/controller/admin/FrontAdminControllerMockHelper.php
new file mode 100644
index 00000000..2b9f2ef1
--- /dev/null
+++ b/tests/front/controller/admin/FrontAdminControllerMockHelper.php
@@ -0,0 +1,56 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use Shaarli\Container\ShaarliTestContainer;
8use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper;
9use Shaarli\History;
10
11/**
12 * Trait FrontControllerMockHelper
13 *
14 * Helper trait used to initialize the ShaarliContainer and mock its services for admin controller tests.
15 *
16 * @property ShaarliTestContainer $container
17 */
18trait FrontAdminControllerMockHelper
19{
20 use FrontControllerMockHelper {
21 FrontControllerMockHelper::createContainer as parentCreateContainer;
22 }
23
24 /**
25 * Mock the container instance
26 */
27 protected function createContainer(): void
28 {
29 $this->parentCreateContainer();
30
31 $this->container->history = $this->createMock(History::class);
32
33 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
34 $this->container->sessionManager->method('checkToken')->willReturn(true);
35 }
36
37
38 /**
39 * Pass a reference of an array which will be populated by `sessionManager->setSessionParameter`
40 * calls during execution.
41 *
42 * @param mixed $variables Array reference to populate.
43 */
44 protected function assignSessionVars(array &$variables): void
45 {
46 $this->container->sessionManager
47 ->expects(static::atLeastOnce())
48 ->method('setSessionParameter')
49 ->willReturnCallback(function ($key, $value) use (&$variables) {
50 $variables[$key] = $value;
51
52 return $this->container->sessionManager;
53 })
54 ;
55 }
56}
diff --git a/tests/front/controller/admin/ImportControllerTest.php b/tests/front/controller/admin/ImportControllerTest.php
new file mode 100644
index 00000000..eb31fad0
--- /dev/null
+++ b/tests/front/controller/admin/ImportControllerTest.php
@@ -0,0 +1,148 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Psr\Http\Message\UploadedFileInterface;
9use Shaarli\Netscape\NetscapeBookmarkUtils;
10use Shaarli\Security\SessionManager;
11use Slim\Http\Request;
12use Slim\Http\Response;
13use Slim\Http\UploadedFile;
14
15class ImportControllerTest extends TestCase
16{
17 use FrontAdminControllerMockHelper;
18
19 /** @var ImportController */
20 protected $controller;
21
22 public function setUp(): void
23 {
24 $this->createContainer();
25
26 $this->controller = new ImportController($this->container);
27 }
28
29 /**
30 * Test displaying import page
31 */
32 public function testIndex(): void
33 {
34 $assignedVariables = [];
35 $this->assignTemplateVars($assignedVariables);
36
37 $request = $this->createMock(Request::class);
38 $response = new Response();
39
40 $result = $this->controller->index($request, $response);
41
42 static::assertSame(200, $result->getStatusCode());
43 static::assertSame('import', (string) $result->getBody());
44
45 static::assertSame('Import - Shaarli', $assignedVariables['pagetitle']);
46 static::assertIsInt($assignedVariables['maxfilesize']);
47 static::assertRegExp('/\d+[KM]iB/', $assignedVariables['maxfilesizeHuman']);
48 }
49
50 /**
51 * Test importing a file with default and valid parameters
52 */
53 public function testImportDefault(): void
54 {
55 $parameters = [
56 'abc' => 'def',
57 'other' => 'param',
58 ];
59
60 $requestFile = new UploadedFile('file', 'name', 'type', 123);
61
62 $request = $this->createMock(Request::class);
63 $request->method('getParams')->willReturnCallback(function () use ($parameters) {
64 return $parameters;
65 });
66 $request->method('getUploadedFiles')->willReturn(['filetoupload' => $requestFile]);
67 $response = new Response();
68
69 $this->container->netscapeBookmarkUtils = $this->createMock(NetscapeBookmarkUtils::class);
70 $this->container->netscapeBookmarkUtils
71 ->expects(static::once())
72 ->method('import')
73 ->willReturnCallback(
74 function (
75 array $post,
76 UploadedFileInterface $file
77 ) use ($parameters, $requestFile): string {
78 static::assertSame($parameters, $post);
79 static::assertSame($requestFile, $file);
80
81 return 'status';
82 }
83 )
84 ;
85
86 $this->container->sessionManager
87 ->expects(static::once())
88 ->method('setSessionParameter')
89 ->with(SessionManager::KEY_SUCCESS_MESSAGES, ['status'])
90 ;
91
92 $result = $this->controller->import($request, $response);
93
94 static::assertSame(302, $result->getStatusCode());
95 static::assertSame(['/subfolder/admin/import'], $result->getHeader('location'));
96 }
97
98 /**
99 * Test posting an import request - without import file
100 */
101 public function testImportFileMissing(): void
102 {
103 $request = $this->createMock(Request::class);
104 $response = new Response();
105
106 $this->container->sessionManager
107 ->expects(static::once())
108 ->method('setSessionParameter')
109 ->with(SessionManager::KEY_ERROR_MESSAGES, ['No import file provided.'])
110 ;
111
112 $result = $this->controller->import($request, $response);
113
114 static::assertSame(302, $result->getStatusCode());
115 static::assertSame(['/subfolder/admin/import'], $result->getHeader('location'));
116 }
117
118 /**
119 * Test posting an import request - with an empty file
120 */
121 public function testImportEmptyFile(): void
122 {
123 $requestFile = new UploadedFile('file', 'name', 'type', 0);
124
125 $request = $this->createMock(Request::class);
126 $request->method('getUploadedFiles')->willReturn(['filetoupload' => $requestFile]);
127 $response = new Response();
128
129 $this->container->netscapeBookmarkUtils = $this->createMock(NetscapeBookmarkUtils::class);
130 $this->container->netscapeBookmarkUtils->expects(static::never())->method('filterAndFormat');
131
132 $this->container->sessionManager
133 ->expects(static::once())
134 ->method('setSessionParameter')
135 ->willReturnCallback(function (string $key, array $value): SessionManager {
136 static::assertSame(SessionManager::KEY_ERROR_MESSAGES, $key);
137 static::assertStringStartsWith('The file you are trying to upload is probably bigger', $value[0]);
138
139 return $this->container->sessionManager;
140 })
141 ;
142
143 $result = $this->controller->import($request, $response);
144
145 static::assertSame(302, $result->getStatusCode());
146 static::assertSame(['/subfolder/admin/import'], $result->getHeader('location'));
147 }
148}
diff --git a/tests/front/controller/admin/LogoutControllerTest.php b/tests/front/controller/admin/LogoutControllerTest.php
new file mode 100644
index 00000000..45e84dc0
--- /dev/null
+++ b/tests/front/controller/admin/LogoutControllerTest.php
@@ -0,0 +1,51 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Security\CookieManager;
9use Shaarli\Security\LoginManager;
10use Shaarli\Security\SessionManager;
11use Slim\Http\Request;
12use Slim\Http\Response;
13
14class LogoutControllerTest extends TestCase
15{
16 use FrontAdminControllerMockHelper;
17
18 /** @var LogoutController */
19 protected $controller;
20
21 public function setUp(): void
22 {
23 $this->createContainer();
24
25 $this->controller = new LogoutController($this->container);
26 }
27
28 public function testValidControllerInvoke(): void
29 {
30 $request = $this->createMock(Request::class);
31 $response = new Response();
32
33 $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches');
34
35 $this->container->sessionManager = $this->createMock(SessionManager::class);
36 $this->container->sessionManager->expects(static::once())->method('logout');
37
38 $this->container->cookieManager = $this->createMock(CookieManager::class);
39 $this->container->cookieManager
40 ->expects(static::once())
41 ->method('setCookieParameter')
42 ->with(CookieManager::STAY_SIGNED_IN, 'false', 0, '/subfolder/')
43 ;
44
45 $result = $this->controller->index($request, $response);
46
47 static::assertInstanceOf(Response::class, $result);
48 static::assertSame(302, $result->getStatusCode());
49 static::assertSame(['/subfolder/'], $result->getHeader('location'));
50 }
51}
diff --git a/tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php b/tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php
new file mode 100644
index 00000000..7d5b752a
--- /dev/null
+++ b/tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php
@@ -0,0 +1,47 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ManageShaareControllerTest;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
9use Shaarli\Front\Controller\Admin\ManageShaareController;
10use Shaarli\Http\HttpAccess;
11use Slim\Http\Request;
12use Slim\Http\Response;
13
14class AddShaareTest extends TestCase
15{
16 use FrontAdminControllerMockHelper;
17
18 /** @var ManageShaareController */
19 protected $controller;
20
21 public function setUp(): void
22 {
23 $this->createContainer();
24
25 $this->container->httpAccess = $this->createMock(HttpAccess::class);
26 $this->controller = new ManageShaareController($this->container);
27 }
28
29 /**
30 * Test displaying add link page
31 */
32 public function testAddShaare(): void
33 {
34 $assignedVariables = [];
35 $this->assignTemplateVars($assignedVariables);
36
37 $request = $this->createMock(Request::class);
38 $response = new Response();
39
40 $result = $this->controller->addShaare($request, $response);
41
42 static::assertSame(200, $result->getStatusCode());
43 static::assertSame('addlink', (string) $result->getBody());
44
45 static::assertSame('Shaare a new link - Shaarli', $assignedVariables['pagetitle']);
46 }
47}
diff --git a/tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php
new file mode 100644
index 00000000..5a615791
--- /dev/null
+++ b/tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php
@@ -0,0 +1,418 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ManageShaareControllerTest;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
10use Shaarli\Formatter\BookmarkFormatter;
11use Shaarli\Formatter\BookmarkRawFormatter;
12use Shaarli\Formatter\FormatterFactory;
13use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
14use Shaarli\Front\Controller\Admin\ManageShaareController;
15use Shaarli\Http\HttpAccess;
16use Shaarli\Security\SessionManager;
17use Slim\Http\Request;
18use Slim\Http\Response;
19
20class ChangeVisibilityBookmarkTest extends TestCase
21{
22 use FrontAdminControllerMockHelper;
23
24 /** @var ManageShaareController */
25 protected $controller;
26
27 public function setUp(): void
28 {
29 $this->createContainer();
30
31 $this->container->httpAccess = $this->createMock(HttpAccess::class);
32 $this->controller = new ManageShaareController($this->container);
33 }
34
35 /**
36 * Change bookmark visibility - Set private - Single public bookmark with valid parameters
37 */
38 public function testSetSingleBookmarkPrivate(): void
39 {
40 $parameters = ['id' => '123', 'newVisibility' => 'private'];
41
42 $request = $this->createMock(Request::class);
43 $request
44 ->method('getParam')
45 ->willReturnCallback(function (string $key) use ($parameters): ?string {
46 return $parameters[$key] ?? null;
47 })
48 ;
49 $response = new Response();
50
51 $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(false);
52
53 static::assertFalse($bookmark->isPrivate());
54
55 $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark);
56 $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, false);
57 $this->container->bookmarkService->expects(static::once())->method('save');
58 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
59 $this->container->formatterFactory
60 ->expects(static::once())
61 ->method('getFormatter')
62 ->with('raw')
63 ->willReturnCallback(function () use ($bookmark): BookmarkFormatter {
64 return new BookmarkRawFormatter($this->container->conf, true);
65 })
66 ;
67
68 // Make sure that PluginManager hook is triggered
69 $this->container->pluginManager
70 ->expects(static::once())
71 ->method('executeHooks')
72 ->with('save_link')
73 ;
74
75 $result = $this->controller->changeVisibility($request, $response);
76
77 static::assertTrue($bookmark->isPrivate());
78
79 static::assertSame(302, $result->getStatusCode());
80 static::assertSame(['/subfolder/'], $result->getHeader('location'));
81 }
82
83 /**
84 * Change bookmark visibility - Set public - Single private bookmark with valid parameters
85 */
86 public function testSetSingleBookmarkPublic(): void
87 {
88 $parameters = ['id' => '123', 'newVisibility' => 'public'];
89
90 $request = $this->createMock(Request::class);
91 $request
92 ->method('getParam')
93 ->willReturnCallback(function (string $key) use ($parameters): ?string {
94 return $parameters[$key] ?? null;
95 })
96 ;
97 $response = new Response();
98
99 $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(true);
100
101 static::assertTrue($bookmark->isPrivate());
102
103 $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark);
104 $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, false);
105 $this->container->bookmarkService->expects(static::once())->method('save');
106 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
107 $this->container->formatterFactory
108 ->expects(static::once())
109 ->method('getFormatter')
110 ->with('raw')
111 ->willReturn(new BookmarkRawFormatter($this->container->conf, true))
112 ;
113
114 // Make sure that PluginManager hook is triggered
115 $this->container->pluginManager
116 ->expects(static::once())
117 ->method('executeHooks')
118 ->with('save_link')
119 ;
120
121 $result = $this->controller->changeVisibility($request, $response);
122
123 static::assertFalse($bookmark->isPrivate());
124
125 static::assertSame(302, $result->getStatusCode());
126 static::assertSame(['/subfolder/'], $result->getHeader('location'));
127 }
128
129 /**
130 * Change bookmark visibility - Set private on single already private bookmark
131 */
132 public function testSetSinglePrivateBookmarkPrivate(): void
133 {
134 $parameters = ['id' => '123', 'newVisibility' => 'private'];
135
136 $request = $this->createMock(Request::class);
137 $request
138 ->method('getParam')
139 ->willReturnCallback(function (string $key) use ($parameters): ?string {
140 return $parameters[$key] ?? null;
141 })
142 ;
143 $response = new Response();
144
145 $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(true);
146
147 static::assertTrue($bookmark->isPrivate());
148
149 $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark);
150 $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, false);
151 $this->container->bookmarkService->expects(static::once())->method('save');
152 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
153 $this->container->formatterFactory
154 ->expects(static::once())
155 ->method('getFormatter')
156 ->with('raw')
157 ->willReturn(new BookmarkRawFormatter($this->container->conf, true))
158 ;
159
160 // Make sure that PluginManager hook is triggered
161 $this->container->pluginManager
162 ->expects(static::once())
163 ->method('executeHooks')
164 ->with('save_link')
165 ;
166
167 $result = $this->controller->changeVisibility($request, $response);
168
169 static::assertTrue($bookmark->isPrivate());
170
171 static::assertSame(302, $result->getStatusCode());
172 static::assertSame(['/subfolder/'], $result->getHeader('location'));
173 }
174
175 /**
176 * Change bookmark visibility - Set multiple bookmarks private
177 */
178 public function testSetMultipleBookmarksPrivate(): void
179 {
180 $parameters = ['id' => '123 456 789', 'newVisibility' => 'private'];
181
182 $request = $this->createMock(Request::class);
183 $request
184 ->method('getParam')
185 ->willReturnCallback(function (string $key) use ($parameters): ?string {
186 return $parameters[$key] ?? null;
187 })
188 ;
189 $response = new Response();
190
191 $bookmarks = [
192 (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(false),
193 (new Bookmark())->setId(456)->setUrl('http://domain.tld')->setTitle('Title 456')->setPrivate(true),
194 (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789')->setPrivate(false),
195 ];
196
197 $this->container->bookmarkService
198 ->expects(static::exactly(3))
199 ->method('get')
200 ->withConsecutive([123], [456], [789])
201 ->willReturnOnConsecutiveCalls(...$bookmarks)
202 ;
203 $this->container->bookmarkService
204 ->expects(static::exactly(3))
205 ->method('set')
206 ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
207 return [$bookmark, false];
208 }, $bookmarks))
209 ;
210 $this->container->bookmarkService->expects(static::once())->method('save');
211 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
212 $this->container->formatterFactory
213 ->expects(static::once())
214 ->method('getFormatter')
215 ->with('raw')
216 ->willReturn(new BookmarkRawFormatter($this->container->conf, true))
217 ;
218
219 // Make sure that PluginManager hook is triggered
220 $this->container->pluginManager
221 ->expects(static::exactly(3))
222 ->method('executeHooks')
223 ->with('save_link')
224 ;
225
226 $result = $this->controller->changeVisibility($request, $response);
227
228 static::assertTrue($bookmarks[0]->isPrivate());
229 static::assertTrue($bookmarks[1]->isPrivate());
230 static::assertTrue($bookmarks[2]->isPrivate());
231
232 static::assertSame(302, $result->getStatusCode());
233 static::assertSame(['/subfolder/'], $result->getHeader('location'));
234 }
235
236 /**
237 * Change bookmark visibility - Single bookmark not found.
238 */
239 public function testChangeVisibilitySingleBookmarkNotFound(): void
240 {
241 $parameters = ['id' => '123', 'newVisibility' => 'private'];
242
243 $request = $this->createMock(Request::class);
244 $request
245 ->method('getParam')
246 ->willReturnCallback(function (string $key) use ($parameters): ?string {
247 return $parameters[$key] ?? null;
248 })
249 ;
250 $response = new Response();
251
252 $this->container->bookmarkService
253 ->expects(static::once())
254 ->method('get')
255 ->willThrowException(new BookmarkNotFoundException())
256 ;
257 $this->container->bookmarkService->expects(static::never())->method('set');
258 $this->container->bookmarkService->expects(static::never())->method('save');
259 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
260 $this->container->formatterFactory
261 ->expects(static::once())
262 ->method('getFormatter')
263 ->with('raw')
264 ->willReturn(new BookmarkRawFormatter($this->container->conf, true))
265 ;
266
267 // Make sure that PluginManager hook is not triggered
268 $this->container->pluginManager
269 ->expects(static::never())
270 ->method('executeHooks')
271 ->with('save_link')
272 ;
273
274 $result = $this->controller->changeVisibility($request, $response);
275
276 static::assertSame(302, $result->getStatusCode());
277 static::assertSame(['/subfolder/'], $result->getHeader('location'));
278 }
279
280 /**
281 * Change bookmark visibility - Multiple bookmarks with one not found.
282 */
283 public function testChangeVisibilityMultipleBookmarksOneNotFound(): void
284 {
285 $parameters = ['id' => '123 456 789', 'newVisibility' => 'public'];
286
287 $request = $this->createMock(Request::class);
288 $request
289 ->method('getParam')
290 ->willReturnCallback(function (string $key) use ($parameters): ?string {
291 return $parameters[$key] ?? null;
292 })
293 ;
294 $response = new Response();
295
296 $bookmarks = [
297 (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(true),
298 (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789')->setPrivate(false),
299 ];
300
301 $this->container->bookmarkService
302 ->expects(static::exactly(3))
303 ->method('get')
304 ->withConsecutive([123], [456], [789])
305 ->willReturnCallback(function (int $id) use ($bookmarks): Bookmark {
306 if ($id === 123) {
307 return $bookmarks[0];
308 }
309 if ($id === 789) {
310 return $bookmarks[1];
311 }
312 throw new BookmarkNotFoundException();
313 })
314 ;
315 $this->container->bookmarkService
316 ->expects(static::exactly(2))
317 ->method('set')
318 ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
319 return [$bookmark, false];
320 }, $bookmarks))
321 ;
322 $this->container->bookmarkService->expects(static::once())->method('save');
323
324 // Make sure that PluginManager hook is not triggered
325 $this->container->pluginManager
326 ->expects(static::exactly(2))
327 ->method('executeHooks')
328 ->with('save_link')
329 ;
330
331 $this->container->sessionManager
332 ->expects(static::once())
333 ->method('setSessionParameter')
334 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 456 could not be found.'])
335 ;
336
337 $result = $this->controller->changeVisibility($request, $response);
338
339 static::assertSame(302, $result->getStatusCode());
340 static::assertSame(['/subfolder/'], $result->getHeader('location'));
341 }
342
343 /**
344 * Change bookmark visibility - Invalid ID
345 */
346 public function testChangeVisibilityInvalidId(): void
347 {
348 $parameters = ['id' => 'nope not an ID', 'newVisibility' => 'private'];
349
350 $request = $this->createMock(Request::class);
351 $request
352 ->method('getParam')
353 ->willReturnCallback(function (string $key) use ($parameters): ?string {
354 return $parameters[$key] ?? null;
355 })
356 ;
357 $response = new Response();
358
359 $this->container->sessionManager
360 ->expects(static::once())
361 ->method('setSessionParameter')
362 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.'])
363 ;
364
365 $result = $this->controller->changeVisibility($request, $response);
366
367 static::assertSame(302, $result->getStatusCode());
368 static::assertSame(['/subfolder/'], $result->getHeader('location'));
369 }
370
371 /**
372 * Change bookmark visibility - Empty ID
373 */
374 public function testChangeVisibilityEmptyId(): void
375 {
376 $request = $this->createMock(Request::class);
377 $response = new Response();
378
379 $this->container->sessionManager
380 ->expects(static::once())
381 ->method('setSessionParameter')
382 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.'])
383 ;
384
385 $result = $this->controller->changeVisibility($request, $response);
386
387 static::assertSame(302, $result->getStatusCode());
388 static::assertSame(['/subfolder/'], $result->getHeader('location'));
389 }
390
391 /**
392 * Change bookmark visibility - with invalid visibility
393 */
394 public function testChangeVisibilityWithInvalidVisibility(): void
395 {
396 $parameters = ['id' => '123', 'newVisibility' => 'invalid'];
397
398 $request = $this->createMock(Request::class);
399 $request
400 ->method('getParam')
401 ->willReturnCallback(function (string $key) use ($parameters): ?string {
402 return $parameters[$key] ?? null;
403 })
404 ;
405 $response = new Response();
406
407 $this->container->sessionManager
408 ->expects(static::once())
409 ->method('setSessionParameter')
410 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid visibility provided.'])
411 ;
412
413 $result = $this->controller->changeVisibility($request, $response);
414
415 static::assertSame(302, $result->getStatusCode());
416 static::assertSame(['/subfolder/'], $result->getHeader('location'));
417 }
418}
diff --git a/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php
new file mode 100644
index 00000000..dee622bb
--- /dev/null
+++ b/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php
@@ -0,0 +1,376 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ManageShaareControllerTest;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
10use Shaarli\Formatter\BookmarkFormatter;
11use Shaarli\Formatter\FormatterFactory;
12use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
13use Shaarli\Front\Controller\Admin\ManageShaareController;
14use Shaarli\Http\HttpAccess;
15use Shaarli\Security\SessionManager;
16use Slim\Http\Request;
17use Slim\Http\Response;
18
19class DeleteBookmarkTest extends TestCase
20{
21 use FrontAdminControllerMockHelper;
22
23 /** @var ManageShaareController */
24 protected $controller;
25
26 public function setUp(): void
27 {
28 $this->createContainer();
29
30 $this->container->httpAccess = $this->createMock(HttpAccess::class);
31 $this->controller = new ManageShaareController($this->container);
32 }
33
34 /**
35 * Delete bookmark - Single bookmark with valid parameters
36 */
37 public function testDeleteSingleBookmark(): void
38 {
39 $parameters = ['id' => '123'];
40
41 $request = $this->createMock(Request::class);
42 $request
43 ->method('getParam')
44 ->willReturnCallback(function (string $key) use ($parameters): ?string {
45 return $parameters[$key] ?? null;
46 })
47 ;
48 $response = new Response();
49
50 $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123');
51
52 $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark);
53 $this->container->bookmarkService->expects(static::once())->method('remove')->with($bookmark, false);
54 $this->container->bookmarkService->expects(static::once())->method('save');
55 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
56 $this->container->formatterFactory
57 ->expects(static::once())
58 ->method('getFormatter')
59 ->with('raw')
60 ->willReturnCallback(function () use ($bookmark): BookmarkFormatter {
61 $formatter = $this->createMock(BookmarkFormatter::class);
62 $formatter
63 ->expects(static::once())
64 ->method('format')
65 ->with($bookmark)
66 ->willReturn(['formatted' => $bookmark])
67 ;
68
69 return $formatter;
70 })
71 ;
72
73 // Make sure that PluginManager hook is triggered
74 $this->container->pluginManager
75 ->expects(static::once())
76 ->method('executeHooks')
77 ->with('delete_link', ['formatted' => $bookmark])
78 ;
79
80 $result = $this->controller->deleteBookmark($request, $response);
81
82 static::assertSame(302, $result->getStatusCode());
83 static::assertSame(['/subfolder/'], $result->getHeader('location'));
84 }
85
86 /**
87 * Delete bookmark - Multiple bookmarks with valid parameters
88 */
89 public function testDeleteMultipleBookmarks(): void
90 {
91 $parameters = ['id' => '123 456 789'];
92
93 $request = $this->createMock(Request::class);
94 $request
95 ->method('getParam')
96 ->willReturnCallback(function (string $key) use ($parameters): ?string {
97 return $parameters[$key] ?? null;
98 })
99 ;
100 $response = new Response();
101
102 $bookmarks = [
103 (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123'),
104 (new Bookmark())->setId(456)->setUrl('http://domain.tld')->setTitle('Title 456'),
105 (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789'),
106 ];
107
108 $this->container->bookmarkService
109 ->expects(static::exactly(3))
110 ->method('get')
111 ->withConsecutive([123], [456], [789])
112 ->willReturnOnConsecutiveCalls(...$bookmarks)
113 ;
114 $this->container->bookmarkService
115 ->expects(static::exactly(3))
116 ->method('remove')
117 ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
118 return [$bookmark, false];
119 }, $bookmarks))
120 ;
121 $this->container->bookmarkService->expects(static::once())->method('save');
122 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
123 $this->container->formatterFactory
124 ->expects(static::once())
125 ->method('getFormatter')
126 ->with('raw')
127 ->willReturnCallback(function () use ($bookmarks): BookmarkFormatter {
128 $formatter = $this->createMock(BookmarkFormatter::class);
129
130 $formatter
131 ->expects(static::exactly(3))
132 ->method('format')
133 ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
134 return [$bookmark];
135 }, $bookmarks))
136 ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array {
137 return ['formatted' => $bookmark];
138 }, $bookmarks))
139 ;
140
141 return $formatter;
142 })
143 ;
144
145 // Make sure that PluginManager hook is triggered
146 $this->container->pluginManager
147 ->expects(static::exactly(3))
148 ->method('executeHooks')
149 ->with('delete_link')
150 ;
151
152 $result = $this->controller->deleteBookmark($request, $response);
153
154 static::assertSame(302, $result->getStatusCode());
155 static::assertSame(['/subfolder/'], $result->getHeader('location'));
156 }
157
158 /**
159 * Delete bookmark - Single bookmark not found in the data store
160 */
161 public function testDeleteSingleBookmarkNotFound(): void
162 {
163 $parameters = ['id' => '123'];
164
165 $request = $this->createMock(Request::class);
166 $request
167 ->method('getParam')
168 ->willReturnCallback(function (string $key) use ($parameters): ?string {
169 return $parameters[$key] ?? null;
170 })
171 ;
172 $response = new Response();
173
174 $this->container->bookmarkService
175 ->expects(static::once())
176 ->method('get')
177 ->willThrowException(new BookmarkNotFoundException())
178 ;
179 $this->container->bookmarkService->expects(static::never())->method('remove');
180 $this->container->bookmarkService->expects(static::never())->method('save');
181 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
182 $this->container->formatterFactory
183 ->expects(static::once())
184 ->method('getFormatter')
185 ->with('raw')
186 ->willReturnCallback(function (): BookmarkFormatter {
187 $formatter = $this->createMock(BookmarkFormatter::class);
188
189 $formatter->expects(static::never())->method('format');
190
191 return $formatter;
192 })
193 ;
194 // Make sure that PluginManager hook is not triggered
195 $this->container->pluginManager
196 ->expects(static::never())
197 ->method('executeHooks')
198 ->with('delete_link')
199 ;
200
201 $result = $this->controller->deleteBookmark($request, $response);
202
203 static::assertSame(302, $result->getStatusCode());
204 static::assertSame(['/subfolder/'], $result->getHeader('location'));
205 }
206
207 /**
208 * Delete bookmark - Multiple bookmarks with one not found in the data store
209 */
210 public function testDeleteMultipleBookmarksOneNotFound(): void
211 {
212 $parameters = ['id' => '123 456 789'];
213
214 $request = $this->createMock(Request::class);
215 $request
216 ->method('getParam')
217 ->willReturnCallback(function (string $key) use ($parameters): ?string {
218 return $parameters[$key] ?? null;
219 })
220 ;
221 $response = new Response();
222
223 $bookmarks = [
224 (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123'),
225 (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789'),
226 ];
227
228 $this->container->bookmarkService
229 ->expects(static::exactly(3))
230 ->method('get')
231 ->withConsecutive([123], [456], [789])
232 ->willReturnCallback(function (int $id) use ($bookmarks): Bookmark {
233 if ($id === 123) {
234 return $bookmarks[0];
235 }
236 if ($id === 789) {
237 return $bookmarks[1];
238 }
239 throw new BookmarkNotFoundException();
240 })
241 ;
242 $this->container->bookmarkService
243 ->expects(static::exactly(2))
244 ->method('remove')
245 ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
246 return [$bookmark, false];
247 }, $bookmarks))
248 ;
249 $this->container->bookmarkService->expects(static::once())->method('save');
250 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
251 $this->container->formatterFactory
252 ->expects(static::once())
253 ->method('getFormatter')
254 ->with('raw')
255 ->willReturnCallback(function () use ($bookmarks): BookmarkFormatter {
256 $formatter = $this->createMock(BookmarkFormatter::class);
257
258 $formatter
259 ->expects(static::exactly(2))
260 ->method('format')
261 ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
262 return [$bookmark];
263 }, $bookmarks))
264 ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array {
265 return ['formatted' => $bookmark];
266 }, $bookmarks))
267 ;
268
269 return $formatter;
270 })
271 ;
272
273 // Make sure that PluginManager hook is not triggered
274 $this->container->pluginManager
275 ->expects(static::exactly(2))
276 ->method('executeHooks')
277 ->with('delete_link')
278 ;
279
280 $this->container->sessionManager
281 ->expects(static::once())
282 ->method('setSessionParameter')
283 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 456 could not be found.'])
284 ;
285
286 $result = $this->controller->deleteBookmark($request, $response);
287
288 static::assertSame(302, $result->getStatusCode());
289 static::assertSame(['/subfolder/'], $result->getHeader('location'));
290 }
291
292 /**
293 * Delete bookmark - Invalid ID
294 */
295 public function testDeleteInvalidId(): void
296 {
297 $parameters = ['id' => 'nope not an ID'];
298
299 $request = $this->createMock(Request::class);
300 $request
301 ->method('getParam')
302 ->willReturnCallback(function (string $key) use ($parameters): ?string {
303 return $parameters[$key] ?? null;
304 })
305 ;
306 $response = new Response();
307
308 $this->container->sessionManager
309 ->expects(static::once())
310 ->method('setSessionParameter')
311 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.'])
312 ;
313
314 $result = $this->controller->deleteBookmark($request, $response);
315
316 static::assertSame(302, $result->getStatusCode());
317 static::assertSame(['/subfolder/'], $result->getHeader('location'));
318 }
319
320 /**
321 * Delete bookmark - Empty ID
322 */
323 public function testDeleteEmptyId(): void
324 {
325 $request = $this->createMock(Request::class);
326 $response = new Response();
327
328 $this->container->sessionManager
329 ->expects(static::once())
330 ->method('setSessionParameter')
331 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.'])
332 ;
333
334 $result = $this->controller->deleteBookmark($request, $response);
335
336 static::assertSame(302, $result->getStatusCode());
337 static::assertSame(['/subfolder/'], $result->getHeader('location'));
338 }
339
340 /**
341 * Delete bookmark - from bookmarklet
342 */
343 public function testDeleteBookmarkFromBookmarklet(): void
344 {
345 $parameters = [
346 'id' => '123',
347 'source' => 'bookmarklet',
348 ];
349
350 $request = $this->createMock(Request::class);
351 $request
352 ->method('getParam')
353 ->willReturnCallback(function (string $key) use ($parameters): ?string {
354 return $parameters[$key] ?? null;
355 })
356 ;
357 $response = new Response();
358
359 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
360 $this->container->formatterFactory
361 ->expects(static::once())
362 ->method('getFormatter')
363 ->willReturnCallback(function (): BookmarkFormatter {
364 $formatter = $this->createMock(BookmarkFormatter::class);
365 $formatter->method('format')->willReturn(['formatted']);
366
367 return $formatter;
368 })
369 ;
370
371 $result = $this->controller->deleteBookmark($request, $response);
372
373 static::assertSame(200, $result->getStatusCode());
374 static::assertSame('<script>self.close();</script>', (string) $result->getBody('location'));
375 }
376}
diff --git a/tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php b/tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php
new file mode 100644
index 00000000..777583d5
--- /dev/null
+++ b/tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php
@@ -0,0 +1,315 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ManageShaareControllerTest;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Config\ConfigManager;
10use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
11use Shaarli\Front\Controller\Admin\ManageShaareController;
12use Shaarli\Http\HttpAccess;
13use Slim\Http\Request;
14use Slim\Http\Response;
15
16class DisplayCreateFormTest extends TestCase
17{
18 use FrontAdminControllerMockHelper;
19
20 /** @var ManageShaareController */
21 protected $controller;
22
23 public function setUp(): void
24 {
25 $this->createContainer();
26
27 $this->container->httpAccess = $this->createMock(HttpAccess::class);
28 $this->controller = new ManageShaareController($this->container);
29 }
30
31 /**
32 * Test displaying bookmark create form
33 * Ensure that every step of the standard workflow works properly.
34 */
35 public function testDisplayCreateFormWithUrl(): void
36 {
37 $this->container->environment = [
38 'HTTP_REFERER' => $referer = 'http://shaarli/subfolder/controller/?searchtag=abc'
39 ];
40
41 $assignedVariables = [];
42 $this->assignTemplateVars($assignedVariables);
43
44 $url = 'http://url.tld/other?part=3&utm_ad=pay#hash';
45 $expectedUrl = str_replace('&utm_ad=pay', '', $url);
46 $remoteTitle = 'Remote Title';
47 $remoteDesc = 'Sometimes the meta description is relevant.';
48 $remoteTags = 'abc def';
49
50 $request = $this->createMock(Request::class);
51 $request->method('getParam')->willReturnCallback(function (string $key) use ($url): ?string {
52 return $key === 'post' ? $url : null;
53 });
54 $response = new Response();
55
56 $this->container->httpAccess
57 ->expects(static::once())
58 ->method('getCurlDownloadCallback')
59 ->willReturnCallback(
60 function (&$charset, &$title, &$description, &$tags) use (
61 $remoteTitle,
62 $remoteDesc,
63 $remoteTags
64 ): callable {
65 return function () use (
66 &$charset,
67 &$title,
68 &$description,
69 &$tags,
70 $remoteTitle,
71 $remoteDesc,
72 $remoteTags
73 ): void {
74 $charset = 'ISO-8859-1';
75 $title = $remoteTitle;
76 $description = $remoteDesc;
77 $tags = $remoteTags;
78 };
79 }
80 )
81 ;
82 $this->container->httpAccess
83 ->expects(static::once())
84 ->method('getHttpResponse')
85 ->with($expectedUrl, 30, 4194304)
86 ->willReturnCallback(function($url, $timeout, $maxBytes, $callback): void {
87 $callback();
88 })
89 ;
90
91 $this->container->bookmarkService
92 ->expects(static::once())
93 ->method('bookmarksCountPerTag')
94 ->willReturn($tags = ['tag1' => 2, 'tag2' => 1])
95 ;
96
97 // Make sure that PluginManager hook is triggered
98 $this->container->pluginManager
99 ->expects(static::at(0))
100 ->method('executeHooks')
101 ->willReturnCallback(function (string $hook, array $data) use ($remoteTitle, $remoteDesc): array {
102 static::assertSame('render_editlink', $hook);
103 static::assertSame($remoteTitle, $data['link']['title']);
104 static::assertSame($remoteDesc, $data['link']['description']);
105
106 return $data;
107 })
108 ;
109
110 $result = $this->controller->displayCreateForm($request, $response);
111
112 static::assertSame(200, $result->getStatusCode());
113 static::assertSame('editlink', (string) $result->getBody());
114
115 static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']);
116
117 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
118 static::assertSame($remoteTitle, $assignedVariables['link']['title']);
119 static::assertSame($remoteDesc, $assignedVariables['link']['description']);
120 static::assertSame($remoteTags, $assignedVariables['link']['tags']);
121 static::assertFalse($assignedVariables['link']['private']);
122
123 static::assertTrue($assignedVariables['link_is_new']);
124 static::assertSame($referer, $assignedVariables['http_referer']);
125 static::assertSame($tags, $assignedVariables['tags']);
126 static::assertArrayHasKey('source', $assignedVariables);
127 static::assertArrayHasKey('default_private_links', $assignedVariables);
128 }
129
130 /**
131 * Test displaying bookmark create form
132 * Ensure all available query parameters are handled properly.
133 */
134 public function testDisplayCreateFormWithFullParameters(): void
135 {
136 $assignedVariables = [];
137 $this->assignTemplateVars($assignedVariables);
138
139 $parameters = [
140 'post' => 'http://url.tld/other?part=3&utm_ad=pay#hash',
141 'title' => 'Provided Title',
142 'description' => 'Provided description.',
143 'tags' => 'abc def',
144 'private' => '1',
145 'source' => 'apps',
146 ];
147 $expectedUrl = str_replace('&utm_ad=pay', '', $parameters['post']);
148
149 $request = $this->createMock(Request::class);
150 $request
151 ->method('getParam')
152 ->willReturnCallback(function (string $key) use ($parameters): ?string {
153 return $parameters[$key] ?? null;
154 });
155 $response = new Response();
156
157 $result = $this->controller->displayCreateForm($request, $response);
158
159 static::assertSame(200, $result->getStatusCode());
160 static::assertSame('editlink', (string) $result->getBody());
161
162 static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']);
163
164 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
165 static::assertSame($parameters['title'], $assignedVariables['link']['title']);
166 static::assertSame($parameters['description'], $assignedVariables['link']['description']);
167 static::assertSame($parameters['tags'], $assignedVariables['link']['tags']);
168 static::assertTrue($assignedVariables['link']['private']);
169 static::assertTrue($assignedVariables['link_is_new']);
170 static::assertSame($parameters['source'], $assignedVariables['source']);
171 }
172
173 /**
174 * Test displaying bookmark create form
175 * Without any parameter.
176 */
177 public function testDisplayCreateFormEmpty(): void
178 {
179 $assignedVariables = [];
180 $this->assignTemplateVars($assignedVariables);
181
182 $request = $this->createMock(Request::class);
183 $response = new Response();
184
185 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
186 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
187
188 $result = $this->controller->displayCreateForm($request, $response);
189
190 static::assertSame(200, $result->getStatusCode());
191 static::assertSame('editlink', (string) $result->getBody());
192 static::assertSame('', $assignedVariables['link']['url']);
193 static::assertSame('Note: ', $assignedVariables['link']['title']);
194 static::assertSame('', $assignedVariables['link']['description']);
195 static::assertSame('', $assignedVariables['link']['tags']);
196 static::assertFalse($assignedVariables['link']['private']);
197 static::assertTrue($assignedVariables['link_is_new']);
198 }
199
200 /**
201 * Test displaying bookmark create form
202 * URL not using HTTP protocol: do not try to retrieve the title
203 */
204 public function testDisplayCreateFormNotHttp(): void
205 {
206 $assignedVariables = [];
207 $this->assignTemplateVars($assignedVariables);
208
209 $url = 'magnet://kubuntu.torrent';
210 $request = $this->createMock(Request::class);
211 $request
212 ->method('getParam')
213 ->willReturnCallback(function (string $key) use ($url): ?string {
214 return $key === 'post' ? $url : null;
215 });
216 $response = new Response();
217
218 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
219 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
220
221 $result = $this->controller->displayCreateForm($request, $response);
222
223 static::assertSame(200, $result->getStatusCode());
224 static::assertSame('editlink', (string) $result->getBody());
225 static::assertSame($url, $assignedVariables['link']['url']);
226 static::assertTrue($assignedVariables['link_is_new']);
227 }
228
229 /**
230 * Test displaying bookmark create form
231 * When markdown formatter is enabled, the no markdown tag should be added to existing tags.
232 */
233 public function testDisplayCreateFormWithMarkdownEnabled(): void
234 {
235 $assignedVariables = [];
236 $this->assignTemplateVars($assignedVariables);
237
238 $this->container->conf = $this->createMock(ConfigManager::class);
239 $this->container->conf
240 ->expects(static::atLeastOnce())
241 ->method('get')->willReturnCallback(function (string $key): ?string {
242 if ($key === 'formatter') {
243 return 'markdown';
244 }
245
246 return $key;
247 })
248 ;
249
250 $request = $this->createMock(Request::class);
251 $response = new Response();
252
253 $result = $this->controller->displayCreateForm($request, $response);
254
255 static::assertSame(200, $result->getStatusCode());
256 static::assertSame('editlink', (string) $result->getBody());
257 static::assertSame(['nomarkdown' => 1], $assignedVariables['tags']);
258 }
259
260 /**
261 * Test displaying bookmark create form
262 * When an existing URL is submitted, we want to edit the existing link.
263 */
264 public function testDisplayCreateFormWithExistingUrl(): void
265 {
266 $assignedVariables = [];
267 $this->assignTemplateVars($assignedVariables);
268
269 $url = 'http://url.tld/other?part=3&utm_ad=pay#hash';
270 $expectedUrl = str_replace('&utm_ad=pay', '', $url);
271
272 $request = $this->createMock(Request::class);
273 $request
274 ->method('getParam')
275 ->willReturnCallback(function (string $key) use ($url): ?string {
276 return $key === 'post' ? $url : null;
277 });
278 $response = new Response();
279
280 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
281 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
282
283 $this->container->bookmarkService
284 ->expects(static::once())
285 ->method('findByUrl')
286 ->with($expectedUrl)
287 ->willReturn(
288 (new Bookmark())
289 ->setId($id = 23)
290 ->setUrl($expectedUrl)
291 ->setTitle($title = 'Bookmark Title')
292 ->setDescription($description = 'Bookmark description.')
293 ->setTags($tags = ['abc', 'def'])
294 ->setPrivate(true)
295 ->setCreated($createdAt = new \DateTime('2020-06-10 18:45:44'))
296 )
297 ;
298
299 $result = $this->controller->displayCreateForm($request, $response);
300
301 static::assertSame(200, $result->getStatusCode());
302 static::assertSame('editlink', (string) $result->getBody());
303
304 static::assertSame('Edit Shaare - Shaarli', $assignedVariables['pagetitle']);
305 static::assertFalse($assignedVariables['link_is_new']);
306
307 static::assertSame($id, $assignedVariables['link']['id']);
308 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
309 static::assertSame($title, $assignedVariables['link']['title']);
310 static::assertSame($description, $assignedVariables['link']['description']);
311 static::assertSame(implode(' ', $tags), $assignedVariables['link']['tags']);
312 static::assertTrue($assignedVariables['link']['private']);
313 static::assertSame($createdAt, $assignedVariables['link']['created']);
314 }
315}
diff --git a/tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php b/tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php
new file mode 100644
index 00000000..1a1cdcf3
--- /dev/null
+++ b/tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php
@@ -0,0 +1,155 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ManageShaareControllerTest;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
10use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
11use Shaarli\Front\Controller\Admin\ManageShaareController;
12use Shaarli\Http\HttpAccess;
13use Shaarli\Security\SessionManager;
14use Slim\Http\Request;
15use Slim\Http\Response;
16
17class DisplayEditFormTest extends TestCase
18{
19 use FrontAdminControllerMockHelper;
20
21 /** @var ManageShaareController */
22 protected $controller;
23
24 public function setUp(): void
25 {
26 $this->createContainer();
27
28 $this->container->httpAccess = $this->createMock(HttpAccess::class);
29 $this->controller = new ManageShaareController($this->container);
30 }
31
32 /**
33 * Test displaying bookmark edit form
34 * When an existing ID is provided, ensure that default workflow works properly.
35 */
36 public function testDisplayEditFormDefault(): void
37 {
38 $assignedVariables = [];
39 $this->assignTemplateVars($assignedVariables);
40
41 $id = 11;
42
43 $request = $this->createMock(Request::class);
44 $response = new Response();
45
46 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
47 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
48
49 $this->container->bookmarkService
50 ->expects(static::once())
51 ->method('get')
52 ->with($id)
53 ->willReturn(
54 (new Bookmark())
55 ->setId($id)
56 ->setUrl($url = 'http://domain.tld')
57 ->setTitle($title = 'Bookmark Title')
58 ->setDescription($description = 'Bookmark description.')
59 ->setTags($tags = ['abc', 'def'])
60 ->setPrivate(true)
61 ->setCreated($createdAt = new \DateTime('2020-06-10 18:45:44'))
62 )
63 ;
64
65 $result = $this->controller->displayEditForm($request, $response, ['id' => (string) $id]);
66
67 static::assertSame(200, $result->getStatusCode());
68 static::assertSame('editlink', (string) $result->getBody());
69
70 static::assertSame('Edit Shaare - Shaarli', $assignedVariables['pagetitle']);
71 static::assertFalse($assignedVariables['link_is_new']);
72
73 static::assertSame($id, $assignedVariables['link']['id']);
74 static::assertSame($url, $assignedVariables['link']['url']);
75 static::assertSame($title, $assignedVariables['link']['title']);
76 static::assertSame($description, $assignedVariables['link']['description']);
77 static::assertSame(implode(' ', $tags), $assignedVariables['link']['tags']);
78 static::assertTrue($assignedVariables['link']['private']);
79 static::assertSame($createdAt, $assignedVariables['link']['created']);
80 }
81
82 /**
83 * Test displaying bookmark edit form
84 * Invalid ID provided.
85 */
86 public function testDisplayEditFormInvalidId(): void
87 {
88 $id = 'invalid';
89
90 $request = $this->createMock(Request::class);
91 $response = new Response();
92
93 $this->container->sessionManager
94 ->expects(static::once())
95 ->method('setSessionParameter')
96 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier invalid could not be found.'])
97 ;
98
99 $result = $this->controller->displayEditForm($request, $response, ['id' => $id]);
100
101 static::assertSame(302, $result->getStatusCode());
102 static::assertSame(['/subfolder/'], $result->getHeader('location'));
103 }
104
105 /**
106 * Test displaying bookmark edit form
107 * ID not provided.
108 */
109 public function testDisplayEditFormIdNotProvided(): void
110 {
111 $request = $this->createMock(Request::class);
112 $response = new Response();
113
114 $this->container->sessionManager
115 ->expects(static::once())
116 ->method('setSessionParameter')
117 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier could not be found.'])
118 ;
119
120 $result = $this->controller->displayEditForm($request, $response, []);
121
122 static::assertSame(302, $result->getStatusCode());
123 static::assertSame(['/subfolder/'], $result->getHeader('location'));
124 }
125
126 /**
127 * Test displaying bookmark edit form
128 * Bookmark not found.
129 */
130 public function testDisplayEditFormBookmarkNotFound(): void
131 {
132 $id = 123;
133
134 $request = $this->createMock(Request::class);
135 $response = new Response();
136
137 $this->container->bookmarkService
138 ->expects(static::once())
139 ->method('get')
140 ->with($id)
141 ->willThrowException(new BookmarkNotFoundException())
142 ;
143
144 $this->container->sessionManager
145 ->expects(static::once())
146 ->method('setSessionParameter')
147 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 123 could not be found.'])
148 ;
149
150 $result = $this->controller->displayEditForm($request, $response, ['id' => (string) $id]);
151
152 static::assertSame(302, $result->getStatusCode());
153 static::assertSame(['/subfolder/'], $result->getHeader('location'));
154 }
155}
diff --git a/tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php
new file mode 100644
index 00000000..1607b475
--- /dev/null
+++ b/tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php
@@ -0,0 +1,145 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ManageShaareControllerTest;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
10use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
11use Shaarli\Front\Controller\Admin\ManageShaareController;
12use Shaarli\Http\HttpAccess;
13use Shaarli\Security\SessionManager;
14use Slim\Http\Request;
15use Slim\Http\Response;
16
17class PinBookmarkTest extends TestCase
18{
19 use FrontAdminControllerMockHelper;
20
21 /** @var ManageShaareController */
22 protected $controller;
23
24 public function setUp(): void
25 {
26 $this->createContainer();
27
28 $this->container->httpAccess = $this->createMock(HttpAccess::class);
29 $this->controller = new ManageShaareController($this->container);
30 }
31
32 /**
33 * Test pin bookmark - with valid input
34 *
35 * @dataProvider initialStickyValuesProvider()
36 */
37 public function testPinBookmarkIsStickyNull(?bool $sticky, bool $expectedValue): void
38 {
39 $id = 123;
40
41 $request = $this->createMock(Request::class);
42 $response = new Response();
43
44 $bookmark = (new Bookmark())
45 ->setId(123)
46 ->setUrl('http://domain.tld')
47 ->setTitle('Title 123')
48 ->setSticky($sticky)
49 ;
50
51 $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark);
52 $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, true);
53
54 // Make sure that PluginManager hook is triggered
55 $this->container->pluginManager
56 ->expects(static::once())
57 ->method('executeHooks')
58 ->with('save_link')
59 ;
60
61 $result = $this->controller->pinBookmark($request, $response, ['id' => (string) $id]);
62
63 static::assertSame(302, $result->getStatusCode());
64 static::assertSame(['/subfolder/'], $result->getHeader('location'));
65
66 static::assertSame($expectedValue, $bookmark->isSticky());
67 }
68
69 public function initialStickyValuesProvider(): array
70 {
71 // [initialStickyState, isStickyAfterPin]
72 return [[null, true], [false, true], [true, false]];
73 }
74
75 /**
76 * Test pin bookmark - invalid bookmark ID
77 */
78 public function testDisplayEditFormInvalidId(): void
79 {
80 $id = 'invalid';
81
82 $request = $this->createMock(Request::class);
83 $response = new Response();
84
85 $this->container->sessionManager
86 ->expects(static::once())
87 ->method('setSessionParameter')
88 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier invalid could not be found.'])
89 ;
90
91 $result = $this->controller->pinBookmark($request, $response, ['id' => $id]);
92
93 static::assertSame(302, $result->getStatusCode());
94 static::assertSame(['/subfolder/'], $result->getHeader('location'));
95 }
96
97 /**
98 * Test pin bookmark - Bookmark ID not provided
99 */
100 public function testDisplayEditFormIdNotProvided(): void
101 {
102 $request = $this->createMock(Request::class);
103 $response = new Response();
104
105 $this->container->sessionManager
106 ->expects(static::once())
107 ->method('setSessionParameter')
108 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier could not be found.'])
109 ;
110
111 $result = $this->controller->pinBookmark($request, $response, []);
112
113 static::assertSame(302, $result->getStatusCode());
114 static::assertSame(['/subfolder/'], $result->getHeader('location'));
115 }
116
117 /**
118 * Test pin bookmark - bookmark not found
119 */
120 public function testDisplayEditFormBookmarkNotFound(): void
121 {
122 $id = 123;
123
124 $request = $this->createMock(Request::class);
125 $response = new Response();
126
127 $this->container->bookmarkService
128 ->expects(static::once())
129 ->method('get')
130 ->with($id)
131 ->willThrowException(new BookmarkNotFoundException())
132 ;
133
134 $this->container->sessionManager
135 ->expects(static::once())
136 ->method('setSessionParameter')
137 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 123 could not be found.'])
138 ;
139
140 $result = $this->controller->pinBookmark($request, $response, ['id' => (string) $id]);
141
142 static::assertSame(302, $result->getStatusCode());
143 static::assertSame(['/subfolder/'], $result->getHeader('location'));
144 }
145}
diff --git a/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php
new file mode 100644
index 00000000..dabcd60d
--- /dev/null
+++ b/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php
@@ -0,0 +1,282 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ManageShaareControllerTest;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Config\ConfigManager;
10use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
11use Shaarli\Front\Controller\Admin\ManageShaareController;
12use Shaarli\Front\Exception\WrongTokenException;
13use Shaarli\Http\HttpAccess;
14use Shaarli\Security\SessionManager;
15use Shaarli\Thumbnailer;
16use Slim\Http\Request;
17use Slim\Http\Response;
18
19class SaveBookmarkTest extends TestCase
20{
21 use FrontAdminControllerMockHelper;
22
23 /** @var ManageShaareController */
24 protected $controller;
25
26 public function setUp(): void
27 {
28 $this->createContainer();
29
30 $this->container->httpAccess = $this->createMock(HttpAccess::class);
31 $this->controller = new ManageShaareController($this->container);
32 }
33
34 /**
35 * Test save a new bookmark
36 */
37 public function testSaveBookmark(): void
38 {
39 $id = 21;
40 $parameters = [
41 'lf_url' => 'http://url.tld/other?part=3#hash',
42 'lf_title' => 'Provided Title',
43 'lf_description' => 'Provided description.',
44 'lf_tags' => 'abc def',
45 'lf_private' => '1',
46 'returnurl' => 'http://shaarli.tld/subfolder/admin/add-shaare'
47 ];
48
49 $request = $this->createMock(Request::class);
50 $request
51 ->method('getParam')
52 ->willReturnCallback(function (string $key) use ($parameters): ?string {
53 return $parameters[$key] ?? null;
54 })
55 ;
56 $response = new Response();
57
58 $checkBookmark = function (Bookmark $bookmark) use ($parameters) {
59 static::assertSame($parameters['lf_url'], $bookmark->getUrl());
60 static::assertSame($parameters['lf_title'], $bookmark->getTitle());
61 static::assertSame($parameters['lf_description'], $bookmark->getDescription());
62 static::assertSame($parameters['lf_tags'], $bookmark->getTagsString());
63 static::assertTrue($bookmark->isPrivate());
64 };
65
66 $this->container->bookmarkService
67 ->expects(static::once())
68 ->method('addOrSet')
69 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void {
70 static::assertFalse($save);
71
72 $checkBookmark($bookmark);
73
74 $bookmark->setId($id);
75 })
76 ;
77 $this->container->bookmarkService
78 ->expects(static::once())
79 ->method('set')
80 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void {
81 static::assertTrue($save);
82
83 $checkBookmark($bookmark);
84
85 static::assertSame($id, $bookmark->getId());
86 })
87 ;
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) use ($parameters, $id): array {
94 static::assertSame('save_link', $hook);
95
96 static::assertSame($id, $data['id']);
97 static::assertSame($parameters['lf_url'], $data['url']);
98 static::assertSame($parameters['lf_title'], $data['title']);
99 static::assertSame($parameters['lf_description'], $data['description']);
100 static::assertSame($parameters['lf_tags'], $data['tags']);
101 static::assertTrue($data['private']);
102
103 return $data;
104 })
105 ;
106
107 $result = $this->controller->save($request, $response);
108
109 static::assertSame(302, $result->getStatusCode());
110 static::assertRegExp('@/subfolder/#[\w\-]{6}@', $result->getHeader('location')[0]);
111 }
112
113
114 /**
115 * Test save an existing bookmark
116 */
117 public function testSaveExistingBookmark(): void
118 {
119 $id = 21;
120 $parameters = [
121 'lf_id' => (string) $id,
122 'lf_url' => 'http://url.tld/other?part=3#hash',
123 'lf_title' => 'Provided Title',
124 'lf_description' => 'Provided description.',
125 'lf_tags' => 'abc def',
126 'lf_private' => '1',
127 'returnurl' => 'http://shaarli.tld/subfolder/?page=2'
128 ];
129
130 $request = $this->createMock(Request::class);
131 $request
132 ->method('getParam')
133 ->willReturnCallback(function (string $key) use ($parameters): ?string {
134 return $parameters[$key] ?? null;
135 })
136 ;
137 $response = new Response();
138
139 $checkBookmark = function (Bookmark $bookmark) use ($parameters, $id) {
140 static::assertSame($id, $bookmark->getId());
141 static::assertSame($parameters['lf_url'], $bookmark->getUrl());
142 static::assertSame($parameters['lf_title'], $bookmark->getTitle());
143 static::assertSame($parameters['lf_description'], $bookmark->getDescription());
144 static::assertSame($parameters['lf_tags'], $bookmark->getTagsString());
145 static::assertTrue($bookmark->isPrivate());
146 };
147
148 $this->container->bookmarkService->expects(static::atLeastOnce())->method('exists')->willReturn(true);
149 $this->container->bookmarkService
150 ->expects(static::once())
151 ->method('get')
152 ->willReturn((new Bookmark())->setId($id)->setUrl('http://other.url'))
153 ;
154 $this->container->bookmarkService
155 ->expects(static::once())
156 ->method('addOrSet')
157 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void {
158 static::assertFalse($save);
159
160 $checkBookmark($bookmark);
161 })
162 ;
163 $this->container->bookmarkService
164 ->expects(static::once())
165 ->method('set')
166 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void {
167 static::assertTrue($save);
168
169 $checkBookmark($bookmark);
170
171 static::assertSame($id, $bookmark->getId());
172 })
173 ;
174
175 // Make sure that PluginManager hook is triggered
176 $this->container->pluginManager
177 ->expects(static::at(0))
178 ->method('executeHooks')
179 ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array {
180 static::assertSame('save_link', $hook);
181
182 static::assertSame($id, $data['id']);
183 static::assertSame($parameters['lf_url'], $data['url']);
184 static::assertSame($parameters['lf_title'], $data['title']);
185 static::assertSame($parameters['lf_description'], $data['description']);
186 static::assertSame($parameters['lf_tags'], $data['tags']);
187 static::assertTrue($data['private']);
188
189 return $data;
190 })
191 ;
192
193 $result = $this->controller->save($request, $response);
194
195 static::assertSame(302, $result->getStatusCode());
196 static::assertRegExp('@/subfolder/\?page=2#[\w\-]{6}@', $result->getHeader('location')[0]);
197 }
198
199 /**
200 * Test save a bookmark - try to retrieve the thumbnail
201 */
202 public function testSaveBookmarkWithThumbnail(): void
203 {
204 $parameters = ['lf_url' => 'http://url.tld/other?part=3#hash'];
205
206 $request = $this->createMock(Request::class);
207 $request
208 ->method('getParam')
209 ->willReturnCallback(function (string $key) use ($parameters): ?string {
210 return $parameters[$key] ?? null;
211 })
212 ;
213 $response = new Response();
214
215 $this->container->conf = $this->createMock(ConfigManager::class);
216 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
217 return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default;
218 });
219
220 $this->container->thumbnailer = $this->createMock(Thumbnailer::class);
221 $this->container->thumbnailer
222 ->expects(static::once())
223 ->method('get')
224 ->with($parameters['lf_url'])
225 ->willReturn($thumb = 'http://thumb.url')
226 ;
227
228 $this->container->bookmarkService
229 ->expects(static::once())
230 ->method('addOrSet')
231 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($thumb): void {
232 static::assertSame($thumb, $bookmark->getThumbnail());
233 })
234 ;
235
236 $result = $this->controller->save($request, $response);
237
238 static::assertSame(302, $result->getStatusCode());
239 }
240
241 /**
242 * Change the password with a wrong existing password
243 */
244 public function testSaveBookmarkFromBookmarklet(): void
245 {
246 $parameters = ['source' => 'bookmarklet'];
247
248 $request = $this->createMock(Request::class);
249 $request
250 ->method('getParam')
251 ->willReturnCallback(function (string $key) use ($parameters): ?string {
252 return $parameters[$key] ?? null;
253 })
254 ;
255 $response = new Response();
256
257 $result = $this->controller->save($request, $response);
258
259 static::assertSame(200, $result->getStatusCode());
260 static::assertSame('<script>self.close();</script>', (string) $result->getBody());
261 }
262
263 /**
264 * Change the password with a wrong existing password
265 */
266 public function testSaveBookmarkWrongToken(): void
267 {
268 $this->container->sessionManager = $this->createMock(SessionManager::class);
269 $this->container->sessionManager->method('checkToken')->willReturn(false);
270
271 $this->container->bookmarkService->expects(static::never())->method('addOrSet');
272 $this->container->bookmarkService->expects(static::never())->method('set');
273
274 $request = $this->createMock(Request::class);
275 $response = new Response();
276
277 $this->expectException(WrongTokenException::class);
278
279 $this->controller->save($request, $response);
280 }
281
282}
diff --git a/tests/front/controller/admin/ManageTagControllerTest.php b/tests/front/controller/admin/ManageTagControllerTest.php
new file mode 100644
index 00000000..09ba0b4b
--- /dev/null
+++ b/tests/front/controller/admin/ManageTagControllerTest.php
@@ -0,0 +1,272 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Bookmark\BookmarkFilter;
10use Shaarli\Front\Exception\WrongTokenException;
11use Shaarli\Security\SessionManager;
12use Slim\Http\Request;
13use Slim\Http\Response;
14
15class ManageTagControllerTest extends TestCase
16{
17 use FrontAdminControllerMockHelper;
18
19 /** @var ManageTagController */
20 protected $controller;
21
22 public function setUp(): void
23 {
24 $this->createContainer();
25
26 $this->controller = new ManageTagController($this->container);
27 }
28
29 /**
30 * Test displaying manage tag page
31 */
32 public function testIndex(): void
33 {
34 $assignedVariables = [];
35 $this->assignTemplateVars($assignedVariables);
36
37 $request = $this->createMock(Request::class);
38 $request->method('getParam')->with('fromtag')->willReturn('fromtag');
39 $response = new Response();
40
41 $result = $this->controller->index($request, $response);
42
43 static::assertSame(200, $result->getStatusCode());
44 static::assertSame('changetag', (string) $result->getBody());
45
46 static::assertSame('fromtag', $assignedVariables['fromtag']);
47 static::assertSame('Manage tags - Shaarli', $assignedVariables['pagetitle']);
48 }
49
50 /**
51 * Test posting a tag update - rename tag - valid info provided.
52 */
53 public function testSaveRenameTagValid(): void
54 {
55 $session = [];
56 $this->assignSessionVars($session);
57
58 $requestParameters = [
59 'renametag' => 'rename',
60 'fromtag' => 'old-tag',
61 'totag' => 'new-tag',
62 ];
63 $request = $this->createMock(Request::class);
64 $request
65 ->expects(static::atLeastOnce())
66 ->method('getParam')
67 ->willReturnCallback(function (string $key) use ($requestParameters): ?string {
68 return $requestParameters[$key] ?? null;
69 })
70 ;
71 $response = new Response();
72
73 $bookmark1 = $this->createMock(Bookmark::class);
74 $bookmark2 = $this->createMock(Bookmark::class);
75 $this->container->bookmarkService
76 ->expects(static::once())
77 ->method('search')
78 ->with(['searchtags' => 'old-tag'], BookmarkFilter::$ALL, true)
79 ->willReturnCallback(function () use ($bookmark1, $bookmark2): array {
80 $bookmark1->expects(static::once())->method('renameTag')->with('old-tag', 'new-tag');
81 $bookmark2->expects(static::once())->method('renameTag')->with('old-tag', 'new-tag');
82
83 return [$bookmark1, $bookmark2];
84 })
85 ;
86 $this->container->bookmarkService
87 ->expects(static::exactly(2))
88 ->method('set')
89 ->withConsecutive([$bookmark1, false], [$bookmark2, false])
90 ;
91 $this->container->bookmarkService->expects(static::once())->method('save');
92
93 $result = $this->controller->save($request, $response);
94
95 static::assertSame(302, $result->getStatusCode());
96 static::assertSame(['/subfolder/?searchtags=new-tag'], $result->getHeader('location'));
97
98 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
99 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
100 static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
101 static::assertSame(['The tag was renamed in 2 bookmarks.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
102 }
103
104 /**
105 * Test posting a tag update - delete tag - valid info provided.
106 */
107 public function testSaveDeleteTagValid(): void
108 {
109 $session = [];
110 $this->assignSessionVars($session);
111
112 $requestParameters = [
113 'deletetag' => 'delete',
114 'fromtag' => 'old-tag',
115 ];
116 $request = $this->createMock(Request::class);
117 $request
118 ->expects(static::atLeastOnce())
119 ->method('getParam')
120 ->willReturnCallback(function (string $key) use ($requestParameters): ?string {
121 return $requestParameters[$key] ?? null;
122 })
123 ;
124 $response = new Response();
125
126 $bookmark1 = $this->createMock(Bookmark::class);
127 $bookmark2 = $this->createMock(Bookmark::class);
128 $this->container->bookmarkService
129 ->expects(static::once())
130 ->method('search')
131 ->with(['searchtags' => 'old-tag'], BookmarkFilter::$ALL, true)
132 ->willReturnCallback(function () use ($bookmark1, $bookmark2): array {
133 $bookmark1->expects(static::once())->method('deleteTag')->with('old-tag');
134 $bookmark2->expects(static::once())->method('deleteTag')->with('old-tag');
135
136 return [$bookmark1, $bookmark2];
137 })
138 ;
139 $this->container->bookmarkService
140 ->expects(static::exactly(2))
141 ->method('set')
142 ->withConsecutive([$bookmark1, false], [$bookmark2, false])
143 ;
144 $this->container->bookmarkService->expects(static::once())->method('save');
145
146 $result = $this->controller->save($request, $response);
147
148 static::assertSame(302, $result->getStatusCode());
149 static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location'));
150
151 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
152 static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
153 static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
154 static::assertSame(['The tag was removed from 2 bookmarks.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]);
155 }
156
157 /**
158 * Test posting a tag update - wrong token.
159 */
160 public function testSaveWrongToken(): void
161 {
162 $this->container->sessionManager = $this->createMock(SessionManager::class);
163 $this->container->sessionManager->method('checkToken')->willReturn(false);
164
165 $this->container->conf->expects(static::never())->method('set');
166 $this->container->conf->expects(static::never())->method('write');
167
168 $request = $this->createMock(Request::class);
169 $response = new Response();
170
171 $this->expectException(WrongTokenException::class);
172
173 $this->controller->save($request, $response);
174 }
175
176 /**
177 * Test posting a tag update - rename tag - missing "FROM" tag.
178 */
179 public function testSaveRenameTagMissingFrom(): void
180 {
181 $session = [];
182 $this->assignSessionVars($session);
183
184 $requestParameters = [
185 'renametag' => 'rename',
186 ];
187 $request = $this->createMock(Request::class);
188 $request
189 ->expects(static::atLeastOnce())
190 ->method('getParam')
191 ->willReturnCallback(function (string $key) use ($requestParameters): ?string {
192 return $requestParameters[$key] ?? null;
193 })
194 ;
195 $response = new Response();
196
197 $result = $this->controller->save($request, $response);
198
199 static::assertSame(302, $result->getStatusCode());
200 static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location'));
201
202 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
203 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
204 static::assertArrayNotHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
205 static::assertSame(['Invalid tags provided.'], $session[SessionManager::KEY_WARNING_MESSAGES]);
206 }
207
208 /**
209 * Test posting a tag update - delete tag - missing "FROM" tag.
210 */
211 public function testSaveDeleteTagMissingFrom(): void
212 {
213 $session = [];
214 $this->assignSessionVars($session);
215
216 $requestParameters = [
217 'deletetag' => 'delete',
218 ];
219 $request = $this->createMock(Request::class);
220 $request
221 ->expects(static::atLeastOnce())
222 ->method('getParam')
223 ->willReturnCallback(function (string $key) use ($requestParameters): ?string {
224 return $requestParameters[$key] ?? null;
225 })
226 ;
227 $response = new Response();
228
229 $result = $this->controller->save($request, $response);
230
231 static::assertSame(302, $result->getStatusCode());
232 static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location'));
233
234 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
235 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
236 static::assertArrayNotHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
237 static::assertSame(['Invalid tags provided.'], $session[SessionManager::KEY_WARNING_MESSAGES]);
238 }
239
240 /**
241 * Test posting a tag update - rename tag - missing "TO" tag.
242 */
243 public function testSaveRenameTagMissingTo(): void
244 {
245 $session = [];
246 $this->assignSessionVars($session);
247
248 $requestParameters = [
249 'renametag' => 'rename',
250 'fromtag' => 'old-tag'
251 ];
252 $request = $this->createMock(Request::class);
253 $request
254 ->expects(static::atLeastOnce())
255 ->method('getParam')
256 ->willReturnCallback(function (string $key) use ($requestParameters): ?string {
257 return $requestParameters[$key] ?? null;
258 })
259 ;
260 $response = new Response();
261
262 $result = $this->controller->save($request, $response);
263
264 static::assertSame(302, $result->getStatusCode());
265 static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location'));
266
267 static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session);
268 static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session);
269 static::assertArrayNotHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session);
270 static::assertSame(['Invalid tags provided.'], $session[SessionManager::KEY_WARNING_MESSAGES]);
271 }
272}
diff --git a/tests/front/controller/admin/PasswordControllerTest.php b/tests/front/controller/admin/PasswordControllerTest.php
new file mode 100644
index 00000000..9a01089e
--- /dev/null
+++ b/tests/front/controller/admin/PasswordControllerTest.php
@@ -0,0 +1,203 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Config\ConfigManager;
9use Shaarli\Front\Exception\OpenShaarliPasswordException;
10use Shaarli\Front\Exception\WrongTokenException;
11use Shaarli\Security\SessionManager;
12use Slim\Http\Request;
13use Slim\Http\Response;
14
15class PasswordControllerTest extends TestCase
16{
17 use FrontAdminControllerMockHelper;
18
19 /** @var PasswordController */
20 protected $controller;
21
22 /** @var mixed[] Variables assigned to the template */
23 protected $assignedVariables = [];
24
25 public function setUp(): void
26 {
27 $this->createContainer();
28 $this->assignTemplateVars($this->assignedVariables);
29
30 $this->controller = new PasswordController($this->container);
31 }
32
33 /**
34 * Test displaying the change password page.
35 */
36 public function testGetPage(): void
37 {
38 $request = $this->createMock(Request::class);
39 $response = new Response();
40
41 $result = $this->controller->index($request, $response);
42
43 static::assertSame(200, $result->getStatusCode());
44 static::assertSame('changepassword', (string) $result->getBody());
45 static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']);
46 }
47
48 /**
49 * Change the password with valid parameters
50 */
51 public function testPostNewPasswordDefault(): void
52 {
53 $request = $this->createMock(Request::class);
54 $request->method('getParam')->willReturnCallback(function (string $key): string {
55 if ('oldpassword' === $key) {
56 return 'old';
57 }
58 if ('setpassword' === $key) {
59 return 'new';
60 }
61
62 return $key;
63 });
64 $response = new Response();
65
66 $this->container->conf = $this->createMock(ConfigManager::class);
67 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
68 if ('credentials.hash' === $key) {
69 return sha1('old' . 'credentials.login' . 'credentials.salt');
70 }
71
72 return strpos($key, 'credentials') !== false ? $key : $default;
73 });
74 $this->container->conf->expects(static::once())->method('write')->with(true);
75
76 $this->container->conf
77 ->method('set')
78 ->willReturnCallback(function (string $key, string $value) {
79 if ('credentials.hash' === $key) {
80 static::assertSame(sha1('new' . 'credentials.login' . 'credentials.salt'), $value);
81 }
82 })
83 ;
84
85 $result = $this->controller->change($request, $response);
86
87 static::assertSame(200, $result->getStatusCode());
88 static::assertSame('changepassword', (string) $result->getBody());
89 static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']);
90 }
91
92 /**
93 * Change the password with a wrong existing password
94 */
95 public function testPostNewPasswordWrongOldPassword(): void
96 {
97 $request = $this->createMock(Request::class);
98 $request->method('getParam')->willReturnCallback(function (string $key): string {
99 if ('oldpassword' === $key) {
100 return 'wrong';
101 }
102 if ('setpassword' === $key) {
103 return 'new';
104 }
105
106 return $key;
107 });
108 $response = new Response();
109
110 $this->container->conf = $this->createMock(ConfigManager::class);
111 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
112 if ('credentials.hash' === $key) {
113 return sha1('old' . 'credentials.login' . 'credentials.salt');
114 }
115
116 return strpos($key, 'credentials') !== false ? $key : $default;
117 });
118
119 $this->container->conf->expects(static::never())->method('set');
120 $this->container->conf->expects(static::never())->method('write');
121
122 $this->container->sessionManager
123 ->expects(static::once())
124 ->method('setSessionParameter')
125 ->with(SessionManager::KEY_ERROR_MESSAGES, ['The old password is not correct.'])
126 ;
127
128 $result = $this->controller->change($request, $response);
129
130 static::assertSame(400, $result->getStatusCode());
131 static::assertSame('changepassword', (string) $result->getBody());
132 static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']);
133 }
134
135 /**
136 * Change the password with a wrong existing password
137 */
138 public function testPostNewPasswordWrongToken(): void
139 {
140 $this->container->sessionManager = $this->createMock(SessionManager::class);
141 $this->container->sessionManager->method('checkToken')->willReturn(false);
142
143 $this->container->conf->expects(static::never())->method('set');
144 $this->container->conf->expects(static::never())->method('write');
145
146 $request = $this->createMock(Request::class);
147 $response = new Response();
148
149 $this->expectException(WrongTokenException::class);
150
151 $this->controller->change($request, $response);
152 }
153
154 /**
155 * Change the password with an empty new password
156 */
157 public function testPostNewEmptyPassword(): void
158 {
159 $this->container->sessionManager
160 ->expects(static::once())
161 ->method('setSessionParameter')
162 ->with(SessionManager::KEY_ERROR_MESSAGES, ['You must provide the current and new password to change it.'])
163 ;
164
165 $this->container->conf->expects(static::never())->method('set');
166 $this->container->conf->expects(static::never())->method('write');
167
168 $request = $this->createMock(Request::class);
169 $request->method('getParam')->willReturnCallback(function (string $key): string {
170 if ('oldpassword' === $key) {
171 return 'old';
172 }
173 if ('setpassword' === $key) {
174 return '';
175 }
176
177 return $key;
178 });
179 $response = new Response();
180
181 $result = $this->controller->change($request, $response);
182
183 static::assertSame(400, $result->getStatusCode());
184 static::assertSame('changepassword', (string) $result->getBody());
185 static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']);
186 }
187
188 /**
189 * Change the password on an open shaarli
190 */
191 public function testPostNewPasswordOnOpenShaarli(): void
192 {
193 $this->container->conf = $this->createMock(ConfigManager::class);
194 $this->container->conf->method('get')->with('security.open_shaarli')->willReturn(true);
195
196 $request = $this->createMock(Request::class);
197 $response = new Response();
198
199 $this->expectException(OpenShaarliPasswordException::class);
200
201 $this->controller->change($request, $response);
202 }
203}
diff --git a/tests/front/controller/admin/PluginsControllerTest.php b/tests/front/controller/admin/PluginsControllerTest.php
new file mode 100644
index 00000000..5b59285c
--- /dev/null
+++ b/tests/front/controller/admin/PluginsControllerTest.php
@@ -0,0 +1,204 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Config\ConfigManager;
9use Shaarli\Front\Exception\WrongTokenException;
10use Shaarli\Plugin\PluginManager;
11use Shaarli\Security\SessionManager;
12use Slim\Http\Request;
13use Slim\Http\Response;
14
15class PluginsControllerTest extends TestCase
16{
17 use FrontAdminControllerMockHelper;
18
19 const PLUGIN_NAMES = ['plugin1', 'plugin2', 'plugin3', 'plugin4'];
20
21 /** @var PluginsController */
22 protected $controller;
23
24 public function setUp(): void
25 {
26 $this->createContainer();
27
28 $this->controller = new PluginsController($this->container);
29
30 mkdir($path = __DIR__ . '/folder');
31 PluginManager::$PLUGINS_PATH = $path;
32 array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, static::PLUGIN_NAMES);
33 }
34
35 public function tearDown()
36 {
37 $path = __DIR__ . '/folder';
38 array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, static::PLUGIN_NAMES);
39 rmdir($path);
40 }
41
42 /**
43 * Test displaying plugins admin page
44 */
45 public function testIndex(): void
46 {
47 $assignedVariables = [];
48 $this->assignTemplateVars($assignedVariables);
49
50 $request = $this->createMock(Request::class);
51 $response = new Response();
52
53 $data = [
54 'plugin1' => ['order' => 2, 'other' => 'field'],
55 'plugin2' => ['order' => 1],
56 'plugin3' => ['order' => false, 'abc' => 'def'],
57 'plugin4' => [],
58 ];
59
60 $this->container->pluginManager
61 ->expects(static::once())
62 ->method('getPluginsMeta')
63 ->willReturn($data);
64
65 $result = $this->controller->index($request, $response);
66
67 static::assertSame(200, $result->getStatusCode());
68 static::assertSame('pluginsadmin', (string) $result->getBody());
69
70 static::assertSame('Plugin Administration - Shaarli', $assignedVariables['pagetitle']);
71 static::assertSame(
72 ['plugin2' => $data['plugin2'], 'plugin1' => $data['plugin1']],
73 $assignedVariables['enabledPlugins']
74 );
75 static::assertSame(
76 ['plugin3' => $data['plugin3'], 'plugin4' => $data['plugin4']],
77 $assignedVariables['disabledPlugins']
78 );
79 }
80
81 /**
82 * Test save plugins admin page
83 */
84 public function testSaveEnabledPlugins(): void
85 {
86 $parameters = [
87 'plugin1' => 'on',
88 'order_plugin1' => '2',
89 'plugin2' => 'on',
90 ];
91
92 $request = $this->createMock(Request::class);
93 $request
94 ->expects(static::atLeastOnce())
95 ->method('getParams')
96 ->willReturnCallback(function () use ($parameters): array {
97 return $parameters;
98 })
99 ;
100 $response = new Response();
101
102 $this->container->pluginManager
103 ->expects(static::once())
104 ->method('executeHooks')
105 ->with('save_plugin_parameters', $parameters)
106 ;
107 $this->container->conf
108 ->expects(static::atLeastOnce())
109 ->method('set')
110 ->with('general.enabled_plugins', ['plugin1', 'plugin2'])
111 ;
112
113 $result = $this->controller->save($request, $response);
114
115 static::assertSame(302, $result->getStatusCode());
116 static::assertSame(['/subfolder/admin/plugins'], $result->getHeader('location'));
117 }
118
119 /**
120 * Test save plugin parameters
121 */
122 public function testSavePluginParameters(): void
123 {
124 $parameters = [
125 'parameters_form' => true,
126 'parameter1' => 'blip',
127 'parameter2' => 'blop',
128 ];
129
130 $request = $this->createMock(Request::class);
131 $request
132 ->expects(static::atLeastOnce())
133 ->method('getParams')
134 ->willReturnCallback(function () use ($parameters): array {
135 return $parameters;
136 })
137 ;
138 $response = new Response();
139
140 $this->container->pluginManager
141 ->expects(static::once())
142 ->method('executeHooks')
143 ->with('save_plugin_parameters', $parameters)
144 ;
145 $this->container->conf
146 ->expects(static::atLeastOnce())
147 ->method('set')
148 ->withConsecutive(['plugins.parameter1', 'blip'], ['plugins.parameter2', 'blop'])
149 ;
150
151 $result = $this->controller->save($request, $response);
152
153 static::assertSame(302, $result->getStatusCode());
154 static::assertSame(['/subfolder/admin/plugins'], $result->getHeader('location'));
155 }
156
157 /**
158 * Test save plugin parameters - error encountered
159 */
160 public function testSaveWithError(): void
161 {
162 $request = $this->createMock(Request::class);
163 $response = new Response();
164
165 $this->container->conf = $this->createMock(ConfigManager::class);
166 $this->container->conf
167 ->expects(static::atLeastOnce())
168 ->method('write')
169 ->willThrowException(new \Exception($message = 'error message'))
170 ;
171
172 $this->container->sessionManager = $this->createMock(SessionManager::class);
173 $this->container->sessionManager->method('checkToken')->willReturn(true);
174 $this->container->sessionManager
175 ->expects(static::once())
176 ->method('setSessionParameter')
177 ->with(
178 SessionManager::KEY_ERROR_MESSAGES,
179 ['Error while saving plugin configuration: ' . PHP_EOL . $message]
180 )
181 ;
182
183 $result = $this->controller->save($request, $response);
184
185 static::assertSame(302, $result->getStatusCode());
186 static::assertSame(['/subfolder/admin/plugins'], $result->getHeader('location'));
187 }
188
189 /**
190 * Test save plugin parameters - wrong token
191 */
192 public function testSaveWrongToken(): void
193 {
194 $this->container->sessionManager = $this->createMock(SessionManager::class);
195 $this->container->sessionManager->method('checkToken')->willReturn(false);
196
197 $request = $this->createMock(Request::class);
198 $response = new Response();
199
200 $this->expectException(WrongTokenException::class);
201
202 $this->controller->save($request, $response);
203 }
204}
diff --git a/tests/front/controller/admin/SessionFilterControllerTest.php b/tests/front/controller/admin/SessionFilterControllerTest.php
new file mode 100644
index 00000000..d306c6e9
--- /dev/null
+++ b/tests/front/controller/admin/SessionFilterControllerTest.php
@@ -0,0 +1,177 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Security\LoginManager;
9use Shaarli\Security\SessionManager;
10use Slim\Http\Request;
11use Slim\Http\Response;
12
13class SessionFilterControllerTest extends TestCase
14{
15 use FrontAdminControllerMockHelper;
16
17 /** @var SessionFilterController */
18 protected $controller;
19
20 public function setUp(): void
21 {
22 $this->createContainer();
23
24 $this->controller = new SessionFilterController($this->container);
25 }
26
27 /**
28 * Visibility - Default call for private filter while logged in without current value
29 */
30 public function testVisibility(): void
31 {
32 $arg = ['visibility' => 'private'];
33
34 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
35
36 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
37 $this->container->sessionManager
38 ->expects(static::once())
39 ->method('setSessionParameter')
40 ->with(SessionManager::KEY_VISIBILITY, 'private')
41 ;
42
43 $request = $this->createMock(Request::class);
44 $response = new Response();
45
46 $result = $this->controller->visibility($request, $response, $arg);
47
48 static::assertInstanceOf(Response::class, $result);
49 static::assertSame(302, $result->getStatusCode());
50 static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
51 }
52
53 /**
54 * Visibility - Toggle off private visibility
55 */
56 public function testVisibilityToggleOff(): void
57 {
58 $arg = ['visibility' => 'private'];
59
60 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
61
62 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
63 $this->container->sessionManager
64 ->method('getSessionParameter')
65 ->with(SessionManager::KEY_VISIBILITY)
66 ->willReturn('private')
67 ;
68 $this->container->sessionManager
69 ->expects(static::never())
70 ->method('setSessionParameter')
71 ;
72 $this->container->sessionManager
73 ->expects(static::once())
74 ->method('deleteSessionParameter')
75 ->with(SessionManager::KEY_VISIBILITY)
76 ;
77
78 $request = $this->createMock(Request::class);
79 $response = new Response();
80
81 $result = $this->controller->visibility($request, $response, $arg);
82
83 static::assertInstanceOf(Response::class, $result);
84 static::assertSame(302, $result->getStatusCode());
85 static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
86 }
87
88 /**
89 * Visibility - Change private to public
90 */
91 public function testVisibilitySwitch(): void
92 {
93 $arg = ['visibility' => 'private'];
94
95 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
96 $this->container->sessionManager
97 ->method('getSessionParameter')
98 ->with(SessionManager::KEY_VISIBILITY)
99 ->willReturn('public')
100 ;
101 $this->container->sessionManager
102 ->expects(static::once())
103 ->method('setSessionParameter')
104 ->with(SessionManager::KEY_VISIBILITY, 'private')
105 ;
106
107 $request = $this->createMock(Request::class);
108 $response = new Response();
109
110 $result = $this->controller->visibility($request, $response, $arg);
111
112 static::assertInstanceOf(Response::class, $result);
113 static::assertSame(302, $result->getStatusCode());
114 static::assertSame(['/subfolder/'], $result->getHeader('location'));
115 }
116
117 /**
118 * Visibility - With invalid value - should remove any visibility setting
119 */
120 public function testVisibilityInvalidValue(): void
121 {
122 $arg = ['visibility' => 'test'];
123
124 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
125
126 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
127 $this->container->sessionManager
128 ->expects(static::never())
129 ->method('setSessionParameter')
130 ;
131 $this->container->sessionManager
132 ->expects(static::once())
133 ->method('deleteSessionParameter')
134 ->with(SessionManager::KEY_VISIBILITY)
135 ;
136
137 $request = $this->createMock(Request::class);
138 $response = new Response();
139
140 $result = $this->controller->visibility($request, $response, $arg);
141
142 static::assertInstanceOf(Response::class, $result);
143 static::assertSame(302, $result->getStatusCode());
144 static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
145 }
146
147 /**
148 * Visibility - Try to change visibility while logged out
149 */
150 public function testVisibilityLoggedOut(): void
151 {
152 $arg = ['visibility' => 'test'];
153
154 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
155
156 $this->container->loginManager = $this->createMock(LoginManager::class);
157 $this->container->loginManager->method('isLoggedIn')->willReturn(false);
158 $this->container->sessionManager
159 ->expects(static::never())
160 ->method('setSessionParameter')
161 ;
162 $this->container->sessionManager
163 ->expects(static::never())
164 ->method('deleteSessionParameter')
165 ->with(SessionManager::KEY_VISIBILITY)
166 ;
167
168 $request = $this->createMock(Request::class);
169 $response = new Response();
170
171 $result = $this->controller->visibility($request, $response, $arg);
172
173 static::assertInstanceOf(Response::class, $result);
174 static::assertSame(302, $result->getStatusCode());
175 static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
176 }
177}
diff --git a/tests/front/controller/admin/ShaarliAdminControllerTest.php b/tests/front/controller/admin/ShaarliAdminControllerTest.php
new file mode 100644
index 00000000..fff427cb
--- /dev/null
+++ b/tests/front/controller/admin/ShaarliAdminControllerTest.php
@@ -0,0 +1,184 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Front\Exception\WrongTokenException;
9use Shaarli\Security\SessionManager;
10use Slim\Http\Request;
11
12/**
13 * Class ShaarliControllerTest
14 *
15 * This class is used to test default behavior of ShaarliAdminController abstract class.
16 * It uses a dummy non abstract controller.
17 */
18class ShaarliAdminControllerTest extends TestCase
19{
20 use FrontAdminControllerMockHelper;
21
22 /** @var ShaarliAdminController */
23 protected $controller;
24
25 public function setUp(): void
26 {
27 $this->createContainer();
28
29 $this->controller = new class($this->container) extends ShaarliAdminController
30 {
31 public function checkToken(Request $request): bool
32 {
33 return parent::checkToken($request);
34 }
35
36 public function saveSuccessMessage(string $message): void
37 {
38 parent::saveSuccessMessage($message);
39 }
40
41 public function saveWarningMessage(string $message): void
42 {
43 parent::saveWarningMessage($message);
44 }
45
46 public function saveErrorMessage(string $message): void
47 {
48 parent::saveErrorMessage($message);
49 }
50 };
51 }
52
53 /**
54 * Trigger controller's checkToken with a valid token.
55 */
56 public function testCheckTokenWithValidToken(): void
57 {
58 $request = $this->createMock(Request::class);
59 $request->method('getParam')->with('token')->willReturn($token = '12345');
60
61 $this->container->sessionManager = $this->createMock(SessionManager::class);
62 $this->container->sessionManager->method('checkToken')->with($token)->willReturn(true);
63
64 static::assertTrue($this->controller->checkToken($request));
65 }
66
67 /**
68 * Trigger controller's checkToken with na valid token should raise an exception.
69 */
70 public function testCheckTokenWithNotValidToken(): void
71 {
72 $request = $this->createMock(Request::class);
73 $request->method('getParam')->with('token')->willReturn($token = '12345');
74
75 $this->container->sessionManager = $this->createMock(SessionManager::class);
76 $this->container->sessionManager->method('checkToken')->with($token)->willReturn(false);
77
78 $this->expectException(WrongTokenException::class);
79
80 $this->controller->checkToken($request);
81 }
82
83 /**
84 * Test saveSuccessMessage() with a first message.
85 */
86 public function testSaveSuccessMessage(): void
87 {
88 $this->container->sessionManager
89 ->expects(static::once())
90 ->method('setSessionParameter')
91 ->with(SessionManager::KEY_SUCCESS_MESSAGES, [$message = 'bravo!'])
92 ;
93
94 $this->controller->saveSuccessMessage($message);
95 }
96
97 /**
98 * Test saveSuccessMessage() with existing messages.
99 */
100 public function testSaveSuccessMessageWithExistingMessages(): void
101 {
102 $this->container->sessionManager
103 ->expects(static::once())
104 ->method('getSessionParameter')
105 ->with(SessionManager::KEY_SUCCESS_MESSAGES)
106 ->willReturn(['success1', 'success2'])
107 ;
108 $this->container->sessionManager
109 ->expects(static::once())
110 ->method('setSessionParameter')
111 ->with(SessionManager::KEY_SUCCESS_MESSAGES, ['success1', 'success2', $message = 'bravo!'])
112 ;
113
114 $this->controller->saveSuccessMessage($message);
115 }
116
117 /**
118 * Test saveWarningMessage() with a first message.
119 */
120 public function testSaveWarningMessage(): void
121 {
122 $this->container->sessionManager
123 ->expects(static::once())
124 ->method('setSessionParameter')
125 ->with(SessionManager::KEY_WARNING_MESSAGES, [$message = 'warning!'])
126 ;
127
128 $this->controller->saveWarningMessage($message);
129 }
130
131 /**
132 * Test saveWarningMessage() with existing messages.
133 */
134 public function testSaveWarningMessageWithExistingMessages(): void
135 {
136 $this->container->sessionManager
137 ->expects(static::once())
138 ->method('getSessionParameter')
139 ->with(SessionManager::KEY_WARNING_MESSAGES)
140 ->willReturn(['warning1', 'warning2'])
141 ;
142 $this->container->sessionManager
143 ->expects(static::once())
144 ->method('setSessionParameter')
145 ->with(SessionManager::KEY_WARNING_MESSAGES, ['warning1', 'warning2', $message = 'warning!'])
146 ;
147
148 $this->controller->saveWarningMessage($message);
149 }
150
151 /**
152 * Test saveErrorMessage() with a first message.
153 */
154 public function testSaveErrorMessage(): void
155 {
156 $this->container->sessionManager
157 ->expects(static::once())
158 ->method('setSessionParameter')
159 ->with(SessionManager::KEY_ERROR_MESSAGES, [$message = 'error!'])
160 ;
161
162 $this->controller->saveErrorMessage($message);
163 }
164
165 /**
166 * Test saveErrorMessage() with existing messages.
167 */
168 public function testSaveErrorMessageWithExistingMessages(): void
169 {
170 $this->container->sessionManager
171 ->expects(static::once())
172 ->method('getSessionParameter')
173 ->with(SessionManager::KEY_ERROR_MESSAGES)
174 ->willReturn(['error1', 'error2'])
175 ;
176 $this->container->sessionManager
177 ->expects(static::once())
178 ->method('setSessionParameter')
179 ->with(SessionManager::KEY_ERROR_MESSAGES, ['error1', 'error2', $message = 'error!'])
180 ;
181
182 $this->controller->saveErrorMessage($message);
183 }
184}
diff --git a/tests/front/controller/admin/ThumbnailsControllerTest.php b/tests/front/controller/admin/ThumbnailsControllerTest.php
new file mode 100644
index 00000000..0c0c8a83
--- /dev/null
+++ b/tests/front/controller/admin/ThumbnailsControllerTest.php
@@ -0,0 +1,154 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
10use Shaarli\Thumbnailer;
11use Slim\Http\Request;
12use Slim\Http\Response;
13
14class ThumbnailsControllerTest extends TestCase
15{
16 use FrontAdminControllerMockHelper;
17
18 /** @var ThumbnailsController */
19 protected $controller;
20
21 public function setUp(): void
22 {
23 $this->createContainer();
24
25 $this->controller = new ThumbnailsController($this->container);
26 }
27
28 /**
29 * Test displaying the thumbnails update page
30 * Note that only non-note and HTTP bookmarks should be returned.
31 */
32 public function testIndex(): void
33 {
34 $assignedVariables = [];
35 $this->assignTemplateVars($assignedVariables);
36
37 $request = $this->createMock(Request::class);
38 $response = new Response();
39
40 $this->container->bookmarkService
41 ->expects(static::once())
42 ->method('search')
43 ->willReturn([
44 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'),
45 (new Bookmark())->setId(2)->setUrl('?abcdef')->setTitle('Note 1'),
46 (new Bookmark())->setId(3)->setUrl('http://url2.tld')->setTitle('Title 2'),
47 (new Bookmark())->setId(4)->setUrl('ftp://domain.tld', ['ftp'])->setTitle('FTP'),
48 ])
49 ;
50
51 $result = $this->controller->index($request, $response);
52
53 static::assertSame(200, $result->getStatusCode());
54 static::assertSame('thumbnails', (string) $result->getBody());
55
56 static::assertSame('Thumbnails update - Shaarli', $assignedVariables['pagetitle']);
57 static::assertSame([1, 3], $assignedVariables['ids']);
58 }
59
60 /**
61 * Test updating a bookmark thumbnail with valid parameters
62 */
63 public function testAjaxUpdateValid(): void
64 {
65 $request = $this->createMock(Request::class);
66 $response = new Response();
67
68 $bookmark = (new Bookmark())
69 ->setId($id = 123)
70 ->setUrl($url = 'http://url1.tld')
71 ->setTitle('Title 1')
72 ->setThumbnail(false)
73 ;
74
75 $this->container->thumbnailer = $this->createMock(Thumbnailer::class);
76 $this->container->thumbnailer
77 ->expects(static::once())
78 ->method('get')
79 ->with($url)
80 ->willReturn($thumb = 'http://img.tld/pic.png')
81 ;
82
83 $this->container->bookmarkService
84 ->expects(static::once())
85 ->method('get')
86 ->with($id)
87 ->willReturn($bookmark)
88 ;
89 $this->container->bookmarkService
90 ->expects(static::once())
91 ->method('set')
92 ->willReturnCallback(function (Bookmark $bookmark) use ($thumb) {
93 static::assertSame($thumb, $bookmark->getThumbnail());
94 })
95 ;
96
97 $result = $this->controller->ajaxUpdate($request, $response, ['id' => (string) $id]);
98
99 static::assertSame(200, $result->getStatusCode());
100
101 $payload = json_decode((string) $result->getBody(), true);
102
103 static::assertSame($id, $payload['id']);
104 static::assertSame($url, $payload['url']);
105 static::assertSame($thumb, $payload['thumbnail']);
106 }
107
108 /**
109 * Test updating a bookmark thumbnail - Invalid ID
110 */
111 public function testAjaxUpdateInvalidId(): void
112 {
113 $request = $this->createMock(Request::class);
114 $response = new Response();
115
116 $result = $this->controller->ajaxUpdate($request, $response, ['id' => 'nope']);
117
118 static::assertSame(400, $result->getStatusCode());
119 }
120
121 /**
122 * Test updating a bookmark thumbnail - No ID
123 */
124 public function testAjaxUpdateNoId(): void
125 {
126 $request = $this->createMock(Request::class);
127 $response = new Response();
128
129 $result = $this->controller->ajaxUpdate($request, $response, []);
130
131 static::assertSame(400, $result->getStatusCode());
132 }
133
134 /**
135 * Test updating a bookmark thumbnail with valid parameters
136 */
137 public function testAjaxUpdateBookmarkNotFound(): void
138 {
139 $id = 123;
140 $request = $this->createMock(Request::class);
141 $response = new Response();
142
143 $this->container->bookmarkService
144 ->expects(static::once())
145 ->method('get')
146 ->with($id)
147 ->willThrowException(new BookmarkNotFoundException())
148 ;
149
150 $result = $this->controller->ajaxUpdate($request, $response, ['id' => (string) $id]);
151
152 static::assertSame(404, $result->getStatusCode());
153 }
154}
diff --git a/tests/front/controller/admin/TokenControllerTest.php b/tests/front/controller/admin/TokenControllerTest.php
new file mode 100644
index 00000000..04b0c0fa
--- /dev/null
+++ b/tests/front/controller/admin/TokenControllerTest.php
@@ -0,0 +1,41 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11class TokenControllerTest extends TestCase
12{
13 use FrontAdminControllerMockHelper;
14
15 /** @var TokenController */
16 protected $controller;
17
18 public function setUp(): void
19 {
20 $this->createContainer();
21
22 $this->controller = new TokenController($this->container);
23 }
24
25 public function testGetToken(): void
26 {
27 $request = $this->createMock(Request::class);
28 $response = new Response();
29
30 $this->container->sessionManager
31 ->expects(static::once())
32 ->method('generateToken')
33 ->willReturn($token = 'token1234')
34 ;
35
36 $result = $this->controller->getToken($request, $response);
37
38 static::assertSame(200, $result->getStatusCode());
39 static::assertSame($token, (string) $result->getBody());
40 }
41}
diff --git a/tests/front/controller/admin/ToolsControllerTest.php b/tests/front/controller/admin/ToolsControllerTest.php
new file mode 100644
index 00000000..fc756f0f
--- /dev/null
+++ b/tests/front/controller/admin/ToolsControllerTest.php
@@ -0,0 +1,69 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use PHPUnit\Framework\TestCase;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11class ToolsControllerTestControllerTest extends TestCase
12{
13 use FrontAdminControllerMockHelper;
14
15 /** @var ToolsController */
16 protected $controller;
17
18 public function setUp(): void
19 {
20 $this->createContainer();
21
22 $this->controller = new ToolsController($this->container);
23 }
24
25 public function testDefaultInvokeWithHttps(): void
26 {
27 $request = $this->createMock(Request::class);
28 $response = new Response();
29
30 $this->container->environment = [
31 'SERVER_NAME' => 'shaarli',
32 'SERVER_PORT' => 443,
33 'HTTPS' => 'on',
34 ];
35
36 // Save RainTPL assigned variables
37 $assignedVariables = [];
38 $this->assignTemplateVars($assignedVariables);
39
40 $result = $this->controller->index($request, $response);
41
42 static::assertSame(200, $result->getStatusCode());
43 static::assertSame('tools', (string) $result->getBody());
44 static::assertSame('https://shaarli', $assignedVariables['pageabsaddr']);
45 static::assertTrue($assignedVariables['sslenabled']);
46 }
47
48 public function testDefaultInvokeWithoutHttps(): void
49 {
50 $request = $this->createMock(Request::class);
51 $response = new Response();
52
53 $this->container->environment = [
54 'SERVER_NAME' => 'shaarli',
55 'SERVER_PORT' => 80,
56 ];
57
58 // Save RainTPL assigned variables
59 $assignedVariables = [];
60 $this->assignTemplateVars($assignedVariables);
61
62 $result = $this->controller->index($request, $response);
63
64 static::assertSame(200, $result->getStatusCode());
65 static::assertSame('tools', (string) $result->getBody());
66 static::assertSame('http://shaarli', $assignedVariables['pageabsaddr']);
67 static::assertFalse($assignedVariables['sslenabled']);
68 }
69}
diff --git a/tests/front/controller/visitor/BookmarkListControllerTest.php b/tests/front/controller/visitor/BookmarkListControllerTest.php
new file mode 100644
index 00000000..5daaa2c4
--- /dev/null
+++ b/tests/front/controller/visitor/BookmarkListControllerTest.php
@@ -0,0 +1,448 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
10use Shaarli\Config\ConfigManager;
11use Shaarli\Security\LoginManager;
12use Shaarli\Thumbnailer;
13use Slim\Http\Request;
14use Slim\Http\Response;
15
16class BookmarkListControllerTest extends TestCase
17{
18 use FrontControllerMockHelper;
19
20 /** @var BookmarkListController */
21 protected $controller;
22
23 public function setUp(): void
24 {
25 $this->createContainer();
26
27 $this->controller = new BookmarkListController($this->container);
28 }
29
30 /**
31 * Test rendering list of bookmarks with default parameters (first page).
32 */
33 public function testIndexDefaultFirstPage(): void
34 {
35 $assignedVariables = [];
36 $this->assignTemplateVars($assignedVariables);
37
38 $request = $this->createMock(Request::class);
39 $response = new Response();
40
41 $this->container->bookmarkService
42 ->expects(static::once())
43 ->method('search')
44 ->with(
45 ['searchtags' => '', 'searchterm' => ''],
46 null,
47 false,
48 false
49 )
50 ->willReturn([
51 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'),
52 (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'),
53 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'),
54 ]
55 );
56
57 $this->container->sessionManager
58 ->method('getSessionParameter')
59 ->willReturnCallback(function (string $parameter, $default = null) {
60 if ('LINKS_PER_PAGE' === $parameter) {
61 return 2;
62 }
63
64 return $default;
65 })
66 ;
67
68 $result = $this->controller->index($request, $response);
69
70 static::assertSame(200, $result->getStatusCode());
71 static::assertSame('linklist', (string) $result->getBody());
72
73 static::assertSame('Shaarli', $assignedVariables['pagetitle']);
74 static::assertSame('?page=2', $assignedVariables['previous_page_url']);
75 static::assertSame('', $assignedVariables['next_page_url']);
76 static::assertSame(2, $assignedVariables['page_max']);
77 static::assertSame('', $assignedVariables['search_tags']);
78 static::assertSame(3, $assignedVariables['result_count']);
79 static::assertSame(1, $assignedVariables['page_current']);
80 static::assertSame('', $assignedVariables['search_term']);
81 static::assertNull($assignedVariables['visibility']);
82 static::assertCount(2, $assignedVariables['links']);
83
84 $link = $assignedVariables['links'][0];
85
86 static::assertSame(1, $link['id']);
87 static::assertSame('http://url1.tld', $link['url']);
88 static::assertSame('Title 1', $link['title']);
89
90 $link = $assignedVariables['links'][1];
91
92 static::assertSame(2, $link['id']);
93 static::assertSame('http://url2.tld', $link['url']);
94 static::assertSame('Title 2', $link['title']);
95 }
96
97 /**
98 * Test rendering list of bookmarks with default parameters (second page).
99 */
100 public function testIndexDefaultSecondPage(): void
101 {
102 $assignedVariables = [];
103 $this->assignTemplateVars($assignedVariables);
104
105 $request = $this->createMock(Request::class);
106 $request->method('getParam')->willReturnCallback(function (string $key) {
107 if ('page' === $key) {
108 return '2';
109 }
110
111 return null;
112 });
113 $response = new Response();
114
115 $this->container->bookmarkService
116 ->expects(static::once())
117 ->method('search')
118 ->with(
119 ['searchtags' => '', 'searchterm' => ''],
120 null,
121 false,
122 false
123 )
124 ->willReturn([
125 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'),
126 (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'),
127 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'),
128 ])
129 ;
130
131 $this->container->sessionManager
132 ->method('getSessionParameter')
133 ->willReturnCallback(function (string $parameter, $default = null) {
134 if ('LINKS_PER_PAGE' === $parameter) {
135 return 2;
136 }
137
138 return $default;
139 })
140 ;
141
142 $result = $this->controller->index($request, $response);
143
144 static::assertSame(200, $result->getStatusCode());
145 static::assertSame('linklist', (string) $result->getBody());
146
147 static::assertSame('Shaarli', $assignedVariables['pagetitle']);
148 static::assertSame('', $assignedVariables['previous_page_url']);
149 static::assertSame('?page=1', $assignedVariables['next_page_url']);
150 static::assertSame(2, $assignedVariables['page_max']);
151 static::assertSame('', $assignedVariables['search_tags']);
152 static::assertSame(3, $assignedVariables['result_count']);
153 static::assertSame(2, $assignedVariables['page_current']);
154 static::assertSame('', $assignedVariables['search_term']);
155 static::assertNull($assignedVariables['visibility']);
156 static::assertCount(1, $assignedVariables['links']);
157
158 $link = $assignedVariables['links'][2];
159
160 static::assertSame(3, $link['id']);
161 static::assertSame('http://url3.tld', $link['url']);
162 static::assertSame('Title 3', $link['title']);
163 }
164
165 /**
166 * Test rendering list of bookmarks with filters.
167 */
168 public function testIndexDefaultWithFilters(): void
169 {
170 $assignedVariables = [];
171 $this->assignTemplateVars($assignedVariables);
172
173 $request = $this->createMock(Request::class);
174 $request->method('getParam')->willReturnCallback(function (string $key) {
175 if ('searchtags' === $key) {
176 return 'abc def';
177 }
178 if ('searchterm' === $key) {
179 return 'ghi jkl';
180 }
181
182 return null;
183 });
184 $response = new Response();
185
186 $this->container->sessionManager
187 ->method('getSessionParameter')
188 ->willReturnCallback(function (string $key, $default) {
189 if ('LINKS_PER_PAGE' === $key) {
190 return 2;
191 }
192 if ('visibility' === $key) {
193 return 'private';
194 }
195 if ('untaggedonly' === $key) {
196 return true;
197 }
198
199 return $default;
200 })
201 ;
202
203 $this->container->bookmarkService
204 ->expects(static::once())
205 ->method('search')
206 ->with(
207 ['searchtags' => 'abc def', 'searchterm' => 'ghi jkl'],
208 'private',
209 false,
210 true
211 )
212 ->willReturn([
213 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'),
214 (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'),
215 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'),
216 ])
217 ;
218
219 $result = $this->controller->index($request, $response);
220
221 static::assertSame(200, $result->getStatusCode());
222 static::assertSame('linklist', (string) $result->getBody());
223
224 static::assertSame('Search: ghi jkl [abc] [def] - Shaarli', $assignedVariables['pagetitle']);
225 static::assertSame('?page=2&searchterm=ghi+jkl&searchtags=abc+def', $assignedVariables['previous_page_url']);
226 }
227
228 /**
229 * Test displaying a permalink with valid parameters
230 */
231 public function testPermalinkValid(): void
232 {
233 $hash = 'abcdef';
234
235 $assignedVariables = [];
236 $this->assignTemplateVars($assignedVariables);
237
238 $request = $this->createMock(Request::class);
239 $response = new Response();
240
241 $this->container->bookmarkService
242 ->expects(static::once())
243 ->method('findByHash')
244 ->with($hash)
245 ->willReturn((new Bookmark())->setId(123)->setTitle('Title 1')->setUrl('http://url1.tld'))
246 ;
247
248 $result = $this->controller->permalink($request, $response, ['hash' => $hash]);
249
250 static::assertSame(200, $result->getStatusCode());
251 static::assertSame('linklist', (string) $result->getBody());
252
253 static::assertSame('Title 1 - Shaarli', $assignedVariables['pagetitle']);
254 static::assertCount(1, $assignedVariables['links']);
255
256 $link = $assignedVariables['links'][0];
257
258 static::assertSame(123, $link['id']);
259 static::assertSame('http://url1.tld', $link['url']);
260 static::assertSame('Title 1', $link['title']);
261 }
262
263 /**
264 * Test displaying a permalink with an unknown small hash : renders a 404 template error
265 */
266 public function testPermalinkNotFound(): void
267 {
268 $hash = 'abcdef';
269
270 $assignedVariables = [];
271 $this->assignTemplateVars($assignedVariables);
272
273 $request = $this->createMock(Request::class);
274 $response = new Response();
275
276 $this->container->bookmarkService
277 ->expects(static::once())
278 ->method('findByHash')
279 ->with($hash)
280 ->willThrowException(new BookmarkNotFoundException())
281 ;
282
283 $result = $this->controller->permalink($request, $response, ['hash' => $hash]);
284
285 static::assertSame(200, $result->getStatusCode());
286 static::assertSame('404', (string) $result->getBody());
287
288 static::assertSame(
289 'The link you are trying to reach does not exist or has been deleted.',
290 $assignedVariables['error_message']
291 );
292 }
293
294 /**
295 * Test getting link list with thumbnail updates.
296 * -> 2 thumbnails update, only 1 datastore write
297 */
298 public function testThumbnailUpdateFromLinkList(): void
299 {
300 $request = $this->createMock(Request::class);
301 $response = new Response();
302
303 $this->container->loginManager = $this->createMock(LoginManager::class);
304 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
305
306 $this->container->conf = $this->createMock(ConfigManager::class);
307 $this->container->conf
308 ->method('get')
309 ->willReturnCallback(function (string $key, $default) {
310 return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default;
311 })
312 ;
313
314 $this->container->thumbnailer = $this->createMock(Thumbnailer::class);
315 $this->container->thumbnailer
316 ->expects(static::exactly(2))
317 ->method('get')
318 ->withConsecutive(['https://url2.tld'], ['https://url4.tld'])
319 ;
320
321 $this->container->bookmarkService
322 ->expects(static::once())
323 ->method('search')
324 ->willReturn([
325 (new Bookmark())->setId(1)->setUrl('https://url1.tld')->setTitle('Title 1')->setThumbnail(false),
326 $b1 = (new Bookmark())->setId(2)->setUrl('https://url2.tld')->setTitle('Title 2'),
327 (new Bookmark())->setId(3)->setUrl('https://url3.tld')->setTitle('Title 3')->setThumbnail(false),
328 $b2 = (new Bookmark())->setId(2)->setUrl('https://url4.tld')->setTitle('Title 4'),
329 (new Bookmark())->setId(2)->setUrl('ftp://url5.tld', ['ftp'])->setTitle('Title 5'),
330 ])
331 ;
332 $this->container->bookmarkService
333 ->expects(static::exactly(2))
334 ->method('set')
335 ->withConsecutive([$b1, false], [$b2, false])
336 ;
337 $this->container->bookmarkService->expects(static::once())->method('save');
338
339 $result = $this->controller->index($request, $response);
340
341 static::assertSame(200, $result->getStatusCode());
342 static::assertSame('linklist', (string) $result->getBody());
343 }
344
345 /**
346 * Test getting a permalink with thumbnail update.
347 */
348 public function testThumbnailUpdateFromPermalink(): void
349 {
350 $request = $this->createMock(Request::class);
351 $response = new Response();
352
353 $this->container->loginManager = $this->createMock(LoginManager::class);
354 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
355
356 $this->container->conf = $this->createMock(ConfigManager::class);
357 $this->container->conf
358 ->method('get')
359 ->willReturnCallback(function (string $key, $default) {
360 return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default;
361 })
362 ;
363
364 $this->container->thumbnailer = $this->createMock(Thumbnailer::class);
365 $this->container->thumbnailer->expects(static::once())->method('get')->withConsecutive(['https://url.tld']);
366
367 $this->container->bookmarkService
368 ->expects(static::once())
369 ->method('findByHash')
370 ->willReturn($bookmark = (new Bookmark())->setId(2)->setUrl('https://url.tld')->setTitle('Title 1'))
371 ;
372 $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, true);
373 $this->container->bookmarkService->expects(static::never())->method('save');
374
375 $result = $this->controller->permalink($request, $response, ['hash' => 'abc']);
376
377 static::assertSame(200, $result->getStatusCode());
378 static::assertSame('linklist', (string) $result->getBody());
379 }
380
381 /**
382 * Trigger legacy controller in link list controller: permalink
383 */
384 public function testLegacyControllerPermalink(): void
385 {
386 $hash = 'abcdef';
387 $this->container->environment['QUERY_STRING'] = $hash;
388
389 $request = $this->createMock(Request::class);
390 $response = new Response();
391
392 $result = $this->controller->index($request, $response);
393
394 static::assertSame(302, $result->getStatusCode());
395 static::assertSame('/subfolder/shaare/' . $hash, $result->getHeader('location')[0]);
396 }
397
398 /**
399 * Trigger legacy controller in link list controller: ?do= query parameter
400 */
401 public function testLegacyControllerDoPage(): void
402 {
403 $request = $this->createMock(Request::class);
404 $request->method('getQueryParam')->with('do')->willReturn('picwall');
405 $response = new Response();
406
407 $result = $this->controller->index($request, $response);
408
409 static::assertSame(302, $result->getStatusCode());
410 static::assertSame('/subfolder/picture-wall', $result->getHeader('location')[0]);
411 }
412
413 /**
414 * Trigger legacy controller in link list controller: ?do= query parameter with unknown legacy route
415 */
416 public function testLegacyControllerUnknownDoPage(): void
417 {
418 $request = $this->createMock(Request::class);
419 $request->method('getQueryParam')->with('do')->willReturn('nope');
420 $response = new Response();
421
422 $result = $this->controller->index($request, $response);
423
424 static::assertSame(200, $result->getStatusCode());
425 static::assertSame('linklist', (string) $result->getBody());
426 }
427
428 /**
429 * Trigger legacy controller in link list controller: other GET route (e.g. ?post)
430 */
431 public function testLegacyControllerGetParameter(): void
432 {
433 $request = $this->createMock(Request::class);
434 $request->method('getQueryParams')->willReturn(['post' => $url = 'http://url.tld']);
435 $response = new Response();
436
437 $this->container->loginManager = $this->createMock(LoginManager::class);
438 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
439
440 $result = $this->controller->index($request, $response);
441
442 static::assertSame(302, $result->getStatusCode());
443 static::assertSame(
444 '/subfolder/admin/shaare?post=' . urlencode($url),
445 $result->getHeader('location')[0]
446 );
447 }
448}
diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php
new file mode 100644
index 00000000..b802c62c
--- /dev/null
+++ b/tests/front/controller/visitor/DailyControllerTest.php
@@ -0,0 +1,476 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Feed\CachedPage;
10use Slim\Http\Request;
11use Slim\Http\Response;
12
13class 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 $currentDay = new \DateTimeImmutable('2020-05-13');
31
32 $request = $this->createMock(Request::class);
33 $request->method('getQueryParam')->willReturn($currentDay->format('Ymd'));
34 $response = new Response();
35
36 // Save RainTPL assigned variables
37 $assignedVariables = [];
38 $this->assignTemplateVars($assignedVariables);
39
40 // Links dataset: 2 links with thumbnails
41 $this->container->bookmarkService
42 ->expects(static::once())
43 ->method('days')
44 ->willReturnCallback(function () use ($currentDay): array {
45 return [
46 '20200510',
47 $currentDay->format('Ymd'),
48 '20200516',
49 ];
50 })
51 ;
52 $this->container->bookmarkService
53 ->expects(static::once())
54 ->method('filterDay')
55 ->willReturnCallback(function (): array {
56 return [
57 (new Bookmark())
58 ->setId(1)
59 ->setUrl('http://url.tld')
60 ->setTitle(static::generateString(50))
61 ->setDescription(static::generateString(500))
62 ,
63 (new Bookmark())
64 ->setId(2)
65 ->setUrl('http://url2.tld')
66 ->setTitle(static::generateString(50))
67 ->setDescription(static::generateString(500))
68 ,
69 (new Bookmark())
70 ->setId(3)
71 ->setUrl('http://url3.tld')
72 ->setTitle(static::generateString(50))
73 ->setDescription(static::generateString(500))
74 ,
75 ];
76 })
77 ;
78
79 // Make sure that PluginManager hook is triggered
80 $this->container->pluginManager
81 ->expects(static::at(0))
82 ->method('executeHooks')
83 ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array {
84 static::assertSame('render_daily', $hook);
85
86 static::assertArrayHasKey('linksToDisplay', $data);
87 static::assertCount(3, $data['linksToDisplay']);
88 static::assertSame(1, $data['linksToDisplay'][0]['id']);
89 static::assertSame($currentDay->getTimestamp(), $data['day']);
90 static::assertSame('20200510', $data['previousday']);
91 static::assertSame('20200516', $data['nextday']);
92
93 static::assertArrayHasKey('loggedin', $param);
94
95 return $data;
96 })
97 ;
98
99 $result = $this->controller->index($request, $response);
100
101 static::assertSame(200, $result->getStatusCode());
102 static::assertSame('daily', (string) $result->getBody());
103 static::assertSame(
104 'Daily - '. format_date($currentDay, false, true) .' - Shaarli',
105 $assignedVariables['pagetitle']
106 );
107 static::assertEquals($currentDay, $assignedVariables['dayDate']);
108 static::assertEquals($currentDay->getTimestamp(), $assignedVariables['day']);
109 static::assertCount(3, $assignedVariables['linksToDisplay']);
110
111 $link = $assignedVariables['linksToDisplay'][0];
112
113 static::assertSame(1, $link['id']);
114 static::assertSame('http://url.tld', $link['url']);
115 static::assertNotEmpty($link['title']);
116 static::assertNotEmpty($link['description']);
117 static::assertNotEmpty($link['formatedDescription']);
118
119 $link = $assignedVariables['linksToDisplay'][1];
120
121 static::assertSame(2, $link['id']);
122 static::assertSame('http://url2.tld', $link['url']);
123 static::assertNotEmpty($link['title']);
124 static::assertNotEmpty($link['description']);
125 static::assertNotEmpty($link['formatedDescription']);
126
127 $link = $assignedVariables['linksToDisplay'][2];
128
129 static::assertSame(3, $link['id']);
130 static::assertSame('http://url3.tld', $link['url']);
131 static::assertNotEmpty($link['title']);
132 static::assertNotEmpty($link['description']);
133 static::assertNotEmpty($link['formatedDescription']);
134
135 static::assertCount(3, $assignedVariables['cols']);
136 static::assertCount(1, $assignedVariables['cols'][0]);
137 static::assertCount(1, $assignedVariables['cols'][1]);
138 static::assertCount(1, $assignedVariables['cols'][2]);
139
140 $link = $assignedVariables['cols'][0][0];
141
142 static::assertSame(1, $link['id']);
143 static::assertSame('http://url.tld', $link['url']);
144 static::assertNotEmpty($link['title']);
145 static::assertNotEmpty($link['description']);
146 static::assertNotEmpty($link['formatedDescription']);
147
148 $link = $assignedVariables['cols'][1][0];
149
150 static::assertSame(2, $link['id']);
151 static::assertSame('http://url2.tld', $link['url']);
152 static::assertNotEmpty($link['title']);
153 static::assertNotEmpty($link['description']);
154 static::assertNotEmpty($link['formatedDescription']);
155
156 $link = $assignedVariables['cols'][2][0];
157
158 static::assertSame(3, $link['id']);
159 static::assertSame('http://url3.tld', $link['url']);
160 static::assertNotEmpty($link['title']);
161 static::assertNotEmpty($link['description']);
162 static::assertNotEmpty($link['formatedDescription']);
163 }
164
165 /**
166 * Daily page - test that everything goes fine with no future or past bookmarks
167 */
168 public function testValidIndexControllerInvokeNoFutureOrPast(): void
169 {
170 $currentDay = new \DateTimeImmutable('2020-05-13');
171
172 $request = $this->createMock(Request::class);
173 $response = new Response();
174
175 // Save RainTPL assigned variables
176 $assignedVariables = [];
177 $this->assignTemplateVars($assignedVariables);
178
179 // Links dataset: 2 links with thumbnails
180 $this->container->bookmarkService
181 ->expects(static::once())
182 ->method('days')
183 ->willReturnCallback(function () use ($currentDay): array {
184 return [
185 $currentDay->format($currentDay->format('Ymd')),
186 ];
187 })
188 ;
189 $this->container->bookmarkService
190 ->expects(static::once())
191 ->method('filterDay')
192 ->willReturnCallback(function (): array {
193 return [
194 (new Bookmark())
195 ->setId(1)
196 ->setUrl('http://url.tld')
197 ->setTitle(static::generateString(50))
198 ->setDescription(static::generateString(500))
199 ,
200 ];
201 })
202 ;
203
204 // Make sure that PluginManager hook is triggered
205 $this->container->pluginManager
206 ->expects(static::at(0))
207 ->method('executeHooks')
208 ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array {
209 static::assertSame('render_daily', $hook);
210
211 static::assertArrayHasKey('linksToDisplay', $data);
212 static::assertCount(1, $data['linksToDisplay']);
213 static::assertSame(1, $data['linksToDisplay'][0]['id']);
214 static::assertSame($currentDay->getTimestamp(), $data['day']);
215 static::assertEmpty($data['previousday']);
216 static::assertEmpty($data['nextday']);
217
218 static::assertArrayHasKey('loggedin', $param);
219
220 return $data;
221 });
222
223 $result = $this->controller->index($request, $response);
224
225 static::assertSame(200, $result->getStatusCode());
226 static::assertSame('daily', (string) $result->getBody());
227 static::assertSame(
228 'Daily - '. format_date($currentDay, false, true) .' - Shaarli',
229 $assignedVariables['pagetitle']
230 );
231 static::assertCount(1, $assignedVariables['linksToDisplay']);
232
233 $link = $assignedVariables['linksToDisplay'][0];
234 static::assertSame(1, $link['id']);
235 }
236
237 /**
238 * Daily page - test that height adjustment in columns is working
239 */
240 public function testValidIndexControllerInvokeHeightAdjustment(): void
241 {
242 $currentDay = new \DateTimeImmutable('2020-05-13');
243
244 $request = $this->createMock(Request::class);
245 $response = new Response();
246
247 // Save RainTPL assigned variables
248 $assignedVariables = [];
249 $this->assignTemplateVars($assignedVariables);
250
251 // Links dataset: 2 links with thumbnails
252 $this->container->bookmarkService
253 ->expects(static::once())
254 ->method('days')
255 ->willReturnCallback(function () use ($currentDay): array {
256 return [
257 $currentDay->format($currentDay->format('Ymd')),
258 ];
259 })
260 ;
261 $this->container->bookmarkService
262 ->expects(static::once())
263 ->method('filterDay')
264 ->willReturnCallback(function (): array {
265 return [
266 (new Bookmark())->setId(1)->setUrl('http://url.tld')->setTitle('title'),
267 (new Bookmark())
268 ->setId(2)
269 ->setUrl('http://url.tld')
270 ->setTitle(static::generateString(50))
271 ->setDescription(static::generateString(5000))
272 ,
273 (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'),
274 (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'),
275 (new Bookmark())->setId(5)->setUrl('http://url.tld')->setTitle('title'),
276 (new Bookmark())->setId(6)->setUrl('http://url.tld')->setTitle('title'),
277 (new Bookmark())->setId(7)->setUrl('http://url.tld')->setTitle('title'),
278 ];
279 })
280 ;
281
282 // Make sure that PluginManager hook is triggered
283 $this->container->pluginManager
284 ->expects(static::at(0))
285 ->method('executeHooks')
286 ->willReturnCallback(function (string $hook, array $data, array $param): array {
287 return $data;
288 })
289 ;
290
291 $result = $this->controller->index($request, $response);
292
293 static::assertSame(200, $result->getStatusCode());
294 static::assertSame('daily', (string) $result->getBody());
295 static::assertCount(7, $assignedVariables['linksToDisplay']);
296
297 $columnIds = function (array $column): array {
298 return array_map(function (array $item): int { return $item['id']; }, $column);
299 };
300
301 static::assertSame([1, 4, 6], $columnIds($assignedVariables['cols'][0]));
302 static::assertSame([2], $columnIds($assignedVariables['cols'][1]));
303 static::assertSame([3, 5, 7], $columnIds($assignedVariables['cols'][2]));
304 }
305
306 /**
307 * Daily page - no bookmark
308 */
309 public function testValidIndexControllerInvokeNoBookmark(): void
310 {
311 $request = $this->createMock(Request::class);
312 $response = new Response();
313
314 // Save RainTPL assigned variables
315 $assignedVariables = [];
316 $this->assignTemplateVars($assignedVariables);
317
318 // Links dataset: 2 links with thumbnails
319 $this->container->bookmarkService
320 ->expects(static::once())
321 ->method('days')
322 ->willReturnCallback(function (): array {
323 return [];
324 })
325 ;
326 $this->container->bookmarkService
327 ->expects(static::once())
328 ->method('filterDay')
329 ->willReturnCallback(function (): array {
330 return [];
331 })
332 ;
333
334 // Make sure that PluginManager hook is triggered
335 $this->container->pluginManager
336 ->expects(static::at(0))
337 ->method('executeHooks')
338 ->willReturnCallback(function (string $hook, array $data, array $param): array {
339 return $data;
340 })
341 ;
342
343 $result = $this->controller->index($request, $response);
344
345 static::assertSame(200, $result->getStatusCode());
346 static::assertSame('daily', (string) $result->getBody());
347 static::assertCount(0, $assignedVariables['linksToDisplay']);
348 static::assertSame('Today', $assignedVariables['dayDesc']);
349 static::assertEquals((new \DateTime())->setTime(0, 0)->getTimestamp(), $assignedVariables['day']);
350 static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']);
351 }
352
353 /**
354 * Daily RSS - default behaviour
355 */
356 public function testValidRssControllerInvokeDefault(): void
357 {
358 $dates = [
359 new \DateTimeImmutable('2020-05-17'),
360 new \DateTimeImmutable('2020-05-15'),
361 new \DateTimeImmutable('2020-05-13'),
362 ];
363
364 $request = $this->createMock(Request::class);
365 $response = new Response();
366
367 $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([
368 (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'),
369 (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'),
370 (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'),
371 (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'),
372 ]);
373
374 $this->container->pageCacheManager
375 ->expects(static::once())
376 ->method('getCachePage')
377 ->willReturnCallback(function (): CachedPage {
378 $cachedPage = $this->createMock(CachedPage::class);
379 $cachedPage->expects(static::once())->method('cache')->with('dailyrss');
380
381 return $cachedPage;
382 }
383 );
384
385 // Save RainTPL assigned variables
386 $assignedVariables = [];
387 $this->assignTemplateVars($assignedVariables);
388
389 $result = $this->controller->rss($request, $response);
390
391 static::assertSame(200, $result->getStatusCode());
392 static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]);
393 static::assertSame('dailyrss', (string) $result->getBody());
394 static::assertSame('Shaarli', $assignedVariables['title']);
395 static::assertSame('http://shaarli', $assignedVariables['index_url']);
396 static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']);
397 static::assertFalse($assignedVariables['hide_timestamps']);
398 static::assertCount(2, $assignedVariables['days']);
399
400 $day = $assignedVariables['days'][$dates[0]->format('Ymd')];
401
402 static::assertEquals($dates[0], $day['date']);
403 static::assertSame($dates[0]->format(\DateTime::RSS), $day['date_rss']);
404 static::assertSame(format_date($dates[0], false), $day['date_human']);
405 static::assertSame('http://shaarli/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']);
406 static::assertCount(1, $day['links']);
407 static::assertSame(1, $day['links'][0]['id']);
408 static::assertSame('http://domain.tld/1', $day['links'][0]['url']);
409 static::assertEquals($dates[0], $day['links'][0]['created']);
410
411 $day = $assignedVariables['days'][$dates[1]->format('Ymd')];
412
413 static::assertEquals($dates[1], $day['date']);
414 static::assertSame($dates[1]->format(\DateTime::RSS), $day['date_rss']);
415 static::assertSame(format_date($dates[1], false), $day['date_human']);
416 static::assertSame('http://shaarli/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']);
417 static::assertCount(2, $day['links']);
418
419 static::assertSame(2, $day['links'][0]['id']);
420 static::assertSame('http://domain.tld/2', $day['links'][0]['url']);
421 static::assertEquals($dates[1], $day['links'][0]['created']);
422 static::assertSame(3, $day['links'][1]['id']);
423 static::assertSame('http://domain.tld/3', $day['links'][1]['url']);
424 static::assertEquals($dates[1], $day['links'][1]['created']);
425 }
426
427 /**
428 * Daily RSS - trigger cache rendering
429 */
430 public function testValidRssControllerInvokeTriggerCache(): void
431 {
432 $request = $this->createMock(Request::class);
433 $response = new Response();
434
435 $this->container->pageCacheManager->method('getCachePage')->willReturnCallback(function (): CachedPage {
436 $cachedPage = $this->createMock(CachedPage::class);
437 $cachedPage->method('cachedVersion')->willReturn('this is cache!');
438
439 return $cachedPage;
440 });
441
442 $this->container->bookmarkService->expects(static::never())->method('search');
443
444 $result = $this->controller->rss($request, $response);
445
446 static::assertSame(200, $result->getStatusCode());
447 static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]);
448 static::assertSame('this is cache!', (string) $result->getBody());
449 }
450
451 /**
452 * Daily RSS - No bookmark
453 */
454 public function testValidRssControllerInvokeNoBookmark(): void
455 {
456 $request = $this->createMock(Request::class);
457 $response = new Response();
458
459 $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([]);
460
461 // Save RainTPL assigned variables
462 $assignedVariables = [];
463 $this->assignTemplateVars($assignedVariables);
464
465 $result = $this->controller->rss($request, $response);
466
467 static::assertSame(200, $result->getStatusCode());
468 static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]);
469 static::assertSame('dailyrss', (string) $result->getBody());
470 static::assertSame('Shaarli', $assignedVariables['title']);
471 static::assertSame('http://shaarli', $assignedVariables['index_url']);
472 static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']);
473 static::assertFalse($assignedVariables['hide_timestamps']);
474 static::assertCount(0, $assignedVariables['days']);
475 }
476}
diff --git a/tests/front/controller/visitor/ErrorControllerTest.php b/tests/front/controller/visitor/ErrorControllerTest.php
new file mode 100644
index 00000000..e497bfef
--- /dev/null
+++ b/tests/front/controller/visitor/ErrorControllerTest.php
@@ -0,0 +1,70 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Front\Exception\ShaarliFrontException;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12class ErrorControllerTest extends TestCase
13{
14 use FrontControllerMockHelper;
15
16 /** @var ErrorController */
17 protected $controller;
18
19 public function setUp(): void
20 {
21 $this->createContainer();
22
23 $this->controller = new ErrorController($this->container);
24 }
25
26 /**
27 * Test displaying error with a ShaarliFrontException: display exception message and use its code for HTTTP code
28 */
29 public function testDisplayFrontExceptionError(): void
30 {
31 $request = $this->createMock(Request::class);
32 $response = new Response();
33
34 $message = 'error message';
35 $errorCode = 418;
36
37 // Save RainTPL assigned variables
38 $assignedVariables = [];
39 $this->assignTemplateVars($assignedVariables);
40
41 $result = ($this->controller)(
42 $request,
43 $response,
44 new class($message, $errorCode) extends ShaarliFrontException {}
45 );
46
47 static::assertSame($errorCode, $result->getStatusCode());
48 static::assertSame($message, $assignedVariables['message']);
49 static::assertArrayNotHasKey('stacktrace', $assignedVariables);
50 }
51
52 /**
53 * Test displaying error with any exception (no debug): only display an error occurred with HTTP 500.
54 */
55 public function testDisplayAnyExceptionErrorNoDebug(): void
56 {
57 $request = $this->createMock(Request::class);
58 $response = new Response();
59
60 // Save RainTPL assigned variables
61 $assignedVariables = [];
62 $this->assignTemplateVars($assignedVariables);
63
64 $result = ($this->controller)($request, $response, new \Exception('abc'));
65
66 static::assertSame(500, $result->getStatusCode());
67 static::assertSame('An unexpected error occurred.', $assignedVariables['message']);
68 static::assertArrayNotHasKey('stacktrace', $assignedVariables);
69 }
70}
diff --git a/tests/front/controller/visitor/FeedControllerTest.php b/tests/front/controller/visitor/FeedControllerTest.php
new file mode 100644
index 00000000..fb417e2a
--- /dev/null
+++ b/tests/front/controller/visitor/FeedControllerTest.php
@@ -0,0 +1,145 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Feed\FeedBuilder;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12class 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 $request = $this->createMock(Request::class);
34 $response = new Response();
35
36 $this->container->feedBuilder->expects(static::once())->method('setLocale');
37 $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false);
38 $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true);
39
40 // Save RainTPL assigned variables
41 $assignedVariables = [];
42 $this->assignTemplateVars($assignedVariables);
43
44 $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']);
45
46 // Make sure that PluginManager hook is triggered
47 $this->container->pluginManager
48 ->expects(static::at(0))
49 ->method('executeHooks')
50 ->willReturnCallback(function (string $hook, array $data, array $param): void {
51 static::assertSame('render_feed', $hook);
52 static::assertSame('data', $data['content']);
53
54 static::assertArrayHasKey('loggedin', $param);
55 static::assertSame('rss', $param['target']);
56 })
57 ;
58
59 $result = $this->controller->rss($request, $response);
60
61 static::assertSame(200, $result->getStatusCode());
62 static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]);
63 static::assertSame('feed.rss', (string) $result->getBody());
64 static::assertSame('data', $assignedVariables['content']);
65 }
66
67 /**
68 * Feed Controller - ATOM default behaviour
69 */
70 public function testDefaultAtomController(): void
71 {
72 $request = $this->createMock(Request::class);
73 $response = new Response();
74
75 $this->container->feedBuilder->expects(static::once())->method('setLocale');
76 $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false);
77 $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true);
78
79 // Save RainTPL assigned variables
80 $assignedVariables = [];
81 $this->assignTemplateVars($assignedVariables);
82
83 $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']);
84
85 // Make sure that PluginManager hook is triggered
86 $this->container->pluginManager
87 ->expects(static::at(0))
88 ->method('executeHooks')
89 ->willReturnCallback(function (string $hook, array $data, array $param): void {
90 static::assertSame('render_feed', $hook);
91 static::assertSame('data', $data['content']);
92
93 static::assertArrayHasKey('loggedin', $param);
94 static::assertSame('atom', $param['target']);
95 })
96 ;
97
98 $result = $this->controller->atom($request, $response);
99
100 static::assertSame(200, $result->getStatusCode());
101 static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]);
102 static::assertSame('feed.atom', (string) $result->getBody());
103 static::assertSame('data', $assignedVariables['content']);
104 }
105
106 /**
107 * Feed Controller - ATOM with parameters
108 */
109 public function testAtomControllerWithParameters(): void
110 {
111 $request = $this->createMock(Request::class);
112 $request->method('getParams')->willReturn(['parameter' => 'value']);
113 $response = new Response();
114
115 // Save RainTPL assigned variables
116 $assignedVariables = [];
117 $this->assignTemplateVars($assignedVariables);
118
119 $this->container->feedBuilder
120 ->method('buildData')
121 ->with('atom', ['parameter' => 'value'])
122 ->willReturn(['content' => 'data'])
123 ;
124
125 // Make sure that PluginManager hook is triggered
126 $this->container->pluginManager
127 ->expects(static::at(0))
128 ->method('executeHooks')
129 ->willReturnCallback(function (string $hook, array $data, array $param): void {
130 static::assertSame('render_feed', $hook);
131 static::assertSame('data', $data['content']);
132
133 static::assertArrayHasKey('loggedin', $param);
134 static::assertSame('atom', $param['target']);
135 })
136 ;
137
138 $result = $this->controller->atom($request, $response);
139
140 static::assertSame(200, $result->getStatusCode());
141 static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]);
142 static::assertSame('feed.atom', (string) $result->getBody());
143 static::assertSame('data', $assignedVariables['content']);
144 }
145}
diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php
new file mode 100644
index 00000000..e0bd4ecf
--- /dev/null
+++ b/tests/front/controller/visitor/FrontControllerMockHelper.php
@@ -0,0 +1,119 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\MockObject\MockObject;
8use Shaarli\Bookmark\BookmarkServiceInterface;
9use Shaarli\Config\ConfigManager;
10use Shaarli\Container\ShaarliTestContainer;
11use Shaarli\Formatter\BookmarkFormatter;
12use Shaarli\Formatter\BookmarkRawFormatter;
13use Shaarli\Formatter\FormatterFactory;
14use Shaarli\Plugin\PluginManager;
15use Shaarli\Render\PageBuilder;
16use Shaarli\Render\PageCacheManager;
17use Shaarli\Security\LoginManager;
18use 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 */
28trait FrontControllerMockHelper
29{
30 /** @var ShaarliTestContainer */
31 protected $container;
32
33 /**
34 * Mock the container instance and initialize container's services used by tests
35 */
36 protected function createContainer(): void
37 {
38 $this->container = $this->createMock(ShaarliTestContainer::class);
39
40 $this->container->loginManager = $this->createMock(LoginManager::class);
41
42 // Config
43 $this->container->conf = $this->createMock(ConfigManager::class);
44 $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) {
45 return $default === null ? $parameter : $default;
46 });
47
48 // PageBuilder
49 $this->container->pageBuilder = $this->createMock(PageBuilder::class);
50 $this->container->pageBuilder
51 ->method('render')
52 ->willReturnCallback(function (string $template): string {
53 return $template;
54 })
55 ;
56
57 // Plugin Manager
58 $this->container->pluginManager = $this->createMock(PluginManager::class);
59
60 // BookmarkService
61 $this->container->bookmarkService = $this->createMock(BookmarkServiceInterface::class);
62
63 // Formatter
64 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
65 $this->container->formatterFactory
66 ->method('getFormatter')
67 ->willReturnCallback(function (): BookmarkFormatter {
68 return new BookmarkRawFormatter($this->container->conf, true);
69 })
70 ;
71
72 // CacheManager
73 $this->container->pageCacheManager = $this->createMock(PageCacheManager::class);
74
75 // SessionManager
76 $this->container->sessionManager = $this->createMock(SessionManager::class);
77
78 // $_SERVER
79 $this->container->environment = [
80 'SERVER_NAME' => 'shaarli',
81 'SERVER_PORT' => '80',
82 'REQUEST_URI' => '/daily-rss',
83 'REMOTE_ADDR' => '1.2.3.4',
84 ];
85
86 $this->container->basePath = '/subfolder';
87 }
88
89 /**
90 * Pass a reference of an array which will be populated by `pageBuilder->assign` calls during execution.
91 *
92 * @param mixed $variables Array reference to populate.
93 */
94 protected function assignTemplateVars(array &$variables): void
95 {
96 $this->container->pageBuilder
97 ->expects(static::atLeastOnce())
98 ->method('assign')
99 ->willReturnCallback(function ($key, $value) use (&$variables) {
100 $variables[$key] = $value;
101
102 return $this;
103 })
104 ;
105 }
106
107 protected static function generateString(int $length): string
108 {
109 // bin2hex(random_bytes) generates string twice as long as given parameter
110 $length = (int) ceil($length / 2);
111
112 return bin2hex(random_bytes($length));
113 }
114
115 /**
116 * Force to be used in PHPUnit context.
117 */
118 protected abstract function createMock($originalClassName): MockObject;
119}
diff --git a/tests/front/controller/visitor/InstallControllerTest.php b/tests/front/controller/visitor/InstallControllerTest.php
new file mode 100644
index 00000000..3b855365
--- /dev/null
+++ b/tests/front/controller/visitor/InstallControllerTest.php
@@ -0,0 +1,262 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Config\ConfigManager;
9use Shaarli\Front\Exception\AlreadyInstalledException;
10use Shaarli\Security\SessionManager;
11use Slim\Http\Request;
12use Slim\Http\Response;
13
14class InstallControllerTest extends TestCase
15{
16 use FrontControllerMockHelper;
17
18 const MOCK_FILE = '.tmp';
19
20 /** @var InstallController */
21 protected $controller;
22
23 public function setUp(): void
24 {
25 $this->createContainer();
26
27 $this->container->conf = $this->createMock(ConfigManager::class);
28 $this->container->conf->method('getConfigFileExt')->willReturn(static::MOCK_FILE);
29 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
30 if ($key === 'resource.raintpl_tpl') {
31 return '.';
32 }
33
34 return $default ?? $key;
35 });
36
37 $this->controller = new InstallController($this->container);
38 }
39
40 protected function tearDown(): void
41 {
42 if (file_exists(static::MOCK_FILE)) {
43 unlink(static::MOCK_FILE);
44 }
45 }
46
47 /**
48 * Test displaying install page with valid session.
49 */
50 public function testInstallIndexWithValidSession(): void
51 {
52 $assignedVariables = [];
53 $this->assignTemplateVars($assignedVariables);
54
55 $request = $this->createMock(Request::class);
56 $response = new Response();
57
58 $this->container->sessionManager = $this->createMock(SessionManager::class);
59 $this->container->sessionManager
60 ->method('getSessionParameter')
61 ->willReturnCallback(function (string $key, $default) {
62 return $key === 'session_tested' ? 'Working' : $default;
63 })
64 ;
65
66 $result = $this->controller->index($request, $response);
67
68 static::assertSame(200, $result->getStatusCode());
69 static::assertSame('install', (string) $result->getBody());
70
71 static::assertIsArray($assignedVariables['continents']);
72 static::assertSame('Africa', $assignedVariables['continents'][0]);
73 static::assertSame('UTC', $assignedVariables['continents']['selected']);
74
75 static::assertIsArray($assignedVariables['cities']);
76 static::assertSame(['continent' => 'Africa', 'city' => 'Abidjan'], $assignedVariables['cities'][0]);
77 static::assertSame('UTC', $assignedVariables['continents']['selected']);
78
79 static::assertIsArray($assignedVariables['languages']);
80 static::assertSame('Automatic', $assignedVariables['languages']['auto']);
81 static::assertSame('French', $assignedVariables['languages']['fr']);
82 }
83
84 /**
85 * Instantiate the install controller with an existing config file: exception.
86 */
87 public function testInstallWithExistingConfigFile(): void
88 {
89 $this->expectException(AlreadyInstalledException::class);
90
91 touch(static::MOCK_FILE);
92
93 $this->controller = new InstallController($this->container);
94 }
95
96 /**
97 * Call controller without session yet defined, redirect to test session install page.
98 */
99 public function testInstallRedirectToSessionTest(): void
100 {
101 $request = $this->createMock(Request::class);
102 $response = new Response();
103
104 $this->container->sessionManager = $this->createMock(SessionManager::class);
105 $this->container->sessionManager
106 ->expects(static::once())
107 ->method('setSessionParameter')
108 ->with(InstallController::SESSION_TEST_KEY, InstallController::SESSION_TEST_VALUE)
109 ;
110
111 $result = $this->controller->index($request, $response);
112
113 static::assertSame(302, $result->getStatusCode());
114 static::assertSame('/subfolder/install/session-test', $result->getHeader('location')[0]);
115 }
116
117 /**
118 * Call controller in session test mode: valid session then redirect to install page.
119 */
120 public function testInstallSessionTestValid(): void
121 {
122 $request = $this->createMock(Request::class);
123 $response = new Response();
124
125 $this->container->sessionManager = $this->createMock(SessionManager::class);
126 $this->container->sessionManager
127 ->method('getSessionParameter')
128 ->with(InstallController::SESSION_TEST_KEY)
129 ->willReturn(InstallController::SESSION_TEST_VALUE)
130 ;
131
132 $result = $this->controller->sessionTest($request, $response);
133
134 static::assertSame(302, $result->getStatusCode());
135 static::assertSame('/subfolder/install', $result->getHeader('location')[0]);
136 }
137
138 /**
139 * Call controller in session test mode: invalid session then redirect to error page.
140 */
141 public function testInstallSessionTestError(): void
142 {
143 $assignedVars = [];
144 $this->assignTemplateVars($assignedVars);
145
146 $request = $this->createMock(Request::class);
147 $response = new Response();
148
149 $this->container->sessionManager = $this->createMock(SessionManager::class);
150 $this->container->sessionManager
151 ->method('getSessionParameter')
152 ->with(InstallController::SESSION_TEST_KEY)
153 ->willReturn('KO')
154 ;
155
156 $result = $this->controller->sessionTest($request, $response);
157
158 static::assertSame(200, $result->getStatusCode());
159 static::assertSame('error', (string) $result->getBody());
160 static::assertStringStartsWith(
161 '<pre>Sessions do not seem to work correctly on your server',
162 $assignedVars['message']
163 );
164 }
165
166 /**
167 * Test saving valid data from install form. Also initialize datastore.
168 */
169 public function testSaveInstallValid(): void
170 {
171 $providedParameters = [
172 'continent' => 'Europe',
173 'city' => 'Berlin',
174 'setlogin' => 'bob',
175 'setpassword' => 'password',
176 'title' => 'Shaarli',
177 'language' => 'fr',
178 'updateCheck' => true,
179 'enableApi' => true,
180 ];
181
182 $expectedSettings = [
183 'general.timezone' => 'Europe/Berlin',
184 'credentials.login' => 'bob',
185 'credentials.salt' => '_NOT_EMPTY',
186 'credentials.hash' => '_NOT_EMPTY',
187 'general.title' => 'Shaarli',
188 'translation.language' => 'en',
189 'updates.check_updates' => true,
190 'api.enabled' => true,
191 'api.secret' => '_NOT_EMPTY',
192 'general.header_link' => '/subfolder',
193 ];
194
195 $request = $this->createMock(Request::class);
196 $request->method('getParam')->willReturnCallback(function (string $key) use ($providedParameters) {
197 return $providedParameters[$key] ?? null;
198 });
199 $response = new Response();
200
201 $this->container->conf = $this->createMock(ConfigManager::class);
202 $this->container->conf
203 ->method('get')
204 ->willReturnCallback(function (string $key, $value) {
205 if ($key === 'credentials.login') {
206 return 'bob';
207 } elseif ($key === 'credentials.salt') {
208 return 'salt';
209 }
210
211 return $value;
212 })
213 ;
214 $this->container->conf
215 ->expects(static::exactly(count($expectedSettings)))
216 ->method('set')
217 ->willReturnCallback(function (string $key, $value) use ($expectedSettings) {
218 if ($expectedSettings[$key] ?? null === '_NOT_EMPTY') {
219 static::assertNotEmpty($value);
220 } else {
221 static::assertSame($expectedSettings[$key], $value);
222 }
223 })
224 ;
225 $this->container->conf->expects(static::once())->method('write');
226
227 $this->container->sessionManager
228 ->expects(static::once())
229 ->method('setSessionParameter')
230 ->with(SessionManager::KEY_SUCCESS_MESSAGES)
231 ;
232
233 $result = $this->controller->save($request, $response);
234
235 static::assertSame(302, $result->getStatusCode());
236 static::assertSame('/subfolder/login', $result->getHeader('location')[0]);
237 }
238
239 /**
240 * Test default settings (timezone and title).
241 * Also check that bookmarks are not initialized if
242 */
243 public function testSaveInstallDefaultValues(): void
244 {
245 $confSettings = [];
246
247 $request = $this->createMock(Request::class);
248 $response = new Response();
249
250 $this->container->conf->method('set')->willReturnCallback(function (string $key, $value) use (&$confSettings) {
251 $confSettings[$key] = $value;
252 });
253
254 $result = $this->controller->save($request, $response);
255
256 static::assertSame(302, $result->getStatusCode());
257 static::assertSame('/subfolder/login', $result->getHeader('location')[0]);
258
259 static::assertSame('UTC', $confSettings['general.timezone']);
260 static::assertSame('Shared bookmarks on http://shaarli', $confSettings['general.title']);
261 }
262}
diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php
new file mode 100644
index 00000000..0a21f938
--- /dev/null
+++ b/tests/front/controller/visitor/LoginControllerTest.php
@@ -0,0 +1,404 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Config\ConfigManager;
9use Shaarli\Front\Exception\LoginBannedException;
10use Shaarli\Front\Exception\WrongTokenException;
11use Shaarli\Render\TemplatePage;
12use Shaarli\Security\CookieManager;
13use Shaarli\Security\SessionManager;
14use Slim\Http\Request;
15use Slim\Http\Response;
16
17class LoginControllerTest extends TestCase
18{
19 use FrontControllerMockHelper;
20
21 /** @var LoginController */
22 protected $controller;
23
24 public function setUp(): void
25 {
26 $this->createContainer();
27
28 $this->container->cookieManager = $this->createMock(CookieManager::class);
29 $this->container->sessionManager->method('checkToken')->willReturn(true);
30
31 $this->controller = new LoginController($this->container);
32 }
33
34 /**
35 * Test displaying login form with valid parameters.
36 */
37 public function testValidControllerInvoke(): void
38 {
39 $request = $this->createMock(Request::class);
40 $request
41 ->expects(static::atLeastOnce())
42 ->method('getParam')
43 ->willReturnCallback(function (string $key) {
44 return 'returnurl' === $key ? '> referer' : null;
45 })
46 ;
47 $response = new Response();
48
49 $assignedVariables = [];
50 $this->container->pageBuilder
51 ->method('assign')
52 ->willReturnCallback(function ($key, $value) use (&$assignedVariables) {
53 $assignedVariables[$key] = $value;
54
55 return $this;
56 })
57 ;
58
59 $this->container->loginManager->method('canLogin')->willReturn(true);
60
61 $result = $this->controller->index($request, $response);
62
63 static::assertInstanceOf(Response::class, $result);
64 static::assertSame(200, $result->getStatusCode());
65 static::assertSame(TemplatePage::LOGIN, (string) $result->getBody());
66
67 static::assertSame('&gt; referer', $assignedVariables['returnurl']);
68 static::assertSame(true, $assignedVariables['remember_user_default']);
69 static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']);
70 }
71
72 /**
73 * Test displaying login form with username defined in the request.
74 */
75 public function testValidControllerInvokeWithUserName(): void
76 {
77 $this->container->environment = ['HTTP_REFERER' => '> referer'];
78
79 $request = $this->createMock(Request::class);
80 $request
81 ->expects(static::atLeastOnce())
82 ->method('getParam')
83 ->willReturnCallback(function (string $key, $default) {
84 if ('login' === $key) {
85 return 'myUser>';
86 }
87
88 return $default;
89 })
90 ;
91 $response = new Response();
92
93 $assignedVariables = [];
94 $this->container->pageBuilder
95 ->method('assign')
96 ->willReturnCallback(function ($key, $value) use (&$assignedVariables) {
97 $assignedVariables[$key] = $value;
98
99 return $this;
100 })
101 ;
102
103 $this->container->loginManager->expects(static::once())->method('canLogin')->willReturn(true);
104
105 $result = $this->controller->index($request, $response);
106
107 static::assertInstanceOf(Response::class, $result);
108 static::assertSame(200, $result->getStatusCode());
109 static::assertSame('loginform', (string) $result->getBody());
110
111 static::assertSame('myUser&gt;', $assignedVariables['username']);
112 static::assertSame('&gt; referer', $assignedVariables['returnurl']);
113 static::assertSame(true, $assignedVariables['remember_user_default']);
114 static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']);
115 }
116
117 /**
118 * Test displaying login page while being logged in.
119 */
120 public function testLoginControllerWhileLoggedIn(): void
121 {
122 $request = $this->createMock(Request::class);
123 $response = new Response();
124
125 $this->container->loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true);
126
127 $result = $this->controller->index($request, $response);
128
129 static::assertInstanceOf(Response::class, $result);
130 static::assertSame(302, $result->getStatusCode());
131 static::assertSame(['/subfolder/'], $result->getHeader('Location'));
132 }
133
134 /**
135 * Test displaying login page with open shaarli configured: redirect to homepage.
136 */
137 public function testLoginControllerOpenShaarli(): void
138 {
139 $request = $this->createMock(Request::class);
140 $response = new Response();
141
142 $conf = $this->createMock(ConfigManager::class);
143 $conf->method('get')->willReturnCallback(function (string $parameter, $default) {
144 if ($parameter === 'security.open_shaarli') {
145 return true;
146 }
147 return $default;
148 });
149 $this->container->conf = $conf;
150
151 $result = $this->controller->index($request, $response);
152
153 static::assertInstanceOf(Response::class, $result);
154 static::assertSame(302, $result->getStatusCode());
155 static::assertSame(['/subfolder/'], $result->getHeader('Location'));
156 }
157
158 /**
159 * Test displaying login page while being banned.
160 */
161 public function testLoginControllerWhileBanned(): void
162 {
163 $request = $this->createMock(Request::class);
164 $response = new Response();
165
166 $this->container->loginManager->method('isLoggedIn')->willReturn(false);
167 $this->container->loginManager->method('canLogin')->willReturn(false);
168
169 $this->expectException(LoginBannedException::class);
170
171 $this->controller->index($request, $response);
172 }
173
174 /**
175 * Test processing login with valid parameters.
176 */
177 public function testProcessLoginWithValidParameters(): void
178 {
179 $parameters = [
180 'login' => 'bob',
181 'password' => 'pass',
182 ];
183 $request = $this->createMock(Request::class);
184 $request
185 ->expects(static::atLeastOnce())
186 ->method('getParam')
187 ->willReturnCallback(function (string $key) use ($parameters) {
188 return $parameters[$key] ?? null;
189 })
190 ;
191 $response = new Response();
192
193 $this->container->loginManager->method('canLogin')->willReturn(true);
194 $this->container->loginManager->expects(static::once())->method('handleSuccessfulLogin');
195 $this->container->loginManager
196 ->expects(static::once())
197 ->method('checkCredentials')
198 ->with('1.2.3.4', '1.2.3.4', 'bob', 'pass')
199 ->willReturn(true)
200 ;
201 $this->container->loginManager->method('getStaySignedInToken')->willReturn(bin2hex(random_bytes(8)));
202
203 $this->container->sessionManager->expects(static::never())->method('extendSession');
204 $this->container->sessionManager->expects(static::once())->method('destroy');
205 $this->container->sessionManager
206 ->expects(static::once())
207 ->method('cookieParameters')
208 ->with(0, '/subfolder/', 'shaarli')
209 ;
210 $this->container->sessionManager->expects(static::once())->method('start');
211 $this->container->sessionManager->expects(static::once())->method('regenerateId')->with(true);
212
213 $result = $this->controller->login($request, $response);
214
215 static::assertSame(302, $result->getStatusCode());
216 static::assertSame('/subfolder/', $result->getHeader('location')[0]);
217 }
218
219 /**
220 * Test processing login with return URL.
221 */
222 public function testProcessLoginWithReturnUrl(): void
223 {
224 $parameters = [
225 'returnurl' => 'http://shaarli/subfolder/admin/shaare',
226 ];
227 $request = $this->createMock(Request::class);
228 $request
229 ->expects(static::atLeastOnce())
230 ->method('getParam')
231 ->willReturnCallback(function (string $key) use ($parameters) {
232 return $parameters[$key] ?? null;
233 })
234 ;
235 $response = new Response();
236
237 $this->container->loginManager->method('canLogin')->willReturn(true);
238 $this->container->loginManager->expects(static::once())->method('handleSuccessfulLogin');
239 $this->container->loginManager->expects(static::once())->method('checkCredentials')->willReturn(true);
240 $this->container->loginManager->method('getStaySignedInToken')->willReturn(bin2hex(random_bytes(8)));
241
242 $result = $this->controller->login($request, $response);
243
244 static::assertSame(302, $result->getStatusCode());
245 static::assertSame('/subfolder/admin/shaare', $result->getHeader('location')[0]);
246 }
247
248 /**
249 * Test processing login with remember me session enabled.
250 */
251 public function testProcessLoginLongLastingSession(): void
252 {
253 $parameters = [
254 'longlastingsession' => true,
255 ];
256 $request = $this->createMock(Request::class);
257 $request
258 ->expects(static::atLeastOnce())
259 ->method('getParam')
260 ->willReturnCallback(function (string $key) use ($parameters) {
261 return $parameters[$key] ?? null;
262 })
263 ;
264 $response = new Response();
265
266 $this->container->loginManager->method('canLogin')->willReturn(true);
267 $this->container->loginManager->expects(static::once())->method('handleSuccessfulLogin');
268 $this->container->loginManager->expects(static::once())->method('checkCredentials')->willReturn(true);
269 $this->container->loginManager->method('getStaySignedInToken')->willReturn(bin2hex(random_bytes(8)));
270
271 $this->container->sessionManager->expects(static::once())->method('destroy');
272 $this->container->sessionManager
273 ->expects(static::once())
274 ->method('cookieParameters')
275 ->with(42, '/subfolder/', 'shaarli')
276 ;
277 $this->container->sessionManager->expects(static::once())->method('start');
278 $this->container->sessionManager->expects(static::once())->method('regenerateId')->with(true);
279 $this->container->sessionManager->expects(static::once())->method('extendSession')->willReturn(42);
280
281 $this->container->cookieManager = $this->createMock(CookieManager::class);
282 $this->container->cookieManager
283 ->expects(static::once())
284 ->method('setCookieParameter')
285 ->willReturnCallback(function (string $name): CookieManager {
286 static::assertSame(CookieManager::STAY_SIGNED_IN, $name);
287
288 return $this->container->cookieManager;
289 })
290 ;
291
292 $result = $this->controller->login($request, $response);
293
294 static::assertSame(302, $result->getStatusCode());
295 static::assertSame('/subfolder/', $result->getHeader('location')[0]);
296 }
297
298 /**
299 * Test processing login with invalid credentials
300 */
301 public function testProcessLoginWrongCredentials(): void
302 {
303 $parameters = [
304 'returnurl' => 'http://shaarli/subfolder/admin/shaare',
305 ];
306 $request = $this->createMock(Request::class);
307 $request
308 ->expects(static::atLeastOnce())
309 ->method('getParam')
310 ->willReturnCallback(function (string $key) use ($parameters) {
311 return $parameters[$key] ?? null;
312 })
313 ;
314 $response = new Response();
315
316 $this->container->loginManager->method('canLogin')->willReturn(true);
317 $this->container->loginManager->expects(static::once())->method('handleFailedLogin');
318 $this->container->loginManager->expects(static::once())->method('checkCredentials')->willReturn(false);
319
320 $this->container->sessionManager
321 ->expects(static::once())
322 ->method('setSessionParameter')
323 ->with(SessionManager::KEY_ERROR_MESSAGES, ['Wrong login/password.'])
324 ;
325
326 $result = $this->controller->login($request, $response);
327
328 static::assertSame(200, $result->getStatusCode());
329 static::assertSame(TemplatePage::LOGIN, (string) $result->getBody());
330 }
331
332 /**
333 * Test processing login with wrong token
334 */
335 public function testProcessLoginWrongToken(): void
336 {
337 $request = $this->createMock(Request::class);
338 $response = new Response();
339
340 $this->container->sessionManager = $this->createMock(SessionManager::class);
341 $this->container->sessionManager->method('checkToken')->willReturn(false);
342
343 $this->expectException(WrongTokenException::class);
344
345 $this->controller->login($request, $response);
346 }
347
348 /**
349 * Test processing login with wrong token
350 */
351 public function testProcessLoginAlreadyLoggedIn(): void
352 {
353 $request = $this->createMock(Request::class);
354 $response = new Response();
355
356 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
357 $this->container->loginManager->expects(static::never())->method('handleSuccessfulLogin');
358 $this->container->loginManager->expects(static::never())->method('handleFailedLogin');
359
360 $result = $this->controller->login($request, $response);
361
362 static::assertSame(302, $result->getStatusCode());
363 static::assertSame('/subfolder/', $result->getHeader('location')[0]);
364 }
365
366 /**
367 * Test processing login with wrong token
368 */
369 public function testProcessLoginInOpenShaarli(): void
370 {
371 $request = $this->createMock(Request::class);
372 $response = new Response();
373
374 $this->container->conf = $this->createMock(ConfigManager::class);
375 $this->container->conf->method('get')->willReturnCallback(function (string $key, $value) {
376 return 'security.open_shaarli' === $key ? true : $value;
377 });
378
379 $this->container->loginManager->expects(static::never())->method('handleSuccessfulLogin');
380 $this->container->loginManager->expects(static::never())->method('handleFailedLogin');
381
382 $result = $this->controller->login($request, $response);
383
384 static::assertSame(302, $result->getStatusCode());
385 static::assertSame('/subfolder/', $result->getHeader('location')[0]);
386 }
387
388 /**
389 * Test processing login while being banned
390 */
391 public function testProcessLoginWhileBanned(): void
392 {
393 $request = $this->createMock(Request::class);
394 $response = new Response();
395
396 $this->container->loginManager->method('canLogin')->willReturn(false);
397 $this->container->loginManager->expects(static::never())->method('handleSuccessfulLogin');
398 $this->container->loginManager->expects(static::never())->method('handleFailedLogin');
399
400 $this->expectException(LoginBannedException::class);
401
402 $this->controller->login($request, $response);
403 }
404}
diff --git a/tests/front/controller/visitor/OpenSearchControllerTest.php b/tests/front/controller/visitor/OpenSearchControllerTest.php
new file mode 100644
index 00000000..5f9f5b12
--- /dev/null
+++ b/tests/front/controller/visitor/OpenSearchControllerTest.php
@@ -0,0 +1,44 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11class 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 $request = $this->createMock(Request::class);
28 $response = new Response();
29
30 // Save RainTPL assigned variables
31 $assignedVariables = [];
32 $this->assignTemplateVars($assignedVariables);
33
34 $result = $this->controller->index($request, $response);
35
36 static::assertSame(200, $result->getStatusCode());
37 static::assertStringContainsString(
38 'application/opensearchdescription+xml',
39 $result->getHeader('Content-Type')[0]
40 );
41 static::assertSame('opensearch', (string) $result->getBody());
42 static::assertSame('http://shaarli', $assignedVariables['serverurl']);
43 }
44}
diff --git a/tests/front/controller/visitor/PictureWallControllerTest.php b/tests/front/controller/visitor/PictureWallControllerTest.php
new file mode 100644
index 00000000..3dc3f292
--- /dev/null
+++ b/tests/front/controller/visitor/PictureWallControllerTest.php
@@ -0,0 +1,121 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\Bookmark;
9use Shaarli\Config\ConfigManager;
10use Shaarli\Front\Exception\ThumbnailsDisabledException;
11use Shaarli\Thumbnailer;
12use Slim\Http\Request;
13use Slim\Http\Response;
14
15class 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 $request = $this->createMock(Request::class);
32 $request->expects(static::once())->method('getQueryParams')->willReturn([]);
33 $response = new Response();
34
35 // ConfigManager: thumbnails are enabled
36 $this->container->conf = $this->createMock(ConfigManager::class);
37 $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) {
38 if ($parameter === 'thumbnails.mode') {
39 return Thumbnailer::MODE_COMMON;
40 }
41
42 return $default;
43 });
44
45 // Save RainTPL assigned variables
46 $assignedVariables = [];
47 $this->assignTemplateVars($assignedVariables);
48
49 // Links dataset: 2 links with thumbnails
50 $this->container->bookmarkService
51 ->expects(static::once())
52 ->method('search')
53 ->willReturnCallback(function (array $parameters, ?string $visibility): array {
54 // Visibility is set through the container, not the call
55 static::assertNull($visibility);
56
57 // No query parameters
58 if (count($parameters) === 0) {
59 return [
60 (new Bookmark())->setId(1)->setUrl('http://url.tld')->setThumbnail('thumb1'),
61 (new Bookmark())->setId(2)->setUrl('http://url2.tld'),
62 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setThumbnail('thumb2'),
63 ];
64 }
65 })
66 ;
67
68 // Make sure that PluginManager hook is triggered
69 $this->container->pluginManager
70 ->expects(static::at(0))
71 ->method('executeHooks')
72 ->willReturnCallback(function (string $hook, array $data, array $param): array {
73 static::assertSame('render_picwall', $hook);
74 static::assertArrayHasKey('linksToDisplay', $data);
75 static::assertCount(2, $data['linksToDisplay']);
76 static::assertSame(1, $data['linksToDisplay'][0]['id']);
77 static::assertSame(3, $data['linksToDisplay'][1]['id']);
78 static::assertArrayHasKey('loggedin', $param);
79
80 return $data;
81 });
82
83 $result = $this->controller->index($request, $response);
84
85 static::assertSame(200, $result->getStatusCode());
86 static::assertSame('picwall', (string) $result->getBody());
87 static::assertSame('Picture wall - Shaarli', $assignedVariables['pagetitle']);
88 static::assertCount(2, $assignedVariables['linksToDisplay']);
89
90 $link = $assignedVariables['linksToDisplay'][0];
91
92 static::assertSame(1, $link['id']);
93 static::assertSame('http://url.tld', $link['url']);
94 static::assertSame('thumb1', $link['thumbnail']);
95
96 $link = $assignedVariables['linksToDisplay'][1];
97
98 static::assertSame(3, $link['id']);
99 static::assertSame('http://url3.tld', $link['url']);
100 static::assertSame('thumb2', $link['thumbnail']);
101 }
102
103 public function testControllerWithThumbnailsDisabled(): void
104 {
105 $this->expectException(ThumbnailsDisabledException::class);
106
107 $request = $this->createMock(Request::class);
108 $response = new Response();
109
110 // ConfigManager: thumbnails are disabled
111 $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) {
112 if ($parameter === 'thumbnails.mode') {
113 return Thumbnailer::MODE_NONE;
114 }
115
116 return $default;
117 });
118
119 $this->controller->index($request, $response);
120 }
121}
diff --git a/tests/front/controller/visitor/PublicSessionFilterControllerTest.php b/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
new file mode 100644
index 00000000..06352750
--- /dev/null
+++ b/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
@@ -0,0 +1,122 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Security\SessionManager;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12class PublicSessionFilterControllerTest extends TestCase
13{
14 use FrontControllerMockHelper;
15
16 /** @var PublicSessionFilterController */
17 protected $controller;
18
19 public function setUp(): void
20 {
21 $this->createContainer();
22
23 $this->controller = new PublicSessionFilterController($this->container);
24 }
25
26 /**
27 * Link per page - Default call with valid parameter and a referer.
28 */
29 public function testLinksPerPage(): void
30 {
31 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
32
33 $request = $this->createMock(Request::class);
34 $request->method('getParam')->with('nb')->willReturn('8');
35 $response = new Response();
36
37 $this->container->sessionManager
38 ->expects(static::once())
39 ->method('setSessionParameter')
40 ->with(SessionManager::KEY_LINKS_PER_PAGE, 8)
41 ;
42
43 $result = $this->controller->linksPerPage($request, $response);
44
45 static::assertInstanceOf(Response::class, $result);
46 static::assertSame(302, $result->getStatusCode());
47 static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
48 }
49
50 /**
51 * Link per page - Invalid value, should use default value (20)
52 */
53 public function testLinksPerPageNotValid(): void
54 {
55 $request = $this->createMock(Request::class);
56 $request->method('getParam')->with('nb')->willReturn('test');
57 $response = new Response();
58
59 $this->container->sessionManager
60 ->expects(static::once())
61 ->method('setSessionParameter')
62 ->with(SessionManager::KEY_LINKS_PER_PAGE, 20)
63 ;
64
65 $result = $this->controller->linksPerPage($request, $response);
66
67 static::assertInstanceOf(Response::class, $result);
68 static::assertSame(302, $result->getStatusCode());
69 static::assertSame(['/subfolder/'], $result->getHeader('location'));
70 }
71
72 /**
73 * Untagged only - valid call
74 */
75 public function testUntaggedOnly(): void
76 {
77 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
78
79 $request = $this->createMock(Request::class);
80 $response = new Response();
81
82 $this->container->sessionManager
83 ->expects(static::once())
84 ->method('setSessionParameter')
85 ->with(SessionManager::KEY_UNTAGGED_ONLY, true)
86 ;
87
88 $result = $this->controller->untaggedOnly($request, $response);
89
90 static::assertInstanceOf(Response::class, $result);
91 static::assertSame(302, $result->getStatusCode());
92 static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
93 }
94
95 /**
96 * Untagged only - toggle off
97 */
98 public function testUntaggedOnlyToggleOff(): void
99 {
100 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
101
102 $request = $this->createMock(Request::class);
103 $response = new Response();
104
105 $this->container->sessionManager
106 ->method('getSessionParameter')
107 ->with(SessionManager::KEY_UNTAGGED_ONLY)
108 ->willReturn(true)
109 ;
110 $this->container->sessionManager
111 ->expects(static::once())
112 ->method('setSessionParameter')
113 ->with(SessionManager::KEY_UNTAGGED_ONLY, false)
114 ;
115
116 $result = $this->controller->untaggedOnly($request, $response);
117
118 static::assertInstanceOf(Response::class, $result);
119 static::assertSame(302, $result->getStatusCode());
120 static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
121 }
122}
diff --git a/tests/front/controller/visitor/ShaarliVisitorControllerTest.php b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php
new file mode 100644
index 00000000..316ce49c
--- /dev/null
+++ b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php
@@ -0,0 +1,215 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\BookmarkFilter;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12/**
13 * Class ShaarliControllerTest
14 *
15 * This class is used to test default behavior of ShaarliVisitorController abstract class.
16 * It uses a dummy non abstract controller.
17 */
18class ShaarliVisitorControllerTest extends TestCase
19{
20 use FrontControllerMockHelper;
21
22 /** @var LoginController */
23 protected $controller;
24
25 /** @var mixed[] List of variable assigned to the template */
26 protected $assignedValues;
27
28 /** @var Request */
29 protected $request;
30
31 public function setUp(): void
32 {
33 $this->createContainer();
34
35 $this->controller = new class($this->container) extends ShaarliVisitorController
36 {
37 public function assignView(string $key, $value): ShaarliVisitorController
38 {
39 return parent::assignView($key, $value);
40 }
41
42 public function render(string $template): string
43 {
44 return parent::render($template);
45 }
46
47 public function redirectFromReferer(
48 Request $request,
49 Response $response,
50 array $loopTerms = [],
51 array $clearParams = [],
52 string $anchor = null
53 ): Response {
54 return parent::redirectFromReferer($request, $response, $loopTerms, $clearParams, $anchor);
55 }
56 };
57 $this->assignedValues = [];
58
59 $this->request = $this->createMock(Request::class);
60 }
61
62 public function testAssignView(): void
63 {
64 $this->assignTemplateVars($this->assignedValues);
65
66 $self = $this->controller->assignView('variableName', 'variableValue');
67
68 static::assertInstanceOf(ShaarliVisitorController::class, $self);
69 static::assertSame('variableValue', $this->assignedValues['variableName']);
70 }
71
72 public function testRender(): void
73 {
74 $this->assignTemplateVars($this->assignedValues);
75
76 $this->container->bookmarkService
77 ->method('count')
78 ->willReturnCallback(function (string $visibility): int {
79 return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10;
80 })
81 ;
82
83 $this->container->pluginManager
84 ->method('executeHooks')
85 ->willReturnCallback(function (string $hook, array &$data, array $params): array {
86 return $data[$hook] = $params;
87 });
88 $this->container->pluginManager->method('getErrors')->willReturn(['error']);
89
90 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
91
92 $render = $this->controller->render('templateName');
93
94 static::assertSame('templateName', $render);
95
96 static::assertSame(10, $this->assignedValues['linkcount']);
97 static::assertSame(5, $this->assignedValues['privateLinkcount']);
98 static::assertSame(['error'], $this->assignedValues['plugin_errors']);
99
100 static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']);
101 static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']);
102 static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']);
103 static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']);
104 static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']);
105 static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']);
106 }
107
108 /**
109 * Test redirectFromReferer() - Default behaviour
110 */
111 public function testRedirectFromRefererDefault(): void
112 {
113 $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2';
114
115 $response = new Response();
116
117 $result = $this->controller->redirectFromReferer($this->request, $response);
118
119 static::assertSame(302, $result->getStatusCode());
120 static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location'));
121 }
122
123 /**
124 * Test redirectFromReferer() - With a loop term not matched in the referer
125 */
126 public function testRedirectFromRefererWithUnmatchedLoopTerm(): void
127 {
128 $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2';
129
130 $response = new Response();
131
132 $result = $this->controller->redirectFromReferer($this->request, $response, ['nope']);
133
134 static::assertSame(302, $result->getStatusCode());
135 static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location'));
136 }
137
138 /**
139 * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default
140 */
141 public function testRedirectFromRefererWithMatchingLoopTermInPath(): void
142 {
143 $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2';
144
145 $response = new Response();
146
147 $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'controller']);
148
149 static::assertSame(302, $result->getStatusCode());
150 static::assertSame(['/subfolder/'], $result->getHeader('location'));
151 }
152
153 /**
154 * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default
155 */
156 public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void
157 {
158 $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2';
159
160 $response = new Response();
161
162 $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'other']);
163
164 static::assertSame(302, $result->getStatusCode());
165 static::assertSame(['/subfolder/'], $result->getHeader('location'));
166 }
167
168 /**
169 * Test redirectFromReferer() - With a loop term matching the referer in its query value
170 * -> we do not block redirection for query parameter values.
171 */
172 public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void
173 {
174 $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2';
175
176 $response = new Response();
177
178 $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'param']);
179
180 static::assertSame(302, $result->getStatusCode());
181 static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location'));
182 }
183
184 /**
185 * Test redirectFromReferer() - With a loop term matching the referer in its domain name
186 * -> we do not block redirection for shaarli's hosts
187 */
188 public function testRedirectFromRefererWithLoopTermInDomain(): void
189 {
190 $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2';
191
192 $response = new Response();
193
194 $result = $this->controller->redirectFromReferer($this->request, $response, ['shaarli']);
195
196 static::assertSame(302, $result->getStatusCode());
197 static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location'));
198 }
199
200 /**
201 * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param
202 * -> the param should be cleared before checking if it matches the redir loop terms
203 */
204 public function testRedirectFromRefererWithMatchingClearedParam(): void
205 {
206 $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2';
207
208 $response = new Response();
209
210 $result = $this->controller->redirectFromReferer($this->request, $response, ['query'], ['query']);
211
212 static::assertSame(302, $result->getStatusCode());
213 static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location'));
214 }
215}
diff --git a/tests/front/controller/visitor/TagCloudControllerTest.php b/tests/front/controller/visitor/TagCloudControllerTest.php
new file mode 100644
index 00000000..9a6a4bc0
--- /dev/null
+++ b/tests/front/controller/visitor/TagCloudControllerTest.php
@@ -0,0 +1,369 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Bookmark\BookmarkFilter;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12class 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 $allTags = [
32 'ghi' => 1,
33 'abc' => 3,
34 'def' => 12,
35 ];
36 $expectedOrder = ['abc', 'def', 'ghi'];
37
38 $request = $this->createMock(Request::class);
39 $response = new Response();
40
41 // Save RainTPL assigned variables
42 $assignedVariables = [];
43 $this->assignTemplateVars($assignedVariables);
44
45 $this->container->bookmarkService
46 ->expects(static::once())
47 ->method('bookmarksCountPerTag')
48 ->with([], null)
49 ->willReturnCallback(function () use ($allTags): array {
50 return $allTags;
51 })
52 ;
53
54 // Make sure that PluginManager hook is triggered
55 $this->container->pluginManager
56 ->expects(static::at(0))
57 ->method('executeHooks')
58 ->willReturnCallback(function (string $hook, array $data, array $param): array {
59 static::assertSame('render_tagcloud', $hook);
60 static::assertSame('', $data['search_tags']);
61 static::assertCount(3, $data['tags']);
62
63 static::assertArrayHasKey('loggedin', $param);
64
65 return $data;
66 })
67 ;
68
69 $result = $this->controller->cloud($request, $response);
70
71 static::assertSame(200, $result->getStatusCode());
72 static::assertSame('tag.cloud', (string) $result->getBody());
73 static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']);
74
75 static::assertSame('', $assignedVariables['search_tags']);
76 static::assertCount(3, $assignedVariables['tags']);
77 static::assertSame($expectedOrder, array_keys($assignedVariables['tags']));
78
79 foreach ($allTags as $tag => $count) {
80 static::assertArrayHasKey($tag, $assignedVariables['tags']);
81 static::assertSame($count, $assignedVariables['tags'][$tag]['count']);
82 static::assertGreaterThan(0, $assignedVariables['tags'][$tag]['size']);
83 static::assertLessThan(5, $assignedVariables['tags'][$tag]['size']);
84 }
85 }
86
87 /**
88 * Tag Cloud - Additional parameters:
89 * - logged in
90 * - visibility private
91 * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore)
92 */
93 public function testValidCloudControllerInvokeWithParameters(): void
94 {
95 $request = $this->createMock(Request::class);
96 $request
97 ->method('getQueryParam')
98 ->with()
99 ->willReturnCallback(function (string $key): ?string {
100 if ('searchtags' === $key) {
101 return 'ghi def';
102 }
103
104 return null;
105 })
106 ;
107 $response = new Response();
108
109 // Save RainTPL assigned variables
110 $assignedVariables = [];
111 $this->assignTemplateVars($assignedVariables);
112
113 $this->container->loginManager->method('isLoggedin')->willReturn(true);
114 $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private');
115
116 $this->container->bookmarkService
117 ->expects(static::once())
118 ->method('bookmarksCountPerTag')
119 ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE)
120 ->willReturnCallback(function (): array {
121 return ['abc' => 3];
122 })
123 ;
124
125 // Make sure that PluginManager hook is triggered
126 $this->container->pluginManager
127 ->expects(static::at(0))
128 ->method('executeHooks')
129 ->willReturnCallback(function (string $hook, array $data, array $param): array {
130 static::assertSame('render_tagcloud', $hook);
131 static::assertSame('ghi def', $data['search_tags']);
132 static::assertCount(1, $data['tags']);
133
134 static::assertArrayHasKey('loggedin', $param);
135
136 return $data;
137 })
138 ;
139
140 $result = $this->controller->cloud($request, $response);
141
142 static::assertSame(200, $result->getStatusCode());
143 static::assertSame('tag.cloud', (string) $result->getBody());
144 static::assertSame('ghi def - Tag cloud - Shaarli', $assignedVariables['pagetitle']);
145
146 static::assertSame('ghi def', $assignedVariables['search_tags']);
147 static::assertCount(1, $assignedVariables['tags']);
148
149 static::assertArrayHasKey('abc', $assignedVariables['tags']);
150 static::assertSame(3, $assignedVariables['tags']['abc']['count']);
151 static::assertGreaterThan(0, $assignedVariables['tags']['abc']['size']);
152 static::assertLessThan(5, $assignedVariables['tags']['abc']['size']);
153 }
154
155 /**
156 * Tag Cloud - empty
157 */
158 public function testEmptyCloud(): void
159 {
160 $request = $this->createMock(Request::class);
161 $response = new Response();
162
163 // Save RainTPL assigned variables
164 $assignedVariables = [];
165 $this->assignTemplateVars($assignedVariables);
166
167 $this->container->bookmarkService
168 ->expects(static::once())
169 ->method('bookmarksCountPerTag')
170 ->with([], null)
171 ->willReturnCallback(function (array $parameters, ?string $visibility): array {
172 return [];
173 })
174 ;
175
176 // Make sure that PluginManager hook is triggered
177 $this->container->pluginManager
178 ->expects(static::at(0))
179 ->method('executeHooks')
180 ->willReturnCallback(function (string $hook, array $data, array $param): array {
181 static::assertSame('render_tagcloud', $hook);
182 static::assertSame('', $data['search_tags']);
183 static::assertCount(0, $data['tags']);
184
185 static::assertArrayHasKey('loggedin', $param);
186
187 return $data;
188 })
189 ;
190
191 $result = $this->controller->cloud($request, $response);
192
193 static::assertSame(200, $result->getStatusCode());
194 static::assertSame('tag.cloud', (string) $result->getBody());
195 static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']);
196
197 static::assertSame('', $assignedVariables['search_tags']);
198 static::assertCount(0, $assignedVariables['tags']);
199 }
200
201 /**
202 * Tag List - Default sort is by usage DESC
203 */
204 public function testValidListControllerInvokeDefault(): void
205 {
206 $allTags = [
207 'def' => 12,
208 'abc' => 3,
209 'ghi' => 1,
210 ];
211
212 $request = $this->createMock(Request::class);
213 $response = new Response();
214
215 // Save RainTPL assigned variables
216 $assignedVariables = [];
217 $this->assignTemplateVars($assignedVariables);
218
219 $this->container->bookmarkService
220 ->expects(static::once())
221 ->method('bookmarksCountPerTag')
222 ->with([], null)
223 ->willReturnCallback(function () use ($allTags): array {
224 return $allTags;
225 })
226 ;
227
228 // Make sure that PluginManager hook is triggered
229 $this->container->pluginManager
230 ->expects(static::at(0))
231 ->method('executeHooks')
232 ->willReturnCallback(function (string $hook, array $data, array $param): array {
233 static::assertSame('render_taglist', $hook);
234 static::assertSame('', $data['search_tags']);
235 static::assertCount(3, $data['tags']);
236
237 static::assertArrayHasKey('loggedin', $param);
238
239 return $data;
240 })
241 ;
242
243 $result = $this->controller->list($request, $response);
244
245 static::assertSame(200, $result->getStatusCode());
246 static::assertSame('tag.list', (string) $result->getBody());
247 static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']);
248
249 static::assertSame('', $assignedVariables['search_tags']);
250 static::assertCount(3, $assignedVariables['tags']);
251
252 foreach ($allTags as $tag => $count) {
253 static::assertSame($count, $assignedVariables['tags'][$tag]);
254 }
255 }
256
257 /**
258 * Tag List - Additional parameters:
259 * - logged in
260 * - visibility private
261 * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore)
262 * - sort alphabetically
263 */
264 public function testValidListControllerInvokeWithParameters(): void
265 {
266 $request = $this->createMock(Request::class);
267 $request
268 ->method('getQueryParam')
269 ->with()
270 ->willReturnCallback(function (string $key): ?string {
271 if ('searchtags' === $key) {
272 return 'ghi def';
273 } elseif ('sort' === $key) {
274 return 'alpha';
275 }
276
277 return null;
278 })
279 ;
280 $response = new Response();
281
282 // Save RainTPL assigned variables
283 $assignedVariables = [];
284 $this->assignTemplateVars($assignedVariables);
285
286 $this->container->loginManager->method('isLoggedin')->willReturn(true);
287 $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private');
288
289 $this->container->bookmarkService
290 ->expects(static::once())
291 ->method('bookmarksCountPerTag')
292 ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE)
293 ->willReturnCallback(function (): array {
294 return ['abc' => 3];
295 })
296 ;
297
298 // Make sure that PluginManager hook is triggered
299 $this->container->pluginManager
300 ->expects(static::at(0))
301 ->method('executeHooks')
302 ->willReturnCallback(function (string $hook, array $data, array $param): array {
303 static::assertSame('render_taglist', $hook);
304 static::assertSame('ghi def', $data['search_tags']);
305 static::assertCount(1, $data['tags']);
306
307 static::assertArrayHasKey('loggedin', $param);
308
309 return $data;
310 })
311 ;
312
313 $result = $this->controller->list($request, $response);
314
315 static::assertSame(200, $result->getStatusCode());
316 static::assertSame('tag.list', (string) $result->getBody());
317 static::assertSame('ghi def - Tag list - Shaarli', $assignedVariables['pagetitle']);
318
319 static::assertSame('ghi def', $assignedVariables['search_tags']);
320 static::assertCount(1, $assignedVariables['tags']);
321 static::assertSame(3, $assignedVariables['tags']['abc']);
322 }
323
324 /**
325 * Tag List - empty
326 */
327 public function testEmptyList(): void
328 {
329 $request = $this->createMock(Request::class);
330 $response = new Response();
331
332 // Save RainTPL assigned variables
333 $assignedVariables = [];
334 $this->assignTemplateVars($assignedVariables);
335
336 $this->container->bookmarkService
337 ->expects(static::once())
338 ->method('bookmarksCountPerTag')
339 ->with([], null)
340 ->willReturnCallback(function (array $parameters, ?string $visibility): array {
341 return [];
342 })
343 ;
344
345 // Make sure that PluginManager hook is triggered
346 $this->container->pluginManager
347 ->expects(static::at(0))
348 ->method('executeHooks')
349 ->willReturnCallback(function (string $hook, array $data, array $param): array {
350 static::assertSame('render_taglist', $hook);
351 static::assertSame('', $data['search_tags']);
352 static::assertCount(0, $data['tags']);
353
354 static::assertArrayHasKey('loggedin', $param);
355
356 return $data;
357 })
358 ;
359
360 $result = $this->controller->list($request, $response);
361
362 static::assertSame(200, $result->getStatusCode());
363 static::assertSame('tag.list', (string) $result->getBody());
364 static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']);
365
366 static::assertSame('', $assignedVariables['search_tags']);
367 static::assertCount(0, $assignedVariables['tags']);
368 }
369}
diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php
new file mode 100644
index 00000000..43076086
--- /dev/null
+++ b/tests/front/controller/visitor/TagControllerTest.php
@@ -0,0 +1,215 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Visitor;
6
7use PHPUnit\Framework\TestCase;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11class 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->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/'];
27
28 $request = $this->createMock(Request::class);
29 $response = new Response();
30
31 $tags = ['newTag' => 'abc'];
32
33 $result = $this->controller->addTag($request, $response, $tags);
34
35 static::assertInstanceOf(Response::class, $result);
36 static::assertSame(302, $result->getStatusCode());
37 static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location'));
38 }
39
40 public function testAddTagWithRefererAndExistingSearch(): void
41 {
42 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def'];
43
44 $request = $this->createMock(Request::class);
45 $response = new Response();
46
47 $tags = ['newTag' => 'abc'];
48
49 $result = $this->controller->addTag($request, $response, $tags);
50
51 static::assertInstanceOf(Response::class, $result);
52 static::assertSame(302, $result->getStatusCode());
53 static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location'));
54 }
55
56 public function testAddTagWithoutRefererAndExistingSearch(): void
57 {
58 $request = $this->createMock(Request::class);
59 $response = new Response();
60
61 $tags = ['newTag' => 'abc'];
62
63 $result = $this->controller->addTag($request, $response, $tags);
64
65 static::assertInstanceOf(Response::class, $result);
66 static::assertSame(302, $result->getStatusCode());
67 static::assertSame(['/subfolder/?searchtags=abc'], $result->getHeader('location'));
68 }
69
70 public function testAddTagRemoveLegacyQueryParam(): void
71 {
72 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc'];
73
74 $request = $this->createMock(Request::class);
75 $response = new Response();
76
77 $tags = ['newTag' => 'abc'];
78
79 $result = $this->controller->addTag($request, $response, $tags);
80
81 static::assertInstanceOf(Response::class, $result);
82 static::assertSame(302, $result->getStatusCode());
83 static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location'));
84 }
85
86 public function testAddTagResetPagination(): void
87 {
88 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12'];
89
90 $request = $this->createMock(Request::class);
91 $response = new Response();
92
93 $tags = ['newTag' => 'abc'];
94
95 $result = $this->controller->addTag($request, $response, $tags);
96
97 static::assertInstanceOf(Response::class, $result);
98 static::assertSame(302, $result->getStatusCode());
99 static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location'));
100 }
101
102 public function testAddTagWithRefererAndEmptySearch(): void
103 {
104 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags='];
105
106 $request = $this->createMock(Request::class);
107 $response = new Response();
108
109 $tags = ['newTag' => 'abc'];
110
111 $result = $this->controller->addTag($request, $response, $tags);
112
113 static::assertInstanceOf(Response::class, $result);
114 static::assertSame(302, $result->getStatusCode());
115 static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location'));
116 }
117
118 public function testAddTagWithoutNewTagWithReferer(): void
119 {
120 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def'];
121
122 $request = $this->createMock(Request::class);
123 $response = new Response();
124
125 $result = $this->controller->addTag($request, $response, []);
126
127 static::assertInstanceOf(Response::class, $result);
128 static::assertSame(302, $result->getStatusCode());
129 static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location'));
130 }
131
132 public function testAddTagWithoutNewTagWithoutReferer(): void
133 {
134 $request = $this->createMock(Request::class);
135 $response = new Response();
136
137 $result = $this->controller->addTag($request, $response, []);
138
139 static::assertInstanceOf(Response::class, $result);
140 static::assertSame(302, $result->getStatusCode());
141 static::assertSame(['/subfolder/'], $result->getHeader('location'));
142 }
143
144 public function testRemoveTagWithoutMatchingTag(): void
145 {
146 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def'];
147
148 $request = $this->createMock(Request::class);
149 $response = new Response();
150
151 $tags = ['tag' => 'abc'];
152
153 $result = $this->controller->removeTag($request, $response, $tags);
154
155 static::assertInstanceOf(Response::class, $result);
156 static::assertSame(302, $result->getStatusCode());
157 static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location'));
158 }
159
160 public function testRemoveTagWithoutTagsearch(): void
161 {
162 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/'];
163
164 $request = $this->createMock(Request::class);
165 $response = new Response();
166
167 $tags = ['tag' => 'abc'];
168
169 $result = $this->controller->removeTag($request, $response, $tags);
170
171 static::assertInstanceOf(Response::class, $result);
172 static::assertSame(302, $result->getStatusCode());
173 static::assertSame(['/controller/'], $result->getHeader('location'));
174 }
175
176 public function testRemoveTagWithoutReferer(): void
177 {
178 $request = $this->createMock(Request::class);
179 $response = new Response();
180
181 $tags = ['tag' => 'abc'];
182
183 $result = $this->controller->removeTag($request, $response, $tags);
184
185 static::assertInstanceOf(Response::class, $result);
186 static::assertSame(302, $result->getStatusCode());
187 static::assertSame(['/subfolder/'], $result->getHeader('location'));
188 }
189
190 public function testRemoveTagWithoutTag(): void
191 {
192 $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc'];
193
194 $request = $this->createMock(Request::class);
195 $response = new Response();
196
197 $result = $this->controller->removeTag($request, $response, []);
198
199 static::assertInstanceOf(Response::class, $result);
200 static::assertSame(302, $result->getStatusCode());
201 static::assertSame(['/controller/?searchtag=abc'], $result->getHeader('location'));
202 }
203
204 public function testRemoveTagWithoutTagWithoutReferer(): void
205 {
206 $request = $this->createMock(Request::class);
207 $response = new Response();
208
209 $result = $this->controller->removeTag($request, $response, []);
210
211 static::assertInstanceOf(Response::class, $result);
212 static::assertSame(302, $result->getStatusCode());
213 static::assertSame(['/subfolder/'], $result->getHeader('location'));
214 }
215}
diff --git a/tests/http/HttpUtils/IndexUrlTest.php b/tests/http/HttpUtils/IndexUrlTest.php
index bcbe59cb..73d33cd4 100644
--- a/tests/http/HttpUtils/IndexUrlTest.php
+++ b/tests/http/HttpUtils/IndexUrlTest.php
@@ -71,4 +71,36 @@ class IndexUrlTest extends \PHPUnit\Framework\TestCase
71 ) 71 )
72 ); 72 );
73 } 73 }
74
75 /**
76 * The route is stored in REQUEST_URI
77 */
78 public function testPageUrlWithRoute()
79 {
80 $this->assertEquals(
81 'http://host.tld/picture-wall',
82 page_url(
83 array(
84 'HTTPS' => 'Off',
85 'SERVER_NAME' => 'host.tld',
86 'SERVER_PORT' => '80',
87 'SCRIPT_NAME' => '/index.php',
88 'REQUEST_URI' => '/picture-wall',
89 )
90 )
91 );
92
93 $this->assertEquals(
94 'http://host.tld/admin/picture-wall',
95 page_url(
96 array(
97 'HTTPS' => 'Off',
98 'SERVER_NAME' => 'host.tld',
99 'SERVER_PORT' => '80',
100 'SCRIPT_NAME' => '/admin/index.php',
101 'REQUEST_URI' => '/admin/picture-wall',
102 )
103 )
104 );
105 }
74} 106}
diff --git a/tests/legacy/LegacyControllerTest.php b/tests/legacy/LegacyControllerTest.php
new file mode 100644
index 00000000..759a5b2a
--- /dev/null
+++ b/tests/legacy/LegacyControllerTest.php
@@ -0,0 +1,99 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Legacy;
6
7use PHPUnit\Framework\TestCase;
8use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12class LegacyControllerTest extends TestCase
13{
14 use FrontControllerMockHelper;
15
16 /** @var LegacyController */
17 protected $controller;
18
19 public function setUp(): void
20 {
21 $this->createContainer();
22
23 $this->controller = new LegacyController($this->container);
24 }
25
26 /**
27 * @dataProvider getProcessProvider
28 */
29 public function testProcess(string $legacyRoute, array $queryParameters, string $slimRoute, bool $isLoggedIn): void
30 {
31 $request = $this->createMock(Request::class);
32 $request->method('getQueryParams')->willReturn($queryParameters);
33 $request
34 ->method('getParam')
35 ->willReturnCallback(function (string $key) use ($queryParameters): ?string {
36 return $queryParameters[$key] ?? null;
37 })
38 ;
39 $response = new Response();
40
41 $this->container->loginManager->method('isLoggedIn')->willReturn($isLoggedIn);
42
43 $result = $this->controller->process($request, $response, $legacyRoute);
44
45 static::assertSame('/subfolder' . $slimRoute, $result->getHeader('location')[0]);
46 }
47
48 public function testProcessNotFound(): void
49 {
50 $request = $this->createMock(Request::class);
51 $response = new Response();
52
53 $this->expectException(UnknowLegacyRouteException::class);
54
55 $this->controller->process($request, $response, 'nope');
56 }
57
58 /**
59 * @return array[] Parameters:
60 * - string legacyRoute
61 * - array queryParameters
62 * - string slimRoute
63 * - bool isLoggedIn
64 */
65 public function getProcessProvider(): array
66 {
67 return [
68 ['post', [], '/admin/shaare', true],
69 ['post', [], '/login', false],
70 ['post', ['title' => 'test'], '/admin/shaare?title=test', true],
71 ['post', ['title' => 'test'], '/login?title=test', false],
72 ['addlink', [], '/admin/add-shaare', true],
73 ['addlink', [], '/login', false],
74 ['login', [], '/login', true],
75 ['login', [], '/login', false],
76 ['logout', [], '/admin/logout', true],
77 ['logout', [], '/admin/logout', false],
78 ['picwall', [], '/picture-wall', false],
79 ['picwall', [], '/picture-wall', true],
80 ['tagcloud', [], '/tags/cloud', false],
81 ['tagcloud', [], '/tags/cloud', true],
82 ['taglist', [], '/tags/list', false],
83 ['taglist', [], '/tags/list', true],
84 ['daily', [], '/daily', false],
85 ['daily', [], '/daily', true],
86 ['daily', ['day' => '123456789', 'discard' => '1'], '/daily?day=123456789', false],
87 ['rss', [], '/feed/rss', false],
88 ['rss', [], '/feed/rss', true],
89 ['rss', ['search' => 'filter123', 'other' => 'param'], '/feed/rss?search=filter123&other=param', false],
90 ['atom', [], '/feed/atom', false],
91 ['atom', [], '/feed/atom', true],
92 ['atom', ['search' => 'filter123', 'other' => 'param'], '/feed/atom?search=filter123&other=param', false],
93 ['opensearch', [], '/open-search', false],
94 ['opensearch', [], '/open-search', true],
95 ['dailyrss', [], '/daily-rss', false],
96 ['dailyrss', [], '/daily-rss', true],
97 ];
98 }
99}
diff --git a/tests/legacy/LegacyLinkDBTest.php b/tests/legacy/LegacyLinkDBTest.php
index 17b2b0e6..0884ad03 100644
--- a/tests/legacy/LegacyLinkDBTest.php
+++ b/tests/legacy/LegacyLinkDBTest.php
@@ -11,7 +11,6 @@ use ReflectionClass;
11use Shaarli; 11use Shaarli;
12use Shaarli\Bookmark\Bookmark; 12use Shaarli\Bookmark\Bookmark;
13 13
14require_once 'application/feed/Cache.php';
15require_once 'application/Utils.php'; 14require_once 'application/Utils.php';
16require_once 'tests/utils/ReferenceLinkDB.php'; 15require_once 'tests/utils/ReferenceLinkDB.php';
17 16
diff --git a/tests/RouterTest.php b/tests/legacy/LegacyRouterTest.php
index 0cd49bb8..c2019ca7 100644
--- a/tests/RouterTest.php
+++ b/tests/legacy/LegacyRouterTest.php
@@ -1,10 +1,13 @@
1<?php 1<?php
2namespace Shaarli; 2
3namespace Shaarli\Legacy;
4
5use PHPUnit\Framework\TestCase;
3 6
4/** 7/**
5 * Unit tests for Router 8 * Unit tests for Router
6 */ 9 */
7class RouterTest extends \PHPUnit\Framework\TestCase 10class LegacyRouterTest extends TestCase
8{ 11{
9 /** 12 /**
10 * Test findPage: login page output. 13 * Test findPage: login page output.
@@ -15,18 +18,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
15 public function testFindPageLoginValid() 18 public function testFindPageLoginValid()
16 { 19 {
17 $this->assertEquals( 20 $this->assertEquals(
18 Router::$PAGE_LOGIN, 21 LegacyRouter::$PAGE_LOGIN,
19 Router::findPage('do=login', array(), false) 22 LegacyRouter::findPage('do=login', array(), false)
20 ); 23 );
21 24
22 $this->assertEquals( 25 $this->assertEquals(
23 Router::$PAGE_LOGIN, 26 LegacyRouter::$PAGE_LOGIN,
24 Router::findPage('do=login', array(), 1) 27 LegacyRouter::findPage('do=login', array(), 1)
25 ); 28 );
26 29
27 $this->assertEquals( 30 $this->assertEquals(
28 Router::$PAGE_LOGIN, 31 LegacyRouter::$PAGE_LOGIN,
29 Router::findPage('do=login&stuff', array(), false) 32 LegacyRouter::findPage('do=login&stuff', array(), false)
30 ); 33 );
31 } 34 }
32 35
@@ -39,13 +42,13 @@ class RouterTest extends \PHPUnit\Framework\TestCase
39 public function testFindPageLoginInvalid() 42 public function testFindPageLoginInvalid()
40 { 43 {
41 $this->assertNotEquals( 44 $this->assertNotEquals(
42 Router::$PAGE_LOGIN, 45 LegacyRouter::$PAGE_LOGIN,
43 Router::findPage('do=login', array(), true) 46 LegacyRouter::findPage('do=login', array(), true)
44 ); 47 );
45 48
46 $this->assertNotEquals( 49 $this->assertNotEquals(
47 Router::$PAGE_LOGIN, 50 LegacyRouter::$PAGE_LOGIN,
48 Router::findPage('do=other', array(), false) 51 LegacyRouter::findPage('do=other', array(), false)
49 ); 52 );
50 } 53 }
51 54
@@ -58,13 +61,13 @@ class RouterTest extends \PHPUnit\Framework\TestCase
58 public function testFindPagePicwallValid() 61 public function testFindPagePicwallValid()
59 { 62 {
60 $this->assertEquals( 63 $this->assertEquals(
61 Router::$PAGE_PICWALL, 64 LegacyRouter::$PAGE_PICWALL,
62 Router::findPage('do=picwall', array(), false) 65 LegacyRouter::findPage('do=picwall', array(), false)
63 ); 66 );
64 67
65 $this->assertEquals( 68 $this->assertEquals(
66 Router::$PAGE_PICWALL, 69 LegacyRouter::$PAGE_PICWALL,
67 Router::findPage('do=picwall', array(), true) 70 LegacyRouter::findPage('do=picwall', array(), true)
68 ); 71 );
69 } 72 }
70 73
@@ -77,13 +80,13 @@ class RouterTest extends \PHPUnit\Framework\TestCase
77 public function testFindPagePicwallInvalid() 80 public function testFindPagePicwallInvalid()
78 { 81 {
79 $this->assertEquals( 82 $this->assertEquals(
80 Router::$PAGE_PICWALL, 83 LegacyRouter::$PAGE_PICWALL,
81 Router::findPage('do=picwall&stuff', array(), false) 84 LegacyRouter::findPage('do=picwall&stuff', array(), false)
82 ); 85 );
83 86
84 $this->assertNotEquals( 87 $this->assertNotEquals(
85 Router::$PAGE_PICWALL, 88 LegacyRouter::$PAGE_PICWALL,
86 Router::findPage('do=other', array(), false) 89 LegacyRouter::findPage('do=other', array(), false)
87 ); 90 );
88 } 91 }
89 92
@@ -96,18 +99,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
96 public function testFindPageTagcloudValid() 99 public function testFindPageTagcloudValid()
97 { 100 {
98 $this->assertEquals( 101 $this->assertEquals(
99 Router::$PAGE_TAGCLOUD, 102 LegacyRouter::$PAGE_TAGCLOUD,
100 Router::findPage('do=tagcloud', array(), false) 103 LegacyRouter::findPage('do=tagcloud', array(), false)
101 ); 104 );
102 105
103 $this->assertEquals( 106 $this->assertEquals(
104 Router::$PAGE_TAGCLOUD, 107 LegacyRouter::$PAGE_TAGCLOUD,
105 Router::findPage('do=tagcloud', array(), true) 108 LegacyRouter::findPage('do=tagcloud', array(), true)
106 ); 109 );
107 110
108 $this->assertEquals( 111 $this->assertEquals(
109 Router::$PAGE_TAGCLOUD, 112 LegacyRouter::$PAGE_TAGCLOUD,
110 Router::findPage('do=tagcloud&stuff', array(), false) 113 LegacyRouter::findPage('do=tagcloud&stuff', array(), false)
111 ); 114 );
112 } 115 }
113 116
@@ -120,8 +123,8 @@ class RouterTest extends \PHPUnit\Framework\TestCase
120 public function testFindPageTagcloudInvalid() 123 public function testFindPageTagcloudInvalid()
121 { 124 {
122 $this->assertNotEquals( 125 $this->assertNotEquals(
123 Router::$PAGE_TAGCLOUD, 126 LegacyRouter::$PAGE_TAGCLOUD,
124 Router::findPage('do=other', array(), false) 127 LegacyRouter::findPage('do=other', array(), false)
125 ); 128 );
126 } 129 }
127 130
@@ -134,23 +137,23 @@ class RouterTest extends \PHPUnit\Framework\TestCase
134 public function testFindPageLinklistValid() 137 public function testFindPageLinklistValid()
135 { 138 {
136 $this->assertEquals( 139 $this->assertEquals(
137 Router::$PAGE_LINKLIST, 140 LegacyRouter::$PAGE_LINKLIST,
138 Router::findPage('', array(), true) 141 LegacyRouter::findPage('', array(), true)
139 ); 142 );
140 143
141 $this->assertEquals( 144 $this->assertEquals(
142 Router::$PAGE_LINKLIST, 145 LegacyRouter::$PAGE_LINKLIST,
143 Router::findPage('whatever', array(), true) 146 LegacyRouter::findPage('whatever', array(), true)
144 ); 147 );
145 148
146 $this->assertEquals( 149 $this->assertEquals(
147 Router::$PAGE_LINKLIST, 150 LegacyRouter::$PAGE_LINKLIST,
148 Router::findPage('whatever', array(), false) 151 LegacyRouter::findPage('whatever', array(), false)
149 ); 152 );
150 153
151 $this->assertEquals( 154 $this->assertEquals(
152 Router::$PAGE_LINKLIST, 155 LegacyRouter::$PAGE_LINKLIST,
153 Router::findPage('do=tools', array(), false) 156 LegacyRouter::findPage('do=tools', array(), false)
154 ); 157 );
155 } 158 }
156 159
@@ -163,13 +166,13 @@ class RouterTest extends \PHPUnit\Framework\TestCase
163 public function testFindPageToolsValid() 166 public function testFindPageToolsValid()
164 { 167 {
165 $this->assertEquals( 168 $this->assertEquals(
166 Router::$PAGE_TOOLS, 169 LegacyRouter::$PAGE_TOOLS,
167 Router::findPage('do=tools', array(), true) 170 LegacyRouter::findPage('do=tools', array(), true)
168 ); 171 );
169 172
170 $this->assertEquals( 173 $this->assertEquals(
171 Router::$PAGE_TOOLS, 174 LegacyRouter::$PAGE_TOOLS,
172 Router::findPage('do=tools&stuff', array(), true) 175 LegacyRouter::findPage('do=tools&stuff', array(), true)
173 ); 176 );
174 } 177 }
175 178
@@ -182,18 +185,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
182 public function testFindPageToolsInvalid() 185 public function testFindPageToolsInvalid()
183 { 186 {
184 $this->assertNotEquals( 187 $this->assertNotEquals(
185 Router::$PAGE_TOOLS, 188 LegacyRouter::$PAGE_TOOLS,
186 Router::findPage('do=tools', array(), 1) 189 LegacyRouter::findPage('do=tools', array(), 1)
187 ); 190 );
188 191
189 $this->assertNotEquals( 192 $this->assertNotEquals(
190 Router::$PAGE_TOOLS, 193 LegacyRouter::$PAGE_TOOLS,
191 Router::findPage('do=tools', array(), false) 194 LegacyRouter::findPage('do=tools', array(), false)
192 ); 195 );
193 196
194 $this->assertNotEquals( 197 $this->assertNotEquals(
195 Router::$PAGE_TOOLS, 198 LegacyRouter::$PAGE_TOOLS,
196 Router::findPage('do=other', array(), true) 199 LegacyRouter::findPage('do=other', array(), true)
197 ); 200 );
198 } 201 }
199 202
@@ -206,12 +209,12 @@ class RouterTest extends \PHPUnit\Framework\TestCase
206 public function testFindPageChangepasswdValid() 209 public function testFindPageChangepasswdValid()
207 { 210 {
208 $this->assertEquals( 211 $this->assertEquals(
209 Router::$PAGE_CHANGEPASSWORD, 212 LegacyRouter::$PAGE_CHANGEPASSWORD,
210 Router::findPage('do=changepasswd', array(), true) 213 LegacyRouter::findPage('do=changepasswd', array(), true)
211 ); 214 );
212 $this->assertEquals( 215 $this->assertEquals(
213 Router::$PAGE_CHANGEPASSWORD, 216 LegacyRouter::$PAGE_CHANGEPASSWORD,
214 Router::findPage('do=changepasswd&stuff', array(), true) 217 LegacyRouter::findPage('do=changepasswd&stuff', array(), true)
215 ); 218 );
216 } 219 }
217 220
@@ -224,18 +227,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
224 public function testFindPageChangepasswdInvalid() 227 public function testFindPageChangepasswdInvalid()
225 { 228 {
226 $this->assertNotEquals( 229 $this->assertNotEquals(
227 Router::$PAGE_CHANGEPASSWORD, 230 LegacyRouter::$PAGE_CHANGEPASSWORD,
228 Router::findPage('do=changepasswd', array(), 1) 231 LegacyRouter::findPage('do=changepasswd', array(), 1)
229 ); 232 );
230 233
231 $this->assertNotEquals( 234 $this->assertNotEquals(
232 Router::$PAGE_CHANGEPASSWORD, 235 LegacyRouter::$PAGE_CHANGEPASSWORD,
233 Router::findPage('do=changepasswd', array(), false) 236 LegacyRouter::findPage('do=changepasswd', array(), false)
234 ); 237 );
235 238
236 $this->assertNotEquals( 239 $this->assertNotEquals(
237 Router::$PAGE_CHANGEPASSWORD, 240 LegacyRouter::$PAGE_CHANGEPASSWORD,
238 Router::findPage('do=other', array(), true) 241 LegacyRouter::findPage('do=other', array(), true)
239 ); 242 );
240 } 243 }
241 /** 244 /**
@@ -247,13 +250,13 @@ class RouterTest extends \PHPUnit\Framework\TestCase
247 public function testFindPageConfigureValid() 250 public function testFindPageConfigureValid()
248 { 251 {
249 $this->assertEquals( 252 $this->assertEquals(
250 Router::$PAGE_CONFIGURE, 253 LegacyRouter::$PAGE_CONFIGURE,
251 Router::findPage('do=configure', array(), true) 254 LegacyRouter::findPage('do=configure', array(), true)
252 ); 255 );
253 256
254 $this->assertEquals( 257 $this->assertEquals(
255 Router::$PAGE_CONFIGURE, 258 LegacyRouter::$PAGE_CONFIGURE,
256 Router::findPage('do=configure&stuff', array(), true) 259 LegacyRouter::findPage('do=configure&stuff', array(), true)
257 ); 260 );
258 } 261 }
259 262
@@ -266,18 +269,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
266 public function testFindPageConfigureInvalid() 269 public function testFindPageConfigureInvalid()
267 { 270 {
268 $this->assertNotEquals( 271 $this->assertNotEquals(
269 Router::$PAGE_CONFIGURE, 272 LegacyRouter::$PAGE_CONFIGURE,
270 Router::findPage('do=configure', array(), 1) 273 LegacyRouter::findPage('do=configure', array(), 1)
271 ); 274 );
272 275
273 $this->assertNotEquals( 276 $this->assertNotEquals(
274 Router::$PAGE_CONFIGURE, 277 LegacyRouter::$PAGE_CONFIGURE,
275 Router::findPage('do=configure', array(), false) 278 LegacyRouter::findPage('do=configure', array(), false)
276 ); 279 );
277 280
278 $this->assertNotEquals( 281 $this->assertNotEquals(
279 Router::$PAGE_CONFIGURE, 282 LegacyRouter::$PAGE_CONFIGURE,
280 Router::findPage('do=other', array(), true) 283 LegacyRouter::findPage('do=other', array(), true)
281 ); 284 );
282 } 285 }
283 286
@@ -290,13 +293,13 @@ class RouterTest extends \PHPUnit\Framework\TestCase
290 public function testFindPageChangetagValid() 293 public function testFindPageChangetagValid()
291 { 294 {
292 $this->assertEquals( 295 $this->assertEquals(
293 Router::$PAGE_CHANGETAG, 296 LegacyRouter::$PAGE_CHANGETAG,
294 Router::findPage('do=changetag', array(), true) 297 LegacyRouter::findPage('do=changetag', array(), true)
295 ); 298 );
296 299
297 $this->assertEquals( 300 $this->assertEquals(
298 Router::$PAGE_CHANGETAG, 301 LegacyRouter::$PAGE_CHANGETAG,
299 Router::findPage('do=changetag&stuff', array(), true) 302 LegacyRouter::findPage('do=changetag&stuff', array(), true)
300 ); 303 );
301 } 304 }
302 305
@@ -309,18 +312,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
309 public function testFindPageChangetagInvalid() 312 public function testFindPageChangetagInvalid()
310 { 313 {
311 $this->assertNotEquals( 314 $this->assertNotEquals(
312 Router::$PAGE_CHANGETAG, 315 LegacyRouter::$PAGE_CHANGETAG,
313 Router::findPage('do=changetag', array(), 1) 316 LegacyRouter::findPage('do=changetag', array(), 1)
314 ); 317 );
315 318
316 $this->assertNotEquals( 319 $this->assertNotEquals(
317 Router::$PAGE_CHANGETAG, 320 LegacyRouter::$PAGE_CHANGETAG,
318 Router::findPage('do=changetag', array(), false) 321 LegacyRouter::findPage('do=changetag', array(), false)
319 ); 322 );
320 323
321 $this->assertNotEquals( 324 $this->assertNotEquals(
322 Router::$PAGE_CHANGETAG, 325 LegacyRouter::$PAGE_CHANGETAG,
323 Router::findPage('do=other', array(), true) 326 LegacyRouter::findPage('do=other', array(), true)
324 ); 327 );
325 } 328 }
326 329
@@ -333,13 +336,13 @@ class RouterTest extends \PHPUnit\Framework\TestCase
333 public function testFindPageAddlinkValid() 336 public function testFindPageAddlinkValid()
334 { 337 {
335 $this->assertEquals( 338 $this->assertEquals(
336 Router::$PAGE_ADDLINK, 339 LegacyRouter::$PAGE_ADDLINK,
337 Router::findPage('do=addlink', array(), true) 340 LegacyRouter::findPage('do=addlink', array(), true)
338 ); 341 );
339 342
340 $this->assertEquals( 343 $this->assertEquals(
341 Router::$PAGE_ADDLINK, 344 LegacyRouter::$PAGE_ADDLINK,
342 Router::findPage('do=addlink&stuff', array(), true) 345 LegacyRouter::findPage('do=addlink&stuff', array(), true)
343 ); 346 );
344 } 347 }
345 348
@@ -352,18 +355,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
352 public function testFindPageAddlinkInvalid() 355 public function testFindPageAddlinkInvalid()
353 { 356 {
354 $this->assertNotEquals( 357 $this->assertNotEquals(
355 Router::$PAGE_ADDLINK, 358 LegacyRouter::$PAGE_ADDLINK,
356 Router::findPage('do=addlink', array(), 1) 359 LegacyRouter::findPage('do=addlink', array(), 1)
357 ); 360 );
358 361
359 $this->assertNotEquals( 362 $this->assertNotEquals(
360 Router::$PAGE_ADDLINK, 363 LegacyRouter::$PAGE_ADDLINK,
361 Router::findPage('do=addlink', array(), false) 364 LegacyRouter::findPage('do=addlink', array(), false)
362 ); 365 );
363 366
364 $this->assertNotEquals( 367 $this->assertNotEquals(
365 Router::$PAGE_ADDLINK, 368 LegacyRouter::$PAGE_ADDLINK,
366 Router::findPage('do=other', array(), true) 369 LegacyRouter::findPage('do=other', array(), true)
367 ); 370 );
368 } 371 }
369 372
@@ -376,13 +379,13 @@ class RouterTest extends \PHPUnit\Framework\TestCase
376 public function testFindPageExportValid() 379 public function testFindPageExportValid()
377 { 380 {
378 $this->assertEquals( 381 $this->assertEquals(
379 Router::$PAGE_EXPORT, 382 LegacyRouter::$PAGE_EXPORT,
380 Router::findPage('do=export', array(), true) 383 LegacyRouter::findPage('do=export', array(), true)
381 ); 384 );
382 385
383 $this->assertEquals( 386 $this->assertEquals(
384 Router::$PAGE_EXPORT, 387 LegacyRouter::$PAGE_EXPORT,
385 Router::findPage('do=export&stuff', array(), true) 388 LegacyRouter::findPage('do=export&stuff', array(), true)
386 ); 389 );
387 } 390 }
388 391
@@ -395,18 +398,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
395 public function testFindPageExportInvalid() 398 public function testFindPageExportInvalid()
396 { 399 {
397 $this->assertNotEquals( 400 $this->assertNotEquals(
398 Router::$PAGE_EXPORT, 401 LegacyRouter::$PAGE_EXPORT,
399 Router::findPage('do=export', array(), 1) 402 LegacyRouter::findPage('do=export', array(), 1)
400 ); 403 );
401 404
402 $this->assertNotEquals( 405 $this->assertNotEquals(
403 Router::$PAGE_EXPORT, 406 LegacyRouter::$PAGE_EXPORT,
404 Router::findPage('do=export', array(), false) 407 LegacyRouter::findPage('do=export', array(), false)
405 ); 408 );
406 409
407 $this->assertNotEquals( 410 $this->assertNotEquals(
408 Router::$PAGE_EXPORT, 411 LegacyRouter::$PAGE_EXPORT,
409 Router::findPage('do=other', array(), true) 412 LegacyRouter::findPage('do=other', array(), true)
410 ); 413 );
411 } 414 }
412 415
@@ -419,13 +422,13 @@ class RouterTest extends \PHPUnit\Framework\TestCase
419 public function testFindPageImportValid() 422 public function testFindPageImportValid()
420 { 423 {
421 $this->assertEquals( 424 $this->assertEquals(
422 Router::$PAGE_IMPORT, 425 LegacyRouter::$PAGE_IMPORT,
423 Router::findPage('do=import', array(), true) 426 LegacyRouter::findPage('do=import', array(), true)
424 ); 427 );
425 428
426 $this->assertEquals( 429 $this->assertEquals(
427 Router::$PAGE_IMPORT, 430 LegacyRouter::$PAGE_IMPORT,
428 Router::findPage('do=import&stuff', array(), true) 431 LegacyRouter::findPage('do=import&stuff', array(), true)
429 ); 432 );
430 } 433 }
431 434
@@ -438,18 +441,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
438 public function testFindPageImportInvalid() 441 public function testFindPageImportInvalid()
439 { 442 {
440 $this->assertNotEquals( 443 $this->assertNotEquals(
441 Router::$PAGE_IMPORT, 444 LegacyRouter::$PAGE_IMPORT,
442 Router::findPage('do=import', array(), 1) 445 LegacyRouter::findPage('do=import', array(), 1)
443 ); 446 );
444 447
445 $this->assertNotEquals( 448 $this->assertNotEquals(
446 Router::$PAGE_IMPORT, 449 LegacyRouter::$PAGE_IMPORT,
447 Router::findPage('do=import', array(), false) 450 LegacyRouter::findPage('do=import', array(), false)
448 ); 451 );
449 452
450 $this->assertNotEquals( 453 $this->assertNotEquals(
451 Router::$PAGE_IMPORT, 454 LegacyRouter::$PAGE_IMPORT,
452 Router::findPage('do=other', array(), true) 455 LegacyRouter::findPage('do=other', array(), true)
453 ); 456 );
454 } 457 }
455 458
@@ -462,24 +465,24 @@ class RouterTest extends \PHPUnit\Framework\TestCase
462 public function testFindPageEditlinkValid() 465 public function testFindPageEditlinkValid()
463 { 466 {
464 $this->assertEquals( 467 $this->assertEquals(
465 Router::$PAGE_EDITLINK, 468 LegacyRouter::$PAGE_EDITLINK,
466 Router::findPage('whatever', array('edit_link' => 1), true) 469 LegacyRouter::findPage('whatever', array('edit_link' => 1), true)
467 ); 470 );
468 471
469 $this->assertEquals( 472 $this->assertEquals(
470 Router::$PAGE_EDITLINK, 473 LegacyRouter::$PAGE_EDITLINK,
471 Router::findPage('', array('edit_link' => 1), true) 474 LegacyRouter::findPage('', array('edit_link' => 1), true)
472 ); 475 );
473 476
474 477
475 $this->assertEquals( 478 $this->assertEquals(
476 Router::$PAGE_EDITLINK, 479 LegacyRouter::$PAGE_EDITLINK,
477 Router::findPage('whatever', array('post' => 1), true) 480 LegacyRouter::findPage('whatever', array('post' => 1), true)
478 ); 481 );
479 482
480 $this->assertEquals( 483 $this->assertEquals(
481 Router::$PAGE_EDITLINK, 484 LegacyRouter::$PAGE_EDITLINK,
482 Router::findPage('whatever', array('post' => 1, 'edit_link' => 1), true) 485 LegacyRouter::findPage('whatever', array('post' => 1, 'edit_link' => 1), true)
483 ); 486 );
484 } 487 }
485 488
@@ -492,18 +495,18 @@ class RouterTest extends \PHPUnit\Framework\TestCase
492 public function testFindPageEditlinkInvalid() 495 public function testFindPageEditlinkInvalid()
493 { 496 {
494 $this->assertNotEquals( 497 $this->assertNotEquals(
495 Router::$PAGE_EDITLINK, 498 LegacyRouter::$PAGE_EDITLINK,
496 Router::findPage('whatever', array('edit_link' => 1), false) 499 LegacyRouter::findPage('whatever', array('edit_link' => 1), false)
497 ); 500 );
498 501
499 $this->assertNotEquals( 502 $this->assertNotEquals(
500 Router::$PAGE_EDITLINK, 503 LegacyRouter::$PAGE_EDITLINK,
501 Router::findPage('whatever', array('edit_link' => 1), 1) 504 LegacyRouter::findPage('whatever', array('edit_link' => 1), 1)
502 ); 505 );
503 506
504 $this->assertNotEquals( 507 $this->assertNotEquals(
505 Router::$PAGE_EDITLINK, 508 LegacyRouter::$PAGE_EDITLINK,
506 Router::findPage('whatever', array(), true) 509 LegacyRouter::findPage('whatever', array(), true)
507 ); 510 );
508 } 511 }
509} 512}
diff --git a/tests/netscape/BookmarkExportTest.php b/tests/netscape/BookmarkExportTest.php
index 6c948bba..509da51d 100644
--- a/tests/netscape/BookmarkExportTest.php
+++ b/tests/netscape/BookmarkExportTest.php
@@ -1,11 +1,12 @@
1<?php 1<?php
2
2namespace Shaarli\Netscape; 3namespace Shaarli\Netscape;
3 4
5use PHPUnit\Framework\TestCase;
4use Shaarli\Bookmark\BookmarkFileService; 6use Shaarli\Bookmark\BookmarkFileService;
5use Shaarli\Bookmark\LinkDB;
6use Shaarli\Config\ConfigManager; 7use Shaarli\Config\ConfigManager;
7use Shaarli\Formatter\FormatterFactory;
8use Shaarli\Formatter\BookmarkFormatter; 8use Shaarli\Formatter\BookmarkFormatter;
9use Shaarli\Formatter\FormatterFactory;
9use Shaarli\History; 10use Shaarli\History;
10 11
11require_once 'tests/utils/ReferenceLinkDB.php'; 12require_once 'tests/utils/ReferenceLinkDB.php';
@@ -13,7 +14,7 @@ require_once 'tests/utils/ReferenceLinkDB.php';
13/** 14/**
14 * Netscape bookmark export 15 * Netscape bookmark export
15 */ 16 */
16class BookmarkExportTest extends \PHPUnit\Framework\TestCase 17class BookmarkExportTest extends TestCase
17{ 18{
18 /** 19 /**
19 * @var string datastore to test write operations 20 * @var string datastore to test write operations
@@ -21,6 +22,11 @@ class BookmarkExportTest extends \PHPUnit\Framework\TestCase
21 protected static $testDatastore = 'sandbox/datastore.php'; 22 protected static $testDatastore = 'sandbox/datastore.php';
22 23
23 /** 24 /**
25 * @var ConfigManager instance.
26 */
27 protected static $conf;
28
29 /**
24 * @var \ReferenceLinkDB instance. 30 * @var \ReferenceLinkDB instance.
25 */ 31 */
26 protected static $refDb = null; 32 protected static $refDb = null;
@@ -36,18 +42,37 @@ class BookmarkExportTest extends \PHPUnit\Framework\TestCase
36 protected static $formatter; 42 protected static $formatter;
37 43
38 /** 44 /**
45 * @var History instance
46 */
47 protected static $history;
48
49 /**
50 * @var NetscapeBookmarkUtils
51 */
52 protected $netscapeBookmarkUtils;
53
54 /**
39 * Instantiate reference data 55 * Instantiate reference data
40 */ 56 */
41 public static function setUpBeforeClass() 57 public static function setUpBeforeClass()
42 { 58 {
43 $conf = new ConfigManager('tests/utils/config/configJson'); 59 static::$conf = new ConfigManager('tests/utils/config/configJson');
44 $conf->set('resource.datastore', self::$testDatastore); 60 static::$conf->set('resource.datastore', static::$testDatastore);
45 self::$refDb = new \ReferenceLinkDB(); 61 static::$refDb = new \ReferenceLinkDB();
46 self::$refDb->write(self::$testDatastore); 62 static::$refDb->write(static::$testDatastore);
47 $history = new History('sandbox/history.php'); 63 static::$history = new History('sandbox/history.php');
48 self::$bookmarkService = new BookmarkFileService($conf, $history, true); 64 static::$bookmarkService = new BookmarkFileService(static::$conf, static::$history, true);
49 $factory = new FormatterFactory($conf, true); 65 $factory = new FormatterFactory(static::$conf, true);
50 self::$formatter = $factory->getFormatter('raw'); 66 static::$formatter = $factory->getFormatter('raw');
67 }
68
69 public function setUp(): void
70 {
71 $this->netscapeBookmarkUtils = new NetscapeBookmarkUtils(
72 static::$bookmarkService,
73 static::$conf,
74 static::$history
75 );
51 } 76 }
52 77
53 /** 78 /**
@@ -57,8 +82,7 @@ class BookmarkExportTest extends \PHPUnit\Framework\TestCase
57 */ 82 */
58 public function testFilterAndFormatInvalid() 83 public function testFilterAndFormatInvalid()
59 { 84 {
60 NetscapeBookmarkUtils::filterAndFormat( 85 $this->netscapeBookmarkUtils->filterAndFormat(
61 self::$bookmarkService,
62 self::$formatter, 86 self::$formatter,
63 'derp', 87 'derp',
64 false, 88 false,
@@ -71,8 +95,7 @@ class BookmarkExportTest extends \PHPUnit\Framework\TestCase
71 */ 95 */
72 public function testFilterAndFormatAll() 96 public function testFilterAndFormatAll()
73 { 97 {
74 $links = NetscapeBookmarkUtils::filterAndFormat( 98 $links = $this->netscapeBookmarkUtils->filterAndFormat(
75 self::$bookmarkService,
76 self::$formatter, 99 self::$formatter,
77 'all', 100 'all',
78 false, 101 false,
@@ -97,8 +120,7 @@ class BookmarkExportTest extends \PHPUnit\Framework\TestCase
97 */ 120 */
98 public function testFilterAndFormatPrivate() 121 public function testFilterAndFormatPrivate()
99 { 122 {
100 $links = NetscapeBookmarkUtils::filterAndFormat( 123 $links = $this->netscapeBookmarkUtils->filterAndFormat(
101 self::$bookmarkService,
102 self::$formatter, 124 self::$formatter,
103 'private', 125 'private',
104 false, 126 false,
@@ -123,8 +145,7 @@ class BookmarkExportTest extends \PHPUnit\Framework\TestCase
123 */ 145 */
124 public function testFilterAndFormatPublic() 146 public function testFilterAndFormatPublic()
125 { 147 {
126 $links = NetscapeBookmarkUtils::filterAndFormat( 148 $links = $this->netscapeBookmarkUtils->filterAndFormat(
127 self::$bookmarkService,
128 self::$formatter, 149 self::$formatter,
129 'public', 150 'public',
130 false, 151 false,
@@ -149,15 +170,14 @@ class BookmarkExportTest extends \PHPUnit\Framework\TestCase
149 */ 170 */
150 public function testFilterAndFormatDoNotPrependNoteUrl() 171 public function testFilterAndFormatDoNotPrependNoteUrl()
151 { 172 {
152 $links = NetscapeBookmarkUtils::filterAndFormat( 173 $links = $this->netscapeBookmarkUtils->filterAndFormat(
153 self::$bookmarkService,
154 self::$formatter, 174 self::$formatter,
155 'public', 175 'public',
156 false, 176 false,
157 '' 177 ''
158 ); 178 );
159 $this->assertEquals( 179 $this->assertEquals(
160 '?WDWyig', 180 '/shaare/WDWyig',
161 $links[2]['url'] 181 $links[2]['url']
162 ); 182 );
163 } 183 }
@@ -168,15 +188,14 @@ class BookmarkExportTest extends \PHPUnit\Framework\TestCase
168 public function testFilterAndFormatPrependNoteUrl() 188 public function testFilterAndFormatPrependNoteUrl()
169 { 189 {
170 $indexUrl = 'http://localhost:7469/shaarli/'; 190 $indexUrl = 'http://localhost:7469/shaarli/';
171 $links = NetscapeBookmarkUtils::filterAndFormat( 191 $links = $this->netscapeBookmarkUtils->filterAndFormat(
172 self::$bookmarkService,
173 self::$formatter, 192 self::$formatter,
174 'public', 193 'public',
175 true, 194 true,
176 $indexUrl 195 $indexUrl
177 ); 196 );
178 $this->assertEquals( 197 $this->assertEquals(
179 $indexUrl . '?WDWyig', 198 $indexUrl . 'shaare/WDWyig',
180 $links[2]['url'] 199 $links[2]['url']
181 ); 200 );
182 } 201 }
diff --git a/tests/netscape/BookmarkImportTest.php b/tests/netscape/BookmarkImportTest.php
index fef7f6d1..f678e26b 100644
--- a/tests/netscape/BookmarkImportTest.php
+++ b/tests/netscape/BookmarkImportTest.php
@@ -1,29 +1,31 @@
1<?php 1<?php
2
2namespace Shaarli\Netscape; 3namespace Shaarli\Netscape;
3 4
4use DateTime; 5use DateTime;
6use PHPUnit\Framework\TestCase;
7use Psr\Http\Message\UploadedFileInterface;
5use Shaarli\Bookmark\Bookmark; 8use Shaarli\Bookmark\Bookmark;
6use Shaarli\Bookmark\BookmarkFilter;
7use Shaarli\Bookmark\BookmarkFileService; 9use Shaarli\Bookmark\BookmarkFileService;
8use Shaarli\Bookmark\LinkDB; 10use Shaarli\Bookmark\BookmarkFilter;
9use Shaarli\Config\ConfigManager; 11use Shaarli\Config\ConfigManager;
10use Shaarli\History; 12use Shaarli\History;
13use Slim\Http\UploadedFile;
11 14
12/** 15/**
13 * Utility function to load a file's metadata in a $_FILES-like array 16 * Utility function to load a file's metadata in a $_FILES-like array
14 * 17 *
15 * @param string $filename Basename of the file 18 * @param string $filename Basename of the file
16 * 19 *
17 * @return array A $_FILES-like array 20 * @return UploadedFileInterface Upload file in PSR-7 compatible object
18 */ 21 */
19function file2array($filename) 22function file2array($filename)
20{ 23{
21 return array( 24 return new UploadedFile(
22 'filetoupload' => array( 25 __DIR__ . '/input/' . $filename,
23 'name' => $filename, 26 $filename,
24 'tmp_name' => __DIR__ . '/input/' . $filename, 27 null,
25 'size' => filesize(__DIR__ . '/input/' . $filename) 28 filesize(__DIR__ . '/input/' . $filename)
26 )
27 ); 29 );
28} 30}
29 31
@@ -31,7 +33,7 @@ function file2array($filename)
31/** 33/**
32 * Netscape bookmark import 34 * Netscape bookmark import
33 */ 35 */
34class BookmarkImportTest extends \PHPUnit\Framework\TestCase 36class BookmarkImportTest extends TestCase
35{ 37{
36 /** 38 /**
37 * @var string datastore to test write operations 39 * @var string datastore to test write operations
@@ -64,6 +66,11 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
64 protected $history; 66 protected $history;
65 67
66 /** 68 /**
69 * @var NetscapeBookmarkUtils
70 */
71 protected $netscapeBookmarkUtils;
72
73 /**
67 * @var string Save the current timezone. 74 * @var string Save the current timezone.
68 */ 75 */
69 protected static $defaultTimeZone; 76 protected static $defaultTimeZone;
@@ -91,6 +98,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
91 $this->conf->set('resource.datastore', self::$testDatastore); 98 $this->conf->set('resource.datastore', self::$testDatastore);
92 $this->history = new History(self::$historyFilePath); 99 $this->history = new History(self::$historyFilePath);
93 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true); 100 $this->bookmarkService = new BookmarkFileService($this->conf, $this->history, true);
101 $this->netscapeBookmarkUtils = new NetscapeBookmarkUtils($this->bookmarkService, $this->conf, $this->history);
94 } 102 }
95 103
96 /** 104 /**
@@ -115,7 +123,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
115 $this->assertEquals( 123 $this->assertEquals(
116 'File empty.htm (0 bytes) has an unknown file format.' 124 'File empty.htm (0 bytes) has an unknown file format.'
117 .' Nothing was imported.', 125 .' Nothing was imported.',
118 NetscapeBookmarkUtils::import(null, $files, null, $this->conf, $this->history) 126 $this->netscapeBookmarkUtils->import(null, $files)
119 ); 127 );
120 $this->assertEquals(0, $this->bookmarkService->count()); 128 $this->assertEquals(0, $this->bookmarkService->count());
121 } 129 }
@@ -128,7 +136,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
128 $files = file2array('no_doctype.htm'); 136 $files = file2array('no_doctype.htm');
129 $this->assertEquals( 137 $this->assertEquals(
130 'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.', 138 'File no_doctype.htm (350 bytes) has an unknown file format. Nothing was imported.',
131 NetscapeBookmarkUtils::import(null, $files, null, $this->conf, $this->history) 139 $this->netscapeBookmarkUtils->import(null, $files)
132 ); 140 );
133 $this->assertEquals(0, $this->bookmarkService->count()); 141 $this->assertEquals(0, $this->bookmarkService->count());
134 } 142 }
@@ -142,7 +150,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
142 $this->assertStringMatchesFormat( 150 $this->assertStringMatchesFormat(
143 'File lowercase_doctype.htm (386 bytes) was successfully processed in %d seconds:' 151 'File lowercase_doctype.htm (386 bytes) was successfully processed in %d seconds:'
144 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 152 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
145 NetscapeBookmarkUtils::import(null, $files, $this->bookmarkService, $this->conf, $this->history) 153 $this->netscapeBookmarkUtils->import(null, $files)
146 ); 154 );
147 $this->assertEquals(2, $this->bookmarkService->count()); 155 $this->assertEquals(2, $this->bookmarkService->count());
148 } 156 }
@@ -157,7 +165,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
157 $this->assertStringMatchesFormat( 165 $this->assertStringMatchesFormat(
158 'File internet_explorer_encoding.htm (356 bytes) was successfully processed in %d seconds:' 166 'File internet_explorer_encoding.htm (356 bytes) was successfully processed in %d seconds:'
159 .' 1 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 167 .' 1 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
160 NetscapeBookmarkUtils::import([], $files, $this->bookmarkService, $this->conf, $this->history) 168 $this->netscapeBookmarkUtils->import([], $files)
161 ); 169 );
162 $this->assertEquals(1, $this->bookmarkService->count()); 170 $this->assertEquals(1, $this->bookmarkService->count());
163 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 171 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -185,7 +193,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
185 $this->assertStringMatchesFormat( 193 $this->assertStringMatchesFormat(
186 'File netscape_nested.htm (1337 bytes) was successfully processed in %d seconds:' 194 'File netscape_nested.htm (1337 bytes) was successfully processed in %d seconds:'
187 .' 8 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 195 .' 8 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
188 NetscapeBookmarkUtils::import([], $files, $this->bookmarkService, $this->conf, $this->history) 196 $this->netscapeBookmarkUtils->import([], $files)
189 ); 197 );
190 $this->assertEquals(8, $this->bookmarkService->count()); 198 $this->assertEquals(8, $this->bookmarkService->count());
191 $this->assertEquals(2, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 199 $this->assertEquals(2, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -306,7 +314,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
306 $this->assertStringMatchesFormat( 314 $this->assertStringMatchesFormat(
307 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 315 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
308 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 316 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
309 NetscapeBookmarkUtils::import([], $files, $this->bookmarkService, $this->conf, $this->history) 317 $this->netscapeBookmarkUtils->import([], $files)
310 ); 318 );
311 319
312 $this->assertEquals(2, $this->bookmarkService->count()); 320 $this->assertEquals(2, $this->bookmarkService->count());
@@ -349,7 +357,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
349 $this->assertStringMatchesFormat( 357 $this->assertStringMatchesFormat(
350 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 358 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
351 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 359 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
352 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 360 $this->netscapeBookmarkUtils->import($post, $files)
353 ); 361 );
354 362
355 $this->assertEquals(2, $this->bookmarkService->count()); 363 $this->assertEquals(2, $this->bookmarkService->count());
@@ -392,7 +400,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
392 $this->assertStringMatchesFormat( 400 $this->assertStringMatchesFormat(
393 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 401 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
394 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 402 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
395 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 403 $this->netscapeBookmarkUtils->import($post, $files)
396 ); 404 );
397 $this->assertEquals(2, $this->bookmarkService->count()); 405 $this->assertEquals(2, $this->bookmarkService->count());
398 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 406 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -410,7 +418,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
410 $this->assertStringMatchesFormat( 418 $this->assertStringMatchesFormat(
411 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 419 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
412 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 420 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
413 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 421 $this->netscapeBookmarkUtils->import($post, $files)
414 ); 422 );
415 $this->assertEquals(2, $this->bookmarkService->count()); 423 $this->assertEquals(2, $this->bookmarkService->count());
416 $this->assertEquals(2, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 424 $this->assertEquals(2, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -430,7 +438,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
430 $this->assertStringMatchesFormat( 438 $this->assertStringMatchesFormat(
431 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 439 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
432 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 440 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
433 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 441 $this->netscapeBookmarkUtils->import($post, $files)
434 ); 442 );
435 $this->assertEquals(2, $this->bookmarkService->count()); 443 $this->assertEquals(2, $this->bookmarkService->count());
436 $this->assertEquals(2, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 444 $this->assertEquals(2, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -445,7 +453,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
445 $this->assertStringMatchesFormat( 453 $this->assertStringMatchesFormat(
446 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 454 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
447 .' 2 bookmarks imported, 2 bookmarks overwritten, 0 bookmarks skipped.', 455 .' 2 bookmarks imported, 2 bookmarks overwritten, 0 bookmarks skipped.',
448 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 456 $this->netscapeBookmarkUtils->import($post, $files)
449 ); 457 );
450 $this->assertEquals(2, $this->bookmarkService->count()); 458 $this->assertEquals(2, $this->bookmarkService->count());
451 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 459 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -465,7 +473,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
465 $this->assertStringMatchesFormat( 473 $this->assertStringMatchesFormat(
466 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 474 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
467 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 475 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
468 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 476 $this->netscapeBookmarkUtils->import($post, $files)
469 ); 477 );
470 $this->assertEquals(2, $this->bookmarkService->count()); 478 $this->assertEquals(2, $this->bookmarkService->count());
471 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 479 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -480,7 +488,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
480 $this->assertStringMatchesFormat( 488 $this->assertStringMatchesFormat(
481 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 489 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
482 .' 2 bookmarks imported, 2 bookmarks overwritten, 0 bookmarks skipped.', 490 .' 2 bookmarks imported, 2 bookmarks overwritten, 0 bookmarks skipped.',
483 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 491 $this->netscapeBookmarkUtils->import($post, $files)
484 ); 492 );
485 $this->assertEquals(2, $this->bookmarkService->count()); 493 $this->assertEquals(2, $this->bookmarkService->count());
486 $this->assertEquals(2, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 494 $this->assertEquals(2, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -498,7 +506,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
498 $this->assertStringMatchesFormat( 506 $this->assertStringMatchesFormat(
499 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 507 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
500 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 508 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
501 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 509 $this->netscapeBookmarkUtils->import($post, $files)
502 ); 510 );
503 $this->assertEquals(2, $this->bookmarkService->count()); 511 $this->assertEquals(2, $this->bookmarkService->count());
504 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 512 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -508,7 +516,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
508 $this->assertStringMatchesFormat( 516 $this->assertStringMatchesFormat(
509 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 517 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
510 .' 0 bookmarks imported, 0 bookmarks overwritten, 2 bookmarks skipped.', 518 .' 0 bookmarks imported, 0 bookmarks overwritten, 2 bookmarks skipped.',
511 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 519 $this->netscapeBookmarkUtils->import($post, $files)
512 ); 520 );
513 $this->assertEquals(2, $this->bookmarkService->count()); 521 $this->assertEquals(2, $this->bookmarkService->count());
514 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 522 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -527,7 +535,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
527 $this->assertStringMatchesFormat( 535 $this->assertStringMatchesFormat(
528 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 536 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
529 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 537 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
530 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 538 $this->netscapeBookmarkUtils->import($post, $files)
531 ); 539 );
532 $this->assertEquals(2, $this->bookmarkService->count()); 540 $this->assertEquals(2, $this->bookmarkService->count());
533 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 541 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -548,7 +556,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
548 $this->assertStringMatchesFormat( 556 $this->assertStringMatchesFormat(
549 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:' 557 'File netscape_basic.htm (482 bytes) was successfully processed in %d seconds:'
550 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 558 .' 2 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
551 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history) 559 $this->netscapeBookmarkUtils->import($post, $files)
552 ); 560 );
553 $this->assertEquals(2, $this->bookmarkService->count()); 561 $this->assertEquals(2, $this->bookmarkService->count());
554 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 562 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -573,7 +581,7 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
573 $this->assertStringMatchesFormat( 581 $this->assertStringMatchesFormat(
574 'File same_date.htm (453 bytes) was successfully processed in %d seconds:' 582 'File same_date.htm (453 bytes) was successfully processed in %d seconds:'
575 .' 3 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.', 583 .' 3 bookmarks imported, 0 bookmarks overwritten, 0 bookmarks skipped.',
576 NetscapeBookmarkUtils::import(array(), $files, $this->bookmarkService, $this->conf, $this->history) 584 $this->netscapeBookmarkUtils->import(array(), $files)
577 ); 585 );
578 $this->assertEquals(3, $this->bookmarkService->count()); 586 $this->assertEquals(3, $this->bookmarkService->count());
579 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE)); 587 $this->assertEquals(0, $this->bookmarkService->count(BookmarkFilter::$PRIVATE));
@@ -589,14 +597,14 @@ class BookmarkImportTest extends \PHPUnit\Framework\TestCase
589 'overwrite' => 'true', 597 'overwrite' => 'true',
590 ]; 598 ];
591 $files = file2array('netscape_basic.htm'); 599 $files = file2array('netscape_basic.htm');
592 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history); 600 $this->netscapeBookmarkUtils->import($post, $files);
593 $history = $this->history->getHistory(); 601 $history = $this->history->getHistory();
594 $this->assertEquals(1, count($history)); 602 $this->assertEquals(1, count($history));
595 $this->assertEquals(History::IMPORT, $history[0]['event']); 603 $this->assertEquals(History::IMPORT, $history[0]['event']);
596 $this->assertTrue(new DateTime('-5 seconds') < $history[0]['datetime']); 604 $this->assertTrue(new DateTime('-5 seconds') < $history[0]['datetime']);
597 605
598 // re-import as private, enable overwriting 606 // re-import as private, enable overwriting
599 NetscapeBookmarkUtils::import($post, $files, $this->bookmarkService, $this->conf, $this->history); 607 $this->netscapeBookmarkUtils->import($post, $files);
600 $history = $this->history->getHistory(); 608 $history = $this->history->getHistory();
601 $this->assertEquals(2, count($history)); 609 $this->assertEquals(2, count($history));
602 $this->assertEquals(History::IMPORT, $history[0]['event']); 610 $this->assertEquals(History::IMPORT, $history[0]['event']);
diff --git a/tests/plugins/PluginAddlinkTest.php b/tests/plugins/PluginAddlinkTest.php
index d052f8b9..aa5c6988 100644
--- a/tests/plugins/PluginAddlinkTest.php
+++ b/tests/plugins/PluginAddlinkTest.php
@@ -2,7 +2,7 @@
2namespace Shaarli\Plugin\Addlink; 2namespace Shaarli\Plugin\Addlink;
3 3
4use Shaarli\Plugin\PluginManager; 4use Shaarli\Plugin\PluginManager;
5use Shaarli\Router; 5use Shaarli\Render\TemplatePage;
6 6
7require_once 'plugins/addlink_toolbar/addlink_toolbar.php'; 7require_once 'plugins/addlink_toolbar/addlink_toolbar.php';
8 8
@@ -26,8 +26,9 @@ class PluginAddlinkTest extends \PHPUnit\Framework\TestCase
26 { 26 {
27 $str = 'stuff'; 27 $str = 'stuff';
28 $data = array($str => $str); 28 $data = array($str => $str);
29 $data['_PAGE_'] = Router::$PAGE_LINKLIST; 29 $data['_PAGE_'] = TemplatePage::LINKLIST;
30 $data['_LOGGEDIN_'] = true; 30 $data['_LOGGEDIN_'] = true;
31 $data['_BASE_PATH_'] = '/subfolder';
31 32
32 $data = hook_addlink_toolbar_render_header($data); 33 $data = hook_addlink_toolbar_render_header($data);
33 $this->assertEquals($str, $data[$str]); 34 $this->assertEquals($str, $data[$str]);
@@ -36,6 +37,8 @@ class PluginAddlinkTest extends \PHPUnit\Framework\TestCase
36 $data = array($str => $str); 37 $data = array($str => $str);
37 $data['_PAGE_'] = $str; 38 $data['_PAGE_'] = $str;
38 $data['_LOGGEDIN_'] = true; 39 $data['_LOGGEDIN_'] = true;
40 $data['_BASE_PATH_'] = '/subfolder';
41
39 $data = hook_addlink_toolbar_render_header($data); 42 $data = hook_addlink_toolbar_render_header($data);
40 $this->assertEquals($str, $data[$str]); 43 $this->assertEquals($str, $data[$str]);
41 $this->assertArrayNotHasKey('fields_toolbar', $data); 44 $this->assertArrayNotHasKey('fields_toolbar', $data);
@@ -48,8 +51,9 @@ class PluginAddlinkTest extends \PHPUnit\Framework\TestCase
48 { 51 {
49 $str = 'stuff'; 52 $str = 'stuff';
50 $data = array($str => $str); 53 $data = array($str => $str);
51 $data['_PAGE_'] = Router::$PAGE_LINKLIST; 54 $data['_PAGE_'] = TemplatePage::LINKLIST;
52 $data['_LOGGEDIN_'] = false; 55 $data['_LOGGEDIN_'] = false;
56 $data['_BASE_PATH_'] = '/subfolder';
53 57
54 $data = hook_addlink_toolbar_render_header($data); 58 $data = hook_addlink_toolbar_render_header($data);
55 $this->assertEquals($str, $data[$str]); 59 $this->assertEquals($str, $data[$str]);
diff --git a/tests/plugins/PluginPlayvideosTest.php b/tests/plugins/PluginPlayvideosTest.php
index 51472617..b7b6ce53 100644
--- a/tests/plugins/PluginPlayvideosTest.php
+++ b/tests/plugins/PluginPlayvideosTest.php
@@ -6,7 +6,7 @@ namespace Shaarli\Plugin\Playvideos;
6 */ 6 */
7 7
8use Shaarli\Plugin\PluginManager; 8use Shaarli\Plugin\PluginManager;
9use Shaarli\Router; 9use Shaarli\Render\TemplatePage;
10 10
11require_once 'plugins/playvideos/playvideos.php'; 11require_once 'plugins/playvideos/playvideos.php';
12 12
@@ -31,7 +31,7 @@ class PluginPlayvideosTest extends \PHPUnit\Framework\TestCase
31 { 31 {
32 $str = 'stuff'; 32 $str = 'stuff';
33 $data = array($str => $str); 33 $data = array($str => $str);
34 $data['_PAGE_'] = Router::$PAGE_LINKLIST; 34 $data['_PAGE_'] = TemplatePage::LINKLIST;
35 35
36 $data = hook_playvideos_render_header($data); 36 $data = hook_playvideos_render_header($data);
37 $this->assertEquals($str, $data[$str]); 37 $this->assertEquals($str, $data[$str]);
@@ -50,7 +50,7 @@ class PluginPlayvideosTest extends \PHPUnit\Framework\TestCase
50 { 50 {
51 $str = 'stuff'; 51 $str = 'stuff';
52 $data = array($str => $str); 52 $data = array($str => $str);
53 $data['_PAGE_'] = Router::$PAGE_LINKLIST; 53 $data['_PAGE_'] = TemplatePage::LINKLIST;
54 54
55 $data = hook_playvideos_render_footer($data); 55 $data = hook_playvideos_render_footer($data);
56 $this->assertEquals($str, $data[$str]); 56 $this->assertEquals($str, $data[$str]);
diff --git a/tests/plugins/PluginPubsubhubbubTest.php b/tests/plugins/PluginPubsubhubbubTest.php
index a7bd8fc9..e66f484e 100644
--- a/tests/plugins/PluginPubsubhubbubTest.php
+++ b/tests/plugins/PluginPubsubhubbubTest.php
@@ -3,7 +3,7 @@ namespace Shaarli\Plugin\Pubsubhubbub;
3 3
4use Shaarli\Config\ConfigManager; 4use Shaarli\Config\ConfigManager;
5use Shaarli\Plugin\PluginManager; 5use Shaarli\Plugin\PluginManager;
6use Shaarli\Router; 6use Shaarli\Render\TemplatePage;
7 7
8require_once 'plugins/pubsubhubbub/pubsubhubbub.php'; 8require_once 'plugins/pubsubhubbub/pubsubhubbub.php';
9 9
@@ -34,7 +34,7 @@ class PluginPubsubhubbubTest extends \PHPUnit\Framework\TestCase
34 $hub = 'http://domain.hub'; 34 $hub = 'http://domain.hub';
35 $conf = new ConfigManager(self::$configFile); 35 $conf = new ConfigManager(self::$configFile);
36 $conf->set('plugins.PUBSUBHUB_URL', $hub); 36 $conf->set('plugins.PUBSUBHUB_URL', $hub);
37 $data['_PAGE_'] = Router::$PAGE_FEED_RSS; 37 $data['_PAGE_'] = TemplatePage::FEED_RSS;
38 38
39 $data = hook_pubsubhubbub_render_feed($data, $conf); 39 $data = hook_pubsubhubbub_render_feed($data, $conf);
40 $expected = '<atom:link rel="hub" href="'. $hub .'" />'; 40 $expected = '<atom:link rel="hub" href="'. $hub .'" />';
@@ -49,7 +49,7 @@ class PluginPubsubhubbubTest extends \PHPUnit\Framework\TestCase
49 $hub = 'http://domain.hub'; 49 $hub = 'http://domain.hub';
50 $conf = new ConfigManager(self::$configFile); 50 $conf = new ConfigManager(self::$configFile);
51 $conf->set('plugins.PUBSUBHUB_URL', $hub); 51 $conf->set('plugins.PUBSUBHUB_URL', $hub);
52 $data['_PAGE_'] = Router::$PAGE_FEED_ATOM; 52 $data['_PAGE_'] = TemplatePage::FEED_ATOM;
53 53
54 $data = hook_pubsubhubbub_render_feed($data, $conf); 54 $data = hook_pubsubhubbub_render_feed($data, $conf);
55 $expected = '<link rel="hub" href="'. $hub .'" />'; 55 $expected = '<link rel="hub" href="'. $hub .'" />';
diff --git a/tests/plugins/PluginQrcodeTest.php b/tests/plugins/PluginQrcodeTest.php
index 0c61e14a..c9f8c733 100644
--- a/tests/plugins/PluginQrcodeTest.php
+++ b/tests/plugins/PluginQrcodeTest.php
@@ -6,7 +6,7 @@ namespace Shaarli\Plugin\Qrcode;
6 */ 6 */
7 7
8use Shaarli\Plugin\PluginManager; 8use Shaarli\Plugin\PluginManager;
9use Shaarli\Router; 9use Shaarli\Render\TemplatePage;
10 10
11require_once 'plugins/qrcode/qrcode.php'; 11require_once 'plugins/qrcode/qrcode.php';
12 12
@@ -57,7 +57,7 @@ class PluginQrcodeTest extends \PHPUnit\Framework\TestCase
57 { 57 {
58 $str = 'stuff'; 58 $str = 'stuff';
59 $data = array($str => $str); 59 $data = array($str => $str);
60 $data['_PAGE_'] = Router::$PAGE_LINKLIST; 60 $data['_PAGE_'] = TemplatePage::LINKLIST;
61 61
62 $data = hook_qrcode_render_footer($data); 62 $data = hook_qrcode_render_footer($data);
63 $this->assertEquals($str, $data[$str]); 63 $this->assertEquals($str, $data[$str]);
diff --git a/tests/plugins/resources/hashtags.md b/tests/plugins/resources/hashtags.md
deleted file mode 100644
index 46326de3..00000000
--- a/tests/plugins/resources/hashtags.md
+++ /dev/null
@@ -1,10 +0,0 @@
1[#lol](?addtag=lol)
2
3 #test
4
5`#test2`
6
7```
8bla #bli blo
9#bla
10```
diff --git a/tests/plugins/resources/hashtags.raw b/tests/plugins/resources/hashtags.raw
deleted file mode 100644
index 9d2dc98a..00000000
--- a/tests/plugins/resources/hashtags.raw
+++ /dev/null
@@ -1,10 +0,0 @@
1#lol
2
3 #test
4
5`#test2`
6
7```
8bla #bli blo
9#bla
10```
diff --git a/tests/plugins/resources/markdown.html b/tests/plugins/resources/markdown.html
deleted file mode 100644
index c3460bf7..00000000
--- a/tests/plugins/resources/markdown.html
+++ /dev/null
@@ -1,33 +0,0 @@
1<div class="markdown"><ul>
2<li>test:
3<ul>
4<li><a href="http://link.tld">zero</a></li>
5<li><a href="http://link.tld">two</a></li>
6<li><a href="http://link.tld">three</a></li>
7</ul></li>
8</ul>
9<ol>
10<li><a href="http://link.tld">zero</a>
11<ol start="2">
12<li><a href="http://link.tld">two</a></li>
13<li><a href="http://link.tld">three</a></li>
14<li><a href="http://link.tld">four</a></li>
15<li>foo <a href="?addtag=foobar">#foobar</a></li>
16</ol></li>
17</ol>
18<p><a href="?addtag=foobar">#foobar</a> foo <code>lol #foo</code> <a href="?addtag=bar">#bar</a></p>
19<p>fsdfs <a href="http://link.tld">http://link.tld</a> <a href="?addtag=foobar">#foobar</a> <code>http://link.tld</code></p>
20<pre><code>http://link.tld #foobar
21next #foo</code></pre>
22<p>Block:</p>
23<pre><code>lorem ipsum #foobar http://link.tld
24#foobar http://link.tld</code></pre>
25<p><a href="?123456">link</a><br />
26<img src="/img/train.png" alt="link" /><br />
27<a href="http://test.tld/path/?query=value#hash">link</a><br />
28<a href="http://test.tld/path/?query=value#hash">link</a><br />
29<a href="https://test.tld/path/?query=value#hash">link</a><br />
30<a href="ftp://test.tld/path/?query=value#hash">link</a><br />
31<a href="magnet:test.tld/path/?query=value#hash">link</a><br />
32<a href="http://alert(&#039;xss&#039;)">link</a><br />
33<a href="http://test.tld/path/?query=value#hash">link</a></p></div>
diff --git a/tests/plugins/resources/markdown.md b/tests/plugins/resources/markdown.md
deleted file mode 100644
index 9350a8c7..00000000
--- a/tests/plugins/resources/markdown.md
+++ /dev/null
@@ -1,34 +0,0 @@
1* test:
2 * [zero](http://link.tld)
3 + [two](http://link.tld)
4 - [three](http://link.tld)
5
61. [zero](http://link.tld)
7 2. [two](http://link.tld)
8 3. [three](http://link.tld)
9 4. [four](http://link.tld)
10 5. foo #foobar
11
12#foobar foo `lol #foo` #bar
13
14fsdfs http://link.tld #foobar `http://link.tld`
15
16 http://link.tld #foobar
17 next #foo
18
19Block:
20
21```
22lorem ipsum #foobar http://link.tld
23#foobar http://link.tld
24```
25
26[link](?123456)
27![link](/img/train.png)
28[link](test.tld/path/?query=value#hash)
29[link](http://test.tld/path/?query=value#hash)
30[link](https://test.tld/path/?query=value#hash)
31[link](ftp://test.tld/path/?query=value#hash)
32[link](magnet:test.tld/path/?query=value#hash)
33[link](javascript:alert('xss'))
34[link](other://test.tld/path/?query=value#hash)
diff --git a/tests/feed/CacheTest.php b/tests/render/PageCacheManagerTest.php
index c0a9f26f..c258f45f 100644
--- a/tests/feed/CacheTest.php
+++ b/tests/render/PageCacheManagerTest.php
@@ -1,18 +1,18 @@
1<?php 1<?php
2
2/** 3/**
3 * Cache tests 4 * Cache tests
4 */ 5 */
5namespace Shaarli\Feed;
6 6
7// required to access $_SESSION array 7namespace Shaarli\Render;
8session_start();
9 8
10require_once 'application/feed/Cache.php'; 9use PHPUnit\Framework\TestCase;
10use Shaarli\Security\SessionManager;
11 11
12/** 12/**
13 * Unitary tests for cached pages 13 * Unitary tests for cached pages
14 */ 14 */
15class CacheTest extends \PHPUnit\Framework\TestCase 15class PageCacheManagerTest extends TestCase
16{ 16{
17 // test cache directory 17 // test cache directory
18 protected static $testCacheDir = 'sandbox/dummycache'; 18 protected static $testCacheDir = 'sandbox/dummycache';
@@ -20,12 +20,19 @@ class CacheTest extends \PHPUnit\Framework\TestCase
20 // dummy cached file names / content 20 // dummy cached file names / content
21 protected static $pages = array('a', 'toto', 'd7b59c'); 21 protected static $pages = array('a', 'toto', 'd7b59c');
22 22
23 /** @var PageCacheManager */
24 protected $cacheManager;
25
26 /** @var SessionManager */
27 protected $sessionManager;
23 28
24 /** 29 /**
25 * Populate the cache with dummy files 30 * Populate the cache with dummy files
26 */ 31 */
27 public function setUp() 32 public function setUp()
28 { 33 {
34 $this->cacheManager = new PageCacheManager(static::$testCacheDir, true);
35
29 if (!is_dir(self::$testCacheDir)) { 36 if (!is_dir(self::$testCacheDir)) {
30 mkdir(self::$testCacheDir); 37 mkdir(self::$testCacheDir);
31 } else { 38 } else {
@@ -52,7 +59,7 @@ class CacheTest extends \PHPUnit\Framework\TestCase
52 */ 59 */
53 public function testPurgeCachedPages() 60 public function testPurgeCachedPages()
54 { 61 {
55 purgeCachedPages(self::$testCacheDir); 62 $this->cacheManager->purgeCachedPages();
56 foreach (self::$pages as $page) { 63 foreach (self::$pages as $page) {
57 $this->assertFileNotExists(self::$testCacheDir . '/' . $page . '.cache'); 64 $this->assertFileNotExists(self::$testCacheDir . '/' . $page . '.cache');
58 } 65 }
@@ -65,28 +72,14 @@ class CacheTest extends \PHPUnit\Framework\TestCase
65 */ 72 */
66 public function testPurgeCachedPagesMissingDir() 73 public function testPurgeCachedPagesMissingDir()
67 { 74 {
75 $this->cacheManager = new PageCacheManager(self::$testCacheDir . '_missing', true);
76
68 $oldlog = ini_get('error_log'); 77 $oldlog = ini_get('error_log');
69 ini_set('error_log', '/dev/null'); 78 ini_set('error_log', '/dev/null');
70 $this->assertEquals( 79 $this->assertEquals(
71 'Cannot purge sandbox/dummycache_missing: no directory', 80 'Cannot purge sandbox/dummycache_missing: no directory',
72 purgeCachedPages(self::$testCacheDir . '_missing') 81 $this->cacheManager->purgeCachedPages()
73 ); 82 );
74 ini_set('error_log', $oldlog); 83 ini_set('error_log', $oldlog);
75 } 84 }
76
77 /**
78 * Purge cached pages and session cache
79 */
80 public function testInvalidateCaches()
81 {
82 $this->assertArrayNotHasKey('tags', $_SESSION);
83 $_SESSION['tags'] = array('goodbye', 'cruel', 'world');
84
85 invalidateCaches(self::$testCacheDir);
86 foreach (self::$pages as $page) {
87 $this->assertFileNotExists(self::$testCacheDir . '/' . $page . '.cache');
88 }
89
90 $this->assertArrayNotHasKey('tags', $_SESSION);
91 }
92} 85}
diff --git a/tests/security/LoginManagerTest.php b/tests/security/LoginManagerTest.php
index 8fd1698c..f242be09 100644
--- a/tests/security/LoginManagerTest.php
+++ b/tests/security/LoginManagerTest.php
@@ -1,7 +1,6 @@
1<?php 1<?php
2namespace Shaarli\Security;
3 2
4require_once 'tests/utils/FakeConfigManager.php'; 3namespace Shaarli\Security;
5 4
6use PHPUnit\Framework\TestCase; 5use PHPUnit\Framework\TestCase;
7 6
@@ -58,6 +57,9 @@ class LoginManagerTest extends TestCase
58 /** @var string Salt used by hash functions */ 57 /** @var string Salt used by hash functions */
59 protected $salt = '669e24fa9c5a59a613f98e8e38327384504a4af2'; 58 protected $salt = '669e24fa9c5a59a613f98e8e38327384504a4af2';
60 59
60 /** @var CookieManager */
61 protected $cookieManager;
62
61 /** 63 /**
62 * Prepare or reset test resources 64 * Prepare or reset test resources
63 */ 65 */
@@ -84,8 +86,12 @@ class LoginManagerTest extends TestCase
84 $this->cookie = []; 86 $this->cookie = [];
85 $this->session = []; 87 $this->session = [];
86 88
87 $this->sessionManager = new SessionManager($this->session, $this->configManager); 89 $this->cookieManager = $this->createMock(CookieManager::class);
88 $this->loginManager = new LoginManager($this->configManager, $this->sessionManager); 90 $this->cookieManager->method('getCookieParameter')->willReturnCallback(function (string $key) {
91 return $this->cookie[$key] ?? null;
92 });
93 $this->sessionManager = new SessionManager($this->session, $this->configManager, 'session_path');
94 $this->loginManager = new LoginManager($this->configManager, $this->sessionManager, $this->cookieManager);
89 $this->server['REMOTE_ADDR'] = $this->ipAddr; 95 $this->server['REMOTE_ADDR'] = $this->ipAddr;
90 } 96 }
91 97
@@ -193,8 +199,8 @@ class LoginManagerTest extends TestCase
193 $configManager = new \FakeConfigManager([ 199 $configManager = new \FakeConfigManager([
194 'resource.ban_file' => $this->banFile, 200 'resource.ban_file' => $this->banFile,
195 ]); 201 ]);
196 $loginManager = new LoginManager($configManager, null); 202 $loginManager = new LoginManager($configManager, null, $this->cookieManager);
197 $loginManager->checkLoginState([], ''); 203 $loginManager->checkLoginState('');
198 204
199 $this->assertFalse($loginManager->isLoggedIn()); 205 $this->assertFalse($loginManager->isLoggedIn());
200 } 206 }
@@ -210,9 +216,9 @@ class LoginManagerTest extends TestCase
210 'expires_on' => time() + 100, 216 'expires_on' => time() + 100,
211 ]; 217 ];
212 $this->loginManager->generateStaySignedInToken($this->clientIpAddress); 218 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
213 $this->cookie[LoginManager::$STAY_SIGNED_IN_COOKIE] = 'nope'; 219 $this->cookie[CookieManager::STAY_SIGNED_IN] = 'nope';
214 220
215 $this->loginManager->checkLoginState($this->cookie, $this->clientIpAddress); 221 $this->loginManager->checkLoginState($this->clientIpAddress);
216 222
217 $this->assertTrue($this->loginManager->isLoggedIn()); 223 $this->assertTrue($this->loginManager->isLoggedIn());
218 $this->assertTrue(empty($this->session['username'])); 224 $this->assertTrue(empty($this->session['username']));
@@ -224,9 +230,9 @@ class LoginManagerTest extends TestCase
224 public function testCheckLoginStateStaySignedInWithValidToken() 230 public function testCheckLoginStateStaySignedInWithValidToken()
225 { 231 {
226 $this->loginManager->generateStaySignedInToken($this->clientIpAddress); 232 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
227 $this->cookie[LoginManager::$STAY_SIGNED_IN_COOKIE] = $this->loginManager->getStaySignedInToken(); 233 $this->cookie[CookieManager::STAY_SIGNED_IN] = $this->loginManager->getStaySignedInToken();
228 234
229 $this->loginManager->checkLoginState($this->cookie, $this->clientIpAddress); 235 $this->loginManager->checkLoginState($this->clientIpAddress);
230 236
231 $this->assertTrue($this->loginManager->isLoggedIn()); 237 $this->assertTrue($this->loginManager->isLoggedIn());
232 $this->assertEquals($this->login, $this->session['username']); 238 $this->assertEquals($this->login, $this->session['username']);
@@ -241,7 +247,7 @@ class LoginManagerTest extends TestCase
241 $this->loginManager->generateStaySignedInToken($this->clientIpAddress); 247 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
242 $this->session['expires_on'] = time() - 100; 248 $this->session['expires_on'] = time() - 100;
243 249
244 $this->loginManager->checkLoginState($this->cookie, $this->clientIpAddress); 250 $this->loginManager->checkLoginState($this->clientIpAddress);
245 251
246 $this->assertFalse($this->loginManager->isLoggedIn()); 252 $this->assertFalse($this->loginManager->isLoggedIn());
247 } 253 }
@@ -253,7 +259,7 @@ class LoginManagerTest extends TestCase
253 { 259 {
254 $this->loginManager->generateStaySignedInToken($this->clientIpAddress); 260 $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
255 261
256 $this->loginManager->checkLoginState($this->cookie, '10.7.157.98'); 262 $this->loginManager->checkLoginState('10.7.157.98');
257 263
258 $this->assertFalse($this->loginManager->isLoggedIn()); 264 $this->assertFalse($this->loginManager->isLoggedIn());
259 } 265 }
diff --git a/tests/security/SessionManagerTest.php b/tests/security/SessionManagerTest.php
index f264505e..60695dcf 100644
--- a/tests/security/SessionManagerTest.php
+++ b/tests/security/SessionManagerTest.php
@@ -1,12 +1,8 @@
1<?php 1<?php
2require_once 'tests/utils/FakeConfigManager.php';
3 2
4// Initialize reference data _before_ PHPUnit starts a session 3namespace Shaarli\Security;
5require_once 'tests/utils/ReferenceSessionIdHashes.php';
6ReferenceSessionIdHashes::genAllHashes();
7 4
8use PHPUnit\Framework\TestCase; 5use PHPUnit\Framework\TestCase;
9use Shaarli\Security\SessionManager;
10 6
11/** 7/**
12 * Test coverage for SessionManager 8 * Test coverage for SessionManager
@@ -30,7 +26,7 @@ class SessionManagerTest extends TestCase
30 */ 26 */
31 public static function setUpBeforeClass() 27 public static function setUpBeforeClass()
32 { 28 {
33 self::$sidHashes = ReferenceSessionIdHashes::getHashes(); 29 self::$sidHashes = \ReferenceSessionIdHashes::getHashes();
34 } 30 }
35 31
36 /** 32 /**
@@ -38,13 +34,13 @@ class SessionManagerTest extends TestCase
38 */ 34 */
39 public function setUp() 35 public function setUp()
40 { 36 {
41 $this->conf = new FakeConfigManager([ 37 $this->conf = new \FakeConfigManager([
42 'credentials.login' => 'johndoe', 38 'credentials.login' => 'johndoe',
43 'credentials.salt' => 'salt', 39 'credentials.salt' => 'salt',
44 'security.session_protection_disabled' => false, 40 'security.session_protection_disabled' => false,
45 ]); 41 ]);
46 $this->session = []; 42 $this->session = [];
47 $this->sessionManager = new SessionManager($this->session, $this->conf); 43 $this->sessionManager = new SessionManager($this->session, $this->conf, 'session_path');
48 } 44 }
49 45
50 /** 46 /**
@@ -69,7 +65,7 @@ class SessionManagerTest extends TestCase
69 $token => 1, 65 $token => 1,
70 ], 66 ],
71 ]; 67 ];
72 $sessionManager = new SessionManager($session, $this->conf); 68 $sessionManager = new SessionManager($session, $this->conf, 'session_path');
73 69
74 // check and destroy the token 70 // check and destroy the token
75 $this->assertTrue($sessionManager->checkToken($token)); 71 $this->assertTrue($sessionManager->checkToken($token));
@@ -269,4 +265,61 @@ class SessionManagerTest extends TestCase
269 $this->session['ip'] = 'ip_id_one'; 265 $this->session['ip'] = 'ip_id_one';
270 $this->assertTrue($this->sessionManager->hasClientIpChanged('ip_id_two')); 266 $this->assertTrue($this->sessionManager->hasClientIpChanged('ip_id_two'));
271 } 267 }
268
269 /**
270 * Test creating an entry in the session array
271 */
272 public function testSetSessionParameterCreate(): void
273 {
274 $this->sessionManager->setSessionParameter('abc', 'def');
275
276 static::assertSame('def', $this->session['abc']);
277 }
278
279 /**
280 * Test updating an entry in the session array
281 */
282 public function testSetSessionParameterUpdate(): void
283 {
284 $this->session['abc'] = 'ghi';
285
286 $this->sessionManager->setSessionParameter('abc', 'def');
287
288 static::assertSame('def', $this->session['abc']);
289 }
290
291 /**
292 * Test updating an entry in the session array with null value
293 */
294 public function testSetSessionParameterUpdateNull(): void
295 {
296 $this->session['abc'] = 'ghi';
297
298 $this->sessionManager->setSessionParameter('abc', null);
299
300 static::assertArrayHasKey('abc', $this->session);
301 static::assertNull($this->session['abc']);
302 }
303
304 /**
305 * Test deleting an existing entry in the session array
306 */
307 public function testDeleteSessionParameter(): void
308 {
309 $this->session['abc'] = 'def';
310
311 $this->sessionManager->deleteSessionParameter('abc');
312
313 static::assertArrayNotHasKey('abc', $this->session);
314 }
315
316 /**
317 * Test deleting a non existent entry in the session array
318 */
319 public function testDeleteSessionParameterNotExisting(): void
320 {
321 $this->sessionManager->deleteSessionParameter('abc');
322
323 static::assertArrayNotHasKey('abc', $this->session);
324 }
272} 325}
diff --git a/tests/updater/UpdaterTest.php b/tests/updater/UpdaterTest.php
index c689982b..a7dd70bf 100644
--- a/tests/updater/UpdaterTest.php
+++ b/tests/updater/UpdaterTest.php
@@ -2,17 +2,18 @@
2namespace Shaarli\Updater; 2namespace Shaarli\Updater;
3 3
4use Exception; 4use Exception;
5use PHPUnit\Framework\TestCase;
6use Shaarli\Bookmark\BookmarkFileService;
7use Shaarli\Bookmark\BookmarkServiceInterface;
5use Shaarli\Config\ConfigManager; 8use Shaarli\Config\ConfigManager;
9use Shaarli\History;
6 10
7require_once 'tests/updater/DummyUpdater.php';
8require_once 'tests/utils/ReferenceLinkDB.php';
9require_once 'inc/rain.tpl.class.php';
10 11
11/** 12/**
12 * Class UpdaterTest. 13 * Class UpdaterTest.
13 * Runs unit tests against the updater class. 14 * Runs unit tests against the updater class.
14 */ 15 */
15class UpdaterTest extends \PHPUnit\Framework\TestCase 16class UpdaterTest extends TestCase
16{ 17{
17 /** 18 /**
18 * @var string Path to test datastore. 19 * @var string Path to test datastore.
@@ -29,13 +30,27 @@ class UpdaterTest extends \PHPUnit\Framework\TestCase
29 */ 30 */
30 protected $conf; 31 protected $conf;
31 32
33 /** @var BookmarkServiceInterface */
34 protected $bookmarkService;
35
36 /** @var \ReferenceLinkDB */
37 protected $refDB;
38
39 /** @var Updater */
40 protected $updater;
41
32 /** 42 /**
33 * Executed before each test. 43 * Executed before each test.
34 */ 44 */
35 public function setUp() 45 public function setUp()
36 { 46 {
47 $this->refDB = new \ReferenceLinkDB();
48 $this->refDB->write(self::$testDatastore);
49
37 copy('tests/utils/config/configJson.json.php', self::$configFile .'.json.php'); 50 copy('tests/utils/config/configJson.json.php', self::$configFile .'.json.php');
38 $this->conf = new ConfigManager(self::$configFile); 51 $this->conf = new ConfigManager(self::$configFile);
52 $this->bookmarkService = new BookmarkFileService($this->conf, $this->createMock(History::class), true);
53 $this->updater = new Updater([], $this->bookmarkService, $this->conf, true);
39 } 54 }
40 55
41 /** 56 /**
@@ -167,4 +182,40 @@ class UpdaterTest extends \PHPUnit\Framework\TestCase
167 $updater = new DummyUpdater($updates, array(), $this->conf, true); 182 $updater = new DummyUpdater($updates, array(), $this->conf, true);
168 $updater->update(); 183 $updater->update();
169 } 184 }
185
186 public function testUpdateMethodRelativeHomeLinkRename(): void
187 {
188 $this->updater->setBasePath('/subfolder');
189 $this->conf->set('general.header_link', '?');
190
191 $this->updater->updateMethodRelativeHomeLink();
192
193 static::assertSame('/subfolder/', $this->conf->get('general.header_link'));
194 }
195
196 public function testUpdateMethodRelativeHomeLinkDoNotRename(): void
197 {
198 $this->conf->set('general.header_link', '~/my-blog');
199
200 $this->updater->updateMethodRelativeHomeLink();
201
202 static::assertSame('~/my-blog', $this->conf->get('general.header_link'));
203 }
204
205 public function testUpdateMethodMigrateExistingNotesUrl(): void
206 {
207 $this->updater->updateMethodMigrateExistingNotesUrl();
208
209 static::assertSame($this->refDB->getLinks()[0]->getUrl(), $this->bookmarkService->get(0)->getUrl());
210 static::assertSame($this->refDB->getLinks()[1]->getUrl(), $this->bookmarkService->get(1)->getUrl());
211 static::assertSame($this->refDB->getLinks()[4]->getUrl(), $this->bookmarkService->get(4)->getUrl());
212 static::assertSame($this->refDB->getLinks()[6]->getUrl(), $this->bookmarkService->get(6)->getUrl());
213 static::assertSame($this->refDB->getLinks()[7]->getUrl(), $this->bookmarkService->get(7)->getUrl());
214 static::assertSame($this->refDB->getLinks()[8]->getUrl(), $this->bookmarkService->get(8)->getUrl());
215 static::assertSame($this->refDB->getLinks()[9]->getUrl(), $this->bookmarkService->get(9)->getUrl());
216 static::assertSame('/shaare/WDWyig', $this->bookmarkService->get(42)->getUrl());
217 static::assertSame('/shaare/WDWyig', $this->bookmarkService->get(41)->getUrl());
218 static::assertSame('/shaare/0gCTjQ', $this->bookmarkService->get(10)->getUrl());
219 static::assertSame('/shaare/PCRizQ', $this->bookmarkService->get(11)->getUrl());
220 }
170} 221}
diff --git a/tests/utils/ReferenceLinkDB.php b/tests/utils/ReferenceLinkDB.php
index 0095f5a1..fc3cb109 100644
--- a/tests/utils/ReferenceLinkDB.php
+++ b/tests/utils/ReferenceLinkDB.php
@@ -30,7 +30,7 @@ class ReferenceLinkDB
30 $this->addLink( 30 $this->addLink(
31 11, 31 11,
32 'Pined older', 32 'Pined older',
33 '?PCRizQ', 33 '/shaare/PCRizQ',
34 'This is an older pinned link', 34 'This is an older pinned link',
35 0, 35 0,
36 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20100309_101010'), 36 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20100309_101010'),
@@ -43,7 +43,7 @@ class ReferenceLinkDB
43 $this->addLink( 43 $this->addLink(
44 10, 44 10,
45 'Pined', 45 'Pined',
46 '?0gCTjQ', 46 '/shaare/0gCTjQ',
47 'This is a pinned link', 47 'This is a pinned link',
48 0, 48 0,
49 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20121207_152312'), 49 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20121207_152312'),
@@ -56,7 +56,7 @@ class ReferenceLinkDB
56 $this->addLink( 56 $this->addLink(
57 41, 57 41,
58 'Link title: @website', 58 'Link title: @website',
59 '?WDWyig', 59 '/shaare/WDWyig',
60 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag', 60 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag',
61 0, 61 0,
62 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20150310_114651'), 62 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20150310_114651'),
@@ -68,7 +68,7 @@ class ReferenceLinkDB
68 $this->addLink( 68 $this->addLink(
69 42, 69 42,
70 'Note: I have a big ID but an old date', 70 'Note: I have a big ID but an old date',
71 '?WDWyig', 71 '/shaare/WDWyig',
72 'Used to test bookmarks reordering.', 72 'Used to test bookmarks reordering.',
73 0, 73 0,
74 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20100310_101010'), 74 DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20100310_101010'),