1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of Rebilly. |
4
|
|
|
* |
5
|
|
|
* For the full copyright and license information, please view the LICENSE |
6
|
|
|
* file that was distributed with this source code. |
7
|
|
|
* |
8
|
|
|
* @see http://rebilly.com |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace Rebilly\OpenAPI\PhpUnit; |
12
|
|
|
|
13
|
|
|
use PHPUnit_Framework_Assert as Assert; |
14
|
|
|
use Psr\Http\Message\RequestInterface as Request; |
15
|
|
|
use Psr\Http\Message\ResponseInterface as Response; |
16
|
|
|
use Psr\Http\Message\StreamInterface as Stream; |
17
|
|
|
use Psr\Http\Message\UriInterface as Uri; |
18
|
|
|
use Rebilly\OpenAPI\Schema as Spec; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Asserts data against OpenAPI specification. |
22
|
|
|
*/ |
23
|
|
|
trait Asserts |
24
|
|
|
{ |
25
|
|
|
/** |
26
|
|
|
* Assert request matches against declared specification. |
27
|
|
|
* |
28
|
|
|
* The list of constraints: |
29
|
|
|
* |
30
|
|
|
* - Assert request method defined |
31
|
|
|
* - Assert request URI declared by host, basePath, schemes and parameters (path, query) |
32
|
|
|
* - Assert content-type declared by consumes |
33
|
|
|
* - Assert headers declared by parameters (header) |
34
|
|
|
* - Assert body declared by parameters (body) |
35
|
|
|
* |
36
|
|
|
* @param Spec $spec |
37
|
|
|
* @param string $template |
38
|
|
|
* @param Request $request |
39
|
|
|
* @param string $msg |
40
|
|
|
*/ |
41
|
4 |
|
final protected static function assertRequest(Spec $spec, $template, Request $request, $msg = '') |
42
|
|
|
{ |
43
|
4 |
|
self::assertMethodAllowed($spec, $template, $request->getMethod(), $msg); |
44
|
3 |
|
self::assertUri($spec, $template, $request->getMethod(), $request->getUri(), $msg); |
45
|
3 |
|
self::assertRequestHeaders($spec, $template, $request->getMethod(), $request->getHeaders(), $msg); |
46
|
2 |
|
self::assertRequestBody($spec, $template, $request->getMethod(), $request->getBody(), $msg); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Assert response matches against declared specification. |
51
|
|
|
* |
52
|
|
|
* The list of constraints: |
53
|
|
|
* |
54
|
|
|
* - Assert response status code or default is defined |
55
|
|
|
* - Assert content-type declared by produces from operation |
56
|
|
|
* - Assert headers |
57
|
|
|
* - Assert body |
58
|
|
|
* |
59
|
|
|
* @param Spec $spec |
60
|
|
|
* @param string $template |
61
|
|
|
* @param string $method |
62
|
|
|
* @param Response $response |
63
|
|
|
* @param string $msg |
64
|
|
|
*/ |
65
|
3 |
|
final protected static function assertResponse(Spec $spec, $template, $method, Response $response, $msg = '') |
66
|
|
|
{ |
67
|
3 |
|
self::assertResponseDefined($spec, $template, $method, $response->getStatusCode(), $msg); |
68
|
3 |
|
self::assertResponseHeaders( |
69
|
|
|
$spec, |
70
|
|
|
$template, |
71
|
|
|
$method, |
72
|
3 |
|
$response->getStatusCode(), |
73
|
3 |
|
$response->getHeaders(), |
74
|
|
|
$msg |
75
|
|
|
); |
76
|
3 |
|
self::assertResponseBody( |
77
|
|
|
$spec, |
78
|
|
|
$template, |
79
|
|
|
$method, |
80
|
3 |
|
$response->getStatusCode(), |
81
|
3 |
|
$response->getBody(), |
82
|
|
|
$msg |
83
|
|
|
); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* Assert URI matches against declared host, basePath, schemes and parameters (path, query). |
88
|
|
|
* |
89
|
|
|
* The list of constraints: |
90
|
|
|
* |
91
|
|
|
* - Assert URI scheme matches allowed schemes |
92
|
|
|
* - Assert URI host matches defined |
93
|
|
|
* - Assert URI path starts with defined base path |
94
|
|
|
* - Assert URI path matches defined template and path parameters |
95
|
|
|
* - Assert URI path matches defined query parameters |
96
|
|
|
* |
97
|
|
|
* @param Spec $spec |
98
|
|
|
* @param string $template |
99
|
|
|
* @param string $method |
100
|
|
|
* @param Uri $uri |
101
|
|
|
* @param string $msg |
102
|
|
|
*/ |
103
|
3 |
|
final protected static function assertUri(Spec $spec, $template, $method, Uri $uri, $msg = '') |
104
|
|
|
{ |
105
|
3 |
|
Assert::assertThat( |
106
|
|
|
$uri, |
107
|
3 |
|
new UriConstraint( |
108
|
3 |
|
$spec->getSupportedSchemes($template, $method), |
109
|
3 |
|
$spec->getHost(), |
110
|
3 |
|
$spec->getBasePath(), |
111
|
|
|
$template, |
112
|
3 |
|
$spec->getRequestPathParameters($template, $method), |
113
|
3 |
|
$spec->getRequestQueryParameters($template, $method) |
114
|
|
|
), |
115
|
|
|
$msg |
116
|
|
|
); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Assert the endpoint supports given operation. |
121
|
|
|
* |
122
|
|
|
* @param Spec $spec |
123
|
|
|
* @param string $template |
124
|
|
|
* @param string $method |
125
|
|
|
* @param string $msg |
126
|
|
|
*/ |
127
|
4 |
|
final protected static function assertMethodAllowed(Spec $spec, $template, $method, $msg = '') |
128
|
|
|
{ |
129
|
4 |
|
Assert::assertThat( |
130
|
|
|
$method, |
131
|
4 |
|
new MethodsAllowedConstraint($spec->getAllowedMethods($template)), |
132
|
|
|
$msg |
133
|
|
|
); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Assert the response status code defined. |
138
|
|
|
* |
139
|
|
|
* @param Spec $spec |
140
|
|
|
* @param string $template |
141
|
|
|
* @param string $method |
142
|
|
|
* @param string $status |
143
|
|
|
* @param string $msg |
144
|
|
|
*/ |
145
|
3 |
|
final protected static function assertResponseDefined(Spec $spec, $template, $method, $status, $msg = '') |
146
|
|
|
{ |
147
|
3 |
|
Assert::assertTrue( |
148
|
3 |
|
in_array((string) $status, $spec->getResponseCodes($template, strtolower($method)), true), |
149
|
3 |
|
$msg ?: "Operation \"{$method} {$template}\" does not support response code \"{$status}\"" |
150
|
|
|
); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Assert the endpoint supports given operation. |
155
|
|
|
* |
156
|
|
|
* @param Spec $spec |
157
|
|
|
* @param string $template |
158
|
|
|
* @param string $method |
159
|
|
|
* @param string $contentType |
160
|
|
|
* @param string $msg |
161
|
|
|
*/ |
162
|
3 |
|
final protected static function assertRequestContentType(Spec $spec, $template, $method, $contentType, $msg = '') |
163
|
|
|
{ |
164
|
3 |
|
Assert::assertThat( |
165
|
|
|
$contentType, |
166
|
3 |
|
new ContentTypeConstraint($spec->getRequestContentTypes($template, $method)), |
167
|
|
|
$msg |
168
|
|
|
); |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Assert the endpoint supports given operation. |
173
|
|
|
* |
174
|
|
|
* @param Spec $spec |
175
|
|
|
* @param string $template |
176
|
|
|
* @param string $method |
177
|
|
|
* @param string $contentType |
178
|
|
|
* @param string $msg |
179
|
|
|
*/ |
180
|
3 |
|
final protected static function assertResponseContentType(Spec $spec, $template, $method, $contentType, $msg = '') |
181
|
|
|
{ |
182
|
3 |
|
Assert::assertThat( |
183
|
|
|
$contentType, |
184
|
3 |
|
new ContentTypeConstraint($spec->getResponseContentTypes($template, $method)), |
185
|
|
|
$msg |
186
|
|
|
); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* @param Spec $spec |
191
|
|
|
* @param string $template |
192
|
|
|
* @param string $method |
193
|
|
|
* @param array $headers |
194
|
|
|
* @param string $msg |
195
|
|
|
*/ |
196
|
3 |
|
final protected static function assertRequestHeaders(Spec $spec, $template, $method, array $headers, $msg = '') |
197
|
|
|
{ |
198
|
3 |
|
Assert::assertThat( |
199
|
|
|
$headers, |
200
|
3 |
|
new HeadersConstraint($spec->getRequestHeaderSchemas($template, strtolower($method))), |
201
|
|
|
$msg |
202
|
|
|
); |
203
|
|
|
|
204
|
3 |
|
if (isset($headers['Content-Type'][0])) { |
205
|
3 |
|
self::assertRequestContentType( |
206
|
|
|
$spec, |
207
|
|
|
$template, |
208
|
|
|
strtolower($method), |
209
|
3 |
|
$headers['Content-Type'][0], |
210
|
|
|
$msg |
211
|
|
|
); |
212
|
|
|
} |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* @param Spec $spec |
217
|
|
|
* @param string $template |
218
|
|
|
* @param string $method |
219
|
|
|
* @param string $status |
220
|
|
|
* @param array $headers |
221
|
|
|
* @param string $msg |
222
|
|
|
*/ |
223
|
3 |
|
final protected static function assertResponseHeaders(Spec $spec, $template, $method, $status, array $headers, $msg = '') |
224
|
|
|
{ |
225
|
3 |
|
Assert::assertThat( |
226
|
|
|
$headers, |
227
|
3 |
|
new HeadersConstraint( |
228
|
3 |
|
$spec->getResponseHeaderSchemas($template, strtolower($method), $status) |
229
|
|
|
), |
230
|
|
|
$msg |
231
|
|
|
); |
232
|
|
|
|
233
|
3 |
|
if (isset($headers['Content-Type'][0])) { |
234
|
3 |
|
self::assertResponseContentType( |
235
|
|
|
$spec, |
236
|
|
|
$template, |
237
|
|
|
$method, |
238
|
3 |
|
$headers['Content-Type'][0], |
239
|
|
|
$msg |
240
|
|
|
); |
241
|
|
|
} |
242
|
|
|
|
243
|
3 |
|
if (isset($headers['Allow'])) { |
244
|
1 |
|
if (isset($headers['Allow'][0]) && strpos($headers['Allow'][0], ',') !== false) { |
245
|
1 |
|
$headers['Allow'] = preg_split('#\s*,\s*#', $headers['Allow'][0], -1, PREG_SPLIT_NO_EMPTY); |
246
|
|
|
} |
247
|
|
|
|
248
|
1 |
|
Assert::assertThat( |
249
|
1 |
|
$headers['Allow'], |
250
|
1 |
|
new MethodsAllowedConstraint($spec->getAllowedMethods($template)), |
251
|
|
|
$msg |
252
|
|
|
); |
253
|
|
|
} |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* @param Spec $spec |
258
|
|
|
* @param string $template |
259
|
|
|
* @param string $method |
260
|
|
|
* @param Stream|null $body |
261
|
|
|
* @param string $msg |
262
|
|
|
*/ |
263
|
2 |
View Code Duplication |
final protected static function assertRequestBody(Spec $spec, $template, $method, Stream $body = null, $msg = '') |
|
|
|
|
264
|
|
|
{ |
265
|
2 |
|
$schema = $spec->getRequestBodySchema($template, strtolower($method)); |
266
|
|
|
|
267
|
2 |
|
if ($schema) { |
268
|
1 |
|
Assert::assertThat( |
269
|
|
|
json_decode($body), |
270
|
1 |
|
new JsonSchemaConstraint($schema, 'request body'), |
271
|
|
|
$msg |
272
|
|
|
); |
273
|
|
|
} else { |
274
|
1 |
|
Assert::assertEmpty(json_decode($body), $msg); |
275
|
|
|
} |
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
/** |
279
|
|
|
* @param Spec $spec |
280
|
|
|
* @param string $template |
281
|
|
|
* @param string $method |
282
|
|
|
* @param string $status |
283
|
|
|
* @param Stream|null $body |
284
|
|
|
* @param string $msg |
285
|
|
|
*/ |
286
|
3 |
View Code Duplication |
final protected static function assertResponseBody(Spec $spec, $template, $method, $status, Stream $body = null, $msg = '') |
|
|
|
|
287
|
|
|
{ |
288
|
3 |
|
$schema = $spec->getResponseBodySchema($template, strtolower($method), $status); |
289
|
|
|
|
290
|
3 |
|
if ($schema) { |
291
|
2 |
|
Assert::assertThat( |
292
|
|
|
json_decode($body), |
293
|
2 |
|
new JsonSchemaConstraint($schema, 'response body'), |
294
|
|
|
$msg |
295
|
|
|
); |
296
|
|
|
} else { |
297
|
1 |
|
Assert::assertEmpty(json_decode($body), $msg); |
298
|
|
|
} |
299
|
|
|
} |
300
|
|
|
} |
301
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.