]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - tests/front/controller/visitor/InstallControllerTest.php
Feature: add a Server administration page
[github/shaarli/Shaarli.git] / tests / front / controller / visitor / InstallControllerTest.php
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Shaarli\Front\Controller\Visitor;
6
7 use Shaarli\Config\ConfigManager;
8 use Shaarli\Front\Exception\AlreadyInstalledException;
9 use Shaarli\Security\SessionManager;
10 use Shaarli\TestCase;
11 use Slim\Http\Request;
12 use Slim\Http\Response;
13
14 class InstallControllerTest extends TestCase
15 {
16 use FrontControllerMockHelper;
17
18 const MOCK_FILE = '.tmp';
19
20 /** @var InstallController */
21 protected $controller;
22
23 public function setUp(): void
24 {
25 $this->createContainer();
26
27 $this->container->conf = $this->createMock(ConfigManager::class);
28 $this->container->conf->method('getConfigFileExt')->willReturn(static::MOCK_FILE);
29 $this->container->conf->method('get')->willReturnCallback(function (string $key, $default) {
30 if ($key === 'resource.raintpl_tpl') {
31 return '.';
32 }
33
34 return $default ?? $key;
35 });
36
37 $this->controller = new InstallController($this->container);
38 }
39
40 protected function tearDown(): void
41 {
42 if (file_exists(static::MOCK_FILE)) {
43 unlink(static::MOCK_FILE);
44 }
45 }
46
47 /**
48 * Test displaying install page with valid session.
49 */
50 public function testInstallIndexWithValidSession(): void
51 {
52 $assignedVariables = [];
53 $this->assignTemplateVars($assignedVariables);
54
55 $request = $this->createMock(Request::class);
56 $response = new Response();
57
58 $this->container->sessionManager = $this->createMock(SessionManager::class);
59 $this->container->sessionManager
60 ->method('getSessionParameter')
61 ->willReturnCallback(function (string $key, $default) {
62 return $key === 'session_tested' ? 'Working' : $default;
63 })
64 ;
65
66 $result = $this->controller->index($request, $response);
67
68 static::assertSame(200, $result->getStatusCode());
69 static::assertSame('install', (string) $result->getBody());
70
71 static::assertIsArray($assignedVariables['continents']);
72 static::assertSame('Africa', $assignedVariables['continents'][0]);
73 static::assertSame('UTC', $assignedVariables['continents']['selected']);
74
75 static::assertIsArray($assignedVariables['cities']);
76 static::assertSame(['continent' => 'Africa', 'city' => 'Abidjan'], $assignedVariables['cities'][0]);
77 static::assertSame('UTC', $assignedVariables['continents']['selected']);
78
79 static::assertIsArray($assignedVariables['languages']);
80 static::assertSame('Automatic', $assignedVariables['languages']['auto']);
81 static::assertSame('French', $assignedVariables['languages']['fr']);
82
83 static::assertSame(PHP_VERSION, $assignedVariables['php_version']);
84 static::assertArrayHasKey('php_has_reached_eol', $assignedVariables);
85 static::assertArrayHasKey('php_eol', $assignedVariables);
86 static::assertArrayHasKey('php_extensions', $assignedVariables);
87 static::assertArrayHasKey('permissions', $assignedVariables);
88 static::assertEmpty($assignedVariables['permissions']);
89
90 static::assertSame('Install Shaarli', $assignedVariables['pagetitle']);
91 }
92
93 /**
94 * Instantiate the install controller with an existing config file: exception.
95 */
96 public function testInstallWithExistingConfigFile(): void
97 {
98 $this->expectException(AlreadyInstalledException::class);
99
100 touch(static::MOCK_FILE);
101
102 $this->controller = new InstallController($this->container);
103 }
104
105 /**
106 * Call controller without session yet defined, redirect to test session install page.
107 */
108 public function testInstallRedirectToSessionTest(): void
109 {
110 $request = $this->createMock(Request::class);
111 $response = new Response();
112
113 $this->container->sessionManager = $this->createMock(SessionManager::class);
114 $this->container->sessionManager
115 ->expects(static::once())
116 ->method('setSessionParameter')
117 ->with(InstallController::SESSION_TEST_KEY, InstallController::SESSION_TEST_VALUE)
118 ;
119
120 $result = $this->controller->index($request, $response);
121
122 static::assertSame(302, $result->getStatusCode());
123 static::assertSame('/subfolder/install/session-test', $result->getHeader('location')[0]);
124 }
125
126 /**
127 * Call controller in session test mode: valid session then redirect to install page.
128 */
129 public function testInstallSessionTestValid(): void
130 {
131 $request = $this->createMock(Request::class);
132 $response = new Response();
133
134 $this->container->sessionManager = $this->createMock(SessionManager::class);
135 $this->container->sessionManager
136 ->method('getSessionParameter')
137 ->with(InstallController::SESSION_TEST_KEY)
138 ->willReturn(InstallController::SESSION_TEST_VALUE)
139 ;
140
141 $result = $this->controller->sessionTest($request, $response);
142
143 static::assertSame(302, $result->getStatusCode());
144 static::assertSame('/subfolder/install', $result->getHeader('location')[0]);
145 }
146
147 /**
148 * Call controller in session test mode: invalid session then redirect to error page.
149 */
150 public function testInstallSessionTestError(): void
151 {
152 $assignedVars = [];
153 $this->assignTemplateVars($assignedVars);
154
155 $request = $this->createMock(Request::class);
156 $response = new Response();
157
158 $this->container->sessionManager = $this->createMock(SessionManager::class);
159 $this->container->sessionManager
160 ->method('getSessionParameter')
161 ->with(InstallController::SESSION_TEST_KEY)
162 ->willReturn('KO')
163 ;
164
165 $result = $this->controller->sessionTest($request, $response);
166
167 static::assertSame(200, $result->getStatusCode());
168 static::assertSame('error', (string) $result->getBody());
169 static::assertStringStartsWith(
170 '<pre>Sessions do not seem to work correctly on your server',
171 $assignedVars['message']
172 );
173 }
174
175 /**
176 * Test saving valid data from install form. Also initialize datastore.
177 */
178 public function testSaveInstallValid(): void
179 {
180 $providedParameters = [
181 'continent' => 'Europe',
182 'city' => 'Berlin',
183 'setlogin' => 'bob',
184 'setpassword' => 'password',
185 'title' => 'Shaarli',
186 'language' => 'fr',
187 'updateCheck' => true,
188 'enableApi' => true,
189 ];
190
191 $expectedSettings = [
192 'general.timezone' => 'Europe/Berlin',
193 'credentials.login' => 'bob',
194 'credentials.salt' => '_NOT_EMPTY',
195 'credentials.hash' => '_NOT_EMPTY',
196 'general.title' => 'Shaarli',
197 'translation.language' => 'en',
198 'updates.check_updates' => true,
199 'api.enabled' => true,
200 'api.secret' => '_NOT_EMPTY',
201 'general.header_link' => '/subfolder',
202 ];
203
204 $request = $this->createMock(Request::class);
205 $request->method('getParam')->willReturnCallback(function (string $key) use ($providedParameters) {
206 return $providedParameters[$key] ?? null;
207 });
208 $response = new Response();
209
210 $this->container->conf = $this->createMock(ConfigManager::class);
211 $this->container->conf
212 ->method('get')
213 ->willReturnCallback(function (string $key, $value) {
214 if ($key === 'credentials.login') {
215 return 'bob';
216 } elseif ($key === 'credentials.salt') {
217 return 'salt';
218 }
219
220 return $value;
221 })
222 ;
223 $this->container->conf
224 ->expects(static::exactly(count($expectedSettings)))
225 ->method('set')
226 ->willReturnCallback(function (string $key, $value) use ($expectedSettings) {
227 if ($expectedSettings[$key] ?? null === '_NOT_EMPTY') {
228 static::assertNotEmpty($value);
229 } else {
230 static::assertSame($expectedSettings[$key], $value);
231 }
232 })
233 ;
234 $this->container->conf->expects(static::once())->method('write');
235
236 $this->container->sessionManager
237 ->expects(static::once())
238 ->method('setSessionParameter')
239 ->with(SessionManager::KEY_SUCCESS_MESSAGES)
240 ;
241
242 $result = $this->controller->save($request, $response);
243
244 static::assertSame(302, $result->getStatusCode());
245 static::assertSame('/subfolder/login', $result->getHeader('location')[0]);
246 }
247
248 /**
249 * Test default settings (timezone and title).
250 * Also check that bookmarks are not initialized if
251 */
252 public function testSaveInstallDefaultValues(): void
253 {
254 $confSettings = [];
255
256 $request = $this->createMock(Request::class);
257 $response = new Response();
258
259 $this->container->conf->method('set')->willReturnCallback(function (string $key, $value) use (&$confSettings) {
260 $confSettings[$key] = $value;
261 });
262
263 $result = $this->controller->save($request, $response);
264
265 static::assertSame(302, $result->getStatusCode());
266 static::assertSame('/subfolder/login', $result->getHeader('location')[0]);
267
268 static::assertSame('UTC', $confSettings['general.timezone']);
269 static::assertSame('Shared bookmarks on http://shaarli/subfolder/', $confSettings['general.title']);
270 }
271
272 /**
273 * Same test as testSaveInstallDefaultValues() but for an instance install in root directory.
274 */
275 public function testSaveInstallDefaultValuesWithoutSubfolder(): void
276 {
277 $confSettings = [];
278
279 $this->container->environment = [
280 'SERVER_NAME' => 'shaarli',
281 'SERVER_PORT' => '80',
282 'REQUEST_URI' => '/install',
283 'REMOTE_ADDR' => '1.2.3.4',
284 'SCRIPT_NAME' => '/index.php',
285 ];
286
287 $this->container->basePath = '';
288
289 $request = $this->createMock(Request::class);
290 $response = new Response();
291
292 $this->container->conf->method('set')->willReturnCallback(function (string $key, $value) use (&$confSettings) {
293 $confSettings[$key] = $value;
294 });
295
296 $result = $this->controller->save($request, $response);
297
298 static::assertSame(302, $result->getStatusCode());
299 static::assertSame('/login', $result->getHeader('location')[0]);
300
301 static::assertSame('UTC', $confSettings['general.timezone']);
302 static::assertSame('Shared bookmarks on http://shaarli/', $confSettings['general.title']);
303 }
304 }