aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/front/controller/admin
diff options
context:
space:
mode:
Diffstat (limited to 'tests/front/controller/admin')
-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.php50
-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.php205
-rw-r--r--tests/front/controller/admin/ServerControllerTest.php184
-rw-r--r--tests/front/controller/admin/SessionFilterControllerTest.php177
-rw-r--r--tests/front/controller/admin/ShaareAddControllerTest.php97
-rw-r--r--tests/front/controller/admin/ShaareManageControllerTest/ChangeVisibilityBookmarkTest.php418
-rw-r--r--tests/front/controller/admin/ShaareManageControllerTest/DeleteBookmarkTest.php380
-rw-r--r--tests/front/controller/admin/ShaareManageControllerTest/PinBookmarkTest.php145
-rw-r--r--tests/front/controller/admin/ShaareManageControllerTest/SharePrivateTest.php139
-rw-r--r--tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateBatchFormTest.php63
-rw-r--r--tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateFormTest.php367
-rw-r--r--tests/front/controller/admin/ShaarePublishControllerTest/DisplayEditFormTest.php155
-rw-r--r--tests/front/controller/admin/ShaarePublishControllerTest/SaveBookmarkTest.php369
-rw-r--r--tests/front/controller/admin/ShaarliAdminControllerTest.php184
-rw-r--r--tests/front/controller/admin/ThumbnailsControllerTest.php156
-rw-r--r--tests/front/controller/admin/TokenControllerTest.php41
-rw-r--r--tests/front/controller/admin/ToolsControllerTest.php69
23 files changed, 4293 insertions, 0 deletions
diff --git a/tests/front/controller/admin/ConfigureControllerTest.php b/tests/front/controller/admin/ConfigureControllerTest.php
new file mode 100644
index 00000000..d82db0a7
--- /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 Shaarli\Config\ConfigManager;
8use Shaarli\Front\Exception\WrongTokenException;
9use Shaarli\Security\SessionManager;
10use Shaarli\TestCase;
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', 'markdownExtra'], $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(5, $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..0e6f2762
--- /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 Shaarli\Bookmark\Bookmark;
8use Shaarli\Formatter\BookmarkFormatter;
9use Shaarli\Formatter\BookmarkRawFormatter;
10use Shaarli\Netscape\NetscapeBookmarkUtils;
11use Shaarli\Security\SessionManager;
12use Shaarli\TestCase;
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/subfolder/', $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..c266caa5
--- /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 Psr\Http\Message\UploadedFileInterface;
8use Shaarli\Netscape\NetscapeBookmarkUtils;
9use Shaarli\Security\SessionManager;
10use Shaarli\TestCase;
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..94e53019
--- /dev/null
+++ b/tests/front/controller/admin/LogoutControllerTest.php
@@ -0,0 +1,50 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use Shaarli\Security\CookieManager;
8use Shaarli\Security\SessionManager;
9use Shaarli\TestCase;
10use Slim\Http\Request;
11use Slim\Http\Response;
12
13class LogoutControllerTest extends TestCase
14{
15 use FrontAdminControllerMockHelper;
16
17 /** @var LogoutController */
18 protected $controller;
19
20 public function setUp(): void
21 {
22 $this->createContainer();
23
24 $this->controller = new LogoutController($this->container);
25 }
26
27 public function testValidControllerInvoke(): void
28 {
29 $request = $this->createMock(Request::class);
30 $response = new Response();
31
32 $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches');
33
34 $this->container->sessionManager = $this->createMock(SessionManager::class);
35 $this->container->sessionManager->expects(static::once())->method('logout');
36
37 $this->container->cookieManager = $this->createMock(CookieManager::class);
38 $this->container->cookieManager
39 ->expects(static::once())
40 ->method('setCookieParameter')
41 ->with(CookieManager::STAY_SIGNED_IN, 'false', 0, '/subfolder/')
42 ;
43
44 $result = $this->controller->index($request, $response);
45
46 static::assertInstanceOf(Response::class, $result);
47 static::assertSame(302, $result->getStatusCode());
48 static::assertSame(['/subfolder/'], $result->getHeader('location'));
49 }
50}
diff --git a/tests/front/controller/admin/ManageTagControllerTest.php b/tests/front/controller/admin/ManageTagControllerTest.php
new file mode 100644
index 00000000..8a0ff7a9
--- /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 Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\BookmarkFilter;
9use Shaarli\Front\Exception\WrongTokenException;
10use Shaarli\Security\SessionManager;
11use Shaarli\TestCase;
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..58f47b49
--- /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 Shaarli\Config\ConfigManager;
8use Shaarli\Front\Exception\OpenShaarliPasswordException;
9use Shaarli\Front\Exception\WrongTokenException;
10use Shaarli\Security\SessionManager;
11use Shaarli\TestCase;
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..974d614d
--- /dev/null
+++ b/tests/front/controller/admin/PluginsControllerTest.php
@@ -0,0 +1,205 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use Shaarli\Config\ConfigManager;
8use Shaarli\Front\Exception\WrongTokenException;
9use Shaarli\Plugin\PluginManager;
10use Shaarli\Security\SessionManager;
11use Shaarli\TestCase;
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(): void
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 'token' => 'this parameter should not be saved'
129 ];
130
131 $request = $this->createMock(Request::class);
132 $request
133 ->expects(static::atLeastOnce())
134 ->method('getParams')
135 ->willReturnCallback(function () use ($parameters): array {
136 return $parameters;
137 })
138 ;
139 $response = new Response();
140
141 $this->container->pluginManager
142 ->expects(static::once())
143 ->method('executeHooks')
144 ->with('save_plugin_parameters', $parameters)
145 ;
146 $this->container->conf
147 ->expects(static::exactly(2))
148 ->method('set')
149 ->withConsecutive(['plugins.parameter1', 'blip'], ['plugins.parameter2', 'blop'])
150 ;
151
152 $result = $this->controller->save($request, $response);
153
154 static::assertSame(302, $result->getStatusCode());
155 static::assertSame(['/subfolder/admin/plugins'], $result->getHeader('location'));
156 }
157
158 /**
159 * Test save plugin parameters - error encountered
160 */
161 public function testSaveWithError(): void
162 {
163 $request = $this->createMock(Request::class);
164 $response = new Response();
165
166 $this->container->conf = $this->createMock(ConfigManager::class);
167 $this->container->conf
168 ->expects(static::atLeastOnce())
169 ->method('write')
170 ->willThrowException(new \Exception($message = 'error message'))
171 ;
172
173 $this->container->sessionManager = $this->createMock(SessionManager::class);
174 $this->container->sessionManager->method('checkToken')->willReturn(true);
175 $this->container->sessionManager
176 ->expects(static::once())
177 ->method('setSessionParameter')
178 ->with(
179 SessionManager::KEY_ERROR_MESSAGES,
180 ['Error while saving plugin configuration: ' . PHP_EOL . $message]
181 )
182 ;
183
184 $result = $this->controller->save($request, $response);
185
186 static::assertSame(302, $result->getStatusCode());
187 static::assertSame(['/subfolder/admin/plugins'], $result->getHeader('location'));
188 }
189
190 /**
191 * Test save plugin parameters - wrong token
192 */
193 public function testSaveWrongToken(): void
194 {
195 $this->container->sessionManager = $this->createMock(SessionManager::class);
196 $this->container->sessionManager->method('checkToken')->willReturn(false);
197
198 $request = $this->createMock(Request::class);
199 $response = new Response();
200
201 $this->expectException(WrongTokenException::class);
202
203 $this->controller->save($request, $response);
204 }
205}
diff --git a/tests/front/controller/admin/ServerControllerTest.php b/tests/front/controller/admin/ServerControllerTest.php
new file mode 100644
index 00000000..355cce7d
--- /dev/null
+++ b/tests/front/controller/admin/ServerControllerTest.php
@@ -0,0 +1,184 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use Shaarli\Config\ConfigManager;
8use Shaarli\Security\SessionManager;
9use Shaarli\TestCase;
10use Slim\Http\Request;
11use Slim\Http\Response;
12
13/**
14 * Test Server administration controller.
15 */
16class ServerControllerTest extends TestCase
17{
18 use FrontAdminControllerMockHelper;
19
20 /** @var ServerController */
21 protected $controller;
22
23 public function setUp(): void
24 {
25 $this->createContainer();
26
27 $this->controller = new ServerController($this->container);
28
29 // initialize dummy cache
30 @mkdir('sandbox/');
31 foreach (['pagecache', 'tmp', 'cache'] as $folder) {
32 @mkdir('sandbox/' . $folder);
33 @touch('sandbox/' . $folder . '/.htaccess');
34 @touch('sandbox/' . $folder . '/1');
35 @touch('sandbox/' . $folder . '/2');
36 }
37 }
38
39 public function tearDown(): void
40 {
41 foreach (['pagecache', 'tmp', 'cache'] as $folder) {
42 @unlink('sandbox/' . $folder . '/.htaccess');
43 @unlink('sandbox/' . $folder . '/1');
44 @unlink('sandbox/' . $folder . '/2');
45 @rmdir('sandbox/' . $folder);
46 }
47 }
48
49 /**
50 * Test default display of server administration page.
51 */
52 public function testIndex(): void
53 {
54 $request = $this->createMock(Request::class);
55 $response = new Response();
56
57 // Save RainTPL assigned variables
58 $assignedVariables = [];
59 $this->assignTemplateVars($assignedVariables);
60
61 $result = $this->controller->index($request, $response);
62
63 static::assertSame(200, $result->getStatusCode());
64 static::assertSame('server', (string) $result->getBody());
65
66 static::assertSame(PHP_VERSION, $assignedVariables['php_version']);
67 static::assertArrayHasKey('php_has_reached_eol', $assignedVariables);
68 static::assertArrayHasKey('php_eol', $assignedVariables);
69 static::assertArrayHasKey('php_extensions', $assignedVariables);
70 static::assertArrayHasKey('permissions', $assignedVariables);
71 static::assertEmpty($assignedVariables['permissions']);
72
73 static::assertRegExp(
74 '#https://github\.com/shaarli/Shaarli/releases/tag/v\d+\.\d+\.\d+#',
75 $assignedVariables['release_url']
76 );
77 static::assertRegExp('#v\d+\.\d+\.\d+#', $assignedVariables['latest_version']);
78 static::assertRegExp('#(v\d+\.\d+\.\d+|dev)#', $assignedVariables['current_version']);
79 static::assertArrayHasKey('index_url', $assignedVariables);
80 static::assertArrayHasKey('client_ip', $assignedVariables);
81 static::assertArrayHasKey('trusted_proxies', $assignedVariables);
82
83 static::assertSame('Server administration - Shaarli', $assignedVariables['pagetitle']);
84 }
85
86 /**
87 * Test clearing the main cache
88 */
89 public function testClearMainCache(): void
90 {
91 $this->container->conf = $this->createMock(ConfigManager::class);
92 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
93 if ($key === 'resource.page_cache') {
94 return 'sandbox/pagecache';
95 } elseif ($key === 'resource.raintpl_tmp') {
96 return 'sandbox/tmp';
97 } elseif ($key === 'resource.thumbnails_cache') {
98 return 'sandbox/cache';
99 } else {
100 return $default;
101 }
102 });
103
104 $this->container->sessionManager
105 ->expects(static::once())
106 ->method('setSessionParameter')
107 ->with(SessionManager::KEY_SUCCESS_MESSAGES, ['Shaarli\'s cache folder has been cleared!'])
108 ;
109
110 $request = $this->createMock(Request::class);
111 $request->method('getQueryParam')->with('type')->willReturn('main');
112 $response = new Response();
113
114 $result = $this->controller->clearCache($request, $response);
115
116 static::assertSame(302, $result->getStatusCode());
117 static::assertSame('/subfolder/admin/server', (string) $result->getHeaderLine('Location'));
118
119 static::assertFileNotExists('sandbox/pagecache/1');
120 static::assertFileNotExists('sandbox/pagecache/2');
121 static::assertFileNotExists('sandbox/tmp/1');
122 static::assertFileNotExists('sandbox/tmp/2');
123
124 static::assertFileExists('sandbox/pagecache/.htaccess');
125 static::assertFileExists('sandbox/tmp/.htaccess');
126 static::assertFileExists('sandbox/cache');
127 static::assertFileExists('sandbox/cache/.htaccess');
128 static::assertFileExists('sandbox/cache/1');
129 static::assertFileExists('sandbox/cache/2');
130 }
131
132 /**
133 * Test clearing thumbnails cache
134 */
135 public function testClearThumbnailsCache(): void
136 {
137 $this->container->conf = $this->createMock(ConfigManager::class);
138 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
139 if ($key === 'resource.page_cache') {
140 return 'sandbox/pagecache';
141 } elseif ($key === 'resource.raintpl_tmp') {
142 return 'sandbox/tmp';
143 } elseif ($key === 'resource.thumbnails_cache') {
144 return 'sandbox/cache';
145 } else {
146 return $default;
147 }
148 });
149
150 $this->container->sessionManager
151 ->expects(static::once())
152 ->method('setSessionParameter')
153 ->willReturnCallback(function (string $key, array $value): SessionManager {
154 static::assertSame(SessionManager::KEY_WARNING_MESSAGES, $key);
155 static::assertCount(1, $value);
156 static::assertStringStartsWith('Thumbnails cache has been cleared.', $value[0]);
157
158 return $this->container->sessionManager;
159 });
160 ;
161
162 $request = $this->createMock(Request::class);
163 $request->method('getQueryParam')->with('type')->willReturn('thumbnails');
164 $response = new Response();
165
166 $result = $this->controller->clearCache($request, $response);
167
168 static::assertSame(302, $result->getStatusCode());
169 static::assertSame('/subfolder/admin/server', (string) $result->getHeaderLine('Location'));
170
171 static::assertFileNotExists('sandbox/cache/1');
172 static::assertFileNotExists('sandbox/cache/2');
173
174 static::assertFileExists('sandbox/cache/.htaccess');
175 static::assertFileExists('sandbox/pagecache');
176 static::assertFileExists('sandbox/pagecache/.htaccess');
177 static::assertFileExists('sandbox/pagecache/1');
178 static::assertFileExists('sandbox/pagecache/2');
179 static::assertFileExists('sandbox/tmp');
180 static::assertFileExists('sandbox/tmp/.htaccess');
181 static::assertFileExists('sandbox/tmp/1');
182 static::assertFileExists('sandbox/tmp/2');
183 }
184}
diff --git a/tests/front/controller/admin/SessionFilterControllerTest.php b/tests/front/controller/admin/SessionFilterControllerTest.php
new file mode 100644
index 00000000..712a625b
--- /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 Shaarli\Security\LoginManager;
8use Shaarli\Security\SessionManager;
9use Shaarli\TestCase;
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/ShaareAddControllerTest.php b/tests/front/controller/admin/ShaareAddControllerTest.php
new file mode 100644
index 00000000..a27ebe64
--- /dev/null
+++ b/tests/front/controller/admin/ShaareAddControllerTest.php
@@ -0,0 +1,97 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use Shaarli\Config\ConfigManager;
8use Shaarli\Formatter\BookmarkMarkdownFormatter;
9use Shaarli\Http\HttpAccess;
10use Shaarli\TestCase;
11use Slim\Http\Request;
12use Slim\Http\Response;
13
14class ShaareAddControllerTest extends TestCase
15{
16 use FrontAdminControllerMockHelper;
17
18 /** @var ShaareAddController */
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 ShaareAddController($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 $expectedTags = [
41 'tag1' => 32,
42 'tag2' => 24,
43 'tag3' => 1,
44 ];
45 $this->container->bookmarkService
46 ->expects(static::once())
47 ->method('bookmarksCountPerTag')
48 ->willReturn($expectedTags)
49 ;
50 $expectedTags = array_merge($expectedTags, [BookmarkMarkdownFormatter::NO_MD_TAG => 1]);
51
52 $this->container->conf = $this->createMock(ConfigManager::class);
53 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
54 return $key === 'formatter' ? 'markdown' : $default;
55 });
56
57 $result = $this->controller->addShaare($request, $response);
58
59 static::assertSame(200, $result->getStatusCode());
60 static::assertSame('addlink', (string) $result->getBody());
61
62 static::assertSame('Shaare a new link - Shaarli', $assignedVariables['pagetitle']);
63 static::assertFalse($assignedVariables['default_private_links']);
64 static::assertTrue($assignedVariables['async_metadata']);
65 static::assertSame($expectedTags, $assignedVariables['tags']);
66 }
67
68 /**
69 * Test displaying add link page
70 */
71 public function testAddShaareWithoutMd(): void
72 {
73 $assignedVariables = [];
74 $this->assignTemplateVars($assignedVariables);
75
76 $request = $this->createMock(Request::class);
77 $response = new Response();
78
79 $expectedTags = [
80 'tag1' => 32,
81 'tag2' => 24,
82 'tag3' => 1,
83 ];
84 $this->container->bookmarkService
85 ->expects(static::once())
86 ->method('bookmarksCountPerTag')
87 ->willReturn($expectedTags)
88 ;
89
90 $result = $this->controller->addShaare($request, $response);
91
92 static::assertSame(200, $result->getStatusCode());
93 static::assertSame('addlink', (string) $result->getBody());
94
95 static::assertSame($expectedTags, $assignedVariables['tags']);
96 }
97}
diff --git a/tests/front/controller/admin/ShaareManageControllerTest/ChangeVisibilityBookmarkTest.php b/tests/front/controller/admin/ShaareManageControllerTest/ChangeVisibilityBookmarkTest.php
new file mode 100644
index 00000000..28b1c023
--- /dev/null
+++ b/tests/front/controller/admin/ShaareManageControllerTest/ChangeVisibilityBookmarkTest.php
@@ -0,0 +1,418 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ShaareManageControllerTest;
6
7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
9use Shaarli\Formatter\BookmarkFormatter;
10use Shaarli\Formatter\BookmarkRawFormatter;
11use Shaarli\Formatter\FormatterFactory;
12use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
13use Shaarli\Front\Controller\Admin\ShaareManageController;
14use Shaarli\Http\HttpAccess;
15use Shaarli\Security\SessionManager;
16use Shaarli\TestCase;
17use Slim\Http\Request;
18use Slim\Http\Response;
19
20class ChangeVisibilityBookmarkTest extends TestCase
21{
22 use FrontAdminControllerMockHelper;
23
24 /** @var ShaareManageController */
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 ShaareManageController($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/ShaareManageControllerTest/DeleteBookmarkTest.php b/tests/front/controller/admin/ShaareManageControllerTest/DeleteBookmarkTest.php
new file mode 100644
index 00000000..770a16d7
--- /dev/null
+++ b/tests/front/controller/admin/ShaareManageControllerTest/DeleteBookmarkTest.php
@@ -0,0 +1,380 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ShaareManageControllerTest;
6
7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
9use Shaarli\Formatter\BookmarkFormatter;
10use Shaarli\Formatter\FormatterFactory;
11use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
12use Shaarli\Front\Controller\Admin\ShaareManageController;
13use Shaarli\Http\HttpAccess;
14use Shaarli\Security\SessionManager;
15use Shaarli\TestCase;
16use Slim\Http\Request;
17use Slim\Http\Response;
18
19class DeleteBookmarkTest extends TestCase
20{
21 use FrontAdminControllerMockHelper;
22
23 /** @var ShaareManageController */
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 ShaareManageController($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->bookmarkService->method('get')->with('123')->willReturn(
360 (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')
361 );
362
363 $this->container->formatterFactory = $this->createMock(FormatterFactory::class);
364 $this->container->formatterFactory
365 ->expects(static::once())
366 ->method('getFormatter')
367 ->willReturnCallback(function (): BookmarkFormatter {
368 $formatter = $this->createMock(BookmarkFormatter::class);
369 $formatter->method('format')->willReturn(['formatted']);
370
371 return $formatter;
372 })
373 ;
374
375 $result = $this->controller->deleteBookmark($request, $response);
376
377 static::assertSame(200, $result->getStatusCode());
378 static::assertSame('<script>self.close();</script>', (string) $result->getBody('location'));
379 }
380}
diff --git a/tests/front/controller/admin/ShaareManageControllerTest/PinBookmarkTest.php b/tests/front/controller/admin/ShaareManageControllerTest/PinBookmarkTest.php
new file mode 100644
index 00000000..b89206ce
--- /dev/null
+++ b/tests/front/controller/admin/ShaareManageControllerTest/PinBookmarkTest.php
@@ -0,0 +1,145 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ShaareManageControllerTest;
6
7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
9use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
10use Shaarli\Front\Controller\Admin\ShaareManageController;
11use Shaarli\Http\HttpAccess;
12use Shaarli\Security\SessionManager;
13use Shaarli\TestCase;
14use Slim\Http\Request;
15use Slim\Http\Response;
16
17class PinBookmarkTest extends TestCase
18{
19 use FrontAdminControllerMockHelper;
20
21 /** @var ShaareManageController */
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 ShaareManageController($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/ShaareManageControllerTest/SharePrivateTest.php b/tests/front/controller/admin/ShaareManageControllerTest/SharePrivateTest.php
new file mode 100644
index 00000000..ae61dfb7
--- /dev/null
+++ b/tests/front/controller/admin/ShaareManageControllerTest/SharePrivateTest.php
@@ -0,0 +1,139 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ShaareManageControllerTest;
6
7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
9use Shaarli\Front\Controller\Admin\ShaareManageController;
10use Shaarli\Http\HttpAccess;
11use Shaarli\TestCase;
12use Slim\Http\Request;
13use Slim\Http\Response;
14
15/**
16 * Test GET /admin/shaare/private/{hash}
17 */
18class SharePrivateTest extends TestCase
19{
20 use FrontAdminControllerMockHelper;
21
22 /** @var ShaareManageController */
23 protected $controller;
24
25 public function setUp(): void
26 {
27 $this->createContainer();
28
29 $this->container->httpAccess = $this->createMock(HttpAccess::class);
30 $this->controller = new ShaareManageController($this->container);
31 }
32
33 /**
34 * Test shaare private with a private bookmark which does not have a key yet.
35 */
36 public function testSharePrivateWithNewPrivateBookmark(): void
37 {
38 $hash = 'abcdcef';
39 $request = $this->createMock(Request::class);
40 $response = new Response();
41
42 $bookmark = (new Bookmark())
43 ->setId(123)
44 ->setUrl('http://domain.tld')
45 ->setTitle('Title 123')
46 ->setPrivate(true)
47 ;
48
49 $this->container->bookmarkService
50 ->expects(static::once())
51 ->method('findByHash')
52 ->with($hash)
53 ->willReturn($bookmark)
54 ;
55 $this->container->bookmarkService
56 ->expects(static::once())
57 ->method('set')
58 ->with($bookmark, true)
59 ->willReturnCallback(function (Bookmark $bookmark): Bookmark {
60 static::assertSame(32, strlen($bookmark->getAdditionalContentEntry('private_key')));
61
62 return $bookmark;
63 })
64 ;
65
66 $result = $this->controller->sharePrivate($request, $response, ['hash' => $hash]);
67
68 static::assertSame(302, $result->getStatusCode());
69 static::assertRegExp('#/subfolder/shaare/' . $hash . '\?key=\w{32}#', $result->getHeaderLine('Location'));
70 }
71
72 /**
73 * Test shaare private with a private bookmark which does already have a key.
74 */
75 public function testSharePrivateWithExistingPrivateBookmark(): void
76 {
77 $hash = 'abcdcef';
78 $existingKey = 'this is a private key';
79 $request = $this->createMock(Request::class);
80 $response = new Response();
81
82 $bookmark = (new Bookmark())
83 ->setId(123)
84 ->setUrl('http://domain.tld')
85 ->setTitle('Title 123')
86 ->setPrivate(true)
87 ->addAdditionalContentEntry('private_key', $existingKey)
88 ;
89
90 $this->container->bookmarkService
91 ->expects(static::once())
92 ->method('findByHash')
93 ->with($hash)
94 ->willReturn($bookmark)
95 ;
96 $this->container->bookmarkService
97 ->expects(static::never())
98 ->method('set')
99 ;
100
101 $result = $this->controller->sharePrivate($request, $response, ['hash' => $hash]);
102
103 static::assertSame(302, $result->getStatusCode());
104 static::assertSame('/subfolder/shaare/' . $hash . '?key=' . $existingKey, $result->getHeaderLine('Location'));
105 }
106
107 /**
108 * Test shaare private with a public bookmark.
109 */
110 public function testSharePrivateWithPublicBookmark(): void
111 {
112 $hash = 'abcdcef';
113 $request = $this->createMock(Request::class);
114 $response = new Response();
115
116 $bookmark = (new Bookmark())
117 ->setId(123)
118 ->setUrl('http://domain.tld')
119 ->setTitle('Title 123')
120 ->setPrivate(false)
121 ;
122
123 $this->container->bookmarkService
124 ->expects(static::once())
125 ->method('findByHash')
126 ->with($hash)
127 ->willReturn($bookmark)
128 ;
129 $this->container->bookmarkService
130 ->expects(static::never())
131 ->method('set')
132 ;
133
134 $result = $this->controller->sharePrivate($request, $response, ['hash' => $hash]);
135
136 static::assertSame(302, $result->getStatusCode());
137 static::assertSame('/subfolder/shaare/' . $hash, $result->getHeaderLine('Location'));
138 }
139}
diff --git a/tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateBatchFormTest.php b/tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateBatchFormTest.php
new file mode 100644
index 00000000..ce8e112b
--- /dev/null
+++ b/tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateBatchFormTest.php
@@ -0,0 +1,63 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ShaarePublishControllerTest;
6
7use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
8use Shaarli\Front\Controller\Admin\ShaarePublishController;
9use Shaarli\Http\HttpAccess;
10use Shaarli\Http\MetadataRetriever;
11use Shaarli\TestCase;
12use Slim\Http\Request;
13use Slim\Http\Response;
14
15class DisplayCreateBatchFormTest extends TestCase
16{
17 use FrontAdminControllerMockHelper;
18
19 /** @var ShaarePublishController */
20 protected $controller;
21
22 public function setUp(): void
23 {
24 $this->createContainer();
25
26 $this->container->httpAccess = $this->createMock(HttpAccess::class);
27 $this->container->metadataRetriever = $this->createMock(MetadataRetriever::class);
28 $this->controller = new ShaarePublishController($this->container);
29 }
30
31 /**
32 * TODO
33 */
34 public function testDisplayCreateFormBatch(): void
35 {
36 $urls = [
37 'https://domain1.tld/url1',
38 'https://domain2.tld/url2',
39 ' ',
40 'https://domain3.tld/url3',
41 ];
42
43 $request = $this->createMock(Request::class);
44 $request->method('getParam')->willReturnCallback(function (string $key) use ($urls): ?string {
45 return $key === 'urls' ? implode(PHP_EOL, $urls) : null;
46 });
47 $response = new Response();
48
49 $assignedVariables = [];
50 $this->assignTemplateVars($assignedVariables);
51
52 $result = $this->controller->displayCreateBatchForms($request, $response);
53
54 static::assertSame(200, $result->getStatusCode());
55 static::assertSame('editlink.batch', (string) $result->getBody());
56
57 static::assertTrue($assignedVariables['batch_mode']);
58 static::assertCount(3, $assignedVariables['links']);
59 static::assertSame($urls[0], $assignedVariables['links'][0]['link']['url']);
60 static::assertSame($urls[1], $assignedVariables['links'][1]['link']['url']);
61 static::assertSame($urls[3], $assignedVariables['links'][2]['link']['url']);
62 }
63}
diff --git a/tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateFormTest.php b/tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateFormTest.php
new file mode 100644
index 00000000..f20b1def
--- /dev/null
+++ b/tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateFormTest.php
@@ -0,0 +1,367 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ShaarePublishControllerTest;
6
7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Config\ConfigManager;
9use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
10use Shaarli\Front\Controller\Admin\ShaarePublishController;
11use Shaarli\Http\HttpAccess;
12use Shaarli\Http\MetadataRetriever;
13use Shaarli\TestCase;
14use Slim\Http\Request;
15use Slim\Http\Response;
16
17class DisplayCreateFormTest extends TestCase
18{
19 use FrontAdminControllerMockHelper;
20
21 /** @var ShaarePublishController */
22 protected $controller;
23
24 public function setUp(): void
25 {
26 $this->createContainer();
27
28 $this->container->httpAccess = $this->createMock(HttpAccess::class);
29 $this->container->metadataRetriever = $this->createMock(MetadataRetriever::class);
30 $this->controller = new ShaarePublishController($this->container);
31 }
32
33 /**
34 * Test displaying bookmark create form
35 * Ensure that every step of the standard workflow works properly.
36 */
37 public function testDisplayCreateFormWithUrlAndWithMetadataRetrieval(): void
38 {
39 $this->container->environment = [
40 'HTTP_REFERER' => $referer = 'http://shaarli/subfolder/controller/?searchtag=abc'
41 ];
42
43 $assignedVariables = [];
44 $this->assignTemplateVars($assignedVariables);
45
46 $url = 'http://url.tld/other?part=3&utm_ad=pay#hash';
47 $expectedUrl = str_replace('&utm_ad=pay', '', $url);
48 $remoteTitle = 'Remote Title';
49 $remoteDesc = 'Sometimes the meta description is relevant.';
50 $remoteTags = 'abc def';
51
52 $request = $this->createMock(Request::class);
53 $request->method('getParam')->willReturnCallback(function (string $key) use ($url): ?string {
54 return $key === 'post' ? $url : null;
55 });
56 $response = new Response();
57
58 $this->container->conf = $this->createMock(ConfigManager::class);
59 $this->container->conf->method('get')->willReturnCallback(function (string $param, $default) {
60 if ($param === 'general.enable_async_metadata') {
61 return false;
62 }
63
64 return $default;
65 });
66
67 $this->container->metadataRetriever->expects(static::once())->method('retrieve')->willReturn([
68 'title' => $remoteTitle,
69 'description' => $remoteDesc,
70 'tags' => $remoteTags,
71 ]);
72
73 $this->container->bookmarkService
74 ->expects(static::once())
75 ->method('bookmarksCountPerTag')
76 ->willReturn($tags = ['tag1' => 2, 'tag2' => 1])
77 ;
78
79 // Make sure that PluginManager hook is triggered
80 $this->container->pluginManager
81 ->expects(static::atLeastOnce())
82 ->method('executeHooks')
83 ->withConsecutive(['render_editlink'], ['render_includes'])
84 ->willReturnCallback(function (string $hook, array $data) use ($remoteTitle, $remoteDesc): array {
85 if ('render_editlink' === $hook) {
86 static::assertSame($remoteTitle, $data['link']['title']);
87 static::assertSame($remoteDesc, $data['link']['description']);
88 }
89
90 return $data;
91 })
92 ;
93
94 $result = $this->controller->displayCreateForm($request, $response);
95
96 static::assertSame(200, $result->getStatusCode());
97 static::assertSame('editlink', (string) $result->getBody());
98
99 static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']);
100
101 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
102 static::assertSame($remoteTitle, $assignedVariables['link']['title']);
103 static::assertSame($remoteDesc, $assignedVariables['link']['description']);
104 static::assertSame($remoteTags, $assignedVariables['link']['tags']);
105 static::assertFalse($assignedVariables['link']['private']);
106
107 static::assertTrue($assignedVariables['link_is_new']);
108 static::assertSame($referer, $assignedVariables['http_referer']);
109 static::assertSame($tags, $assignedVariables['tags']);
110 static::assertArrayHasKey('source', $assignedVariables);
111 static::assertArrayHasKey('default_private_links', $assignedVariables);
112 static::assertArrayHasKey('async_metadata', $assignedVariables);
113 static::assertArrayHasKey('retrieve_description', $assignedVariables);
114 }
115
116 /**
117 * Test displaying bookmark create form without any external metadata retrieval attempt
118 */
119 public function testDisplayCreateFormWithUrlAndWithoutMetadata(): void
120 {
121 $this->container->environment = [
122 'HTTP_REFERER' => $referer = 'http://shaarli/subfolder/controller/?searchtag=abc'
123 ];
124
125 $assignedVariables = [];
126 $this->assignTemplateVars($assignedVariables);
127
128 $url = 'http://url.tld/other?part=3&utm_ad=pay#hash';
129 $expectedUrl = str_replace('&utm_ad=pay', '', $url);
130
131 $request = $this->createMock(Request::class);
132 $request->method('getParam')->willReturnCallback(function (string $key) use ($url): ?string {
133 return $key === 'post' ? $url : null;
134 });
135 $response = new Response();
136
137 $this->container->metadataRetriever->expects(static::never())->method('retrieve');
138
139 $this->container->bookmarkService
140 ->expects(static::once())
141 ->method('bookmarksCountPerTag')
142 ->willReturn($tags = ['tag1' => 2, 'tag2' => 1])
143 ;
144
145 // Make sure that PluginManager hook is triggered
146 $this->container->pluginManager
147 ->expects(static::atLeastOnce())
148 ->method('executeHooks')
149 ->withConsecutive(['render_editlink'], ['render_includes'])
150 ->willReturnCallback(function (string $hook, array $data): array {
151 if ('render_editlink' === $hook) {
152 static::assertSame('', $data['link']['title']);
153 static::assertSame('', $data['link']['description']);
154 }
155
156 return $data;
157 })
158 ;
159
160 $result = $this->controller->displayCreateForm($request, $response);
161
162 static::assertSame(200, $result->getStatusCode());
163 static::assertSame('editlink', (string) $result->getBody());
164
165 static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']);
166
167 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
168 static::assertSame('', $assignedVariables['link']['title']);
169 static::assertSame('', $assignedVariables['link']['description']);
170 static::assertSame('', $assignedVariables['link']['tags']);
171 static::assertFalse($assignedVariables['link']['private']);
172
173 static::assertTrue($assignedVariables['link_is_new']);
174 static::assertSame($referer, $assignedVariables['http_referer']);
175 static::assertSame($tags, $assignedVariables['tags']);
176 static::assertArrayHasKey('source', $assignedVariables);
177 static::assertArrayHasKey('default_private_links', $assignedVariables);
178 static::assertArrayHasKey('async_metadata', $assignedVariables);
179 static::assertArrayHasKey('retrieve_description', $assignedVariables);
180 }
181
182 /**
183 * Test displaying bookmark create form
184 * Ensure all available query parameters are handled properly.
185 */
186 public function testDisplayCreateFormWithFullParameters(): void
187 {
188 $assignedVariables = [];
189 $this->assignTemplateVars($assignedVariables);
190
191 $parameters = [
192 'post' => 'http://url.tld/other?part=3&utm_ad=pay#hash',
193 'title' => 'Provided Title',
194 'description' => 'Provided description.',
195 'tags' => 'abc def',
196 'private' => '1',
197 'source' => 'apps',
198 ];
199 $expectedUrl = str_replace('&utm_ad=pay', '', $parameters['post']);
200
201 $request = $this->createMock(Request::class);
202 $request
203 ->method('getParam')
204 ->willReturnCallback(function (string $key) use ($parameters): ?string {
205 return $parameters[$key] ?? null;
206 });
207 $response = new Response();
208
209 $result = $this->controller->displayCreateForm($request, $response);
210
211 static::assertSame(200, $result->getStatusCode());
212 static::assertSame('editlink', (string) $result->getBody());
213
214 static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']);
215
216 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
217 static::assertSame($parameters['title'], $assignedVariables['link']['title']);
218 static::assertSame($parameters['description'], $assignedVariables['link']['description']);
219 static::assertSame($parameters['tags'], $assignedVariables['link']['tags']);
220 static::assertTrue($assignedVariables['link']['private']);
221 static::assertTrue($assignedVariables['link_is_new']);
222 static::assertSame($parameters['source'], $assignedVariables['source']);
223 }
224
225 /**
226 * Test displaying bookmark create form
227 * Without any parameter.
228 */
229 public function testDisplayCreateFormEmpty(): void
230 {
231 $assignedVariables = [];
232 $this->assignTemplateVars($assignedVariables);
233
234 $request = $this->createMock(Request::class);
235 $response = new Response();
236
237 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
238 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
239
240 $result = $this->controller->displayCreateForm($request, $response);
241
242 static::assertSame(200, $result->getStatusCode());
243 static::assertSame('editlink', (string) $result->getBody());
244 static::assertSame('', $assignedVariables['link']['url']);
245 static::assertSame('Note: ', $assignedVariables['link']['title']);
246 static::assertSame('', $assignedVariables['link']['description']);
247 static::assertSame('', $assignedVariables['link']['tags']);
248 static::assertFalse($assignedVariables['link']['private']);
249 static::assertTrue($assignedVariables['link_is_new']);
250 }
251
252 /**
253 * Test displaying bookmark create form
254 * URL not using HTTP protocol: do not try to retrieve the title
255 */
256 public function testDisplayCreateFormNotHttp(): void
257 {
258 $assignedVariables = [];
259 $this->assignTemplateVars($assignedVariables);
260
261 $url = 'magnet://kubuntu.torrent';
262 $request = $this->createMock(Request::class);
263 $request
264 ->method('getParam')
265 ->willReturnCallback(function (string $key) use ($url): ?string {
266 return $key === 'post' ? $url : null;
267 });
268 $response = new Response();
269
270 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
271 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
272
273 $result = $this->controller->displayCreateForm($request, $response);
274
275 static::assertSame(200, $result->getStatusCode());
276 static::assertSame('editlink', (string) $result->getBody());
277 static::assertSame($url, $assignedVariables['link']['url']);
278 static::assertTrue($assignedVariables['link_is_new']);
279 }
280
281 /**
282 * Test displaying bookmark create form
283 * When markdown formatter is enabled, the no markdown tag should be added to existing tags.
284 */
285 public function testDisplayCreateFormWithMarkdownEnabled(): void
286 {
287 $assignedVariables = [];
288 $this->assignTemplateVars($assignedVariables);
289
290 $this->container->conf = $this->createMock(ConfigManager::class);
291 $this->container->conf
292 ->expects(static::atLeastOnce())
293 ->method('get')->willReturnCallback(function (string $key): ?string {
294 if ($key === 'formatter') {
295 return 'markdown';
296 }
297
298 return $key;
299 })
300 ;
301
302 $request = $this->createMock(Request::class);
303 $response = new Response();
304
305 $result = $this->controller->displayCreateForm($request, $response);
306
307 static::assertSame(200, $result->getStatusCode());
308 static::assertSame('editlink', (string) $result->getBody());
309 static::assertSame(['nomarkdown' => 1], $assignedVariables['tags']);
310 }
311
312 /**
313 * Test displaying bookmark create form
314 * When an existing URL is submitted, we want to edit the existing link.
315 */
316 public function testDisplayCreateFormWithExistingUrl(): void
317 {
318 $assignedVariables = [];
319 $this->assignTemplateVars($assignedVariables);
320
321 $url = 'http://url.tld/other?part=3&utm_ad=pay#hash';
322 $expectedUrl = str_replace('&utm_ad=pay', '', $url);
323
324 $request = $this->createMock(Request::class);
325 $request
326 ->method('getParam')
327 ->willReturnCallback(function (string $key) use ($url): ?string {
328 return $key === 'post' ? $url : null;
329 });
330 $response = new Response();
331
332 $this->container->httpAccess->expects(static::never())->method('getHttpResponse');
333 $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback');
334
335 $this->container->bookmarkService
336 ->expects(static::once())
337 ->method('findByUrl')
338 ->with($expectedUrl)
339 ->willReturn(
340 (new Bookmark())
341 ->setId($id = 23)
342 ->setUrl($expectedUrl)
343 ->setTitle($title = 'Bookmark Title')
344 ->setDescription($description = 'Bookmark description.')
345 ->setTags($tags = ['abc', 'def'])
346 ->setPrivate(true)
347 ->setCreated($createdAt = new \DateTime('2020-06-10 18:45:44'))
348 )
349 ;
350
351 $result = $this->controller->displayCreateForm($request, $response);
352
353 static::assertSame(200, $result->getStatusCode());
354 static::assertSame('editlink', (string) $result->getBody());
355
356 static::assertSame('Edit Shaare - Shaarli', $assignedVariables['pagetitle']);
357 static::assertFalse($assignedVariables['link_is_new']);
358
359 static::assertSame($id, $assignedVariables['link']['id']);
360 static::assertSame($expectedUrl, $assignedVariables['link']['url']);
361 static::assertSame($title, $assignedVariables['link']['title']);
362 static::assertSame($description, $assignedVariables['link']['description']);
363 static::assertSame(implode(' ', $tags), $assignedVariables['link']['tags']);
364 static::assertTrue($assignedVariables['link']['private']);
365 static::assertSame($createdAt, $assignedVariables['link']['created']);
366 }
367}
diff --git a/tests/front/controller/admin/ShaarePublishControllerTest/DisplayEditFormTest.php b/tests/front/controller/admin/ShaarePublishControllerTest/DisplayEditFormTest.php
new file mode 100644
index 00000000..da393e49
--- /dev/null
+++ b/tests/front/controller/admin/ShaarePublishControllerTest/DisplayEditFormTest.php
@@ -0,0 +1,155 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ShaarePublishControllerTest;
6
7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
9use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
10use Shaarli\Front\Controller\Admin\ShaarePublishController;
11use Shaarli\Http\HttpAccess;
12use Shaarli\Security\SessionManager;
13use Shaarli\TestCase;
14use Slim\Http\Request;
15use Slim\Http\Response;
16
17class DisplayEditFormTest extends TestCase
18{
19 use FrontAdminControllerMockHelper;
20
21 /** @var ShaarePublishController */
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 ShaarePublishController($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/ShaarePublishControllerTest/SaveBookmarkTest.php b/tests/front/controller/admin/ShaarePublishControllerTest/SaveBookmarkTest.php
new file mode 100644
index 00000000..b6a861bc
--- /dev/null
+++ b/tests/front/controller/admin/ShaarePublishControllerTest/SaveBookmarkTest.php
@@ -0,0 +1,369 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin\ShaarePublishControllerTest;
6
7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Config\ConfigManager;
9use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper;
10use Shaarli\Front\Controller\Admin\ShaarePublishController;
11use Shaarli\Front\Exception\WrongTokenException;
12use Shaarli\Http\HttpAccess;
13use Shaarli\Security\SessionManager;
14use Shaarli\TestCase;
15use Shaarli\Thumbnailer;
16use Slim\Http\Request;
17use Slim\Http\Response;
18
19class SaveBookmarkTest extends TestCase
20{
21 use FrontAdminControllerMockHelper;
22
23 /** @var ShaarePublishController */
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 ShaarePublishController($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/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): Bookmark {
70 static::assertFalse($save);
71
72 $checkBookmark($bookmark);
73
74 $bookmark->setId($id);
75
76 return $bookmark;
77 })
78 ;
79 $this->container->bookmarkService
80 ->expects(static::once())
81 ->method('set')
82 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark {
83 static::assertTrue($save);
84
85 $checkBookmark($bookmark);
86
87 static::assertSame($id, $bookmark->getId());
88
89 return $bookmark;
90 })
91 ;
92
93 // Make sure that PluginManager hook is triggered
94 $this->container->pluginManager
95 ->expects(static::atLeastOnce())
96 ->method('executeHooks')
97 ->withConsecutive(['save_link'])
98 ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array {
99 if ('save_link' === $hook) {
100 static::assertSame($id, $data['id']);
101 static::assertSame($parameters['lf_url'], $data['url']);
102 static::assertSame($parameters['lf_title'], $data['title']);
103 static::assertSame($parameters['lf_description'], $data['description']);
104 static::assertSame($parameters['lf_tags'], $data['tags']);
105 static::assertTrue($data['private']);
106 }
107
108 return $data;
109 })
110 ;
111
112 $result = $this->controller->save($request, $response);
113
114 static::assertSame(302, $result->getStatusCode());
115 static::assertRegExp('@/subfolder/#[\w\-]{6}@', $result->getHeader('location')[0]);
116 }
117
118
119 /**
120 * Test save an existing bookmark
121 */
122 public function testSaveExistingBookmark(): void
123 {
124 $id = 21;
125 $parameters = [
126 'lf_id' => (string) $id,
127 'lf_url' => 'http://url.tld/other?part=3#hash',
128 'lf_title' => 'Provided Title',
129 'lf_description' => 'Provided description.',
130 'lf_tags' => 'abc def',
131 'lf_private' => '1',
132 'returnurl' => 'http://shaarli/subfolder/?page=2'
133 ];
134
135 $request = $this->createMock(Request::class);
136 $request
137 ->method('getParam')
138 ->willReturnCallback(function (string $key) use ($parameters): ?string {
139 return $parameters[$key] ?? null;
140 })
141 ;
142 $response = new Response();
143
144 $checkBookmark = function (Bookmark $bookmark) use ($parameters, $id) {
145 static::assertSame($id, $bookmark->getId());
146 static::assertSame($parameters['lf_url'], $bookmark->getUrl());
147 static::assertSame($parameters['lf_title'], $bookmark->getTitle());
148 static::assertSame($parameters['lf_description'], $bookmark->getDescription());
149 static::assertSame($parameters['lf_tags'], $bookmark->getTagsString());
150 static::assertTrue($bookmark->isPrivate());
151 };
152
153 $this->container->bookmarkService->expects(static::atLeastOnce())->method('exists')->willReturn(true);
154 $this->container->bookmarkService
155 ->expects(static::once())
156 ->method('get')
157 ->willReturn((new Bookmark())->setId($id)->setUrl('http://other.url'))
158 ;
159 $this->container->bookmarkService
160 ->expects(static::once())
161 ->method('addOrSet')
162 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark {
163 static::assertFalse($save);
164
165 $checkBookmark($bookmark);
166
167 return $bookmark;
168 })
169 ;
170 $this->container->bookmarkService
171 ->expects(static::once())
172 ->method('set')
173 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark {
174 static::assertTrue($save);
175
176 $checkBookmark($bookmark);
177
178 static::assertSame($id, $bookmark->getId());
179
180 return $bookmark;
181 })
182 ;
183
184 // Make sure that PluginManager hook is triggered
185 $this->container->pluginManager
186 ->expects(static::atLeastOnce())
187 ->method('executeHooks')
188 ->withConsecutive(['save_link'])
189 ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array {
190 if ('save_link' === $hook) {
191 static::assertSame($id, $data['id']);
192 static::assertSame($parameters['lf_url'], $data['url']);
193 static::assertSame($parameters['lf_title'], $data['title']);
194 static::assertSame($parameters['lf_description'], $data['description']);
195 static::assertSame($parameters['lf_tags'], $data['tags']);
196 static::assertTrue($data['private']);
197 }
198
199 return $data;
200 })
201 ;
202
203 $result = $this->controller->save($request, $response);
204
205 static::assertSame(302, $result->getStatusCode());
206 static::assertRegExp('@/subfolder/\?page=2#[\w\-]{6}@', $result->getHeader('location')[0]);
207 }
208
209 /**
210 * Test save a bookmark - try to retrieve the thumbnail
211 */
212 public function testSaveBookmarkWithThumbnailSync(): void
213 {
214 $parameters = ['lf_url' => 'http://url.tld/other?part=3#hash'];
215
216 $request = $this->createMock(Request::class);
217 $request
218 ->method('getParam')
219 ->willReturnCallback(function (string $key) use ($parameters): ?string {
220 return $parameters[$key] ?? null;
221 })
222 ;
223 $response = new Response();
224
225 $this->container->conf = $this->createMock(ConfigManager::class);
226 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
227 if ($key === 'thumbnails.mode') {
228 return Thumbnailer::MODE_ALL;
229 } elseif ($key === 'general.enable_async_metadata') {
230 return false;
231 }
232
233 return $default;
234 });
235
236 $this->container->thumbnailer = $this->createMock(Thumbnailer::class);
237 $this->container->thumbnailer
238 ->expects(static::once())
239 ->method('get')
240 ->with($parameters['lf_url'])
241 ->willReturn($thumb = 'http://thumb.url')
242 ;
243
244 $this->container->bookmarkService
245 ->expects(static::once())
246 ->method('addOrSet')
247 ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($thumb): Bookmark {
248 static::assertSame($thumb, $bookmark->getThumbnail());
249
250 return $bookmark;
251 })
252 ;
253
254 $result = $this->controller->save($request, $response);
255
256 static::assertSame(302, $result->getStatusCode());
257 }
258
259 /**
260 * Test save a bookmark - with ID #0
261 */
262 public function testSaveBookmarkWithIdZero(): void
263 {
264 $parameters = ['lf_id' => '0'];
265
266 $request = $this->createMock(Request::class);
267 $request
268 ->method('getParam')
269 ->willReturnCallback(function (string $key) use ($parameters): ?string {
270 return $parameters[$key] ?? null;
271 })
272 ;
273 $response = new Response();
274
275 $this->container->bookmarkService->expects(static::once())->method('exists')->with(0)->willReturn(true);
276 $this->container->bookmarkService->expects(static::once())->method('get')->with(0)->willReturn(new Bookmark());
277
278 $result = $this->controller->save($request, $response);
279
280 static::assertSame(302, $result->getStatusCode());
281 }
282
283 /**
284 * Test save a bookmark - do not attempt to retrieve thumbnails if async mode is enabled.
285 */
286 public function testSaveBookmarkWithThumbnailAsync(): void
287 {
288 $parameters = ['lf_url' => 'http://url.tld/other?part=3#hash'];
289
290 $request = $this->createMock(Request::class);
291 $request
292 ->method('getParam')
293 ->willReturnCallback(function (string $key) use ($parameters): ?string {
294 return $parameters[$key] ?? null;
295 })
296 ;
297 $response = new Response();
298
299 $this->container->conf = $this->createMock(ConfigManager::class);
300 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
301 if ($key === 'thumbnails.mode') {
302 return Thumbnailer::MODE_ALL;
303 } elseif ($key === 'general.enable_async_metadata') {
304 return true;
305 }
306
307 return $default;
308 });
309
310 $this->container->thumbnailer = $this->createMock(Thumbnailer::class);
311 $this->container->thumbnailer->expects(static::never())->method('get');
312
313 $this->container->bookmarkService
314 ->expects(static::once())
315 ->method('addOrSet')
316 ->willReturnCallback(function (Bookmark $bookmark): Bookmark {
317 static::assertNull($bookmark->getThumbnail());
318
319 return $bookmark;
320 })
321 ;
322
323 $result = $this->controller->save($request, $response);
324
325 static::assertSame(302, $result->getStatusCode());
326 }
327
328 /**
329 * Change the password with a wrong existing password
330 */
331 public function testSaveBookmarkFromBookmarklet(): void
332 {
333 $parameters = ['source' => 'bookmarklet'];
334
335 $request = $this->createMock(Request::class);
336 $request
337 ->method('getParam')
338 ->willReturnCallback(function (string $key) use ($parameters): ?string {
339 return $parameters[$key] ?? null;
340 })
341 ;
342 $response = new Response();
343
344 $result = $this->controller->save($request, $response);
345
346 static::assertSame(200, $result->getStatusCode());
347 static::assertSame('<script>self.close();</script>', (string) $result->getBody());
348 }
349
350 /**
351 * Change the password with a wrong existing password
352 */
353 public function testSaveBookmarkWrongToken(): void
354 {
355 $this->container->sessionManager = $this->createMock(SessionManager::class);
356 $this->container->sessionManager->method('checkToken')->willReturn(false);
357
358 $this->container->bookmarkService->expects(static::never())->method('addOrSet');
359 $this->container->bookmarkService->expects(static::never())->method('set');
360
361 $request = $this->createMock(Request::class);
362 $response = new Response();
363
364 $this->expectException(WrongTokenException::class);
365
366 $this->controller->save($request, $response);
367 }
368
369}
diff --git a/tests/front/controller/admin/ShaarliAdminControllerTest.php b/tests/front/controller/admin/ShaarliAdminControllerTest.php
new file mode 100644
index 00000000..486d5d2d
--- /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 Shaarli\Front\Exception\WrongTokenException;
8use Shaarli\Security\SessionManager;
9use Shaarli\TestCase;
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..e5749654
--- /dev/null
+++ b/tests/front/controller/admin/ThumbnailsControllerTest.php
@@ -0,0 +1,156 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Front\Controller\Admin;
6
7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
9use Shaarli\TestCase;
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): Bookmark {
93 static::assertSame($thumb, $bookmark->getThumbnail());
94
95 return $bookmark;
96 })
97 ;
98
99 $result = $this->controller->ajaxUpdate($request, $response, ['id' => (string) $id]);
100
101 static::assertSame(200, $result->getStatusCode());
102
103 $payload = json_decode((string) $result->getBody(), true);
104
105 static::assertSame($id, $payload['id']);
106 static::assertSame($url, $payload['url']);
107 static::assertSame($thumb, $payload['thumbnail']);
108 }
109
110 /**
111 * Test updating a bookmark thumbnail - Invalid ID
112 */
113 public function testAjaxUpdateInvalidId(): void
114 {
115 $request = $this->createMock(Request::class);
116 $response = new Response();
117
118 $result = $this->controller->ajaxUpdate($request, $response, ['id' => 'nope']);
119
120 static::assertSame(400, $result->getStatusCode());
121 }
122
123 /**
124 * Test updating a bookmark thumbnail - No ID
125 */
126 public function testAjaxUpdateNoId(): void
127 {
128 $request = $this->createMock(Request::class);
129 $response = new Response();
130
131 $result = $this->controller->ajaxUpdate($request, $response, []);
132
133 static::assertSame(400, $result->getStatusCode());
134 }
135
136 /**
137 * Test updating a bookmark thumbnail with valid parameters
138 */
139 public function testAjaxUpdateBookmarkNotFound(): void
140 {
141 $id = 123;
142 $request = $this->createMock(Request::class);
143 $response = new Response();
144
145 $this->container->bookmarkService
146 ->expects(static::once())
147 ->method('get')
148 ->with($id)
149 ->willThrowException(new BookmarkNotFoundException())
150 ;
151
152 $result = $this->controller->ajaxUpdate($request, $response, ['id' => (string) $id]);
153
154 static::assertSame(404, $result->getStatusCode());
155 }
156}
diff --git a/tests/front/controller/admin/TokenControllerTest.php b/tests/front/controller/admin/TokenControllerTest.php
new file mode 100644
index 00000000..d2f0907f
--- /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 Shaarli\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..e82f8b14
--- /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 Shaarli\TestCase;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11class ToolsControllerTest 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}