Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
251 changes: 114 additions & 137 deletions src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ApiAttributesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;

use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
Expand Down Expand Up @@ -89,15 +90,14 @@ public static function mapQueryStringProvider(): iterable
/**
* @dataProvider mapRequestPayloadProvider
*/
public function testMapRequestPayload(string $format, array $parameters, ?string $content, string $expectedResponse, int $expectedStatusCode)
public function testMapRequestPayload(string $format, array $parameters, ?string $content, callable $responseAssertion, int $expectedStatusCode)
{
$client = self::createClient(['test_case' => 'ApiAttributesTest']);

[$acceptHeader, $assertion] = [
'html' => ['text/html', self::assertStringContainsString(...)],
'json' => ['application/json', self::assertJsonStringEqualsJsonString(...)],
'xml' => ['text/xml', self::assertXmlStringEqualsXmlString(...)],
'dummy' => ['application/dummy', self::assertStringContainsString(...)],
$acceptHeader = [
'json' => 'application/json',
'xml' => 'text/xml',
'dummy' => 'application/dummy',
][$format];

$client->request(
Expand All @@ -111,12 +111,7 @@ public function testMapRequestPayload(string $format, array $parameters, ?string

$response = $client->getResponse();
$responseContent = $response->getContent();

if ($expectedResponse) {
$assertion($expectedResponse, $responseContent);
} else {
self::assertSame('', $responseContent);
}
$responseAssertion($responseContent);

self::assertSame($expectedStatusCode, $response->getStatusCode());
}
Expand All @@ -127,7 +122,9 @@ public static function mapRequestPayloadProvider(): iterable
'format' => 'json',
'parameters' => [],
'content' => '',
'expectedResponse' => '',
'responseAssertion' => static function (string $response) {
self::assertSame('', $response);
},
'expectedStatusCode' => 204,
];

Expand All @@ -140,12 +137,16 @@ public static function mapRequestPayloadProvider(): iterable
"approved": false
}
JSON,
'expectedResponse' => <<<'JSON'
{
"comment": "Hello everyone!",
"approved": false
}
JSON,
'responseAssertion' => static function (string $response) {
self::assertJsonStringEqualsJsonString(<<<'JSON'
{
"comment": "Hello everyone!",
"approved": false
}
JSON,
$response
);
},
'expectedStatusCode' => 200,
];

Expand All @@ -158,22 +159,28 @@ public static function mapRequestPayloadProvider(): iterable
"approved": false,
}
JSON,
'expectedResponse' => <<<'JSON'
{
"type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10",
"title": "An error occurred",
"status": 400,
"detail": "Bad Request"
}
JSON,
'responseAssertion' => static function (string $response) {
self::assertJsonStringEqualsJsonString(<<<'JSON'
{
"type": "https:\/\/tools.ietf.org\/html\/rfc2616#section-10",
"title": "An error occurred",
"status": 400,
"detail": "Bad Request"
}
JSON,
$response
);
},
'expectedStatusCode' => 400,
];

yield 'unsupported format' => [
'format' => 'dummy',
'parameters' => [],
'content' => 'Hello',
'expectedResponse' => '415 Unsupported Media Type',
'responseAssertion' => static function (string $response) {
self::assertStringContainsString('415 Unsupported Media Type', $response);
},
'expectedStatusCode' => 415,
];

Expand All @@ -186,12 +193,16 @@ public static function mapRequestPayloadProvider(): iterable
<approved>true</approved>
</request>
XML,
'expectedResponse' => <<<'XML'
<response>
<comment>Hello everyone!</comment>
<approved>1</approved>
</response>
XML,
'responseAssertion' => static function (string $response) {
self::assertXmlStringEqualsXmlString(<<<'XML'
<response>
<comment>Hello everyone!</comment>
<approved>1</approved>
</response>
XML,
$response
);
},
'expectedStatusCode' => 200,
];

Expand All @@ -204,24 +215,28 @@ public static function mapRequestPayloadProvider(): iterable
"approved": "string instead of bool"
}
JSON,
'expectedResponse' => <<<'JSON'
{
"type": "https:\/\/symfony.com\/errors\/validation",
"title": "Validation Failed",
"status": 422,
"detail": "approved: This value should be of type bool.",
"violations": [
{
"propertyPath": "approved",
"title": "This value should be of type bool.",
"template": "This value should be of type {{ type }}.",
"parameters": {
"{{ type }}": "bool"
'responseAssertion' => static function (string $response) {
self::assertJsonStringEqualsJsonString(<<<'JSON'
{
"type": "https:\/\/symfony.com\/errors\/validation",
"title": "Validation Failed",
"status": 422,
"detail": "approved: This value should be of type bool.",
"violations": [
{
"propertyPath": "approved",
"title": "This value should be of type bool.",
"template": "This value should be of type {{ type }}.",
"parameters": {
"{{ type }}": "bool"
}
}
}
]
}
JSON,
]
}
JSON,
$response
);
},
'expectedStatusCode' => 422,
];

