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