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 --- .../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 ++++++++++ 9 files changed, 1938 insertions(+) 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/controller/visitor') diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php new file mode 100644 index 00000000..6ff769fc --- /dev/null +++ b/tests/front/controller/visitor/DailyControllerTest.php @@ -0,0 +1,497 @@ +createContainer(); + + $this->controller = new DailyController($this->container); + DailyController::$DAILY_RSS_NB_DAYS = 2; + } + + public function testValidIndexControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $currentDay = new \DateTimeImmutable('2020-05-13'); + + $request = $this->createMock(Request::class); + $request->method('getQueryParam')->willReturn($currentDay->format('Ymd')); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function () use ($currentDay): array { + return [ + '20200510', + $currentDay->format('Ymd'), + '20200516', + ]; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return [ + (new Bookmark()) + ->setId(1) + ->setUrl('http://url.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + (new Bookmark()) + ->setId(2) + ->setUrl('http://url2.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + (new Bookmark()) + ->setId(3) + ->setUrl('http://url3.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + ]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { + static::assertSame('render_daily', $hook); + + static::assertArrayHasKey('linksToDisplay', $data); + static::assertCount(3, $data['linksToDisplay']); + static::assertSame(1, $data['linksToDisplay'][0]['id']); + static::assertSame($currentDay->getTimestamp(), $data['day']); + static::assertSame('20200510', $data['previousday']); + static::assertSame('20200516', $data['nextday']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertSame( + 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', + $assignedVariables['pagetitle'] + ); + static::assertEquals($currentDay, $assignedVariables['dayDate']); + static::assertEquals($currentDay->getTimestamp(), $assignedVariables['day']); + static::assertCount(3, $assignedVariables['linksToDisplay']); + + $link = $assignedVariables['linksToDisplay'][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['linksToDisplay'][1]; + + static::assertSame(2, $link['id']); + static::assertSame('http://url2.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['linksToDisplay'][2]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + static::assertCount(3, $assignedVariables['cols']); + static::assertCount(1, $assignedVariables['cols'][0]); + static::assertCount(1, $assignedVariables['cols'][1]); + static::assertCount(1, $assignedVariables['cols'][2]); + + $link = $assignedVariables['cols'][0][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['cols'][1][0]; + + static::assertSame(2, $link['id']); + static::assertSame('http://url2.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + + $link = $assignedVariables['cols'][2][0]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertNotEmpty($link['title']); + static::assertNotEmpty($link['description']); + static::assertNotEmpty($link['formatedDescription']); + } + + /** + * Daily page - test that everything goes fine with no future or past bookmarks + */ + public function testValidIndexControllerInvokeNoFutureOrPast(): void + { + $this->createValidContainerMockSet(); + + $currentDay = new \DateTimeImmutable('2020-05-13'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function () use ($currentDay): array { + return [ + $currentDay->format($currentDay->format('Ymd')), + ]; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return [ + (new Bookmark()) + ->setId(1) + ->setUrl('http://url.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(500)) + , + ]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param) use ($currentDay): array { + static::assertSame('render_daily', $hook); + + static::assertArrayHasKey('linksToDisplay', $data); + static::assertCount(1, $data['linksToDisplay']); + static::assertSame(1, $data['linksToDisplay'][0]['id']); + static::assertSame($currentDay->getTimestamp(), $data['day']); + static::assertEmpty($data['previousday']); + static::assertEmpty($data['nextday']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertSame( + 'Daily - '. format_date($currentDay, false, true) .' - Shaarli', + $assignedVariables['pagetitle'] + ); + static::assertCount(1, $assignedVariables['linksToDisplay']); + + $link = $assignedVariables['linksToDisplay'][0]; + static::assertSame(1, $link['id']); + } + + /** + * Daily page - test that height adjustment in columns is working + */ + public function testValidIndexControllerInvokeHeightAdjustment(): void + { + $this->createValidContainerMockSet(); + + $currentDay = new \DateTimeImmutable('2020-05-13'); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function () use ($currentDay): array { + return [ + $currentDay->format($currentDay->format('Ymd')), + ]; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return [ + (new Bookmark())->setId(1)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark()) + ->setId(2) + ->setUrl('http://url.tld') + ->setTitle(static::generateContent(50)) + ->setDescription(static::generateContent(5000)) + , + (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(5)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(6)->setUrl('http://url.tld')->setTitle('title'), + (new Bookmark())->setId(7)->setUrl('http://url.tld')->setTitle('title'), + ]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertCount(7, $assignedVariables['linksToDisplay']); + + $columnIds = function (array $column): array { + return array_map(function (array $item): int { return $item['id']; }, $column); + }; + + static::assertSame([1, 4, 6], $columnIds($assignedVariables['cols'][0])); + static::assertSame([2], $columnIds($assignedVariables['cols'][1])); + static::assertSame([3, 5, 7], $columnIds($assignedVariables['cols'][2])); + } + + /** + * Daily page - no bookmark + */ + public function testValidIndexControllerInvokeNoBookmark(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('days') + ->willReturnCallback(function (): array { + return []; + }) + ; + $this->container->bookmarkService + ->expects(static::once()) + ->method('filterDay') + ->willReturnCallback(function (): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + return $data; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('daily', (string) $result->getBody()); + static::assertCount(0, $assignedVariables['linksToDisplay']); + static::assertSame('Today', $assignedVariables['dayDesc']); + static::assertEquals((new \DateTime())->setTime(0, 0)->getTimestamp(), $assignedVariables['day']); + static::assertEquals((new \DateTime())->setTime(0, 0), $assignedVariables['dayDate']); + } + + /** + * Daily RSS - default behaviour + */ + public function testValidRssControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $dates = [ + new \DateTimeImmutable('2020-05-17'), + new \DateTimeImmutable('2020-05-15'), + new \DateTimeImmutable('2020-05-13'), + ]; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ + (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), + (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), + (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), + (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'), + ]); + + $this->container->pageCacheManager + ->expects(static::once()) + ->method('getCachePage') + ->willReturnCallback(function (): CachedPage { + $cachedPage = $this->createMock(CachedPage::class); + $cachedPage->expects(static::once())->method('cache')->with('dailyrss'); + + return $cachedPage; + } + ); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('dailyrss', (string) $result->getBody()); + static::assertSame('Shaarli', $assignedVariables['title']); + static::assertSame('http://shaarli', $assignedVariables['index_url']); + static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); + static::assertFalse($assignedVariables['hide_timestamps']); + static::assertCount(2, $assignedVariables['days']); + + $day = $assignedVariables['days'][$dates[0]->format('Ymd')]; + + static::assertEquals($dates[0], $day['date']); + static::assertSame($dates[0]->format(\DateTime::RSS), $day['date_rss']); + static::assertSame(format_date($dates[0], false), $day['date_human']); + static::assertSame('http://shaarli/daily?day='. $dates[0]->format('Ymd'), $day['absolute_url']); + static::assertCount(1, $day['links']); + static::assertSame(1, $day['links'][0]['id']); + static::assertSame('http://domain.tld/1', $day['links'][0]['url']); + static::assertEquals($dates[0], $day['links'][0]['created']); + + $day = $assignedVariables['days'][$dates[1]->format('Ymd')]; + + static::assertEquals($dates[1], $day['date']); + static::assertSame($dates[1]->format(\DateTime::RSS), $day['date_rss']); + static::assertSame(format_date($dates[1], false), $day['date_human']); + static::assertSame('http://shaarli/daily?day='. $dates[1]->format('Ymd'), $day['absolute_url']); + static::assertCount(2, $day['links']); + + static::assertSame(2, $day['links'][0]['id']); + static::assertSame('http://domain.tld/2', $day['links'][0]['url']); + static::assertEquals($dates[1], $day['links'][0]['created']); + static::assertSame(3, $day['links'][1]['id']); + static::assertSame('http://domain.tld/3', $day['links'][1]['url']); + static::assertEquals($dates[1], $day['links'][1]['created']); + } + + /** + * Daily RSS - trigger cache rendering + */ + public function testValidRssControllerInvokeTriggerCache(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->pageCacheManager->method('getCachePage')->willReturnCallback(function (): CachedPage { + $cachedPage = $this->createMock(CachedPage::class); + $cachedPage->method('cachedVersion')->willReturn('this is cache!'); + + return $cachedPage; + }); + + $this->container->bookmarkService->expects(static::never())->method('search'); + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('this is cache!', (string) $result->getBody()); + } + + /** + * Daily RSS - No bookmark + */ + public function testValidRssControllerInvokeNoBookmark(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([]); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('dailyrss', (string) $result->getBody()); + static::assertSame('Shaarli', $assignedVariables['title']); + static::assertSame('http://shaarli', $assignedVariables['index_url']); + static::assertSame('http://shaarli/daily-rss', $assignedVariables['page_url']); + static::assertFalse($assignedVariables['hide_timestamps']); + static::assertCount(0, $assignedVariables['days']); + } + + protected static function generateContent(int $length): string + { + // bin2hex(random_bytes) generates string twice as long as given parameter + $length = (int) ceil($length / 2); + return bin2hex(random_bytes($length)); + } +} diff --git a/tests/front/controller/visitor/FeedControllerTest.php b/tests/front/controller/visitor/FeedControllerTest.php new file mode 100644 index 00000000..fd4679ea --- /dev/null +++ b/tests/front/controller/visitor/FeedControllerTest.php @@ -0,0 +1,151 @@ +createContainer(); + + $this->container->feedBuilder = $this->createMock(FeedBuilder::class); + + $this->controller = new FeedController($this->container); + } + + /** + * Feed Controller - RSS default behaviour + */ + public function testDefaultRssController(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->feedBuilder->expects(static::once())->method('setLocale'); + $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); + $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): void { + static::assertSame('render_feed', $hook); + static::assertSame('data', $data['content']); + + static::assertArrayHasKey('loggedin', $param); + static::assertSame('rss', $param['target']); + }) + ; + + $result = $this->controller->rss($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/rss', $result->getHeader('Content-Type')[0]); + static::assertSame('feed.rss', (string) $result->getBody()); + static::assertSame('data', $assignedVariables['content']); + } + + /** + * Feed Controller - ATOM default behaviour + */ + public function testDefaultAtomController(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->feedBuilder->expects(static::once())->method('setLocale'); + $this->container->feedBuilder->expects(static::once())->method('setHideDates')->with(false); + $this->container->feedBuilder->expects(static::once())->method('setUsePermalinks')->with(true); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->feedBuilder->method('buildData')->willReturn(['content' => 'data']); + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): void { + static::assertSame('render_feed', $hook); + static::assertSame('data', $data['content']); + + static::assertArrayHasKey('loggedin', $param); + static::assertSame('atom', $param['target']); + }) + ; + + $result = $this->controller->atom($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); + static::assertSame('feed.atom', (string) $result->getBody()); + static::assertSame('data', $assignedVariables['content']); + } + + /** + * Feed Controller - ATOM with parameters + */ + public function testAtomControllerWithParameters(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->method('getParams')->willReturn(['parameter' => 'value']); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->feedBuilder + ->method('buildData') + ->with('atom', ['parameter' => 'value']) + ->willReturn(['content' => 'data']) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): void { + static::assertSame('render_feed', $hook); + static::assertSame('data', $data['content']); + + static::assertArrayHasKey('loggedin', $param); + static::assertSame('atom', $param['target']); + }) + ; + + $result = $this->controller->atom($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString('application/atom', $result->getHeader('Content-Type')[0]); + static::assertSame('feed.atom', (string) $result->getBody()); + static::assertSame('data', $assignedVariables['content']); + } +} diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php new file mode 100644 index 00000000..bc3266b5 --- /dev/null +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php @@ -0,0 +1,114 @@ +container = $this->createMock(ShaarliTestContainer::class); + } + + /** + * Initialize container's services used by tests + */ + protected function createValidContainerMockSet(): void + { + $this->container->loginManager = $this->createMock(LoginManager::class); + + // Config + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + return $default; + }); + + // PageBuilder + $this->container->pageBuilder = $this->createMock(PageBuilder::class); + $this->container->pageBuilder + ->method('render') + ->willReturnCallback(function (string $template): string { + return $template; + }) + ; + + // Plugin Manager + $this->container->pluginManager = $this->createMock(PluginManager::class); + + // BookmarkService + $this->container->bookmarkService = $this->createMock(BookmarkServiceInterface::class); + + // Formatter + $this->container->formatterFactory = $this->createMock(FormatterFactory::class); + $this->container->formatterFactory + ->method('getFormatter') + ->willReturnCallback(function (): BookmarkFormatter { + return new BookmarkRawFormatter($this->container->conf, true); + }) + ; + + // CacheManager + $this->container->pageCacheManager = $this->createMock(PageCacheManager::class); + + // SessionManager + $this->container->sessionManager = $this->createMock(SessionManager::class); + + // $_SERVER + $this->container->environment = [ + 'SERVER_NAME' => 'shaarli', + 'SERVER_PORT' => '80', + 'REQUEST_URI' => '/daily-rss', + ]; + } + + /** + * Pass a reference of an array which will be populated by `pageBuilder->assign` calls during execution. + * + * @param mixed $variables Array reference to populate. + */ + protected function assignTemplateVars(array &$variables): void + { + $this->container->pageBuilder + ->expects(static::atLeastOnce()) + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$variables) { + $variables[$key] = $value; + + return $this; + }) + ; + } + + /** + * Force to be used in PHPUnit context. + */ + protected abstract function createMock($originalClassName): MockObject; +} diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php new file mode 100644 index 00000000..9d223316 --- /dev/null +++ b/tests/front/controller/visitor/LoginControllerTest.php @@ -0,0 +1,144 @@ +createContainer(); + + $this->controller = new LoginController($this->container); + } + + public function testValidControllerInvoke(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); + $response = new Response(); + + $assignedVariables = []; + $this->container->pageBuilder + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { + $assignedVariables[$key] = $value; + + return $this; + }) + ; + + $this->container->loginManager->method('canLogin')->willReturn(true); + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(200, $result->getStatusCode()); + static::assertSame('loginform', (string) $result->getBody()); + + static::assertSame('> referer', $assignedVariables['returnurl']); + static::assertSame(true, $assignedVariables['remember_user_default']); + static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); + } + + public function testValidControllerInvokeWithUserName(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); + $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); + $response = new Response(); + + $assignedVariables = []; + $this->container->pageBuilder + ->method('assign') + ->willReturnCallback(function ($key, $value) use (&$assignedVariables) { + $assignedVariables[$key] = $value; + + return $this; + }) + ; + + $this->container->loginManager->expects(static::once())->method('canLogin')->willReturn(true); + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(200, $result->getStatusCode()); + static::assertSame('loginform', (string) $result->getBody()); + + static::assertSame('myUser>', $assignedVariables['username']); + static::assertSame('> referer', $assignedVariables['returnurl']); + static::assertSame(true, $assignedVariables['remember_user_default']); + static::assertSame('Login - Shaarli', $assignedVariables['pagetitle']); + } + + public function testLoginControllerWhileLoggedIn(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->loginManager->expects(static::once())->method('isLoggedIn')->willReturn(true); + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('Location')); + } + + public function testLoginControllerOpenShaarli(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $conf = $this->createMock(ConfigManager::class); + $conf->method('get')->willReturnCallback(function (string $parameter, $default) { + if ($parameter === 'security.open_shaarli') { + return true; + } + return $default; + }); + $this->container->conf = $conf; + + $result = $this->controller->index($request, $response); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('Location')); + } + + public function testLoginControllerWhileBanned(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->loginManager->method('isLoggedIn')->willReturn(false); + $this->container->loginManager->method('canLogin')->willReturn(false); + + $this->expectException(LoginBannedException::class); + + $this->controller->index($request, $response); + } +} diff --git a/tests/front/controller/visitor/OpenSearchControllerTest.php b/tests/front/controller/visitor/OpenSearchControllerTest.php new file mode 100644 index 00000000..52475318 --- /dev/null +++ b/tests/front/controller/visitor/OpenSearchControllerTest.php @@ -0,0 +1,46 @@ +createContainer(); + + $this->controller = new OpenSearchController($this->container); + } + + public function testOpenSearchController(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertStringContainsString( + 'application/opensearchdescription+xml', + $result->getHeader('Content-Type')[0] + ); + static::assertSame('opensearch', (string) $result->getBody()); + static::assertSame('http://shaarli', $assignedVariables['serverurl']); + } +} diff --git a/tests/front/controller/visitor/PictureWallControllerTest.php b/tests/front/controller/visitor/PictureWallControllerTest.php new file mode 100644 index 00000000..7ac842cb --- /dev/null +++ b/tests/front/controller/visitor/PictureWallControllerTest.php @@ -0,0 +1,125 @@ +createContainer(); + + $this->controller = new PictureWallController($this->container); + } + + public function testValidControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request->expects(static::once())->method('getQueryParams')->willReturn([]); + $response = new Response(); + + // ConfigManager: thumbnails are enabled + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + if ($parameter === 'thumbnails.mode') { + return Thumbnailer::MODE_COMMON; + } + + return $default; + }); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + // Links dataset: 2 links with thumbnails + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + // Visibility is set through the container, not the call + static::assertNull($visibility); + + // No query parameters + if (count($parameters) === 0) { + return [ + (new Bookmark())->setId(1)->setUrl('http://url.tld')->setThumbnail('thumb1'), + (new Bookmark())->setId(2)->setUrl('http://url2.tld'), + (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setThumbnail('thumb2'), + ]; + } + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_picwall', $hook); + static::assertArrayHasKey('linksToDisplay', $data); + static::assertCount(2, $data['linksToDisplay']); + static::assertSame(1, $data['linksToDisplay'][0]['id']); + static::assertSame(3, $data['linksToDisplay'][1]['id']); + static::assertArrayHasKey('loggedin', $param); + + return $data; + }); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('picwall', (string) $result->getBody()); + static::assertSame('Picture wall - Shaarli', $assignedVariables['pagetitle']); + static::assertCount(2, $assignedVariables['linksToDisplay']); + + $link = $assignedVariables['linksToDisplay'][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url.tld', $link['url']); + static::assertSame('thumb1', $link['thumbnail']); + + $link = $assignedVariables['linksToDisplay'][1]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertSame('thumb2', $link['thumbnail']); + } + + public function testControllerWithThumbnailsDisabled(): void + { + $this->expectException(ThumbnailsDisabledException::class); + + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // ConfigManager: thumbnails are disabled + $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { + if ($parameter === 'thumbnails.mode') { + return Thumbnailer::MODE_NONE; + } + + return $default; + }); + + $this->controller->index($request, $response); + } +} diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php new file mode 100644 index 00000000..e2e88da3 --- /dev/null +++ b/tests/front/controller/visitor/ShaarliPublicControllerTest.php @@ -0,0 +1,239 @@ +createContainer(); + + $this->controller = new class($this->container) extends ShaarliVisitorController + { + public function assignView(string $key, $value): ShaarliVisitorController + { + return parent::assignView($key, $value); + } + + public function render(string $template): string + { + return parent::render($template); + } + + public function redirectFromReferer( + Request $request, + Response $response, + array $loopTerms = [], + array $clearParams = [] + ): Response { + return parent::redirectFromReferer($request, $response, $loopTerms, $clearParams); + } + }; + $this->assignedValues = []; + + $this->request = $this->createMock(Request::class); + $this->request->method('getUri')->willReturnCallback(function (): Uri { + $uri = $this->createMock(Uri::class); + $uri->method('getBasePath')->willReturn('/subfolder'); + + return $uri; + }); + } + + public function testAssignView(): void + { + $this->createValidContainerMockSet(); + + $this->assignTemplateVars($this->assignedValues); + + $self = $this->controller->assignView('variableName', 'variableValue'); + + static::assertInstanceOf(ShaarliVisitorController::class, $self); + static::assertSame('variableValue', $this->assignedValues['variableName']); + } + + public function testRender(): void + { + $this->createValidContainerMockSet(); + + $this->assignTemplateVars($this->assignedValues); + + $this->container->bookmarkService + ->method('count') + ->willReturnCallback(function (string $visibility): int { + return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; + }) + ; + + $this->container->pluginManager + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array &$data, array $params): array { + return $data[$hook] = $params; + }); + $this->container->pluginManager->method('getErrors')->willReturn(['error']); + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $render = $this->controller->render('templateName'); + + static::assertSame('templateName', $render); + + static::assertSame(10, $this->assignedValues['linkcount']); + static::assertSame(5, $this->assignedValues['privateLinkcount']); + static::assertSame(['error'], $this->assignedValues['plugin_errors']); + + static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); + static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); + static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); + static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); + } + + /** + * Test redirectFromReferer() - Default behaviour + */ + public function testRedirectFromRefererDefault(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term not matched in the referer + */ + public function testRedirectFromRefererWithUnmatchedLoopTerm(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInPath(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'controller']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'other']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query value + * -> we do not block redirection for query parameter values. + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'param']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its domain name + * -> we do not block redirection for shaarli's hosts + */ + public function testRedirectFromRefererWithLoopTermInDomain(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['shaarli']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param + * -> the param should be cleared before checking if it matches the redir loop terms + */ + public function testRedirectFromRefererWithMatchingClearedParam(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['query'], ['query']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location')); + } +} diff --git a/tests/front/controller/visitor/TagCloudControllerTest.php b/tests/front/controller/visitor/TagCloudControllerTest.php new file mode 100644 index 00000000..e636d496 --- /dev/null +++ b/tests/front/controller/visitor/TagCloudControllerTest.php @@ -0,0 +1,381 @@ +createContainer(); + + $this->controller = new TagCloudController($this->container); + } + + /** + * Tag Cloud - default parameters + */ + public function testValidCloudControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $allTags = [ + 'ghi' => 1, + 'abc' => 3, + 'def' => 12, + ]; + $expectedOrder = ['abc', 'def', 'ghi']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function () use ($allTags): array { + return $allTags; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(3, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->cloud($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(3, $assignedVariables['tags']); + static::assertSame($expectedOrder, array_keys($assignedVariables['tags'])); + + foreach ($allTags as $tag => $count) { + static::assertArrayHasKey($tag, $assignedVariables['tags']); + static::assertSame($count, $assignedVariables['tags'][$tag]['count']); + static::assertGreaterThan(0, $assignedVariables['tags'][$tag]['size']); + static::assertLessThan(5, $assignedVariables['tags'][$tag]['size']); + } + } + + /** + * Tag Cloud - Additional parameters: + * - logged in + * - visibility private + * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) + */ + public function testValidCloudControllerInvokeWithParameters(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request + ->method('getQueryParam') + ->with() + ->willReturnCallback(function (string $key): ?string { + if ('searchtags' === $key) { + return 'ghi def'; + } + + return null; + }) + ; + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->loginManager->method('isLoggedin')->willReturn(true); + $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) + ->willReturnCallback(function (): array { + return ['abc' => 3]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('ghi def', $data['search_tags']); + static::assertCount(1, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->cloud($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('ghi def - Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('ghi def', $assignedVariables['search_tags']); + static::assertCount(1, $assignedVariables['tags']); + + static::assertArrayHasKey('abc', $assignedVariables['tags']); + static::assertSame(3, $assignedVariables['tags']['abc']['count']); + static::assertGreaterThan(0, $assignedVariables['tags']['abc']['size']); + static::assertLessThan(5, $assignedVariables['tags']['abc']['size']); + } + + /** + * Tag Cloud - empty + */ + public function testEmptyCloud(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_tagcloud', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(0, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->cloud($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.cloud', (string) $result->getBody()); + static::assertSame('Tag cloud - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(0, $assignedVariables['tags']); + } + + /** + * Tag List - Default sort is by usage DESC + */ + public function testValidListControllerInvokeDefault(): void + { + $this->createValidContainerMockSet(); + + $allTags = [ + 'def' => 12, + 'abc' => 3, + 'ghi' => 1, + ]; + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function () use ($allTags): array { + return $allTags; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_taglist', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(3, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->list($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.list', (string) $result->getBody()); + static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(3, $assignedVariables['tags']); + + foreach ($allTags as $tag => $count) { + static::assertSame($count, $assignedVariables['tags'][$tag]); + } + } + + /** + * Tag List - Additional parameters: + * - logged in + * - visibility private + * - search tags: `ghi` and `def` (note that filtered tags are not displayed anymore) + * - sort alphabetically + */ + public function testValidListControllerInvokeWithParameters(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $request + ->method('getQueryParam') + ->with() + ->willReturnCallback(function (string $key): ?string { + if ('searchtags' === $key) { + return 'ghi def'; + } elseif ('sort' === $key) { + return 'alpha'; + } + + return null; + }) + ; + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->loginManager->method('isLoggedin')->willReturn(true); + $this->container->sessionManager->expects(static::once())->method('getSessionParameter')->willReturn('private'); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with(['ghi', 'def'], BookmarkFilter::$PRIVATE) + ->willReturnCallback(function (): array { + return ['abc' => 3]; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_taglist', $hook); + static::assertSame('ghi def', $data['search_tags']); + static::assertCount(1, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->list($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.list', (string) $result->getBody()); + static::assertSame('ghi def - Tag list - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('ghi def', $assignedVariables['search_tags']); + static::assertCount(1, $assignedVariables['tags']); + static::assertSame(3, $assignedVariables['tags']['abc']); + } + + /** + * Tag List - empty + */ + public function testEmptyList(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + // Save RainTPL assigned variables + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('bookmarksCountPerTag') + ->with([], null) + ->willReturnCallback(function (array $parameters, ?string $visibility): array { + return []; + }) + ; + + // Make sure that PluginManager hook is triggered + $this->container->pluginManager + ->expects(static::at(0)) + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array $data, array $param): array { + static::assertSame('render_taglist', $hook); + static::assertSame('', $data['search_tags']); + static::assertCount(0, $data['tags']); + + static::assertArrayHasKey('loggedin', $param); + + return $data; + }) + ; + + $result = $this->controller->list($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('tag.list', (string) $result->getBody()); + static::assertSame('Tag list - Shaarli', $assignedVariables['pagetitle']); + + static::assertSame('', $assignedVariables['search_tags']); + static::assertCount(0, $assignedVariables['tags']); + } +} diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php new file mode 100644 index 00000000..9a2b1f71 --- /dev/null +++ b/tests/front/controller/visitor/TagControllerTest.php @@ -0,0 +1,241 @@ +createContainer(); + + $this->controller = new TagController($this->container); + } + + public function testAddTagWithReferer(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); + } + + public function testAddTagWithRefererAndExistingSearch(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); + } + + public function testAddTagWithoutRefererAndExistingSearch(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./?searchtags=abc'], $result->getHeader('location')); + } + + public function testAddTagRemoveLegacyQueryParam(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); + } + + public function testAddTagResetPagination(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def+abc'], $result->getHeader('location')); + } + + public function testAddTagWithRefererAndEmptySearch(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['newTag' => 'abc']; + + $result = $this->controller->addTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=abc'], $result->getHeader('location')); + } + + public function testAddTagWithoutNewTagWithReferer(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->addTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); + } + + public function testAddTagWithoutNewTagWithoutReferer(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->addTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutMatchingTag(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['tag' => 'abc']; + + $result = $this->controller->removeTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtags=def'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutTagsearch(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['tag' => 'abc']; + + $result = $this->controller->removeTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutReferer(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $tags = ['tag' => 'abc']; + + $result = $this->controller->removeTag($request, $response, $tags); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutTag(): void + { + $this->createValidContainerMockSet(); + + $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc']; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->removeTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/controller/?searchtag=abc'], $result->getHeader('location')); + } + + public function testRemoveTagWithoutTagWithoutReferer(): void + { + $this->createValidContainerMockSet(); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->removeTag($request, $response, []); + + static::assertInstanceOf(Response::class, $result); + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['./'], $result->getHeader('location')); + } +} -- cgit v1.2.3 From ef00f9d2033f6de11e71bf3a909399cae6f73a9f Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 27 May 2020 13:35:48 +0200 Subject: Process password change controller through Slim --- .../controller/visitor/DailyControllerTest.php | 14 ------------ .../controller/visitor/FeedControllerTest.php | 6 ----- .../visitor/FrontControllerMockHelper.php | 8 +------ .../controller/visitor/LoginControllerTest.php | 10 --------- .../visitor/OpenSearchControllerTest.php | 2 -- .../visitor/PictureWallControllerTest.php | 4 ---- .../visitor/ShaarliPublicControllerTest.php | 18 --------------- .../controller/visitor/TagCloudControllerTest.php | 12 ---------- .../front/controller/visitor/TagControllerTest.php | 26 ---------------------- 9 files changed, 1 insertion(+), 99 deletions(-) (limited to 'tests/front/controller/visitor') diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php index 6ff769fc..872420fd 100644 --- a/tests/front/controller/visitor/DailyControllerTest.php +++ b/tests/front/controller/visitor/DailyControllerTest.php @@ -27,8 +27,6 @@ class DailyControllerTest extends TestCase public function testValidIndexControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $currentDay = new \DateTimeImmutable('2020-05-13'); $request = $this->createMock(Request::class); @@ -169,8 +167,6 @@ class DailyControllerTest extends TestCase */ public function testValidIndexControllerInvokeNoFutureOrPast(): void { - $this->createValidContainerMockSet(); - $currentDay = new \DateTimeImmutable('2020-05-13'); $request = $this->createMock(Request::class); @@ -243,8 +239,6 @@ class DailyControllerTest extends TestCase */ public function testValidIndexControllerInvokeHeightAdjustment(): void { - $this->createValidContainerMockSet(); - $currentDay = new \DateTimeImmutable('2020-05-13'); $request = $this->createMock(Request::class); @@ -314,8 +308,6 @@ class DailyControllerTest extends TestCase */ public function testValidIndexControllerInvokeNoBookmark(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -363,8 +355,6 @@ class DailyControllerTest extends TestCase */ public function testValidRssControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $dates = [ new \DateTimeImmutable('2020-05-17'), new \DateTimeImmutable('2020-05-15'), @@ -439,8 +429,6 @@ class DailyControllerTest extends TestCase */ public function testValidRssControllerInvokeTriggerCache(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -465,8 +453,6 @@ class DailyControllerTest extends TestCase */ public function testValidRssControllerInvokeNoBookmark(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/FeedControllerTest.php b/tests/front/controller/visitor/FeedControllerTest.php index fd4679ea..fb417e2a 100644 --- a/tests/front/controller/visitor/FeedControllerTest.php +++ b/tests/front/controller/visitor/FeedControllerTest.php @@ -30,8 +30,6 @@ class FeedControllerTest extends TestCase */ public function testDefaultRssController(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -71,8 +69,6 @@ class FeedControllerTest extends TestCase */ public function testDefaultAtomController(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -112,8 +108,6 @@ class FeedControllerTest extends TestCase */ public function testAtomControllerWithParameters(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request->method('getParams')->willReturn(['parameter' => 'value']); $response = new Response(); diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php index bc3266b5..d16b6949 100644 --- a/tests/front/controller/visitor/FrontControllerMockHelper.php +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php @@ -31,18 +31,12 @@ trait FrontControllerMockHelper protected $container; /** - * Mock the container instance + * Mock the container instance and initialize container's services used by tests */ protected function createContainer(): void { $this->container = $this->createMock(ShaarliTestContainer::class); - } - /** - * Initialize container's services used by tests - */ - protected function createValidContainerMockSet(): void - { $this->container->loginManager = $this->createMock(LoginManager::class); // Config diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php index 9d223316..faa8ac71 100644 --- a/tests/front/controller/visitor/LoginControllerTest.php +++ b/tests/front/controller/visitor/LoginControllerTest.php @@ -26,8 +26,6 @@ class LoginControllerTest extends TestCase public function testValidControllerInvoke(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); $response = new Response(); @@ -57,8 +55,6 @@ class LoginControllerTest extends TestCase public function testValidControllerInvokeWithUserName(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request->expects(static::once())->method('getServerParam')->willReturn('> referer'); $request->expects(static::exactly(2))->method('getParam')->willReturn('myUser>'); @@ -90,8 +86,6 @@ class LoginControllerTest extends TestCase public function testLoginControllerWhileLoggedIn(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -106,8 +100,6 @@ class LoginControllerTest extends TestCase public function testLoginControllerOpenShaarli(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -129,8 +121,6 @@ class LoginControllerTest extends TestCase public function testLoginControllerWhileBanned(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/OpenSearchControllerTest.php b/tests/front/controller/visitor/OpenSearchControllerTest.php index 52475318..5f9f5b12 100644 --- a/tests/front/controller/visitor/OpenSearchControllerTest.php +++ b/tests/front/controller/visitor/OpenSearchControllerTest.php @@ -24,8 +24,6 @@ class OpenSearchControllerTest extends TestCase public function testOpenSearchController(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/PictureWallControllerTest.php b/tests/front/controller/visitor/PictureWallControllerTest.php index 7ac842cb..3dc3f292 100644 --- a/tests/front/controller/visitor/PictureWallControllerTest.php +++ b/tests/front/controller/visitor/PictureWallControllerTest.php @@ -28,8 +28,6 @@ class PictureWallControllerTest extends TestCase public function testValidControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request->expects(static::once())->method('getQueryParams')->willReturn([]); $response = new Response(); @@ -106,8 +104,6 @@ class PictureWallControllerTest extends TestCase { $this->expectException(ThumbnailsDisabledException::class); - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php index e2e88da3..1f7d57ad 100644 --- a/tests/front/controller/visitor/ShaarliPublicControllerTest.php +++ b/tests/front/controller/visitor/ShaarliPublicControllerTest.php @@ -67,8 +67,6 @@ class ShaarliControllerTest extends TestCase public function testAssignView(): void { - $this->createValidContainerMockSet(); - $this->assignTemplateVars($this->assignedValues); $self = $this->controller->assignView('variableName', 'variableValue'); @@ -79,8 +77,6 @@ class ShaarliControllerTest extends TestCase public function testRender(): void { - $this->createValidContainerMockSet(); - $this->assignTemplateVars($this->assignedValues); $this->container->bookmarkService @@ -120,8 +116,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererDefault(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -137,8 +131,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithUnmatchedLoopTerm(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -154,8 +146,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithMatchingLoopTermInPath(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -171,8 +161,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -189,8 +177,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -207,8 +193,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithLoopTermInDomain(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); @@ -225,8 +209,6 @@ class ShaarliControllerTest extends TestCase */ public function testRedirectFromRefererWithMatchingClearedParam(): void { - $this->createValidContainerMockSet(); - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; $response = new Response(); diff --git a/tests/front/controller/visitor/TagCloudControllerTest.php b/tests/front/controller/visitor/TagCloudControllerTest.php index e636d496..9a6a4bc0 100644 --- a/tests/front/controller/visitor/TagCloudControllerTest.php +++ b/tests/front/controller/visitor/TagCloudControllerTest.php @@ -28,8 +28,6 @@ class TagCloudControllerTest extends TestCase */ public function testValidCloudControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $allTags = [ 'ghi' => 1, 'abc' => 3, @@ -94,8 +92,6 @@ class TagCloudControllerTest extends TestCase */ public function testValidCloudControllerInvokeWithParameters(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request ->method('getQueryParam') @@ -161,8 +157,6 @@ class TagCloudControllerTest extends TestCase */ public function testEmptyCloud(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -209,8 +203,6 @@ class TagCloudControllerTest extends TestCase */ public function testValidListControllerInvokeDefault(): void { - $this->createValidContainerMockSet(); - $allTags = [ 'def' => 12, 'abc' => 3, @@ -271,8 +263,6 @@ class TagCloudControllerTest extends TestCase */ public function testValidListControllerInvokeWithParameters(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $request ->method('getQueryParam') @@ -336,8 +326,6 @@ class TagCloudControllerTest extends TestCase */ public function testEmptyList(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php index 9a2b1f71..1242a2e9 100644 --- a/tests/front/controller/visitor/TagControllerTest.php +++ b/tests/front/controller/visitor/TagControllerTest.php @@ -23,8 +23,6 @@ class TagControllerTest extends TestCase public function testAddTagWithReferer(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; $request = $this->createMock(Request::class); @@ -41,8 +39,6 @@ class TagControllerTest extends TestCase public function testAddTagWithRefererAndExistingSearch(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; $request = $this->createMock(Request::class); @@ -59,8 +55,6 @@ class TagControllerTest extends TestCase public function testAddTagWithoutRefererAndExistingSearch(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -75,8 +69,6 @@ class TagControllerTest extends TestCase public function testAddTagRemoveLegacyQueryParam(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&addtag=abc']; $request = $this->createMock(Request::class); @@ -93,8 +85,6 @@ class TagControllerTest extends TestCase public function testAddTagResetPagination(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def&page=12']; $request = $this->createMock(Request::class); @@ -111,8 +101,6 @@ class TagControllerTest extends TestCase public function testAddTagWithRefererAndEmptySearch(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=']; $request = $this->createMock(Request::class); @@ -129,8 +117,6 @@ class TagControllerTest extends TestCase public function testAddTagWithoutNewTagWithReferer(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; $request = $this->createMock(Request::class); @@ -145,8 +131,6 @@ class TagControllerTest extends TestCase public function testAddTagWithoutNewTagWithoutReferer(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -159,8 +143,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutMatchingTag(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtags=def']; $request = $this->createMock(Request::class); @@ -177,8 +159,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutTagsearch(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/']; $request = $this->createMock(Request::class); @@ -195,8 +175,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutReferer(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); @@ -211,8 +189,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutTag(): void { - $this->createValidContainerMockSet(); - $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/controller/?searchtag=abc']; $request = $this->createMock(Request::class); @@ -227,8 +203,6 @@ class TagControllerTest extends TestCase public function testRemoveTagWithoutTagWithoutReferer(): void { - $this->createValidContainerMockSet(); - $request = $this->createMock(Request::class); $response = new Response(); -- cgit v1.2.3 From fdedbfd4a7fb547da0e0ce65c6180f74aad90691 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Wed, 27 May 2020 14:13:49 +0200 Subject: Test ShaarliAdminController --- tests/front/controller/visitor/ShaarliPublicControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests/front/controller/visitor') diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php index 1f7d57ad..899b280b 100644 --- a/tests/front/controller/visitor/ShaarliPublicControllerTest.php +++ b/tests/front/controller/visitor/ShaarliPublicControllerTest.php @@ -16,7 +16,7 @@ use Slim\Http\Uri; * This class is used to test default behavior of ShaarliController abstract class. * It uses a dummy non abstract controller. */ -class ShaarliControllerTest extends TestCase +class ShaarliPublicControllerTest extends TestCase { use FrontControllerMockHelper; -- cgit v1.2.3 From 66063ed1a18d739b1a60bfb163d8656417a4c529 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 30 May 2020 14:00:06 +0200 Subject: Process configure page through Slim controller --- .../controller/visitor/DailyControllerTest.php | 27 ++++++++-------------- .../visitor/FrontControllerMockHelper.php | 10 +++++++- 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'tests/front/controller/visitor') diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php index 872420fd..b802c62c 100644 --- a/tests/front/controller/visitor/DailyControllerTest.php +++ b/tests/front/controller/visitor/DailyControllerTest.php @@ -57,20 +57,20 @@ class DailyControllerTest extends TestCase (new Bookmark()) ->setId(1) ->setUrl('http://url.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(500)) , (new Bookmark()) ->setId(2) ->setUrl('http://url2.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(500)) , (new Bookmark()) ->setId(3) ->setUrl('http://url3.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(500)) , ]; }) @@ -194,8 +194,8 @@ class DailyControllerTest extends TestCase (new Bookmark()) ->setId(1) ->setUrl('http://url.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(500)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(500)) , ]; }) @@ -267,8 +267,8 @@ class DailyControllerTest extends TestCase (new Bookmark()) ->setId(2) ->setUrl('http://url.tld') - ->setTitle(static::generateContent(50)) - ->setDescription(static::generateContent(5000)) + ->setTitle(static::generateString(50)) + ->setDescription(static::generateString(5000)) , (new Bookmark())->setId(3)->setUrl('http://url.tld')->setTitle('title'), (new Bookmark())->setId(4)->setUrl('http://url.tld')->setTitle('title'), @@ -473,11 +473,4 @@ class DailyControllerTest extends TestCase static::assertFalse($assignedVariables['hide_timestamps']); static::assertCount(0, $assignedVariables['days']); } - - protected static function generateContent(int $length): string - { - // bin2hex(random_bytes) generates string twice as long as given parameter - $length = (int) ceil($length / 2); - return bin2hex(random_bytes($length)); - } } diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php index d16b6949..fecd0c82 100644 --- a/tests/front/controller/visitor/FrontControllerMockHelper.php +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php @@ -42,7 +42,7 @@ trait FrontControllerMockHelper // Config $this->container->conf = $this->createMock(ConfigManager::class); $this->container->conf->method('get')->willReturnCallback(function (string $parameter, $default) { - return $default; + return $default === null ? $parameter : $default; }); // PageBuilder @@ -101,6 +101,14 @@ trait FrontControllerMockHelper ; } + protected static function generateString(int $length): string + { + // bin2hex(random_bytes) generates string twice as long as given parameter + $length = (int) ceil($length / 2); + + return bin2hex(random_bytes($length)); + } + /** * Force to be used in PHPUnit context. */ -- cgit v1.2.3 From 818b3193ffabec57501e3bdfa997206e3c0671ef Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 13 Jun 2020 11:22:14 +0200 Subject: Explicitly define base and asset path in templates With the new routes, all pages are not all at the same folder level anymore (e.g. /shaare and /shaare/123), so we can't just use './' everywhere. The most consistent way to handle this is to prefix all path with the proper variable, and handle the actual path in controllers. --- .../visitor/FrontControllerMockHelper.php | 2 + .../visitor/ShaarliPublicControllerTest.php | 221 --------------------- .../visitor/ShaarliVisitorControllerTest.php | 217 ++++++++++++++++++++ 3 files changed, 219 insertions(+), 221 deletions(-) delete mode 100644 tests/front/controller/visitor/ShaarliPublicControllerTest.php create mode 100644 tests/front/controller/visitor/ShaarliVisitorControllerTest.php (limited to 'tests/front/controller/visitor') diff --git a/tests/front/controller/visitor/FrontControllerMockHelper.php b/tests/front/controller/visitor/FrontControllerMockHelper.php index fecd0c82..7f560662 100644 --- a/tests/front/controller/visitor/FrontControllerMockHelper.php +++ b/tests/front/controller/visitor/FrontControllerMockHelper.php @@ -81,6 +81,8 @@ trait FrontControllerMockHelper 'SERVER_PORT' => '80', 'REQUEST_URI' => '/daily-rss', ]; + + $this->container->basePath = '/subfolder'; } /** diff --git a/tests/front/controller/visitor/ShaarliPublicControllerTest.php b/tests/front/controller/visitor/ShaarliPublicControllerTest.php deleted file mode 100644 index 899b280b..00000000 --- a/tests/front/controller/visitor/ShaarliPublicControllerTest.php +++ /dev/null @@ -1,221 +0,0 @@ -createContainer(); - - $this->controller = new class($this->container) extends ShaarliVisitorController - { - public function assignView(string $key, $value): ShaarliVisitorController - { - return parent::assignView($key, $value); - } - - public function render(string $template): string - { - return parent::render($template); - } - - public function redirectFromReferer( - Request $request, - Response $response, - array $loopTerms = [], - array $clearParams = [] - ): Response { - return parent::redirectFromReferer($request, $response, $loopTerms, $clearParams); - } - }; - $this->assignedValues = []; - - $this->request = $this->createMock(Request::class); - $this->request->method('getUri')->willReturnCallback(function (): Uri { - $uri = $this->createMock(Uri::class); - $uri->method('getBasePath')->willReturn('/subfolder'); - - return $uri; - }); - } - - public function testAssignView(): void - { - $this->assignTemplateVars($this->assignedValues); - - $self = $this->controller->assignView('variableName', 'variableValue'); - - static::assertInstanceOf(ShaarliVisitorController::class, $self); - static::assertSame('variableValue', $this->assignedValues['variableName']); - } - - public function testRender(): void - { - $this->assignTemplateVars($this->assignedValues); - - $this->container->bookmarkService - ->method('count') - ->willReturnCallback(function (string $visibility): int { - return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; - }) - ; - - $this->container->pluginManager - ->method('executeHooks') - ->willReturnCallback(function (string $hook, array &$data, array $params): array { - return $data[$hook] = $params; - }); - $this->container->pluginManager->method('getErrors')->willReturn(['error']); - - $this->container->loginManager->method('isLoggedIn')->willReturn(true); - - $render = $this->controller->render('templateName'); - - static::assertSame('templateName', $render); - - static::assertSame(10, $this->assignedValues['linkcount']); - static::assertSame(5, $this->assignedValues['privateLinkcount']); - static::assertSame(['error'], $this->assignedValues['plugin_errors']); - - static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); - static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); - static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); - static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); - static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); - static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); - } - - /** - * Test redirectFromReferer() - Default behaviour - */ - public function testRedirectFromRefererDefault(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term not matched in the referer - */ - public function testRedirectFromRefererWithUnmatchedLoopTerm(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['nope']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default - */ - public function testRedirectFromRefererWithMatchingLoopTermInPath(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'controller']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default - */ - public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'other']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its query value - * -> we do not block redirection for query parameter values. - */ - public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'param']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching the referer in its domain name - * -> we do not block redirection for shaarli's hosts - */ - public function testRedirectFromRefererWithLoopTermInDomain(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['shaarli']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); - } - - /** - * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param - * -> the param should be cleared before checking if it matches the redir loop terms - */ - public function testRedirectFromRefererWithMatchingClearedParam(): void - { - $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; - - $response = new Response(); - - $result = $this->controller->redirectFromReferer($this->request, $response, ['query'], ['query']); - - static::assertSame(302, $result->getStatusCode()); - static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location')); - } -} diff --git a/tests/front/controller/visitor/ShaarliVisitorControllerTest.php b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php new file mode 100644 index 00000000..83d08358 --- /dev/null +++ b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php @@ -0,0 +1,217 @@ +createContainer(); + + $this->controller = new class($this->container) extends ShaarliVisitorController + { + public function assignView(string $key, $value): ShaarliVisitorController + { + return parent::assignView($key, $value); + } + + public function render(string $template): string + { + return parent::render($template); + } + + public function redirectFromReferer( + Request $request, + Response $response, + array $loopTerms = [], + array $clearParams = [], + string $anchor = null + ): Response { + return parent::redirectFromReferer($request, $response, $loopTerms, $clearParams, $anchor); + } + }; + $this->assignedValues = []; + + $this->request = $this->createMock(Request::class); + } + + public function testAssignView(): void + { + $this->assignTemplateVars($this->assignedValues); + + $self = $this->controller->assignView('variableName', 'variableValue'); + + static::assertInstanceOf(ShaarliVisitorController::class, $self); + static::assertSame('variableValue', $this->assignedValues['variableName']); + } + + public function testRender(): void + { + $this->assignTemplateVars($this->assignedValues); + + $this->container->bookmarkService + ->method('count') + ->willReturnCallback(function (string $visibility): int { + return $visibility === BookmarkFilter::$PRIVATE ? 5 : 10; + }) + ; + + $this->container->pluginManager + ->method('executeHooks') + ->willReturnCallback(function (string $hook, array &$data, array $params): array { + return $data[$hook] = $params; + }); + $this->container->pluginManager->method('getErrors')->willReturn(['error']); + + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $render = $this->controller->render('templateName'); + + static::assertSame('templateName', $render); + + static::assertSame(10, $this->assignedValues['linkcount']); + static::assertSame(5, $this->assignedValues['privateLinkcount']); + static::assertSame(['error'], $this->assignedValues['plugin_errors']); + static::assertSame('/subfolder', $this->assignedValues['base_path']); + static::assertSame('/subfolder/tpl/default', $this->assignedValues['asset_path']); + + static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']); + static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_header']['render_header']['target']); + static::assertTrue($this->assignedValues['plugins_header']['render_header']['loggedin']); + static::assertSame('templateName', $this->assignedValues['plugins_footer']['render_footer']['target']); + static::assertTrue($this->assignedValues['plugins_footer']['render_footer']['loggedin']); + } + + /** + * Test redirectFromReferer() - Default behaviour + */ + public function testRedirectFromRefererDefault(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term not matched in the referer + */ + public function testRedirectFromRefererWithUnmatchedLoopTerm(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its path -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInPath(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'controller']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query parameters -> redirect to default + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryParam(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'other']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its query value + * -> we do not block redirection for query parameter values. + */ + public function testRedirectFromRefererWithMatchingLoopTermInQueryValue(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['nope', 'param']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching the referer in its domain name + * -> we do not block redirection for shaarli's hosts + */ + public function testRedirectFromRefererWithLoopTermInDomain(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['shaarli']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?query=param&other=2'], $result->getHeader('location')); + } + + /** + * Test redirectFromReferer() - With a loop term matching a query parameter AND clear this query param + * -> the param should be cleared before checking if it matches the redir loop terms + */ + public function testRedirectFromRefererWithMatchingClearedParam(): void + { + $this->container->environment['HTTP_REFERER'] = 'http://shaarli.tld/subfolder/controller?query=param&other=2'; + + $response = new Response(); + + $result = $this->controller->redirectFromReferer($this->request, $response, ['query'], ['query']); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame(['/subfolder/controller?other=2'], $result->getHeader('location')); + } +} -- cgit v1.2.3 From 9c75f877935fa6adec951a4d8d32b328aaab314f Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 13 Jun 2020 13:08:01 +0200 Subject: Use multi-level routes for existing controllers instead of 1 level everywhere Also prefix most admin routes with /admin/ --- tests/front/controller/visitor/LoginControllerTest.php | 4 ++-- tests/front/controller/visitor/TagControllerTest.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'tests/front/controller/visitor') diff --git a/tests/front/controller/visitor/LoginControllerTest.php b/tests/front/controller/visitor/LoginControllerTest.php index faa8ac71..e57f44b9 100644 --- a/tests/front/controller/visitor/LoginControllerTest.php +++ b/tests/front/controller/visitor/LoginControllerTest.php @@ -95,7 +95,7 @@ class LoginControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('Location')); + static::assertSame(['/subfolder/'], $result->getHeader('Location')); } public function testLoginControllerOpenShaarli(): void @@ -116,7 +116,7 @@ class LoginControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('Location')); + static::assertSame(['/subfolder/'], $result->getHeader('Location')); } public function testLoginControllerWhileBanned(): void diff --git a/tests/front/controller/visitor/TagControllerTest.php b/tests/front/controller/visitor/TagControllerTest.php index 1242a2e9..43076086 100644 --- a/tests/front/controller/visitor/TagControllerTest.php +++ b/tests/front/controller/visitor/TagControllerTest.php @@ -64,7 +64,7 @@ class TagControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./?searchtags=abc'], $result->getHeader('location')); + static::assertSame(['/subfolder/?searchtags=abc'], $result->getHeader('location')); } public function testAddTagRemoveLegacyQueryParam(): void @@ -138,7 +138,7 @@ class TagControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); + static::assertSame(['/subfolder/'], $result->getHeader('location')); } public function testRemoveTagWithoutMatchingTag(): void @@ -184,7 +184,7 @@ class TagControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); + static::assertSame(['/subfolder/'], $result->getHeader('location')); } public function testRemoveTagWithoutTag(): void @@ -210,6 +210,6 @@ class TagControllerTest extends TestCase static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); - static::assertSame(['./'], $result->getHeader('location')); + static::assertSame(['/subfolder/'], $result->getHeader('location')); } } -- cgit v1.2.3 From 1a8ac737e52cb25a5c346232ee398f5908cee7d7 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Mon, 6 Jul 2020 08:04:35 +0200 Subject: Process main page (linklist) through Slim controller Including a bunch of improvements on the container, and helper used across new controllers. --- .../visitor/BookmarkListControllerTest.php | 448 +++++++++++++++++++++ 1 file changed, 448 insertions(+) create mode 100644 tests/front/controller/visitor/BookmarkListControllerTest.php (limited to 'tests/front/controller/visitor') diff --git a/tests/front/controller/visitor/BookmarkListControllerTest.php b/tests/front/controller/visitor/BookmarkListControllerTest.php new file mode 100644 index 00000000..5daaa2c4 --- /dev/null +++ b/tests/front/controller/visitor/BookmarkListControllerTest.php @@ -0,0 +1,448 @@ +createContainer(); + + $this->controller = new BookmarkListController($this->container); + } + + /** + * Test rendering list of bookmarks with default parameters (first page). + */ + public function testIndexDefaultFirstPage(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->with( + ['searchtags' => '', 'searchterm' => ''], + null, + false, + false + ) + ->willReturn([ + (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), + (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), + (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), + ] + ); + + $this->container->sessionManager + ->method('getSessionParameter') + ->willReturnCallback(function (string $parameter, $default = null) { + if ('LINKS_PER_PAGE' === $parameter) { + return 2; + } + + return $default; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + + static::assertSame('Shaarli', $assignedVariables['pagetitle']); + static::assertSame('?page=2', $assignedVariables['previous_page_url']); + static::assertSame('', $assignedVariables['next_page_url']); + static::assertSame(2, $assignedVariables['page_max']); + static::assertSame('', $assignedVariables['search_tags']); + static::assertSame(3, $assignedVariables['result_count']); + static::assertSame(1, $assignedVariables['page_current']); + static::assertSame('', $assignedVariables['search_term']); + static::assertNull($assignedVariables['visibility']); + static::assertCount(2, $assignedVariables['links']); + + $link = $assignedVariables['links'][0]; + + static::assertSame(1, $link['id']); + static::assertSame('http://url1.tld', $link['url']); + static::assertSame('Title 1', $link['title']); + + $link = $assignedVariables['links'][1]; + + static::assertSame(2, $link['id']); + static::assertSame('http://url2.tld', $link['url']); + static::assertSame('Title 2', $link['title']); + } + + /** + * Test rendering list of bookmarks with default parameters (second page). + */ + public function testIndexDefaultSecondPage(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key) { + if ('page' === $key) { + return '2'; + } + + return null; + }); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->with( + ['searchtags' => '', 'searchterm' => ''], + null, + false, + false + ) + ->willReturn([ + (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), + (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), + (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), + ]) + ; + + $this->container->sessionManager + ->method('getSessionParameter') + ->willReturnCallback(function (string $parameter, $default = null) { + if ('LINKS_PER_PAGE' === $parameter) { + return 2; + } + + return $default; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + + static::assertSame('Shaarli', $assignedVariables['pagetitle']); + static::assertSame('', $assignedVariables['previous_page_url']); + static::assertSame('?page=1', $assignedVariables['next_page_url']); + static::assertSame(2, $assignedVariables['page_max']); + static::assertSame('', $assignedVariables['search_tags']); + static::assertSame(3, $assignedVariables['result_count']); + static::assertSame(2, $assignedVariables['page_current']); + static::assertSame('', $assignedVariables['search_term']); + static::assertNull($assignedVariables['visibility']); + static::assertCount(1, $assignedVariables['links']); + + $link = $assignedVariables['links'][2]; + + static::assertSame(3, $link['id']); + static::assertSame('http://url3.tld', $link['url']); + static::assertSame('Title 3', $link['title']); + } + + /** + * Test rendering list of bookmarks with filters. + */ + public function testIndexDefaultWithFilters(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $request->method('getParam')->willReturnCallback(function (string $key) { + if ('searchtags' === $key) { + return 'abc def'; + } + if ('searchterm' === $key) { + return 'ghi jkl'; + } + + return null; + }); + $response = new Response(); + + $this->container->sessionManager + ->method('getSessionParameter') + ->willReturnCallback(function (string $key, $default) { + if ('LINKS_PER_PAGE' === $key) { + return 2; + } + if ('visibility' === $key) { + return 'private'; + } + if ('untaggedonly' === $key) { + return true; + } + + return $default; + }) + ; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->with( + ['searchtags' => 'abc def', 'searchterm' => 'ghi jkl'], + 'private', + false, + true + ) + ->willReturn([ + (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), + (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), + (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), + ]) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + + static::assertSame('Search: ghi jkl [abc] [def] - Shaarli', $assignedVariables['pagetitle']); + static::assertSame('?page=2&searchterm=ghi+jkl&searchtags=abc+def', $assignedVariables['previous_page_url']); + } + + /** + * Test displaying a permalink with valid parameters + */ + public function testPermalinkValid(): void + { + $hash = 'abcdef'; + + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByHash') + ->with($hash) + ->willReturn((new Bookmark())->setId(123)->setTitle('Title 1')->setUrl('http://url1.tld')) + ; + + $result = $this->controller->permalink($request, $response, ['hash' => $hash]); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + + static::assertSame('Title 1 - Shaarli', $assignedVariables['pagetitle']); + static::assertCount(1, $assignedVariables['links']); + + $link = $assignedVariables['links'][0]; + + static::assertSame(123, $link['id']); + static::assertSame('http://url1.tld', $link['url']); + static::assertSame('Title 1', $link['title']); + } + + /** + * Test displaying a permalink with an unknown small hash : renders a 404 template error + */ + public function testPermalinkNotFound(): void + { + $hash = 'abcdef'; + + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByHash') + ->with($hash) + ->willThrowException(new BookmarkNotFoundException()) + ; + + $result = $this->controller->permalink($request, $response, ['hash' => $hash]); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('404', (string) $result->getBody()); + + static::assertSame( + 'The link you are trying to reach does not exist or has been deleted.', + $assignedVariables['error_message'] + ); + } + + /** + * Test getting link list with thumbnail updates. + * -> 2 thumbnails update, only 1 datastore write + */ + public function testThumbnailUpdateFromLinkList(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf + ->method('get') + ->willReturnCallback(function (string $key, $default) { + return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default; + }) + ; + + $this->container->thumbnailer = $this->createMock(Thumbnailer::class); + $this->container->thumbnailer + ->expects(static::exactly(2)) + ->method('get') + ->withConsecutive(['https://url2.tld'], ['https://url4.tld']) + ; + + $this->container->bookmarkService + ->expects(static::once()) + ->method('search') + ->willReturn([ + (new Bookmark())->setId(1)->setUrl('https://url1.tld')->setTitle('Title 1')->setThumbnail(false), + $b1 = (new Bookmark())->setId(2)->setUrl('https://url2.tld')->setTitle('Title 2'), + (new Bookmark())->setId(3)->setUrl('https://url3.tld')->setTitle('Title 3')->setThumbnail(false), + $b2 = (new Bookmark())->setId(2)->setUrl('https://url4.tld')->setTitle('Title 4'), + (new Bookmark())->setId(2)->setUrl('ftp://url5.tld', ['ftp'])->setTitle('Title 5'), + ]) + ; + $this->container->bookmarkService + ->expects(static::exactly(2)) + ->method('set') + ->withConsecutive([$b1, false], [$b2, false]) + ; + $this->container->bookmarkService->expects(static::once())->method('save'); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + } + + /** + * Test getting a permalink with thumbnail update. + */ + public function testThumbnailUpdateFromPermalink(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf + ->method('get') + ->willReturnCallback(function (string $key, $default) { + return $key === 'thumbnails.mode' ? Thumbnailer::MODE_ALL : $default; + }) + ; + + $this->container->thumbnailer = $this->createMock(Thumbnailer::class); + $this->container->thumbnailer->expects(static::once())->method('get')->withConsecutive(['https://url.tld']); + + $this->container->bookmarkService + ->expects(static::once()) + ->method('findByHash') + ->willReturn($bookmark = (new Bookmark())->setId(2)->setUrl('https://url.tld')->setTitle('Title 1')) + ; + $this->container->bookmarkService->expects(static::once())->method('set')->with($bookmark, true); + $this->container->bookmarkService->expects(static::never())->method('save'); + + $result = $this->controller->permalink($request, $response, ['hash' => 'abc']); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + } + + /** + * Trigger legacy controller in link list controller: permalink + */ + public function testLegacyControllerPermalink(): void + { + $hash = 'abcdef'; + $this->container->environment['QUERY_STRING'] = $hash; + + $request = $this->createMock(Request::class); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/shaare/' . $hash, $result->getHeader('location')[0]); + } + + /** + * Trigger legacy controller in link list controller: ?do= query parameter + */ + public function testLegacyControllerDoPage(): void + { + $request = $this->createMock(Request::class); + $request->method('getQueryParam')->with('do')->willReturn('picwall'); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/picture-wall', $result->getHeader('location')[0]); + } + + /** + * Trigger legacy controller in link list controller: ?do= query parameter with unknown legacy route + */ + public function testLegacyControllerUnknownDoPage(): void + { + $request = $this->createMock(Request::class); + $request->method('getQueryParam')->with('do')->willReturn('nope'); + $response = new Response(); + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('linklist', (string) $result->getBody()); + } + + /** + * Trigger legacy controller in link list controller: other GET route (e.g. ?post) + */ + public function testLegacyControllerGetParameter(): void + { + $request = $this->createMock(Request::class); + $request->method('getQueryParams')->willReturn(['post' => $url = 'http://url.tld']); + $response = new Response(); + + $this->container->loginManager = $this->createMock(LoginManager::class); + $this->container->loginManager->method('isLoggedIn')->willReturn(true); + + $result = $this->controller->index($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame( + '/subfolder/admin/shaare?post=' . urlencode($url), + $result->getHeader('location')[0] + ); + } +} -- cgit v1.2.3 From c4ad3d4f061d05a01db25aa54dda830ba776792d Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Tue, 7 Jul 2020 10:15:56 +0200 Subject: Process Shaarli install through Slim controller --- .../controller/visitor/InstallControllerTest.php | 264 +++++++++++++++++++++ 1 file changed, 264 insertions(+) create mode 100644 tests/front/controller/visitor/InstallControllerTest.php (limited to 'tests/front/controller/visitor') diff --git a/tests/front/controller/visitor/InstallControllerTest.php b/tests/front/controller/visitor/InstallControllerTest.php new file mode 100644 index 00000000..6871fdd9 --- /dev/null +++ b/tests/front/controller/visitor/InstallControllerTest.php @@ -0,0 +1,264 @@ +createContainer(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('getConfigFileExt')->willReturn(static::MOCK_FILE); + $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { + if ($key === 'resource.raintpl_tpl') { + return '.'; + } + + return $default ?? $key; + }); + + $this->controller = new InstallController($this->container); + } + + protected function tearDown(): void + { + if (file_exists(static::MOCK_FILE)) { + unlink(static::MOCK_FILE); + } + } + + /** + * Test displaying install page with valid session. + */ + public function testInstallIndexWithValidSession(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->method('getSessionParameter') + ->willReturnCallback(function (string $key, $default) { + return $key === 'session_tested' ? 'Working' : $default; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('install', (string) $result->getBody()); + + static::assertIsArray($assignedVariables['continents']); + static::assertSame('Africa', $assignedVariables['continents'][0]); + static::assertSame('UTC', $assignedVariables['continents']['selected']); + + static::assertIsArray($assignedVariables['cities']); + static::assertSame(['continent' => 'Africa', 'city' => 'Abidjan'], $assignedVariables['cities'][0]); + static::assertSame('UTC', $assignedVariables['continents']['selected']); + + static::assertIsArray($assignedVariables['languages']); + static::assertSame('Automatic', $assignedVariables['languages']['auto']); + static::assertSame('French', $assignedVariables['languages']['fr']); + } + + /** + * Instantiate the install controller with an existing config file: exception. + */ + public function testInstallWithExistingConfigFile(): void + { + $this->expectException(AlreadyInstalledException::class); + + touch(static::MOCK_FILE); + + $this->controller = new InstallController($this->container); + } + + /** + * Call controller without session yet defined, redirect to test session install page. + */ + public function testInstallRedirectToSessionTest(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(InstallController::SESSION_TEST_KEY, InstallController::SESSION_TEST_VALUE) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/install/session-test', $result->getHeader('location')[0]); + } + + /** + * Call controller in session test mode: valid session then redirect to install page. + */ + public function testInstallSessionTestValid(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(InstallController::SESSION_TEST_KEY) + ->willReturn(InstallController::SESSION_TEST_VALUE) + ; + + $result = $this->controller->sessionTest($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/install', $result->getHeader('location')[0]); + } + + /** + * Call controller in session test mode: invalid session then redirect to error page. + */ + public function testInstallSessionTestError(): void + { + $assignedVars = []; + $this->assignTemplateVars($assignedVars); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(InstallController::SESSION_TEST_KEY) + ->willReturn('KO') + ; + + $result = $this->controller->sessionTest($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('error', (string) $result->getBody()); + static::assertStringStartsWith( + '
Sessions do not seem to work correctly on your server',
+            $assignedVars['message']
+        );
+    }
+
+    /**
+     * Test saving valid data from install form. Also initialize datastore.
+     */
+    public function testSaveInstallValid(): void
+    {
+        $providedParameters = [
+            'continent' => 'Europe',
+            'city' => 'Berlin',
+            'setlogin' => 'bob',
+            'setpassword' => 'password',
+            'title' => 'Shaarli',
+            'language' => 'fr',
+            'updateCheck' => true,
+            'enableApi' => true,
+        ];
+
+        $expectedSettings = [
+            'general.timezone' => 'Europe/Berlin',
+            'credentials.login' => 'bob',
+            'credentials.salt' => '_NOT_EMPTY',
+            'credentials.hash' => '_NOT_EMPTY',
+            'general.title' => 'Shaarli',
+            'translation.language' => 'en',
+            'updates.check_updates' => true,
+            'api.enabled' => true,
+            'api.secret' => '_NOT_EMPTY',
+        ];
+
+        $request = $this->createMock(Request::class);
+        $request->method('getParam')->willReturnCallback(function (string $key) use ($providedParameters) {
+            return $providedParameters[$key] ?? null;
+        });
+        $response = new Response();
+
+        $this->container->conf = $this->createMock(ConfigManager::class);
+        $this->container->conf
+            ->method('get')
+            ->willReturnCallback(function (string $key, $value) {
+                if ($key === 'credentials.login') {
+                    return 'bob';
+                } elseif ($key === 'credentials.salt') {
+                    return 'salt';
+                }
+
+                return $value;
+            })
+        ;
+        $this->container->conf
+            ->expects(static::exactly(count($expectedSettings)))
+            ->method('set')
+            ->willReturnCallback(function (string $key, $value) use ($expectedSettings) {
+                if ($expectedSettings[$key] ?? null === '_NOT_EMPTY') {
+                    static::assertNotEmpty($value);
+                } else {
+                    static::assertSame($expectedSettings[$key], $value);
+                }
+            })
+        ;
+        $this->container->conf->expects(static::once())->method('write');
+
+        $this->container->bookmarkService->expects(static::once())->method('count')->willReturn(0);
+        $this->container->bookmarkService->expects(static::once())->method('initialize');
+
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_SUCCESS_MESSAGES)
+        ;
+
+        $result = $this->controller->save($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+    }
+
+    /**
+     * Test default settings (timezone and title).
+     * Also check that bookmarks are not initialized if
+     */
+    public function testSaveInstallDefaultValues(): void
+    {
+        $confSettings = [];
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->conf->method('set')->willReturnCallback(function (string $key, $value) use (&$confSettings) {
+            $confSettings[$key] = $value;
+        });
+
+        $result = $this->controller->save($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+
+        static::assertSame('UTC', $confSettings['general.timezone']);
+        static::assertSame('Shared bookmarks on http://shaarli', $confSettings['general.title']);
+    }
+}
-- 
cgit v1.2.3


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