Expand All @@ -234,36 +249,20 @@ public static function mapRequestPayloadProvider(): iterable
"approved": true
}
JSON,
'expectedResponse' => <<<'JSON'
{
"type": "https:\/\/symfony.com\/errors\/validation",
"title": "Validation Failed",
"status": 422,
"detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.",
"violations": [
{
"propertyPath": "comment",
"title": "This value should not be blank.",
"template": "This value should not be blank.",
"parameters": {
"{{ value }}": "\"\""
},
"type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3"
},
{
"propertyPath": "comment",
"title": "This value is too short. It should have 10 characters or more.",
"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.",
"parameters": {
"{{ value }}": "\"\"",
"{{ limit }}": "10",
"{{ value_length }}": "0"
},
"type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45"
}
]
}
JSON,
'responseAssertion' => static function (string $response) {
self::assertJson($response);

$json = json_decode($response, true);

self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null);
self::assertSame('Validation Failed', $json['title'] ?? null);
self::assertSame(422, $json['status'] ?? null);
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);
self::assertIsArray($json['violations'] ?? null);
self::assertCount(2, $json['violations']);
self::assertSame('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3', $json['violations'][0]['type'] ?? null);
self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $json['violations'][1]['type'] ?? null);
},
'expectedStatusCode' => 422,
];

Expand All @@ -276,76 +275,54 @@ public static function mapRequestPayloadProvider(): iterable
<approved>false</approved>
</request>
XML,
'expectedResponse' => <<<'XML'
<?xml version="1.0"?>
<response>
<type>https://symfony.com/errors/validation</type>
<title>Validation Failed</title>
<status>422</status>
<detail>comment: This value is too short. It should have 10 characters or more.</detail>
<violations>
<propertyPath>comment</propertyPath>
<title>This value is too short. It should have 10 characters or more.</title>
<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>
<parameters>
<item key="{{ value }}">"H"</item>
<item key="{{ limit }}">10</item>
<item key="{{ value_length }}">1</item>
</parameters>
<type>urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45</type>
</violations>
</response>
XML,
'responseAssertion' => static function (string $response) {
$crawler = new Crawler($response);

self::assertSame('https://symfony.com/errors/validation', $crawler->filterXPath('response/type')->text());
self::assertSame('Validation Failed', $crawler->filterXPath('response/title')->text());
self::assertSame('422', $crawler->filterXPath('response/status')->text());
self::assertSame('comment: This value is too short. It should have 10 characters or more.', $crawler->filterXPath('response/detail')->text());
self::assertCount(1, $crawler->filterXPath('response/violations'));
self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $crawler->filterXPath('response/violations/type')->text());
},
'expectedStatusCode' => 422,
];

yield 'valid input' => [
'format' => 'json',
'input' => ['comment' => 'Hello everyone!', 'approved' => '0'],
'content' => null,
'expectedResponse' => <<<'JSON'
{
"comment": "Hello everyone!",
"approved": false
}
JSON,
'responseAssertion' => static function (string $response) {
self::assertJsonStringEqualsJsonString(<<<'JSON'
{
"comment": "Hello everyone!",
"approved": false
}
JSON,
$response
);
},
'expectedStatusCode' => 200,
];

yield 'validation error input' => [
'format' => 'json',
'input' => ['comment' => '', 'approved' => '1'],
'content' => null,
'expectedResponse' => <<<'JSON'
{
"type": "https:\/\/symfony.com\/errors\/validation",
"title": "Validation Failed",
"status": 422,
"detail": "comment: This value should not be blank.\ncomment: This value is too short. It should have 10 characters or more.",
"violations": [
{
"propertyPath": "comment",
"title": "This value should not be blank.",
"template": "This value should not be blank.",
"parameters": {
"{{ value }}": "\"\""
},
"type": "urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3"
},
{
"propertyPath": "comment",
"title": "This value is too short. It should have 10 characters or more.",
"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.",
"parameters": {
"{{ value }}": "\"\"",
"{{ limit }}": "10",
"{{ value_length }}": "0"
},
"type": "urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45"
}
]
}
JSON,
'responseAssertion' => static function (string $response) {
self::assertJson($response);

$json = json_decode($response, true);

self::assertSame('https://symfony.com/errors/validation', $json['type'] ?? null);
self::assertSame('Validation Failed', $json['title'] ?? null);
self::assertSame(422, $json['status'] ?? null);
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);
self::assertIsArray($json['violations'] ?? null);
self::assertCount(2, $json['violations']);
self::assertSame('urn:uuid:c1051bb4-d103-4f74-8988-acbcafc7fdc3', $json['violations'][0]['type'] ?? null);
self::assertSame('urn:uuid:9ff3fdc4-b214-49db-8718-39c315e33d45', $json['violations'][1]['type'] ?? null);
},
'expectedStatusCode' => 422,
];
}
Expand Down
Loading