From c4ad3d4f061d05a01db25aa54dda830ba776792d Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Tue, 7 Jul 2020 10:15:56 +0200 Subject: Process Shaarli install through Slim controller --- tests/bootstrap.php | 11 +- tests/container/ContainerBuilderTest.php | 11 + tests/front/ShaarliMiddlewareTest.php | 12 + .../controller/admin/LogoutControllerTest.php | 18 +- .../controller/visitor/InstallControllerTest.php | 264 +++++++++++++++++++++ tests/render/PageCacheManagerTest.php | 5 +- tests/security/LoginManagerTest.php | 30 ++- tests/security/SessionManagerTest.php | 14 +- tests/updater/UpdaterTest.php | 42 +++- 9 files changed, 365 insertions(+), 42 deletions(-) create mode 100644 tests/front/controller/visitor/InstallControllerTest.php (limited to 'tests') diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 511698ff..d4ddedd5 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -18,9 +18,14 @@ require_once 'application/bookmark/LinkUtils.php'; require_once 'application/Utils.php'; require_once 'application/http/UrlUtils.php'; require_once 'application/http/HttpUtils.php'; -require_once 'tests/utils/ReferenceLinkDB.php'; -require_once 'tests/utils/ReferenceHistory.php'; -require_once 'tests/utils/FakeBookmarkService.php'; require_once 'tests/container/ShaarliTestContainer.php'; require_once 'tests/front/controller/visitor/FrontControllerMockHelper.php'; require_once 'tests/front/controller/admin/FrontAdminControllerMockHelper.php'; +require_once 'tests/updater/DummyUpdater.php'; +require_once 'tests/utils/FakeBookmarkService.php'; +require_once 'tests/utils/FakeConfigManager.php'; +require_once 'tests/utils/ReferenceHistory.php'; +require_once 'tests/utils/ReferenceLinkDB.php'; +require_once 'tests/utils/ReferenceSessionIdHashes.php'; + +\ReferenceSessionIdHashes::genAllHashes(); diff --git a/tests/container/ContainerBuilderTest.php b/tests/container/ContainerBuilderTest.php index db533f37..fa77bf31 100644 --- a/tests/container/ContainerBuilderTest.php +++ b/tests/container/ContainerBuilderTest.php @@ -11,12 +11,15 @@ use Shaarli\Feed\FeedBuilder; use Shaarli\Formatter\FormatterFactory; use Shaarli\History; use Shaarli\Http\HttpAccess; +use Shaarli\Netscape\NetscapeBookmarkUtils; use Shaarli\Plugin\PluginManager; use Shaarli\Render\PageBuilder; use Shaarli\Render\PageCacheManager; +use Shaarli\Security\CookieManager; use Shaarli\Security\LoginManager; use Shaarli\Security\SessionManager; use Shaarli\Thumbnailer; +use Shaarli\Updater\Updater; class ContainerBuilderTest extends TestCase { @@ -32,10 +35,14 @@ class ContainerBuilderTest extends TestCase /** @var ContainerBuilder */ protected $containerBuilder; + /** @var CookieManager */ + protected $cookieManager; + public function setUp(): void { $this->conf = new ConfigManager('tests/utils/config/configJson'); $this->sessionManager = $this->createMock(SessionManager::class); + $this->cookieManager = $this->createMock(CookieManager::class); $this->loginManager = $this->createMock(LoginManager::class); $this->loginManager->method('isLoggedIn')->willReturn(true); @@ -43,6 +50,7 @@ class ContainerBuilderTest extends TestCase $this->containerBuilder = new ContainerBuilder( $this->conf, $this->sessionManager, + $this->cookieManager, $this->loginManager ); } @@ -53,6 +61,7 @@ class ContainerBuilderTest extends TestCase static::assertInstanceOf(ConfigManager::class, $container->conf); static::assertInstanceOf(SessionManager::class, $container->sessionManager); + static::assertInstanceOf(CookieManager::class, $container->cookieManager); static::assertInstanceOf(LoginManager::class, $container->loginManager); static::assertInstanceOf(History::class, $container->history); static::assertInstanceOf(BookmarkServiceInterface::class, $container->bookmarkService); @@ -63,6 +72,8 @@ class ContainerBuilderTest extends TestCase static::assertInstanceOf(FeedBuilder::class, $container->feedBuilder); static::assertInstanceOf(Thumbnailer::class, $container->thumbnailer); static::assertInstanceOf(HttpAccess::class, $container->httpAccess); + static::assertInstanceOf(NetscapeBookmarkUtils::class, $container->netscapeBookmarkUtils); + static::assertInstanceOf(Updater::class, $container->updater); // Set by the middleware static::assertNull($container->basePath); diff --git a/tests/front/ShaarliMiddlewareTest.php b/tests/front/ShaarliMiddlewareTest.php index 81ea1344..20090d8b 100644 --- a/tests/front/ShaarliMiddlewareTest.php +++ b/tests/front/ShaarliMiddlewareTest.php @@ -19,6 +19,8 @@ use Slim\Http\Uri; class ShaarliMiddlewareTest extends TestCase { + protected const TMP_MOCK_FILE = '.tmp'; + /** @var ShaarliContainer */ protected $container; @@ -29,12 +31,21 @@ class ShaarliMiddlewareTest extends TestCase { $this->container = $this->createMock(ShaarliContainer::class); + touch(static::TMP_MOCK_FILE); + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE); + $this->container->loginManager = $this->createMock(LoginManager::class); $this->middleware = new ShaarliMiddleware($this->container); } + public function tearDown() + { + unlink(static::TMP_MOCK_FILE); + } + /** * Test middleware execution with valid controller call */ @@ -179,6 +190,7 @@ class ShaarliMiddlewareTest extends TestCase $this->container->conf->method('get')->willReturnCallback(function (string $key): string { return $key; }); + $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE); $this->container->pageCacheManager = $this->createMock(PageCacheManager::class); $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches'); diff --git a/tests/front/controller/admin/LogoutControllerTest.php b/tests/front/controller/admin/LogoutControllerTest.php index ca177085..45e84dc0 100644 --- a/tests/front/controller/admin/LogoutControllerTest.php +++ b/tests/front/controller/admin/LogoutControllerTest.php @@ -4,14 +4,8 @@ declare(strict_types=1); namespace Shaarli\Front\Controller\Admin; -/** Override PHP builtin setcookie function in the local namespace to mock it... more or less */ -if (!function_exists('Shaarli\Front\Controller\Admin\setcookie')) { - function setcookie(string $name, string $value): void { - $_COOKIE[$name] = $value; - } -} - use PHPUnit\Framework\TestCase; +use Shaarli\Security\CookieManager; use Shaarli\Security\LoginManager; use Shaarli\Security\SessionManager; use Slim\Http\Request; @@ -29,8 +23,6 @@ class LogoutControllerTest extends TestCase $this->createContainer(); $this->controller = new LogoutController($this->container); - - setcookie(LoginManager::$STAY_SIGNED_IN_COOKIE, $cookie = 'hi there'); } public function testValidControllerInvoke(): void @@ -43,13 +35,17 @@ class LogoutControllerTest extends TestCase $this->container->sessionManager = $this->createMock(SessionManager::class); $this->container->sessionManager->expects(static::once())->method('logout'); - static::assertSame('hi there', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); + $this->container->cookieManager = $this->createMock(CookieManager::class); + $this->container->cookieManager + ->expects(static::once()) + ->method('setCookieParameter') + ->with(CookieManager::STAY_SIGNED_IN, 'false', 0, '/subfolder/') + ; $result = $this->controller->index($request, $response); static::assertInstanceOf(Response::class, $result); static::assertSame(302, $result->getStatusCode()); static::assertSame(['/subfolder/'], $result->getHeader('location')); - static::assertSame('false', $_COOKIE[LoginManager::$STAY_SIGNED_IN_COOKIE]); } } diff --git a/tests/front/controller/visitor/InstallControllerTest.php b/tests/front/controller/visitor/InstallControllerTest.php new file mode 100644 index 00000000..6871fdd9 --- /dev/null +++ b/tests/front/controller/visitor/InstallControllerTest.php @@ -0,0 +1,264 @@ +createContainer(); + + $this->container->conf = $this->createMock(ConfigManager::class); + $this->container->conf->method('getConfigFileExt')->willReturn(static::MOCK_FILE); + $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) { + if ($key === 'resource.raintpl_tpl') { + return '.'; + } + + return $default ?? $key; + }); + + $this->controller = new InstallController($this->container); + } + + protected function tearDown(): void + { + if (file_exists(static::MOCK_FILE)) { + unlink(static::MOCK_FILE); + } + } + + /** + * Test displaying install page with valid session. + */ + public function testInstallIndexWithValidSession(): void + { + $assignedVariables = []; + $this->assignTemplateVars($assignedVariables); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->method('getSessionParameter') + ->willReturnCallback(function (string $key, $default) { + return $key === 'session_tested' ? 'Working' : $default; + }) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('install', (string) $result->getBody()); + + static::assertIsArray($assignedVariables['continents']); + static::assertSame('Africa', $assignedVariables['continents'][0]); + static::assertSame('UTC', $assignedVariables['continents']['selected']); + + static::assertIsArray($assignedVariables['cities']); + static::assertSame(['continent' => 'Africa', 'city' => 'Abidjan'], $assignedVariables['cities'][0]); + static::assertSame('UTC', $assignedVariables['continents']['selected']); + + static::assertIsArray($assignedVariables['languages']); + static::assertSame('Automatic', $assignedVariables['languages']['auto']); + static::assertSame('French', $assignedVariables['languages']['fr']); + } + + /** + * Instantiate the install controller with an existing config file: exception. + */ + public function testInstallWithExistingConfigFile(): void + { + $this->expectException(AlreadyInstalledException::class); + + touch(static::MOCK_FILE); + + $this->controller = new InstallController($this->container); + } + + /** + * Call controller without session yet defined, redirect to test session install page. + */ + public function testInstallRedirectToSessionTest(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->expects(static::once()) + ->method('setSessionParameter') + ->with(InstallController::SESSION_TEST_KEY, InstallController::SESSION_TEST_VALUE) + ; + + $result = $this->controller->index($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/install/session-test', $result->getHeader('location')[0]); + } + + /** + * Call controller in session test mode: valid session then redirect to install page. + */ + public function testInstallSessionTestValid(): void + { + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(InstallController::SESSION_TEST_KEY) + ->willReturn(InstallController::SESSION_TEST_VALUE) + ; + + $result = $this->controller->sessionTest($request, $response); + + static::assertSame(302, $result->getStatusCode()); + static::assertSame('/subfolder/install', $result->getHeader('location')[0]); + } + + /** + * Call controller in session test mode: invalid session then redirect to error page. + */ + public function testInstallSessionTestError(): void + { + $assignedVars = []; + $this->assignTemplateVars($assignedVars); + + $request = $this->createMock(Request::class); + $response = new Response(); + + $this->container->sessionManager = $this->createMock(SessionManager::class); + $this->container->sessionManager + ->method('getSessionParameter') + ->with(InstallController::SESSION_TEST_KEY) + ->willReturn('KO') + ; + + $result = $this->controller->sessionTest($request, $response); + + static::assertSame(200, $result->getStatusCode()); + static::assertSame('error', (string) $result->getBody()); + static::assertStringStartsWith( + '
Sessions do not seem to work correctly on your server',
+            $assignedVars['message']
+        );
+    }
+
+    /**
+     * Test saving valid data from install form. Also initialize datastore.
+     */
+    public function testSaveInstallValid(): void
+    {
+        $providedParameters = [
+            'continent' => 'Europe',
+            'city' => 'Berlin',
+            'setlogin' => 'bob',
+            'setpassword' => 'password',
+            'title' => 'Shaarli',
+            'language' => 'fr',
+            'updateCheck' => true,
+            'enableApi' => true,
+        ];
+
+        $expectedSettings = [
+            'general.timezone' => 'Europe/Berlin',
+            'credentials.login' => 'bob',
+            'credentials.salt' => '_NOT_EMPTY',
+            'credentials.hash' => '_NOT_EMPTY',
+            'general.title' => 'Shaarli',
+            'translation.language' => 'en',
+            'updates.check_updates' => true,
+            'api.enabled' => true,
+            'api.secret' => '_NOT_EMPTY',
+        ];
+
+        $request = $this->createMock(Request::class);
+        $request->method('getParam')->willReturnCallback(function (string $key) use ($providedParameters) {
+            return $providedParameters[$key] ?? null;
+        });
+        $response = new Response();
+
+        $this->container->conf = $this->createMock(ConfigManager::class);
+        $this->container->conf
+            ->method('get')
+            ->willReturnCallback(function (string $key, $value) {
+                if ($key === 'credentials.login') {
+                    return 'bob';
+                } elseif ($key === 'credentials.salt') {
+                    return 'salt';
+                }
+
+                return $value;
+            })
+        ;
+        $this->container->conf
+            ->expects(static::exactly(count($expectedSettings)))
+            ->method('set')
+            ->willReturnCallback(function (string $key, $value) use ($expectedSettings) {
+                if ($expectedSettings[$key] ?? null === '_NOT_EMPTY') {
+                    static::assertNotEmpty($value);
+                } else {
+                    static::assertSame($expectedSettings[$key], $value);
+                }
+            })
+        ;
+        $this->container->conf->expects(static::once())->method('write');
+
+        $this->container->bookmarkService->expects(static::once())->method('count')->willReturn(0);
+        $this->container->bookmarkService->expects(static::once())->method('initialize');
+
+        $this->container->sessionManager
+            ->expects(static::once())
+            ->method('setSessionParameter')
+            ->with(SessionManager::KEY_SUCCESS_MESSAGES)
+        ;
+
+        $result = $this->controller->save($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+    }
+
+    /**
+     * Test default settings (timezone and title).
+     * Also check that bookmarks are not initialized if
+     */
+    public function testSaveInstallDefaultValues(): void
+    {
+        $confSettings = [];
+
+        $request = $this->createMock(Request::class);
+        $response = new Response();
+
+        $this->container->conf->method('set')->willReturnCallback(function (string $key, $value) use (&$confSettings) {
+            $confSettings[$key] = $value;
+        });
+
+        $result = $this->controller->save($request, $response);
+
+        static::assertSame(302, $result->getStatusCode());
+        static::assertSame('/subfolder/', $result->getHeader('location')[0]);
+
+        static::assertSame('UTC', $confSettings['general.timezone']);
+        static::assertSame('Shared bookmarks on http://shaarli', $confSettings['general.title']);
+    }
+}
diff --git a/tests/render/PageCacheManagerTest.php b/tests/render/PageCacheManagerTest.php
index b870e6eb..c258f45f 100644
--- a/tests/render/PageCacheManagerTest.php
+++ b/tests/render/PageCacheManagerTest.php
@@ -1,15 +1,14 @@
 cookie = [];
         $this->session = [];
 