---
 .../visitor/FrontControllerMockHelper.php          |   1 +
 .../controller/visitor/LoginControllerTest.php     | 278 ++++++++++++++++++++-
 2 files changed, 275 insertions(+), 4 deletions(-)

(limited to 'tests/front/controller/visitor')

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


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

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

(limited to 'tests/front/controller/visitor')

diff --git a/tests/front/controller/visitor/InstallControllerTest.php b/tests/front/controller/visitor/InstallControllerTest.php
index 6871fdd9..29c4d7a0 100644
--- a/tests/front/controller/visitor/InstallControllerTest.php
+++ b/tests/front/controller/visitor/InstallControllerTest.php
@@ -189,6 +189,7 @@ class InstallControllerTest extends TestCase
             'updates.check_updates' => true,
             'api.enabled' => true,
             'api.secret' => '_NOT_EMPTY',
+            'general.header_link' => '/subfolder',
         ];
 
         $request = $this->createMock(Request::class);
-- 
cgit v1.2.3


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

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

(limited to 'tests/front/controller/visitor')

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


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

---
 .../visitor/PublicSessionFilterControllerTest.php  | 71 ++++++++++++++++++++++
 1 file changed, 71 insertions(+)
 create mode 100644 tests/front/controller/visitor/PublicSessionFilterControllerTest.php

