]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - tests/front/ShaarliMiddlewareTest.php
Move all admin controller into a dedicated group
[github/shaarli/Shaarli.git] / tests / front / ShaarliMiddlewareTest.php
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Shaarli\Front;
6
7 use PHPUnit\Framework\TestCase;
8 use Shaarli\Config\ConfigManager;
9 use Shaarli\Container\ShaarliContainer;
10 use Shaarli\Front\Exception\LoginBannedException;
11 use Shaarli\Front\Exception\UnauthorizedException;
12 use Shaarli\Render\PageBuilder;
13 use Shaarli\Render\PageCacheManager;
14 use Shaarli\Security\LoginManager;
15 use Shaarli\Updater\Updater;
16 use Slim\Http\Request;
17 use Slim\Http\Response;
18 use Slim\Http\Uri;
19
20 class ShaarliMiddlewareTest extends TestCase
21 {
22 protected const TMP_MOCK_FILE = '.tmp';
23
24 /** @var ShaarliContainer */
25 protected $container;
26
27 /** @var ShaarliMiddleware */
28 protected $middleware;
29
30 public function setUp(): void
31 {
32 $this->container = $this->createMock(ShaarliContainer::class);
33
34 touch(static::TMP_MOCK_FILE);
35
36 $this->container->conf = $this->createMock(ConfigManager::class);
37 $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE);
38
39 $this->container->loginManager = $this->createMock(LoginManager::class);
40
41 $this->container->environment = ['REQUEST_URI' => 'http://shaarli/subfolder/path'];
42
43 $this->middleware = new ShaarliMiddleware($this->container);
44 }
45
46 public function tearDown(): void
47 {
48 unlink(static::TMP_MOCK_FILE);
49 }
50
51 /**
52 * Test middleware execution with valid controller call
53 */
54 public function testMiddlewareExecution(): void
55 {
56 $request = $this->createMock(Request::class);
57 $request->method('getUri')->willReturnCallback(function (): Uri {
58 $uri = $this->createMock(Uri::class);
59 $uri->method('getBasePath')->willReturn('/subfolder');
60
61 return $uri;
62 });
63
64 $response = new Response();
65 $controller = function (Request $request, Response $response): Response {
66 return $response->withStatus(418); // I'm a tea pot
67 };
68
69 /** @var Response $result */
70 $result = $this->middleware->__invoke($request, $response, $controller);
71
72 static::assertInstanceOf(Response::class, $result);
73 static::assertSame(418, $result->getStatusCode());
74 }
75
76 /**
77 * Test middleware execution with controller throwing a known front exception
78 */
79 public function testMiddlewareExecutionWithFrontException(): void
80 {
81 $request = $this->createMock(Request::class);
82 $request->method('getUri')->willReturnCallback(function (): Uri {
83 $uri = $this->createMock(Uri::class);
84 $uri->method('getBasePath')->willReturn('/subfolder');
85
86 return $uri;
87 });
88
89 $response = new Response();
90 $controller = function (): void {
91 $exception = new LoginBannedException();
92
93 throw new $exception;
94 };
95
96 $pageBuilder = $this->createMock(PageBuilder::class);
97 $pageBuilder->method('render')->willReturnCallback(function (string $message): string {
98 return $message;
99 });
100 $this->container->pageBuilder = $pageBuilder;
101
102 /** @var Response $result */
103 $result = $this->middleware->__invoke($request, $response, $controller);
104
105 static::assertInstanceOf(Response::class, $result);
106 static::assertSame(401, $result->getStatusCode());
107 static::assertContains('error', (string) $result->getBody());
108 }
109
110 /**
111 * Test middleware execution with controller throwing a not authorized exception
112 */
113 public function testMiddlewareExecutionWithUnauthorizedException(): void
114 {
115 $request = $this->createMock(Request::class);
116 $request->method('getUri')->willReturnCallback(function (): Uri {
117 $uri = $this->createMock(Uri::class);
118 $uri->method('getBasePath')->willReturn('/subfolder');
119
120 return $uri;
121 });
122
123 $response = new Response();
124 $controller = function (): void {
125 throw new UnauthorizedException();
126 };
127
128 /** @var Response $result */
129 $result = $this->middleware->__invoke($request, $response, $controller);
130
131 static::assertSame(302, $result->getStatusCode());
132 static::assertSame(
133 '/subfolder/login?returnurl=' . urlencode('http://shaarli/subfolder/path'),
134 $result->getHeader('location')[0]
135 );
136 }
137
138 /**
139 * Test middleware execution with controller throwing a not authorized exception
140 */
141 public function testMiddlewareExecutionWithServerExceptionWith(): void
142 {
143 $request = $this->createMock(Request::class);
144 $request->method('getUri')->willReturnCallback(function (): Uri {
145 $uri = $this->createMock(Uri::class);
146 $uri->method('getBasePath')->willReturn('/subfolder');
147
148 return $uri;
149 });
150
151 $response = new Response();
152 $controller = function (): void {
153 throw new \Exception();
154 };
155
156 $parameters = [];
157 $this->container->pageBuilder = $this->createMock(PageBuilder::class);
158 $this->container->pageBuilder->method('render')->willReturnCallback(function (string $message): string {
159 return $message;
160 });
161 $this->container->pageBuilder
162 ->method('assign')
163 ->willReturnCallback(function (string $key, string $value) use (&$parameters): void {
164 $parameters[$key] = $value;
165 })
166 ;
167
168 /** @var Response $result */
169 $result = $this->middleware->__invoke($request, $response, $controller);
170
171 static::assertSame(500, $result->getStatusCode());
172 static::assertContains('error', (string) $result->getBody());
173 static::assertSame('An unexpected error occurred.', $parameters['message']);
174 }
175
176 public function testMiddlewareExecutionWithUpdates(): void
177 {
178 $request = $this->createMock(Request::class);
179 $request->method('getUri')->willReturnCallback(function (): Uri {
180 $uri = $this->createMock(Uri::class);
181 $uri->method('getBasePath')->willReturn('/subfolder');
182
183 return $uri;
184 });
185
186 $response = new Response();
187 $controller = function (Request $request, Response $response): Response {
188 return $response->withStatus(418); // I'm a tea pot
189 };
190
191 $this->container->loginManager = $this->createMock(LoginManager::class);
192 $this->container->loginManager->method('isLoggedIn')->willReturn(true);
193
194 $this->container->conf = $this->createMock(ConfigManager::class);
195 $this->container->conf->method('get')->willReturnCallback(function (string $key): string {
196 return $key;
197 });
198 $this->container->conf->method('getConfigFileExt')->willReturn(static::TMP_MOCK_FILE);
199
200 $this->container->pageCacheManager = $this->createMock(PageCacheManager::class);
201 $this->container->pageCacheManager->expects(static::once())->method('invalidateCaches');
202
203 $this->container->updater = $this->createMock(Updater::class);
204 $this->container->updater
205 ->expects(static::once())
206 ->method('update')
207 ->willReturn(['update123'])
208 ;
209 $this->container->updater->method('getDoneUpdates')->willReturn($updates = ['update123', 'other']);
210 $this->container->updater
211 ->expects(static::once())
212 ->method('writeUpdates')
213 ->with('resource.updates', $updates)
214 ;
215
216 /** @var Response $result */
217 $result = $this->middleware->__invoke($request, $response, $controller);
218
219 static::assertInstanceOf(Response::class, $result);
220 static::assertSame(418, $result->getStatusCode());
221 }
222 }