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