(limited to 'tests/front/controller/visitor')

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


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

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

(limited to 'tests/front/controller/visitor')

diff --git a/tests/front/controller/visitor/ShaarliVisitorControllerTest.php b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php
index 83d08358..316ce49c 100644
--- a/tests/front/controller/visitor/ShaarliVisitorControllerTest.php
+++ b/tests/front/controller/visitor/ShaarliVisitorControllerTest.php
@@ -96,8 +96,6 @@ class ShaarliVisitorControllerTest extends TestCase
         static::assertSame(10, $this->assignedValues['linkcount']);
         static::assertSame(5, $this->assignedValues['privateLinkcount']);
         static::assertSame(['error'], $this->assignedValues['plugin_errors']);
-        static::assertSame('/subfolder', $this->assignedValues['base_path']);
-        static::assertSame('/subfolder/tpl/default', $this->assignedValues['asset_path']);
 
         static::assertSame('templateName', $this->assignedValues['plugins_includes']['render_includes']['target']);
         static::assertTrue($this->assignedValues['plugins_includes']['render_includes']['loggedin']);
-- 
cgit v1.2.3


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

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

(limited to 'tests/front/controller/visitor')

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


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

Also handle authentication check in a new middleware for the admin group.
---
 .../visitor/PublicSessionFilterControllerTest.php  | 51 ++++++++++++++++++++++
 1 file changed, 51 insertions(+)