-        $this->sessionManager = new SessionManager($this->session, $this->configManager);
-        $this->loginManager = new LoginManager($this->configManager, $this->sessionManager);
+        $this->cookieManager = $this->createMock(CookieManager::class);
+        $this->cookieManager->method('getCookieParameter')->willReturnCallback(function (string $key) {
+            return $this->cookie[$key] ?? null;
+        });
+        $this->sessionManager = new SessionManager($this->session, $this->configManager, 'session_path');
+        $this->loginManager = new LoginManager($this->configManager, $this->sessionManager, $this->cookieManager);
         $this->server['REMOTE_ADDR'] = $this->ipAddr;
     }
 
@@ -193,8 +199,8 @@ class LoginManagerTest extends TestCase
         $configManager = new \FakeConfigManager([
             'resource.ban_file' => $this->banFile,
         ]);
-        $loginManager = new LoginManager($configManager, null);
-        $loginManager->checkLoginState([], '');
+        $loginManager = new LoginManager($configManager, null, $this->cookieManager);
+        $loginManager->checkLoginState('');
 
         $this->assertFalse($loginManager->isLoggedIn());
     }
@@ -210,9 +216,9 @@ class LoginManagerTest extends TestCase
             'expires_on' => time() + 100,
         ];
         $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
-        $this->cookie[LoginManager::$STAY_SIGNED_IN_COOKIE] = 'nope';
+        $this->cookie[CookieManager::STAY_SIGNED_IN] = 'nope';
 
