From 485b168a9677d160b0c0426e4f282b9bd0c632c1 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sun, 26 Jan 2020 11:15:15 +0100 Subject: Process picwall rendering through Slim controller + UT --- .../front/controller/PictureWallControllerTest.php | 180 +++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 tests/front/controller/PictureWallControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/PictureWallControllerTest.php b/tests/front/controller/PictureWallControllerTest.php new file mode 100644 index 00000000..63802abd --- /dev/null +++ b/tests/front/controller/PictureWallControllerTest.php @@ -0,0 +1,180 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new PictureWallController($this->container); + } + + public function testValidControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getQueryParams')->willReturn([]); + $response = new Response(); + + // ConfigManager: thumbnails are enabled + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + if ($parameter === 'thumbnails.mode') { + return Thumbnailer::MODE_COMMON; + } + + return $default; + }); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->container->pageBuilder + ->expects(static::atLeastOnce()) + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { + $assignedVariables[$key] = $value; + + return $this; + }) + ; + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + // Visibility is set through the container, not the call + static::assertNull($visibility); + + // No query parameters + if (count($parameters) === 0) { + return [ + (new Bookmark())->setId(1)->setUrl('http://url.tld')->setThumbnail('thumb1'), + (new Bookmark())->setId(2)->setUrl('http://url2.tld'), + (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setThumbnail('thumb2'), + ]; + } + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_picwall', $hook); + static::assertArrayHasKey('linksToDisplay', $data); + static::assertCount(2, $data['linksToDisplay']); + static::assertSame(1, $data['linksToDisplay'][0]['id']); + static::assertSame(3, $data['linksToDisplay'][1]['id']); + static::assertArrayHasKey('loggedin', $param); + + return $data; + }); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('picwall', (string) $result->getBody()); + static::assertSame('Picture wall - Shaarli', $assignedVariables['pagetitle']); + static::assertCount(2, $assignedVariables['linksToDisplay']); + + $link = $assignedVariables['linksToDisplay'][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url.tld', $link['url']); + static::assertSame('thumb1', $link['thumbnail']); + + $link = $assignedVariables['linksToDisplay'][1]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertSame('thumb2', $link['thumbnail']); + } + + public function testControllerWithThumbnailsDisabled(): void + { + $this->expectException(ThumbnailsDisabledException::class); + + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // ConfigManager: thumbnails are disabled + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + if ($parameter === 'thumbnails.mode') { + return Thumbnailer::MODE_NONE; + } + + return $default; + }); + + $this->controller->index($request, $response); + } + + protected function createValidContainerMockSet(): void + { + $loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager = $loginManager; + + // Config + $conf = $this->createMock(ConfigManager::class); + $this->container->conf = $conf; + + // PageBuilder + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + $this->container->pageBuilder = $pageBuilder; + + // Plugin Manager + $pluginManager = $this->createMock(PluginManager::class); + $this->container->pluginManager = $pluginManager; + + // BookmarkService + $bookmarkService = $this->createMock(BookmarkServiceInterface::class); + $this->container->bookmarkService = $bookmarkService; + + // Formatter + $formatterFactory = $this->createMock(FormatterFactory::class); + $formatterFactory + ->method('getFormatter') + ->willReturnCallback(function (string $type): BookmarkFormatter { + if ($type === 'raw') { + return new BookmarkRawFormatter($this->container->conf, true); + } + }) + ; + $this->container->formatterFactory = $formatterFactory; + } +} -- cgit v1.2.3 From 8e47af2b3620c920116ec056173277c039163ec1 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Thu, 23 Jan 2020 21:52:03 +0100 Subject: Process logout through Slim controller --- tests/front/controller/LogoutControllerTest.php | 60 +++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tests/front/controller/LogoutControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/LogoutControllerTest.php b/tests/front/controller/LogoutControllerTest.php new file mode 100644 index 00000000..d9ca1c25 --- /dev/null +++ b/tests/front/controller/LogoutControllerTest.php @@ -0,0 +1,60 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new LogoutController($this->container); + + setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, $cookie = 'hi there'); + } + + public function testValidControllerInvoke(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $pageCacheManager = $this->createMock(PageCacheManager::class); + $pageCacheManager->expects(static::once())->method('invalidateCaches'); + $this->container->pageCacheManager = $pageCacheManager; + + $sessionManager = $this->createMock(SessionManager::class); + $sessionManager->expects(static::once())->method('logout'); + $this->container->sessionManager = $sessionManager; + + static::assertSame('hi there', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertContains('./', $result->getHeader('Location')); + static::assertSame('false', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); + } +} -- cgit v1.2.3 From 03340c18ead651ef9e11f883745695f2edafbae3 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Tue, 12 May 2020 12:44:48 +0200 Subject: Slim router: handle add tag route --- tests/front/controller/TagControllerTest.php | 191 +++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 tests/front/controller/TagControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/TagControllerTest.php b/tests/front/controller/TagControllerTest.php new file mode 100644 index 00000000..bbac5652 --- /dev/null +++ b/tests/front/controller/TagControllerTest.php @@ -0,0 +1,191 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new TagController($this->container); + } + + public function testAddTagWithReferer(): void + { + $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); + } + + public function testAddTagWithRefererAndExistingSearch(): void + { + $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); + } + + public function testAddTagWithoutRefererAndExistingSearch(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./?searchtags=abc'], $result->getHeader('location')); + } + + public function testAddTagRemoveLegacyQueryParam(): void + { + $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); + } + + public function testAddTagResetPagination(): void + { + $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); + } + + public function testAddTagWithRefererAndEmptySearch(): void + { + $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); + } + + public function testAddTagWithoutNewTagWithReferer(): void + { + $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->addTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); + } + + public function testAddTagWithoutNewTagWithoutReferer(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->addTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + protected function createValidContainerMockSet(): void + { + // User logged out + $loginManager = $this->createMock(LoginManager::class); + $loginManager->method('isLoggedIn')->willReturn(false); + $loginManager->method('canLogin')->willReturn(true); + $this->container->loginManager = $loginManager; + + // Config + $conf = $this->createMock(ConfigManager::class); + $conf->method('get')->willReturnCallback(function (string $parameter, $default) { + return $default; + }); + $this->container->conf = $conf; + + // PageBuilder + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + $this->container->pageBuilder = $pageBuilder; + + $pluginManager = $this->createMock(PluginManager::class); + $this->container->pluginManager = $pluginManager; + $bookmarkService = $this->createMock(BookmarkServiceInterface::class); + $this->container->bookmarkService = $bookmarkService; + } +} -- cgit v1.2.3 From 72caf4e84c412ab6a4181b83a96dbef8ebb3c65a Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 16 May 2020 12:55:29 +0200 Subject: Working version before optimization --- tests/front/controller/TagCloudControllerTest.php | 258 ++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 tests/front/controller/TagCloudControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/TagCloudControllerTest.php b/tests/front/controller/TagCloudControllerTest.php new file mode 100644 index 00000000..a76d5835 --- /dev/null +++ b/tests/front/controller/TagCloudControllerTest.php @@ -0,0 +1,258 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new TagCloudController($this->container); + } + + public function testValidCloudControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $allTags = [ + 'ghi' => 1, + 'abc' => 3, + 'def' => 12, + ]; + $expectedOrder = ['abc', 'def', 'ghi']; + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getQueryParam')->with('searchtags')->willReturn(null); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function () use ($allTags): array { + return $allTags; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(3, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(3, $assignedVariables['tags']); + static::assertSame($expectedOrder, array_keys($assignedVariables['tags'])); + + foreach ($allTags as $tag => $count) { + static::assertArrayHasKey($tag, $assignedVariables['tags']); + static::assertSame($count, $assignedVariables['tags'][$tag]['count']); + static::assertGreaterThan(0, $assignedVariables['tags'][$tag]['size']); + static::assertLessThan(5, $assignedVariables['tags'][$tag]['size']); + } + } + + /** + * Additional parameters: + * - logged in + * - visibility private + * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) + */ + public function testValidCloudControllerInvokeWithParameters(): void + { + $this->createValidContainerMockSet(); + + $allTags = [ + 'ghi' => 1, + 'abc' => 3, + 'def' => 12, + ]; + + $request = $this->createMock(Request::class); + $request + ->expects(static::once()) + ->method('getQueryParam') + ->with('searchtags') + ->willReturn('ghi def') + ; + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->loginManager->method('isLoggedin')->willReturn(true); + $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) + ->willReturnCallback(function () use ($allTags): array { + return $allTags; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('ghi def', $data['search_tags']); + static::assertCount(1, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('ghi def - Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('ghi def', $assignedVariables['search_tags']); + static::assertCount(1, $assignedVariables['tags']); + + static::assertArrayHasKey('abc', $assignedVariables['tags']); + static::assertSame(3, $assignedVariables['tags']['abc']['count']); + static::assertGreaterThan(0, $assignedVariables['tags']['abc']['size']); + static::assertLessThan(5, $assignedVariables['tags']['abc']['size']); + } + + public function testEmptyCloud(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getQueryParam')->with('searchtags')->willReturn(null); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(0, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(0, $assignedVariables['tags']); + } + + protected function createValidContainerMockSet(): void + { + $loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager = $loginManager; + + $sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager = $sessionManager; + + // Config + $conf = $this->createMock(ConfigManager::class); + $this->container->conf = $conf; + + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + return $default; + }); + + // PageBuilder + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + $this->container->pageBuilder = $pageBuilder; + + // Plugin Manager + $pluginManager = $this->createMock(PluginManager::class); + $this->container->pluginManager = $pluginManager; + + // BookmarkService + $bookmarkService = $this->createMock(BookmarkServiceInterface::class); + $this->container->bookmarkService = $bookmarkService; + } + + protected function assignTemplateVars(array &$variables): void + { + $this->container->pageBuilder + ->expects(static::atLeastOnce()) + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$variables) { + $variables[$key] = $value; + + return $this; + }) + ; + } +} -- cgit v1.2.3 From c79473bd84ab5aba7836d2caaf61847cabaf1e53 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 16 May 2020 13:13:00 +0200 Subject: Handle tag filtering in the Bookmark service --- tests/front/controller/TagCloudControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/front') diff --git a/tests/front/controller/TagCloudControllerTest.php b/tests/front/controller/TagCloudControllerTest.php index a76d5835..5cbf06a9 100644 --- a/tests/front/controller/TagCloudControllerTest.php +++ b/tests/front/controller/TagCloudControllerTest.php @@ -127,8 +127,8 @@ class TagCloudControllerTest extends TestCase ->expects(static::once()) ->method('bookmarksCountPerTag') ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) - ->willReturnCallback(function () use ($allTags): array { - return $allTags; + ->willReturnCallback(function (): array { + return ['abc' => 3]; }) ; -- cgit v1.2.3 From 3772298ee7d8d0708f4e72798600accafa17740b Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 16 May 2020 13:33:39 +0200 Subject: Few optimizations and code readability for tag cloud controller --- tests/front/controller/TagCloudControllerTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/front') diff --git a/tests/front/controller/TagCloudControllerTest.php b/tests/front/controller/TagCloudControllerTest.php index 5cbf06a9..352bdee2 100644 --- a/tests/front/controller/TagCloudControllerTest.php +++ b/tests/front/controller/TagCloudControllerTest.php @@ -73,7 +73,7 @@ class TagCloudControllerTest extends TestCase }) ; - $result = $this->controller->index($request, $response); + $result = $this->controller->cloud($request, $response); static::assertSame(200, $result->getStatusCode()); static::assertSame('tag.cloud', (string) $result->getBody()); @@ -147,7 +147,7 @@ class TagCloudControllerTest extends TestCase }) ; - $result = $this->controller->index($request, $response); + $result = $this->controller->cloud($request, $response); static::assertSame(200, $result->getStatusCode()); static::assertSame('tag.cloud', (string) $result->getBody()); @@ -198,7 +198,7 @@ class TagCloudControllerTest extends TestCase }) ; - $result = $this->controller->index($request, $response); + $result = $this->controller->cloud($request, $response); static::assertSame(200, $result->getStatusCode()); static::assertSame('tag.cloud', (string) $result->getBody()); -- cgit v1.2.3 From 60ae241251b753fc052e50ebd95277dfcb074cb0 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 16 May 2020 14:56:22 +0200 Subject: Process tag list page through Slim controller --- tests/front/controller/TagCloudControllerTest.php | 203 ++++++++++++++++++++-- 1 file changed, 191 insertions(+), 12 deletions(-) (limited to 'tests/front') diff --git a/tests/front/controller/TagCloudControllerTest.php b/tests/front/controller/TagCloudControllerTest.php index 352bdee2..719610d7 100644 --- a/tests/front/controller/TagCloudControllerTest.php +++ b/tests/front/controller/TagCloudControllerTest.php @@ -30,6 +30,9 @@ class TagCloudControllerTest extends TestCase $this->controller = new TagCloudController($this->container); } + /** + * Tag Cloud - default parameters + */ public function testValidCloudControllerInvokeDefault(): void { $this->createValidContainerMockSet(); @@ -42,7 +45,6 @@ class TagCloudControllerTest extends TestCase $expectedOrder = ['abc', 'def', 'ghi']; $request = $this->createMock(Request::class); - $request->expects(static::once())->method('getQueryParam')->with('searchtags')->willReturn(null); $response = new Response(); // Save RainTPL assigned variables @@ -92,7 +94,7 @@ class TagCloudControllerTest extends TestCase } /** - * Additional parameters: + * Tag Cloud - Additional parameters: * - logged in * - visibility private * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) @@ -101,18 +103,17 @@ class TagCloudControllerTest extends TestCase { $this->createValidContainerMockSet(); - $allTags = [ - 'ghi' => 1, - 'abc' => 3, - 'def' => 12, - ]; - $request = $this->createMock(Request::class); $request - ->expects(static::once()) ->method('getQueryParam') - ->with('searchtags') - ->willReturn('ghi def') + ->with() + ->willReturnCallback(function (string $key): ?string { + if ('searchtags' === $key) { + return 'ghi def'; + } + + return null; + }) ; $response = new Response(); @@ -162,12 +163,14 @@ class TagCloudControllerTest extends TestCase static::assertLessThan(5, $assignedVariables['tags']['abc']['size']); } + /** + * Tag Cloud - empty + */ public function testEmptyCloud(): void { $this->createValidContainerMockSet(); $request = $this->createMock(Request::class); - $request->expects(static::once())->method('getQueryParam')->with('searchtags')->willReturn(null); $response = new Response(); // Save RainTPL assigned variables @@ -208,6 +211,182 @@ class TagCloudControllerTest extends TestCase static::assertCount(0, $assignedVariables['tags']); } + /** + * Tag List - Default sort is by usage DESC + */ + public function testValidListControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $allTags = [ + 'def' => 12, + 'abc' => 3, + 'ghi' => 1, + ]; + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function () use ($allTags): array { + return $allTags; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_taglist', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(3, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->list($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.list', (string) $result->getBody()); + static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(3, $assignedVariables['tags']); + + foreach ($allTags as $tag => $count) { + static::assertSame($count, $assignedVariables['tags'][$tag]); + } + } + + /** + * Tag List - Additional parameters: + * - logged in + * - visibility private + * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) + * - sort alphabetically + */ + public function testValidListControllerInvokeWithParameters(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request + ->method('getQueryParam') + ->with() + ->willReturnCallback(function (string $key): ?string { + if ('searchtags' === $key) { + return 'ghi def'; + } elseif ('sort' === $key) { + return 'alpha'; + } + + return null; + }) + ; + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->loginManager->method('isLoggedin')->willReturn(true); + $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) + ->willReturnCallback(function (): array { + return ['abc' => 3]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_taglist', $hook); + static::assertSame('ghi def', $data['search_tags']); + static::assertCount(1, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->list($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.list', (string) $result->getBody()); + static::assertSame('ghi def - Tag list - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('ghi def', $assignedVariables['search_tags']); + static::assertCount(1, $assignedVariables['tags']); + static::assertSame(3, $assignedVariables['tags']['abc']); + } + + /** + * Tag List - empty + */ + public function testEmptyList(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_taglist', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(0, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->list($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.list', (string) $result->getBody()); + static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(0, $assignedVariables['tags']); + } + + protected function createValidContainerMockSet(): void { $loginManager = $this->createMock(LoginManager::class); -- cgit v1.2.3 From 69e29ff65ef56b886748c58ba5b037cf217c4a1d Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sun, 17 May 2020 11:06:39 +0200 Subject: Process daily page through Slim controller --- tests/front/controller/DailyControllerTest.php | 423 +++++++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100644 tests/front/controller/DailyControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/DailyControllerTest.php b/tests/front/controller/DailyControllerTest.php new file mode 100644 index 00000000..bb453d5b --- /dev/null +++ b/tests/front/controller/DailyControllerTest.php @@ -0,0 +1,423 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new DailyController($this->container); + } + + public function testValidControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $currentDay = new \DateTimeImmutable('2020-05-13'); + + $request = $this->createMock(Request::class); + $request->method('getQueryParam')->willReturn($currentDay->format('Ymd')); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function () use ($currentDay): array { + return [ + '20200510', + $currentDay->format('Ymd'), + '20200516', + ]; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return [ + (new Bookmark()) + ->setId(1) + ->setUrl('http://url.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + (new Bookmark()) + ->setId(2) + ->setUrl('http://url2.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + (new Bookmark()) + ->setId(3) + ->setUrl('http://url3.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + ]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { + static::assertSame('render_daily', $hook); + + static::assertArrayHasKey('linksToDisplay', $data); + static::assertCount(3, $data['linksToDisplay']); + static::assertSame(1, $data['linksToDisplay'][0]['id']); + static::assertSame($currentDay->getTimestamp(), $data['day']); + static::assertSame('20200510', $data['previousday']); + static::assertSame('20200516', $data['nextday']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertSame( + 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', + $assignedVariables['pagetitle'] + ); + static::assertCount(3, $assignedVariables['linksToDisplay']); + + $link = $assignedVariables['linksToDisplay'][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['linksToDisplay'][1]; + + static::assertSame(2, $link['id']); + static::assertSame('http://url2.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['linksToDisplay'][2]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + static::assertCount(3, $assignedVariables['cols']); + static::assertCount(1, $assignedVariables['cols'][0]); + static::assertCount(1, $assignedVariables['cols'][1]); + static::assertCount(1, $assignedVariables['cols'][2]); + + $link = $assignedVariables['cols'][0][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['cols'][1][0]; + + static::assertSame(2, $link['id']); + static::assertSame('http://url2.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['cols'][2][0]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + } + + /** + * Daily page - test that everything goes fine with no future or past bookmarks + */ + public function testValidControllerInvokeNoFutureOrPast(): void + { + $this->createValidContainerMockSet(); + + $currentDay = new \DateTimeImmutable('2020-05-13'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function () use ($currentDay): array { + return [ + $currentDay->format($currentDay->format('Ymd')), + ]; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return [ + (new Bookmark()) + ->setId(1) + ->setUrl('http://url.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + ]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { + static::assertSame('render_daily', $hook); + + static::assertArrayHasKey('linksToDisplay', $data); + static::assertCount(1, $data['linksToDisplay']); + static::assertSame(1, $data['linksToDisplay'][0]['id']); + static::assertSame($currentDay->getTimestamp(), $data['day']); + static::assertEmpty($data['previousday']); + static::assertEmpty($data['nextday']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertSame( + 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', + $assignedVariables['pagetitle'] + ); + static::assertCount(1, $assignedVariables['linksToDisplay']); + + $link = $assignedVariables['linksToDisplay'][0]; + static::assertSame(1, $link['id']); + } + + /** + * Daily page - test that height adjustment in columns is working + */ + public function testValidControllerInvokeHeightAdjustment(): void + { + $this->createValidContainerMockSet(); + + $currentDay = new \DateTimeImmutable('2020-05-13'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function () use ($currentDay): array { + return [ + $currentDay->format($currentDay->format('Ymd')), + ]; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return [ + (new Bookmark())->setId(1)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark()) + ->setId(2) + ->setUrl('http://url.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(5000)) + , + (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(5)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(6)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(7)->setUrl('http://url.tld')->setTitle('title'), + ]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertCount(7, $assignedVariables['linksToDisplay']); + + $columnIds = function (array $column): array { + return array_map(function (array $item): int { return $item['id']; }, $column); + }; + + static::assertSame([1, 4, 6], $columnIds($assignedVariables['cols'][0])); + static::assertSame([2], $columnIds($assignedVariables['cols'][1])); + static::assertSame([3, 5, 7], $columnIds($assignedVariables['cols'][2])); + } + + /** + * Daily page - no bookmark + */ + public function testValidControllerInvokeNoBookmark(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function (): array { + return []; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertCount(0, $assignedVariables['linksToDisplay']); + static::assertSame('Today', $assignedVariables['dayDesc']); + } + + protected function createValidContainerMockSet(): void + { + $loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager = $loginManager; + + // Config + $conf = $this->createMock(ConfigManager::class); + $this->container->conf = $conf; + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + return $default; + }); + + // PageBuilder + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + $this->container->pageBuilder = $pageBuilder; + + // Plugin Manager + $pluginManager = $this->createMock(PluginManager::class); + $this->container->pluginManager = $pluginManager; + + // BookmarkService + $bookmarkService = $this->createMock(BookmarkServiceInterface::class); + $this->container->bookmarkService = $bookmarkService; + + // Formatter + $formatterFactory = $this->createMock(FormatterFactory::class); + $formatterFactory + ->method('getFormatter') + ->willReturnCallback(function (): BookmarkFormatter { + return new BookmarkRawFormatter($this->container->conf, true); + }) + ; + $this->container->formatterFactory = $formatterFactory; + } + + protected function assignTemplateVars(array &$variables): void + { + $this->container->pageBuilder + ->expects(static::atLeastOnce()) + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$variables) { + $variables[$key] = $value; + + return $this; + }) + ; + } + + protected static function generateContent(int $length): string + { + // bin2hex(random_bytes) generates string twice as long as given parameter + $length = (int) ceil($length / 2); + return bin2hex(random_bytes($length)); + } +} -- cgit v1.2.3 From e3d28be9673a9f8404ff907b8191209729ad690c Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sun, 17 May 2020 11:29:17 +0200 Subject: Slim daily: minor bugfix with empty data --- tests/front/controller/DailyControllerTest.php | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests/front') diff --git a/tests/front/controller/DailyControllerTest.php b/tests/front/controller/DailyControllerTest.php index bb453d5b..2714bfd9 100644 --- a/tests/front/controller/DailyControllerTest.php +++ b/tests/front/controller/DailyControllerTest.php @@ -112,6 +112,8 @@ class DailyControllerTest extends TestCase 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', $assignedVariables['pagetitle'] ); + static::assertEquals($currentDay, $assignedVariables['dayDate']); + static::assertEquals($currentDay->getTimestamp(), $assignedVariables['day']); static::assertCount(3, $assignedVariables['linksToDisplay']); $link = $assignedVariables['linksToDisplay'][0]; @@ -358,6 +360,8 @@ class DailyControllerTest extends TestCase static::assertSame('daily', (string) $result->getBody()); static::assertCount(0, $assignedVariables['linksToDisplay']); static::assertSame('Today', $assignedVariables['dayDesc']); + static::assertEquals((new \DateTime())->setTime(0, 0)->getTimestamp(), $assignedVariables['day']); + static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']); } protected function createValidContainerMockSet(): void -- cgit v1.2.3 From c4d5be53c2ae503c00da3cfe6b28d0ce9d2ca7f5 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sun, 17 May 2020 14:16:32 +0200 Subject: Process Daily RSS feed through Slim controller The daily RSS template has been entirely rewritten to handle the whole feed through the template engine. --- tests/front/controller/DailyControllerTest.php | 152 ++++++++++++++++++++++++- 1 file changed, 148 insertions(+), 4 deletions(-) (limited to 'tests/front') diff --git a/tests/front/controller/DailyControllerTest.php b/tests/front/controller/DailyControllerTest.php index 2714bfd9..72a0339f 100644 --- a/tests/front/controller/DailyControllerTest.php +++ b/tests/front/controller/DailyControllerTest.php @@ -9,11 +9,13 @@ use Shaarli\Bookmark\Bookmark; use Shaarli\Bookmark\BookmarkServiceInterface; use Shaarli\Config\ConfigManager; use Shaarli\Container\ShaarliContainer; +use Shaarli\Feed\CachedPage; use Shaarli\Formatter\BookmarkFormatter; use Shaarli\Formatter\BookmarkRawFormatter; use Shaarli\Formatter\FormatterFactory; use Shaarli\Plugin\PluginManager; use Shaarli\Render\PageBuilder; +use Shaarli\Render\PageCacheManager; use Shaarli\Security\LoginManager; use Slim\Http\Request; use Slim\Http\Response; @@ -30,9 +32,10 @@ class DailyControllerTest extends TestCase { $this->container = $this->createMock(ShaarliContainer::class); $this->controller = new DailyController($this->container); + DailyController::$DAILY_RSS_NB_DAYS = 2; } - public function testValidControllerInvokeDefault(): void + public function testValidIndexControllerInvokeDefault(): void { $this->createValidContainerMockSet(); @@ -173,7 +176,7 @@ class DailyControllerTest extends TestCase /** * Daily page - test that everything goes fine with no future or past bookmarks */ - public function testValidControllerInvokeNoFutureOrPast(): void + public function testValidIndexControllerInvokeNoFutureOrPast(): void { $this->createValidContainerMockSet(); @@ -247,7 +250,7 @@ class DailyControllerTest extends TestCase /** * Daily page - test that height adjustment in columns is working */ - public function testValidControllerInvokeHeightAdjustment(): void + public function testValidIndexControllerInvokeHeightAdjustment(): void { $this->createValidContainerMockSet(); @@ -318,7 +321,7 @@ class DailyControllerTest extends TestCase /** * Daily page - no bookmark */ - public function testValidControllerInvokeNoBookmark(): void + public function testValidIndexControllerInvokeNoBookmark(): void { $this->createValidContainerMockSet(); @@ -364,6 +367,136 @@ class DailyControllerTest extends TestCase static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']); } + /** + * Daily RSS - default behaviour + */ + public function testValidRssControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $dates = [ + new \DateTimeImmutable('2020-05-17'), + new \DateTimeImmutable('2020-05-15'), + new \DateTimeImmutable('2020-05-13'), + ]; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ + (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), + (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), + (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), + (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'), + ]); + + $this->container->pageCacheManager + ->expects(static::once()) + ->method('getCachePage') + ->willReturnCallback(function (): CachedPage { + $cachedPage = $this->createMock(CachedPage::class); + $cachedPage->expects(static::once())->method('cache')->with('dailyrss'); + + return $cachedPage; + } + ); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('dailyrss', (string) $result->getBody()); + static::assertSame('Shaarli', $assignedVariables['title']); + static::assertSame('http://shaarli', $assignedVariables['index_url']); + static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); + static::assertFalse($assignedVariables['hide_timestamps']); + static::assertCount(2, $assignedVariables['days']); + + $day = $assignedVariables['days'][$dates[0]->format('Ymd')]; + + static::assertEquals($dates[0], $day['date']); + static::assertSame($dates[0]->format(\DateTimeInterface::RSS), $day['date_rss']); + static::assertSame(format_date($dates[0], false), $day['date_human']); + static::assertSame('http://shaarli/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']); + static::assertCount(1, $day['links']); + static::assertSame(1, $day['links'][0]['id']); + static::assertSame('http://domain.tld/1', $day['links'][0]['url']); + static::assertEquals($dates[0], $day['links'][0]['created']); + + $day = $assignedVariables['days'][$dates[1]->format('Ymd')]; + + static::assertEquals($dates[1], $day['date']); + static::assertSame($dates[1]->format(\DateTimeInterface::RSS), $day['date_rss']); + static::assertSame(format_date($dates[1], false), $day['date_human']); + static::assertSame('http://shaarli/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']); + static::assertCount(2, $day['links']); + + static::assertSame(2, $day['links'][0]['id']); + static::assertSame('http://domain.tld/2', $day['links'][0]['url']); + static::assertEquals($dates[1], $day['links'][0]['created']); + static::assertSame(3, $day['links'][1]['id']); + static::assertSame('http://domain.tld/3', $day['links'][1]['url']); + static::assertEquals($dates[1], $day['links'][1]['created']); + } + + /** + * Daily RSS - trigger cache rendering + */ + public function testValidRssControllerInvokeTriggerCache(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->pageCacheManager->method('getCachePage')->willReturnCallback(function (): CachedPage { + $cachedPage = $this->createMock(CachedPage::class); + $cachedPage->method('cachedVersion')->willReturn('this is cache!'); + + return $cachedPage; + }); + + $this->container->bookmarkService->expects(static::never())->method('search'); + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('this is cache!', (string) $result->getBody()); + } + + /** + * Daily RSS - No bookmark + */ + public function testValidRssControllerInvokeNoBookmark(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([]); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('dailyrss', (string) $result->getBody()); + static::assertSame('Shaarli', $assignedVariables['title']); + static::assertSame('http://shaarli', $assignedVariables['index_url']); + static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); + static::assertFalse($assignedVariables['hide_timestamps']); + static::assertCount(0, $assignedVariables['days']); + } + protected function createValidContainerMockSet(): void { $loginManager = $this->createMock(LoginManager::class); @@ -403,6 +536,17 @@ class DailyControllerTest extends TestCase }) ; $this->container->formatterFactory = $formatterFactory; + + // CacheManager + $pageCacheManager = $this->createMock(PageCacheManager::class); + $this->container->pageCacheManager = $pageCacheManager; + + // $_SERVER + $this->container->environment = [ + 'SERVER_NAME' => 'shaarli', + 'SERVER_PORT' => '80', + 'REQUEST_URI' => '/daily-rss', + ]; } protected function assignTemplateVars(array &$variables): void -- cgit v1.2.3 From 029ada5a071240fd10f3557fd3c0fc865c54c5a8 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sun, 17 May 2020 15:45:26 +0200 Subject: PHP 7.1 compatibility --- tests/front/controller/DailyControllerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/front') diff --git a/tests/front/controller/DailyControllerTest.php b/tests/front/controller/DailyControllerTest.php index 72a0339f..88ec116b 100644 --- a/tests/front/controller/DailyControllerTest.php +++ b/tests/front/controller/DailyControllerTest.php @@ -419,7 +419,7 @@ class DailyControllerTest extends TestCase $day = $assignedVariables['days'][$dates[0]->format('Ymd')]; static::assertEquals($dates[0], $day['date']); - static::assertSame($dates[0]->format(\DateTimeInterface::RSS), $day['date_rss']); + static::assertSame($dates[0]->format(\DateTime::RSS), $day['date_rss']); static::assertSame(format_date($dates[0], false), $day['date_human']); static::assertSame('http://shaarli/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']); static::assertCount(1, $day['links']); @@ -430,7 +430,7 @@ class DailyControllerTest extends TestCase $day = $assignedVariables['days'][$dates[1]->format('Ymd')]; static::assertEquals($dates[1], $day['date']); - static::assertSame($dates[1]->format(\DateTimeInterface::RSS), $day['date_rss']); + static::assertSame($dates[1]->format(\DateTime::RSS), $day['date_rss']); static::assertSame(format_date($dates[1], false), $day['date_human']); static::assertSame('http://shaarli/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']); static::assertCount(2, $day['links']); -- cgit v1.2.3 From 7b2ba6ef820335df682fbe3dcfaceef3a62cf4a5 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Mon, 18 May 2020 17:17:36 +0200 Subject: RSS/ATOM feeds: process through Slim controller --- tests/front/controller/FeedControllerTest.php | 219 ++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 tests/front/controller/FeedControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/FeedControllerTest.php b/tests/front/controller/FeedControllerTest.php new file mode 100644 index 00000000..d4cc5536 --- /dev/null +++ b/tests/front/controller/FeedControllerTest.php @@ -0,0 +1,219 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new FeedController($this->container); + } + + /** + * Feed Controller - RSS default behaviour + */ + public function testDefaultRssController(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->feedBuilder->expects(static::once())->method('setLocale'); + $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); + $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): void { + static::assertSame('render_feed', $hook); + static::assertSame('data', $data['content']); + + static::assertArrayHasKey('loggedin', $param); + static::assertSame('rss', $param['target']); + }) + ; + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('feed.rss', (string) $result->getBody()); + static::assertSame('data', $assignedVariables['content']); + } + + /** + * Feed Controller - ATOM default behaviour + */ + public function testDefaultAtomController(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->feedBuilder->expects(static::once())->method('setLocale'); + $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); + $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): void { + static::assertSame('render_feed', $hook); + static::assertSame('data', $data['content']); + + static::assertArrayHasKey('loggedin', $param); + static::assertSame('atom', $param['target']); + }) + ; + + $result = $this->controller->atom($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); + static::assertSame('feed.atom', (string) $result->getBody()); + static::assertSame('data', $assignedVariables['content']); + } + + /** + * Feed Controller - ATOM with parameters + */ + public function testAtomControllerWithParameters(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->method('getParams')->willReturn(['parameter' => 'value']); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->feedBuilder + ->method('buildData') + ->with('atom', ['parameter' => 'value']) + ->willReturn(['content' => 'data']) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): void { + static::assertSame('render_feed', $hook); + static::assertSame('data', $data['content']); + + static::assertArrayHasKey('loggedin', $param); + static::assertSame('atom', $param['target']); + }) + ; + + $result = $this->controller->atom($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); + static::assertSame('feed.atom', (string) $result->getBody()); + static::assertSame('data', $assignedVariables['content']); + } + + protected function createValidContainerMockSet(): void + { + $loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager = $loginManager; + + // Config + $conf = $this->createMock(ConfigManager::class); + $this->container->conf = $conf; + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + return $default; + }); + + // PageBuilder + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + $this->container->pageBuilder = $pageBuilder; + + $bookmarkService = $this->createMock(BookmarkServiceInterface::class); + $this->container->bookmarkService = $bookmarkService; + + // Plugin Manager + $pluginManager = $this->createMock(PluginManager::class); + $this->container->pluginManager = $pluginManager; + + // Formatter + $formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory = $formatterFactory; + + // CacheManager + $pageCacheManager = $this->createMock(PageCacheManager::class); + $this->container->pageCacheManager = $pageCacheManager; + + // FeedBuilder + $feedBuilder = $this->createMock(FeedBuilder::class); + $this->container->feedBuilder = $feedBuilder; + + // $_SERVER + $this->container->environment = [ + 'SERVER_NAME' => 'shaarli', + 'SERVER_PORT' => '80', + 'REQUEST_URI' => '/daily-rss', + ]; + } + + protected function assignTemplateVars(array &$variables): void + { + $this->container->pageBuilder + ->expects(static::atLeastOnce()) + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$variables) { + $variables[$key] = $value; + + return $this; + }) + ; + } +} -- cgit v1.2.3 From 5ec4708ced1cdca01eddd7e52377ab5e5f8b3290 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 20 May 2020 10:47:20 +0200 Subject: Process OpenSearch controller through Slim Also it was missing on the default template feeds --- .../front/controller/OpenSearchControllerTest.php | 92 ++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 tests/front/controller/OpenSearchControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/OpenSearchControllerTest.php b/tests/front/controller/OpenSearchControllerTest.php new file mode 100644 index 00000000..7ba0f7df --- /dev/null +++ b/tests/front/controller/OpenSearchControllerTest.php @@ -0,0 +1,92 @@ +container = $this->createMock(ShaarliContainer::class); + $this->controller = new OpenSearchController($this->container); + } + + public function testOpenSearchController(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/xml', $result->getHeader('Content-Type')[0]); + static::assertSame('opensearch', (string) $result->getBody()); + static::assertSame('http://shaarli', $assignedVariables['serverurl']); + } + + protected function createValidContainerMockSet(): void + { + $loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager = $loginManager; + + // PageBuilder + $pageBuilder = $this->createMock(PageBuilder::class); + $pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + $this->container->pageBuilder = $pageBuilder; + + $bookmarkService = $this->createMock(BookmarkServiceInterface::class); + $this->container->bookmarkService = $bookmarkService; + + // Plugin Manager + $pluginManager = $this->createMock(PluginManager::class); + $this->container->pluginManager = $pluginManager; + + // $_SERVER + $this->container->environment = [ + 'SERVER_NAME' => 'shaarli', + 'SERVER_PORT' => '80', + 'REQUEST_URI' => '/open-search', + ]; + } + + protected function assignTemplateVars(array &$variables): void + { + $this->container->pageBuilder + ->expects(static::atLeastOnce()) + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$variables) { + $variables[$key] = $value; + + return $this; + }) + ; + } +} -- cgit v1.2.3 From dd09ec52b20b4a548ecf5c847627575e506e3a50 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 20 May 2020 12:43:40 +0200 Subject: Refactor front controller tests to create container mock using a trait --- tests/front/controller/DailyControllerTest.php | 84 +-------------- tests/front/controller/FeedControllerTest.php | 78 +------------- .../front/controller/FrontControllerMockHelper.php | 114 +++++++++++++++++++++ tests/front/controller/LoginControllerTest.php | 58 +++-------- tests/front/controller/LogoutControllerTest.php | 19 ++-- .../front/controller/OpenSearchControllerTest.php | 60 ++--------- .../front/controller/PictureWallControllerTest.php | 65 +----------- tests/front/controller/ShaarliControllerTest.php | 68 +++++------- tests/front/controller/TagCloudControllerTest.php | 62 +---------- tests/front/controller/TagControllerTest.php | 49 ++------- 10 files changed, 192 insertions(+), 465 deletions(-) create mode 100644 tests/front/controller/FrontControllerMockHelper.php (limited to 'tests/front') diff --git a/tests/front/controller/DailyControllerTest.php b/tests/front/controller/DailyControllerTest.php index 88ec116b..7ec99030 100644 --- a/tests/front/controller/DailyControllerTest.php +++ b/tests/front/controller/DailyControllerTest.php @@ -6,31 +6,21 @@ namespace Shaarli\Front\Controller; use PHPUnit\Framework\TestCase; use Shaarli\Bookmark\Bookmark; -use Shaarli\Bookmark\BookmarkServiceInterface; -use Shaarli\Config\ConfigManager; -use Shaarli\Container\ShaarliContainer; use Shaarli\Feed\CachedPage; -use Shaarli\Formatter\BookmarkFormatter; -use Shaarli\Formatter\BookmarkRawFormatter; -use Shaarli\Formatter\FormatterFactory; -use Shaarli\Plugin\PluginManager; -use Shaarli\Render\PageBuilder; -use Shaarli\Render\PageCacheManager; -use Shaarli\Security\LoginManager; use Slim\Http\Request; use Slim\Http\Response; class DailyControllerTest extends TestCase { - /** @var ShaarliContainer */ - protected $container; + use FrontControllerMockHelper; /** @var DailyController */ protected $controller; public function setUp(): void { - $this->container = $this->createMock(ShaarliContainer::class); + $this->createContainer(); + $this->controller = new DailyController($this->container); DailyController::$DAILY_RSS_NB_DAYS = 2; } @@ -105,7 +95,8 @@ class DailyControllerTest extends TestCase static::assertArrayHasKey('loggedin', $param); return $data; - }); + }) + ; $result = $this->controller->index($request, $response); @@ -497,71 +488,6 @@ class DailyControllerTest extends TestCase static::assertCount(0, $assignedVariables['days']); } - protected function createValidContainerMockSet(): void - { - $loginManager = $this->createMock(LoginManager::class); - $this->container->loginManager = $loginManager; - - // Config - $conf = $this->createMock(ConfigManager::class); - $this->container->conf = $conf; - $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { - return $default; - }); - - // PageBuilder - $pageBuilder = $this->createMock(PageBuilder::class); - $pageBuilder - ->method('render') - ->willReturnCallback(function (string $template): string { - return $template; - }) - ; - $this->container->pageBuilder = $pageBuilder; - - // Plugin Manager - $pluginManager = $this->createMock(PluginManager::class); - $this->container->pluginManager = $pluginManager; - - // BookmarkService - $bookmarkService = $this->createMock(BookmarkServiceInterface::class); - $this->container->bookmarkService = $bookmarkService; - - // Formatter - $formatterFactory = $this->createMock(FormatterFactory::class); - $formatterFactory - ->method('getFormatter') - ->willReturnCallback(function (): BookmarkFormatter { - return new BookmarkRawFormatter($this->container->conf, true); - }) - ; - $this->container->formatterFactory = $formatterFactory; - - // CacheManager - $pageCacheManager = $this->createMock(PageCacheManager::class); - $this->container->pageCacheManager = $pageCacheManager; - - // $_SERVER - $this->container->environment = [ - 'SERVER_NAME' => 'shaarli', - 'SERVER_PORT' => '80', - 'REQUEST_URI' => '/daily-rss', - ]; - } - - protected function assignTemplateVars(array &$variables): void - { - $this->container->pageBuilder - ->expects(static::atLeastOnce()) - ->method('assign') - ->willReturnCallback(function ($key, $value) use (&$variables) { - $variables[$key] = $value; - - return $this; - }) - ; - } - protected static function generateContent(int $length): string { // bin2hex(random_bytes) generates string twice as long as given parameter diff --git a/tests/front/controller/FeedControllerTest.php b/tests/front/controller/FeedControllerTest.php index d4cc5536..7e8657e2 100644 --- a/tests/front/controller/FeedControllerTest.php +++ b/tests/front/controller/FeedControllerTest.php @@ -5,29 +5,23 @@ declare(strict_types=1); namespace Shaarli\Front\Controller; use PHPUnit\Framework\TestCase; -use Shaarli\Bookmark\BookmarkServiceInterface; -use Shaarli\Config\ConfigManager; -use Shaarli\Container\ShaarliContainer; use Shaarli\Feed\FeedBuilder; -use Shaarli\Formatter\FormatterFactory; -use Shaarli\Plugin\PluginManager; -use Shaarli\Render\PageBuilder; -use Shaarli\Render\PageCacheManager; -use Shaarli\Security\LoginManager; use Slim\Http\Request; use Slim\Http\Response; class FeedControllerTest extends TestCase { - /** @var ShaarliContainer */ - protected $container; + use FrontControllerMockHelper; /** @var FeedController */ protected $controller; public function setUp(): void { - $this->container = $this->createMock(ShaarliContainer::class); + $this->createContainer(); + + $this->container->feedBuilder = $this->createMock(FeedBuilder::class); + $this->controller = new FeedController($this->container); } @@ -154,66 +148,4 @@ class FeedControllerTest extends TestCase static::assertSame('feed.atom', (string) $result->getBody()); static::assertSame('data', $assignedVariables['content']); } - - protected function createValidContainerMockSet(): void - { - $loginManager = $this->createMock(LoginManager::class); - $this->container->loginManager = $loginManager; - - // Config - $conf = $this->createMock(ConfigManager::class); - $this->container->conf = $conf; - $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { - return $default; - }); - - // PageBuilder - $pageBuilder = $this->createMock(PageBuilder::class); - $pageBuilder - ->method('render') - ->willReturnCallback(function (string $template): string { - return $template; - }) - ; - $this->container->pageBuilder = $pageBuilder; - - $bookmarkService = $this->createMock(BookmarkServiceInterface::class); - $this->container->bookmarkService = $bookmarkService; - - // Plugin Manager - $pluginManager = $this->createMock(PluginManager::class); - $this->container->pluginManager = $pluginManager; - - // Formatter - $formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory = $formatterFactory; - - // CacheManager - $pageCacheManager = $this->createMock(PageCacheManager::class); - $this->container->pageCacheManager = $pageCacheManager; - - // FeedBuilder - $feedBuilder = $this->createMock(FeedBuilder::class); - $this->container->feedBuilder = $feedBuilder; - - // $_SERVER - $this->container->environment = [ - 'SERVER_NAME' => 'shaarli', - 'SERVER_PORT' => '80', - 'REQUEST_URI' => '/daily-rss', - ]; - } - - protected function assignTemplateVars(array &$variables): void - { - $this->container->pageBuilder - ->expects(static::atLeastOnce()) - ->method('assign') - ->willReturnCallback(function ($key, $value) use (&$variables) { - $variables[$key] = $value; - - return $this; - }) - ; - } } diff --git a/tests/front/controller/FrontControllerMockHelper.php b/tests/front/controller/FrontControllerMockHelper.php new file mode 100644 index 00000000..b65607e7 --- /dev/null +++ b/tests/front/controller/FrontControllerMockHelper.php @@ -0,0 +1,114 @@ +container = $this->createMock(ShaarliTestContainer::class); + } + + /** + * Initialize container's services used by tests + */ + protected function createValidContainerMockSet(): void + { + $this->container->loginManager = $this->createMock(LoginManager::class); + + // Config + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + return $default; + }); + + // PageBuilder + $this->container->pageBuilder = $this->createMock(PageBuilder::class); + $this->container->pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + + // Plugin Manager + $this->container->pluginManager = $this->createMock(PluginManager::class); + + // BookmarkService + $this->container->bookmarkService = $this->createMock(BookmarkServiceInterface::class); + + // Formatter + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->method('getFormatter') + ->willReturnCallback(function (): BookmarkFormatter { + return new BookmarkRawFormatter($this->container->conf, true); + }) + ; + + // CacheManager + $this->container->pageCacheManager = $this->createMock(PageCacheManager::class); + + // SessionManager + $this->container->sessionManager = $this->createMock(SessionManager::class); + + // $_SERVER + $this->container->environment = [ + 'SERVER_NAME' => 'shaarli', + 'SERVER_PORT' => '80', + 'REQUEST_URI' => '/daily-rss', + ]; + } + + /** + * Pass a reference of an array which will be populated by `pageBuilder->assign` calls during execution. + * + * @param mixed $variables Array reference to populate. + */ + protected function assignTemplateVars(array &$variables): void + { + $this->container->pageBuilder + ->expects(static::atLeastOnce()) + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$variables) { + $variables[$key] = $value; + + return $this; + }) + ; + } + + /** + * Force to be used in PHPUnit context. + */ + protected abstract function createMock($originalClassName): MockObject; +} diff --git a/tests/front/controller/LoginControllerTest.php b/tests/front/controller/LoginControllerTest.php index 8cf8ece7..21937f3c 100644 --- a/tests/front/controller/LoginControllerTest.php +++ b/tests/front/controller/LoginControllerTest.php @@ -5,27 +5,22 @@ declare(strict_types=1); namespace Shaarli\Front\Controller; use PHPUnit\Framework\TestCase; -use Shaarli\Bookmark\BookmarkServiceInterface; use Shaarli\Config\ConfigManager; -use Shaarli\Container\ShaarliContainer; use Shaarli\Front\Exception\LoginBannedException; -use Shaarli\Plugin\PluginManager; -use Shaarli\Render\PageBuilder; -use Shaarli\Security\LoginManager; use Slim\Http\Request; use Slim\Http\Response; class LoginControllerTest extends TestCase { - /** @var ShaarliContainer */ - protected $container; + use FrontControllerMockHelper; /** @var LoginController */ protected $controller; public function setUp(): void { - $this->container = $this->createMock(ShaarliContainer::class); + $this->createContainer(); + $this->controller = new LoginController($this->container); } @@ -47,6 +42,8 @@ class LoginControllerTest extends TestCase }) ; + $this->container->loginManager->method('canLogin')->willReturn(true); + $result = $this->controller->index($request, $response); static::assertInstanceOf(Response::class, $result); @@ -77,6 +74,8 @@ class LoginControllerTest extends TestCase }) ; + $this->container->loginManager->expects(static::once())->method('canLogin')->willReturn(true); + $result = $this->controller->index($request, $response); static::assertInstanceOf(Response::class, $result); @@ -91,12 +90,12 @@ class LoginControllerTest extends TestCase public function testLoginControllerWhileLoggedIn(): void { + $this->createValidContainerMockSet(); + $request = $this->createMock(Request::class); $response = new Response(); - $loginManager = $this->createMock(LoginManager::class); - $loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true); - $this->container->loginManager = $loginManager; + $this->container->loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true); $result = $this->controller->index($request, $response); @@ -135,44 +134,11 @@ class LoginControllerTest extends TestCase $request = $this->createMock(Request::class); $response = new Response(); - $loginManager = $this->createMock(LoginManager::class); - $loginManager->method('isLoggedIn')->willReturn(false); - $loginManager->method('canLogin')->willReturn(false); - $this->container->loginManager = $loginManager; + $this->container->loginManager->method('isLoggedIn')->willReturn(false); + $this->container->loginManager->method('canLogin')->willReturn(false); $this->expectException(LoginBannedException::class); $this->controller->index($request, $response); } - - protected function createValidContainerMockSet(): void - { - // User logged out - $loginManager = $this->createMock(LoginManager::class); - $loginManager->method('isLoggedIn')->willReturn(false); - $loginManager->method('canLogin')->willReturn(true); - $this->container->loginManager = $loginManager; - - // Config - $conf = $this->createMock(ConfigManager::class); - $conf->method('get')->willReturnCallback(function (string $parameter, $default) { - return $default; - }); - $this->container->conf = $conf; - - // PageBuilder - $pageBuilder = $this->createMock(PageBuilder::class); - $pageBuilder - ->method('render') - ->willReturnCallback(function (string $template): string { - return $template; - }) - ; - $this->container->pageBuilder = $pageBuilder; - - $pluginManager = $this->createMock(PluginManager::class); - $this->container->pluginManager = $pluginManager; - $bookmarkService = $this->createMock(BookmarkServiceInterface::class); - $this->container->bookmarkService = $bookmarkService; - } } diff --git a/tests/front/controller/LogoutControllerTest.php b/tests/front/controller/LogoutControllerTest.php index d9ca1c25..8e01c367 100644 --- a/tests/front/controller/LogoutControllerTest.php +++ b/tests/front/controller/LogoutControllerTest.php @@ -12,8 +12,6 @@ if (!function_exists('Shaarli\Front\Controller\setcookie')) { } use PHPUnit\Framework\TestCase; -use Shaarli\Container\ShaarliContainer; -use Shaarli\Render\PageCacheManager; use Shaarli\Security\LoginManager; use Shaarli\Security\SessionManager; use Slim\Http\Request; @@ -21,15 +19,15 @@ use Slim\Http\Response; class LogoutControllerTest extends TestCase { - /** @var ShaarliContainer */ - protected $container; + use FrontControllerMockHelper; /** @var LogoutController */ protected $controller; public function setUp(): void { - $this->container = $this->createMock(ShaarliContainer::class); + $this->createContainer(); + $this->controller = new LogoutController($this->container); setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, $cookie = 'hi there'); @@ -37,16 +35,15 @@ class LogoutControllerTest extends TestCase public function testValidControllerInvoke(): void { + $this->createValidContainerMockSet(); + $request = $this->createMock(Request::class); $response = new Response(); - $pageCacheManager = $this->createMock(PageCacheManager::class); - $pageCacheManager->expects(static::once())->method('invalidateCaches'); - $this->container->pageCacheManager = $pageCacheManager; + $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches'); - $sessionManager = $this->createMock(SessionManager::class); - $sessionManager->expects(static::once())->method('logout'); - $this->container->sessionManager = $sessionManager; + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->expects(static::once())->method('logout'); static::assertSame('hi there', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); diff --git a/tests/front/controller/OpenSearchControllerTest.php b/tests/front/controller/OpenSearchControllerTest.php index 7ba0f7df..f3b6f439 100644 --- a/tests/front/controller/OpenSearchControllerTest.php +++ b/tests/front/controller/OpenSearchControllerTest.php @@ -5,26 +5,22 @@ declare(strict_types=1); namespace front\controller; use PHPUnit\Framework\TestCase; -use Shaarli\Bookmark\BookmarkServiceInterface; -use Shaarli\Container\ShaarliContainer; +use Shaarli\Front\Controller\FrontControllerMockHelper; use Shaarli\Front\Controller\OpenSearchController; -use Shaarli\Plugin\PluginManager; -use Shaarli\Render\PageBuilder; -use Shaarli\Security\LoginManager; use Slim\Http\Request; use Slim\Http\Response; class OpenSearchControllerTest extends TestCase { - /** @var ShaarliContainer */ - protected $container; + use FrontControllerMockHelper; /** @var OpenSearchController */ protected $controller; public function setUp(): void { - $this->container = $this->createMock(ShaarliContainer::class); + $this->createContainer(); + $this->controller = new OpenSearchController($this->container); } @@ -42,51 +38,11 @@ class OpenSearchControllerTest extends TestCase $result = $this->controller->index($request, $response); static::assertSame(200, $result->getStatusCode()); - static::assertStringContainsString('application/xml', $result->getHeader('Content-Type')[0]); + static::assertStringContainsString( + 'application/opensearchdescription+xml', + $result->getHeader('Content-Type')[0] + ); static::assertSame('opensearch', (string) $result->getBody()); static::assertSame('http://shaarli', $assignedVariables['serverurl']); } - - protected function createValidContainerMockSet(): void - { - $loginManager = $this->createMock(LoginManager::class); - $this->container->loginManager = $loginManager; - - // PageBuilder - $pageBuilder = $this->createMock(PageBuilder::class); - $pageBuilder - ->method('render') - ->willReturnCallback(function (string $template): string { - return $template; - }) - ; - $this->container->pageBuilder = $pageBuilder; - - $bookmarkService = $this->createMock(BookmarkServiceInterface::class); - $this->container->bookmarkService = $bookmarkService; - - // Plugin Manager - $pluginManager = $this->createMock(PluginManager::class); - $this->container->pluginManager = $pluginManager; - - // $_SERVER - $this->container->environment = [ - 'SERVER_NAME' => 'shaarli', - 'SERVER_PORT' => '80', - 'REQUEST_URI' => '/open-search', - ]; - } - - protected function assignTemplateVars(array &$variables): void - { - $this->container->pageBuilder - ->expects(static::atLeastOnce()) - ->method('assign') - ->willReturnCallback(function ($key, $value) use (&$variables) { - $variables[$key] = $value; - - return $this; - }) - ; - } } diff --git a/tests/front/controller/PictureWallControllerTest.php b/tests/front/controller/PictureWallControllerTest.php index 63802abd..8160bb38 100644 --- a/tests/front/controller/PictureWallControllerTest.php +++ b/tests/front/controller/PictureWallControllerTest.php @@ -6,31 +6,23 @@ namespace Shaarli\Front\Controller; use PHPUnit\Framework\TestCase; use Shaarli\Bookmark\Bookmark; -use Shaarli\Bookmark\BookmarkServiceInterface; use Shaarli\Config\ConfigManager; -use Shaarli\Container\ShaarliContainer; -use Shaarli\Formatter\BookmarkFormatter; -use Shaarli\Formatter\BookmarkRawFormatter; -use Shaarli\Formatter\FormatterFactory; use Shaarli\Front\Exception\ThumbnailsDisabledException; -use Shaarli\Plugin\PluginManager; -use Shaarli\Render\PageBuilder; -use Shaarli\Security\LoginManager; use Shaarli\Thumbnailer; use Slim\Http\Request; use Slim\Http\Response; class PictureWallControllerTest extends TestCase { - /** @var ShaarliContainer */ - protected $container; + use FrontControllerMockHelper; /** @var PictureWallController */ protected $controller; public function setUp(): void { - $this->container = $this->createMock(ShaarliContainer::class); + $this->createContainer(); + $this->controller = new PictureWallController($this->container); } @@ -43,6 +35,7 @@ class PictureWallControllerTest extends TestCase $response = new Response(); // ConfigManager: thumbnails are enabled + $this->container->conf = $this->createMock(ConfigManager::class); $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { if ($parameter === 'thumbnails.mode') { return Thumbnailer::MODE_COMMON; @@ -53,15 +46,7 @@ class PictureWallControllerTest extends TestCase // Save RainTPL assigned variables $assignedVariables = []; - $this->container->pageBuilder - ->expects(static::atLeastOnce()) - ->method('assign') - ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { - $assignedVariables[$key] = $value; - - return $this; - }) - ; + $this->assignTemplateVars($assignedVariables); // Links dataset: 2 links with thumbnails $this->container->bookmarkService @@ -137,44 +122,4 @@ class PictureWallControllerTest extends TestCase $this->controller->index($request, $response); } - - protected function createValidContainerMockSet(): void - { - $loginManager = $this->createMock(LoginManager::class); - $this->container->loginManager = $loginManager; - - // Config - $conf = $this->createMock(ConfigManager::class); - $this->container->conf = $conf; - - // PageBuilder - $pageBuilder = $this->createMock(PageBuilder::class); - $pageBuilder - ->method('render') - ->willReturnCallback(function (string $template): string { - return $template; - }) - ; - $this->container->pageBuilder = $pageBuilder; - - // Plugin Manager - $pluginManager = $this->createMock(PluginManager::class); - $this->container->pluginManager = $pluginManager; - - // BookmarkService - $bookmarkService = $this->createMock(BookmarkServiceInterface::class); - $this->container->bookmarkService = $bookmarkService; - - // Formatter - $formatterFactory = $this->createMock(FormatterFactory::class); - $formatterFactory - ->method('getFormatter') - ->willReturnCallback(function (string $type): BookmarkFormatter { - if ($type === 'raw') { - return new BookmarkRawFormatter($this->container->conf, true); - } - }) - ; - $this->container->formatterFactory = $formatterFactory; - } } diff --git a/tests/front/controller/ShaarliControllerTest.php b/tests/front/controller/ShaarliControllerTest.php index 6fa3feb9..3efe4d95 100644 --- a/tests/front/controller/ShaarliControllerTest.php +++ b/tests/front/controller/ShaarliControllerTest.php @@ -6,11 +6,6 @@ namespace Shaarli\Front\Controller; use PHPUnit\Framework\TestCase; use Shaarli\Bookmark\BookmarkFilter; -use Shaarli\Bookmark\BookmarkServiceInterface; -use Shaarli\Container\ShaarliContainer; -use Shaarli\Plugin\PluginManager; -use Shaarli\Render\PageBuilder; -use Shaarli\Security\LoginManager; /** * Class ShaarliControllerTest @@ -20,8 +15,7 @@ use Shaarli\Security\LoginManager; */ class ShaarliControllerTest extends TestCase { - /** @var ShaarliContainer */ - protected $container; + use FrontControllerMockHelper; /** @var LoginController */ protected $controller; @@ -31,7 +25,8 @@ class ShaarliControllerTest extends TestCase public function setUp(): void { - $this->container = $this->createMock(ShaarliContainer::class); + $this->createContainer(); + $this->controller = new class($this->container) extends ShaarliController { public function assignView(string $key, $value): ShaarliController @@ -51,6 +46,8 @@ class ShaarliControllerTest extends TestCase { $this->createValidContainerMockSet(); + $this->assignTemplateVars($this->assignedValues); + $self = $this->controller->assignView('variableName', 'variableValue'); static::assertInstanceOf(ShaarliController::class, $self); @@ -61,6 +58,24 @@ class ShaarliControllerTest extends TestCase { $this->createValidContainerMockSet(); + $this->assignTemplateVars($this->assignedValues); + + $this->container->bookmarkService + ->method('count') + ->willReturnCallback(function (string $visibility): int { + return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; + }) + ; + + $this->container->pluginManager + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array &$data, array $params): array { + return $data[$hook] = $params; + }); + $this->container->pluginManager->method('getErrors')->willReturn(['error']); + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $render = $this->controller->render('templateName'); static::assertSame('templateName', $render); @@ -76,41 +91,4 @@ class ShaarliControllerTest extends TestCase static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); } - - protected function createValidContainerMockSet(): void - { - $pageBuilder = $this->createMock(PageBuilder::class); - $pageBuilder - ->method('assign') - ->willReturnCallback(function (string $key, $value): void { - $this->assignedValues[$key] = $value; - }); - $pageBuilder - ->method('render') - ->willReturnCallback(function (string $template): string { - return $template; - }); - $this->container->pageBuilder = $pageBuilder; - - $bookmarkService = $this->createMock(BookmarkServiceInterface::class); - $bookmarkService - ->method('count') - ->willReturnCallback(function (string $visibility): int { - return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; - }); - $this->container->bookmarkService = $bookmarkService; - - $pluginManager = $this->createMock(PluginManager::class); - $pluginManager - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array &$data, array $params): array { - return $data[$hook] = $params; - }); - $pluginManager->method('getErrors')->willReturn(['error']); - $this->container->pluginManager = $pluginManager; - - $loginManager = $this->createMock(LoginManager::class); - $loginManager->method('isLoggedIn')->willReturn(true); - $this->container->loginManager = $loginManager; - } } diff --git a/tests/front/controller/TagCloudControllerTest.php b/tests/front/controller/TagCloudControllerTest.php index 719610d7..8c27900d 100644 --- a/tests/front/controller/TagCloudControllerTest.php +++ b/tests/front/controller/TagCloudControllerTest.php @@ -6,27 +6,20 @@ namespace Shaarli\Front\Controller; use PHPUnit\Framework\TestCase; use Shaarli\Bookmark\BookmarkFilter; -use Shaarli\Bookmark\BookmarkServiceInterface; -use Shaarli\Config\ConfigManager; -use Shaarli\Container\ShaarliContainer; -use Shaarli\Plugin\PluginManager; -use Shaarli\Render\PageBuilder; -use Shaarli\Security\LoginManager; -use Shaarli\Security\SessionManager; use Slim\Http\Request; use Slim\Http\Response; class TagCloudControllerTest extends TestCase { - /** @var ShaarliContainer */ - protected $container; + use FrontControllerMockHelper; /** @var TagCloudController */ protected $controller; public function setUp(): void { - $this->container = $this->createMock(ShaarliContainer::class); + $this->createContainer(); + $this->controller = new TagCloudController($this->container); } @@ -385,53 +378,4 @@ class TagCloudControllerTest extends TestCase static::assertSame('', $assignedVariables['search_tags']); static::assertCount(0, $assignedVariables['tags']); } - - - protected function createValidContainerMockSet(): void - { - $loginManager = $this->createMock(LoginManager::class); - $this->container->loginManager = $loginManager; - - $sessionManager = $this->createMock(SessionManager::class); - $this->container->sessionManager = $sessionManager; - - // Config - $conf = $this->createMock(ConfigManager::class); - $this->container->conf = $conf; - - $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { - return $default; - }); - - // PageBuilder - $pageBuilder = $this->createMock(PageBuilder::class); - $pageBuilder - ->method('render') - ->willReturnCallback(function (string $template): string { - return $template; - }) - ; - $this->container->pageBuilder = $pageBuilder; - - // Plugin Manager - $pluginManager = $this->createMock(PluginManager::class); - $this->container->pluginManager = $pluginManager; - - // BookmarkService - $bookmarkService = $this->createMock(BookmarkServiceInterface::class); - $this->container->bookmarkService = $bookmarkService; - } - - protected function assignTemplateVars(array &$variables): void - { - $this->container->pageBuilder - ->expects(static::atLeastOnce()) - ->method('assign') - ->willReturnCallback(function ($key, $value) use (&$variables) { - $variables[$key] = $value; - - return $this; - }) - ; - } } diff --git a/tests/front/controller/TagControllerTest.php b/tests/front/controller/TagControllerTest.php index bbac5652..5eea537b 100644 --- a/tests/front/controller/TagControllerTest.php +++ b/tests/front/controller/TagControllerTest.php @@ -5,32 +5,27 @@ declare(strict_types=1); namespace Shaarli\Front\Controller; use PHPUnit\Framework\TestCase; -use Shaarli\Bookmark\BookmarkServiceInterface; -use Shaarli\Config\ConfigManager; -use Shaarli\Container\ShaarliContainer; -use Shaarli\Plugin\PluginManager; -use Shaarli\Render\PageBuilder; -use Shaarli\Security\LoginManager; use Slim\Http\Request; use Slim\Http\Response; class TagControllerTest extends TestCase { - /** @var ShaarliContainer */ - protected $container; + use FrontControllerMockHelper; /** @var TagController */ protected $controller; public function setUp(): void { - $this->container = $this->createMock(ShaarliContainer::class); + $this->createContainer(); + $this->controller = new TagController($this->container); } public function testAddTagWithReferer(): void { $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; $request = $this->createMock(Request::class); @@ -48,6 +43,7 @@ class TagControllerTest extends TestCase public function testAddTagWithRefererAndExistingSearch(): void { $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; $request = $this->createMock(Request::class); @@ -81,6 +77,7 @@ class TagControllerTest extends TestCase public function testAddTagRemoveLegacyQueryParam(): void { $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; $request = $this->createMock(Request::class); @@ -98,6 +95,7 @@ class TagControllerTest extends TestCase public function testAddTagResetPagination(): void { $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; $request = $this->createMock(Request::class); @@ -115,6 +113,7 @@ class TagControllerTest extends TestCase public function testAddTagWithRefererAndEmptySearch(): void { $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; $request = $this->createMock(Request::class); @@ -132,6 +131,7 @@ class TagControllerTest extends TestCase public function testAddTagWithoutNewTagWithReferer(): void { $this->createValidContainerMockSet(); + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; $request = $this->createMock(Request::class); @@ -157,35 +157,4 @@ class TagControllerTest extends TestCase static::assertSame(302, $result->getStatusCode()); static::assertSame(['./'], $result->getHeader('location')); } - - protected function createValidContainerMockSet(): void - { - // User logged out - $loginManager = $this->createMock(LoginManager::class); - $loginManager->method('isLoggedIn')->willReturn(false); - $loginManager->method('canLogin')->willReturn(true); - $this->container->loginManager = $loginManager; - - // Config - $conf = $this->createMock(ConfigManager::class); - $conf->method('get')->willReturnCallback(function (string $parameter, $default) { - return $default; - }); - $this->container->conf = $conf; - - // PageBuilder - $pageBuilder = $this->createMock(PageBuilder::class); - $pageBuilder - ->method('render') - ->willReturnCallback(function (string $template): string { - return $template; - }) - ; - $this->container->pageBuilder = $pageBuilder; - - $pluginManager = $this->createMock(PluginManager::class); - $this->container->pluginManager = $pluginManager; - $bookmarkService = $this->createMock(BookmarkServiceInterface::class); - $this->container->bookmarkService = $bookmarkService; - } } -- cgit v1.2.3 From 893f5159c64e5bcff505c8367e6dc22cc2a7b14d Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 20 May 2020 14:38:31 +0200 Subject: Process remove tag endpoint through Slim controller --- tests/front/controller/TagControllerTest.php | 82 ++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) (limited to 'tests/front') diff --git a/tests/front/controller/TagControllerTest.php b/tests/front/controller/TagControllerTest.php index 5eea537b..2184cb11 100644 --- a/tests/front/controller/TagControllerTest.php +++ b/tests/front/controller/TagControllerTest.php @@ -157,4 +157,86 @@ class TagControllerTest extends TestCase static::assertSame(302, $result->getStatusCode()); static::assertSame(['./'], $result->getHeader('location')); } + + public function testRemoveTagWithoutMatchingTag(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['tag' => 'abc']; + + $result = $this->controller->removeTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutTagsearch(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['tag' => 'abc']; + + $result = $this->controller->removeTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutReferer(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['tag' => 'abc']; + + $result = $this->controller->removeTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutTag(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->removeTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtag=abc'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutTagWithoutReferer(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->removeTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } } -- cgit v1.2.3 From af290059d10319e76d1e7d78b592cab99c26d91a Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 22 May 2020 11:02:56 +0200 Subject: Process session filters through Slim controllers Including: - visibility - links per page - untagged only --- .../controller/SessionFilterControllerTest.php | 290 +++++++++++++++++++++ tests/front/controller/ShaarliControllerTest.php | 131 ++++++++++ 2 files changed, 421 insertions(+) create mode 100644 tests/front/controller/SessionFilterControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/SessionFilterControllerTest.php b/tests/front/controller/SessionFilterControllerTest.php new file mode 100644 index 00000000..f541de03 --- /dev/null +++ b/tests/front/controller/SessionFilterControllerTest.php @@ -0,0 +1,290 @@ +createContainer(); + + $this->controller = new SessionFilterController($this->container); + } + + /** + * Link per page - Default call with valid parameter and a referer. + */ + public function testLinksPerPage(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $request = $this->createMock(Request::class); + $request->method('getParam')->with('nb')->willReturn('8'); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_LINKS_PER_PAGE, 8) + ; + + $result = $this->controller->linksPerPage($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Link per page - Invalid value, should use default value (20) + */ + public function testLinksPerPageNotValid(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->method('getParam')->with('nb')->willReturn('test'); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_LINKS_PER_PAGE, 20) + ; + + $result = $this->controller->linksPerPage($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + /** + * Visibility - Default call for private filter while logged in without current value + */ + public function testVisibility(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'private']; + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_VISIBILITY, 'private') + ; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Visibility - Toggle off private visibility + */ + public function testVisibilityToggleOff(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'private']; + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ->willReturn('private') + ; + $this->container->sessionManager + ->expects(static::never()) + ->method('setSessionParameter') + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('deleteSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Visibility - Change private to public + */ + public function testVisibilitySwitch(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'private']; + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ->willReturn('public') + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_VISIBILITY, 'private') + ; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + /** + * Visibility - With invalid value - should remove any visibility setting + */ + public function testVisibilityInvalidValue(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'test']; + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $this->container->sessionManager + ->expects(static::never()) + ->method('setSessionParameter') + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('deleteSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Visibility - Try to change visibility while logged out + */ + public function testVisibilityLoggedOut(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'test']; + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $this->container->loginManager->method('isLoggedIn')->willReturn(false); + $this->container->sessionManager + ->expects(static::never()) + ->method('setSessionParameter') + ; + $this->container->sessionManager + ->expects(static::never()) + ->method('deleteSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Untagged only - valid call + */ + public function testUntaggedOnly(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_UNTAGGED_ONLY, true) + ; + + $result = $this->controller->untaggedOnly($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Untagged only - toggle off + */ + public function testUntaggedOnlyToggleOff(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->method('getSessionParameter') + ->with(SessionManager::KEY_UNTAGGED_ONLY) + ->willReturn(true) + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_UNTAGGED_ONLY, false) + ; + + $result = $this->controller->untaggedOnly($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } +} diff --git a/tests/front/controller/ShaarliControllerTest.php b/tests/front/controller/ShaarliControllerTest.php index 3efe4d95..a6011b49 100644 --- a/tests/front/controller/ShaarliControllerTest.php +++ b/tests/front/controller/ShaarliControllerTest.php @@ -6,6 +6,7 @@ namespace Shaarli\Front\Controller; use PHPUnit\Framework\TestCase; use Shaarli\Bookmark\BookmarkFilter; +use Slim\Http\Response; /** * Class ShaarliControllerTest @@ -38,6 +39,14 @@ class ShaarliControllerTest extends TestCase { return parent::render($template); } + + public function redirectFromReferer( + Response $response, + array $loopTerms = [], + array $clearParams = [] + ): Response { + return parent::redirectFromReferer($response, $loopTerms, $clearParams); + } }; $this->assignedValues = []; } @@ -91,4 +100,126 @@ class ShaarliControllerTest extends TestCase static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); } + + /** + * Test redirectFromReferer() - Default behaviour + */ + public function testRedirectFromRefererDefault(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term not matched in the referer + */ + public function testRedirectFromRefererWithUnmatchedLoopTerm(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($response, ['nope']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInPath(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($response, ['nope', 'controller']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($response, ['nope', 'other']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query value + * -> we do not block redirection for query parameter values. + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($response, ['nope', 'param']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its domain name + * -> we do not block redirection for shaarli's hosts + */ + public function testRedirectFromRefererWithLoopTermInDomain(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($response, ['shaarli']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param + * -> the param should be cleared before checking if it matches the redir loop terms + */ + public function testRedirectFromRefererWithMatchingClearedParam(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($response, ['query'], ['query']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location')); + } } -- cgit v1.2.3 From 2899ebb5b5e82890c877151f5c02045266ac9973 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 22 May 2020 13:20:31 +0200 Subject: Initialize admin Slim controllers - Reorganize visitor controllers - Fix redirection with Slim's requests base path - Fix daily links --- tests/front/controller/DailyControllerTest.php | 497 --------------------- tests/front/controller/FeedControllerTest.php | 151 ------- .../front/controller/FrontControllerMockHelper.php | 114 ----- tests/front/controller/LoginControllerTest.php | 144 ------ tests/front/controller/LogoutControllerTest.php | 57 --- .../front/controller/OpenSearchControllerTest.php | 48 -- .../front/controller/PictureWallControllerTest.php | 125 ------ .../controller/SessionFilterControllerTest.php | 290 ------------ tests/front/controller/ShaarliControllerTest.php | 225 ---------- tests/front/controller/TagCloudControllerTest.php | 381 ---------------- tests/front/controller/TagControllerTest.php | 242 ---------- .../admin/FrontAdminControllerMockHelper.php | 34 ++ .../controller/admin/LogoutControllerTest.php | 57 +++ .../admin/SessionFilterControllerTest.php | 348 +++++++++++++++ .../controller/visitor/DailyControllerTest.php | 497 +++++++++++++++++++++ .../controller/visitor/FeedControllerTest.php | 151 +++++++ .../visitor/FrontControllerMockHelper.php | 114 +++++ .../controller/visitor/LoginControllerTest.php | 144 ++++++ .../visitor/OpenSearchControllerTest.php | 46 ++ .../visitor/PictureWallControllerTest.php | 125 ++++++ .../visitor/ShaarliPublicControllerTest.php | 239 ++++++++++ .../controller/visitor/TagCloudControllerTest.php | 381 ++++++++++++++++ .../front/controller/visitor/TagControllerTest.php | 241 ++++++++++ 23 files changed, 2377 insertions(+), 2274 deletions(-) delete mode 100644 tests/front/controller/DailyControllerTest.php delete mode 100644 tests/front/controller/FeedControllerTest.php delete mode 100644 tests/front/controller/FrontControllerMockHelper.php delete mode 100644 tests/front/controller/LoginControllerTest.php delete mode 100644 tests/front/controller/LogoutControllerTest.php delete mode 100644 tests/front/controller/OpenSearchControllerTest.php delete mode 100644 tests/front/controller/PictureWallControllerTest.php delete mode 100644 tests/front/controller/SessionFilterControllerTest.php delete mode 100644 tests/front/controller/ShaarliControllerTest.php delete mode 100644 tests/front/controller/TagCloudControllerTest.php delete mode 100644 tests/front/controller/TagControllerTest.php create mode 100644 tests/front/controller/admin/FrontAdminControllerMockHelper.php create mode 100644 tests/front/controller/admin/LogoutControllerTest.php create mode 100644 tests/front/controller/admin/SessionFilterControllerTest.php create mode 100644 tests/front/controller/visitor/DailyControllerTest.php create mode 100644 tests/front/controller/visitor/FeedControllerTest.php create mode 100644 tests/front/controller/visitor/FrontControllerMockHelper.php create mode 100644 tests/front/controller/visitor/LoginControllerTest.php create mode 100644 tests/front/controller/visitor/OpenSearchControllerTest.php create mode 100644 tests/front/controller/visitor/PictureWallControllerTest.php create mode 100644 tests/front/controller/visitor/ShaarliPublicControllerTest.php create mode 100644 tests/front/controller/visitor/TagCloudControllerTest.php create mode 100644 tests/front/controller/visitor/TagControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/DailyControllerTest.php b/tests/front/controller/DailyControllerTest.php deleted file mode 100644 index 7ec99030..00000000 --- a/tests/front/controller/DailyControllerTest.php +++ /dev/null @@ -1,497 +0,0 @@ -createContainer(); - - $this->controller = new DailyController($this->container); - DailyController::$DAILY_RSS_NB_DAYS = 2; - } - - public function testValidIndexControllerInvokeDefault(): void - { - $this->createValidContainerMockSet(); - - $currentDay = new \DateTimeImmutable('2020-05-13'); - - $request = $this->createMock(Request::class); - $request->method('getQueryParam')->willReturn($currentDay->format('Ymd')); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - // Links dataset: 2 links with thumbnails - $this->container->bookmarkService - ->expects(static::once()) - ->method('days') - ->willReturnCallback(function () use ($currentDay): array { - return [ - '20200510', - $currentDay->format('Ymd'), - '20200516', - ]; - }) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('filterDay') - ->willReturnCallback(function (): array { - return [ - (new Bookmark()) - ->setId(1) - ->setUrl('http://url.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) - , - (new Bookmark()) - ->setId(2) - ->setUrl('http://url2.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) - , - (new Bookmark()) - ->setId(3) - ->setUrl('http://url3.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) - , - ]; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { - static::assertSame('render_daily', $hook); - - static::assertArrayHasKey('linksToDisplay', $data); - static::assertCount(3, $data['linksToDisplay']); - static::assertSame(1, $data['linksToDisplay'][0]['id']); - static::assertSame($currentDay->getTimestamp(), $data['day']); - static::assertSame('20200510', $data['previousday']); - static::assertSame('20200516', $data['nextday']); - - static::assertArrayHasKey('loggedin', $param); - - return $data; - }) - ; - - $result = $this->controller->index($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('daily', (string) $result->getBody()); - static::assertSame( - 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', - $assignedVariables['pagetitle'] - ); - static::assertEquals($currentDay, $assignedVariables['dayDate']); - static::assertEquals($currentDay->getTimestamp(), $assignedVariables['day']); - static::assertCount(3, $assignedVariables['linksToDisplay']); - - $link = $assignedVariables['linksToDisplay'][0]; - - static::assertSame(1, $link['id']); - static::assertSame('http://url.tld', $link['url']); - static::assertNotEmpty($link['title']); - static::assertNotEmpty($link['description']); - static::assertNotEmpty($link['formatedDescription']); - - $link = $assignedVariables['linksToDisplay'][1]; - - static::assertSame(2, $link['id']); - static::assertSame('http://url2.tld', $link['url']); - static::assertNotEmpty($link['title']); - static::assertNotEmpty($link['description']); - static::assertNotEmpty($link['formatedDescription']); - - $link = $assignedVariables['linksToDisplay'][2]; - - static::assertSame(3, $link['id']); - static::assertSame('http://url3.tld', $link['url']); - static::assertNotEmpty($link['title']); - static::assertNotEmpty($link['description']); - static::assertNotEmpty($link['formatedDescription']); - - static::assertCount(3, $assignedVariables['cols']); - static::assertCount(1, $assignedVariables['cols'][0]); - static::assertCount(1, $assignedVariables['cols'][1]); - static::assertCount(1, $assignedVariables['cols'][2]); - - $link = $assignedVariables['cols'][0][0]; - - static::assertSame(1, $link['id']); - static::assertSame('http://url.tld', $link['url']); - static::assertNotEmpty($link['title']); - static::assertNotEmpty($link['description']); - static::assertNotEmpty($link['formatedDescription']); - - $link = $assignedVariables['cols'][1][0]; - - static::assertSame(2, $link['id']); - static::assertSame('http://url2.tld', $link['url']); - static::assertNotEmpty($link['title']); - static::assertNotEmpty($link['description']); - static::assertNotEmpty($link['formatedDescription']); - - $link = $assignedVariables['cols'][2][0]; - - static::assertSame(3, $link['id']); - static::assertSame('http://url3.tld', $link['url']); - static::assertNotEmpty($link['title']); - static::assertNotEmpty($link['description']); - static::assertNotEmpty($link['formatedDescription']); - } - - /** - * Daily page - test that everything goes fine with no future or past bookmarks - */ - public function testValidIndexControllerInvokeNoFutureOrPast(): void - { - $this->createValidContainerMockSet(); - - $currentDay = new \DateTimeImmutable('2020-05-13'); - - $request = $this->createMock(Request::class); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - // Links dataset: 2 links with thumbnails - $this->container->bookmarkService - ->expects(static::once()) - ->method('days') - ->willReturnCallback(function () use ($currentDay): array { - return [ - $currentDay->format($currentDay->format('Ymd')), - ]; - }) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('filterDay') - ->willReturnCallback(function (): array { - return [ - (new Bookmark()) - ->setId(1) - ->setUrl('http://url.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) - , - ]; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { - static::assertSame('render_daily', $hook); - - static::assertArrayHasKey('linksToDisplay', $data); - static::assertCount(1, $data['linksToDisplay']); - static::assertSame(1, $data['linksToDisplay'][0]['id']); - static::assertSame($currentDay->getTimestamp(), $data['day']); - static::assertEmpty($data['previousday']); - static::assertEmpty($data['nextday']); - - static::assertArrayHasKey('loggedin', $param); - - return $data; - }); - - $result = $this->controller->index($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('daily', (string) $result->getBody()); - static::assertSame( - 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', - $assignedVariables['pagetitle'] - ); - static::assertCount(1, $assignedVariables['linksToDisplay']); - - $link = $assignedVariables['linksToDisplay'][0]; - static::assertSame(1, $link['id']); - } - - /** - * Daily page - test that height adjustment in columns is working - */ - public function testValidIndexControllerInvokeHeightAdjustment(): void - { - $this->createValidContainerMockSet(); - - $currentDay = new \DateTimeImmutable('2020-05-13'); - - $request = $this->createMock(Request::class); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - // Links dataset: 2 links with thumbnails - $this->container->bookmarkService - ->expects(static::once()) - ->method('days') - ->willReturnCallback(function () use ($currentDay): array { - return [ - $currentDay->format($currentDay->format('Ymd')), - ]; - }) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('filterDay') - ->willReturnCallback(function (): array { - return [ - (new Bookmark())->setId(1)->setUrl('http://url.tld')->setTitle('title'), - (new Bookmark()) - ->setId(2) - ->setUrl('http://url.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(5000)) - , - (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'), - (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'), - (new Bookmark())->setId(5)->setUrl('http://url.tld')->setTitle('title'), - (new Bookmark())->setId(6)->setUrl('http://url.tld')->setTitle('title'), - (new Bookmark())->setId(7)->setUrl('http://url.tld')->setTitle('title'), - ]; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): array { - return $data; - }) - ; - - $result = $this->controller->index($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('daily', (string) $result->getBody()); - static::assertCount(7, $assignedVariables['linksToDisplay']); - - $columnIds = function (array $column): array { - return array_map(function (array $item): int { return $item['id']; }, $column); - }; - - static::assertSame([1, 4, 6], $columnIds($assignedVariables['cols'][0])); - static::assertSame([2], $columnIds($assignedVariables['cols'][1])); - static::assertSame([3, 5, 7], $columnIds($assignedVariables['cols'][2])); - } - - /** - * Daily page - no bookmark - */ - public function testValidIndexControllerInvokeNoBookmark(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - // Links dataset: 2 links with thumbnails - $this->container->bookmarkService - ->expects(static::once()) - ->method('days') - ->willReturnCallback(function (): array { - return []; - }) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('filterDay') - ->willReturnCallback(function (): array { - return []; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): array { - return $data; - }) - ; - - $result = $this->controller->index($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('daily', (string) $result->getBody()); - static::assertCount(0, $assignedVariables['linksToDisplay']); - static::assertSame('Today', $assignedVariables['dayDesc']); - static::assertEquals((new \DateTime())->setTime(0, 0)->getTimestamp(), $assignedVariables['day']); - static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']); - } - - /** - * Daily RSS - default behaviour - */ - public function testValidRssControllerInvokeDefault(): void - { - $this->createValidContainerMockSet(); - - $dates = [ - new \DateTimeImmutable('2020-05-17'), - new \DateTimeImmutable('2020-05-15'), - new \DateTimeImmutable('2020-05-13'), - ]; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ - (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), - (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), - (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), - (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'), - ]); - - $this->container->pageCacheManager - ->expects(static::once()) - ->method('getCachePage') - ->willReturnCallback(function (): CachedPage { - $cachedPage = $this->createMock(CachedPage::class); - $cachedPage->expects(static::once())->method('cache')->with('dailyrss'); - - return $cachedPage; - } - ); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $result = $this->controller->rss($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); - static::assertSame('dailyrss', (string) $result->getBody()); - static::assertSame('Shaarli', $assignedVariables['title']); - static::assertSame('http://shaarli', $assignedVariables['index_url']); - static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); - static::assertFalse($assignedVariables['hide_timestamps']); - static::assertCount(2, $assignedVariables['days']); - - $day = $assignedVariables['days'][$dates[0]->format('Ymd')]; - - static::assertEquals($dates[0], $day['date']); - static::assertSame($dates[0]->format(\DateTime::RSS), $day['date_rss']); - static::assertSame(format_date($dates[0], false), $day['date_human']); - static::assertSame('http://shaarli/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']); - static::assertCount(1, $day['links']); - static::assertSame(1, $day['links'][0]['id']); - static::assertSame('http://domain.tld/1', $day['links'][0]['url']); - static::assertEquals($dates[0], $day['links'][0]['created']); - - $day = $assignedVariables['days'][$dates[1]->format('Ymd')]; - - static::assertEquals($dates[1], $day['date']); - static::assertSame($dates[1]->format(\DateTime::RSS), $day['date_rss']); - static::assertSame(format_date($dates[1], false), $day['date_human']); - static::assertSame('http://shaarli/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']); - static::assertCount(2, $day['links']); - - static::assertSame(2, $day['links'][0]['id']); - static::assertSame('http://domain.tld/2', $day['links'][0]['url']); - static::assertEquals($dates[1], $day['links'][0]['created']); - static::assertSame(3, $day['links'][1]['id']); - static::assertSame('http://domain.tld/3', $day['links'][1]['url']); - static::assertEquals($dates[1], $day['links'][1]['created']); - } - - /** - * Daily RSS - trigger cache rendering - */ - public function testValidRssControllerInvokeTriggerCache(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->pageCacheManager->method('getCachePage')->willReturnCallback(function (): CachedPage { - $cachedPage = $this->createMock(CachedPage::class); - $cachedPage->method('cachedVersion')->willReturn('this is cache!'); - - return $cachedPage; - }); - - $this->container->bookmarkService->expects(static::never())->method('search'); - - $result = $this->controller->rss($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); - static::assertSame('this is cache!', (string) $result->getBody()); - } - - /** - * Daily RSS - No bookmark - */ - public function testValidRssControllerInvokeNoBookmark(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([]); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $result = $this->controller->rss($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); - static::assertSame('dailyrss', (string) $result->getBody()); - static::assertSame('Shaarli', $assignedVariables['title']); - static::assertSame('http://shaarli', $assignedVariables['index_url']); - static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); - static::assertFalse($assignedVariables['hide_timestamps']); - static::assertCount(0, $assignedVariables['days']); - } - - protected static function generateContent(int $length): string - { - // bin2hex(random_bytes) generates string twice as long as given parameter - $length = (int) ceil($length / 2); - return bin2hex(random_bytes($length)); - } -} diff --git a/tests/front/controller/FeedControllerTest.php b/tests/front/controller/FeedControllerTest.php deleted file mode 100644 index 7e8657e2..00000000 --- a/tests/front/controller/FeedControllerTest.php +++ /dev/null @@ -1,151 +0,0 @@ -createContainer(); - - $this->container->feedBuilder = $this->createMock(FeedBuilder::class); - - $this->controller = new FeedController($this->container); - } - - /** - * Feed Controller - RSS default behaviour - */ - public function testDefaultRssController(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->feedBuilder->expects(static::once())->method('setLocale'); - $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); - $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): void { - static::assertSame('render_feed', $hook); - static::assertSame('data', $data['content']); - - static::assertArrayHasKey('loggedin', $param); - static::assertSame('rss', $param['target']); - }) - ; - - $result = $this->controller->rss($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); - static::assertSame('feed.rss', (string) $result->getBody()); - static::assertSame('data', $assignedVariables['content']); - } - - /** - * Feed Controller - ATOM default behaviour - */ - public function testDefaultAtomController(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->feedBuilder->expects(static::once())->method('setLocale'); - $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); - $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): void { - static::assertSame('render_feed', $hook); - static::assertSame('data', $data['content']); - - static::assertArrayHasKey('loggedin', $param); - static::assertSame('atom', $param['target']); - }) - ; - - $result = $this->controller->atom($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); - static::assertSame('feed.atom', (string) $result->getBody()); - static::assertSame('data', $assignedVariables['content']); - } - - /** - * Feed Controller - ATOM with parameters - */ - public function testAtomControllerWithParameters(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $request->method('getParams')->willReturn(['parameter' => 'value']); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->feedBuilder - ->method('buildData') - ->with('atom', ['parameter' => 'value']) - ->willReturn(['content' => 'data']) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): void { - static::assertSame('render_feed', $hook); - static::assertSame('data', $data['content']); - - static::assertArrayHasKey('loggedin', $param); - static::assertSame('atom', $param['target']); - }) - ; - - $result = $this->controller->atom($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); - static::assertSame('feed.atom', (string) $result->getBody()); - static::assertSame('data', $assignedVariables['content']); - } -} diff --git a/tests/front/controller/FrontControllerMockHelper.php b/tests/front/controller/FrontControllerMockHelper.php deleted file mode 100644 index b65607e7..00000000 --- a/tests/front/controller/FrontControllerMockHelper.php +++ /dev/null @@ -1,114 +0,0 @@ -container = $this->createMock(ShaarliTestContainer::class); - } - - /** - * Initialize container's services used by tests - */ - protected function createValidContainerMockSet(): void - { - $this->container->loginManager = $this->createMock(LoginManager::class); - - // Config - $this->container->conf = $this->createMock(ConfigManager::class); - $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { - return $default; - }); - - // PageBuilder - $this->container->pageBuilder = $this->createMock(PageBuilder::class); - $this->container->pageBuilder - ->method('render') - ->willReturnCallback(function (string $template): string { - return $template; - }) - ; - - // Plugin Manager - $this->container->pluginManager = $this->createMock(PluginManager::class); - - // BookmarkService - $this->container->bookmarkService = $this->createMock(BookmarkServiceInterface::class); - - // Formatter - $this->container->formatterFactory = $this->createMock(FormatterFactory::class); - $this->container->formatterFactory - ->method('getFormatter') - ->willReturnCallback(function (): BookmarkFormatter { - return new BookmarkRawFormatter($this->container->conf, true); - }) - ; - - // CacheManager - $this->container->pageCacheManager = $this->createMock(PageCacheManager::class); - - // SessionManager - $this->container->sessionManager = $this->createMock(SessionManager::class); - - // $_SERVER - $this->container->environment = [ - 'SERVER_NAME' => 'shaarli', - 'SERVER_PORT' => '80', - 'REQUEST_URI' => '/daily-rss', - ]; - } - - /** - * Pass a reference of an array which will be populated by `pageBuilder->assign` calls during execution. - * - * @param mixed $variables Array reference to populate. - */ - protected function assignTemplateVars(array &$variables): void - { - $this->container->pageBuilder - ->expects(static::atLeastOnce()) - ->method('assign') - ->willReturnCallback(function ($key, $value) use (&$variables) { - $variables[$key] = $value; - - return $this; - }) - ; - } - - /** - * Force to be used in PHPUnit context. - */ - protected abstract function createMock($originalClassName): MockObject; -} diff --git a/tests/front/controller/LoginControllerTest.php b/tests/front/controller/LoginControllerTest.php deleted file mode 100644 index 21937f3c..00000000 --- a/tests/front/controller/LoginControllerTest.php +++ /dev/null @@ -1,144 +0,0 @@ -createContainer(); - - $this->controller = new LoginController($this->container); - } - - public function testValidControllerInvoke(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); - $response = new Response(); - - $assignedVariables = []; - $this->container->pageBuilder - ->method('assign') - ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { - $assignedVariables[$key] = $value; - - return $this; - }) - ; - - $this->container->loginManager->method('canLogin')->willReturn(true); - - $result = $this->controller->index($request, $response); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(200, $result->getStatusCode()); - static::assertSame('loginform', (string) $result->getBody()); - - static::assertSame('> referer', $assignedVariables['returnurl']); - static::assertSame(true, $assignedVariables['remember_user_default']); - static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); - } - - public function testValidControllerInvokeWithUserName(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); - $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); - $response = new Response(); - - $assignedVariables = []; - $this->container->pageBuilder - ->method('assign') - ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { - $assignedVariables[$key] = $value; - - return $this; - }) - ; - - $this->container->loginManager->expects(static::once())->method('canLogin')->willReturn(true); - - $result = $this->controller->index($request, $response); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(200, $result->getStatusCode()); - static::assertSame('loginform', (string) $result->getBody()); - - static::assertSame('myUser>', $assignedVariables['username']); - static::assertSame('> referer', $assignedVariables['returnurl']); - static::assertSame(true, $assignedVariables['remember_user_default']); - static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); - } - - public function testLoginControllerWhileLoggedIn(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true); - - $result = $this->controller->index($request, $response); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('Location')); - } - - public function testLoginControllerOpenShaarli(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $conf = $this->createMock(ConfigManager::class); - $conf->method('get')->willReturnCallback(function (string $parameter, $default) { - if ($parameter === 'security.open_shaarli') { - return true; - } - return $default; - }); - $this->container->conf = $conf; - - $result = $this->controller->index($request, $response); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('Location')); - } - - public function testLoginControllerWhileBanned(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->loginManager->method('isLoggedIn')->willReturn(false); - $this->container->loginManager->method('canLogin')->willReturn(false); - - $this->expectException(LoginBannedException::class); - - $this->controller->index($request, $response); - } -} diff --git a/tests/front/controller/LogoutControllerTest.php b/tests/front/controller/LogoutControllerTest.php deleted file mode 100644 index 8e01c367..00000000 --- a/tests/front/controller/LogoutControllerTest.php +++ /dev/null @@ -1,57 +0,0 @@ -createContainer(); - - $this->controller = new LogoutController($this->container); - - setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, $cookie = 'hi there'); - } - - public function testValidControllerInvoke(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches'); - - $this->container->sessionManager = $this->createMock(SessionManager::class); - $this->container->sessionManager->expects(static::once())->method('logout'); - - static::assertSame('hi there', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); - - $result = $this->controller->index($request, $response); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertContains('./', $result->getHeader('Location')); - static::assertSame('false', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); - } -} diff --git a/tests/front/controller/OpenSearchControllerTest.php b/tests/front/controller/OpenSearchControllerTest.php deleted file mode 100644 index f3b6f439..00000000 --- a/tests/front/controller/OpenSearchControllerTest.php +++ /dev/null @@ -1,48 +0,0 @@ -createContainer(); - - $this->controller = new OpenSearchController($this->container); - } - - public function testOpenSearchController(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $result = $this->controller->index($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertStringContainsString( - 'application/opensearchdescription+xml', - $result->getHeader('Content-Type')[0] - ); - static::assertSame('opensearch', (string) $result->getBody()); - static::assertSame('http://shaarli', $assignedVariables['serverurl']); - } -} diff --git a/tests/front/controller/PictureWallControllerTest.php b/tests/front/controller/PictureWallControllerTest.php deleted file mode 100644 index 8160bb38..00000000 --- a/tests/front/controller/PictureWallControllerTest.php +++ /dev/null @@ -1,125 +0,0 @@ -createContainer(); - - $this->controller = new PictureWallController($this->container); - } - - public function testValidControllerInvokeDefault(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $request->expects(static::once())->method('getQueryParams')->willReturn([]); - $response = new Response(); - - // ConfigManager: thumbnails are enabled - $this->container->conf = $this->createMock(ConfigManager::class); - $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { - if ($parameter === 'thumbnails.mode') { - return Thumbnailer::MODE_COMMON; - } - - return $default; - }); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - // Links dataset: 2 links with thumbnails - $this->container->bookmarkService - ->expects(static::once()) - ->method('search') - ->willReturnCallback(function (array $parameters, ?string $visibility): array { - // Visibility is set through the container, not the call - static::assertNull($visibility); - - // No query parameters - if (count($parameters) === 0) { - return [ - (new Bookmark())->setId(1)->setUrl('http://url.tld')->setThumbnail('thumb1'), - (new Bookmark())->setId(2)->setUrl('http://url2.tld'), - (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setThumbnail('thumb2'), - ]; - } - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): array { - static::assertSame('render_picwall', $hook); - static::assertArrayHasKey('linksToDisplay', $data); - static::assertCount(2, $data['linksToDisplay']); - static::assertSame(1, $data['linksToDisplay'][0]['id']); - static::assertSame(3, $data['linksToDisplay'][1]['id']); - static::assertArrayHasKey('loggedin', $param); - - return $data; - }); - - $result = $this->controller->index($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('picwall', (string) $result->getBody()); - static::assertSame('Picture wall - Shaarli', $assignedVariables['pagetitle']); - static::assertCount(2, $assignedVariables['linksToDisplay']); - - $link = $assignedVariables['linksToDisplay'][0]; - - static::assertSame(1, $link['id']); - static::assertSame('http://url.tld', $link['url']); - static::assertSame('thumb1', $link['thumbnail']); - - $link = $assignedVariables['linksToDisplay'][1]; - - static::assertSame(3, $link['id']); - static::assertSame('http://url3.tld', $link['url']); - static::assertSame('thumb2', $link['thumbnail']); - } - - public function testControllerWithThumbnailsDisabled(): void - { - $this->expectException(ThumbnailsDisabledException::class); - - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - // ConfigManager: thumbnails are disabled - $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { - if ($parameter === 'thumbnails.mode') { - return Thumbnailer::MODE_NONE; - } - - return $default; - }); - - $this->controller->index($request, $response); - } -} diff --git a/tests/front/controller/SessionFilterControllerTest.php b/tests/front/controller/SessionFilterControllerTest.php deleted file mode 100644 index f541de03..00000000 --- a/tests/front/controller/SessionFilterControllerTest.php +++ /dev/null @@ -1,290 +0,0 @@ -createContainer(); - - $this->controller = new SessionFilterController($this->container); - } - - /** - * Link per page - Default call with valid parameter and a referer. - */ - public function testLinksPerPage(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; - - $request = $this->createMock(Request::class); - $request->method('getParam')->with('nb')->willReturn('8'); - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_LINKS_PER_PAGE, 8) - ; - - $result = $this->controller->linksPerPage($request, $response); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); - } - - /** - * Link per page - Invalid value, should use default value (20) - */ - public function testLinksPerPageNotValid(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $request->method('getParam')->with('nb')->willReturn('test'); - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_LINKS_PER_PAGE, 20) - ; - - $result = $this->controller->linksPerPage($request, $response); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); - } - - /** - * Visibility - Default call for private filter while logged in without current value - */ - public function testVisibility(): void - { - $this->createValidContainerMockSet(); - - $arg = ['visibility' => 'private']; - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; - - $this->container->loginManager->method('isLoggedIn')->willReturn(true); - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_VISIBILITY, 'private') - ; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->visibility($request, $response, $arg); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); - } - - /** - * Visibility - Toggle off private visibility - */ - public function testVisibilityToggleOff(): void - { - $this->createValidContainerMockSet(); - - $arg = ['visibility' => 'private']; - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; - - $this->container->loginManager->method('isLoggedIn')->willReturn(true); - $this->container->sessionManager - ->method('getSessionParameter') - ->with(SessionManager::KEY_VISIBILITY) - ->willReturn('private') - ; - $this->container->sessionManager - ->expects(static::never()) - ->method('setSessionParameter') - ; - $this->container->sessionManager - ->expects(static::once()) - ->method('deleteSessionParameter') - ->with(SessionManager::KEY_VISIBILITY) - ; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->visibility($request, $response, $arg); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); - } - - /** - * Visibility - Change private to public - */ - public function testVisibilitySwitch(): void - { - $this->createValidContainerMockSet(); - - $arg = ['visibility' => 'private']; - - $this->container->loginManager->method('isLoggedIn')->willReturn(true); - $this->container->sessionManager - ->method('getSessionParameter') - ->with(SessionManager::KEY_VISIBILITY) - ->willReturn('public') - ; - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_VISIBILITY, 'private') - ; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->visibility($request, $response, $arg); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); - } - - /** - * Visibility - With invalid value - should remove any visibility setting - */ - public function testVisibilityInvalidValue(): void - { - $this->createValidContainerMockSet(); - - $arg = ['visibility' => 'test']; - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; - - $this->container->loginManager->method('isLoggedIn')->willReturn(true); - $this->container->sessionManager - ->expects(static::never()) - ->method('setSessionParameter') - ; - $this->container->sessionManager - ->expects(static::once()) - ->method('deleteSessionParameter') - ->with(SessionManager::KEY_VISIBILITY) - ; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->visibility($request, $response, $arg); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); - } - - /** - * Visibility - Try to change visibility while logged out - */ - public function testVisibilityLoggedOut(): void - { - $this->createValidContainerMockSet(); - - $arg = ['visibility' => 'test']; - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; - - $this->container->loginManager->method('isLoggedIn')->willReturn(false); - $this->container->sessionManager - ->expects(static::never()) - ->method('setSessionParameter') - ; - $this->container->sessionManager - ->expects(static::never()) - ->method('deleteSessionParameter') - ->with(SessionManager::KEY_VISIBILITY) - ; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->visibility($request, $response, $arg); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); - } - - /** - * Untagged only - valid call - */ - public function testUntaggedOnly(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_UNTAGGED_ONLY, true) - ; - - $result = $this->controller->untaggedOnly($request, $response); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); - } - - /** - * Untagged only - toggle off - */ - public function testUntaggedOnlyToggleOff(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $this->container->sessionManager - ->method('getSessionParameter') - ->with(SessionManager::KEY_UNTAGGED_ONLY) - ->willReturn(true) - ; - $this->container->sessionManager - ->expects(static::once()) - ->method('setSessionParameter') - ->with(SessionManager::KEY_UNTAGGED_ONLY, false) - ; - - $result = $this->controller->untaggedOnly($request, $response); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); - } -} diff --git a/tests/front/controller/ShaarliControllerTest.php b/tests/front/controller/ShaarliControllerTest.php deleted file mode 100644 index a6011b49..00000000 --- a/tests/front/controller/ShaarliControllerTest.php +++ /dev/null @@ -1,225 +0,0 @@ -createContainer(); - - $this->controller = new class($this->container) extends ShaarliController - { - public function assignView(string $key, $value): ShaarliController - { - return parent::assignView($key, $value); - } - - public function render(string $template): string - { - return parent::render($template); - } - - public function redirectFromReferer( - Response $response, - array $loopTerms = [], - array $clearParams = [] - ): Response { - return parent::redirectFromReferer($response, $loopTerms, $clearParams); - } - }; - $this->assignedValues = []; - } - - public function testAssignView(): void - { - $this->createValidContainerMockSet(); - - $this->assignTemplateVars($this->assignedValues); - - $self = $this->controller->assignView('variableName', 'variableValue'); - - static::assertInstanceOf(ShaarliController::class, $self); - static::assertSame('variableValue', $this->assignedValues['variableName']); - } - - public function testRender(): void - { - $this->createValidContainerMockSet(); - - $this->assignTemplateVars($this->assignedValues); - - $this->container->bookmarkService - ->method('count') - ->willReturnCallback(function (string $visibility): int { - return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; - }) - ; - - $this->container->pluginManager - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array &$data, array $params): array { - return $data[$hook] = $params; - }); - $this->container->pluginManager->method('getErrors')->willReturn(['error']); - - $this->container->loginManager->method('isLoggedIn')->willReturn(true); - - $render = $this->controller->render('templateName'); - - static::assertSame('templateName', $render); - - static::assertSame(10, $this->assignedValues['linkcount']); - static::assertSame(5, $this->assignedValues['privateLinkcount']); - static::assertSame(['error'], $this->assignedValues['plugin_errors']); - - static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); - static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); - static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); - static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); - static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); - static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); - } - - /** - * Test redirectFromReferer() - Default behaviour - */ - public function testRedirectFromRefererDefault(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term not matched in the referer - */ - public function testRedirectFromRefererWithUnmatchedLoopTerm(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($response, ['nope']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default - */ - public function testRedirectFromRefererWithMatchingLoopTermInPath(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($response, ['nope', 'controller']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default - */ - public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($response, ['nope', 'other']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its query value - * -> we do not block redirection for query parameter values. - */ - public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($response, ['nope', 'param']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its domain name - * -> we do not block redirection for shaarli's hosts - */ - public function testRedirectFromRefererWithLoopTermInDomain(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($response, ['shaarli']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param - * -> the param should be cleared before checking if it matches the redir loop terms - */ - public function testRedirectFromRefererWithMatchingClearedParam(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($response, ['query'], ['query']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location')); - } -} diff --git a/tests/front/controller/TagCloudControllerTest.php b/tests/front/controller/TagCloudControllerTest.php deleted file mode 100644 index 8c27900d..00000000 --- a/tests/front/controller/TagCloudControllerTest.php +++ /dev/null @@ -1,381 +0,0 @@ -createContainer(); - - $this->controller = new TagCloudController($this->container); - } - - /** - * Tag Cloud - default parameters - */ - public function testValidCloudControllerInvokeDefault(): void - { - $this->createValidContainerMockSet(); - - $allTags = [ - 'ghi' => 1, - 'abc' => 3, - 'def' => 12, - ]; - $expectedOrder = ['abc', 'def', 'ghi']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('bookmarksCountPerTag') - ->with([], null) - ->willReturnCallback(function () use ($allTags): array { - return $allTags; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): array { - static::assertSame('render_tagcloud', $hook); - static::assertSame('', $data['search_tags']); - static::assertCount(3, $data['tags']); - - static::assertArrayHasKey('loggedin', $param); - - return $data; - }) - ; - - $result = $this->controller->cloud($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('tag.cloud', (string) $result->getBody()); - static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); - - static::assertSame('', $assignedVariables['search_tags']); - static::assertCount(3, $assignedVariables['tags']); - static::assertSame($expectedOrder, array_keys($assignedVariables['tags'])); - - foreach ($allTags as $tag => $count) { - static::assertArrayHasKey($tag, $assignedVariables['tags']); - static::assertSame($count, $assignedVariables['tags'][$tag]['count']); - static::assertGreaterThan(0, $assignedVariables['tags'][$tag]['size']); - static::assertLessThan(5, $assignedVariables['tags'][$tag]['size']); - } - } - - /** - * Tag Cloud - Additional parameters: - * - logged in - * - visibility private - * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) - */ - public function testValidCloudControllerInvokeWithParameters(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $request - ->method('getQueryParam') - ->with() - ->willReturnCallback(function (string $key): ?string { - if ('searchtags' === $key) { - return 'ghi def'; - } - - return null; - }) - ; - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->loginManager->method('isLoggedin')->willReturn(true); - $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('bookmarksCountPerTag') - ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) - ->willReturnCallback(function (): array { - return ['abc' => 3]; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): array { - static::assertSame('render_tagcloud', $hook); - static::assertSame('ghi def', $data['search_tags']); - static::assertCount(1, $data['tags']); - - static::assertArrayHasKey('loggedin', $param); - - return $data; - }) - ; - - $result = $this->controller->cloud($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('tag.cloud', (string) $result->getBody()); - static::assertSame('ghi def - Tag cloud - Shaarli', $assignedVariables['pagetitle']); - - static::assertSame('ghi def', $assignedVariables['search_tags']); - static::assertCount(1, $assignedVariables['tags']); - - static::assertArrayHasKey('abc', $assignedVariables['tags']); - static::assertSame(3, $assignedVariables['tags']['abc']['count']); - static::assertGreaterThan(0, $assignedVariables['tags']['abc']['size']); - static::assertLessThan(5, $assignedVariables['tags']['abc']['size']); - } - - /** - * Tag Cloud - empty - */ - public function testEmptyCloud(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('bookmarksCountPerTag') - ->with([], null) - ->willReturnCallback(function (array $parameters, ?string $visibility): array { - return []; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): array { - static::assertSame('render_tagcloud', $hook); - static::assertSame('', $data['search_tags']); - static::assertCount(0, $data['tags']); - - static::assertArrayHasKey('loggedin', $param); - - return $data; - }) - ; - - $result = $this->controller->cloud($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('tag.cloud', (string) $result->getBody()); - static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); - - static::assertSame('', $assignedVariables['search_tags']); - static::assertCount(0, $assignedVariables['tags']); - } - - /** - * Tag List - Default sort is by usage DESC - */ - public function testValidListControllerInvokeDefault(): void - { - $this->createValidContainerMockSet(); - - $allTags = [ - 'def' => 12, - 'abc' => 3, - 'ghi' => 1, - ]; - - $request = $this->createMock(Request::class); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('bookmarksCountPerTag') - ->with([], null) - ->willReturnCallback(function () use ($allTags): array { - return $allTags; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): array { - static::assertSame('render_taglist', $hook); - static::assertSame('', $data['search_tags']); - static::assertCount(3, $data['tags']); - - static::assertArrayHasKey('loggedin', $param); - - return $data; - }) - ; - - $result = $this->controller->list($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('tag.list', (string) $result->getBody()); - static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); - - static::assertSame('', $assignedVariables['search_tags']); - static::assertCount(3, $assignedVariables['tags']); - - foreach ($allTags as $tag => $count) { - static::assertSame($count, $assignedVariables['tags'][$tag]); - } - } - - /** - * Tag List - Additional parameters: - * - logged in - * - visibility private - * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) - * - sort alphabetically - */ - public function testValidListControllerInvokeWithParameters(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $request - ->method('getQueryParam') - ->with() - ->willReturnCallback(function (string $key): ?string { - if ('searchtags' === $key) { - return 'ghi def'; - } elseif ('sort' === $key) { - return 'alpha'; - } - - return null; - }) - ; - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->loginManager->method('isLoggedin')->willReturn(true); - $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('bookmarksCountPerTag') - ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) - ->willReturnCallback(function (): array { - return ['abc' => 3]; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): array { - static::assertSame('render_taglist', $hook); - static::assertSame('ghi def', $data['search_tags']); - static::assertCount(1, $data['tags']); - - static::assertArrayHasKey('loggedin', $param); - - return $data; - }) - ; - - $result = $this->controller->list($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('tag.list', (string) $result->getBody()); - static::assertSame('ghi def - Tag list - Shaarli', $assignedVariables['pagetitle']); - - static::assertSame('ghi def', $assignedVariables['search_tags']); - static::assertCount(1, $assignedVariables['tags']); - static::assertSame(3, $assignedVariables['tags']['abc']); - } - - /** - * Tag List - empty - */ - public function testEmptyList(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - // Save RainTPL assigned variables - $assignedVariables = []; - $this->assignTemplateVars($assignedVariables); - - $this->container->bookmarkService - ->expects(static::once()) - ->method('bookmarksCountPerTag') - ->with([], null) - ->willReturnCallback(function (array $parameters, ?string $visibility): array { - return []; - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data, array $param): array { - static::assertSame('render_taglist', $hook); - static::assertSame('', $data['search_tags']); - static::assertCount(0, $data['tags']); - - static::assertArrayHasKey('loggedin', $param); - - return $data; - }) - ; - - $result = $this->controller->list($request, $response); - - static::assertSame(200, $result->getStatusCode()); - static::assertSame('tag.list', (string) $result->getBody()); - static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); - - static::assertSame('', $assignedVariables['search_tags']); - static::assertCount(0, $assignedVariables['tags']); - } -} diff --git a/tests/front/controller/TagControllerTest.php b/tests/front/controller/TagControllerTest.php deleted file mode 100644 index 2184cb11..00000000 --- a/tests/front/controller/TagControllerTest.php +++ /dev/null @@ -1,242 +0,0 @@ -createContainer(); - - $this->controller = new TagController($this->container); - } - - public function testAddTagWithReferer(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $tags = ['newTag' => 'abc']; - - $result = $this->controller->addTag($request, $response, $tags); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); - } - - public function testAddTagWithRefererAndExistingSearch(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $tags = ['newTag' => 'abc']; - - $result = $this->controller->addTag($request, $response, $tags); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); - } - - public function testAddTagWithoutRefererAndExistingSearch(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $tags = ['newTag' => 'abc']; - - $result = $this->controller->addTag($request, $response, $tags); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./?searchtags=abc'], $result->getHeader('location')); - } - - public function testAddTagRemoveLegacyQueryParam(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $tags = ['newTag' => 'abc']; - - $result = $this->controller->addTag($request, $response, $tags); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); - } - - public function testAddTagResetPagination(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $tags = ['newTag' => 'abc']; - - $result = $this->controller->addTag($request, $response, $tags); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); - } - - public function testAddTagWithRefererAndEmptySearch(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $tags = ['newTag' => 'abc']; - - $result = $this->controller->addTag($request, $response, $tags); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); - } - - public function testAddTagWithoutNewTagWithReferer(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->addTag($request, $response, []); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); - } - - public function testAddTagWithoutNewTagWithoutReferer(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->addTag($request, $response, []); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); - } - - public function testRemoveTagWithoutMatchingTag(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $tags = ['tag' => 'abc']; - - $result = $this->controller->removeTag($request, $response, $tags); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); - } - - public function testRemoveTagWithoutTagsearch(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $tags = ['tag' => 'abc']; - - $result = $this->controller->removeTag($request, $response, $tags); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/controller/'], $result->getHeader('location')); - } - - public function testRemoveTagWithoutReferer(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $tags = ['tag' => 'abc']; - - $result = $this->controller->removeTag($request, $response, $tags); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); - } - - public function testRemoveTagWithoutTag(): void - { - $this->createValidContainerMockSet(); - - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc']; - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->removeTag($request, $response, []); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/controller/?searchtag=abc'], $result->getHeader('location')); - } - - public function testRemoveTagWithoutTagWithoutReferer(): void - { - $this->createValidContainerMockSet(); - - $request = $this->createMock(Request::class); - $response = new Response(); - - $result = $this->controller->removeTag($request, $response, []); - - static::assertInstanceOf(Response::class, $result); - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); - } -} diff --git a/tests/front/controller/admin/FrontAdminControllerMockHelper.php b/tests/front/controller/admin/FrontAdminControllerMockHelper.php new file mode 100644 index 00000000..94581c09 --- /dev/null +++ b/tests/front/controller/admin/FrontAdminControllerMockHelper.php @@ -0,0 +1,34 @@ +parentCreateContainer(); + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + } +} diff --git a/tests/front/controller/admin/LogoutControllerTest.php b/tests/front/controller/admin/LogoutControllerTest.php new file mode 100644 index 00000000..239e39b2 --- /dev/null +++ b/tests/front/controller/admin/LogoutControllerTest.php @@ -0,0 +1,57 @@ +createContainer(); + + $this->controller = new LogoutController($this->container); + + setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, $cookie = 'hi there'); + } + + public function testValidControllerInvoke(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches'); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->expects(static::once())->method('logout'); + + static::assertSame('hi there', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertContains('./', $result->getHeader('Location')); + static::assertSame('false', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); + } +} diff --git a/tests/front/controller/admin/SessionFilterControllerTest.php b/tests/front/controller/admin/SessionFilterControllerTest.php new file mode 100644 index 00000000..f50f2fc2 --- /dev/null +++ b/tests/front/controller/admin/SessionFilterControllerTest.php @@ -0,0 +1,348 @@ +createContainer(); + + $this->controller = new SessionFilterController($this->container); + } + + /** + * Link per page - Default call with valid parameter and a referer. + */ + public function testLinksPerPage(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $request->method('getParam')->with('nb')->willReturn('8'); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_LINKS_PER_PAGE, 8) + ; + + $result = $this->controller->linksPerPage($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Link per page - Invalid value, should use default value (20) + */ + public function testLinksPerPageNotValid(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $request->method('getParam')->with('nb')->willReturn('test'); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_LINKS_PER_PAGE, 20) + ; + + $result = $this->controller->linksPerPage($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder'], $result->getHeader('location')); + } + + /** + * Visibility - Default call for private filter while logged in without current value + */ + public function testVisibility(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'private']; + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_VISIBILITY, 'private') + ; + + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Visibility - Toggle off private visibility + */ + public function testVisibilityToggleOff(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'private']; + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ->willReturn('private') + ; + $this->container->sessionManager + ->expects(static::never()) + ->method('setSessionParameter') + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('deleteSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ; + + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Visibility - Change private to public + */ + public function testVisibilitySwitch(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'private']; + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ->willReturn('public') + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_VISIBILITY, 'private') + ; + + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder'], $result->getHeader('location')); + } + + /** + * Visibility - With invalid value - should remove any visibility setting + */ + public function testVisibilityInvalidValue(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'test']; + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $this->container->sessionManager + ->expects(static::never()) + ->method('setSessionParameter') + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('deleteSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ; + + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Visibility - Try to change visibility while logged out + */ + public function testVisibilityLoggedOut(): void + { + $this->createValidContainerMockSet(); + + $arg = ['visibility' => 'test']; + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(false); + $this->container->sessionManager + ->expects(static::never()) + ->method('setSessionParameter') + ; + $this->container->sessionManager + ->expects(static::never()) + ->method('deleteSessionParameter') + ->with(SessionManager::KEY_VISIBILITY) + ; + + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $response = new Response(); + + $result = $this->controller->visibility($request, $response, $arg); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Untagged only - valid call + */ + public function testUntaggedOnly(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_UNTAGGED_ONLY, true) + ; + + $result = $this->controller->untaggedOnly($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } + + /** + * Untagged only - toggle off + */ + public function testUntaggedOnlyToggleOff(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; + + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + + $response = new Response(); + + $this->container->sessionManager + ->method('getSessionParameter') + ->with(SessionManager::KEY_UNTAGGED_ONLY) + ->willReturn(true) + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_UNTAGGED_ONLY, false) + ; + + $result = $this->controller->untaggedOnly($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location')); + } +} diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php new file mode 100644 index 00000000..6ff769fc --- /dev/null +++ b/tests/front/controller/visitor/DailyControllerTest.php @@ -0,0 +1,497 @@ +createContainer(); + + $this->controller = new DailyController($this->container); + DailyController::$DAILY_RSS_NB_DAYS = 2; + } + + public function testValidIndexControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $currentDay = new \DateTimeImmutable('2020-05-13'); + + $request = $this->createMock(Request::class); + $request->method('getQueryParam')->willReturn($currentDay->format('Ymd')); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function () use ($currentDay): array { + return [ + '20200510', + $currentDay->format('Ymd'), + '20200516', + ]; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return [ + (new Bookmark()) + ->setId(1) + ->setUrl('http://url.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + (new Bookmark()) + ->setId(2) + ->setUrl('http://url2.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + (new Bookmark()) + ->setId(3) + ->setUrl('http://url3.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + ]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { + static::assertSame('render_daily', $hook); + + static::assertArrayHasKey('linksToDisplay', $data); + static::assertCount(3, $data['linksToDisplay']); + static::assertSame(1, $data['linksToDisplay'][0]['id']); + static::assertSame($currentDay->getTimestamp(), $data['day']); + static::assertSame('20200510', $data['previousday']); + static::assertSame('20200516', $data['nextday']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertSame( + 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', + $assignedVariables['pagetitle'] + ); + static::assertEquals($currentDay, $assignedVariables['dayDate']); + static::assertEquals($currentDay->getTimestamp(), $assignedVariables['day']); + static::assertCount(3, $assignedVariables['linksToDisplay']); + + $link = $assignedVariables['linksToDisplay'][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['linksToDisplay'][1]; + + static::assertSame(2, $link['id']); + static::assertSame('http://url2.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['linksToDisplay'][2]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + static::assertCount(3, $assignedVariables['cols']); + static::assertCount(1, $assignedVariables['cols'][0]); + static::assertCount(1, $assignedVariables['cols'][1]); + static::assertCount(1, $assignedVariables['cols'][2]); + + $link = $assignedVariables['cols'][0][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['cols'][1][0]; + + static::assertSame(2, $link['id']); + static::assertSame('http://url2.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['cols'][2][0]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + } + + /** + * Daily page - test that everything goes fine with no future or past bookmarks + */ + public function testValidIndexControllerInvokeNoFutureOrPast(): void + { + $this->createValidContainerMockSet(); + + $currentDay = new \DateTimeImmutable('2020-05-13'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function () use ($currentDay): array { + return [ + $currentDay->format($currentDay->format('Ymd')), + ]; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return [ + (new Bookmark()) + ->setId(1) + ->setUrl('http://url.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + ]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { + static::assertSame('render_daily', $hook); + + static::assertArrayHasKey('linksToDisplay', $data); + static::assertCount(1, $data['linksToDisplay']); + static::assertSame(1, $data['linksToDisplay'][0]['id']); + static::assertSame($currentDay->getTimestamp(), $data['day']); + static::assertEmpty($data['previousday']); + static::assertEmpty($data['nextday']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertSame( + 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', + $assignedVariables['pagetitle'] + ); + static::assertCount(1, $assignedVariables['linksToDisplay']); + + $link = $assignedVariables['linksToDisplay'][0]; + static::assertSame(1, $link['id']); + } + + /** + * Daily page - test that height adjustment in columns is working + */ + public function testValidIndexControllerInvokeHeightAdjustment(): void + { + $this->createValidContainerMockSet(); + + $currentDay = new \DateTimeImmutable('2020-05-13'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function () use ($currentDay): array { + return [ + $currentDay->format($currentDay->format('Ymd')), + ]; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return [ + (new Bookmark())->setId(1)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark()) + ->setId(2) + ->setUrl('http://url.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(5000)) + , + (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(5)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(6)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(7)->setUrl('http://url.tld')->setTitle('title'), + ]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertCount(7, $assignedVariables['linksToDisplay']); + + $columnIds = function (array $column): array { + return array_map(function (array $item): int { return $item['id']; }, $column); + }; + + static::assertSame([1, 4, 6], $columnIds($assignedVariables['cols'][0])); + static::assertSame([2], $columnIds($assignedVariables['cols'][1])); + static::assertSame([3, 5, 7], $columnIds($assignedVariables['cols'][2])); + } + + /** + * Daily page - no bookmark + */ + public function testValidIndexControllerInvokeNoBookmark(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function (): array { + return []; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertCount(0, $assignedVariables['linksToDisplay']); + static::assertSame('Today', $assignedVariables['dayDesc']); + static::assertEquals((new \DateTime())->setTime(0, 0)->getTimestamp(), $assignedVariables['day']); + static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']); + } + + /** + * Daily RSS - default behaviour + */ + public function testValidRssControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $dates = [ + new \DateTimeImmutable('2020-05-17'), + new \DateTimeImmutable('2020-05-15'), + new \DateTimeImmutable('2020-05-13'), + ]; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ + (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), + (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), + (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), + (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'), + ]); + + $this->container->pageCacheManager + ->expects(static::once()) + ->method('getCachePage') + ->willReturnCallback(function (): CachedPage { + $cachedPage = $this->createMock(CachedPage::class); + $cachedPage->expects(static::once())->method('cache')->with('dailyrss'); + + return $cachedPage; + } + ); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('dailyrss', (string) $result->getBody()); + static::assertSame('Shaarli', $assignedVariables['title']); + static::assertSame('http://shaarli', $assignedVariables['index_url']); + static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); + static::assertFalse($assignedVariables['hide_timestamps']); + static::assertCount(2, $assignedVariables['days']); + + $day = $assignedVariables['days'][$dates[0]->format('Ymd')]; + + static::assertEquals($dates[0], $day['date']); + static::assertSame($dates[0]->format(\DateTime::RSS), $day['date_rss']); + static::assertSame(format_date($dates[0], false), $day['date_human']); + static::assertSame('http://shaarli/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']); + static::assertCount(1, $day['links']); + static::assertSame(1, $day['links'][0]['id']); + static::assertSame('http://domain.tld/1', $day['links'][0]['url']); + static::assertEquals($dates[0], $day['links'][0]['created']); + + $day = $assignedVariables['days'][$dates[1]->format('Ymd')]; + + static::assertEquals($dates[1], $day['date']); + static::assertSame($dates[1]->format(\DateTime::RSS), $day['date_rss']); + static::assertSame(format_date($dates[1], false), $day['date_human']); + static::assertSame('http://shaarli/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']); + static::assertCount(2, $day['links']); + + static::assertSame(2, $day['links'][0]['id']); + static::assertSame('http://domain.tld/2', $day['links'][0]['url']); + static::assertEquals($dates[1], $day['links'][0]['created']); + static::assertSame(3, $day['links'][1]['id']); + static::assertSame('http://domain.tld/3', $day['links'][1]['url']); + static::assertEquals($dates[1], $day['links'][1]['created']); + } + + /** + * Daily RSS - trigger cache rendering + */ + public function testValidRssControllerInvokeTriggerCache(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->pageCacheManager->method('getCachePage')->willReturnCallback(function (): CachedPage { + $cachedPage = $this->createMock(CachedPage::class); + $cachedPage->method('cachedVersion')->willReturn('this is cache!'); + + return $cachedPage; + }); + + $this->container->bookmarkService->expects(static::never())->method('search'); + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('this is cache!', (string) $result->getBody()); + } + + /** + * Daily RSS - No bookmark + */ + public function testValidRssControllerInvokeNoBookmark(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([]); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('dailyrss', (string) $result->getBody()); + static::assertSame('Shaarli', $assignedVariables['title']); + static::assertSame('http://shaarli', $assignedVariables['index_url']); + static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); + static::assertFalse($assignedVariables['hide_timestamps']); + static::assertCount(0, $assignedVariables['days']); + } + + protected static function generateContent(int $length): string + { + // bin2hex(random_bytes) generates string twice as long as given parameter + $length = (int) ceil($length / 2); + return bin2hex(random_bytes($length)); + } +} diff --git a/tests/front/controller/visitor/FeedControllerTest.php b/tests/front/controller/visitor/FeedControllerTest.php new file mode 100644 index 00000000..fd4679ea --- /dev/null +++ b/tests/front/controller/visitor/FeedControllerTest.php @@ -0,0 +1,151 @@ +createContainer(); + + $this->container->feedBuilder = $this->createMock(FeedBuilder::class); + + $this->controller = new FeedController($this->container); + } + + /** + * Feed Controller - RSS default behaviour + */ + public function testDefaultRssController(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->feedBuilder->expects(static::once())->method('setLocale'); + $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); + $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): void { + static::assertSame('render_feed', $hook); + static::assertSame('data', $data['content']); + + static::assertArrayHasKey('loggedin', $param); + static::assertSame('rss', $param['target']); + }) + ; + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('feed.rss', (string) $result->getBody()); + static::assertSame('data', $assignedVariables['content']); + } + + /** + * Feed Controller - ATOM default behaviour + */ + public function testDefaultAtomController(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->feedBuilder->expects(static::once())->method('setLocale'); + $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); + $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): void { + static::assertSame('render_feed', $hook); + static::assertSame('data', $data['content']); + + static::assertArrayHasKey('loggedin', $param); + static::assertSame('atom', $param['target']); + }) + ; + + $result = $this->controller->atom($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); + static::assertSame('feed.atom', (string) $result->getBody()); + static::assertSame('data', $assignedVariables['content']); + } + + /** + * Feed Controller - ATOM with parameters + */ + public function testAtomControllerWithParameters(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->method('getParams')->willReturn(['parameter' => 'value']); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->feedBuilder + ->method('buildData') + ->with('atom', ['parameter' => 'value']) + ->willReturn(['content' => 'data']) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): void { + static::assertSame('render_feed', $hook); + static::assertSame('data', $data['content']); + + static::assertArrayHasKey('loggedin', $param); + static::assertSame('atom', $param['target']); + }) + ; + + $result = $this->controller->atom($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); + static::assertSame('feed.atom', (string) $result->getBody()); + static::assertSame('data', $assignedVariables['content']); + } +} diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php new file mode 100644 index 00000000..bc3266b5 --- /dev/null +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php @@ -0,0 +1,114 @@ +container = $this->createMock(ShaarliTestContainer::class); + } + + /** + * Initialize container's services used by tests + */ + protected function createValidContainerMockSet(): void + { + $this->container->loginManager = $this->createMock(LoginManager::class); + + // Config + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + return $default; + }); + + // PageBuilder + $this->container->pageBuilder = $this->createMock(PageBuilder::class); + $this->container->pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + + // Plugin Manager + $this->container->pluginManager = $this->createMock(PluginManager::class); + + // BookmarkService + $this->container->bookmarkService = $this->createMock(BookmarkServiceInterface::class); + + // Formatter + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->method('getFormatter') + ->willReturnCallback(function (): BookmarkFormatter { + return new BookmarkRawFormatter($this->container->conf, true); + }) + ; + + // CacheManager + $this->container->pageCacheManager = $this->createMock(PageCacheManager::class); + + // SessionManager + $this->container->sessionManager = $this->createMock(SessionManager::class); + + // $_SERVER + $this->container->environment = [ + 'SERVER_NAME' => 'shaarli', + 'SERVER_PORT' => '80', + 'REQUEST_URI' => '/daily-rss', + ]; + } + + /** + * Pass a reference of an array which will be populated by `pageBuilder->assign` calls during execution. + * + * @param mixed $variables Array reference to populate. + */ + protected function assignTemplateVars(array &$variables): void + { + $this->container->pageBuilder + ->expects(static::atLeastOnce()) + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$variables) { + $variables[$key] = $value; + + return $this; + }) + ; + } + + /** + * Force to be used in PHPUnit context. + */ + protected abstract function createMock($originalClassName): MockObject; +} diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php new file mode 100644 index 00000000..9d223316 --- /dev/null +++ b/tests/front/controller/visitor/LoginControllerTest.php @@ -0,0 +1,144 @@ +createContainer(); + + $this->controller = new LoginController($this->container); + } + + public function testValidControllerInvoke(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); + $response = new Response(); + + $assignedVariables = []; + $this->container->pageBuilder + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { + $assignedVariables[$key] = $value; + + return $this; + }) + ; + + $this->container->loginManager->method('canLogin')->willReturn(true); + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(200, $result->getStatusCode()); + static::assertSame('loginform', (string) $result->getBody()); + + static::assertSame('> referer', $assignedVariables['returnurl']); + static::assertSame(true, $assignedVariables['remember_user_default']); + static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); + } + + public function testValidControllerInvokeWithUserName(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); + $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); + $response = new Response(); + + $assignedVariables = []; + $this->container->pageBuilder + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { + $assignedVariables[$key] = $value; + + return $this; + }) + ; + + $this->container->loginManager->expects(static::once())->method('canLogin')->willReturn(true); + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(200, $result->getStatusCode()); + static::assertSame('loginform', (string) $result->getBody()); + + static::assertSame('myUser>', $assignedVariables['username']); + static::assertSame('> referer', $assignedVariables['returnurl']); + static::assertSame(true, $assignedVariables['remember_user_default']); + static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); + } + + public function testLoginControllerWhileLoggedIn(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true); + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('Location')); + } + + public function testLoginControllerOpenShaarli(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $conf = $this->createMock(ConfigManager::class); + $conf->method('get')->willReturnCallback(function (string $parameter, $default) { + if ($parameter === 'security.open_shaarli') { + return true; + } + return $default; + }); + $this->container->conf = $conf; + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('Location')); + } + + public function testLoginControllerWhileBanned(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->loginManager->method('isLoggedIn')->willReturn(false); + $this->container->loginManager->method('canLogin')->willReturn(false); + + $this->expectException(LoginBannedException::class); + + $this->controller->index($request, $response); + } +} diff --git a/tests/front/controller/visitor/OpenSearchControllerTest.php b/tests/front/controller/visitor/OpenSearchControllerTest.php new file mode 100644 index 00000000..52475318 --- /dev/null +++ b/tests/front/controller/visitor/OpenSearchControllerTest.php @@ -0,0 +1,46 @@ +createContainer(); + + $this->controller = new OpenSearchController($this->container); + } + + public function testOpenSearchController(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString( + 'application/opensearchdescription+xml', + $result->getHeader('Content-Type')[0] + ); + static::assertSame('opensearch', (string) $result->getBody()); + static::assertSame('http://shaarli', $assignedVariables['serverurl']); + } +} diff --git a/tests/front/controller/visitor/PictureWallControllerTest.php b/tests/front/controller/visitor/PictureWallControllerTest.php new file mode 100644 index 00000000..7ac842cb --- /dev/null +++ b/tests/front/controller/visitor/PictureWallControllerTest.php @@ -0,0 +1,125 @@ +createContainer(); + + $this->controller = new PictureWallController($this->container); + } + + public function testValidControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getQueryParams')->willReturn([]); + $response = new Response(); + + // ConfigManager: thumbnails are enabled + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + if ($parameter === 'thumbnails.mode') { + return Thumbnailer::MODE_COMMON; + } + + return $default; + }); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + // Visibility is set through the container, not the call + static::assertNull($visibility); + + // No query parameters + if (count($parameters) === 0) { + return [ + (new Bookmark())->setId(1)->setUrl('http://url.tld')->setThumbnail('thumb1'), + (new Bookmark())->setId(2)->setUrl('http://url2.tld'), + (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setThumbnail('thumb2'), + ]; + } + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_picwall', $hook); + static::assertArrayHasKey('linksToDisplay', $data); + static::assertCount(2, $data['linksToDisplay']); + static::assertSame(1, $data['linksToDisplay'][0]['id']); + static::assertSame(3, $data['linksToDisplay'][1]['id']); + static::assertArrayHasKey('loggedin', $param); + + return $data; + }); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('picwall', (string) $result->getBody()); + static::assertSame('Picture wall - Shaarli', $assignedVariables['pagetitle']); + static::assertCount(2, $assignedVariables['linksToDisplay']); + + $link = $assignedVariables['linksToDisplay'][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url.tld', $link['url']); + static::assertSame('thumb1', $link['thumbnail']); + + $link = $assignedVariables['linksToDisplay'][1]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertSame('thumb2', $link['thumbnail']); + } + + public function testControllerWithThumbnailsDisabled(): void + { + $this->expectException(ThumbnailsDisabledException::class); + + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // ConfigManager: thumbnails are disabled + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + if ($parameter === 'thumbnails.mode') { + return Thumbnailer::MODE_NONE; + } + + return $default; + }); + + $this->controller->index($request, $response); + } +} diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php new file mode 100644 index 00000000..e2e88da3 --- /dev/null +++ b/tests/front/controller/visitor/ShaarliPublicControllerTest.php @@ -0,0 +1,239 @@ +createContainer(); + + $this->controller = new class($this->container) extends ShaarliVisitorController + { + public function assignView(string $key, $value): ShaarliVisitorController + { + return parent::assignView($key, $value); + } + + public function render(string $template): string + { + return parent::render($template); + } + + public function redirectFromReferer( + Request $request, + Response $response, + array $loopTerms = [], + array $clearParams = [] + ): Response { + return parent::redirectFromReferer($request, $response, $loopTerms, $clearParams); + } + }; + $this->assignedValues = []; + + $this->request = $this->createMock(Request::class); + $this->request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + } + + public function testAssignView(): void + { + $this->createValidContainerMockSet(); + + $this->assignTemplateVars($this->assignedValues); + + $self = $this->controller->assignView('variableName', 'variableValue'); + + static::assertInstanceOf(ShaarliVisitorController::class, $self); + static::assertSame('variableValue', $this->assignedValues['variableName']); + } + + public function testRender(): void + { + $this->createValidContainerMockSet(); + + $this->assignTemplateVars($this->assignedValues); + + $this->container->bookmarkService + ->method('count') + ->willReturnCallback(function (string $visibility): int { + return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; + }) + ; + + $this->container->pluginManager + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array &$data, array $params): array { + return $data[$hook] = $params; + }); + $this->container->pluginManager->method('getErrors')->willReturn(['error']); + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $render = $this->controller->render('templateName'); + + static::assertSame('templateName', $render); + + static::assertSame(10, $this->assignedValues['linkcount']); + static::assertSame(5, $this->assignedValues['privateLinkcount']); + static::assertSame(['error'], $this->assignedValues['plugin_errors']); + + static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); + static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); + static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); + static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); + } + + /** + * Test redirectFromReferer() - Default behaviour + */ + public function testRedirectFromRefererDefault(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term not matched in the referer + */ + public function testRedirectFromRefererWithUnmatchedLoopTerm(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInPath(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'controller']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'other']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query value + * -> we do not block redirection for query parameter values. + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'param']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its domain name + * -> we do not block redirection for shaarli's hosts + */ + public function testRedirectFromRefererWithLoopTermInDomain(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['shaarli']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param + * -> the param should be cleared before checking if it matches the redir loop terms + */ + public function testRedirectFromRefererWithMatchingClearedParam(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['query'], ['query']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location')); + } +} diff --git a/tests/front/controller/visitor/TagCloudControllerTest.php b/tests/front/controller/visitor/TagCloudControllerTest.php new file mode 100644 index 00000000..e636d496 --- /dev/null +++ b/tests/front/controller/visitor/TagCloudControllerTest.php @@ -0,0 +1,381 @@ +createContainer(); + + $this->controller = new TagCloudController($this->container); + } + + /** + * Tag Cloud - default parameters + */ + public function testValidCloudControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $allTags = [ + 'ghi' => 1, + 'abc' => 3, + 'def' => 12, + ]; + $expectedOrder = ['abc', 'def', 'ghi']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function () use ($allTags): array { + return $allTags; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(3, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->cloud($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(3, $assignedVariables['tags']); + static::assertSame($expectedOrder, array_keys($assignedVariables['tags'])); + + foreach ($allTags as $tag => $count) { + static::assertArrayHasKey($tag, $assignedVariables['tags']); + static::assertSame($count, $assignedVariables['tags'][$tag]['count']); + static::assertGreaterThan(0, $assignedVariables['tags'][$tag]['size']); + static::assertLessThan(5, $assignedVariables['tags'][$tag]['size']); + } + } + + /** + * Tag Cloud - Additional parameters: + * - logged in + * - visibility private + * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) + */ + public function testValidCloudControllerInvokeWithParameters(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request + ->method('getQueryParam') + ->with() + ->willReturnCallback(function (string $key): ?string { + if ('searchtags' === $key) { + return 'ghi def'; + } + + return null; + }) + ; + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->loginManager->method('isLoggedin')->willReturn(true); + $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) + ->willReturnCallback(function (): array { + return ['abc' => 3]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('ghi def', $data['search_tags']); + static::assertCount(1, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->cloud($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('ghi def - Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('ghi def', $assignedVariables['search_tags']); + static::assertCount(1, $assignedVariables['tags']); + + static::assertArrayHasKey('abc', $assignedVariables['tags']); + static::assertSame(3, $assignedVariables['tags']['abc']['count']); + static::assertGreaterThan(0, $assignedVariables['tags']['abc']['size']); + static::assertLessThan(5, $assignedVariables['tags']['abc']['size']); + } + + /** + * Tag Cloud - empty + */ + public function testEmptyCloud(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(0, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->cloud($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(0, $assignedVariables['tags']); + } + + /** + * Tag List - Default sort is by usage DESC + */ + public function testValidListControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $allTags = [ + 'def' => 12, + 'abc' => 3, + 'ghi' => 1, + ]; + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function () use ($allTags): array { + return $allTags; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_taglist', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(3, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->list($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.list', (string) $result->getBody()); + static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(3, $assignedVariables['tags']); + + foreach ($allTags as $tag => $count) { + static::assertSame($count, $assignedVariables['tags'][$tag]); + } + } + + /** + * Tag List - Additional parameters: + * - logged in + * - visibility private + * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) + * - sort alphabetically + */ + public function testValidListControllerInvokeWithParameters(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request + ->method('getQueryParam') + ->with() + ->willReturnCallback(function (string $key): ?string { + if ('searchtags' === $key) { + return 'ghi def'; + } elseif ('sort' === $key) { + return 'alpha'; + } + + return null; + }) + ; + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->loginManager->method('isLoggedin')->willReturn(true); + $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) + ->willReturnCallback(function (): array { + return ['abc' => 3]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_taglist', $hook); + static::assertSame('ghi def', $data['search_tags']); + static::assertCount(1, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->list($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.list', (string) $result->getBody()); + static::assertSame('ghi def - Tag list - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('ghi def', $assignedVariables['search_tags']); + static::assertCount(1, $assignedVariables['tags']); + static::assertSame(3, $assignedVariables['tags']['abc']); + } + + /** + * Tag List - empty + */ + public function testEmptyList(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_taglist', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(0, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->list($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.list', (string) $result->getBody()); + static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(0, $assignedVariables['tags']); + } +} diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php new file mode 100644 index 00000000..9a2b1f71 --- /dev/null +++ b/tests/front/controller/visitor/TagControllerTest.php @@ -0,0 +1,241 @@ +createContainer(); + + $this->controller = new TagController($this->container); + } + + public function testAddTagWithReferer(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); + } + + public function testAddTagWithRefererAndExistingSearch(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); + } + + public function testAddTagWithoutRefererAndExistingSearch(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./?searchtags=abc'], $result->getHeader('location')); + } + + public function testAddTagRemoveLegacyQueryParam(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); + } + + public function testAddTagResetPagination(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); + } + + public function testAddTagWithRefererAndEmptySearch(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); + } + + public function testAddTagWithoutNewTagWithReferer(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->addTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); + } + + public function testAddTagWithoutNewTagWithoutReferer(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->addTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutMatchingTag(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['tag' => 'abc']; + + $result = $this->controller->removeTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutTagsearch(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['tag' => 'abc']; + + $result = $this->controller->removeTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutReferer(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['tag' => 'abc']; + + $result = $this->controller->removeTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutTag(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->removeTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtag=abc'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutTagWithoutReferer(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->removeTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } +} -- cgit v1.2.3 From ba43064ddb7771fc97df135a32f9b0d5e373dd36 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 22 May 2020 13:47:02 +0200 Subject: Process tools page through Slim controller --- .../controller/admin/LogoutControllerTest.php | 2 +- .../front/controller/admin/ToolsControllerTest.php | 73 ++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/front/controller/admin/ToolsControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/LogoutControllerTest.php b/tests/front/controller/admin/LogoutControllerTest.php index 239e39b2..ba681b16 100644 --- a/tests/front/controller/admin/LogoutControllerTest.php +++ b/tests/front/controller/admin/LogoutControllerTest.php @@ -5,7 +5,7 @@ declare(strict_types=1); namespace Shaarli\Front\Controller\Admin; /** Override PHP builtin setcookie function in the local namespace to mock it... more or less */ -if (!function_exists('Shaarli\Front\Controller\setcookie')) { +if (!function_exists('Shaarli\Front\Controller\Admin\setcookie')) { function setcookie(string $name, string $value): void { $_COOKIE[$name] = $value; } diff --git a/tests/front/controller/admin/ToolsControllerTest.php b/tests/front/controller/admin/ToolsControllerTest.php new file mode 100644 index 00000000..47c5746e --- /dev/null +++ b/tests/front/controller/admin/ToolsControllerTest.php @@ -0,0 +1,73 @@ +createContainer(); + + $this->controller = new ToolsController($this->container); + } + + public function testDefaultInvokeWithHttps(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->environment = [ + 'SERVER_NAME' => 'shaarli', + 'SERVER_PORT' => 443, + 'HTTPS' => 'on', + ]; + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tools', (string) $result->getBody()); + static::assertSame('https://shaarli', $assignedVariables['pageabsaddr']); + static::assertTrue($assignedVariables['sslenabled']); + } + + public function testDefaultInvokeWithoutHttps(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->environment = [ + 'SERVER_NAME' => 'shaarli', + 'SERVER_PORT' => 80, + ]; + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tools', (string) $result->getBody()); + static::assertSame('http://shaarli', $assignedVariables['pageabsaddr']); + static::assertFalse($assignedVariables['sslenabled']); + } +} -- cgit v1.2.3 From ef00f9d2033f6de11e71bf3a909399cae6f73a9f Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 27 May 2020 13:35:48 +0200 Subject: Process password change controller through Slim --- .../admin/FrontAdminControllerMockHelper.php | 3 +- .../controller/admin/LogoutControllerTest.php | 2 - .../controller/admin/PasswordControllerTest.php | 186 +++++++++++++++++++++ .../admin/SessionFilterControllerTest.php | 18 -- .../front/controller/admin/ToolsControllerTest.php | 4 - .../controller/visitor/DailyControllerTest.php | 14 -- .../controller/visitor/FeedControllerTest.php | 6 - .../visitor/FrontControllerMockHelper.php | 8 +- .../controller/visitor/LoginControllerTest.php | 10 -- .../visitor/OpenSearchControllerTest.php | 2 - .../visitor/PictureWallControllerTest.php | 4 - .../visitor/ShaarliPublicControllerTest.php | 18 -- .../controller/visitor/TagCloudControllerTest.php | 12 -- .../front/controller/visitor/TagControllerTest.php | 26 --- 14 files changed, 188 insertions(+), 125 deletions(-) create mode 100644 tests/front/controller/admin/PasswordControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/FrontAdminControllerMockHelper.php b/tests/front/controller/admin/FrontAdminControllerMockHelper.php index 94581c09..bd40c0c7 100644 --- a/tests/front/controller/admin/FrontAdminControllerMockHelper.php +++ b/tests/front/controller/admin/FrontAdminControllerMockHelper.php @@ -6,7 +6,6 @@ namespace Shaarli\Front\Controller\Admin; use Shaarli\Container\ShaarliTestContainer; use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper; -use Shaarli\Security\LoginManager; /** * Trait FrontControllerMockHelper @@ -28,7 +27,7 @@ trait FrontAdminControllerMockHelper { $this->parentCreateContainer(); - $this->container->loginManager = $this->createMock(LoginManager::class); $this->container->loginManager->method('isLoggedIn')->willReturn(true); + $this->container->sessionManager->method('checkToken')->willReturn(true); } } diff --git a/tests/front/controller/admin/LogoutControllerTest.php b/tests/front/controller/admin/LogoutControllerTest.php index ba681b16..78a0fe73 100644 --- a/tests/front/controller/admin/LogoutControllerTest.php +++ b/tests/front/controller/admin/LogoutControllerTest.php @@ -35,8 +35,6 @@ class LogoutControllerTest extends TestCase public function testValidControllerInvoke(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/admin/PasswordControllerTest.php b/tests/front/controller/admin/PasswordControllerTest.php new file mode 100644 index 00000000..7262243e --- /dev/null +++ b/tests/front/controller/admin/PasswordControllerTest.php @@ -0,0 +1,186 @@ +createContainer(); + $this->assignTemplateVars($this->assignedVariables); + + $this->controller = new PasswordController($this->container); + } + + /** + * Test displaying the change password page. + */ + public function testGetPage(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('changepassword', (string) $result->getBody()); + static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']); + } + + /** + * Change the password with valid parameters + */ + public function testPostNewPasswordDefault(): void + { + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key): string { + if ('oldpassword' === $key) { + return 'old'; + } + if ('setpassword' === $key) { + return 'new'; + } + + return $key; + }); + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { + if ('credentials.hash' === $key) { + return sha1('old' . 'credentials.login' . 'credentials.salt'); + } + + return strpos($key, 'credentials') !== false ? $key : $default; + }); + $this->container->conf->expects(static::once())->method('write')->with(true); + + $this->container->conf + ->method('set') + ->willReturnCallback(function (string $key, string $value) { + if ('credentials.hash' === $key) { + static::assertSame(sha1('new' . 'credentials.login' . 'credentials.salt'), $value); + } + }) + ; + + $result = $this->controller->change($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('changepassword', (string) $result->getBody()); + static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']); + } + + /** + * Change the password with a wrong existing password + */ + public function testPostNewPasswordWrongOldPassword(): void + { + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key): string { + if ('oldpassword' === $key) { + return 'wrong'; + } + if ('setpassword' === $key) { + return 'new'; + } + + return $key; + }); + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { + if ('credentials.hash' === $key) { + return sha1('old' . 'credentials.login' . 'credentials.salt'); + } + + return strpos($key, 'credentials') !== false ? $key : $default; + }); + + $this->container->conf->expects(static::never())->method('set'); + $this->container->conf->expects(static::never())->method('write'); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['The old password is not correct.']) + ; + + $result = $this->controller->change($request, $response); + + static::assertSame(400, $result->getStatusCode()); + static::assertSame('changepassword', (string) $result->getBody()); + static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']); + } + + /** + * Change the password with a wrong existing password + */ + public function testPostNewPasswordWrongToken(): void + { + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->method('checkToken')->willReturn(false); + + $this->container->conf->expects(static::never())->method('set'); + $this->container->conf->expects(static::never())->method('write'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->expectException(WrongTokenException::class); + + $this->controller->change($request, $response); + } + + /** + * Change the password with an empty new password + */ + public function testPostNewEmptyPassword(): void + { + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['You must provide the current and new password to change it.']) + ; + + $this->container->conf->expects(static::never())->method('set'); + $this->container->conf->expects(static::never())->method('write'); + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key): string { + if ('oldpassword' === $key) { + return 'old'; + } + if ('setpassword' === $key) { + return ''; + } + + return $key; + }); + $response = new Response(); + + $result = $this->controller->change($request, $response); + + static::assertSame(400, $result->getStatusCode()); + static::assertSame('changepassword', (string) $result->getBody()); + static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']); + } +} diff --git a/tests/front/controller/admin/SessionFilterControllerTest.php b/tests/front/controller/admin/SessionFilterControllerTest.php index f50f2fc2..096963cf 100644 --- a/tests/front/controller/admin/SessionFilterControllerTest.php +++ b/tests/front/controller/admin/SessionFilterControllerTest.php @@ -30,8 +30,6 @@ class SessionFilterControllerTest extends TestCase */ public function testLinksPerPage(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; $request = $this->createMock(Request::class); @@ -62,8 +60,6 @@ class SessionFilterControllerTest extends TestCase */ public function testLinksPerPageNotValid(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request->method('getUri')->willReturnCallback(function (): Uri { $uri = $this->createMock(Uri::class); @@ -92,8 +88,6 @@ class SessionFilterControllerTest extends TestCase */ public function testVisibility(): void { - $this->createValidContainerMockSet(); - $arg = ['visibility' => 'private']; $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; @@ -126,8 +120,6 @@ class SessionFilterControllerTest extends TestCase */ public function testVisibilityToggleOff(): void { - $this->createValidContainerMockSet(); - $arg = ['visibility' => 'private']; $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; @@ -169,8 +161,6 @@ class SessionFilterControllerTest extends TestCase */ public function testVisibilitySwitch(): void { - $this->createValidContainerMockSet(); - $arg = ['visibility' => 'private']; $this->container->loginManager->method('isLoggedIn')->willReturn(true); @@ -206,8 +196,6 @@ class SessionFilterControllerTest extends TestCase */ public function testVisibilityInvalidValue(): void { - $this->createValidContainerMockSet(); - $arg = ['visibility' => 'test']; $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; @@ -244,8 +232,6 @@ class SessionFilterControllerTest extends TestCase */ public function testVisibilityLoggedOut(): void { - $this->createValidContainerMockSet(); - $arg = ['visibility' => 'test']; $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; @@ -283,8 +269,6 @@ class SessionFilterControllerTest extends TestCase */ public function testUntaggedOnly(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; $request = $this->createMock(Request::class); @@ -314,8 +298,6 @@ class SessionFilterControllerTest extends TestCase */ public function testUntaggedOnlyToggleOff(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; $request = $this->createMock(Request::class); diff --git a/tests/front/controller/admin/ToolsControllerTest.php b/tests/front/controller/admin/ToolsControllerTest.php index 47c5746e..fc756f0f 100644 --- a/tests/front/controller/admin/ToolsControllerTest.php +++ b/tests/front/controller/admin/ToolsControllerTest.php @@ -24,8 +24,6 @@ class ToolsControllerTestControllerTest extends TestCase public function testDefaultInvokeWithHttps(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -49,8 +47,6 @@ class ToolsControllerTestControllerTest extends TestCase public function testDefaultInvokeWithoutHttps(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php index 6ff769fc..872420fd 100644 --- a/tests/front/controller/visitor/DailyControllerTest.php +++ b/tests/front/controller/visitor/DailyControllerTest.php @@ -27,8 +27,6 @@ class DailyControllerTest extends TestCase public function testValidIndexControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $currentDay = new \DateTimeImmutable('2020-05-13'); $request = $this->createMock(Request::class); @@ -169,8 +167,6 @@ class DailyControllerTest extends TestCase */ public function testValidIndexControllerInvokeNoFutureOrPast(): void { - $this->createValidContainerMockSet(); - $currentDay = new \DateTimeImmutable('2020-05-13'); $request = $this->createMock(Request::class); @@ -243,8 +239,6 @@ class DailyControllerTest extends TestCase */ public function testValidIndexControllerInvokeHeightAdjustment(): void { - $this->createValidContainerMockSet(); - $currentDay = new \DateTimeImmutable('2020-05-13'); $request = $this->createMock(Request::class); @@ -314,8 +308,6 @@ class DailyControllerTest extends TestCase */ public function testValidIndexControllerInvokeNoBookmark(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -363,8 +355,6 @@ class DailyControllerTest extends TestCase */ public function testValidRssControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $dates = [ new \DateTimeImmutable('2020-05-17'), new \DateTimeImmutable('2020-05-15'), @@ -439,8 +429,6 @@ class DailyControllerTest extends TestCase */ public function testValidRssControllerInvokeTriggerCache(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -465,8 +453,6 @@ class DailyControllerTest extends TestCase */ public function testValidRssControllerInvokeNoBookmark(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/FeedControllerTest.php b/tests/front/controller/visitor/FeedControllerTest.php index fd4679ea..fb417e2a 100644 --- a/tests/front/controller/visitor/FeedControllerTest.php +++ b/tests/front/controller/visitor/FeedControllerTest.php @@ -30,8 +30,6 @@ class FeedControllerTest extends TestCase */ public function testDefaultRssController(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -71,8 +69,6 @@ class FeedControllerTest extends TestCase */ public function testDefaultAtomController(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -112,8 +108,6 @@ class FeedControllerTest extends TestCase */ public function testAtomControllerWithParameters(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request->method('getParams')->willReturn(['parameter' => 'value']); $response = new Response(); diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php index bc3266b5..d16b6949 100644 --- a/tests/front/controller/visitor/FrontControllerMockHelper.php +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php @@ -31,18 +31,12 @@ trait FrontControllerMockHelper protected $container; /** - * Mock the container instance + * Mock the container instance and initialize container's services used by tests */ protected function createContainer(): void { $this->container = $this->createMock(ShaarliTestContainer::class); - } - /** - * Initialize container's services used by tests - */ - protected function createValidContainerMockSet(): void - { $this->container->loginManager = $this->createMock(LoginManager::class); // Config diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php index 9d223316..faa8ac71 100644 --- a/tests/front/controller/visitor/LoginControllerTest.php +++ b/tests/front/controller/visitor/LoginControllerTest.php @@ -26,8 +26,6 @@ class LoginControllerTest extends TestCase public function testValidControllerInvoke(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); $response = new Response(); @@ -57,8 +55,6 @@ class LoginControllerTest extends TestCase public function testValidControllerInvokeWithUserName(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); @@ -90,8 +86,6 @@ class LoginControllerTest extends TestCase public function testLoginControllerWhileLoggedIn(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -106,8 +100,6 @@ class LoginControllerTest extends TestCase public function testLoginControllerOpenShaarli(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -129,8 +121,6 @@ class LoginControllerTest extends TestCase public function testLoginControllerWhileBanned(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/OpenSearchControllerTest.php b/tests/front/controller/visitor/OpenSearchControllerTest.php index 52475318..5f9f5b12 100644 --- a/tests/front/controller/visitor/OpenSearchControllerTest.php +++ b/tests/front/controller/visitor/OpenSearchControllerTest.php @@ -24,8 +24,6 @@ class OpenSearchControllerTest extends TestCase public function testOpenSearchController(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/PictureWallControllerTest.php b/tests/front/controller/visitor/PictureWallControllerTest.php index 7ac842cb..3dc3f292 100644 --- a/tests/front/controller/visitor/PictureWallControllerTest.php +++ b/tests/front/controller/visitor/PictureWallControllerTest.php @@ -28,8 +28,6 @@ class PictureWallControllerTest extends TestCase public function testValidControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request->expects(static::once())->method('getQueryParams')->willReturn([]); $response = new Response(); @@ -106,8 +104,6 @@ class PictureWallControllerTest extends TestCase { $this->expectException(ThumbnailsDisabledException::class); - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php index e2e88da3..1f7d57ad 100644 --- a/tests/front/controller/visitor/ShaarliPublicControllerTest.php +++ b/tests/front/controller/visitor/ShaarliPublicControllerTest.php @@ -67,8 +67,6 @@ class ShaarliControllerTest extends TestCase public function testAssignView(): void { - $this->createValidContainerMockSet(); - $this->assignTemplateVars($this->assignedValues); $self = $this->controller->assignView('variableName', 'variableValue'); @@ -79,8 +77,6 @@ class ShaarliControllerTest extends TestCase public function testRender(): void { - $this->createValidContainerMockSet(); - $this->assignTemplateVars($this->assignedValues); $this->container->bookmarkService @@ -120,8 +116,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererDefault(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -137,8 +131,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithUnmatchedLoopTerm(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -154,8 +146,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithMatchingLoopTermInPath(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -171,8 +161,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -189,8 +177,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -207,8 +193,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithLoopTermInDomain(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -225,8 +209,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithMatchingClearedParam(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); diff --git a/tests/front/controller/visitor/TagCloudControllerTest.php b/tests/front/controller/visitor/TagCloudControllerTest.php index e636d496..9a6a4bc0 100644 --- a/tests/front/controller/visitor/TagCloudControllerTest.php +++ b/tests/front/controller/visitor/TagCloudControllerTest.php @@ -28,8 +28,6 @@ class TagCloudControllerTest extends TestCase */ public function testValidCloudControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $allTags = [ 'ghi' => 1, 'abc' => 3, @@ -94,8 +92,6 @@ class TagCloudControllerTest extends TestCase */ public function testValidCloudControllerInvokeWithParameters(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request ->method('getQueryParam') @@ -161,8 +157,6 @@ class TagCloudControllerTest extends TestCase */ public function testEmptyCloud(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -209,8 +203,6 @@ class TagCloudControllerTest extends TestCase */ public function testValidListControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $allTags = [ 'def' => 12, 'abc' => 3, @@ -271,8 +263,6 @@ class TagCloudControllerTest extends TestCase */ public function testValidListControllerInvokeWithParameters(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request ->method('getQueryParam') @@ -336,8 +326,6 @@ class TagCloudControllerTest extends TestCase */ public function testEmptyList(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php index 9a2b1f71..1242a2e9 100644 --- a/tests/front/controller/visitor/TagControllerTest.php +++ b/tests/front/controller/visitor/TagControllerTest.php @@ -23,8 +23,6 @@ class TagControllerTest extends TestCase public function testAddTagWithReferer(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; $request = $this->createMock(Request::class); @@ -41,8 +39,6 @@ class TagControllerTest extends TestCase public function testAddTagWithRefererAndExistingSearch(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; $request = $this->createMock(Request::class); @@ -59,8 +55,6 @@ class TagControllerTest extends TestCase public function testAddTagWithoutRefererAndExistingSearch(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -75,8 +69,6 @@ class TagControllerTest extends TestCase public function testAddTagRemoveLegacyQueryParam(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; $request = $this->createMock(Request::class); @@ -93,8 +85,6 @@ class TagControllerTest extends TestCase public function testAddTagResetPagination(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; $request = $this->createMock(Request::class); @@ -111,8 +101,6 @@ class TagControllerTest extends TestCase public function testAddTagWithRefererAndEmptySearch(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; $request = $this->createMock(Request::class); @@ -129,8 +117,6 @@ class TagControllerTest extends TestCase public function testAddTagWithoutNewTagWithReferer(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; $request = $this->createMock(Request::class); @@ -145,8 +131,6 @@ class TagControllerTest extends TestCase public function testAddTagWithoutNewTagWithoutReferer(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -159,8 +143,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutMatchingTag(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; $request = $this->createMock(Request::class); @@ -177,8 +159,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutTagsearch(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; $request = $this->createMock(Request::class); @@ -195,8 +175,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutReferer(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -211,8 +189,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutTag(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc']; $request = $this->createMock(Request::class); @@ -227,8 +203,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutTagWithoutReferer(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); -- cgit v1.2.3 From fdedbfd4a7fb547da0e0ce65c6180f74aad90691 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 27 May 2020 14:13:49 +0200 Subject: Test ShaarliAdminController --- .../admin/ShaarliAdminControllerTest.php | 199 +++++++++++++++++++++ .../visitor/ShaarliPublicControllerTest.php | 2 +- 2 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 tests/front/controller/admin/ShaarliAdminControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ShaarliAdminControllerTest.php b/tests/front/controller/admin/ShaarliAdminControllerTest.php new file mode 100644 index 00000000..7c5f50a6 --- /dev/null +++ b/tests/front/controller/admin/ShaarliAdminControllerTest.php @@ -0,0 +1,199 @@ +createContainer(); + + $this->controller = new class($this->container) extends ShaarliAdminController + { + public function checkToken(Request $request): bool + { + return parent::checkToken($request); + } + + public function saveSuccessMessage(string $message): void + { + parent::saveSuccessMessage($message); + } + + public function saveWarningMessage(string $message): void + { + parent::saveWarningMessage($message); + } + + public function saveErrorMessage(string $message): void + { + parent::saveErrorMessage($message); + } + }; + } + + /** + * Creating an instance of an admin controller while logged out should raise an exception. + */ + public function testInstantiateWhileLoggedOut(): void + { + $this->expectException(UnauthorizedException::class); + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(false); + + $this->controller = new class($this->container) extends ShaarliAdminController {}; + } + + /** + * Trigger controller's checkToken with a valid token. + */ + public function testCheckTokenWithValidToken(): void + { + $request = $this->createMock(Request::class); + $request->method('getParam')->with('token')->willReturn($token = '12345'); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->method('checkToken')->with($token)->willReturn(true); + + static::assertTrue($this->controller->checkToken($request)); + } + + /** + * Trigger controller's checkToken with na valid token should raise an exception. + */ + public function testCheckTokenWithNotValidToken(): void + { + $request = $this->createMock(Request::class); + $request->method('getParam')->with('token')->willReturn($token = '12345'); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->method('checkToken')->with($token)->willReturn(false); + + $this->expectException(WrongTokenException::class); + + $this->controller->checkToken($request); + } + + /** + * Test saveSuccessMessage() with a first message. + */ + public function testSaveSuccessMessage(): void + { + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_SUCCESS_MESSAGES, [$message = 'bravo!']) + ; + + $this->controller->saveSuccessMessage($message); + } + + /** + * Test saveSuccessMessage() with existing messages. + */ + public function testSaveSuccessMessageWithExistingMessages(): void + { + $this->container->sessionManager + ->expects(static::once()) + ->method('getSessionParameter') + ->with(SessionManager::KEY_SUCCESS_MESSAGES) + ->willReturn(['success1', 'success2']) + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_SUCCESS_MESSAGES, ['success1', 'success2', $message = 'bravo!']) + ; + + $this->controller->saveSuccessMessage($message); + } + + /** + * Test saveWarningMessage() with a first message. + */ + public function testSaveWarningMessage(): void + { + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_WARNING_MESSAGES, [$message = 'warning!']) + ; + + $this->controller->saveWarningMessage($message); + } + + /** + * Test saveWarningMessage() with existing messages. + */ + public function testSaveWarningMessageWithExistingMessages(): void + { + $this->container->sessionManager + ->expects(static::once()) + ->method('getSessionParameter') + ->with(SessionManager::KEY_WARNING_MESSAGES) + ->willReturn(['warning1', 'warning2']) + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_WARNING_MESSAGES, ['warning1', 'warning2', $message = 'warning!']) + ; + + $this->controller->saveWarningMessage($message); + } + + /** + * Test saveErrorMessage() with a first message. + */ + public function testSaveErrorMessage(): void + { + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, [$message = 'error!']) + ; + + $this->controller->saveErrorMessage($message); + } + + /** + * Test saveErrorMessage() with existing messages. + */ + public function testSaveErrorMessageWithExistingMessages(): void + { + $this->container->sessionManager + ->expects(static::once()) + ->method('getSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES) + ->willReturn(['error1', 'error2']) + ; + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['error1', 'error2', $message = 'error!']) + ; + + $this->controller->saveErrorMessage($message); + } +} diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php index 1f7d57ad..899b280b 100644 --- a/tests/front/controller/visitor/ShaarliPublicControllerTest.php +++ b/tests/front/controller/visitor/ShaarliPublicControllerTest.php @@ -16,7 +16,7 @@ use Slim\Http\Uri; * This class is used to test default behavior of ShaarliController abstract class. * It uses a dummy non abstract controller. */ -class ShaarliControllerTest extends TestCase +class ShaarliPublicControllerTest extends TestCase { use FrontControllerMockHelper; -- cgit v1.2.3 From 465033230da0398426010aa7bd3694735b71c899 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 27 May 2020 14:18:07 +0200 Subject: Password change: UT use case with open shaarli --- tests/front/controller/admin/PasswordControllerTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'tests/front') diff --git a/tests/front/controller/admin/PasswordControllerTest.php b/tests/front/controller/admin/PasswordControllerTest.php index 7262243e..9a01089e 100644 --- a/tests/front/controller/admin/PasswordControllerTest.php +++ b/tests/front/controller/admin/PasswordControllerTest.php @@ -6,6 +6,7 @@ namespace Shaarli\Front\Controller\Admin; use PHPUnit\Framework\TestCase; use Shaarli\Config\ConfigManager; +use Shaarli\Front\Exception\OpenShaarliPasswordException; use Shaarli\Front\Exception\WrongTokenException; use Shaarli\Security\SessionManager; use Slim\Http\Request; @@ -183,4 +184,20 @@ class PasswordControllerTest extends TestCase static::assertSame('changepassword', (string) $result->getBody()); static::assertSame('Change password - Shaarli', $this->assignedVariables['pagetitle']); } + + /** + * Change the password on an open shaarli + */ + public function testPostNewPasswordOnOpenShaarli(): void + { + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->with('security.open_shaarli')->willReturn(true); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->expectException(OpenShaarliPasswordException::class); + + $this->controller->change($request, $response); + } } -- cgit v1.2.3 From 66063ed1a18d739b1a60bfb163d8656417a4c529 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 30 May 2020 14:00:06 +0200 Subject: Process configure page through Slim controller --- .../controller/admin/ConfigureControllerTest.php | 252 +++++++++++++++++++++ .../admin/FrontAdminControllerMockHelper.php | 23 ++ .../controller/visitor/DailyControllerTest.php | 27 +-- .../visitor/FrontControllerMockHelper.php | 10 +- 4 files changed, 294 insertions(+), 18 deletions(-) create mode 100644 tests/front/controller/admin/ConfigureControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ConfigureControllerTest.php b/tests/front/controller/admin/ConfigureControllerTest.php new file mode 100644 index 00000000..40304a18 --- /dev/null +++ b/tests/front/controller/admin/ConfigureControllerTest.php @@ -0,0 +1,252 @@ +createContainer(); + + $this->controller = new ConfigureController($this->container); + } + + /** + * Test displaying configure page - it should display all config variables + */ + public function testIndex(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $key) { + return $key; + }); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('configure', (string) $result->getBody()); + + static::assertSame('Configure - general.title', $assignedVariables['pagetitle']); + static::assertSame('general.title', $assignedVariables['title']); + static::assertSame('resource.theme', $assignedVariables['theme']); + static::assertEmpty($assignedVariables['theme_available']); + static::assertSame(['default', 'markdown'], $assignedVariables['formatter_available']); + static::assertNotEmpty($assignedVariables['continents']); + static::assertNotEmpty($assignedVariables['cities']); + static::assertSame('general.retrieve_description', $assignedVariables['retrieve_description']); + static::assertSame('privacy.default_private_links', $assignedVariables['private_links_default']); + static::assertSame('security.session_protection_disabled', $assignedVariables['session_protection_disabled']); + static::assertSame('feed.rss_permalinks', $assignedVariables['enable_rss_permalinks']); + static::assertSame('updates.check_updates', $assignedVariables['enable_update_check']); + static::assertSame('privacy.hide_public_links', $assignedVariables['hide_public_links']); + static::assertSame('api.enabled', $assignedVariables['api_enabled']); + static::assertSame('api.secret', $assignedVariables['api_secret']); + static::assertCount(4, $assignedVariables['languages']); + static::assertArrayHasKey('gd_enabled', $assignedVariables); + static::assertSame('thumbnails.mode', $assignedVariables['thumbnails_mode']); + } + + /** + * Test posting a new config - make sure that everything is saved properly, without errors. + */ + public function testSaveNewConfig(): void + { + $session = []; + $this->assignSessionVars($session); + + $parameters = [ + 'token' => 'token', + 'continent' => 'Europe', + 'city' => 'Moscow', + 'title' => 'Shaarli', + 'titleLink' => './', + 'retrieveDescription' => 'on', + 'theme' => 'vintage', + 'disablesessionprotection' => null, + 'privateLinkByDefault' => true, + 'enableRssPermalinks' => true, + 'updateCheck' => false, + 'hidePublicLinks' => 'on', + 'enableApi' => 'on', + 'apiSecret' => 'abcdef', + 'formatter' => 'markdown', + 'language' => 'fr', + 'enableThumbnails' => Thumbnailer::MODE_NONE, + ]; + + $parametersConfigMapping = [ + 'general.timezone' => $parameters['continent'] . '/' . $parameters['city'], + 'general.title' => $parameters['title'], + 'general.header_link' => $parameters['titleLink'], + 'general.retrieve_description' => !!$parameters['retrieveDescription'], + 'resource.theme' => $parameters['theme'], + 'security.session_protection_disabled' => !!$parameters['disablesessionprotection'], + 'privacy.default_private_links' => !!$parameters['privateLinkByDefault'], + 'feed.rss_permalinks' => !!$parameters['enableRssPermalinks'], + 'updates.check_updates' => !!$parameters['updateCheck'], + 'privacy.hide_public_links' => !!$parameters['hidePublicLinks'], + 'api.enabled' => !!$parameters['enableApi'], + 'api.secret' => $parameters['apiSecret'], + 'formatter' => $parameters['formatter'], + 'translation.language' => $parameters['language'], + 'thumbnails.mode' => $parameters['enableThumbnails'], + ]; + + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParam')->willReturnCallback(function (string $key) use ($parameters) { + if (false === array_key_exists($key, $parameters)) { + static::fail('unknown key: ' . $key); + } + + return $parameters[$key]; + } + ); + + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf + ->expects(static::atLeastOnce()) + ->method('set') + ->willReturnCallback(function (string $key, $value) use ($parametersConfigMapping): void { + if (false === array_key_exists($key, $parametersConfigMapping)) { + static::fail('unknown key: ' . $key); + } + + static::assertSame($parametersConfigMapping[$key], $value); + } + ); + + $result = $this->controller->save($request, $response); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./configure'], $result->getHeader('Location')); + + static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); + static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); + static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session); + static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]); + } + + /** + * Test posting a new config - wrong token. + */ + public function testSaveNewConfigWrongToken(): void + { + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->method('checkToken')->willReturn(false); + + $this->container->conf->expects(static::never())->method('set'); + $this->container->conf->expects(static::never())->method('write'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->expectException(WrongTokenException::class); + + $this->controller->save($request, $response); + } + + /** + * Test posting a new config - thumbnail activation. + */ + public function testSaveNewConfigThumbnailsActivation(): void + { + $session = []; + $this->assignSessionVars($session); + + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParam')->willReturnCallback(function (string $key) { + if ('enableThumbnails' === $key) { + return Thumbnailer::MODE_ALL; + } + + return $key; + }) + ; + $response = new Response(); + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./configure'], $result->getHeader('Location')); + + static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); + static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); + static::assertStringContainsString( + 'You have enabled or changed thumbnails mode', + $session[SessionManager::KEY_WARNING_MESSAGES][0] + ); + static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session); + static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]); + } + + /** + * Test posting a new config - thumbnail activation. + */ + public function testSaveNewConfigThumbnailsAlreadyActive(): void + { + $session = []; + $this->assignSessionVars($session); + + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParam')->willReturnCallback(function (string $key) { + if ('enableThumbnails' === $key) { + return Thumbnailer::MODE_ALL; + } + + return $key; + }) + ; + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf + ->expects(static::atLeastOnce()) + ->method('get') + ->willReturnCallback(function (string $key): string { + if ('thumbnails.mode' === $key) { + return Thumbnailer::MODE_ALL; + } + + return $key; + }) + ; + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./configure'], $result->getHeader('Location')); + + static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); + static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); + static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session); + static::assertSame(['Configuration was saved.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]); + } +} diff --git a/tests/front/controller/admin/FrontAdminControllerMockHelper.php b/tests/front/controller/admin/FrontAdminControllerMockHelper.php index bd40c0c7..2b9f2ef1 100644 --- a/tests/front/controller/admin/FrontAdminControllerMockHelper.php +++ b/tests/front/controller/admin/FrontAdminControllerMockHelper.php @@ -6,6 +6,7 @@ namespace Shaarli\Front\Controller\Admin; use Shaarli\Container\ShaarliTestContainer; use Shaarli\Front\Controller\Visitor\FrontControllerMockHelper; +use Shaarli\History; /** * Trait FrontControllerMockHelper @@ -27,7 +28,29 @@ trait FrontAdminControllerMockHelper { $this->parentCreateContainer(); + $this->container->history = $this->createMock(History::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(true); $this->container->sessionManager->method('checkToken')->willReturn(true); } + + + /** + * Pass a reference of an array which will be populated by `sessionManager->setSessionParameter` + * calls during execution. + * + * @param mixed $variables Array reference to populate. + */ + protected function assignSessionVars(array &$variables): void + { + $this->container->sessionManager + ->expects(static::atLeastOnce()) + ->method('setSessionParameter') + ->willReturnCallback(function ($key, $value) use (&$variables) { + $variables[$key] = $value; + + return $this->container->sessionManager; + }) + ; + } } diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php index 872420fd..b802c62c 100644 --- a/tests/front/controller/visitor/DailyControllerTest.php +++ b/tests/front/controller/visitor/DailyControllerTest.php @@ -57,20 +57,20 @@ class DailyControllerTest extends TestCase (new Bookmark()) ->setId(1) ->setUrl('http://url.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(500)) , (new Bookmark()) ->setId(2) ->setUrl('http://url2.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(500)) , (new Bookmark()) ->setId(3) ->setUrl('http://url3.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(500)) , ]; }) @@ -194,8 +194,8 @@ class DailyControllerTest extends TestCase (new Bookmark()) ->setId(1) ->setUrl('http://url.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(500)) , ]; }) @@ -267,8 +267,8 @@ class DailyControllerTest extends TestCase (new Bookmark()) ->setId(2) ->setUrl('http://url.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(5000)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(5000)) , (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'), (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'), @@ -473,11 +473,4 @@ class DailyControllerTest extends TestCase static::assertFalse($assignedVariables['hide_timestamps']); static::assertCount(0, $assignedVariables['days']); } - - protected static function generateContent(int $length): string - { - // bin2hex(random_bytes) generates string twice as long as given parameter - $length = (int) ceil($length / 2); - return bin2hex(random_bytes($length)); - } } diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php index d16b6949..fecd0c82 100644 --- a/tests/front/controller/visitor/FrontControllerMockHelper.php +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php @@ -42,7 +42,7 @@ trait FrontControllerMockHelper // Config $this->container->conf = $this->createMock(ConfigManager::class); $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { - return $default; + return $default === null ? $parameter : $default; }); // PageBuilder @@ -101,6 +101,14 @@ trait FrontControllerMockHelper ; } + protected static function generateString(int $length): string + { + // bin2hex(random_bytes) generates string twice as long as given parameter + $length = (int) ceil($length / 2); + + return bin2hex(random_bytes($length)); + } + /** * Force to be used in PHPUnit context. */ -- cgit v1.2.3 From 8eac2e54882d8adae8cbb45386dca1b465242632 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 30 May 2020 15:51:14 +0200 Subject: Process manage tags page through Slim controller --- .../controller/admin/ManageTagControllerTest.php | 272 +++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 tests/front/controller/admin/ManageTagControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ManageTagControllerTest.php b/tests/front/controller/admin/ManageTagControllerTest.php new file mode 100644 index 00000000..eed99231 --- /dev/null +++ b/tests/front/controller/admin/ManageTagControllerTest.php @@ -0,0 +1,272 @@ +createContainer(); + + $this->controller = new ManageTagController($this->container); + } + + /** + * Test displaying manage tag page + */ + public function testIndex(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $request->method('getParam')->with('fromtag')->willReturn('fromtag'); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('changetag', (string) $result->getBody()); + + static::assertSame('fromtag', $assignedVariables['fromtag']); + static::assertSame('Manage tags - Shaarli', $assignedVariables['pagetitle']); + } + + /** + * Test posting a tag update - rename tag - valid info provided. + */ + public function testSaveRenameTagValid(): void + { + $session = []; + $this->assignSessionVars($session); + + $requestParameters = [ + 'renametag' => 'rename', + 'fromtag' => 'old-tag', + 'totag' => 'new-tag', + ]; + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParam') + ->willReturnCallback(function (string $key) use ($requestParameters): ?string { + return $requestParameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmark1 = $this->createMock(Bookmark::class); + $bookmark2 = $this->createMock(Bookmark::class); + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->with(['searchtags' => 'old-tag'], BookmarkFilter::$ALL, true) + ->willReturnCallback(function () use ($bookmark1, $bookmark2): array { + $bookmark1->expects(static::once())->method('renameTag')->with('old-tag', 'new-tag'); + $bookmark2->expects(static::once())->method('renameTag')->with('old-tag', 'new-tag'); + + return [$bookmark1, $bookmark2]; + }) + ; + $this->container->bookmarkService + ->expects(static::exactly(2)) + ->method('set') + ->withConsecutive([$bookmark1, false], [$bookmark2, false]) + ; + $this->container->bookmarkService->expects(static::once())->method('save'); + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./?searchtags=new-tag'], $result->getHeader('location')); + + static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); + static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); + static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session); + static::assertSame(['The tag was renamed in 2 bookmarks.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]); + } + + /** + * Test posting a tag update - delete tag - valid info provided. + */ + public function testSaveDeleteTagValid(): void + { + $session = []; + $this->assignSessionVars($session); + + $requestParameters = [ + 'deletetag' => 'delete', + 'fromtag' => 'old-tag', + ]; + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParam') + ->willReturnCallback(function (string $key) use ($requestParameters): ?string { + return $requestParameters[$key] ?? null; + }) + ; + $response = new Response(); + + $bookmark1 = $this->createMock(Bookmark::class); + $bookmark2 = $this->createMock(Bookmark::class); + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->with(['searchtags' => 'old-tag'], BookmarkFilter::$ALL, true) + ->willReturnCallback(function () use ($bookmark1, $bookmark2): array { + $bookmark1->expects(static::once())->method('deleteTag')->with('old-tag'); + $bookmark2->expects(static::once())->method('deleteTag')->with('old-tag'); + + return [$bookmark1, $bookmark2]; + }) + ; + $this->container->bookmarkService + ->expects(static::exactly(2)) + ->method('set') + ->withConsecutive([$bookmark1, false], [$bookmark2, false]) + ; + $this->container->bookmarkService->expects(static::once())->method('save'); + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./manage-tags'], $result->getHeader('location')); + + static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); + static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); + static::assertArrayHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session); + static::assertSame(['The tag was removed from 2 bookmarks.'], $session[SessionManager::KEY_SUCCESS_MESSAGES]); + } + + /** + * Test posting a tag update - wrong token. + */ + public function testSaveWrongToken(): void + { + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->method('checkToken')->willReturn(false); + + $this->container->conf->expects(static::never())->method('set'); + $this->container->conf->expects(static::never())->method('write'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->expectException(WrongTokenException::class); + + $this->controller->save($request, $response); + } + + /** + * Test posting a tag update - rename tag - missing "FROM" tag. + */ + public function testSaveRenameTagMissingFrom(): void + { + $session = []; + $this->assignSessionVars($session); + + $requestParameters = [ + 'renametag' => 'rename', + ]; + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParam') + ->willReturnCallback(function (string $key) use ($requestParameters): ?string { + return $requestParameters[$key] ?? null; + }) + ; + $response = new Response(); + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./manage-tags'], $result->getHeader('location')); + + static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); + static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); + static::assertArrayNotHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session); + static::assertSame(['Invalid tags provided.'], $session[SessionManager::KEY_WARNING_MESSAGES]); + } + + /** + * Test posting a tag update - delete tag - missing "FROM" tag. + */ + public function testSaveDeleteTagMissingFrom(): void + { + $session = []; + $this->assignSessionVars($session); + + $requestParameters = [ + 'deletetag' => 'delete', + ]; + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParam') + ->willReturnCallback(function (string $key) use ($requestParameters): ?string { + return $requestParameters[$key] ?? null; + }) + ; + $response = new Response(); + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./manage-tags'], $result->getHeader('location')); + + static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); + static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); + static::assertArrayNotHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session); + static::assertSame(['Invalid tags provided.'], $session[SessionManager::KEY_WARNING_MESSAGES]); + } + + /** + * Test posting a tag update - rename tag - missing "TO" tag. + */ + public function testSaveRenameTagMissingTo(): void + { + $session = []; + $this->assignSessionVars($session); + + $requestParameters = [ + 'renametag' => 'rename', + 'fromtag' => 'old-tag' + ]; + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParam') + ->willReturnCallback(function (string $key) use ($requestParameters): ?string { + return $requestParameters[$key] ?? null; + }) + ; + $response = new Response(); + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./manage-tags'], $result->getHeader('location')); + + static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); + static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); + static::assertArrayNotHasKey(SessionManager::KEY_SUCCESS_MESSAGES, $session); + static::assertSame(['Invalid tags provided.'], $session[SessionManager::KEY_WARNING_MESSAGES]); + } +} -- cgit v1.2.3 From c22fa57a5505fe95fd01860e3d3dfbb089f869cd Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 6 Jun 2020 14:01:03 +0200 Subject: Handle shaare creation/edition/deletion through Slim controllers --- .../admin/PostBookmarkControllerTest.php | 652 +++++++++++++++++++++ 1 file changed, 652 insertions(+) create mode 100644 tests/front/controller/admin/PostBookmarkControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/PostBookmarkControllerTest.php b/tests/front/controller/admin/PostBookmarkControllerTest.php new file mode 100644 index 00000000..f00a15c9 --- /dev/null +++ b/tests/front/controller/admin/PostBookmarkControllerTest.php @@ -0,0 +1,652 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->controller = new PostBookmarkController($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']); + } + + /** + * Test displaying bookmark create form + * Ensure that every step of the standard workflow works properly. + */ + public function testDisplayCreateFormWithUrl(): 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->httpAccess + ->expects(static::once()) + ->method('getCurlDownloadCallback') + ->willReturnCallback( + function (&$charset, &$title, &$description, &$tags) use ( + $remoteTitle, + $remoteDesc, + $remoteTags + ): callable { + return function () use ( + &$charset, + &$title, + &$description, + &$tags, + $remoteTitle, + $remoteDesc, + $remoteTags + ): void { + $charset = 'ISO-8859-1'; + $title = $remoteTitle; + $description = $remoteDesc; + $tags = $remoteTags; + }; + } + ) + ; + $this->container->httpAccess + ->expects(static::once()) + ->method('getHttpResponse') + ->with($expectedUrl, 30, 4194304) + ->willReturnCallback(function($url, $timeout, $maxBytes, $callback): void { + $callback(); + }) + ; + + $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::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data) use ($remoteTitle, $remoteDesc): array { + static::assertSame('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); + } + + /** + * 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']); + } + + /** + * 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 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.tld/subfolder/add-shaare' + ]; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $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): void { + static::assertFalse($save); + + $checkBookmark($bookmark); + + $bookmark->setId($id); + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('set') + ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void { + static::assertTrue($save); + + $checkBookmark($bookmark); + + static::assertSame($id, $bookmark->getId()); + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { + static::assertSame('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.tld/subfolder/?page=2' + ]; + + $request = $this->createMock(Request::class); + $request + ->method('getParam') + ->willReturnCallback(function (string $key) use ($parameters): ?string { + return $parameters[$key] ?? null; + }) + ; + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $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): void { + static::assertFalse($save); + + $checkBookmark($bookmark); + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('set') + ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void { + static::assertTrue($save); + + $checkBookmark($bookmark); + + static::assertSame($id, $bookmark->getId()); + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { + static::assertSame('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 testSaveBookmarkWithThumbnail(): 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; + }) + ; + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { + return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $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): void { + static::assertSame($thumb, $bookmark->getThumbnail()); + }) + ; + + $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 From 818b3193ffabec57501e3bdfa997206e3c0671ef Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 13 Jun 2020 11:22:14 +0200 Subject: Explicitly define base and asset path in templates With the new routes, all pages are not all at the same folder level anymore (e.g. /shaare and /shaare/123), so we can't just use './' everywhere. The most consistent way to handle this is to prefix all path with the proper variable, and handle the actual path in controllers. --- tests/front/ShaarliMiddlewareTest.php | 15 ++ .../admin/PostBookmarkControllerTest.php | 19 -- .../admin/SessionFilterControllerTest.php | 60 +----- .../visitor/FrontControllerMockHelper.php | 2 + .../visitor/ShaarliPublicControllerTest.php | 221 --------------------- .../visitor/ShaarliVisitorControllerTest.php | 217 ++++++++++++++++++++ 6 files changed, 236 insertions(+), 298 deletions(-) delete mode 100644 tests/front/controller/visitor/ShaarliPublicControllerTest.php create mode 100644 tests/front/controller/visitor/ShaarliVisitorControllerTest.php (limited to 'tests/front') diff --git a/tests/front/ShaarliMiddlewareTest.php b/tests/front/ShaarliMiddlewareTest.php index 80974f37..57be1002 100644 --- a/tests/front/ShaarliMiddlewareTest.php +++ b/tests/front/ShaarliMiddlewareTest.php @@ -11,6 +11,7 @@ use Shaarli\Front\Exception\LoginBannedException; use Shaarli\Render\PageBuilder; use Slim\Http\Request; use Slim\Http\Response; +use Slim\Http\Uri; class ShaarliMiddlewareTest extends TestCase { @@ -29,6 +30,13 @@ class ShaarliMiddlewareTest extends TestCase public function testMiddlewareExecution(): void { $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $response = new Response(); $controller = function (Request $request, Response $response): Response { return $response->withStatus(418); // I'm a tea pot @@ -44,6 +52,13 @@ class ShaarliMiddlewareTest extends TestCase public function testMiddlewareExecutionWithException(): void { $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + $response = new Response(); $controller = function (): void { $exception = new LoginBannedException(); diff --git a/tests/front/controller/admin/PostBookmarkControllerTest.php b/tests/front/controller/admin/PostBookmarkControllerTest.php index f00a15c9..69673bd2 100644 --- a/tests/front/controller/admin/PostBookmarkControllerTest.php +++ b/tests/front/controller/admin/PostBookmarkControllerTest.php @@ -13,7 +13,6 @@ use Shaarli\Security\SessionManager; use Shaarli\Thumbnailer; use Slim\Http\Request; use Slim\Http\Response; -use Slim\Http\Uri; class PostBookmarkControllerTest extends TestCase { @@ -406,12 +405,6 @@ class PostBookmarkControllerTest extends TestCase return $parameters[$key] ?? null; }) ; - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $response = new Response(); $checkBookmark = function (Bookmark $bookmark) use ($parameters) { @@ -493,12 +486,6 @@ class PostBookmarkControllerTest extends TestCase return $parameters[$key] ?? null; }) ; - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $response = new Response(); $checkBookmark = function (Bookmark $bookmark) use ($parameters, $id) { @@ -575,12 +562,6 @@ class PostBookmarkControllerTest extends TestCase return $parameters[$key] ?? null; }) ; - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $response = new Response(); $this->container->conf = $this->createMock(ConfigManager::class); diff --git a/tests/front/controller/admin/SessionFilterControllerTest.php b/tests/front/controller/admin/SessionFilterControllerTest.php index 096963cf..ea07edee 100644 --- a/tests/front/controller/admin/SessionFilterControllerTest.php +++ b/tests/front/controller/admin/SessionFilterControllerTest.php @@ -9,7 +9,6 @@ use Shaarli\Security\LoginManager; use Shaarli\Security\SessionManager; use Slim\Http\Request; use Slim\Http\Response; -use Slim\Http\Uri; class SessionFilterControllerTest extends TestCase { @@ -33,12 +32,6 @@ class SessionFilterControllerTest extends TestCase $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; $request = $this->createMock(Request::class); - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $request->method('getParam')->with('nb')->willReturn('8'); $response = new Response(); @@ -61,12 +54,6 @@ class SessionFilterControllerTest extends TestCase public function testLinksPerPageNotValid(): void { $request = $this->createMock(Request::class); - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $request->method('getParam')->with('nb')->willReturn('test'); $response = new Response(); @@ -80,7 +67,7 @@ class SessionFilterControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder'], $result->getHeader('location')); + static::assertSame(['/subfolder/'], $result->getHeader('location')); } /** @@ -100,12 +87,6 @@ class SessionFilterControllerTest extends TestCase ; $request = $this->createMock(Request::class); - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $response = new Response(); $result = $this->controller->visibility($request, $response, $arg); @@ -141,12 +122,6 @@ class SessionFilterControllerTest extends TestCase ; $request = $this->createMock(Request::class); - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $response = new Response(); $result = $this->controller->visibility($request, $response, $arg); @@ -176,19 +151,13 @@ class SessionFilterControllerTest extends TestCase ; $request = $this->createMock(Request::class); - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $response = new Response(); $result = $this->controller->visibility($request, $response, $arg); static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder'], $result->getHeader('location')); + static::assertSame(['/subfolder/'], $result->getHeader('location')); } /** @@ -212,12 +181,6 @@ class SessionFilterControllerTest extends TestCase ; $request = $this->createMock(Request::class); - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $response = new Response(); $result = $this->controller->visibility($request, $response, $arg); @@ -249,12 +212,6 @@ class SessionFilterControllerTest extends TestCase ; $request = $this->createMock(Request::class); - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $response = new Response(); $result = $this->controller->visibility($request, $response, $arg); @@ -272,12 +229,6 @@ class SessionFilterControllerTest extends TestCase $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; $request = $this->createMock(Request::class); - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); $response = new Response(); $this->container->sessionManager @@ -301,13 +252,6 @@ class SessionFilterControllerTest extends TestCase $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc']; $request = $this->createMock(Request::class); - $request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); - $response = new Response(); $this->container->sessionManager diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php index fecd0c82..7f560662 100644 --- a/tests/front/controller/visitor/FrontControllerMockHelper.php +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php @@ -81,6 +81,8 @@ trait FrontControllerMockHelper 'SERVER_PORT' => '80', 'REQUEST_URI' => '/daily-rss', ]; + + $this->container->basePath = '/subfolder'; } /** diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php deleted file mode 100644 index 899b280b..00000000 --- a/tests/front/controller/visitor/ShaarliPublicControllerTest.php +++ /dev/null @@ -1,221 +0,0 @@ -createContainer(); - - $this->controller = new class($this->container) extends ShaarliVisitorController - { - public function assignView(string $key, $value): ShaarliVisitorController - { - return parent::assignView($key, $value); - } - - public function render(string $template): string - { - return parent::render($template); - } - - public function redirectFromReferer( - Request $request, - Response $response, - array $loopTerms = [], - array $clearParams = [] - ): Response { - return parent::redirectFromReferer($request, $response, $loopTerms, $clearParams); - } - }; - $this->assignedValues = []; - - $this->request = $this->createMock(Request::class); - $this->request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); - } - - public function testAssignView(): void - { - $this->assignTemplateVars($this->assignedValues); - - $self = $this->controller->assignView('variableName', 'variableValue'); - - static::assertInstanceOf(ShaarliVisitorController::class, $self); - static::assertSame('variableValue', $this->assignedValues['variableName']); - } - - public function testRender(): void - { - $this->assignTemplateVars($this->assignedValues); - - $this->container->bookmarkService - ->method('count') - ->willReturnCallback(function (string $visibility): int { - return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; - }) - ; - - $this->container->pluginManager - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array &$data, array $params): array { - return $data[$hook] = $params; - }); - $this->container->pluginManager->method('getErrors')->willReturn(['error']); - - $this->container->loginManager->method('isLoggedIn')->willReturn(true); - - $render = $this->controller->render('templateName'); - - static::assertSame('templateName', $render); - - static::assertSame(10, $this->assignedValues['linkcount']); - static::assertSame(5, $this->assignedValues['privateLinkcount']); - static::assertSame(['error'], $this->assignedValues['plugin_errors']); - - static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); - static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); - static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); - static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); - static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); - static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); - } - - /** - * Test redirectFromReferer() - Default behaviour - */ - public function testRedirectFromRefererDefault(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term not matched in the referer - */ - public function testRedirectFromRefererWithUnmatchedLoopTerm(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['nope']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default - */ - public function testRedirectFromRefererWithMatchingLoopTermInPath(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'controller']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default - */ - public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'other']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its query value - * -> we do not block redirection for query parameter values. - */ - public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'param']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its domain name - * -> we do not block redirection for shaarli's hosts - */ - public function testRedirectFromRefererWithLoopTermInDomain(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['shaarli']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param - * -> the param should be cleared before checking if it matches the redir loop terms - */ - public function testRedirectFromRefererWithMatchingClearedParam(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['query'], ['query']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location')); - } -} diff --git a/tests/front/controller/visitor/ShaarliVisitorControllerTest.php b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php new file mode 100644 index 00000000..83d08358 --- /dev/null +++ b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php @@ -0,0 +1,217 @@ +createContainer(); + + $this->controller = new class($this->container) extends ShaarliVisitorController + { + public function assignView(string $key, $value): ShaarliVisitorController + { + return parent::assignView($key, $value); + } + + public function render(string $template): string + { + return parent::render($template); + } + + public function redirectFromReferer( + Request $request, + Response $response, + array $loopTerms = [], + array $clearParams = [], + string $anchor = null + ): Response { + return parent::redirectFromReferer($request, $response, $loopTerms, $clearParams, $anchor); + } + }; + $this->assignedValues = []; + + $this->request = $this->createMock(Request::class); + } + + public function testAssignView(): void + { + $this->assignTemplateVars($this->assignedValues); + + $self = $this->controller->assignView('variableName', 'variableValue'); + + static::assertInstanceOf(ShaarliVisitorController::class, $self); + static::assertSame('variableValue', $this->assignedValues['variableName']); + } + + public function testRender(): void + { + $this->assignTemplateVars($this->assignedValues); + + $this->container->bookmarkService + ->method('count') + ->willReturnCallback(function (string $visibility): int { + return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; + }) + ; + + $this->container->pluginManager + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array &$data, array $params): array { + return $data[$hook] = $params; + }); + $this->container->pluginManager->method('getErrors')->willReturn(['error']); + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $render = $this->controller->render('templateName'); + + static::assertSame('templateName', $render); + + static::assertSame(10, $this->assignedValues['linkcount']); + static::assertSame(5, $this->assignedValues['privateLinkcount']); + static::assertSame(['error'], $this->assignedValues['plugin_errors']); + static::assertSame('/subfolder', $this->assignedValues['base_path']); + static::assertSame('/subfolder/tpl/default', $this->assignedValues['asset_path']); + + static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); + static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); + static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); + static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); + } + + /** + * Test redirectFromReferer() - Default behaviour + */ + public function testRedirectFromRefererDefault(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term not matched in the referer + */ + public function testRedirectFromRefererWithUnmatchedLoopTerm(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInPath(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'controller']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'other']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query value + * -> we do not block redirection for query parameter values. + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'param']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its domain name + * -> we do not block redirection for shaarli's hosts + */ + public function testRedirectFromRefererWithLoopTermInDomain(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['shaarli']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param + * -> the param should be cleared before checking if it matches the redir loop terms + */ + public function testRedirectFromRefererWithMatchingClearedParam(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['query'], ['query']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location')); + } +} -- cgit v1.2.3 From 9c75f877935fa6adec951a4d8d32b328aaab314f Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 13 Jun 2020 13:08:01 +0200 Subject: Use multi-level routes for existing controllers instead of 1 level everywhere Also prefix most admin routes with /admin/ --- tests/front/controller/admin/ConfigureControllerTest.php | 6 +++--- tests/front/controller/admin/LogoutControllerTest.php | 2 +- tests/front/controller/admin/ManageTagControllerTest.php | 10 +++++----- tests/front/controller/admin/PostBookmarkControllerTest.php | 6 +++--- tests/front/controller/visitor/LoginControllerTest.php | 4 ++-- tests/front/controller/visitor/TagControllerTest.php | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) (limited to 'tests/front') diff --git a/tests/front/controller/admin/ConfigureControllerTest.php b/tests/front/controller/admin/ConfigureControllerTest.php index 40304a18..f2f84bac 100644 --- a/tests/front/controller/admin/ConfigureControllerTest.php +++ b/tests/front/controller/admin/ConfigureControllerTest.php @@ -142,7 +142,7 @@ class ConfigureControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./configure'], $result->getHeader('Location')); + static::assertSame(['/subfolder/admin/configure'], $result->getHeader('Location')); static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); @@ -193,7 +193,7 @@ class ConfigureControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./configure'], $result->getHeader('Location')); + static::assertSame(['/subfolder/admin/configure'], $result->getHeader('Location')); static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); @@ -242,7 +242,7 @@ class ConfigureControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./configure'], $result->getHeader('Location')); + static::assertSame(['/subfolder/admin/configure'], $result->getHeader('Location')); static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); diff --git a/tests/front/controller/admin/LogoutControllerTest.php b/tests/front/controller/admin/LogoutControllerTest.php index 78a0fe73..ca177085 100644 --- a/tests/front/controller/admin/LogoutControllerTest.php +++ b/tests/front/controller/admin/LogoutControllerTest.php @@ -49,7 +49,7 @@ class LogoutControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertContains('./', $result->getHeader('Location')); + static::assertSame(['/subfolder/'], $result->getHeader('location')); static::assertSame('false', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); } } diff --git a/tests/front/controller/admin/ManageTagControllerTest.php b/tests/front/controller/admin/ManageTagControllerTest.php index eed99231..09ba0b4b 100644 --- a/tests/front/controller/admin/ManageTagControllerTest.php +++ b/tests/front/controller/admin/ManageTagControllerTest.php @@ -93,7 +93,7 @@ class ManageTagControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./?searchtags=new-tag'], $result->getHeader('location')); + static::assertSame(['/subfolder/?searchtags=new-tag'], $result->getHeader('location')); static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); @@ -146,7 +146,7 @@ class ManageTagControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./manage-tags'], $result->getHeader('location')); + static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location')); static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); static::assertArrayNotHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); @@ -197,7 +197,7 @@ class ManageTagControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./manage-tags'], $result->getHeader('location')); + static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location')); static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); @@ -229,7 +229,7 @@ class ManageTagControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./manage-tags'], $result->getHeader('location')); + static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location')); static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); @@ -262,7 +262,7 @@ class ManageTagControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./manage-tags'], $result->getHeader('location')); + static::assertSame(['/subfolder/admin/tags'], $result->getHeader('location')); static::assertArrayNotHasKey(SessionManager::KEY_ERROR_MESSAGES, $session); static::assertArrayHasKey(SessionManager::KEY_WARNING_MESSAGES, $session); diff --git a/tests/front/controller/admin/PostBookmarkControllerTest.php b/tests/front/controller/admin/PostBookmarkControllerTest.php index 69673bd2..8dcd1b50 100644 --- a/tests/front/controller/admin/PostBookmarkControllerTest.php +++ b/tests/front/controller/admin/PostBookmarkControllerTest.php @@ -395,7 +395,7 @@ class PostBookmarkControllerTest extends TestCase 'lf_description' => 'Provided description.', 'lf_tags' => 'abc def', 'lf_private' => '1', - 'returnurl' => 'http://shaarli.tld/subfolder/add-shaare' + 'returnurl' => 'http://shaarli.tld/subfolder/admin/add-shaare' ]; $request = $this->createMock(Request::class); @@ -459,7 +459,7 @@ class PostBookmarkControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertRegExp('@/subfolder/#\w{6}@', $result->getHeader('location')[0]); + static::assertRegExp('@/subfolder/#[\w\-]{6}@', $result->getHeader('location')[0]); } @@ -545,7 +545,7 @@ class PostBookmarkControllerTest extends TestCase $result = $this->controller->save($request, $response); static::assertSame(302, $result->getStatusCode()); - static::assertRegExp('@/subfolder/\?page=2#\w{6}@', $result->getHeader('location')[0]); + static::assertRegExp('@/subfolder/\?page=2#[\w\-]{6}@', $result->getHeader('location')[0]); } /** diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php index faa8ac71..e57f44b9 100644 --- a/tests/front/controller/visitor/LoginControllerTest.php +++ b/tests/front/controller/visitor/LoginControllerTest.php @@ -95,7 +95,7 @@ class LoginControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('Location')); + static::assertSame(['/subfolder/'], $result->getHeader('Location')); } public function testLoginControllerOpenShaarli(): void @@ -116,7 +116,7 @@ class LoginControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('Location')); + static::assertSame(['/subfolder/'], $result->getHeader('Location')); } public function testLoginControllerWhileBanned(): void diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php index 1242a2e9..43076086 100644 --- a/tests/front/controller/visitor/TagControllerTest.php +++ b/tests/front/controller/visitor/TagControllerTest.php @@ -64,7 +64,7 @@ class TagControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./?searchtags=abc'], $result->getHeader('location')); + static::assertSame(['/subfolder/?searchtags=abc'], $result->getHeader('location')); } public function testAddTagRemoveLegacyQueryParam(): void @@ -138,7 +138,7 @@ class TagControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); + static::assertSame(['/subfolder/'], $result->getHeader('location')); } public function testRemoveTagWithoutMatchingTag(): void @@ -184,7 +184,7 @@ class TagControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); + static::assertSame(['/subfolder/'], $result->getHeader('location')); } public function testRemoveTagWithoutTag(): void @@ -210,6 +210,6 @@ class TagControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); + static::assertSame(['/subfolder/'], $result->getHeader('location')); } } -- cgit v1.2.3 From baa6979194573855b260593094983c33ec338dc7 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 13 Jun 2020 15:37:02 +0200 Subject: Improve ManageTagController coverage and error handling --- .../ManageShaareControllerTest/AddShaareTest.php | 47 ++ .../DeleteBookmarkTest.php | 361 ++++++++++++ .../DisplayCreateFormTest.php | 315 ++++++++++ .../DisplayEditFormTest.php | 155 +++++ .../SaveBookmarkTest.php | 282 +++++++++ .../admin/PostBookmarkControllerTest.php | 633 --------------------- 6 files changed, 1160 insertions(+), 633 deletions(-) create mode 100644 tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php create mode 100644 tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php create mode 100644 tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php create mode 100644 tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php create mode 100644 tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php delete mode 100644 tests/front/controller/admin/PostBookmarkControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php b/tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php new file mode 100644 index 00000000..7d5b752a --- /dev/null +++ b/tests/front/controller/admin/ManageShaareControllerTest/AddShaareTest.php @@ -0,0 +1,47 @@ +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/DeleteBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php new file mode 100644 index 00000000..caaf549d --- /dev/null +++ b/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php @@ -0,0 +1,361 @@ +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); + + return $formatter; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::once()) + ->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 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)) + ; + + 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)) + ; + + 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->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->expects(static::once()) + ->method('getFormatter') + ->willReturn($this->createMock(BookmarkFormatter::class)) + ; + + $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 new file mode 100644 index 00000000..777583d5 --- /dev/null +++ b/tests/front/controller/admin/ManageShaareControllerTest/DisplayCreateFormTest.php @@ -0,0 +1,315 @@ +createContainer(); + + $this->container->httpAccess = $this->createMock(HttpAccess::class); + $this->controller = new ManageShaareController($this->container); + } + + /** + * Test displaying bookmark create form + * Ensure that every step of the standard workflow works properly. + */ + public function testDisplayCreateFormWithUrl(): 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->httpAccess + ->expects(static::once()) + ->method('getCurlDownloadCallback') + ->willReturnCallback( + function (&$charset, &$title, &$description, &$tags) use ( + $remoteTitle, + $remoteDesc, + $remoteTags + ): callable { + return function () use ( + &$charset, + &$title, + &$description, + &$tags, + $remoteTitle, + $remoteDesc, + $remoteTags + ): void { + $charset = 'ISO-8859-1'; + $title = $remoteTitle; + $description = $remoteDesc; + $tags = $remoteTags; + }; + } + ) + ; + $this->container->httpAccess + ->expects(static::once()) + ->method('getHttpResponse') + ->with($expectedUrl, 30, 4194304) + ->willReturnCallback(function($url, $timeout, $maxBytes, $callback): void { + $callback(); + }) + ; + + $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::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data) use ($remoteTitle, $remoteDesc): array { + static::assertSame('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); + } + + /** + * 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 new file mode 100644 index 00000000..1a1cdcf3 --- /dev/null +++ b/tests/front/controller/admin/ManageShaareControllerTest/DisplayEditFormTest.php @@ -0,0 +1,155 @@ +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/SaveBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php new file mode 100644 index 00000000..dabcd60d --- /dev/null +++ b/tests/front/controller/admin/ManageShaareControllerTest/SaveBookmarkTest.php @@ -0,0 +1,282 @@ +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.tld/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): void { + static::assertFalse($save); + + $checkBookmark($bookmark); + + $bookmark->setId($id); + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('set') + ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void { + static::assertTrue($save); + + $checkBookmark($bookmark); + + static::assertSame($id, $bookmark->getId()); + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { + static::assertSame('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.tld/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): void { + static::assertFalse($save); + + $checkBookmark($bookmark); + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('set') + ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void { + static::assertTrue($save); + + $checkBookmark($bookmark); + + static::assertSame($id, $bookmark->getId()); + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { + static::assertSame('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 testSaveBookmarkWithThumbnail(): 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) { + return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $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): void { + static::assertSame($thumb, $bookmark->getThumbnail()); + }) + ; + + $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/PostBookmarkControllerTest.php b/tests/front/controller/admin/PostBookmarkControllerTest.php deleted file mode 100644 index 8dcd1b50..00000000 --- a/tests/front/controller/admin/PostBookmarkControllerTest.php +++ /dev/null @@ -1,633 +0,0 @@ -createContainer(); - - $this->container->httpAccess = $this->createMock(HttpAccess::class); - $this->controller = new PostBookmarkController($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']); - } - - /** - * Test displaying bookmark create form - * Ensure that every step of the standard workflow works properly. - */ - public function testDisplayCreateFormWithUrl(): 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->httpAccess - ->expects(static::once()) - ->method('getCurlDownloadCallback') - ->willReturnCallback( - function (&$charset, &$title, &$description, &$tags) use ( - $remoteTitle, - $remoteDesc, - $remoteTags - ): callable { - return function () use ( - &$charset, - &$title, - &$description, - &$tags, - $remoteTitle, - $remoteDesc, - $remoteTags - ): void { - $charset = 'ISO-8859-1'; - $title = $remoteTitle; - $description = $remoteDesc; - $tags = $remoteTags; - }; - } - ) - ; - $this->container->httpAccess - ->expects(static::once()) - ->method('getHttpResponse') - ->with($expectedUrl, 30, 4194304) - ->willReturnCallback(function($url, $timeout, $maxBytes, $callback): void { - $callback(); - }) - ; - - $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::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data) use ($remoteTitle, $remoteDesc): array { - static::assertSame('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); - } - - /** - * 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']); - } - - /** - * 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 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.tld/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): void { - static::assertFalse($save); - - $checkBookmark($bookmark); - - $bookmark->setId($id); - }) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('set') - ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void { - static::assertTrue($save); - - $checkBookmark($bookmark); - - static::assertSame($id, $bookmark->getId()); - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { - static::assertSame('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.tld/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): void { - static::assertFalse($save); - - $checkBookmark($bookmark); - }) - ; - $this->container->bookmarkService - ->expects(static::once()) - ->method('set') - ->willReturnCallback(function (Bookmark $bookmark, bool $save) use ($checkBookmark, $id): void { - static::assertTrue($save); - - $checkBookmark($bookmark); - - static::assertSame($id, $bookmark->getId()); - }) - ; - - // Make sure that PluginManager hook is triggered - $this->container->pluginManager - ->expects(static::at(0)) - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array $data) use ($parameters, $id): array { - static::assertSame('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 testSaveBookmarkWithThumbnail(): 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) { - return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $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): void { - static::assertSame($thumb, $bookmark->getThumbnail()); - }) - ; - - $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 From 7b8a6f2858248601d43c1b8247deb91b74392d2e Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 13 Jun 2020 19:40:32 +0200 Subject: Process change visibility action through Slim controller --- .../ChangeVisibilityBookmarkTest.php | 418 +++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php new file mode 100644 index 00000000..5a615791 --- /dev/null +++ b/tests/front/controller/admin/ManageShaareControllerTest/ChangeVisibilityBookmarkTest.php @@ -0,0 +1,418 @@ +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')); + } +} -- cgit v1.2.3 From 3447d888d7881eed437117a6de2450abb96f6a76 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Mon, 15 Jun 2020 08:15:40 +0200 Subject: Pin bookmarks through Slim controller --- .../ManageShaareControllerTest/PinBookmarkTest.php | 145 +++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php new file mode 100644 index 00000000..1607b475 --- /dev/null +++ b/tests/front/controller/admin/ManageShaareControllerTest/PinBookmarkTest.php @@ -0,0 +1,145 @@ +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')); + } +} -- cgit v1.2.3 From c70ff64a61d62cc8d35a62f30596ecc2a3c578a3 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 17 Jun 2020 16:04:18 +0200 Subject: Process bookmark exports through Slim controllers --- .../controller/admin/ExportControllerTest.php | 167 +++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 tests/front/controller/admin/ExportControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ExportControllerTest.php b/tests/front/controller/admin/ExportControllerTest.php new file mode 100644 index 00000000..e43a9626 --- /dev/null +++ b/tests/front/controller/admin/ExportControllerTest.php @@ -0,0 +1,167 @@ +createContainer(); + + $this->controller = new ExportController($this->container); + } + + /** + * Test displaying export page + */ + public function testIndex(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('export', (string) $result->getBody()); + + static::assertSame('Export - Shaarli', $assignedVariables['pagetitle']); + } + + /** + * Test posting an export request + */ + public function testExportDefault(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $parameters = [ + 'selection' => 'all', + 'prepend_note_url' => 'on', + ]; + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key) use ($parameters) { + return $parameters[$key] ?? null; + }); + $response = new Response(); + + $bookmarks = [ + (new Bookmark())->setUrl('http://link1.tld')->setTitle('Title 1'), + (new Bookmark())->setUrl('http://link2.tld')->setTitle('Title 2'), + ]; + + $this->container->netscapeBookmarkUtils = $this->createMock(NetscapeBookmarkUtils::class); + $this->container->netscapeBookmarkUtils + ->expects(static::once()) + ->method('filterAndFormat') + ->willReturnCallback( + function ( + BookmarkFormatter $formatter, + string $selection, + bool $prependNoteUrl, + string $indexUrl + ) use ($parameters, $bookmarks): array { + static::assertInstanceOf(BookmarkRawFormatter::class, $formatter); + static::assertSame($parameters['selection'], $selection); + static::assertTrue($prependNoteUrl); + static::assertSame('http://shaarli', $indexUrl); + + return $bookmarks; + } + ) + ; + + $result = $this->controller->export($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('export.bookmarks', (string) $result->getBody()); + static::assertSame(['text/html; charset=utf-8'], $result->getHeader('content-type')); + static::assertRegExp( + '/attachment; filename=bookmarks_all_[\d]{8}_[\d]{6}\.html/', + $result->getHeader('content-disposition')[0] + ); + + static::assertNotEmpty($assignedVariables['date']); + static::assertSame(PHP_EOL, $assignedVariables['eol']); + static::assertSame('all', $assignedVariables['selection']); + static::assertSame($bookmarks, $assignedVariables['links']); + } + + /** + * Test posting an export request - without selection parameter + */ + public function testExportSelectionMissing(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['Please select an export mode.']) + ; + + $result = $this->controller->export($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/admin/export'], $result->getHeader('location')); + } + + /** + * Test posting an export request - without selection parameter + */ + public function testExportErrorEncountered(): void + { + $parameters = [ + 'selection' => 'all', + ]; + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key) use ($parameters) { + return $parameters[$key] ?? null; + }); + $response = new Response(); + + $this->container->netscapeBookmarkUtils = $this->createMock(NetscapeBookmarkUtils::class); + $this->container->netscapeBookmarkUtils + ->expects(static::once()) + ->method('filterAndFormat') + ->willThrowException(new \Exception($message = 'error message')); + ; + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, [$message]) + ; + + $result = $this->controller->export($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/admin/export'], $result->getHeader('location')); + } +} -- cgit v1.2.3 From 78657347c5b463d7c22bfc8c87b7db39fe058833 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 17 Jun 2020 19:08:02 +0200 Subject: Process bookmarks import through Slim controller --- .../controller/admin/ExportControllerTest.php | 6 +- .../controller/admin/ImportControllerTest.php | 148 +++++++++++++++++++++ 2 files changed, 149 insertions(+), 5 deletions(-) create mode 100644 tests/front/controller/admin/ImportControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ExportControllerTest.php b/tests/front/controller/admin/ExportControllerTest.php index e43a9626..50d9e378 100644 --- a/tests/front/controller/admin/ExportControllerTest.php +++ b/tests/front/controller/admin/ExportControllerTest.php @@ -2,14 +2,12 @@ declare(strict_types=1); -namespace front\controller\admin; +namespace Shaarli\Front\Controller\Admin; use PHPUnit\Framework\TestCase; use Shaarli\Bookmark\Bookmark; use Shaarli\Formatter\BookmarkFormatter; use Shaarli\Formatter\BookmarkRawFormatter; -use Shaarli\Front\Controller\Admin\ExportController; -use Shaarli\Front\Controller\Admin\FrontAdminControllerMockHelper; use Shaarli\Netscape\NetscapeBookmarkUtils; use Shaarli\Security\SessionManager; use Slim\Http\Request; @@ -117,7 +115,6 @@ class ExportControllerTest extends TestCase $request = $this->createMock(Request::class); $response = new Response(); - $this->container->sessionManager = $this->createMock(SessionManager::class); $this->container->sessionManager ->expects(static::once()) ->method('setSessionParameter') @@ -152,7 +149,6 @@ class ExportControllerTest extends TestCase ->willThrowException(new \Exception($message = 'error message')); ; - $this->container->sessionManager = $this->createMock(SessionManager::class); $this->container->sessionManager ->expects(static::once()) ->method('setSessionParameter') diff --git a/tests/front/controller/admin/ImportControllerTest.php b/tests/front/controller/admin/ImportControllerTest.php new file mode 100644 index 00000000..eb31fad0 --- /dev/null +++ b/tests/front/controller/admin/ImportControllerTest.php @@ -0,0 +1,148 @@ +createContainer(); + + $this->controller = new ImportController($this->container); + } + + /** + * Test displaying import page + */ + public function testIndex(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('import', (string) $result->getBody()); + + static::assertSame('Import - Shaarli', $assignedVariables['pagetitle']); + static::assertIsInt($assignedVariables['maxfilesize']); + static::assertRegExp('/\d+[KM]iB/', $assignedVariables['maxfilesizeHuman']); + } + + /** + * Test importing a file with default and valid parameters + */ + public function testImportDefault(): void + { + $parameters = [ + 'abc' => 'def', + 'other' => 'param', + ]; + + $requestFile = new UploadedFile('file', 'name', 'type', 123); + + $request = $this->createMock(Request::class); + $request->method('getParams')->willReturnCallback(function () use ($parameters) { + return $parameters; + }); + $request->method('getUploadedFiles')->willReturn(['filetoupload' => $requestFile]); + $response = new Response(); + + $this->container->netscapeBookmarkUtils = $this->createMock(NetscapeBookmarkUtils::class); + $this->container->netscapeBookmarkUtils + ->expects(static::once()) + ->method('import') + ->willReturnCallback( + function ( + array $post, + UploadedFileInterface $file + ) use ($parameters, $requestFile): string { + static::assertSame($parameters, $post); + static::assertSame($requestFile, $file); + + return 'status'; + } + ) + ; + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_SUCCESS_MESSAGES, ['status']) + ; + + $result = $this->controller->import($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/admin/import'], $result->getHeader('location')); + } + + /** + * Test posting an import request - without import file + */ + public function testImportFileMissing(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(SessionManager::KEY_ERROR_MESSAGES, ['No import file provided.']) + ; + + $result = $this->controller->import($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/admin/import'], $result->getHeader('location')); + } + + /** + * Test posting an import request - with an empty file + */ + public function testImportEmptyFile(): void + { + $requestFile = new UploadedFile('file', 'name', 'type', 0); + + $request = $this->createMock(Request::class); + $request->method('getUploadedFiles')->willReturn(['filetoupload' => $requestFile]); + $response = new Response(); + + $this->container->netscapeBookmarkUtils = $this->createMock(NetscapeBookmarkUtils::class); + $this->container->netscapeBookmarkUtils->expects(static::never())->method('filterAndFormat'); + + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->willReturnCallback(function (string $key, array $value): SessionManager { + static::assertSame(SessionManager::KEY_ERROR_MESSAGES, $key); + static::assertStringStartsWith('The file you are trying to upload is probably bigger', $value[0]); + + return $this->container->sessionManager; + }) + ; + + $result = $this->controller->import($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/admin/import'], $result->getHeader('location')); + } +} -- cgit v1.2.3 From 1b8620b1ad4e2c647ff2d032c8e7c6687b6647a1 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 20 Jun 2020 15:14:24 +0200 Subject: Process plugins administration page through Slim controllers --- .../controller/admin/PluginsControllerTest.php | 190 +++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 tests/front/controller/admin/PluginsControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/PluginsControllerTest.php b/tests/front/controller/admin/PluginsControllerTest.php new file mode 100644 index 00000000..700a0df2 --- /dev/null +++ b/tests/front/controller/admin/PluginsControllerTest.php @@ -0,0 +1,190 @@ +createContainer(); + + $this->controller = new PluginsController($this->container); + } + + /** + * Test displaying plugins admin page + */ + public function testIndex(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $data = [ + 'plugin1' => ['order' => 2, 'other' => 'field'], + 'plugin2' => ['order' => 1], + 'plugin3' => ['order' => false, 'abc' => 'def'], + 'plugin4' => [], + ]; + + $this->container->pluginManager + ->expects(static::once()) + ->method('getPluginsMeta') + ->willReturn($data); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('pluginsadmin', (string) $result->getBody()); + + static::assertSame('Plugin Administration - Shaarli', $assignedVariables['pagetitle']); + static::assertSame( + ['plugin2' => $data['plugin2'], 'plugin1' => $data['plugin1']], + $assignedVariables['enabledPlugins'] + ); + static::assertSame( + ['plugin3' => $data['plugin3'], 'plugin4' => $data['plugin4']], + $assignedVariables['disabledPlugins'] + ); + } + + /** + * Test save plugins admin page + */ + public function testSaveEnabledPlugins(): void + { + $parameters = [ + 'plugin1' => 'on', + 'order_plugin1' => '2', + 'plugin2' => 'on', + ]; + + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParams') + ->willReturnCallback(function () use ($parameters): array { + return $parameters; + }) + ; + $response = new Response(); + + $this->container->pluginManager + ->expects(static::once()) + ->method('executeHooks') + ->with('save_plugin_parameters', $parameters) + ; + $this->container->conf + ->expects(static::atLeastOnce()) + ->method('set') + ->with('general.enabled_plugins', ['plugin1', 'plugin2']) + ; + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/admin/plugins'], $result->getHeader('location')); + } + + /** + * Test save plugin parameters + */ + public function testSavePluginParameters(): void + { + $parameters = [ + 'parameters_form' => true, + 'parameter1' => 'blip', + 'parameter2' => 'blop', + ]; + + $request = $this->createMock(Request::class); + $request + ->expects(static::atLeastOnce()) + ->method('getParams') + ->willReturnCallback(function () use ($parameters): array { + return $parameters; + }) + ; + $response = new Response(); + + $this->container->pluginManager + ->expects(static::once()) + ->method('executeHooks') + ->with('save_plugin_parameters', $parameters) + ; + $this->container->conf + ->expects(static::atLeastOnce()) + ->method('set') + ->withConsecutive(['plugins.parameter1', 'blip'], ['plugins.parameter2', 'blop']) + ; + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/admin/plugins'], $result->getHeader('location')); + } + + /** + * Test save plugin parameters - error encountered + */ + public function testSaveWithError(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf + ->expects(static::atLeastOnce()) + ->method('write') + ->willThrowException(new \Exception($message = 'error message')) + ; + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->method('checkToken')->willReturn(true); + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with( + SessionManager::KEY_ERROR_MESSAGES, + ['ERROR while saving plugin configuration: ' . PHP_EOL . $message] + ) + ; + + $result = $this->controller->save($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/admin/plugins'], $result->getHeader('location')); + } + + /** + * Test save plugin parameters - wrong token + */ + public function testSaveWrongToken(): void + { + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager->method('checkToken')->willReturn(false); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->expectException(WrongTokenException::class); + + $this->controller->save($request, $response); + } +} -- cgit v1.2.3 From 764d34a7d347d653414e5f5c632e02499edaef04 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sun, 21 Jun 2020 12:21:31 +0200 Subject: Process token retrieve through Slim controller --- .../front/controller/admin/TokenControllerTest.php | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 tests/front/controller/admin/TokenControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/TokenControllerTest.php b/tests/front/controller/admin/TokenControllerTest.php new file mode 100644 index 00000000..04b0c0fa --- /dev/null +++ b/tests/front/controller/admin/TokenControllerTest.php @@ -0,0 +1,41 @@ +createContainer(); + + $this->controller = new TokenController($this->container); + } + + public function testGetToken(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager + ->expects(static::once()) + ->method('generateToken') + ->willReturn($token = 'token1234') + ; + + $result = $this->controller->getToken($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame($token, (string) $result->getBody()); + } +} -- cgit v1.2.3 From 6132d64748dfc6806ed25f71d2e078a5ed29d071 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 27 Jun 2020 12:08:26 +0200 Subject: Process thumbnail synchronize page through Slim controllers --- .../controller/admin/ThumbnailsControllerTest.php | 154 +++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 tests/front/controller/admin/ThumbnailsControllerTest.php (limited to 'tests/front') diff --git a/tests/front/controller/admin/ThumbnailsControllerTest.php b/tests/front/controller/admin/ThumbnailsControllerTest.php new file mode 100644 index 00000000..0c0c8a83 --- /dev/null +++ b/tests/front/controller/admin/ThumbnailsControllerTest.php @@ -0,0 +1,154 @@ +createContainer(); + + $this->controller = new ThumbnailsController($this->container); + } + + /** + * Test displaying the thumbnails update page + * Note that only non-note and HTTP bookmarks should be returned. + */ + public function testIndex(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->willReturn([ + (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), + (new Bookmark())->setId(2)->setUrl('?abcdef')->setTitle('Note 1'), + (new Bookmark())->setId(3)->setUrl('http://url2.tld')->setTitle('Title 2'), + (new Bookmark())->setId(4)->setUrl('ftp://domain.tld', ['ftp'])->setTitle('FTP'), + ]) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('thumbnails', (string) $result->getBody()); + + static::assertSame('Thumbnails update - Shaarli', $assignedVariables['pagetitle']); + static::assertSame([1, 3], $assignedVariables['ids']); + } + + /** + * Test updating a bookmark thumbnail with valid parameters + */ + public function testAjaxUpdateValid(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $bookmark = (new Bookmark()) + ->setId($id = 123) + ->setUrl($url = 'http://url1.tld') + ->setTitle('Title 1') + ->setThumbnail(false) + ; + + $this->container->thumbnailer = $this->createMock(Thumbnailer::class); + $this->container->thumbnailer + ->expects(static::once()) + ->method('get') + ->with($url) + ->willReturn($thumb = 'http://img.tld/pic.png') + ; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('get') + ->with($id) + ->willReturn($bookmark) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('set') + ->willReturnCallback(function (Bookmark $bookmark) use ($thumb) { + static::assertSame($thumb, $bookmark->getThumbnail()); + }) + ; + + $result = $this->controller->ajaxUpdate($request, $response, ['id' => (string) $id]); + + static::assertSame(200, $result->getStatusCode()); + + $payload = json_decode((string) $result->getBody(), true); + + static::assertSame($id, $payload['id']); + static::assertSame($url, $payload['url']); + static::assertSame($thumb, $payload['thumbnail']); + } + + /** + * Test updating a bookmark thumbnail - Invalid ID + */ + public function testAjaxUpdateInvalidId(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->ajaxUpdate($request, $response, ['id' => 'nope']); + + static::assertSame(400, $result->getStatusCode()); + } + + /** + * Test updating a bookmark thumbnail - No ID + */ + public function testAjaxUpdateNoId(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->ajaxUpdate($request, $response, []); + + static::assertSame(400, $result->getStatusCode()); + } + + /** + * Test updating a bookmark thumbnail with valid parameters + */ + public function testAjaxUpdateBookmarkNotFound(): void + { + $id = 123; + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('get') + ->with($id) + ->willThrowException(new BookmarkNotFoundException()) + ; + + $result = $this->controller->ajaxUpdate($request, $response, ['id' => (string) $id]); + + static::assertSame(404, $result->getStatusCode()); + } +} -- cgit v1.2.3 From 1a8ac737e52cb25a5c346232ee398f5908cee7d7 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Mon, 6 Jul 2020 08:04:35 +0200 Subject: Process main page (linklist) through Slim controller Including a bunch of improvements on the container, and helper used across new controllers. --- tests/front/ShaarliMiddlewareTest.php | 130 +++++- .../visitor/BookmarkListControllerTest.php | 448 +++++++++++++++++++++ 2 files changed, 573 insertions(+), 5 deletions(-) create mode 100644 tests/front/controller/visitor/BookmarkListControllerTest.php (limited to 'tests/front') diff --git a/tests/front/ShaarliMiddlewareTest.php b/tests/front/ShaarliMiddlewareTest.php index 57be1002..81ea1344 100644 --- a/tests/front/ShaarliMiddlewareTest.php +++ b/tests/front/ShaarliMiddlewareTest.php @@ -8,7 +8,11 @@ use PHPUnit\Framework\TestCase; use Shaarli\Config\ConfigManager; use Shaarli\Container\ShaarliContainer; use Shaarli\Front\Exception\LoginBannedException; +use Shaarli\Front\Exception\UnauthorizedException; use Shaarli\Render\PageBuilder; +use Shaarli\Render\PageCacheManager; +use Shaarli\Security\LoginManager; +use Shaarli\Updater\Updater; use Slim\Http\Request; use Slim\Http\Response; use Slim\Http\Uri; @@ -24,9 +28,16 @@ class ShaarliMiddlewareTest extends TestCase public function setUp(): void { $this->container = $this->createMock(ShaarliContainer::class); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->middleware = new ShaarliMiddleware($this->container); } + /** + * Test middleware execution with valid controller call + */ public function testMiddlewareExecution(): void { $request = $this->createMock(Request::class); @@ -49,7 +60,10 @@ class ShaarliMiddlewareTest extends TestCase static::assertSame(418, $result->getStatusCode()); } - public function testMiddlewareExecutionWithException(): void + /** + * Test middleware execution with controller throwing a known front exception + */ + public function testMiddlewareExecutionWithFrontException(): void { $request = $this->createMock(Request::class); $request->method('getUri')->willReturnCallback(function (): Uri { @@ -58,7 +72,7 @@ class ShaarliMiddlewareTest extends TestCase return $uri; }); - + $response = new Response(); $controller = function (): void { $exception = new LoginBannedException(); @@ -72,9 +86,6 @@ class ShaarliMiddlewareTest extends TestCase }); $this->container->pageBuilder = $pageBuilder; - $conf = $this->createMock(ConfigManager::class); - $this->container->conf = $conf; - /** @var Response $result */ $result = $this->middleware->__invoke($request, $response, $controller); @@ -82,4 +93,113 @@ class ShaarliMiddlewareTest extends TestCase static::assertSame(401, $result->getStatusCode()); static::assertContains('error', (string) $result->getBody()); } + + /** + * Test middleware execution with controller throwing a not authorized exception + */ + public function testMiddlewareExecutionWithUnauthorizedException(): void + { + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + + $response = new Response(); + $controller = function (): void { + throw new UnauthorizedException(); + }; + + /** @var Response $result */ + $result = $this->middleware->__invoke($request, $response, $controller); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/login', $result->getHeader('location')[0]); + } + + /** + * Test middleware execution with controller throwing a not authorized exception + */ + public function testMiddlewareExecutionWithServerExceptionWith(): void + { + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + + $response = new Response(); + $controller = function (): void { + throw new \Exception(); + }; + + $parameters = []; + $this->container->pageBuilder = $this->createMock(PageBuilder::class); + $this->container->pageBuilder->method('render')->willReturnCallback(function (string $message): string { + return $message; + }); + $this->container->pageBuilder + ->method('assign') + ->willReturnCallback(function (string $key, string $value) use (&$parameters): void { + $parameters[$key] = $value; + }) + ; + + /** @var Response $result */ + $result = $this->middleware->__invoke($request, $response, $controller); + + static::assertSame(500, $result->getStatusCode()); + static::assertContains('error', (string) $result->getBody()); + static::assertSame('An unexpected error occurred.', $parameters['message']); + } + + public function testMiddlewareExecutionWithUpdates(): void + { + $request = $this->createMock(Request::class); + $request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + + $response = new Response(); + $controller = function (Request $request, Response $response): Response { + return $response->withStatus(418); // I'm a tea pot + }; + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $key): string { + return $key; + }); + + $this->container->pageCacheManager = $this->createMock(PageCacheManager::class); + $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches'); + + $this->container->updater = $this->createMock(Updater::class); + $this->container->updater + ->expects(static::once()) + ->method('update') + ->willReturn(['update123']) + ; + $this->container->updater->method('getDoneUpdates')->willReturn($updates = ['update123', 'other']); + $this->container->updater + ->expects(static::once()) + ->method('writeUpdates') + ->with('resource.updates', $updates) + ; + + /** @var Response $result */ + $result = $this->middleware->__invoke($request, $response, $controller); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(418, $result->getStatusCode()); + } } diff --git a/tests/front/controller/visitor/BookmarkListControllerTest.php b/tests/front/controller/visitor/BookmarkListControllerTest.php new file mode 100644 index 00000000..5daaa2c4 --- /dev/null +++ b/tests/front/controller/visitor/BookmarkListControllerTest.php @@ -0,0 +1,448 @@ +createContainer(); + + $this->controller = new BookmarkListController($this->container); + } + + /** + * Test rendering list of bookmarks with default parameters (first page). + */ + public function testIndexDefaultFirstPage(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->with( + ['searchtags' => '', 'searchterm' => ''], + null, + false, + false + ) + ->willReturn([ + (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), + (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), + (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), + ] + ); + + $this->container->sessionManager + ->method('getSessionParameter') + ->willReturnCallback(function (string $parameter, $default = null) { + if ('LINKS_PER_PAGE' === $parameter) { + return 2; + } + + return $default; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + + static::assertSame('Shaarli', $assignedVariables['pagetitle']); + static::assertSame('?page=2', $assignedVariables['previous_page_url']); + static::assertSame('', $assignedVariables['next_page_url']); + static::assertSame(2, $assignedVariables['page_max']); + static::assertSame('', $assignedVariables['search_tags']); + static::assertSame(3, $assignedVariables['result_count']); + static::assertSame(1, $assignedVariables['page_current']); + static::assertSame('', $assignedVariables['search_term']); + static::assertNull($assignedVariables['visibility']); + static::assertCount(2, $assignedVariables['links']); + + $link = $assignedVariables['links'][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url1.tld', $link['url']); + static::assertSame('Title 1', $link['title']); + + $link = $assignedVariables['links'][1]; + + static::assertSame(2, $link['id']); + static::assertSame('http://url2.tld', $link['url']); + static::assertSame('Title 2', $link['title']); + } + + /** + * Test rendering list of bookmarks with default parameters (second page). + */ + public function testIndexDefaultSecondPage(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key) { + if ('page' === $key) { + return '2'; + } + + return null; + }); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->with( + ['searchtags' => '', 'searchterm' => ''], + null, + false, + false + ) + ->willReturn([ + (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), + (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), + (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), + ]) + ; + + $this->container->sessionManager + ->method('getSessionParameter') + ->willReturnCallback(function (string $parameter, $default = null) { + if ('LINKS_PER_PAGE' === $parameter) { + return 2; + } + + return $default; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + + static::assertSame('Shaarli', $assignedVariables['pagetitle']); + static::assertSame('', $assignedVariables['previous_page_url']); + static::assertSame('?page=1', $assignedVariables['next_page_url']); + static::assertSame(2, $assignedVariables['page_max']); + static::assertSame('', $assignedVariables['search_tags']); + static::assertSame(3, $assignedVariables['result_count']); + static::assertSame(2, $assignedVariables['page_current']); + static::assertSame('', $assignedVariables['search_term']); + static::assertNull($assignedVariables['visibility']); + static::assertCount(1, $assignedVariables['links']); + + $link = $assignedVariables['links'][2]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertSame('Title 3', $link['title']); + } + + /** + * Test rendering list of bookmarks with filters. + */ + public function testIndexDefaultWithFilters(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key) { + if ('searchtags' === $key) { + return 'abc def'; + } + if ('searchterm' === $key) { + return 'ghi jkl'; + } + + return null; + }); + $response = new Response(); + + $this->container->sessionManager + ->method('getSessionParameter') + ->willReturnCallback(function (string $key, $default) { + if ('LINKS_PER_PAGE' === $key) { + return 2; + } + if ('visibility' === $key) { + return 'private'; + } + if ('untaggedonly' === $key) { + return true; + } + + return $default; + }) + ; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->with( + ['searchtags' => 'abc def', 'searchterm' => 'ghi jkl'], + 'private', + false, + true + ) + ->willReturn([ + (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), + (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), + (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), + ]) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + + static::assertSame('Search: ghi jkl [abc] [def] - Shaarli', $assignedVariables['pagetitle']); + static::assertSame('?page=2&searchterm=ghi+jkl&searchtags=abc+def', $assignedVariables['previous_page_url']); + } + + /** + * Test displaying a permalink with valid parameters + */ + public function testPermalinkValid(): void + { + $hash = 'abcdef'; + + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByHash') + ->with($hash) + ->willReturn((new Bookmark())->setId(123)->setTitle('Title 1')->setUrl('http://url1.tld')) + ; + + $result = $this->controller->permalink($request, $response, ['hash' => $hash]); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + + static::assertSame('Title 1 - Shaarli', $assignedVariables['pagetitle']); + static::assertCount(1, $assignedVariables['links']); + + $link = $assignedVariables['links'][0]; + + static::assertSame(123, $link['id']); + static::assertSame('http://url1.tld', $link['url']); + static::assertSame('Title 1', $link['title']); + } + + /** + * Test displaying a permalink with an unknown small hash : renders a 404 template error + */ + public function testPermalinkNotFound(): void + { + $hash = 'abcdef'; + + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByHash') + ->with($hash) + ->willThrowException(new BookmarkNotFoundException()) + ; + + $result = $this->controller->permalink($request, $response, ['hash' => $hash]); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('404', (string) $result->getBody()); + + static::assertSame( + 'The link you are trying to reach does not exist or has been deleted.', + $assignedVariables['error_message'] + ); + } + + /** + * Test getting link list with thumbnail updates. + * -> 2 thumbnails update, only 1 datastore write + */ + public function testThumbnailUpdateFromLinkList(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf + ->method('get') + ->willReturnCallback(function (string $key, $default) { + return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default; + }) + ; + + $this->container->thumbnailer = $this->createMock(Thumbnailer::class); + $this->container->thumbnailer + ->expects(static::exactly(2)) + ->method('get') + ->withConsecutive(['https://url2.tld'], ['https://url4.tld']) + ; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->willReturn([ + (new Bookmark())->setId(1)->setUrl('https://url1.tld')->setTitle('Title 1')->setThumbnail(false), + $b1 = (new Bookmark())->setId(2)->setUrl('https://url2.tld')->setTitle('Title 2'), + (new Bookmark())->setId(3)->setUrl('https://url3.tld')->setTitle('Title 3')->setThumbnail(false), + $b2 = (new Bookmark())->setId(2)->setUrl('https://url4.tld')->setTitle('Title 4'), + (new Bookmark())->setId(2)->setUrl('ftp://url5.tld', ['ftp'])->setTitle('Title 5'), + ]) + ; + $this->container->bookmarkService + ->expects(static::exactly(2)) + ->method('set') + ->withConsecutive([$b1, false], [$b2, false]) + ; + $this->container->bookmarkService->expects(static::once())->method('save'); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + } + + /** + * Test getting a permalink with thumbnail update. + */ + public function testThumbnailUpdateFromPermalink(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf + ->method('get') + ->willReturnCallback(function (string $key, $default) { + return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default; + }) + ; + + $this->container->thumbnailer = $this->createMock(Thumbnailer::class); + $this->container->thumbnailer->expects(static::once())->method('get')->withConsecutive(['https://url.tld']); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByHash') + ->willReturn($bookmark = (new Bookmark())->setId(2)->setUrl('https://url.tld')->setTitle('Title 1')) + ; + $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, true); + $this->container->bookmarkService->expects(static::never())->method('save'); + + $result = $this->controller->permalink($request, $response, ['hash' => 'abc']); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + } + + /** + * Trigger legacy controller in link list controller: permalink + */ + public function testLegacyControllerPermalink(): void + { + $hash = 'abcdef'; + $this->container->environment['QUERY_STRING'] = $hash; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/shaare/' . $hash, $result->getHeader('location')[0]); + } + + /** + * Trigger legacy controller in link list controller: ?do= query parameter + */ + public function testLegacyControllerDoPage(): void + { + $request = $this->createMock(Request::class); + $request->method('getQueryParam')->with('do')->willReturn('picwall'); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/picture-wall', $result->getHeader('location')[0]); + } + + /** + * Trigger legacy controller in link list controller: ?do= query parameter with unknown legacy route + */ + public function testLegacyControllerUnknownDoPage(): void + { + $request = $this->createMock(Request::class); + $request->method('getQueryParam')->with('do')->willReturn('nope'); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + } + + /** + * Trigger legacy controller in link list controller: other GET route (e.g. ?post) + */ + public function testLegacyControllerGetParameter(): void + { + $request = $this->createMock(Request::class); + $request->method('getQueryParams')->willReturn(['post' => $url = 'http://url.tld']); + $response = new Response(); + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $result = $this->controller->index($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame( + '/subfolder/admin/shaare?post=' . urlencode($url), + $result->getHeader('location')[0] + ); + } +} -- cgit v1.2.3 From c4ad3d4f061d05a01db25aa54dda830ba776792d Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Tue, 7 Jul 2020 10:15:56 +0200 Subject: Process Shaarli install through Slim controller --- tests/front/ShaarliMiddlewareTest.php | 12 + .../controller/admin/LogoutControllerTest.php | 18 +- .../controller/visitor/InstallControllerTest.php | 264 +++++++++++++++++++++ 3 files changed, 283 insertions(+), 11 deletions(-) create mode 100644 tests/front/controller/visitor/InstallControllerTest.php (limited to 'tests/front') diff --git a/tests/front/ShaarliMiddlewareTest.php b/tests/front/ShaarliMiddlewareTest.php index 81ea1344..20090d8b 100644 --- a/tests/front/ShaarliMiddlewareTest.php +++ b/tests/front/ShaarliMiddlewareTest.php @@ -19,6 +19,8 @@ use Slim\Http\Uri; class ShaarliMiddlewareTest extends TestCase { + protected const TMP_MOCK_FILE = '.tmp'; + /** @var ShaarliContainer */ protected $container; @@ -29,12 +31,21 @@ class ShaarliMiddlewareTest extends TestCase { $this->container = $this->createMock(ShaarliContainer::class); + touch(static::TMP_MOCK_FILE); + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE); + $this->container->loginManager = $this->createMock(LoginManager::class); $this->middleware = new ShaarliMiddleware($this->container); } + public function tearDown() + { + unlink(static::TMP_MOCK_FILE); + } + /** * Test middleware execution with valid controller call */ @@ -179,6 +190,7 @@ class ShaarliMiddlewareTest extends TestCase $this->container->conf->method('get')->willReturnCallback(function (string $key): string { return $key; }); + $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE); $this->container->pageCacheManager = $this->createMock(PageCacheManager::class); $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches'); diff --git a/tests/front/controller/admin/LogoutControllerTest.php b/tests/front/controller/admin/LogoutControllerTest.php index ca177085..45e84dc0 100644 --- a/tests/front/controller/admin/LogoutControllerTest.php +++ b/tests/front/controller/admin/LogoutControllerTest.php @@ -4,14 +4,8 @@ declare(strict_types=1); namespace Shaarli\Front\Controller\Admin; -/** Override PHP builtin setcookie function in the local namespace to mock it... more or less */ -if (!function_exists('Shaarli\Front\Controller\Admin\setcookie')) { - function setcookie(string $name, string $value): void { - $_COOKIE[$name] = $value; - } -} - use PHPUnit\Framework\TestCase; +use Shaarli\Security\CookieManager; use Shaarli\Security\LoginManager; use Shaarli\Security\SessionManager; use Slim\Http\Request; @@ -29,8 +23,6 @@ class LogoutControllerTest extends TestCase $this->createContainer(); $this->controller = new LogoutController($this->container); - - setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, $cookie = 'hi there'); } public function testValidControllerInvoke(): void @@ -43,13 +35,17 @@ class LogoutControllerTest extends TestCase $this->container->sessionManager = $this->createMock(SessionManager::class); $this->container->sessionManager->expects(static::once())->method('logout'); - static::assertSame('hi there', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); + $this->container->cookieManager = $this->createMock(CookieManager::class); + $this->container->cookieManager + ->expects(static::once()) + ->method('setCookieParameter') + ->with(CookieManager::STAY_SIGNED_IN, 'false', 0, '/subfolder/') + ; $result = $this->controller->index($request, $response); static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); static::assertSame(['/subfolder/'], $result->getHeader('location')); - static::assertSame('false', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); } } diff --git a/tests/front/controller/visitor/InstallControllerTest.php b/tests/front/controller/visitor/InstallControllerTest.php new file mode 100644 index 00000000..6871fdd9 --- /dev/null +++ b/tests/front/controller/visitor/InstallControllerTest.php @@ -0,0 +1,264 @@ +createContainer(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('getConfigFileExt')->willReturn(static::MOCK_FILE); + $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { + if ($key === 'resource.raintpl_tpl') { + return '.'; + } + + return $default ?? $key; + }); + + $this->controller = new InstallController($this->container); + } + + protected function tearDown(): void + { + if (file_exists(static::MOCK_FILE)) { + unlink(static::MOCK_FILE); + } + } + + /** + * Test displaying install page with valid session. + */ + public function testInstallIndexWithValidSession(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->method('getSessionParameter') + ->willReturnCallback(function (string $key, $default) { + return $key === 'session_tested' ? 'Working' : $default; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('install', (string) $result->getBody()); + + static::assertIsArray($assignedVariables['continents']); + static::assertSame('Africa', $assignedVariables['continents'][0]); + static::assertSame('UTC', $assignedVariables['continents']['selected']); + + static::assertIsArray($assignedVariables['cities']); + static::assertSame(['continent' => 'Africa', 'city' => 'Abidjan'], $assignedVariables['cities'][0]); + static::assertSame('UTC', $assignedVariables['continents']['selected']); + + static::assertIsArray($assignedVariables['languages']); + static::assertSame('Automatic', $assignedVariables['languages']['auto']); + static::assertSame('French', $assignedVariables['languages']['fr']); + } + + /** + * Instantiate the install controller with an existing config file: exception. + */ + public function testInstallWithExistingConfigFile(): void + { + $this->expectException(AlreadyInstalledException::class); + + touch(static::MOCK_FILE); + + $this->controller = new InstallController($this->container); + } + + /** + * Call controller without session yet defined, redirect to test session install page. + */ + public function testInstallRedirectToSessionTest(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(InstallController::SESSION_TEST_KEY, InstallController::SESSION_TEST_VALUE) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/install/session-test', $result->getHeader('location')[0]); + } + + /** + * Call controller in session test mode: valid session then redirect to install page. + */ + public function testInstallSessionTestValid(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(InstallController::SESSION_TEST_KEY) + ->willReturn(InstallController::SESSION_TEST_VALUE) + ; + + $result = $this->controller->sessionTest($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/install', $result->getHeader('location')[0]); + } + + /** + * Call controller in session test mode: invalid session then redirect to error page. + */ + public function testInstallSessionTestError(): void + { + $assignedVars = []; + $this->assignTemplateVars($assignedVars); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(InstallController::SESSION_TEST_KEY) + ->willReturn('KO') + ; + + $result = $this->controller->sessionTest($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('error', (string) $result->getBody()); + static::assertStringStartsWith( + '
Sessions do not seem to work correctly on your server',
+            $assignedVars['message']
+        );
+    }
+
+    /**
+     * Test saving valid data from install form. Also initialize datastore.
+     */
+    public function testSaveInstallValid(): void
+    {
+        $providedParameters = [
+            'continent' => 'Europe',
+            'city' => 'Berlin',
+            'setlogin' => 'bob',
+            'setpassword' => 'password',
+            'title' => 'Shaarli',
+            'language' => 'fr',
+            'updateCheck' => true,
+            'enableApi' => true,
+        ];
+
+        $expectedSettings = [
+            'general.timezone' => 'Europe/Berlin',
+            'credentials.login' => 'bob',
+            'credentials.salt' => '_NOT_EMPTY',
+            'credentials.hash' => '_NOT_EMPTY',
+            'general.title' => 'Shaarli',
+            'translation.language' => 'en',
+            'updates.check_updates' => true,
+            'api.enabled' => true,
+            'api.secret' => '_NOT_EMPTY',
+        ];
+
+        $request = $this->createMock(Request::class);
+        $request->method('getParam')->willReturnCallback(function (string $key) use ($providedParameters) {
+            return $providedParameters[$key] ?? null;
+        });
+        $response = new Response();
+
+        $this->container->conf = $this->createMock(ConfigManager::class);
+        $this->container->conf
+            ->method('get')
+            ->willReturnCallback(function (string $key, $value) {
+                if ($key === 'credentials.login') {
+                    return 'bob';
+                } elseif ($key === 'credentials.salt') {
+                    return 'salt';
+                }
+
+                return $value;
+            })
+        ;
+        $this->container->conf
+            ->expects(static::exactly(count($expectedSettings)))
+            ->method('set')
+            ->willReturnCallback(function (string $key, $value) use ($expectedSettings) {
+                if ($expectedSettings[$key] ?? null === '_NOT_EMPTY') {
+                    static::assertNotEmpty($value);
+                } else {
+                    static::assertSame($expectedSettings[$key], $value);
+                }
+            })
+        ;
+        $this->container->conf->expects(static::once())->method('write');
+
+        $this->container->bookmarkService->expects(static::once())->method('count')->willReturn(0);
+        $this->container->bookmarkService->expects(static::once())->method('initialize');
+
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_SUCCESS_MESSAGES)
+        ;
+
+        $result = $this->controller->save($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+    }
+
+    /**
+     * Test default settings (timezone and title).
+     * Also check that bookmarks are not initialized if
+     */
+    public function testSaveInstallDefaultValues(): void
+    {
+        $confSettings = [];
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->conf->method('set')->willReturnCallback(function (string $key, $value) use (&$confSettings) {
+            $confSettings[$key] = $value;
+        });
+
+        $result = $this->controller->save($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+
+        static::assertSame('UTC', $confSettings['general.timezone']);
+        static::assertSame('Shared bookmarks on http://shaarli', $confSettings['general.title']);
+    }
+}
-- 
cgit v1.2.3