(limited to 'tests/front/controller/visitor')

diff --git a/tests/front/controller/visitor/PublicSessionFilterControllerTest.php b/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
index 3aa1cb99..06352750 100644
--- a/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
+++ b/tests/front/controller/visitor/PublicSessionFilterControllerTest.php
@@ -68,4 +68,55 @@ class PublicSessionFilterControllerTest extends TestCase
         static::assertSame(302, $result->getStatusCode());
         static::assertSame(['/subfolder/'], $result->getHeader('location'));
     }
+
+    /**
+     * Untagged only - valid call
+     */
+    public function testUntaggedOnly(): void
+    {
+        $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_UNTAGGED_ONLY, true)
+        ;
+
+        $result = $this->controller->untaggedOnly($request, $response);
+
+        static::assertInstanceOf(Response::class, $result);
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
+    }
+
+    /**
+     * Untagged only - toggle off
+     */
+    public function testUntaggedOnlyToggleOff(): void
+    {
+        $this->container->environment = ['HTTP_REFERER' => 'http://shaarli/subfolder/controller/?searchtag=abc'];
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->sessionManager
+            ->method('getSessionParameter')
+            ->with(SessionManager::KEY_UNTAGGED_ONLY)
+            ->willReturn(true)
+        ;
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_UNTAGGED_ONLY, false)
+        ;
+
+        $result = $this->controller->untaggedOnly($request, $response);
+
+        static::assertInstanceOf(Response::class, $result);
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame(['/subfolder/controller/?searchtag=abc'], $result->getHeader('location'));
+    }
 }