-        $this->loginManager->checkLoginState($this->cookie, $this->clientIpAddress);
+        $this->loginManager->checkLoginState($this->clientIpAddress);
 
         $this->assertTrue($this->loginManager->isLoggedIn());
         $this->assertTrue(empty($this->session['username']));
@@ -224,9 +230,9 @@ class LoginManagerTest extends TestCase
     public function testCheckLoginStateStaySignedInWithValidToken()
     {
         $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
-        $this->cookie[LoginManager::$STAY_SIGNED_IN_COOKIE] = $this->loginManager->getStaySignedInToken();
+        $this->cookie[CookieManager::STAY_SIGNED_IN] = $this->loginManager->getStaySignedInToken();
 
-        $this->loginManager->checkLoginState($this->cookie, $this->clientIpAddress);
+        $this->loginManager->checkLoginState($this->clientIpAddress);
 
         $this->assertTrue($this->loginManager->isLoggedIn());
         $this->assertEquals($this->login, $this->session['username']);
@@ -241,7 +247,7 @@ class LoginManagerTest extends TestCase
         $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
         $this->session['expires_on'] = time() - 100;
 
-        $this->loginManager->checkLoginState($this->cookie, $this->clientIpAddress);
+        $this->loginManager->checkLoginState($this->clientIpAddress);
 
         $this->assertFalse($this->loginManager->isLoggedIn());
     }