From a8c11451e8d885a243c1ad52012093ba8d121e2c Mon Sep 17 00:00:00 2001
From: ArthurHoaro 
Date: Tue, 21 Jul 2020 20:33:33 +0200
Subject: Process login through Slim controller

---
 tests/front/ShaarliMiddlewareTest.php              |   7 +-
 .../visitor/FrontControllerMockHelper.php          |   1 +
 .../controller/visitor/LoginControllerTest.php     | 278 ++++++++++++++++++++-
 3 files changed, 281 insertions(+), 5 deletions(-)

(limited to 'tests/front')

diff --git a/tests/front/ShaarliMiddlewareTest.php b/tests/front/ShaarliMiddlewareTest.php
index 20090d8b..09bebd04 100644
--- a/tests/front/ShaarliMiddlewareTest.php
+++ b/tests/front/ShaarliMiddlewareTest.php
@@ -38,6 +38,8 @@ class ShaarliMiddlewareTest extends TestCase
 
         $this->container->loginManager = $this->createMock(LoginManager::class);
 
+        $this->container->environment = ['REQUEST_URI' => 'http://shaarli/subfolder/path'];
+
         $this->middleware = new ShaarliMiddleware($this->container);
     }
 
@@ -127,7 +129,10 @@ class ShaarliMiddlewareTest extends TestCase
         $result = $this->middleware->__invoke($request, $response, $controller);
 
         static::assertSame(302, $result->getStatusCode());
