From 5d8de7587d67b5c3e5d1fed8562d9b87ecde80c1 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 10 Oct 2020 17:40:26 +0200 Subject: Feature: bulk creation of bookmarks This changes creates a new form in addlink page allowing to create multiple bookmarks at once more easily. It focuses on re-using as much existing code and template component as possible. These changes includes: - a new form in addlink (hidden behind a button by default), containing a text area for URL, and tags/private status to apply to created links - this form displays a new template called editlink.batch, itself including editlink template multiple times - User interation in this new templates are handle by a new JS script (shaare-batch.js) making AJAX requests, and therefore does not need page reloading - ManageShaareController has been split into 3 distinct controllers: + ShaareAdd: displays addlink template + ShaareManage: various operation applied on existing shaares (change visibility, pin, deletion, etc.) + ShaarePublish: handles creation/edit forms and saving Shaare's form - Updated translations Fixes #137 --- .../ManageShaareControllerTest/AddShaareTest.php | 47 --- .../ChangeVisibilityBookmarkTest.php | 418 --------------------- .../DeleteBookmarkTest.php | 380 ------------------- .../DisplayCreateFormTest.php | 367 ------------------ .../DisplayEditFormTest.php | 155 -------- .../ManageShaareControllerTest/PinBookmarkTest.php | 145 ------- .../SaveBookmarkTest.php | 369 ------------------ .../SharePrivateTest.php | 139 ------- .../controller/admin/ShaareAddControllerTest.php | 97 +++++ .../ChangeVisibilityBookmarkTest.php | 418 +++++++++++++++++++++ .../DeleteBookmarkTest.php | 380 +++++++++++++++++++ .../ShaareManageControllerTest/PinBookmarkTest.php | 145 +++++++ .../SharePrivateTest.php | 139 +++++++ .../DisplayCreateBatchFormTest.php | 62 +++ .../DisplayCreateFormTest.php | 367 ++++++++++++++++++ .../DisplayEditFormTest.php | 155 ++++++++ .../SaveBookmarkTest.php | 369 ++++++++++++++++++ 17 files changed, 2132 insertions(+), 2020 deletions(-) delete mode 100644 tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php delete mode 100644 tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php delete mode 100644 tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php delete mode 100644 tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php delete mode 100644 tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php delete mode 100644 tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php delete mode 100644 tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php delete mode 100644 tests/front/controller/admin/ManageShaareControllerTest/SharePrivateTest.php create mode 100644 tests/front/controller/admin/ShaareAddControllerTest.php create mode 100644 tests/front/controller/admin/ShaareManageControllerTest/ChangeVisibilityBookmarkTest.php create mode 100644 tests/front/controller/admin/ShaareManageControllerTest/DeleteBookmarkTest.php create mode 100644 tests/front/controller/admin/ShaareManageControllerTest/PinBookmarkTest.php create mode 100644 tests/front/controller/admin/ShaareManageControllerTest/SharePrivateTest.php create mode 100644 tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateBatchFormTest.php create mode 100644 tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateFormTest.php create mode 100644 tests/front/controller/admin/ShaarePublishControllerTest/DisplayEditFormTest.php create mode 100644 tests/front/controller/admin/ShaarePublishControllerTest/SaveBookmarkTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php b/tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php deleted file mode 100644 index 0f27ec2f..00000000 --- a/tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php +++ /dev/null @@ -1,47 +0,0 @@ -createContainer(); - - $this->container->httpAccess = $this->createMock(HttpAccess::class); - $this->controller = new ManageShaareController($this->container); - } - - /** - * Test displaying add link page - */ - public function testAddShaare(): void - { - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->addShaare($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('addlink', (string) $result->getBody()); - - static::assertSame('Shaare a new link - Shaarli', $assignedVariables['pagetitle']); - } -} diff --git a/tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php deleted file mode 100644 index 096d0774..00000000 --- a/tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php +++ /dev/null @@ -1,418 +0,0 @@ -createContainer(); - - $this->container->httpAccess = $this->createMock(HttpAccess::class); - $this->controller = new ManageShaareController($this->container); - } - - /** - * Change bookmark visibility - Set private - Single public bookmark with valid parameters - */ - public function testSetSingleBookmarkPrivate(): void - { - $parameters = ['id' => '123', 'newVisibility' => 'private']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(false); - - static::assertFalse($bookmark->isPrivate()); - - $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); - $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, false); - $this->container->bookmarkService->expects(static::once())->method('save'); - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->with('raw') - ->willReturnCallback(function () use ($bookmark): BookmarkFormatter { - return new BookmarkRawFormatter($this->container->conf, true); - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::once()) - ->method('executeHooks') - ->with('save_link') - ; - - $result = $this->controller->changeVisibility($request, $response); - - static::assertTrue($bookmark->isPrivate()); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Change bookmark visibility - Set public - Single private bookmark with valid parameters - */ - public function testSetSingleBookmarkPublic(): void - { - $parameters = ['id' => '123', 'newVisibility' => 'public']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(true); - - static::assertTrue($bookmark->isPrivate()); - - $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); - $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, false); - $this->container->bookmarkService->expects(static::once())->method('save'); - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->with('raw') - ->willReturn(new BookmarkRawFormatter($this->container->conf, true)) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::once()) - ->method('executeHooks') - ->with('save_link') - ; - - $result = $this->controller->changeVisibility($request, $response); - - static::assertFalse($bookmark->isPrivate()); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Change bookmark visibility - Set private on single already private bookmark - */ - public function testSetSinglePrivateBookmarkPrivate(): void - { - $parameters = ['id' => '123', 'newVisibility' => 'private']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(true); - - static::assertTrue($bookmark->isPrivate()); - - $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); - $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, false); - $this->container->bookmarkService->expects(static::once())->method('save'); - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->with('raw') - ->willReturn(new BookmarkRawFormatter($this->container->conf, true)) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::once()) - ->method('executeHooks') - ->with('save_link') - ; - - $result = $this->controller->changeVisibility($request, $response); - - static::assertTrue($bookmark->isPrivate()); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Change bookmark visibility - Set multiple bookmarks private - */ - public function testSetMultipleBookmarksPrivate(): void - { - $parameters = ['id' => '123 456 789', 'newVisibility' => 'private']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $bookmarks = [ - (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(false), - (new Bookmark())->setId(456)->setUrl('http://domain.tld')->setTitle('Title 456')->setPrivate(true), - (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789')->setPrivate(false), - ]; - - $this->container->bookmarkService - ->expects(static::exactly(3)) - ->method('get') - ->withConsecutive([123], [456], [789]) - ->willReturnOnConsecutiveCalls(...$bookmarks) - ; - $this->container->bookmarkService - ->expects(static::exactly(3)) - ->method('set') - ->withConsecutive(...array_map(function (Bookmark $bookmark): array { - return [$bookmark, false]; - }, $bookmarks)) - ; - $this->container->bookmarkService->expects(static::once())->method('save'); - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->with('raw') - ->willReturn(new BookmarkRawFormatter($this->container->conf, true)) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::exactly(3)) - ->method('executeHooks') - ->with('save_link') - ; - - $result = $this->controller->changeVisibility($request, $response); - - static::assertTrue($bookmarks[0]->isPrivate()); - static::assertTrue($bookmarks[1]->isPrivate()); - static::assertTrue($bookmarks[2]->isPrivate()); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Change bookmark visibility - Single bookmark not found. - */ - public function testChangeVisibilitySingleBookmarkNotFound(): void - { - $parameters = ['id' => '123', 'newVisibility' => 'private']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('get') - ->willThrowException(new BookmarkNotFoundException()) - ; - $this->container->bookmarkService->expects(static::never())->method('set'); - $this->container->bookmarkService->expects(static::never())->method('save'); - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->with('raw') - ->willReturn(new BookmarkRawFormatter($this->container->conf, true)) - ; - - // Make sure that PluginManager hook is not triggered - $this->container->pluginManager - ->expects(static::never()) - ->method('executeHooks') - ->with('save_link') - ; - - $result = $this->controller->changeVisibility($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Change bookmark visibility - Multiple bookmarks with one not found. - */ - public function testChangeVisibilityMultipleBookmarksOneNotFound(): void - { - $parameters = ['id' => '123 456 789', 'newVisibility' => 'public']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $bookmarks = [ - (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(true), - (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789')->setPrivate(false), - ]; - - $this->container->bookmarkService - ->expects(static::exactly(3)) - ->method('get') - ->withConsecutive([123], [456], [789]) - ->willReturnCallback(function (int $id) use ($bookmarks): Bookmark { - if ($id === 123) { - return $bookmarks[0]; - } - if ($id === 789) { - return $bookmarks[1]; - } - throw new BookmarkNotFoundException(); - }) - ; - $this->container->bookmarkService - ->expects(static::exactly(2)) - ->method('set') - ->withConsecutive(...array_map(function (Bookmark $bookmark): array { - return [$bookmark, false]; - }, $bookmarks)) - ; - $this->container->bookmarkService->expects(static::once())->method('save'); - - // Make sure that PluginManager hook is not triggered - $this->container->pluginManager - ->expects(static::exactly(2)) - ->method('executeHooks') - ->with('save_link') - ; - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 456 could not be found.']) - ; - - $result = $this->controller->changeVisibility($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Change bookmark visibility - Invalid ID - */ - public function testChangeVisibilityInvalidId(): void - { - $parameters = ['id' => 'nope not an ID', 'newVisibility' => 'private']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.']) - ; - - $result = $this->controller->changeVisibility($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Change bookmark visibility - Empty ID - */ - public function testChangeVisibilityEmptyId(): void - { - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.']) - ; - - $result = $this->controller->changeVisibility($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Change bookmark visibility - with invalid visibility - */ - public function testChangeVisibilityWithInvalidVisibility(): void - { - $parameters = ['id' => '123', 'newVisibility' => 'invalid']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid visibility provided.']) - ; - - $result = $this->controller->changeVisibility($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } -} diff --git a/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php deleted file mode 100644 index 83bbee7c..00000000 --- a/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php +++ /dev/null @@ -1,380 +0,0 @@ -createContainer(); - - $this->container->httpAccess = $this->createMock(HttpAccess::class); - $this->controller = new ManageShaareController($this->container); - } - - /** - * Delete bookmark - Single bookmark with valid parameters - */ - public function testDeleteSingleBookmark(): void - { - $parameters = ['id' => '123']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123'); - - $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); - $this->container->bookmarkService->expects(static::once())->method('remove')->with($bookmark, false); - $this->container->bookmarkService->expects(static::once())->method('save'); - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->with('raw') - ->willReturnCallback(function () use ($bookmark): BookmarkFormatter { - $formatter = $this->createMock(BookmarkFormatter::class); - $formatter - ->expects(static::once()) - ->method('format') - ->with($bookmark) - ->willReturn(['formatted' => $bookmark]) - ; - - return $formatter; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::once()) - ->method('executeHooks') - ->with('delete_link', ['formatted' => $bookmark]) - ; - - $result = $this->controller->deleteBookmark($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Delete bookmark - Multiple bookmarks with valid parameters - */ - public function testDeleteMultipleBookmarks(): void - { - $parameters = ['id' => '123 456 789']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $bookmarks = [ - (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123'), - (new Bookmark())->setId(456)->setUrl('http://domain.tld')->setTitle('Title 456'), - (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789'), - ]; - - $this->container->bookmarkService - ->expects(static::exactly(3)) - ->method('get') - ->withConsecutive([123], [456], [789]) - ->willReturnOnConsecutiveCalls(...$bookmarks) - ; - $this->container->bookmarkService - ->expects(static::exactly(3)) - ->method('remove') - ->withConsecutive(...array_map(function (Bookmark $bookmark): array { - return [$bookmark, false]; - }, $bookmarks)) - ; - $this->container->bookmarkService->expects(static::once())->method('save'); - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->with('raw') - ->willReturnCallback(function () use ($bookmarks): BookmarkFormatter { - $formatter = $this->createMock(BookmarkFormatter::class); - - $formatter - ->expects(static::exactly(3)) - ->method('format') - ->withConsecutive(...array_map(function (Bookmark $bookmark): array { - return [$bookmark]; - }, $bookmarks)) - ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array { - return ['formatted' => $bookmark]; - }, $bookmarks)) - ; - - return $formatter; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::exactly(3)) - ->method('executeHooks') - ->with('delete_link') - ; - - $result = $this->controller->deleteBookmark($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Delete bookmark - Single bookmark not found in the data store - */ - public function testDeleteSingleBookmarkNotFound(): void - { - $parameters = ['id' => '123']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('get') - ->willThrowException(new BookmarkNotFoundException()) - ; - $this->container->bookmarkService->expects(static::never())->method('remove'); - $this->container->bookmarkService->expects(static::never())->method('save'); - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->with('raw') - ->willReturnCallback(function (): BookmarkFormatter { - $formatter = $this->createMock(BookmarkFormatter::class); - - $formatter->expects(static::never())->method('format'); - - return $formatter; - }) - ; - // Make sure that PluginManager hook is not triggered - $this->container->pluginManager - ->expects(static::never()) - ->method('executeHooks') - ->with('delete_link') - ; - - $result = $this->controller->deleteBookmark($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Delete bookmark - Multiple bookmarks with one not found in the data store - */ - public function testDeleteMultipleBookmarksOneNotFound(): void - { - $parameters = ['id' => '123 456 789']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $bookmarks = [ - (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123'), - (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789'), - ]; - - $this->container->bookmarkService - ->expects(static::exactly(3)) - ->method('get') - ->withConsecutive([123], [456], [789]) - ->willReturnCallback(function (int $id) use ($bookmarks): Bookmark { - if ($id === 123) { - return $bookmarks[0]; - } - if ($id === 789) { - return $bookmarks[1]; - } - throw new BookmarkNotFoundException(); - }) - ; - $this->container->bookmarkService - ->expects(static::exactly(2)) - ->method('remove') - ->withConsecutive(...array_map(function (Bookmark $bookmark): array { - return [$bookmark, false]; - }, $bookmarks)) - ; - $this->container->bookmarkService->expects(static::once())->method('save'); - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->with('raw') - ->willReturnCallback(function () use ($bookmarks): BookmarkFormatter { - $formatter = $this->createMock(BookmarkFormatter::class); - - $formatter - ->expects(static::exactly(2)) - ->method('format') - ->withConsecutive(...array_map(function (Bookmark $bookmark): array { - return [$bookmark]; - }, $bookmarks)) - ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array { - return ['formatted' => $bookmark]; - }, $bookmarks)) - ; - - return $formatter; - }) - ; - - // Make sure that PluginManager hook is not triggered - $this->container->pluginManager - ->expects(static::exactly(2)) - ->method('executeHooks') - ->with('delete_link') - ; - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 456 could not be found.']) - ; - - $result = $this->controller->deleteBookmark($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Delete bookmark - Invalid ID - */ - public function testDeleteInvalidId(): void - { - $parameters = ['id' => 'nope not an ID']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.']) - ; - - $result = $this->controller->deleteBookmark($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Delete bookmark - Empty ID - */ - public function testDeleteEmptyId(): void - { - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.']) - ; - - $result = $this->controller->deleteBookmark($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Delete bookmark - from bookmarklet - */ - public function testDeleteBookmarkFromBookmarklet(): void - { - $parameters = [ - 'id' => '123', - 'source' => 'bookmarklet', - ]; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $this->container->bookmarkService->method('get')->with('123')->willReturn( - (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123') - ); - - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->expects(static::once()) - ->method('getFormatter') - ->willReturnCallback(function (): BookmarkFormatter { - $formatter = $this->createMock(BookmarkFormatter::class); - $formatter->method('format')->willReturn(['formatted']); - - return $formatter; - }) - ; - - $result = $this->controller->deleteBookmark($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('', (string) $result->getBody('location')); - } -} diff --git a/tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php b/tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php deleted file mode 100644 index eafa54eb..00000000 --- a/tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php +++ /dev/null @@ -1,367 +0,0 @@ -createContainer(); - - $this->container->httpAccess = $this->createMock(HttpAccess::class); - $this->container->metadataRetriever = $this->createMock(MetadataRetriever::class); - $this->controller = new ManageShaareController($this->container); - } - - /** - * Test displaying bookmark create form - * Ensure that every step of the standard workflow works properly. - */ - public function testDisplayCreateFormWithUrlAndWithMetadataRetrieval(): void - { - $this->container->environment = [ - 'HTTP_REFERER' => $referer = 'http://shaarli/subfolder/controller/?searchtag=abc' - ]; - - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $url = 'http://url.tld/other?part=3&utm_ad=pay#hash'; - $expectedUrl = str_replace('&utm_ad=pay', '', $url); - $remoteTitle = 'Remote Title'; - $remoteDesc = 'Sometimes the meta description is relevant.'; - $remoteTags = 'abc def'; - - $request = $this->createMock(Request::class); - $request->method('getParam')->willReturnCallback(function (string $key) use ($url): ?string { - return $key === 'post' ? $url : null; - }); - $response = new Response(); - - $this->container->conf = $this->createMock(ConfigManager::class); - $this->container->conf->method('get')->willReturnCallback(function (string $param, $default) { - if ($param === 'general.enable_async_metadata') { - return false; - } - - return $default; - }); - - $this->container->metadataRetriever->expects(static::once())->method('retrieve')->willReturn([ - 'title' => $remoteTitle, - 'description' => $remoteDesc, - 'tags' => $remoteTags, - ]); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('bookmarksCountPerTag') - ->willReturn($tags = ['tag1' => 2, 'tag2' => 1]) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::atLeastOnce()) - ->method('executeHooks') - ->withConsecutive(['render_editlink'], ['render_includes']) - ->willReturnCallback(function (string $hook, array $data) use ($remoteTitle, $remoteDesc): array { - if ('render_editlink' === $hook) { - static::assertSame($remoteTitle, $data['link']['title']); - static::assertSame($remoteDesc, $data['link']['description']); - } - - return $data; - }) - ; - - $result = $this->controller->displayCreateForm($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('editlink', (string) $result->getBody()); - - static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']); - - static::assertSame($expectedUrl, $assignedVariables['link']['url']); - static::assertSame($remoteTitle, $assignedVariables['link']['title']); - static::assertSame($remoteDesc, $assignedVariables['link']['description']); - static::assertSame($remoteTags, $assignedVariables['link']['tags']); - static::assertFalse($assignedVariables['link']['private']); - - static::assertTrue($assignedVariables['link_is_new']); - static::assertSame($referer, $assignedVariables['http_referer']); - static::assertSame($tags, $assignedVariables['tags']); - static::assertArrayHasKey('source', $assignedVariables); - static::assertArrayHasKey('default_private_links', $assignedVariables); - static::assertArrayHasKey('async_metadata', $assignedVariables); - static::assertArrayHasKey('retrieve_description', $assignedVariables); - } - - /** - * Test displaying bookmark create form without any external metadata retrieval attempt - */ - public function testDisplayCreateFormWithUrlAndWithoutMetadata(): void - { - $this->container->environment = [ - 'HTTP_REFERER' => $referer = 'http://shaarli/subfolder/controller/?searchtag=abc' - ]; - - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $url = 'http://url.tld/other?part=3&utm_ad=pay#hash'; - $expectedUrl = str_replace('&utm_ad=pay', '', $url); - - $request = $this->createMock(Request::class); - $request->method('getParam')->willReturnCallback(function (string $key) use ($url): ?string { - return $key === 'post' ? $url : null; - }); - $response = new Response(); - - $this->container->metadataRetriever->expects(static::never())->method('retrieve'); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('bookmarksCountPerTag') - ->willReturn($tags = ['tag1' => 2, 'tag2' => 1]) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::atLeastOnce()) - ->method('executeHooks') - ->withConsecutive(['render_editlink'], ['render_includes']) - ->willReturnCallback(function (string $hook, array $data): array { - if ('render_editlink' === $hook) { - static::assertSame('', $data['link']['title']); - static::assertSame('', $data['link']['description']); - } - - return $data; - }) - ; - - $result = $this->controller->displayCreateForm($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('editlink', (string) $result->getBody()); - - static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']); - - static::assertSame($expectedUrl, $assignedVariables['link']['url']); - static::assertSame('', $assignedVariables['link']['title']); - static::assertSame('', $assignedVariables['link']['description']); - static::assertSame('', $assignedVariables['link']['tags']); - static::assertFalse($assignedVariables['link']['private']); - - static::assertTrue($assignedVariables['link_is_new']); - static::assertSame($referer, $assignedVariables['http_referer']); - static::assertSame($tags, $assignedVariables['tags']); - static::assertArrayHasKey('source', $assignedVariables); - static::assertArrayHasKey('default_private_links', $assignedVariables); - static::assertArrayHasKey('async_metadata', $assignedVariables); - static::assertArrayHasKey('retrieve_description', $assignedVariables); - } - - /** - * Test displaying bookmark create form - * Ensure all available query parameters are handled properly. - */ - public function testDisplayCreateFormWithFullParameters(): void - { - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $parameters = [ - 'post' => 'http://url.tld/other?part=3&utm_ad=pay#hash', - 'title' => 'Provided Title', - 'description' => 'Provided description.', - 'tags' => 'abc def', - 'private' => '1', - 'source' => 'apps', - ]; - $expectedUrl = str_replace('&utm_ad=pay', '', $parameters['post']); - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }); - $response = new Response(); - - $result = $this->controller->displayCreateForm($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('editlink', (string) $result->getBody()); - - static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']); - - static::assertSame($expectedUrl, $assignedVariables['link']['url']); - static::assertSame($parameters['title'], $assignedVariables['link']['title']); - static::assertSame($parameters['description'], $assignedVariables['link']['description']); - static::assertSame($parameters['tags'], $assignedVariables['link']['tags']); - static::assertTrue($assignedVariables['link']['private']); - static::assertTrue($assignedVariables['link_is_new']); - static::assertSame($parameters['source'], $assignedVariables['source']); - } - - /** - * Test displaying bookmark create form - * Without any parameter. - */ - public function testDisplayCreateFormEmpty(): void - { - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->httpAccess->expects(static::never())->method('getHttpResponse'); - $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback'); - - $result = $this->controller->displayCreateForm($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('editlink', (string) $result->getBody()); - static::assertSame('', $assignedVariables['link']['url']); - static::assertSame('Note: ', $assignedVariables['link']['title']); - static::assertSame('', $assignedVariables['link']['description']); - static::assertSame('', $assignedVariables['link']['tags']); - static::assertFalse($assignedVariables['link']['private']); - static::assertTrue($assignedVariables['link_is_new']); - } - - /** - * Test displaying bookmark create form - * URL not using HTTP protocol: do not try to retrieve the title - */ - public function testDisplayCreateFormNotHttp(): void - { - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $url = 'magnet://kubuntu.torrent'; - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($url): ?string { - return $key === 'post' ? $url : null; - }); - $response = new Response(); - - $this->container->httpAccess->expects(static::never())->method('getHttpResponse'); - $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback'); - - $result = $this->controller->displayCreateForm($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('editlink', (string) $result->getBody()); - static::assertSame($url, $assignedVariables['link']['url']); - static::assertTrue($assignedVariables['link_is_new']); - } - - /** - * Test displaying bookmark create form - * When markdown formatter is enabled, the no markdown tag should be added to existing tags. - */ - public function testDisplayCreateFormWithMarkdownEnabled(): void - { - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->conf = $this->createMock(ConfigManager::class); - $this->container->conf - ->expects(static::atLeastOnce()) - ->method('get')->willReturnCallback(function (string $key): ?string { - if ($key === 'formatter') { - return 'markdown'; - } - - return $key; - }) - ; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->displayCreateForm($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('editlink', (string) $result->getBody()); - static::assertSame(['nomarkdown' => 1], $assignedVariables['tags']); - } - - /** - * Test displaying bookmark create form - * When an existing URL is submitted, we want to edit the existing link. - */ - public function testDisplayCreateFormWithExistingUrl(): void - { - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $url = 'http://url.tld/other?part=3&utm_ad=pay#hash'; - $expectedUrl = str_replace('&utm_ad=pay', '', $url); - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($url): ?string { - return $key === 'post' ? $url : null; - }); - $response = new Response(); - - $this->container->httpAccess->expects(static::never())->method('getHttpResponse'); - $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback'); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('findByUrl') - ->with($expectedUrl) - ->willReturn( - (new Bookmark()) - ->setId($id = 23) - ->setUrl($expectedUrl) - ->setTitle($title = 'Bookmark Title') - ->setDescription($description = 'Bookmark description.') - ->setTags($tags = ['abc', 'def']) - ->setPrivate(true) - ->setCreated($createdAt = new \DateTime('2020-06-10 18:45:44')) - ) - ; - - $result = $this->controller->displayCreateForm($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('editlink', (string) $result->getBody()); - - static::assertSame('Edit Shaare - Shaarli', $assignedVariables['pagetitle']); - static::assertFalse($assignedVariables['link_is_new']); - - static::assertSame($id, $assignedVariables['link']['id']); - static::assertSame($expectedUrl, $assignedVariables['link']['url']); - static::assertSame($title, $assignedVariables['link']['title']); - static::assertSame($description, $assignedVariables['link']['description']); - static::assertSame(implode(' ', $tags), $assignedVariables['link']['tags']); - static::assertTrue($assignedVariables['link']['private']); - static::assertSame($createdAt, $assignedVariables['link']['created']); - } -} diff --git a/tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php b/tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php deleted file mode 100644 index 2dc3f41c..00000000 --- a/tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php +++ /dev/null @@ -1,155 +0,0 @@ -createContainer(); - - $this->container->httpAccess = $this->createMock(HttpAccess::class); - $this->controller = new ManageShaareController($this->container); - } - - /** - * Test displaying bookmark edit form - * When an existing ID is provided, ensure that default workflow works properly. - */ - public function testDisplayEditFormDefault(): void - { - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $id = 11; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->httpAccess->expects(static::never())->method('getHttpResponse'); - $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback'); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('get') - ->with($id) - ->willReturn( - (new Bookmark()) - ->setId($id) - ->setUrl($url = 'http://domain.tld') - ->setTitle($title = 'Bookmark Title') - ->setDescription($description = 'Bookmark description.') - ->setTags($tags = ['abc', 'def']) - ->setPrivate(true) - ->setCreated($createdAt = new \DateTime('2020-06-10 18:45:44')) - ) - ; - - $result = $this->controller->displayEditForm($request, $response, ['id' => (string) $id]); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('editlink', (string) $result->getBody()); - - static::assertSame('Edit Shaare - Shaarli', $assignedVariables['pagetitle']); - static::assertFalse($assignedVariables['link_is_new']); - - static::assertSame($id, $assignedVariables['link']['id']); - static::assertSame($url, $assignedVariables['link']['url']); - static::assertSame($title, $assignedVariables['link']['title']); - static::assertSame($description, $assignedVariables['link']['description']); - static::assertSame(implode(' ', $tags), $assignedVariables['link']['tags']); - static::assertTrue($assignedVariables['link']['private']); - static::assertSame($createdAt, $assignedVariables['link']['created']); - } - - /** - * Test displaying bookmark edit form - * Invalid ID provided. - */ - public function testDisplayEditFormInvalidId(): void - { - $id = 'invalid'; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier invalid could not be found.']) - ; - - $result = $this->controller->displayEditForm($request, $response, ['id' => $id]); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Test displaying bookmark edit form - * ID not provided. - */ - public function testDisplayEditFormIdNotProvided(): void - { - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier could not be found.']) - ; - - $result = $this->controller->displayEditForm($request, $response, []); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Test displaying bookmark edit form - * Bookmark not found. - */ - public function testDisplayEditFormBookmarkNotFound(): void - { - $id = 123; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('get') - ->with($id) - ->willThrowException(new BookmarkNotFoundException()) - ; - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 123 could not be found.']) - ; - - $result = $this->controller->displayEditForm($request, $response, ['id' => (string) $id]); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } -} diff --git a/tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php deleted file mode 100644 index 50ce7df1..00000000 --- a/tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php +++ /dev/null @@ -1,145 +0,0 @@ -createContainer(); - - $this->container->httpAccess = $this->createMock(HttpAccess::class); - $this->controller = new ManageShaareController($this->container); - } - - /** - * Test pin bookmark - with valid input - * - * @dataProvider initialStickyValuesProvider() - */ - public function testPinBookmarkIsStickyNull(?bool $sticky, bool $expectedValue): void - { - $id = 123; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $bookmark = (new Bookmark()) - ->setId(123) - ->setUrl('http://domain.tld') - ->setTitle('Title 123') - ->setSticky($sticky) - ; - - $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); - $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, true); - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::once()) - ->method('executeHooks') - ->with('save_link') - ; - - $result = $this->controller->pinBookmark($request, $response, ['id' => (string) $id]); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - - static::assertSame($expectedValue, $bookmark->isSticky()); - } - - public function initialStickyValuesProvider(): array - { - // [initialStickyState, isStickyAfterPin] - return [[null, true], [false, true], [true, false]]; - } - - /** - * Test pin bookmark - invalid bookmark ID - */ - public function testDisplayEditFormInvalidId(): void - { - $id = 'invalid'; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier invalid could not be found.']) - ; - - $result = $this->controller->pinBookmark($request, $response, ['id' => $id]); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Test pin bookmark - Bookmark ID not provided - */ - public function testDisplayEditFormIdNotProvided(): void - { - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier could not be found.']) - ; - - $result = $this->controller->pinBookmark($request, $response, []); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } - - /** - * Test pin bookmark - bookmark not found - */ - public function testDisplayEditFormBookmarkNotFound(): void - { - $id = 123; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('get') - ->with($id) - ->willThrowException(new BookmarkNotFoundException()) - ; - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 123 could not be found.']) - ; - - $result = $this->controller->pinBookmark($request, $response, ['id' => (string) $id]); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/'], $result->getHeader('location')); - } -} diff --git a/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php deleted file mode 100644 index 1adeef5a..00000000 --- a/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php +++ /dev/null @@ -1,369 +0,0 @@ -createContainer(); - - $this->container->httpAccess = $this->createMock(HttpAccess::class); - $this->controller = new ManageShaareController($this->container); - } - - /** - * Test save a new bookmark - */ - public function testSaveBookmark(): void - { - $id = 21; - $parameters = [ - 'lf_url' => 'http://url.tld/other?part=3#hash', - 'lf_title' => 'Provided Title', - 'lf_description' => 'Provided description.', - 'lf_tags' => 'abc def', - 'lf_private' => '1', - 'returnurl' => 'http://shaarli/subfolder/admin/add-shaare' - ]; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $checkBookmark = function (Bookmark $bookmark) use ($parameters) { - static::assertSame($parameters['lf_url'], $bookmark->getUrl()); - static::assertSame($parameters['lf_title'], $bookmark->getTitle()); - static::assertSame($parameters['lf_description'], $bookmark->getDescription()); - static::assertSame($parameters['lf_tags'], $bookmark->getTagsString()); - static::assertTrue($bookmark->isPrivate()); - }; - - $this->container->bookmarkService - ->expects(static::once()) - ->method('addOrSet') - ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark { - static::assertFalse($save); - - $checkBookmark($bookmark); - - $bookmark->setId($id); - - return $bookmark; - }) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('set') - ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark { - static::assertTrue($save); - - $checkBookmark($bookmark); - - static::assertSame($id, $bookmark->getId()); - - return $bookmark; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::atLeastOnce()) - ->method('executeHooks') - ->withConsecutive(['save_link']) - ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { - if ('save_link' === $hook) { - static::assertSame($id, $data['id']); - static::assertSame($parameters['lf_url'], $data['url']); - static::assertSame($parameters['lf_title'], $data['title']); - static::assertSame($parameters['lf_description'], $data['description']); - static::assertSame($parameters['lf_tags'], $data['tags']); - static::assertTrue($data['private']); - } - - return $data; - }) - ; - - $result = $this->controller->save($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertRegExp('@/subfolder/#[\w\-]{6}@', $result->getHeader('location')[0]); - } - - - /** - * Test save an existing bookmark - */ - public function testSaveExistingBookmark(): void - { - $id = 21; - $parameters = [ - 'lf_id' => (string) $id, - 'lf_url' => 'http://url.tld/other?part=3#hash', - 'lf_title' => 'Provided Title', - 'lf_description' => 'Provided description.', - 'lf_tags' => 'abc def', - 'lf_private' => '1', - 'returnurl' => 'http://shaarli/subfolder/?page=2' - ]; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $checkBookmark = function (Bookmark $bookmark) use ($parameters, $id) { - static::assertSame($id, $bookmark->getId()); - static::assertSame($parameters['lf_url'], $bookmark->getUrl()); - static::assertSame($parameters['lf_title'], $bookmark->getTitle()); - static::assertSame($parameters['lf_description'], $bookmark->getDescription()); - static::assertSame($parameters['lf_tags'], $bookmark->getTagsString()); - static::assertTrue($bookmark->isPrivate()); - }; - - $this->container->bookmarkService->expects(static::atLeastOnce())->method('exists')->willReturn(true); - $this->container->bookmarkService - ->expects(static::once()) - ->method('get') - ->willReturn((new Bookmark())->setId($id)->setUrl('http://other.url')) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('addOrSet') - ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark { - static::assertFalse($save); - - $checkBookmark($bookmark); - - return $bookmark; - }) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('set') - ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark { - static::assertTrue($save); - - $checkBookmark($bookmark); - - static::assertSame($id, $bookmark->getId()); - - return $bookmark; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::atLeastOnce()) - ->method('executeHooks') - ->withConsecutive(['save_link']) - ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { - if ('save_link' === $hook) { - static::assertSame($id, $data['id']); - static::assertSame($parameters['lf_url'], $data['url']); - static::assertSame($parameters['lf_title'], $data['title']); - static::assertSame($parameters['lf_description'], $data['description']); - static::assertSame($parameters['lf_tags'], $data['tags']); - static::assertTrue($data['private']); - } - - return $data; - }) - ; - - $result = $this->controller->save($request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertRegExp('@/subfolder/\?page=2#[\w\-]{6}@', $result->getHeader('location')[0]); - } - - /** - * Test save a bookmark - try to retrieve the thumbnail - */ - public function testSaveBookmarkWithThumbnailSync(): void - { - $parameters = ['lf_url' => 'http://url.tld/other?part=3#hash']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $this->container->conf = $this->createMock(ConfigManager::class); - $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { - if ($key === 'thumbnails.mode') { - return Thumbnailer::MODE_ALL; - } elseif ($key === 'general.enable_async_metadata') { - return false; - } - - return $default; - }); - - $this->container->thumbnailer = $this->createMock(Thumbnailer::class); - $this->container->thumbnailer - ->expects(static::once()) - ->method('get') - ->with($parameters['lf_url']) - ->willReturn($thumb = 'http://thumb.url') - ; - - $this->container->bookmarkService - ->expects(static::once()) - ->method('addOrSet') - ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($thumb): Bookmark { - static::assertSame($thumb, $bookmark->getThumbnail()); - - return $bookmark; - }) - ; - - $result = $this->controller->save($request, $response); - - static::assertSame(302, $result->getStatusCode()); - } - - /** - * Test save a bookmark - with ID #0 - */ - public function testSaveBookmarkWithIdZero(): void - { - $parameters = ['lf_id' => '0']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $this->container->bookmarkService->expects(static::once())->method('exists')->with(0)->willReturn(true); - $this->container->bookmarkService->expects(static::once())->method('get')->with(0)->willReturn(new Bookmark()); - - $result = $this->controller->save($request, $response); - - static::assertSame(302, $result->getStatusCode()); - } - - /** - * Test save a bookmark - do not attempt to retrieve thumbnails if async mode is enabled. - */ - public function testSaveBookmarkWithThumbnailAsync(): void - { - $parameters = ['lf_url' => 'http://url.tld/other?part=3#hash']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $this->container->conf = $this->createMock(ConfigManager::class); - $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { - if ($key === 'thumbnails.mode') { - return Thumbnailer::MODE_ALL; - } elseif ($key === 'general.enable_async_metadata') { - return true; - } - - return $default; - }); - - $this->container->thumbnailer = $this->createMock(Thumbnailer::class); - $this->container->thumbnailer->expects(static::never())->method('get'); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('addOrSet') - ->willReturnCallback(function (Bookmark $bookmark): Bookmark { - static::assertNull($bookmark->getThumbnail()); - - return $bookmark; - }) - ; - - $result = $this->controller->save($request, $response); - - static::assertSame(302, $result->getStatusCode()); - } - - /** - * Change the password with a wrong existing password - */ - public function testSaveBookmarkFromBookmarklet(): void - { - $parameters = ['source' => 'bookmarklet']; - - $request = $this->createMock(Request::class); - $request - ->method('getParam') - ->willReturnCallback(function (string $key) use ($parameters): ?string { - return $parameters[$key] ?? null; - }) - ; - $response = new Response(); - - $result = $this->controller->save($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('', (string) $result->getBody()); - } - - /** - * Change the password with a wrong existing password - */ - public function testSaveBookmarkWrongToken(): void - { - $this->container->sessionManager = $this->createMock(SessionManager::class); - $this->container->sessionManager->method('checkToken')->willReturn(false); - - $this->container->bookmarkService->expects(static::never())->method('addOrSet'); - $this->container->bookmarkService->expects(static::never())->method('set'); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->expectException(WrongTokenException::class); - - $this->controller->save($request, $response); - } - -} diff --git a/tests/front/controller/admin/ManageShaareControllerTest/SharePrivateTest.php b/tests/front/controller/admin/ManageShaareControllerTest/SharePrivateTest.php deleted file mode 100644 index 1e7877c7..00000000 --- a/tests/front/controller/admin/ManageShaareControllerTest/SharePrivateTest.php +++ /dev/null @@ -1,139 +0,0 @@ -createContainer(); - - $this->container->httpAccess = $this->createMock(HttpAccess::class); - $this->controller = new ManageShaareController($this->container); - } - - /** - * Test shaare private with a private bookmark which does not have a key yet. - */ - public function testSharePrivateWithNewPrivateBookmark(): void - { - $hash = 'abcdcef'; - $request = $this->createMock(Request::class); - $response = new Response(); - - $bookmark = (new Bookmark()) - ->setId(123) - ->setUrl('http://domain.tld') - ->setTitle('Title 123') - ->setPrivate(true) - ; - - $this->container->bookmarkService - ->expects(static::once()) - ->method('findByHash') - ->with($hash) - ->willReturn($bookmark) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('set') - ->with($bookmark, true) - ->willReturnCallback(function (Bookmark $bookmark): Bookmark { - static::assertSame(32, strlen($bookmark->getAdditionalContentEntry('private_key'))); - - return $bookmark; - }) - ; - - $result = $this->controller->sharePrivate($request, $response, ['hash' => $hash]); - - static::assertSame(302, $result->getStatusCode()); - static::assertRegExp('#/subfolder/shaare/' . $hash . '\?key=\w{32}#', $result->getHeaderLine('Location')); - } - - /** - * Test shaare private with a private bookmark which does already have a key. - */ - public function testSharePrivateWithExistingPrivateBookmark(): void - { - $hash = 'abcdcef'; - $existingKey = 'this is a private key'; - $request = $this->createMock(Request::class); - $response = new Response(); - - $bookmark = (new Bookmark()) - ->setId(123) - ->setUrl('http://domain.tld') - ->setTitle('Title 123') - ->setPrivate(true) - ->addAdditionalContentEntry('private_key', $existingKey) - ; - - $this->container->bookmarkService - ->expects(static::once()) - ->method('findByHash') - ->with($hash) - ->willReturn($bookmark) - ; - $this->container->bookmarkService - ->expects(static::never()) - ->method('set') - ; - - $result = $this->controller->sharePrivate($request, $response, ['hash' => $hash]); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame('/subfolder/shaare/' . $hash . '?key=' . $existingKey, $result->getHeaderLine('Location')); - } - - /** - * Test shaare private with a public bookmark. - */ - public function testSharePrivateWithPublicBookmark(): void - { - $hash = 'abcdcef'; - $request = $this->createMock(Request::class); - $response = new Response(); - - $bookmark = (new Bookmark()) - ->setId(123) - ->setUrl('http://domain.tld') - ->setTitle('Title 123') - ->setPrivate(false) - ; - - $this->container->bookmarkService - ->expects(static::once()) - ->method('findByHash') - ->with($hash) - ->willReturn($bookmark) - ; - $this->container->bookmarkService - ->expects(static::never()) - ->method('set') - ; - - $result = $this->controller->sharePrivate($request, $response, ['hash' => $hash]); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame('/subfolder/shaare/' . $hash, $result->getHeaderLine('Location')); - } -} 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 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->controller = new ShaareAddController($this->container); + } + + /** + * Test displaying add link page + */ + public function testAddShaare(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $expectedTags = [ + 'tag1' => 32, + 'tag2' => 24, + 'tag3' => 1, + ]; + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->willReturn($expectedTags) + ; + $expectedTags = array_merge($expectedTags, [BookmarkMarkdownFormatter::NO_MD_TAG => 1]); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { + return $key === 'formatter' ? 'markdown' : $default; + }); + + $result = $this->controller->addShaare($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('addlink', (string) $result->getBody()); + + static::assertSame('Shaare a new link - Shaarli', $assignedVariables['pagetitle']); + static::assertFalse($assignedVariables['default_private_links']); + static::assertTrue($assignedVariables['async_metadata']); + static::assertSame($expectedTags, $assignedVariables['tags']); + } + + /** + * Test displaying add link page + */ + public function testAddShaareWithoutMd(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $expectedTags = [ + 'tag1' => 32, + 'tag2' => 24, + 'tag3' => 1, + ]; + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->willReturn($expectedTags) + ; + + $result = $this->controller->addShaare($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('addlink', (string) $result->getBody()); + + static::assertSame($expectedTags, $assignedVariables['tags']); + } +} 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 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->controller = new ShaareManageController($this->container); + } + + /** + * Change bookmark visibility - Set private - Single public bookmark with valid parameters + */ + public function testSetSingleBookmarkPrivate(): void + { + $parameters = ['id' => '123', 'newVisibility' => 'private']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(false); + + static::assertFalse($bookmark->isPrivate()); + + $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); + $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, false); + $this->container->bookmarkService->expects(static::once())->method('save'); + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->with('raw') + ->willReturnCallback(function () use ($bookmark): BookmarkFormatter { + return new BookmarkRawFormatter($this->container->conf, true); + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::once()) + ->method('executeHooks') + ->with('save_link') + ; + + $result = $this->controller->changeVisibility($request, $response); + + static::assertTrue($bookmark->isPrivate()); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Change bookmark visibility - Set public - Single private bookmark with valid parameters + */ + public function testSetSingleBookmarkPublic(): void + { + $parameters = ['id' => '123', 'newVisibility' => 'public']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(true); + + static::assertTrue($bookmark->isPrivate()); + + $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); + $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, false); + $this->container->bookmarkService->expects(static::once())->method('save'); + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->with('raw') + ->willReturn(new BookmarkRawFormatter($this->container->conf, true)) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::once()) + ->method('executeHooks') + ->with('save_link') + ; + + $result = $this->controller->changeVisibility($request, $response); + + static::assertFalse($bookmark->isPrivate()); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Change bookmark visibility - Set private on single already private bookmark + */ + public function testSetSinglePrivateBookmarkPrivate(): void + { + $parameters = ['id' => '123', 'newVisibility' => 'private']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(true); + + static::assertTrue($bookmark->isPrivate()); + + $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); + $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, false); + $this->container->bookmarkService->expects(static::once())->method('save'); + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->with('raw') + ->willReturn(new BookmarkRawFormatter($this->container->conf, true)) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::once()) + ->method('executeHooks') + ->with('save_link') + ; + + $result = $this->controller->changeVisibility($request, $response); + + static::assertTrue($bookmark->isPrivate()); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Change bookmark visibility - Set multiple bookmarks private + */ + public function testSetMultipleBookmarksPrivate(): void + { + $parameters = ['id' => '123 456 789', 'newVisibility' => 'private']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmarks = [ + (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(false), + (new Bookmark())->setId(456)->setUrl('http://domain.tld')->setTitle('Title 456')->setPrivate(true), + (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789')->setPrivate(false), + ]; + + $this->container->bookmarkService + ->expects(static::exactly(3)) + ->method('get') + ->withConsecutive([123], [456], [789]) + ->willReturnOnConsecutiveCalls(...$bookmarks) + ; + $this->container->bookmarkService + ->expects(static::exactly(3)) + ->method('set') + ->withConsecutive(...array_map(function (Bookmark $bookmark): array { + return [$bookmark, false]; + }, $bookmarks)) + ; + $this->container->bookmarkService->expects(static::once())->method('save'); + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->with('raw') + ->willReturn(new BookmarkRawFormatter($this->container->conf, true)) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::exactly(3)) + ->method('executeHooks') + ->with('save_link') + ; + + $result = $this->controller->changeVisibility($request, $response); + + static::assertTrue($bookmarks[0]->isPrivate()); + static::assertTrue($bookmarks[1]->isPrivate()); + static::assertTrue($bookmarks[2]->isPrivate()); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Change bookmark visibility - Single bookmark not found. + */ + public function testChangeVisibilitySingleBookmarkNotFound(): void + { + $parameters = ['id' => '123', 'newVisibility' => 'private']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('get') + ->willThrowException(new BookmarkNotFoundException()) + ; + $this->container->bookmarkService->expects(static::never())->method('set'); + $this->container->bookmarkService->expects(static::never())->method('save'); + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->with('raw') + ->willReturn(new BookmarkRawFormatter($this->container->conf, true)) + ; + + // Make sure that PluginManager hook is not triggered + $this->container->pluginManager + ->expects(static::never()) + ->method('executeHooks') + ->with('save_link') + ; + + $result = $this->controller->changeVisibility($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Change bookmark visibility - Multiple bookmarks with one not found. + */ + public function testChangeVisibilityMultipleBookmarksOneNotFound(): void + { + $parameters = ['id' => '123 456 789', 'newVisibility' => 'public']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmarks = [ + (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123')->setPrivate(true), + (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789')->setPrivate(false), + ]; + + $this->container->bookmarkService + ->expects(static::exactly(3)) + ->method('get') + ->withConsecutive([123], [456], [789]) + ->willReturnCallback(function (int $id) use ($bookmarks): Bookmark { + if ($id === 123) { + return $bookmarks[0]; + } + if ($id === 789) { + return $bookmarks[1]; + } + throw new BookmarkNotFoundException(); + }) + ; + $this->container->bookmarkService + ->expects(static::exactly(2)) + ->method('set') + ->withConsecutive(...array_map(function (Bookmark $bookmark): array { + return [$bookmark, false]; + }, $bookmarks)) + ; + $this->container->bookmarkService->expects(static::once())->method('save'); + + // Make sure that PluginManager hook is not triggered + $this->container->pluginManager + ->expects(static::exactly(2)) + ->method('executeHooks') + ->with('save_link') + ; + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 456 could not be found.']) + ; + + $result = $this->controller->changeVisibility($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Change bookmark visibility - Invalid ID + */ + public function testChangeVisibilityInvalidId(): void + { + $parameters = ['id' => 'nope not an ID', 'newVisibility' => 'private']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.']) + ; + + $result = $this->controller->changeVisibility($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Change bookmark visibility - Empty ID + */ + public function testChangeVisibilityEmptyId(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.']) + ; + + $result = $this->controller->changeVisibility($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Change bookmark visibility - with invalid visibility + */ + public function testChangeVisibilityWithInvalidVisibility(): void + { + $parameters = ['id' => '123', 'newVisibility' => 'invalid']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid visibility provided.']) + ; + + $result = $this->controller->changeVisibility($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } +} 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 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->controller = new ShaareManageController($this->container); + } + + /** + * Delete bookmark - Single bookmark with valid parameters + */ + public function testDeleteSingleBookmark(): void + { + $parameters = ['id' => '123']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmark = (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123'); + + $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); + $this->container->bookmarkService->expects(static::once())->method('remove')->with($bookmark, false); + $this->container->bookmarkService->expects(static::once())->method('save'); + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->with('raw') + ->willReturnCallback(function () use ($bookmark): BookmarkFormatter { + $formatter = $this->createMock(BookmarkFormatter::class); + $formatter + ->expects(static::once()) + ->method('format') + ->with($bookmark) + ->willReturn(['formatted' => $bookmark]) + ; + + return $formatter; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::once()) + ->method('executeHooks') + ->with('delete_link', ['formatted' => $bookmark]) + ; + + $result = $this->controller->deleteBookmark($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Delete bookmark - Multiple bookmarks with valid parameters + */ + public function testDeleteMultipleBookmarks(): void + { + $parameters = ['id' => '123 456 789']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmarks = [ + (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123'), + (new Bookmark())->setId(456)->setUrl('http://domain.tld')->setTitle('Title 456'), + (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789'), + ]; + + $this->container->bookmarkService + ->expects(static::exactly(3)) + ->method('get') + ->withConsecutive([123], [456], [789]) + ->willReturnOnConsecutiveCalls(...$bookmarks) + ; + $this->container->bookmarkService + ->expects(static::exactly(3)) + ->method('remove') + ->withConsecutive(...array_map(function (Bookmark $bookmark): array { + return [$bookmark, false]; + }, $bookmarks)) + ; + $this->container->bookmarkService->expects(static::once())->method('save'); + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->with('raw') + ->willReturnCallback(function () use ($bookmarks): BookmarkFormatter { + $formatter = $this->createMock(BookmarkFormatter::class); + + $formatter + ->expects(static::exactly(3)) + ->method('format') + ->withConsecutive(...array_map(function (Bookmark $bookmark): array { + return [$bookmark]; + }, $bookmarks)) + ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array { + return ['formatted' => $bookmark]; + }, $bookmarks)) + ; + + return $formatter; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::exactly(3)) + ->method('executeHooks') + ->with('delete_link') + ; + + $result = $this->controller->deleteBookmark($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Delete bookmark - Single bookmark not found in the data store + */ + public function testDeleteSingleBookmarkNotFound(): void + { + $parameters = ['id' => '123']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('get') + ->willThrowException(new BookmarkNotFoundException()) + ; + $this->container->bookmarkService->expects(static::never())->method('remove'); + $this->container->bookmarkService->expects(static::never())->method('save'); + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->with('raw') + ->willReturnCallback(function (): BookmarkFormatter { + $formatter = $this->createMock(BookmarkFormatter::class); + + $formatter->expects(static::never())->method('format'); + + return $formatter; + }) + ; + // Make sure that PluginManager hook is not triggered + $this->container->pluginManager + ->expects(static::never()) + ->method('executeHooks') + ->with('delete_link') + ; + + $result = $this->controller->deleteBookmark($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Delete bookmark - Multiple bookmarks with one not found in the data store + */ + public function testDeleteMultipleBookmarksOneNotFound(): void + { + $parameters = ['id' => '123 456 789']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmarks = [ + (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123'), + (new Bookmark())->setId(789)->setUrl('http://domain.tld')->setTitle('Title 789'), + ]; + + $this->container->bookmarkService + ->expects(static::exactly(3)) + ->method('get') + ->withConsecutive([123], [456], [789]) + ->willReturnCallback(function (int $id) use ($bookmarks): Bookmark { + if ($id === 123) { + return $bookmarks[0]; + } + if ($id === 789) { + return $bookmarks[1]; + } + throw new BookmarkNotFoundException(); + }) + ; + $this->container->bookmarkService + ->expects(static::exactly(2)) + ->method('remove') + ->withConsecutive(...array_map(function (Bookmark $bookmark): array { + return [$bookmark, false]; + }, $bookmarks)) + ; + $this->container->bookmarkService->expects(static::once())->method('save'); + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->with('raw') + ->willReturnCallback(function () use ($bookmarks): BookmarkFormatter { + $formatter = $this->createMock(BookmarkFormatter::class); + + $formatter + ->expects(static::exactly(2)) + ->method('format') + ->withConsecutive(...array_map(function (Bookmark $bookmark): array { + return [$bookmark]; + }, $bookmarks)) + ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array { + return ['formatted' => $bookmark]; + }, $bookmarks)) + ; + + return $formatter; + }) + ; + + // Make sure that PluginManager hook is not triggered + $this->container->pluginManager + ->expects(static::exactly(2)) + ->method('executeHooks') + ->with('delete_link') + ; + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 456 could not be found.']) + ; + + $result = $this->controller->deleteBookmark($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Delete bookmark - Invalid ID + */ + public function testDeleteInvalidId(): void + { + $parameters = ['id' => 'nope not an ID']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.']) + ; + + $result = $this->controller->deleteBookmark($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Delete bookmark - Empty ID + */ + public function testDeleteEmptyId(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Invalid bookmark ID provided.']) + ; + + $result = $this->controller->deleteBookmark($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Delete bookmark - from bookmarklet + */ + public function testDeleteBookmarkFromBookmarklet(): void + { + $parameters = [ + 'id' => '123', + 'source' => 'bookmarklet', + ]; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $this->container->bookmarkService->method('get')->with('123')->willReturn( + (new Bookmark())->setId(123)->setUrl('http://domain.tld')->setTitle('Title 123') + ); + + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->willReturnCallback(function (): BookmarkFormatter { + $formatter = $this->createMock(BookmarkFormatter::class); + $formatter->method('format')->willReturn(['formatted']); + + return $formatter; + }) + ; + + $result = $this->controller->deleteBookmark($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('', (string) $result->getBody('location')); + } +} 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 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->controller = new ShaareManageController($this->container); + } + + /** + * Test pin bookmark - with valid input + * + * @dataProvider initialStickyValuesProvider() + */ + public function testPinBookmarkIsStickyNull(?bool $sticky, bool $expectedValue): void + { + $id = 123; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $bookmark = (new Bookmark()) + ->setId(123) + ->setUrl('http://domain.tld') + ->setTitle('Title 123') + ->setSticky($sticky) + ; + + $this->container->bookmarkService->expects(static::once())->method('get')->with(123)->willReturn($bookmark); + $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, true); + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::once()) + ->method('executeHooks') + ->with('save_link') + ; + + $result = $this->controller->pinBookmark($request, $response, ['id' => (string) $id]); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + + static::assertSame($expectedValue, $bookmark->isSticky()); + } + + public function initialStickyValuesProvider(): array + { + // [initialStickyState, isStickyAfterPin] + return [[null, true], [false, true], [true, false]]; + } + + /** + * Test pin bookmark - invalid bookmark ID + */ + public function testDisplayEditFormInvalidId(): void + { + $id = 'invalid'; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier invalid could not be found.']) + ; + + $result = $this->controller->pinBookmark($request, $response, ['id' => $id]); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Test pin bookmark - Bookmark ID not provided + */ + public function testDisplayEditFormIdNotProvided(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier could not be found.']) + ; + + $result = $this->controller->pinBookmark($request, $response, []); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Test pin bookmark - bookmark not found + */ + public function testDisplayEditFormBookmarkNotFound(): void + { + $id = 123; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('get') + ->with($id) + ->willThrowException(new BookmarkNotFoundException()) + ; + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 123 could not be found.']) + ; + + $result = $this->controller->pinBookmark($request, $response, ['id' => (string) $id]); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } +} 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 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->controller = new ShaareManageController($this->container); + } + + /** + * Test shaare private with a private bookmark which does not have a key yet. + */ + public function testSharePrivateWithNewPrivateBookmark(): void + { + $hash = 'abcdcef'; + $request = $this->createMock(Request::class); + $response = new Response(); + + $bookmark = (new Bookmark()) + ->setId(123) + ->setUrl('http://domain.tld') + ->setTitle('Title 123') + ->setPrivate(true) + ; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByHash') + ->with($hash) + ->willReturn($bookmark) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('set') + ->with($bookmark, true) + ->willReturnCallback(function (Bookmark $bookmark): Bookmark { + static::assertSame(32, strlen($bookmark->getAdditionalContentEntry('private_key'))); + + return $bookmark; + }) + ; + + $result = $this->controller->sharePrivate($request, $response, ['hash' => $hash]); + + static::assertSame(302, $result->getStatusCode()); + static::assertRegExp('#/subfolder/shaare/' . $hash . '\?key=\w{32}#', $result->getHeaderLine('Location')); + } + + /** + * Test shaare private with a private bookmark which does already have a key. + */ + public function testSharePrivateWithExistingPrivateBookmark(): void + { + $hash = 'abcdcef'; + $existingKey = 'this is a private key'; + $request = $this->createMock(Request::class); + $response = new Response(); + + $bookmark = (new Bookmark()) + ->setId(123) + ->setUrl('http://domain.tld') + ->setTitle('Title 123') + ->setPrivate(true) + ->addAdditionalContentEntry('private_key', $existingKey) + ; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByHash') + ->with($hash) + ->willReturn($bookmark) + ; + $this->container->bookmarkService + ->expects(static::never()) + ->method('set') + ; + + $result = $this->controller->sharePrivate($request, $response, ['hash' => $hash]); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/shaare/' . $hash . '?key=' . $existingKey, $result->getHeaderLine('Location')); + } + + /** + * Test shaare private with a public bookmark. + */ + public function testSharePrivateWithPublicBookmark(): void + { + $hash = 'abcdcef'; + $request = $this->createMock(Request::class); + $response = new Response(); + + $bookmark = (new Bookmark()) + ->setId(123) + ->setUrl('http://domain.tld') + ->setTitle('Title 123') + ->setPrivate(false) + ; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByHash') + ->with($hash) + ->willReturn($bookmark) + ; + $this->container->bookmarkService + ->expects(static::never()) + ->method('set') + ; + + $result = $this->controller->sharePrivate($request, $response, ['hash' => $hash]); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/shaare/' . $hash, $result->getHeaderLine('Location')); + } +} diff --git a/tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateBatchFormTest.php b/tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateBatchFormTest.php new file mode 100644 index 00000000..34547120 --- /dev/null +++ b/tests/front/controller/admin/ShaarePublishControllerTest/DisplayCreateBatchFormTest.php @@ -0,0 +1,62 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->container->metadataRetriever = $this->createMock(MetadataRetriever::class); + $this->controller = new ShaarePublishController($this->container); + } + + /** + * TODO + */ + public function testDisplayCreateFormBatch(): void + { + $urls = [ + 'https://domain1.tld/url1', + 'https://domain2.tld/url2', + 'https://domain3.tld/url3', + ]; + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key) use ($urls): ?string { + return $key === 'urls' ? implode(PHP_EOL, $urls) : null; + }); + $response = new Response(); + + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->displayCreateBatchForms($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('editlink.batch', (string) $result->getBody()); + + static::assertTrue($assignedVariables['batch_mode']); + static::assertCount(3, $assignedVariables['links']); + static::assertSame($urls[0], $assignedVariables['links'][0]['link']['url']); + static::assertSame($urls[1], $assignedVariables['links'][1]['link']['url']); + static::assertSame($urls[2], $assignedVariables['links'][2]['link']['url']); + } +} 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 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->container->metadataRetriever = $this->createMock(MetadataRetriever::class); + $this->controller = new ShaarePublishController($this->container); + } + + /** + * Test displaying bookmark create form + * Ensure that every step of the standard workflow works properly. + */ + public function testDisplayCreateFormWithUrlAndWithMetadataRetrieval(): void + { + $this->container->environment = [ + 'HTTP_REFERER' => $referer = 'http://shaarli/subfolder/controller/?searchtag=abc' + ]; + + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $url = 'http://url.tld/other?part=3&utm_ad=pay#hash'; + $expectedUrl = str_replace('&utm_ad=pay', '', $url); + $remoteTitle = 'Remote Title'; + $remoteDesc = 'Sometimes the meta description is relevant.'; + $remoteTags = 'abc def'; + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key) use ($url): ?string { + return $key === 'post' ? $url : null; + }); + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $param, $default) { + if ($param === 'general.enable_async_metadata') { + return false; + } + + return $default; + }); + + $this->container->metadataRetriever->expects(static::once())->method('retrieve')->willReturn([ + 'title' => $remoteTitle, + 'description' => $remoteDesc, + 'tags' => $remoteTags, + ]); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->willReturn($tags = ['tag1' => 2, 'tag2' => 1]) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::atLeastOnce()) + ->method('executeHooks') + ->withConsecutive(['render_editlink'], ['render_includes']) + ->willReturnCallback(function (string $hook, array $data) use ($remoteTitle, $remoteDesc): array { + if ('render_editlink' === $hook) { + static::assertSame($remoteTitle, $data['link']['title']); + static::assertSame($remoteDesc, $data['link']['description']); + } + + return $data; + }) + ; + + $result = $this->controller->displayCreateForm($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('editlink', (string) $result->getBody()); + + static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame($expectedUrl, $assignedVariables['link']['url']); + static::assertSame($remoteTitle, $assignedVariables['link']['title']); + static::assertSame($remoteDesc, $assignedVariables['link']['description']); + static::assertSame($remoteTags, $assignedVariables['link']['tags']); + static::assertFalse($assignedVariables['link']['private']); + + static::assertTrue($assignedVariables['link_is_new']); + static::assertSame($referer, $assignedVariables['http_referer']); + static::assertSame($tags, $assignedVariables['tags']); + static::assertArrayHasKey('source', $assignedVariables); + static::assertArrayHasKey('default_private_links', $assignedVariables); + static::assertArrayHasKey('async_metadata', $assignedVariables); + static::assertArrayHasKey('retrieve_description', $assignedVariables); + } + + /** + * Test displaying bookmark create form without any external metadata retrieval attempt + */ + public function testDisplayCreateFormWithUrlAndWithoutMetadata(): void + { + $this->container->environment = [ + 'HTTP_REFERER' => $referer = 'http://shaarli/subfolder/controller/?searchtag=abc' + ]; + + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $url = 'http://url.tld/other?part=3&utm_ad=pay#hash'; + $expectedUrl = str_replace('&utm_ad=pay', '', $url); + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key) use ($url): ?string { + return $key === 'post' ? $url : null; + }); + $response = new Response(); + + $this->container->metadataRetriever->expects(static::never())->method('retrieve'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->willReturn($tags = ['tag1' => 2, 'tag2' => 1]) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::atLeastOnce()) + ->method('executeHooks') + ->withConsecutive(['render_editlink'], ['render_includes']) + ->willReturnCallback(function (string $hook, array $data): array { + if ('render_editlink' === $hook) { + static::assertSame('', $data['link']['title']); + static::assertSame('', $data['link']['description']); + } + + return $data; + }) + ; + + $result = $this->controller->displayCreateForm($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('editlink', (string) $result->getBody()); + + static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame($expectedUrl, $assignedVariables['link']['url']); + static::assertSame('', $assignedVariables['link']['title']); + static::assertSame('', $assignedVariables['link']['description']); + static::assertSame('', $assignedVariables['link']['tags']); + static::assertFalse($assignedVariables['link']['private']); + + static::assertTrue($assignedVariables['link_is_new']); + static::assertSame($referer, $assignedVariables['http_referer']); + static::assertSame($tags, $assignedVariables['tags']); + static::assertArrayHasKey('source', $assignedVariables); + static::assertArrayHasKey('default_private_links', $assignedVariables); + static::assertArrayHasKey('async_metadata', $assignedVariables); + static::assertArrayHasKey('retrieve_description', $assignedVariables); + } + + /** + * Test displaying bookmark create form + * Ensure all available query parameters are handled properly. + */ + public function testDisplayCreateFormWithFullParameters(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $parameters = [ + 'post' => 'http://url.tld/other?part=3&utm_ad=pay#hash', + 'title' => 'Provided Title', + 'description' => 'Provided description.', + 'tags' => 'abc def', + 'private' => '1', + 'source' => 'apps', + ]; + $expectedUrl = str_replace('&utm_ad=pay', '', $parameters['post']); + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }); + $response = new Response(); + + $result = $this->controller->displayCreateForm($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('editlink', (string) $result->getBody()); + + static::assertSame('Shaare - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame($expectedUrl, $assignedVariables['link']['url']); + static::assertSame($parameters['title'], $assignedVariables['link']['title']); + static::assertSame($parameters['description'], $assignedVariables['link']['description']); + static::assertSame($parameters['tags'], $assignedVariables['link']['tags']); + static::assertTrue($assignedVariables['link']['private']); + static::assertTrue($assignedVariables['link_is_new']); + static::assertSame($parameters['source'], $assignedVariables['source']); + } + + /** + * Test displaying bookmark create form + * Without any parameter. + */ + public function testDisplayCreateFormEmpty(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->httpAccess->expects(static::never())->method('getHttpResponse'); + $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback'); + + $result = $this->controller->displayCreateForm($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('editlink', (string) $result->getBody()); + static::assertSame('', $assignedVariables['link']['url']); + static::assertSame('Note: ', $assignedVariables['link']['title']); + static::assertSame('', $assignedVariables['link']['description']); + static::assertSame('', $assignedVariables['link']['tags']); + static::assertFalse($assignedVariables['link']['private']); + static::assertTrue($assignedVariables['link_is_new']); + } + + /** + * Test displaying bookmark create form + * URL not using HTTP protocol: do not try to retrieve the title + */ + public function testDisplayCreateFormNotHttp(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $url = 'magnet://kubuntu.torrent'; + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($url): ?string { + return $key === 'post' ? $url : null; + }); + $response = new Response(); + + $this->container->httpAccess->expects(static::never())->method('getHttpResponse'); + $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback'); + + $result = $this->controller->displayCreateForm($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('editlink', (string) $result->getBody()); + static::assertSame($url, $assignedVariables['link']['url']); + static::assertTrue($assignedVariables['link_is_new']); + } + + /** + * Test displaying bookmark create form + * When markdown formatter is enabled, the no markdown tag should be added to existing tags. + */ + public function testDisplayCreateFormWithMarkdownEnabled(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf + ->expects(static::atLeastOnce()) + ->method('get')->willReturnCallback(function (string $key): ?string { + if ($key === 'formatter') { + return 'markdown'; + } + + return $key; + }) + ; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->displayCreateForm($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('editlink', (string) $result->getBody()); + static::assertSame(['nomarkdown' => 1], $assignedVariables['tags']); + } + + /** + * Test displaying bookmark create form + * When an existing URL is submitted, we want to edit the existing link. + */ + public function testDisplayCreateFormWithExistingUrl(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $url = 'http://url.tld/other?part=3&utm_ad=pay#hash'; + $expectedUrl = str_replace('&utm_ad=pay', '', $url); + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($url): ?string { + return $key === 'post' ? $url : null; + }); + $response = new Response(); + + $this->container->httpAccess->expects(static::never())->method('getHttpResponse'); + $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByUrl') + ->with($expectedUrl) + ->willReturn( + (new Bookmark()) + ->setId($id = 23) + ->setUrl($expectedUrl) + ->setTitle($title = 'Bookmark Title') + ->setDescription($description = 'Bookmark description.') + ->setTags($tags = ['abc', 'def']) + ->setPrivate(true) + ->setCreated($createdAt = new \DateTime('2020-06-10 18:45:44')) + ) + ; + + $result = $this->controller->displayCreateForm($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('editlink', (string) $result->getBody()); + + static::assertSame('Edit Shaare - Shaarli', $assignedVariables['pagetitle']); + static::assertFalse($assignedVariables['link_is_new']); + + static::assertSame($id, $assignedVariables['link']['id']); + static::assertSame($expectedUrl, $assignedVariables['link']['url']); + static::assertSame($title, $assignedVariables['link']['title']); + static::assertSame($description, $assignedVariables['link']['description']); + static::assertSame(implode(' ', $tags), $assignedVariables['link']['tags']); + static::assertTrue($assignedVariables['link']['private']); + static::assertSame($createdAt, $assignedVariables['link']['created']); + } +} 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 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->controller = new ShaarePublishController($this->container); + } + + /** + * Test displaying bookmark edit form + * When an existing ID is provided, ensure that default workflow works properly. + */ + public function testDisplayEditFormDefault(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $id = 11; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->httpAccess->expects(static::never())->method('getHttpResponse'); + $this->container->httpAccess->expects(static::never())->method('getCurlDownloadCallback'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('get') + ->with($id) + ->willReturn( + (new Bookmark()) + ->setId($id) + ->setUrl($url = 'http://domain.tld') + ->setTitle($title = 'Bookmark Title') + ->setDescription($description = 'Bookmark description.') + ->setTags($tags = ['abc', 'def']) + ->setPrivate(true) + ->setCreated($createdAt = new \DateTime('2020-06-10 18:45:44')) + ) + ; + + $result = $this->controller->displayEditForm($request, $response, ['id' => (string) $id]); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('editlink', (string) $result->getBody()); + + static::assertSame('Edit Shaare - Shaarli', $assignedVariables['pagetitle']); + static::assertFalse($assignedVariables['link_is_new']); + + static::assertSame($id, $assignedVariables['link']['id']); + static::assertSame($url, $assignedVariables['link']['url']); + static::assertSame($title, $assignedVariables['link']['title']); + static::assertSame($description, $assignedVariables['link']['description']); + static::assertSame(implode(' ', $tags), $assignedVariables['link']['tags']); + static::assertTrue($assignedVariables['link']['private']); + static::assertSame($createdAt, $assignedVariables['link']['created']); + } + + /** + * Test displaying bookmark edit form + * Invalid ID provided. + */ + public function testDisplayEditFormInvalidId(): void + { + $id = 'invalid'; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier invalid could not be found.']) + ; + + $result = $this->controller->displayEditForm($request, $response, ['id' => $id]); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Test displaying bookmark edit form + * ID not provided. + */ + public function testDisplayEditFormIdNotProvided(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier could not be found.']) + ; + + $result = $this->controller->displayEditForm($request, $response, []); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Test displaying bookmark edit form + * Bookmark not found. + */ + public function testDisplayEditFormBookmarkNotFound(): void + { + $id = 123; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('get') + ->with($id) + ->willThrowException(new BookmarkNotFoundException()) + ; + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Bookmark with identifier 123 could not be found.']) + ; + + $result = $this->controller->displayEditForm($request, $response, ['id' => (string) $id]); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } +} 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 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->controller = new ShaarePublishController($this->container); + } + + /** + * Test save a new bookmark + */ + public function testSaveBookmark(): void + { + $id = 21; + $parameters = [ + 'lf_url' => 'http://url.tld/other?part=3#hash', + 'lf_title' => 'Provided Title', + 'lf_description' => 'Provided description.', + 'lf_tags' => 'abc def', + 'lf_private' => '1', + 'returnurl' => 'http://shaarli/subfolder/admin/add-shaare' + ]; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $checkBookmark = function (Bookmark $bookmark) use ($parameters) { + static::assertSame($parameters['lf_url'], $bookmark->getUrl()); + static::assertSame($parameters['lf_title'], $bookmark->getTitle()); + static::assertSame($parameters['lf_description'], $bookmark->getDescription()); + static::assertSame($parameters['lf_tags'], $bookmark->getTagsString()); + static::assertTrue($bookmark->isPrivate()); + }; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('addOrSet') + ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark { + static::assertFalse($save); + + $checkBookmark($bookmark); + + $bookmark->setId($id); + + return $bookmark; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('set') + ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark { + static::assertTrue($save); + + $checkBookmark($bookmark); + + static::assertSame($id, $bookmark->getId()); + + return $bookmark; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::atLeastOnce()) + ->method('executeHooks') + ->withConsecutive(['save_link']) + ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { + if ('save_link' === $hook) { + static::assertSame($id, $data['id']); + static::assertSame($parameters['lf_url'], $data['url']); + static::assertSame($parameters['lf_title'], $data['title']); + static::assertSame($parameters['lf_description'], $data['description']); + static::assertSame($parameters['lf_tags'], $data['tags']); + static::assertTrue($data['private']); + } + + return $data; + }) + ; + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertRegExp('@/subfolder/#[\w\-]{6}@', $result->getHeader('location')[0]); + } + + + /** + * Test save an existing bookmark + */ + public function testSaveExistingBookmark(): void + { + $id = 21; + $parameters = [ + 'lf_id' => (string) $id, + 'lf_url' => 'http://url.tld/other?part=3#hash', + 'lf_title' => 'Provided Title', + 'lf_description' => 'Provided description.', + 'lf_tags' => 'abc def', + 'lf_private' => '1', + 'returnurl' => 'http://shaarli/subfolder/?page=2' + ]; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $checkBookmark = function (Bookmark $bookmark) use ($parameters, $id) { + static::assertSame($id, $bookmark->getId()); + static::assertSame($parameters['lf_url'], $bookmark->getUrl()); + static::assertSame($parameters['lf_title'], $bookmark->getTitle()); + static::assertSame($parameters['lf_description'], $bookmark->getDescription()); + static::assertSame($parameters['lf_tags'], $bookmark->getTagsString()); + static::assertTrue($bookmark->isPrivate()); + }; + + $this->container->bookmarkService->expects(static::atLeastOnce())->method('exists')->willReturn(true); + $this->container->bookmarkService + ->expects(static::once()) + ->method('get') + ->willReturn((new Bookmark())->setId($id)->setUrl('http://other.url')) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('addOrSet') + ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark { + static::assertFalse($save); + + $checkBookmark($bookmark); + + return $bookmark; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('set') + ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): Bookmark { + static::assertTrue($save); + + $checkBookmark($bookmark); + + static::assertSame($id, $bookmark->getId()); + + return $bookmark; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::atLeastOnce()) + ->method('executeHooks') + ->withConsecutive(['save_link']) + ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { + if ('save_link' === $hook) { + static::assertSame($id, $data['id']); + static::assertSame($parameters['lf_url'], $data['url']); + static::assertSame($parameters['lf_title'], $data['title']); + static::assertSame($parameters['lf_description'], $data['description']); + static::assertSame($parameters['lf_tags'], $data['tags']); + static::assertTrue($data['private']); + } + + return $data; + }) + ; + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertRegExp('@/subfolder/\?page=2#[\w\-]{6}@', $result->getHeader('location')[0]); + } + + /** + * Test save a bookmark - try to retrieve the thumbnail + */ + public function testSaveBookmarkWithThumbnailSync(): void + { + $parameters = ['lf_url' => 'http://url.tld/other?part=3#hash']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { + if ($key === 'thumbnails.mode') { + return Thumbnailer::MODE_ALL; + } elseif ($key === 'general.enable_async_metadata') { + return false; + } + + return $default; + }); + + $this->container->thumbnailer = $this->createMock(Thumbnailer::class); + $this->container->thumbnailer + ->expects(static::once()) + ->method('get') + ->with($parameters['lf_url']) + ->willReturn($thumb = 'http://thumb.url') + ; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('addOrSet') + ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($thumb): Bookmark { + static::assertSame($thumb, $bookmark->getThumbnail()); + + return $bookmark; + }) + ; + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + } + + /** + * Test save a bookmark - with ID #0 + */ + public function testSaveBookmarkWithIdZero(): void + { + $parameters = ['lf_id' => '0']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $this->container->bookmarkService->expects(static::once())->method('exists')->with(0)->willReturn(true); + $this->container->bookmarkService->expects(static::once())->method('get')->with(0)->willReturn(new Bookmark()); + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + } + + /** + * Test save a bookmark - do not attempt to retrieve thumbnails if async mode is enabled. + */ + public function testSaveBookmarkWithThumbnailAsync(): void + { + $parameters = ['lf_url' => 'http://url.tld/other?part=3#hash']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { + if ($key === 'thumbnails.mode') { + return Thumbnailer::MODE_ALL; + } elseif ($key === 'general.enable_async_metadata') { + return true; + } + + return $default; + }); + + $this->container->thumbnailer = $this->createMock(Thumbnailer::class); + $this->container->thumbnailer->expects(static::never())->method('get'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('addOrSet') + ->willReturnCallback(function (Bookmark $bookmark): Bookmark { + static::assertNull($bookmark->getThumbnail()); + + return $bookmark; + }) + ; + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + } + + /** + * Change the password with a wrong existing password + */ + public function testSaveBookmarkFromBookmarklet(): void + { + $parameters = ['source' => 'bookmarklet']; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $response = new Response(); + + $result = $this->controller->save($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('', (string) $result->getBody()); + } + + /** + * Change the password with a wrong existing password + */ + public function testSaveBookmarkWrongToken(): void + { + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->method('checkToken')->willReturn(false); + + $this->container->bookmarkService->expects(static::never())->method('addOrSet'); + $this->container->bookmarkService->expects(static::never())->method('set'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->expectException(WrongTokenException::class); + + $this->controller->save($request, $response); + } + +} -- cgit v1.2.3