@@ -253,7 +259,7 @@ class LoginManagerTest extends TestCase
     {
         $this->loginManager->generateStaySignedInToken($this->clientIpAddress);
 
-        $this->loginManager->checkLoginState($this->cookie, '10.7.157.98');
+        $this->loginManager->checkLoginState('10.7.157.98');
 
         $this->assertFalse($this->loginManager->isLoggedIn());
     }
diff --git a/tests/security/SessionManagerTest.php b/tests/security/SessionManagerTest.php
index d9db775e..60695dcf 100644
--- a/tests/security/SessionManagerTest.php
+++ b/tests/security/SessionManagerTest.php
@@ -1,12 +1,8 @@
 conf = new FakeConfigManager([
+        $this->conf = new \FakeConfigManager([
             'credentials.login' => 'johndoe',
             'credentials.salt' => 'salt',
             'security.session_protection_disabled' => false,
         ]);
         $this->session = [];
-        $this->sessionManager = new SessionManager($this->session, $this->conf);
+        $this->sessionManager = new SessionManager($this->session, $this->conf, 'session_path');
     }
 
     /**
@@ -69,7 +65,7 @@ class SessionManagerTest extends TestCase
                 $token => 1,
             ],
         ];
-        $sessionManager = new SessionManager($session, $this->conf);
+        $sessionManager = new SessionManager($session, $this->conf, 'session_path');
 
         // check and destroy the token
         $this->assertTrue($sessionManager->checkToken($token));
diff --git a/tests/updater/UpdaterTest.php b/tests/updater/UpdaterTest.php
index afc35aec..c801d451 100644
--- a/tests/updater/UpdaterTest.php
+++ b/tests/updater/UpdaterTest.php
@@ -7,9 +7,6 @@ use Shaarli\Bookmark\BookmarkServiceInterface;
 use Shaarli\Config\ConfigManager;
 use Shaarli\History;
 
-require_once 'tests/updater/DummyUpdater.php';
-require_once 'tests/utils/ReferenceLinkDB.php';
-require_once 'inc/rain.tpl.class.php';
 
 /**
  * Class UpdaterTest.
@@ -35,6 +32,9 @@ class UpdaterTest extends \PHPUnit\Framework\TestCase
     /** @var BookmarkServiceInterface */
     protected $bookmarkService;
 
+    /** @var \ReferenceLinkDB */
+    protected $refDB;
+
     /** @var Updater */
     protected $updater;
 
@@ -43,6 +43,9 @@ class UpdaterTest extends \PHPUnit\Framework\TestCase
      */
     public function setUp()
     {
+        $this->refDB = new \ReferenceLinkDB();
+        $this->refDB->write(self::$testDatastore);
+
         copy('tests/utils/config/configJson.json.php', self::$configFile .'.json.php');
         $this->conf = new ConfigManager(self::$configFile);
         $this->bookmarkService = new BookmarkFileService($this->conf, $this->createMock(History::class), true);
@@ -181,9 +184,40 @@ class UpdaterTest extends \PHPUnit\Framework\TestCase
 
     public function testUpdateMethodRelativeHomeLinkRename(): void
     {
+        $this->updater->setBasePath('/subfolder');
         $this->conf->set('general.header_link', '?');
+
+        $this->updater->updateMethodRelativeHomeLink();
+
+        static::assertSame('/subfolder/', $this->conf->get('general.header_link'));
+    }
+
+    public function testUpdateMethodRelativeHomeLinkDoNotRename(): void
+    {
+        $this->updater->setBasePath('/subfolder');
+        $this->conf->set('general.header_link', '~/my-blog');
+
         $this->updater->updateMethodRelativeHomeLink();
 
-        static::assertSame();
+        static::assertSame('~/my-blog', $this->conf->get('general.header_link'));
+    }
+
+    public function testUpdateMethodMigrateExistingNotesUrl(): void
+    {
+        $this->updater->setBasePath('/subfolder');
+
+        $this->updater->updateMethodMigrateExistingNotesUrl();
+
+        static::assertSame($this->refDB->getLinks()[0]->getUrl(), $this->bookmarkService->get(0)->getUrl());
+        static::assertSame($this->refDB->getLinks()[1]->getUrl(), $this->bookmarkService->get(1)->getUrl());
+        static::assertSame($this->refDB->getLinks()[4]->getUrl(), $this->bookmarkService->get(4)->getUrl());
+        static::assertSame($this->refDB->getLinks()[6]->getUrl(), $this->bookmarkService->get(6)->getUrl());
+        static::assertSame($this->refDB->getLinks()[7]->getUrl(), $this->bookmarkService->get(7)->getUrl());
+        static::assertSame($this->refDB->getLinks()[8]->getUrl(), $this->bookmarkService->get(8)->getUrl());
+        static::assertSame($this->refDB->getLinks()[9]->getUrl(), $this->bookmarkService->get(9)->getUrl());
+        static::assertSame('/subfolder/shaare/WDWyig', $this->bookmarkService->get(42)->getUrl());
+        static::assertSame('/subfolder/shaare/WDWyig', $this->bookmarkService->get(41)->getUrl());
+        static::assertSame('/subfolder/shaare/0gCTjQ', $this->bookmarkService->get(10)->getUrl());
+        static::assertSame('/subfolder/shaare/PCRizQ', $this->bookmarkService->get(11)->getUrl());
     }
 }
-- 
cgit v1.2.3