-        static::assertSame('/subfolder/login', $result->getHeader('location')[0]);
+        static::assertSame(
+            '/subfolder/login?returnurl=' . urlencode('http://shaarli/subfolder/path'),
+            $result->getHeader('location')[0]
+        );
     }
 
     /**
diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php
index 7f560662..e0bd4ecf 100644
--- a/tests/front/controller/visitor/FrontControllerMockHelper.php
+++ b/tests/front/controller/visitor/FrontControllerMockHelper.php
@@ -80,6 +80,7 @@ trait FrontControllerMockHelper
             'SERVER_NAME' => 'shaarli',
             'SERVER_PORT' => '80',
             'REQUEST_URI' => '/daily-rss',
+            'REMOTE_ADDR' => '1.2.3.4',
         ];
 
         $this->container->basePath = '/subfolder';
diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php
index e57f44b9..0a21f938 100644
--- a/tests/front/controller/visitor/LoginControllerTest.php
+++ b/tests/front/controller/visitor/LoginControllerTest.php
@@ -7,6 +7,10 @@ namespace Shaarli\Front\Controller\Visitor;
 use PHPUnit\Framework\TestCase;
 use Shaarli\Config\ConfigManager;
 use Shaarli\Front\Exception\LoginBannedException;
+use Shaarli\Front\Exception\WrongTokenException;
+use Shaarli\Render\TemplatePage;
+use Shaarli\Security\CookieManager;
+use Shaarli\Security\SessionManager;
 use Slim\Http\Request;
 use Slim\Http\Response;
 
@@ -21,13 +25,25 @@ class LoginControllerTest extends TestCase
     {
         $this->createContainer();
 
+        $this->container->cookieManager = $this->createMock(CookieManager::class);
+        $this->container->sessionManager->method('checkToken')->willReturn(true);
+
         $this->controller = new LoginController($this->container);
     }
 
+    /**
+     * Test displaying login form with valid parameters.
+     */
     public function testValidControllerInvoke(): void
     {
         $request = $this->createMock(Request::class);
-        $request->expects(static::once())->method('getServerParam')->willReturn('> referer');
+        $request
+            ->expects(static::atLeastOnce())
+            ->method('getParam')
+            ->willReturnCallback(function (string $key) {
+                return 'returnurl' === $key ? '> referer' : null;
+            })
+        ;
         $response = new Response();
 
         $assignedVariables = [];
@@ -46,18 +62,32 @@ class LoginControllerTest extends TestCase
 
         static::assertInstanceOf(Response::class, $result);
         static::assertSame(200, $result->getStatusCode());
-        static::assertSame('loginform', (string) $result->getBody());
+        static::assertSame(TemplatePage::LOGIN, (string) $result->getBody());
 
         static::assertSame('> referer', $assignedVariables['returnurl']);
         static::assertSame(true, $assignedVariables['remember_user_default']);
         static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']);
     }
 
