Issues (40)

Tests/CookieMiddlewareTest.php (3 issues)

1
<?php
2
/**
3
* @author SignpostMarv
4
*/
5
declare(strict_types=1);
6
7
namespace SignpostMarv\DaftFramework\Tests;
8
9
use Generator;
10
use PHPUnit\Framework\TestCase as Base;
11
use SignpostMarv\DaftFramework\Http\CookieMiddleware;
12
use SignpostMarv\DaftFramework\HttpHandler;
13
use SignpostMarv\DaftRouter\DaftSource;
14
use Symfony\Component\HttpFoundation\Cookie;
15
use Symfony\Component\HttpFoundation\Request;
16
17
class CookieMiddlewareTest extends Base
18
{
19
	/**
20
	* @dataProvider DataProvderCookeMiddlewareTest
21
	*/
22
	public function testCookieMiddleware(
23
		string $implementation,
24
		string $baseUrl,
25
		string $basePath,
26
		array $config,
27
		string $cookieName,
28
		string $cookieValue,
29
		? string $secure,
30
		? string $http,
31
		? string $sameSite
32
	) : void {
33
		$url = sprintf(
34
			'cookie-test/%s/%s/%s/%s/%s',
35
			rawurlencode($cookieName),
36
			rawurlencode($cookieValue),
37
			rawurlencode($secure ?? '1'),
38
			rawurlencode($http ?? '1'),
39
			rawurlencode($sameSite ?? 'lax')
40
		);
41
42
		/**
43
		* @var array<string, bool|string>
44
		*/
45
		$cookieConfig = [];
46
47
		if (is_string($secure) && is_string($http) && is_string($sameSite)) {
48
			$cookieConfig = [
49
				'secure' => '1' !== $secure,
50
				'httpOnly' => '1' !== $http,
51
				'sameSite' => (('lax' === $sameSite) ? 'strict' : 'lax'),
52
			];
53
		}
54
55
		$config[CookieMiddleware::class] = $cookieConfig;
56
57
		/**
58
		* @var array<string, string|array<int, string>>
59
		*/
60
		$sourceConfig = (array) $config[DaftSource::class];
61
62
		$sourceConfig['sources'] = [
63
			fixtures\Routes\CookieTest::class,
64
		];
65
		$sourceConfig['cacheFile'] = (
66
			__DIR__ .
67
			'/fixtures/cookie-test.fast-route.cache'
68
		);
69
70
		$config[DaftSource::class] = $sourceConfig;
71
72
		$instance = Utilities::ObtainHttpHandlerInstanceMixedArgs(
73
			$this,
74
			$implementation,
75
			$baseUrl,
76
			$basePath,
77
			$config
78
		);
79
80
		$request = Request::create($baseUrl . $url);
81
82
		$response = $instance->handle($request);
83
84
		$cookie = current(array_filter(
85
			$response->headers->getCookies(),
86
			function (Cookie $cookie) use ($cookieName) : bool {
87
				return $cookieName === $cookie->getName();
88
			}
89
		));
90
91
		static::assertInstanceOf(Cookie::class, $cookie);
92
93
		if (is_string($secure) && is_string($http) && is_string($sameSite)) {
94
			static::assertSame(
0 ignored issues
show
Bug Best Practice introduced by
The method PHPUnit\Framework\Assert::assertSame() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

94
			static::/** @scrutinizer ignore-call */ 
95
           assertSame(
Loading history...
95
				'1' === $secure,
0 ignored issues
show
'1' === $secure of type boolean is incompatible with the type PHPUnit\Framework\T expected by parameter $expected of PHPUnit\Framework\Assert::assertSame(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

95
				/** @scrutinizer ignore-type */ '1' === $secure,
Loading history...
96
				$cookie->isSecure(),
97
				'Secure must match without middleware'
98
			);
99
			static::assertSame(
100
				'1' === $http,
101
				$cookie->isHttpOnly(),
102
				'HttpOnly must match without middleware'
103
			);
104
			static::assertSame(
105
				$sameSite,
0 ignored issues
show
$sameSite of type string is incompatible with the type PHPUnit\Framework\T expected by parameter $expected of PHPUnit\Framework\Assert::assertSame(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

105
				/** @scrutinizer ignore-type */ $sameSite,
Loading history...
106
				$cookie->getSameSite(),
107
				'SameSite must match without middleware'
108
			);
109
		}
110
111
		/**
112
		* @var array<string, string|array<int, string>>
113
		*/
114
		$sourceConfig = (array) $config[DaftSource::class];
115
116
		$sourceConfig['sources'] = [fixtures\Routes\CookieTest::class, CookieMiddleware::class];
117
		$sourceConfig['cacheFile'] = (__DIR__ . '/fixtures/cookie-middleware.fast-route.cache');
118
119
		$config[DaftSource::class] = $sourceConfig;
120
121
		$instance = Utilities::ObtainHttpHandlerInstanceMixedArgs(
122
			$this,
123
			$implementation,
124
			$baseUrl,
125
			$basePath,
126
			$config
127
		);
128
129
		$request = Request::create($baseUrl . $url);
130
131
		$response = $instance->handle($request);
132
133
		$cookie = current(array_filter(
134
			$response->headers->getCookies(),
135
			function (Cookie $cookie) use ($cookieName) : bool {
136
				return $cookieName === $cookie->getName();
137
			}
138
		));
139
140
		static::assertInstanceOf(Cookie::class, $cookie);
141
142
		if (is_string($secure) && is_string($http) && is_string($sameSite)) {
143
			/**
144
			* @var array<string, string|bool>
145
			*/
146
			$cookieConfig = $config[CookieMiddleware::class];
147
148
			static::assertSame(
149
				$cookieConfig['secure'],
150
				$cookie->isSecure(),
151
				sprintf(
152
					'Secure must match flipped value with middleware %s vs %s',
153
					var_export($cookieConfig['secure'], true),
154
					var_export($cookie->isSecure(), true)
155
				)
156
			);
157
			static::assertSame(
158
				$cookieConfig['httpOnly'],
159
				$cookie->isHttpOnly(),
160
				sprintf(
161
					'HttpOnly must match flipped value with middleware %s vs %s',
162
					var_export($cookieConfig['httpOnly'], true),
163
					var_export($cookie->isHttpOnly(), true)
164
				)
165
			);
166
			static::assertSame(
167
				$cookieConfig['sameSite'],
168
				$cookie->getSameSite(),
169
				sprintf(
170
					'SameSite must match flipped value with middleware %s vs %s',
171
					var_export($cookieConfig['sameSite'], true),
172
					var_export($cookie->getSameSite(), true)
173
				)
174
			);
175
		}
176
	}
177
178
	/**
179
	* @return Generator<int, array{0:class-string<HttpHandler>, 1:string, 2:string, 3:array, 4:string, 5:string, 6:string|null, 7:string|null, 8:string|null}, mixed, void>
180
	*/
181
	public function DataProvderCookeMiddlewareTest() : Generator
182
	{
183
		foreach ($this->DataProviderCookieNameValue() as $cookie) {
184
			foreach ($this->DataProviderHttpHandlerInstances() as $handlerArgs) {
185
				[
186
					$implementation,
187
					,
188
					$baseUrl,
189
					$basePath,
190
					$config,
191
					$cookieName,
192
					$cookieValue,
193
					$secure,
194
					$http,
195
					$sameSite,
196
				] = array_merge($handlerArgs, $cookie, [null, null, null]);
197
198
				/**
199
				* @var array{0:class-string<HttpHandler>, 1:string, 2:string, 3:array, 4:string, 5:string, 6:string|null, 7:string|null, 8:string|null}
200
				*/
201
				$yielding = [
202
					$implementation,
203
					$baseUrl,
204
					$basePath,
205
					$config,
206
					$cookieName,
207
					$cookieValue,
208
					$secure,
209
					$http,
210
					$sameSite,
211
				];
212
213
				yield $yielding;
214
215
				foreach ($this->DataProviderCookieSecure() as $secure) {
216
					foreach ($this->DataProviderCookieHttp() as $http) {
217
						foreach ($this->DataProviderCookieSameSite() as $sameSite) {
218
							[
219
								$implementation,
220
								,
221
								$baseUrl,
222
								$basePath,
223
								$config,
224
								$cookieName,
225
								$cookieValue,
226
							] = array_merge($handlerArgs, $cookie);
227
228
							/**
229
							* @var array{0:class-string<HttpHandler>, 1:string, 2:string, 3:array, 4:string, 5:string, 6:string|null, 7:string|null, 8:string|null}
230
							*/
231
							$yielding = [
232
								$implementation,
233
								$baseUrl,
234
								$basePath,
235
								$config,
236
								$cookieName,
237
								$cookieValue,
238
								$secure,
239
								$http,
240
								$sameSite,
241
							];
242
243
							yield $yielding;
244
						}
245
					}
246
				}
247
			}
248
		}
249
	}
250
251
	/**
252
	* @psalm-return Generator<int, array{0:class-string<HttpHandler>, 1:array, 2:string, 3:string, 4:array}, mixed, void>
253
	*/
254
	public function DataProviderHttpHandlerInstances() : Generator
255
	{
256
		yield from [
257
			[
258
				HttpHandler::class,
259
				[],
260
				'https://example.com/',
261
				realpath(__DIR__ . '/fixtures'),
262
				[
263
					DaftSource::class => [],
264
				],
265
			],
266
		];
267
	}
268
269
	/**
270
	* @psalm-return Generator<int, array{0:string, 1:string}, mixed, void>
271
	*/
272
	public function DataProviderCookieNameValue() : Generator
273
	{
274
		yield from [
275
			['a', 'b'],
276
		];
277
	}
278
279
	/**
280
	* @psalm-return Generator<int, string, mixed, void>
281
	*/
282
	public function DataProviderCookieSecure() : Generator
283
	{
284
		yield from ['0', '1'];
285
	}
286
287
	/**
288
	* @psalm-return Generator<int, string, mixed, void>
289
	*/
290
	public function DataProviderCookieHttp() : Generator
291
	{
292
		yield from ['0', '1'];
293
	}
294
295
	/**
296
	* @psalm-return Generator<int, string, mixed, void>
297
	*/
298
	public function DataProviderCookieSameSite() : Generator
299
	{
300
		yield from ['lax', 'strict'];
301
	}
302
}
303