-- 
cgit v1.2.3


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

---
 .../controller/visitor/ErrorControllerTest.php     | 70 ++++++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 tests/front/controller/visitor/ErrorControllerTest.php

(limited to 'tests/front/controller/visitor')

diff --git a/tests/front/controller/visitor/ErrorControllerTest.php b/tests/front/controller/visitor/ErrorControllerTest.php
new file mode 100644
index 00000000..e497bfef
--- /dev/null
+++ b/tests/front/controller/visitor/ErrorControllerTest.php
@@ -0,0 +1,70 @@
+createContainer();
+
+        $this->controller = new ErrorController($this->container);
+    }
+
+    /**
+     * Test displaying error with a ShaarliFrontException: display exception message and use its code for HTTTP code
+     */
+    public function testDisplayFrontExceptionError(): void
+    {
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $message = 'error message';
+        $errorCode = 418;
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        $result = ($this->controller)(
+            $request,
+            $response,
+            new class($message, $errorCode) extends ShaarliFrontException {}
+        );
+
+        static::assertSame($errorCode, $result->getStatusCode());
+        static::assertSame($message, $assignedVariables['message']);
+        static::assertArrayNotHasKey('stacktrace', $assignedVariables);
+    }
+
+    /**
+     * Test displaying error with any exception (no debug): only display an error occurred with HTTP 500.
+     */
+    public function testDisplayAnyExceptionErrorNoDebug(): void
+    {
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        // Save RainTPL assigned variables
+        $assignedVariables = [];
+        $this->assignTemplateVars($assignedVariables);
+
+        $result = ($this->controller)($request, $response, new \Exception('abc'));
+
+        static::assertSame(500, $result->getStatusCode());
+        static::assertSame('An unexpected error occurred.', $assignedVariables['message']);
+        static::assertArrayNotHasKey('stacktrace', $assignedVariables);
+    }
+}
-- 
cgit v1.2.3