+    /**
+     * Test displaying login form with username defined in the request.
+     */
     public function testValidControllerInvokeWithUserName(): void
     {
+        $this->container->environment = ['HTTP_REFERER' => '> referer'];
+
         $request = $this->createMock(Request::class);
-        $request->expects(static::once())->method('getServerParam')->willReturn('> referer');
-        $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>');
+        $request
+            ->expects(static::atLeastOnce())
+            ->method('getParam')
+            ->willReturnCallback(function (string $key, $default) {
+                if ('login' === $key) {
+                    return 'myUser>';
+                }
+
+                return $default;
+            })
+        ;
         $response = new Response();
 
         $assignedVariables = [];
@@ -84,6 +114,9 @@ class LoginControllerTest extends TestCase
         static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']);
     }
 
+    /**
+     * Test displaying login page while being logged in.
+     */
     public function testLoginControllerWhileLoggedIn(): void
     {
         $request = $this->createMock(Request::class);
@@ -98,6 +131,9 @@ class LoginControllerTest extends TestCase
         static::assertSame(['/subfolder/'], $result->getHeader('Location'));
     }
 
+    /**
+     * Test displaying login page with open shaarli configured: redirect to homepage.
+     */
     public function testLoginControllerOpenShaarli(): void
     {
         $request = $this->createMock(Request::class);
@@ -119,6 +155,9 @@ class LoginControllerTest extends TestCase
         static::assertSame(['/subfolder/'], $result->getHeader('Location'));
     }
 
