11
11
12
12
namespace Symfony \Bundle \FrameworkBundle \Tests \Functional ;
13
13
14
+ use Symfony \Component \DomCrawler \Crawler ;
14
15
use Symfony \Component \HttpFoundation \JsonResponse ;
15
16
use Symfony \Component \HttpFoundation \Request ;
16
17
use Symfony \Component \HttpFoundation \Response ;
@@ -89,15 +90,14 @@ public static function mapQueryStringProvider(): iterable
89
90
/**
90
91
* @dataProvider mapRequestPayloadProvider
91
92
*/
92
- public function testMapRequestPayload (string $ format , array $ parameters , ?string $ content , string $ expectedResponse , int $ expectedStatusCode )
93
+ public function testMapRequestPayload (string $ format , array $ parameters , ?string $ content , callable $ responseAssertion , int $ expectedStatusCode )
93
94
{
94
95
$ client = self ::createClient (['test_case ' => 'ApiAttributesTest ' ]);
95
96
96
- [$ acceptHeader , $ assertion ] = [
97
- 'html ' => ['text/html ' , self ::assertStringContainsString (...)],
98
- 'json ' => ['application/json ' , self ::assertJsonStringEqualsJsonString (...)],
99
- 'xml ' => ['text/xml ' , self ::assertXmlStringEqualsXmlString (...)],
100
- 'dummy ' => ['application/dummy ' , self ::assertStringContainsString (...)],
97
+ $ acceptHeader = [
98
+ 'json ' => 'application/json ' ,
99
+ 'xml ' => 'text/xml ' ,
100
+ 'dummy ' => 'application/dummy ' ,
101
101
][$ format ];
102
102
103
103
$ client ->request (
@@ -111,12 +111,7 @@ public function testMapRequestPayload(string $format, array $parameters, ?string
111
111
112
112
$ response = $ client ->getResponse ();
113
113
$ responseContent = $ response ->getContent ();
114
-
115
- if ($ expectedResponse ) {
116
- $ assertion ($ expectedResponse , $ responseContent );
117
- } else {
118
- self ::assertSame ('' , $ responseContent );
119
- }
114
+ $ responseAssertion ($ responseContent );
120
115
121
116
self ::assertSame ($ expectedStatusCode , $ response ->getStatusCode ());
122
117
}
@@ -127,7 +122,9 @@ public static function mapRequestPayloadProvider(): iterable
127
122
'format ' => 'json ' ,
128
123
'parameters ' => [],
129
124
'content ' => '' ,
130
- 'expectedResponse ' => '' ,
125
+ 'responseAssertion ' => static function (string $ response ) {
126
+ self ::assertSame ('' , $ response );
127
+ },
131
128
'expectedStatusCode ' => 204 ,
132
129
];
133
130
@@ -140,12 +137,16 @@ public static function mapRequestPayloadProvider(): iterable
140
137
"approved": false
141
138
}
142
139
JSON,
143
- 'expectedResponse ' => <<<'JSON'
144
- {
145
- "comment": "Hello everyone!",
146
- "approved": false
147
- }
148
- JSON,
140
+ 'responseAssertion ' => static function (string $ response ) {
141
+ self ::assertJsonStringEqualsJsonString (<<<'JSON'
142
+ {
143
+ "comment": "Hello everyone!",
144
+ "approved": false
145
+ }
146
+ JSON,
147
+ $ response
148
+ );
149
+ },
149
150
'expectedStatusCode ' => 200 ,
150
151
];
151
152
@@ -158,22 +159,28 @@ public static function mapRequestPayloadProvider(): iterable
158
159
"approved": false,
159
160
}
160
161
JSON,
161
- 'expectedResponse ' => <<<'JSON'
162
- {
163
- "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10",
164
- "title": "An error occurred",
165
- "status": 400,
166
- "detail": "Bad Request"
167
- }
168
- JSON,
162
+ 'responseAssertion ' => static function (string $ response ) {
163
+ self ::assertJsonStringEqualsJsonString (<<<'JSON'
164
+ {
165
+ "type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10",
166
+ "title": "An error occurred",
167
+ "status": 400,
168
+ "detail": "Bad Request"
169
+ }
170
+ JSON,
171
+ $ response
172
+ );
173
+ },
169
174
'expectedStatusCode ' => 400 ,
170
175
];
171
176
172
177
yield 'unsupported format ' => [
173
178
'format ' => 'dummy ' ,
174
179
'parameters ' => [],
175
180
'content ' => 'Hello ' ,
176
- 'expectedResponse ' => '415 Unsupported Media Type ' ,
181
+ 'responseAssertion ' => static function (string $ response ) {
182
+ self ::assertStringContainsString ('415 Unsupported Media Type ' , $ response );
183
+ },
177
184
'expectedStatusCode ' => 415 ,
178
185
];
179
186
@@ -186,12 +193,16 @@ public static function mapRequestPayloadProvider(): iterable
186
193
<approved>true</approved>
187
194
</request>
188
195
XML,
189
- 'expectedResponse ' => <<<'XML'
190
- <response>
191
- <comment>Hello everyone!</comment>
192
- <approved>1</approved>
193
- </response>
194
- XML,
196
+ 'responseAssertion ' => static function (string $ response ) {
197
+ self ::assertXmlStringEqualsXmlString (<<<'XML'
198
+ <response>
199
+ <comment>Hello everyone!</comment>
200
+ <approved>1</approved>
201
+ </response>
202
+ XML,
203
+ $ response
204
+ );
205
+ },
195
206
'expectedStatusCode ' => 200 ,
196
207
];
197
208
@@ -204,24 +215,28 @@ public static function mapRequestPayloadProvider(): iterable
204
215
"approved": "string instead of bool"
205
216
}
206
217
JSON,
207
- 'expectedResponse ' => <<<'JSON'
208
- {
209
- "type": "https:\/\/symfony.com\/errors\/validation",
210
- "title": "Validation Failed",
211
- "status": 422,
212
- "detail": "approved: This value should be of type bool.",
213
- "violations": [
214
- {
215
- "propertyPath": "approved",
216
- "title": "This value should be of type bool.",
217
- "template": "This value should be of type {{ type }}.",
218
- "parameters": {
219
- "{{ type }}": "bool"
218
+ 'responseAssertion ' => static function (string $ response ) {
219
+ self ::assertJsonStringEqualsJsonString (<<<'JSON'
220
+ {
221
+ "type": "https:\/\/symfony.com\/errors\/validation",
222
+ "title": "Validation Failed",
223
+ "status": 422,
224
+ "detail": "approved: This value should be of type bool.",
225
+ "violations": [
226
+ {
227
+ "propertyPath": "approved",
228
+ "title": "This value should be of type bool.",
229
+ "template": "This value should be of type {{ type }}.",
230
+ "parameters": {
231
+ "{{ type }}": "bool"
232
+ }
220
233
}
221
- }
222
- ]
223
- }
224
- JSON,
234
+ ]
235
+ }
236
+ JSON,
237
+ $ response
238
+ );
239
+ },
225
240
'expectedStatusCode ' => 422 ,
226
241
];
227
242
@@ -234,36 +249,20 @@ public static function mapRequestPayloadProvider(): iterable
234
249
"approved": true
235
250
}
236
251
JSON,
237
- 'expectedResponse ' => <<<'JSON'
238
- {
239
- "type": "https:\/\/symfony.com\/errors\/validation",
240
- "title": "Validation Failed",
241
- "status": 422,
242
- "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.",
243
- "violations": [
244
- {
245
- "propertyPath": "comment",
246
- "title": "This value should not be blank.",
247
- "template": "This value should not be blank.",
248
- "parameters": {
249
- "{{ value }}": "\"\""
250
- },
251
- "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3"
252
- },
253
- {
254
- "propertyPath": "comment",
255
- "title": "This value is too short. It should have 10 characters or more.",
256
- "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.",
257
- "parameters": {
258
- "{{ value }}": "\"\"",
259
- "{{ limit }}": "10",
260
- "{{ value_length }}": "0"
261
- },
262
- "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45"
263
- }
264
- ]
265
- }
266
- JSON,
252
+ 'responseAssertion ' => static function (string $ response ) {
253
+ self ::assertJson ($ response );
254
+
255
+ $ json = json_decode ($ response , true );
256
+
257
+ self ::assertSame ('https://symfony.com/errors/validation ' , $ json ['type ' ] ?? null );
258
+ self ::assertSame ('Validation Failed ' , $ json ['title ' ] ?? null );
259
+ self ::assertSame (422 , $ json ['status ' ] ?? null );
260
+ self ::assertSame ("comment: This value should not be blank. \ncomment: This value is too short. It should have 10 characters or more. " , $ json ['detail ' ] ?? null );
261
+ self ::assertIsArray ($ json ['violations ' ] ?? null );
262
+ self ::assertCount (2 , $ json ['violations ' ]);
263
+ self ::assertSame ('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3 ' , $ json ['violations ' ][0 ]['type ' ] ?? null );
264
+ self ::assertSame ('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45 ' , $ json ['violations ' ][1 ]['type ' ] ?? null );
265
+ },
267
266
'expectedStatusCode ' => 422 ,
268
267
];
269
268
@@ -276,76 +275,54 @@ public static function mapRequestPayloadProvider(): iterable
276
275
<approved>false</approved>
277
276
</request>
278
277
XML,
279
- 'expectedResponse ' => <<<'XML'
280
- <?xml version="1.0"?>
281
- <response>
282
- <type>https://symfony.com/errors/validation</type>
283
- <title>Validation Failed</title>
284
- <status>422</status>
285
- <detail>comment: This value is too short. It should have 10 characters or more.</detail>
286
- <violations>
287
- <propertyPath>comment</propertyPath>
288
- <title>This value is too short. It should have 10 characters or more.</title>
289
- <template>This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.</template>
290
- <parameters>
291
- <item key="{{ value }}">"H"</item>
292
- <item key="{{ limit }}">10</item>
293
- <item key="{{ value_length }}">1</item>
294
- </parameters>
295
- <type>urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45</type>
296
- </violations>
297
- </response>
298
- XML,
278
+ 'responseAssertion ' => static function (string $ response ) {
279
+ $ crawler = new Crawler ($ response );
280
+
281
+ self ::assertSame ('https://symfony.com/errors/validation ' , $ crawler ->filterXPath ('response/type ' )->text ());
282
+ self ::assertSame ('Validation Failed ' , $ crawler ->filterXPath ('response/title ' )->text ());
283
+ self ::assertSame ('422 ' , $ crawler ->filterXPath ('response/status ' )->text ());
284
+ self ::assertSame ('comment: This value is too short. It should have 10 characters or more. ' , $ crawler ->filterXPath ('response/detail ' )->text ());
285
+ self ::assertCount (1 , $ crawler ->filterXPath ('response/violations ' ));
286
+ self ::assertSame ('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45 ' , $ crawler ->filterXPath ('response/violations/type ' )->text ());
287
+ },
299
288
'expectedStatusCode ' => 422 ,
300
289
];
301
290
302
291
yield 'valid input ' => [
303
292
'format ' => 'json ' ,
304
293
'input ' => ['comment ' => 'Hello everyone! ' , 'approved ' => '0 ' ],
305
294
'content ' => null ,
306
- 'expectedResponse ' => <<<'JSON'
307
- {
308
- "comment": "Hello everyone!",
309
- "approved": false
310
- }
311
- JSON,
295
+ 'responseAssertion ' => static function (string $ response ) {
296
+ self ::assertJsonStringEqualsJsonString (<<<'JSON'
297
+ {
298
+ "comment": "Hello everyone!",
299
+ "approved": false
300
+ }
301
+ JSON,
302
+ $ response
303
+ );
304
+ },
312
305
'expectedStatusCode ' => 200 ,
313
306
];
314
307
315
308
yield 'validation error input ' => [
316
309
'format ' => 'json ' ,
317
310
'input ' => ['comment ' => '' , 'approved ' => '1 ' ],
318
311
'content ' => null ,
319
- 'expectedResponse ' => <<<'JSON'
320
- {
321
- "type": "https:\/\/symfony.com\/errors\/validation",
322
- "title": "Validation Failed",
323
- "status": 422,
324
- "detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.",
325
- "violations": [
326
- {
327
- "propertyPath": "comment",
328
- "title": "This value should not be blank.",
329
- "template": "This value should not be blank.",
330
- "parameters": {
331
- "{{ value }}": "\"\""
332
- },
333
- "type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3"
334
- },
335
- {
336
- "propertyPath": "comment",
337
- "title": "This value is too short. It should have 10 characters or more.",
338
- "template": "This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more.",
339
- "parameters": {
340
- "{{ value }}": "\"\"",
341
- "{{ limit }}": "10",
342
- "{{ value_length }}": "0"
343
- },
344
- "type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45"
345
- }
346
- ]
347
- }
348
- JSON,
312
+ 'responseAssertion ' => static function (string $ response ) {
313
+ self ::assertJson ($ response );
314
+
315
+ $ json = json_decode ($ response , true );
316
+
317
+ self ::assertSame ('https://symfony.com/errors/validation ' , $ json ['type ' ] ?? null );
318
+ self ::assertSame ('Validation Failed ' , $ json ['title ' ] ?? null );
319
+ self ::assertSame (422 , $ json ['status ' ] ?? null );
320
+ self ::assertSame ("comment: This value should not be blank. \ncomment: This value is too short. It should have 10 characters or more. " , $ json ['detail ' ] ?? null );
321
+ self ::assertIsArray ($ json ['violations ' ] ?? null );
322
+ self ::assertCount (2 , $ json ['violations ' ]);
323
+ self ::assertSame ('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3 ' , $ json ['violations ' ][0 ]['type ' ] ?? null );
324
+ self ::assertSame ('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45 ' , $ json ['violations ' ][1 ]['type ' ] ?? null );
325
+ },
349
326
'expectedStatusCode ' => 422 ,
350
327
];
351
328
}
0 commit comments