+    /**
+     * Test displaying login page while being banned.
+     */
     public function testLoginControllerWhileBanned(): void
     {
         $request = $this->createMock(Request::class);
@@ -131,4 +170,235 @@ class LoginControllerTest extends TestCase
 
         $this->controller->index($request, $response);
     }
+
+    /**
+     * Test processing login with valid parameters.
+     */
+    public function testProcessLoginWithValidParameters(): void
+    {
+        $parameters = [
+            'login' => 'bob',
+            'password' => 'pass',
+        ];
+        $request = $this->createMock(Request::class);
+        $request
+            ->expects(static::atLeastOnce())
+            ->method('getParam')
+            ->willReturnCallback(function (string $key) use ($parameters) {
+                return $parameters[$key] ?? null;
+            })
+        ;
+        $response = new Response();
+
+        $this->container->loginManager->method('canLogin')->willReturn(true);
+        $this->container->loginManager->expects(static::once())->method('handleSuccessfulLogin');
+        $this->container->loginManager
+            ->expects(static::once())
+            ->method('checkCredentials')
+            ->with('1.2.3.4', '1.2.3.4', 'bob', 'pass')
+            ->willReturn(true)
+        ;
+        $this->container->loginManager->method('getStaySignedInToken')->willReturn(bin2hex(random_bytes(8)));
+
+        $this->container->sessionManager->expects(static::never())->method('extendSession');
+        $this->container->sessionManager->expects(static::once())->method('destroy');
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('cookieParameters')
+            ->with(0, '/subfolder/', 'shaarli')
+        ;
+        $this->container->sessionManager->expects(static::once())->method('start');
+        $this->container->sessionManager->expects(static::once())->method('regenerateId')->with(true);
+
+        $result = $this->controller->login($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+    }
+
+    /**
+     * Test processing login with return URL.
+     */
+    public function testProcessLoginWithReturnUrl(): void
+    {
+        $parameters = [
+            'returnurl' => 'http://shaarli/subfolder/admin/shaare',
+        ];
+        $request = $this->createMock(Request::class);
+        $request
+            ->expects(static::atLeastOnce())
+            ->method('getParam')
+            ->willReturnCallback(function (string $key) use ($parameters) {
+                return $parameters[$key] ?? null;
+            })
+        ;
+        $response = new Response();
+
+        $this->container->loginManager->method('canLogin')->willReturn(true);
+        $this->container->loginManager->expects(static::once())->method('handleSuccessfulLogin');
+        $this->container->loginManager->expects(static::once())->method('checkCredentials')->willReturn(true);
+        $this->container->loginManager->method('getStaySignedInToken')->willReturn(bin2hex(random_bytes(8)));
+
+        $result = $this->controller->login($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/admin/shaare', $result->getHeader('location')[0]);
+    }
+
+    /**
+     * Test processing login with remember me session enabled.
+     */
+    public function testProcessLoginLongLastingSession(): void
+    {
+        $parameters = [
+            'longlastingsession' => true,
+        ];
+        $request = $this->createMock(Request::class);
+        $request
+            ->expects(static::atLeastOnce())
+            ->method('getParam')
+            ->willReturnCallback(function (string $key) use ($parameters) {
+                return $parameters[$key] ?? null;
+            })
+        ;
+        $response = new Response();
+
+        $this->container->loginManager->method('canLogin')->willReturn(true);
+        $this->container->loginManager->expects(static::once())->method('handleSuccessfulLogin');
+        $this->container->loginManager->expects(static::once())->method('checkCredentials')->willReturn(true);
+        $this->container->loginManager->method('getStaySignedInToken')->willReturn(bin2hex(random_bytes(8)));
+
+        $this->container->sessionManager->expects(static::once())->method('destroy');
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('cookieParameters')
+            ->with(42, '/subfolder/', 'shaarli')
+        ;
+        $this->container->sessionManager->expects(static::once())->method('start');
+        $this->container->sessionManager->expects(static::once())->method('regenerateId')->with(true);
+        $this->container->sessionManager->expects(static::once())->method('extendSession')->willReturn(42);
+
+        $this->container->cookieManager = $this->createMock(CookieManager::class);
+        $this->container->cookieManager
+            ->expects(static::once())
+            ->method('setCookieParameter')
+            ->willReturnCallback(function (string $name): CookieManager {
+                static::assertSame(CookieManager::STAY_SIGNED_IN, $name);
+
+                return $this->container->cookieManager;
+            })
+        ;
+
+        $result = $this->controller->login($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+    }
+
+    /**
+     * Test processing login with invalid credentials
+     */
+    public function testProcessLoginWrongCredentials(): void
+    {
+        $parameters = [
+            'returnurl' => 'http://shaarli/subfolder/admin/shaare',
+        ];
+        $request = $this->createMock(Request::class);
+        $request
+            ->expects(static::atLeastOnce())
+            ->method('getParam')
+            ->willReturnCallback(function (string $key) use ($parameters) {
+                return $parameters[$key] ?? null;
+            })
+        ;
+        $response = new Response();
+
+        $this->container->loginManager->method('canLogin')->willReturn(true);
+        $this->container->loginManager->expects(static::once())->method('handleFailedLogin');
+        $this->container->loginManager->expects(static::once())->method('checkCredentials')->willReturn(false);
+
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_ERROR_MESSAGES, ['Wrong login/password.'])
+        ;
+
+        $result = $this->controller->login($request, $response);
+
+        static::assertSame(200, $result->getStatusCode());
+        static::assertSame(TemplatePage::LOGIN, (string) $result->getBody());
+    }
+
+    /**
+     * Test processing login with wrong token
+     */
+    public function testProcessLoginWrongToken(): void
+    {
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->sessionManager = $this->createMock(SessionManager::class);
+        $this->container->sessionManager->method('checkToken')->willReturn(false);
+
+        $this->expectException(WrongTokenException::class);
+
+        $this->controller->login($request, $response);
+    }
+
+    /**
+     * Test processing login with wrong token
+     */
+    public function testProcessLoginAlreadyLoggedIn(): void
+    {
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->loginManager->method('isLoggedIn')->willReturn(true);
+        $this->container->loginManager->expects(static::never())->method('handleSuccessfulLogin');
+        $this->container->loginManager->expects(static::never())->method('handleFailedLogin');
+
+        $result = $this->controller->login($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+    }
+
+    /**
+     * Test processing login with wrong token
+     */
+    public function testProcessLoginInOpenShaarli(): void
+    {
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->conf = $this->createMock(ConfigManager::class);
+        $this->container->conf->method('get')->willReturnCallback(function (string $key, $value) {
+            return 'security.open_shaarli' === $key ? true : $value;
+        });
+
+        $this->container->loginManager->expects(static::never())->method('handleSuccessfulLogin');
+        $this->container->loginManager->expects(static::never())->method('handleFailedLogin');
+
+        $result = $this->controller->login($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+    }
+
+    /**
+     * Test processing login while being banned
+     */
+    public function testProcessLoginWhileBanned(): void
+    {
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->loginManager->method('canLogin')->willReturn(false);
+        $this->container->loginManager->expects(static::never())->method('handleSuccessfulLogin');
+        $this->container->loginManager->expects(static::never())->method('handleFailedLogin');
+
+        $this->expectException(LoginBannedException::class);
+
+        $this->controller->login($request, $response);
+    }
 }
-- 
cgit v1.2.3


From 3ee8351e438f13ccf36062ce956e0b4a4d5f4a29 Mon Sep 17 00:00:00 2001
From: ArthurHoaro 
Date: Thu, 23 Jul 2020 16:41:32 +0200
Subject: Multiple small fixes

---
 tests/front/controller/admin/PluginsControllerTest.php   | 2 +-
 tests/front/controller/visitor/InstallControllerTest.php | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

(limited to 'tests/front')

diff --git a/tests/front/controller/admin/PluginsControllerTest.php b/tests/front/controller/admin/PluginsControllerTest.php
index 700a0df2..ad0cda70 100644
--- a/tests/front/controller/admin/PluginsControllerTest.php
+++ b/tests/front/controller/admin/PluginsControllerTest.php
@@ -162,7 +162,7 @@ class PluginsControllerTest extends TestCase
             ->method('setSessionParameter')
             ->with(
                 SessionManager::KEY_ERROR_MESSAGES,
-                ['ERROR while saving plugin configuration: ' . PHP_EOL . $message]
+                ['Error while saving plugin configuration: ' . PHP_EOL . $message]
             )
         ;
 
diff --git a/tests/front/controller/visitor/InstallControllerTest.php b/tests/front/controller/visitor/InstallControllerTest.php
index 6871fdd9..29c4d7a0 100644
--- a/tests/front/controller/visitor/InstallControllerTest.php
+++ b/tests/front/controller/visitor/InstallControllerTest.php
@@ -189,6 +189,7 @@ class InstallControllerTest extends TestCase
             'updates.check_updates' => true,
             'api.enabled' => true,
             'api.secret' => '_NOT_EMPTY',
+            'general.header_link' => '/subfolder',
         ];
 
         $request = $this->createMock(Request::class);
-- 
cgit v1.2.3


From 87ae3c4f08431e02869376cb57add257747910d1 Mon Sep 17 00:00:00 2001
From: ArthurHoaro 
Date: Fri, 24 Jul 2020 10:30:47 +0200
Subject: Fix default link and redirection in install controller

---
 tests/front/controller/visitor/InstallControllerTest.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'tests/front')

diff --git a/tests/front/controller/visitor/InstallControllerTest.php b/tests/front/controller/visitor/InstallControllerTest.php
index 29c4d7a0..089c64ac 100644
--- a/tests/front/controller/visitor/InstallControllerTest.php
+++ b/tests/front/controller/visitor/InstallControllerTest.php
@@ -236,7 +236,7 @@ class InstallControllerTest extends TestCase
         $result = $this->controller->save($request, $response);
 
         static::assertSame(302, $result->getStatusCode());
-        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+        static::assertSame('/subfolder/login', $result->getHeader('location')[0]);
     }
 
     /**
@@ -257,7 +257,7 @@ class InstallControllerTest extends TestCase
         $result = $this->controller->save($request, $response);
 
         static::assertSame(302, $result->getStatusCode());
-        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+        static::assertSame('/subfolder/login', $result->getHeader('location')[0]);
 
         static::assertSame('UTC', $confSettings['general.timezone']);
         static::assertSame('Shared bookmarks on http://shaarli', $confSettings['general.title']);
-- 
cgit v1.2.3


From 204035bd3c91b9a5c39fcb6fc470e108b032dbd9 Mon Sep 17 00:00:00 2001
From: ArthurHoaro 
Date: Fri, 24 Jul 2020 12:48:53 +0200
Subject: Fix: visitor are allowed to chose nb of links per page

---
 .../admin/SessionFilterControllerTest.php          | 48 +--------------
 .../visitor/PublicSessionFilterControllerTest.php  | 71 ++++++++++++++++++++++
 2 files changed, 72 insertions(+), 47 deletions(-)
 create mode 100644 tests/front/controller/visitor/PublicSessionFilterControllerTest.php

(limited to 'tests/front')

diff --git a/tests/front/controller/admin/SessionFilterControllerTest.php b/tests/front/controller/admin/SessionFilterControllerTest.php
index ea07edee..124b0bf2 100644
--- a/tests/front/controller/admin/SessionFilterControllerTest.php
+++ b/tests/front/controller/admin/SessionFilterControllerTest.php
@@ -23,53 +23,7 @@ class SessionFilterControllerTest extends TestCase
 
         $this->controller = new SessionFilterController($this->container);
     }
-
-    /**
-     * Link per page - Default call with valid parameter and a referer.
-     */
-    public function testLinksPerPage(): void
-    {
-        $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
-
-        $request = $this->createMock(Request::class);
-        $request->method('getParam')->with('nb')->willReturn('8');
-        $response = new Response();
-
-        $this->container->sessionManager
-            ->expects(static::once())
-            ->method('setSessionParameter')
-            ->with(SessionManager::KEY_LINKS_PER_PAGE, 8)
-        ;
-
-        $result = $this->controller->linksPerPage($request, $response);
-
-        static::assertInstanceOf(Response::class, $result);
-        static::assertSame(302, $result->getStatusCode());
-        static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
-    }
-
-    /**
-     * Link per page - Invalid value, should use default value (20)
-     */
-    public function testLinksPerPageNotValid(): void
-    {
-        $request = $this->createMock(Request::class);
-        $request->method('getParam')->with('nb')->willReturn('test');
-        $response = new Response();
-
-        $this->container->sessionManager
-            ->expects(static::once())
-            ->method('setSessionParameter')
-            ->with(SessionManager::KEY_LINKS_PER_PAGE, 20)
-        ;
-
-        $result = $this->controller->linksPerPage($request, $response);
-
-        static::assertInstanceOf(Response::class, $result);
-        static::assertSame(302, $result->getStatusCode());
-        static::assertSame(['/subfolder/'], $result->getHeader('location'));
-    }
-
+    
     /**
      * Visibility - Default call for private filter while logged in without current value
      */
diff --git a/tests/front/controller/visitor/PublicSessionFilterControllerTest.php b/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
new file mode 100644
index 00000000..3aa1cb99
--- /dev/null
+++ b/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
@@ -0,0 +1,71 @@
+createContainer();
+
+        $this->controller = new PublicSessionFilterController($this->container);
+    }
+
+    /**
+     * Link per page - Default call with valid parameter and a referer.
+     */
+    public function testLinksPerPage(): void
+    {
+        $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
+
+        $request = $this->createMock(Request::class);
+        $request->method('getParam')->with('nb')->willReturn('8');
+        $response = new Response();
+
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_LINKS_PER_PAGE, 8)
+        ;
+
+        $result = $this->controller->linksPerPage($request, $response);
+
+        static::assertInstanceOf(Response::class, $result);
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
+    }
+
+    /**
+     * Link per page - Invalid value, should use default value (20)
+     */
+    public function testLinksPerPageNotValid(): void
+    {
+        $request = $this->createMock(Request::class);
+        $request->method('getParam')->with('nb')->willReturn('test');
+        $response = new Response();
+
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_LINKS_PER_PAGE, 20)
+        ;
+
+        $result = $this->controller->linksPerPage($request, $response);
+
+        static::assertInstanceOf(Response::class, $result);
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame(['/subfolder/'], $result->getHeader('location'));
+    }
+}
-- 
cgit v1.2.3


From 9fbc42294e7667c5ef19cafa0d1fcfbc1c0f36a9 Mon Sep 17 00:00:00 2001
From: ArthurHoaro 
Date: Sun, 26 Jul 2020 14:43:10 +0200
Subject: New basePath: fix officiel plugin paths and vintage template

---
 .../DeleteBookmarkTest.php                         | 23 ++++++++++++++++++----
 .../controller/admin/PluginsControllerTest.php     | 14 +++++++++++++
 .../admin/SessionFilterControllerTest.php          |  2 +-
 .../visitor/ShaarliVisitorControllerTest.php       |  2 --
 4 files changed, 34 insertions(+), 7 deletions(-)

(limited to 'tests/front')

diff --git a/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php b/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php
index caaf549d..dee622bb 100644
--- a/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php
+++ b/tests/front/controller/admin/ManageShaareControllerTest/DeleteBookmarkTest.php
@@ -59,8 +59,12 @@ class DeleteBookmarkTest extends TestCase
             ->with('raw')
             ->willReturnCallback(function () use ($bookmark): BookmarkFormatter {
                 $formatter = $this->createMock(BookmarkFormatter::class);
-
-                $formatter->expects(static::once())->method('format')->with($bookmark);
+                $formatter
+                    ->expects(static::once())
+                    ->method('format')
+                    ->with($bookmark)
+                    ->willReturn(['formatted' => $bookmark])
+                ;
 
                 return $formatter;
             })
@@ -70,7 +74,7 @@ class DeleteBookmarkTest extends TestCase
         $this->container->pluginManager
             ->expects(static::once())
             ->method('executeHooks')
-            ->with('delete_link')
+            ->with('delete_link', ['formatted' => $bookmark])
         ;
 
         $result = $this->controller->deleteBookmark($request, $response);
@@ -129,6 +133,9 @@ class DeleteBookmarkTest extends TestCase
                     ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
                         return [$bookmark];
                     }, $bookmarks))
+                    ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array {
+                        return ['formatted' => $bookmark];
+                    }, $bookmarks))
                 ;
 
                 return $formatter;
@@ -254,6 +261,9 @@ class DeleteBookmarkTest extends TestCase
                     ->withConsecutive(...array_map(function (Bookmark $bookmark): array {
                         return [$bookmark];
                     }, $bookmarks))
+                    ->willReturnOnConsecutiveCalls(...array_map(function (Bookmark $bookmark): array {
+                        return ['formatted' => $bookmark];
+                    }, $bookmarks))
                 ;
 
                 return $formatter;
@@ -350,7 +360,12 @@ class DeleteBookmarkTest extends TestCase
         $this->container->formatterFactory
             ->expects(static::once())
             ->method('getFormatter')
-            ->willReturn($this->createMock(BookmarkFormatter::class))
+            ->willReturnCallback(function (): BookmarkFormatter {
+                $formatter = $this->createMock(BookmarkFormatter::class);
+                $formatter->method('format')->willReturn(['formatted']);
+
+                return $formatter;
+            })
         ;
 
         $result = $this->controller->deleteBookmark($request, $response);
diff --git a/tests/front/controller/admin/PluginsControllerTest.php b/tests/front/controller/admin/PluginsControllerTest.php
index ad0cda70..5b59285c 100644
--- a/tests/front/controller/admin/PluginsControllerTest.php
+++ b/tests/front/controller/admin/PluginsControllerTest.php
@@ -7,6 +7,7 @@ namespace Shaarli\Front\Controller\Admin;
 use PHPUnit\Framework\TestCase;
 use Shaarli\Config\ConfigManager;
 use Shaarli\Front\Exception\WrongTokenException;
+use Shaarli\Plugin\PluginManager;
 use Shaarli\Security\SessionManager;
 use Slim\Http\Request;
 use Slim\Http\Response;
@@ -15,6 +16,8 @@ class PluginsControllerTest extends TestCase
 {
     use FrontAdminControllerMockHelper;
 
+    const PLUGIN_NAMES = ['plugin1', 'plugin2', 'plugin3', 'plugin4'];
+
     /** @var PluginsController */
     protected $controller;
 
@@ -23,6 +26,17 @@ class PluginsControllerTest extends TestCase
         $this->createContainer();
 
         $this->controller = new PluginsController($this->container);
+
+        mkdir($path = __DIR__ . '/folder');
+        PluginManager::$PLUGINS_PATH = $path;
+        array_map(function (string $plugin) use ($path) { touch($path . '/' . $plugin); }, static::PLUGIN_NAMES);
+    }
+
+    public function tearDown()
+    {
+        $path = __DIR__ . '/folder';
+        array_map(function (string $plugin) use ($path) { unlink($path . '/' . $plugin); }, static::PLUGIN_NAMES);
+        rmdir($path);
     }
 
     /**
diff --git a/tests/front/controller/admin/SessionFilterControllerTest.php b/tests/front/controller/admin/SessionFilterControllerTest.php
index 124b0bf2..7d5511ed 100644
--- a/tests/front/controller/admin/SessionFilterControllerTest.php
+++ b/tests/front/controller/admin/SessionFilterControllerTest.php
@@ -23,7 +23,7 @@ class SessionFilterControllerTest extends TestCase
 
         $this->controller = new SessionFilterController($this->container);
     }
-    
+
     /**
      * Visibility - Default call for private filter while logged in without current value
      */
diff --git a/tests/front/controller/visitor/ShaarliVisitorControllerTest.php b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php
index 83d08358..316ce49c 100644
--- a/tests/front/controller/visitor/ShaarliVisitorControllerTest.php
+++ b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php
@@ -96,8 +96,6 @@ class ShaarliVisitorControllerTest extends TestCase
         static::assertSame(10, $this->assignedValues['linkcount']);
         static::assertSame(5, $this->assignedValues['privateLinkcount']);
         static::assertSame(['error'], $this->assignedValues['plugin_errors']);
-        static::assertSame('/subfolder', $this->assignedValues['base_path']);
-        static::assertSame('/subfolder/tpl/default', $this->assignedValues['asset_path']);
 
         static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']);
         static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']);
-- 
cgit v1.2.3


From d6e5f04d3987e498c5cb859eed6bff33d67949df Mon Sep 17 00:00:00 2001
From: ArthurHoaro 
Date: Sat, 1 Aug 2020 11:10:57 +0200
Subject: Remove anonymous permission and initialize bookmarks on login

---
 tests/front/controller/visitor/InstallControllerTest.php | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'tests/front')

diff --git a/tests/front/controller/visitor/InstallControllerTest.php b/tests/front/controller/visitor/InstallControllerTest.php
index 089c64ac..3b855365 100644
--- a/tests/front/controller/visitor/InstallControllerTest.php
+++ b/tests/front/controller/visitor/InstallControllerTest.php
@@ -224,9 +224,6 @@ class InstallControllerTest extends TestCase
         ;
         $this->container->conf->expects(static::once())->method('write');
 
-        $this->container->bookmarkService->expects(static::once())->method('count')->willReturn(0);
-        $this->container->bookmarkService->expects(static::once())->method('initialize');
-
         $this->container->sessionManager
             ->expects(static::once())
             ->method('setSessionParameter')
-- 
cgit v1.2.3


From bedbb845eec20363b928b424143787dbe988eefe Mon Sep 17 00:00:00 2001
From: ArthurHoaro 
Date: Thu, 13 Aug 2020 11:08:13 +0200
Subject: Move all admin controller into a dedicated group

Also handle authentication check in a new middleware for the admin group.
---
 tests/front/ShaarliAdminMiddlewareTest.php         | 100 +++++++++++++++++++++
 tests/front/ShaarliMiddlewareTest.php              |   2 +-
 .../admin/SessionFilterControllerTest.php          |  51 -----------
 .../admin/ShaarliAdminControllerTest.php           |  15 ----
 .../visitor/PublicSessionFilterControllerTest.php  |  51 +++++++++++
 5 files changed, 152 insertions(+), 67 deletions(-)
 create mode 100644 tests/front/ShaarliAdminMiddlewareTest.php

(limited to 'tests/front')

diff --git a/tests/front/ShaarliAdminMiddlewareTest.php b/tests/front/ShaarliAdminMiddlewareTest.php
new file mode 100644
index 00000000..7451330b
--- /dev/null
+++ b/tests/front/ShaarliAdminMiddlewareTest.php
@@ -0,0 +1,100 @@
+container = $this->createMock(ShaarliContainer::class);
+
+        touch(static::TMP_MOCK_FILE);
+
+        $this->container->conf = $this->createMock(ConfigManager::class);
+        $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE);
+
+        $this->container->loginManager = $this->createMock(LoginManager::class);
+        $this->container->updater = $this->createMock(Updater::class);
+
+        $this->container->environment = ['REQUEST_URI' => 'http://shaarli/subfolder/path'];
+
+        $this->middleware = new ShaarliAdminMiddleware($this->container);
+    }
+
+    public function tearDown(): void
+    {
+        unlink(static::TMP_MOCK_FILE);
+    }
+
+    /**
+     * Try to access an admin controller while logged out -> redirected to login page.
+     */
+    public function testMiddlewareWhileLoggedOut(): void
+    {
+        $this->container->loginManager->expects(static::once())->method('isLoggedIn')->willReturn(false);
+
+        $request = $this->createMock(Request::class);
+        $request->method('getUri')->willReturnCallback(function (): Uri {
+            $uri = $this->createMock(Uri::class);
+            $uri->method('getBasePath')->willReturn('/subfolder');
+
+            return $uri;
+        });
+
+        $response = new Response();
+
+        /** @var Response $result */
+        $result = $this->middleware->__invoke($request, $response, function () {});
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame(
+            '/subfolder/login?returnurl=' . urlencode('http://shaarli/subfolder/path'),
+            $result->getHeader('location')[0]
+        );
+    }
+
+    /**
+     * Process controller while logged in.
+     */
+    public function testMiddlewareWhileLoggedIn(): void
+    {
+        $this->container->loginManager->method('isLoggedIn')->willReturn(true);
+
+        $request = $this->createMock(Request::class);
+        $request->method('getUri')->willReturnCallback(function (): Uri {
+            $uri = $this->createMock(Uri::class);
+            $uri->method('getBasePath')->willReturn('/subfolder');
+
+            return $uri;
+        });
+
+        $response = new Response();
+        $controller = function (Request $request, Response $response): Response {
+            return $response->withStatus(418); // I'm a tea pot
+        };
+
+        /** @var Response $result */
+        $result = $this->middleware->__invoke($request, $response, $controller);
+
+        static::assertSame(418, $result->getStatusCode());
+    }
+}
diff --git a/tests/front/ShaarliMiddlewareTest.php b/tests/front/ShaarliMiddlewareTest.php
index 09bebd04..d435f506 100644
--- a/tests/front/ShaarliMiddlewareTest.php
+++ b/tests/front/ShaarliMiddlewareTest.php
@@ -43,7 +43,7 @@ class ShaarliMiddlewareTest extends TestCase
         $this->middleware = new ShaarliMiddleware($this->container);
     }
 
-    public function tearDown()
+    public function tearDown(): void
     {
         unlink(static::TMP_MOCK_FILE);
     }
diff --git a/tests/front/controller/admin/SessionFilterControllerTest.php b/tests/front/controller/admin/SessionFilterControllerTest.php
index 7d5511ed..d306c6e9 100644
--- a/tests/front/controller/admin/SessionFilterControllerTest.php
+++ b/tests/front/controller/admin/SessionFilterControllerTest.php
@@ -174,55 +174,4 @@ class SessionFilterControllerTest extends TestCase
         static::assertSame(302, $result->getStatusCode());
         static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
     }
-
-    /**
-     * Untagged only - valid call
-     */
-    public function testUntaggedOnly(): void
-    {
-        $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
-
-        $request = $this->createMock(Request::class);
-        $response = new Response();
-
-        $this->container->sessionManager
-            ->expects(static::once())
-            ->method('setSessionParameter')
-            ->with(SessionManager::KEY_UNTAGGED_ONLY, true)
-        ;
-
-        $result = $this->controller->untaggedOnly($request, $response);
-
-        static::assertInstanceOf(Response::class, $result);
-        static::assertSame(302, $result->getStatusCode());
-        static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
-    }
-
-    /**
-     * Untagged only - toggle off
-     */
-    public function testUntaggedOnlyToggleOff(): void
-    {
-        $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
-
-        $request = $this->createMock(Request::class);
-        $response = new Response();
-
-        $this->container->sessionManager
-            ->method('getSessionParameter')
-            ->with(SessionManager::KEY_UNTAGGED_ONLY)
-            ->willReturn(true)
-        ;
-        $this->container->sessionManager
-            ->expects(static::once())
-            ->method('setSessionParameter')
-            ->with(SessionManager::KEY_UNTAGGED_ONLY, false)
-        ;
-
-        $result = $this->controller->untaggedOnly($request, $response);
-
-        static::assertInstanceOf(Response::class, $result);
-        static::assertSame(302, $result->getStatusCode());
-        static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
-    }
 }
diff --git a/tests/front/controller/admin/ShaarliAdminControllerTest.php b/tests/front/controller/admin/ShaarliAdminControllerTest.php
index 7c5f50a6..fff427cb 100644
--- a/tests/front/controller/admin/ShaarliAdminControllerTest.php
+++ b/tests/front/controller/admin/ShaarliAdminControllerTest.php
@@ -5,9 +5,7 @@ declare(strict_types=1);
 namespace Shaarli\Front\Controller\Admin;
 
 use PHPUnit\Framework\TestCase;
-use Shaarli\Front\Exception\UnauthorizedException;
 use Shaarli\Front\Exception\WrongTokenException;
-use Shaarli\Security\LoginManager;
 use Shaarli\Security\SessionManager;
 use Slim\Http\Request;
 
@@ -52,19 +50,6 @@ class ShaarliAdminControllerTest extends TestCase
         };
     }
 
-    /**
-     * Creating an instance of an admin controller while logged out should raise an exception.
-     */
-    public function testInstantiateWhileLoggedOut(): void
-    {
-        $this->expectException(UnauthorizedException::class);
-
-        $this->container->loginManager = $this->createMock(LoginManager::class);
-        $this->container->loginManager->method('isLoggedIn')->willReturn(false);
-
-        $this->controller = new class($this->container) extends ShaarliAdminController {};
-    }
-
     /**
      * Trigger controller's checkToken with a valid token.
      */
diff --git a/tests/front/controller/visitor/PublicSessionFilterControllerTest.php b/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
index 3aa1cb99..06352750 100644
--- a/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
+++ b/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
@@ -68,4 +68,55 @@ class PublicSessionFilterControllerTest extends TestCase
         static::assertSame(302, $result->getStatusCode());
         static::assertSame(['/subfolder/'], $result->getHeader('location'));
     }
+
+    /**
+     * Untagged only - valid call
+     */
+    public function testUntaggedOnly(): void
+    {
+        $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_UNTAGGED_ONLY, true)
+        ;
+
+        $result = $this->controller->untaggedOnly($request, $response);
+
+        static::assertInstanceOf(Response::class, $result);
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
+    }
+
+    /**
+     * Untagged only - toggle off
+     */
+    public function testUntaggedOnlyToggleOff(): void
+    {
+        $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->sessionManager
+            ->method('getSessionParameter')
+            ->with(SessionManager::KEY_UNTAGGED_ONLY)
+            ->willReturn(true)
+        ;
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_UNTAGGED_ONLY, false)
+        ;
+
+        $result = $this->controller->untaggedOnly($request, $response);
+
+        static::assertInstanceOf(Response::class, $result);
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
+    }
 }
-- 
cgit v1.2.3


From 0c6fdbe12bbbb336348666b14b82096f24d5858b Mon Sep 17 00:00:00 2001
From: ArthurHoaro 
Date: Fri, 21 Aug 2020 10:50:44 +0200
Subject: Move error handling to dedicated controller instead of middleware

---
 tests/front/ShaarliMiddlewareTest.php              | 29 +++++----
 .../controller/visitor/ErrorControllerTest.php     | 70 ++++++++++++++++++++++
 2 files changed, 84 insertions(+), 15 deletions(-)
 create mode 100644 tests/front/controller/visitor/ErrorControllerTest.php

(limited to 'tests/front')

diff --git a/tests/front/ShaarliMiddlewareTest.php b/tests/front/ShaarliMiddlewareTest.php
index d435f506..05aa34a9 100644
--- a/tests/front/ShaarliMiddlewareTest.php
+++ b/tests/front/ShaarliMiddlewareTest.php
@@ -74,7 +74,8 @@ class ShaarliMiddlewareTest extends TestCase
     }
 
     /**
-     * Test middleware execution with controller throwing a known front exception
+     * Test middleware execution with controller throwing a known front exception.
+     * The exception should be thrown to be later handled by the error handler.
      */
     public function testMiddlewareExecutionWithFrontException(): void
     {
@@ -99,16 +100,14 @@ class ShaarliMiddlewareTest extends TestCase
         });
         $this->container->pageBuilder = $pageBuilder;
 
-        /** @var Response $result */
-        $result = $this->middleware->__invoke($request, $response, $controller);
+        $this->expectException(LoginBannedException::class);
 
-        static::assertInstanceOf(Response::class, $result);
-        static::assertSame(401, $result->getStatusCode());
-        static::assertContains('error', (string) $result->getBody());
+        $this->middleware->__invoke($request, $response, $controller);
     }
 
     /**
      * Test middleware execution with controller throwing a not authorized exception
+     * The middle should send a redirection response to the login page.
      */
     public function testMiddlewareExecutionWithUnauthorizedException(): void
     {
@@ -136,9 +135,10 @@ class ShaarliMiddlewareTest extends TestCase
     }
 
     /**
-     * Test middleware execution with controller throwing a not authorized exception
+     * Test middleware execution with controller throwing a not authorized exception.
+     * The exception should be thrown to be later handled by the error handler.
      */
-    public function testMiddlewareExecutionWithServerExceptionWith(): void
+    public function testMiddlewareExecutionWithServerException(): void
     {
         $request = $this->createMock(Request::class);
         $request->method('getUri')->willReturnCallback(function (): Uri {
@@ -148,9 +148,11 @@ class ShaarliMiddlewareTest extends TestCase
             return $uri;
         });
 
+        $dummyException = new class() extends \Exception {};
+
         $response = new Response();
-        $controller = function (): void {
-            throw new \Exception();
+        $controller = function () use ($dummyException): void {
+            throw $dummyException;
         };
 
         $parameters = [];
@@ -165,12 +167,9 @@ class ShaarliMiddlewareTest extends TestCase
             })
         ;
 
-        /** @var Response $result */
-        $result = $this->middleware->__invoke($request, $response, $controller);
+        $this->expectException(get_class($dummyException));
 
-        static::assertSame(500, $result->getStatusCode());
-        static::assertContains('error', (string) $result->getBody());
-        static::assertSame('An unexpected error occurred.', $parameters['message']);
+        $this->middleware->__invoke($request, $response, $controller);
     }
 
     public function testMiddlewareExecutionWithUpdates(): void
diff --git a/tests/front/controller/visitor/ErrorControllerTest.php b/tests/front/controller/visitor/ErrorControllerTest.php
new file mode 100644
index 00000000..e497bfef
--- /dev/null
+++ b/tests/front/controller/visitor/ErrorControllerTest.php
@@ -0,0 +1,70 @@
+createContainer();
+
+        $this->controller = new ErrorController($this->container);
+    }
+
+    /**
+     * Test displaying error with a ShaarliFrontException: display exception message and use its code for HTTTP code
+     */
+    public function testDisplayFrontExceptionError(): void
+    {
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $message = 'error message';
+        $errorCode = 418;
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        $result = ($this->controller)(
+            $request,
+            $response,
+            new class($message, $errorCode) extends ShaarliFrontException {}
+        );
+
+        static::assertSame($errorCode, $result->getStatusCode());
+        static::assertSame($message, $assignedVariables['message']);
+        static::assertArrayNotHasKey('stacktrace', $assignedVariables);
+    }
+
+    /**
+     * Test displaying error with any exception (no debug): only display an error occurred with HTTP 500.
+     */
+    public function testDisplayAnyExceptionErrorNoDebug(): void
+    {
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        $result = ($this->controller)($request, $response, new \Exception('abc'));
+
+        static::assertSame(500, $result->getStatusCode());
+        static::assertSame('An unexpected error occurred.', $assignedVariables['message']);
+        static::assertArrayNotHasKey('stacktrace', $assignedVariables);
+    }
+}
-- 
cgit v1.2.3