feature #39666 [FrameworkBundle][HttpFoundation] add assertResponseFormatSame() (dunglas)

This PR was squashed before being merged into the 5.3-dev branch.

Discussion
----------

[FrameworkBundle][HttpFoundation] add assertResponseFormatSame()

| Q             | A
| ------------- | ---
| Branch?       | 5.x
| Bug fix?      | no
| New feature?  | yes <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | Fix n/a
| License       | MIT
| Doc PR        | todo

Add a new PHPUnit assertion checking the format of the HTTP request.

Example:

```php
namespace App\Tests;

use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\ApiTestCase;
use App\Entity\Book;

class BooksTest extends ApiTestCase
{
    public function testGetCollection(): void
    {
        static::createClient()->request('GET', '/books');
        $this->assertResponseFormatSame('jsonld');
    }
}
```

Commits
-------

8fffa2c6f8 [FrameworkBundle][HttpFoundation] add assertResponseFormatSame()
This commit is contained in:
Fabien Potencier 2021-01-03 09:13:40 +01:00
commit 5e10543cc0
6 changed files with 162 additions and 0 deletions

View File

@ -7,6 +7,7 @@ CHANGELOG
* Added support for configuring PHP error level to log levels
* Added the `dispatcher` option to `debug:event-dispatcher`
* Added the `event_dispatcher.dispatcher` tag
* Added `assertResponseFormatSame()` in `BrowserKitAssertionsTrait`
5.2.0
-----

View File

@ -38,6 +38,11 @@ trait BrowserKitAssertionsTrait
self::assertThatForResponse(new ResponseConstraint\ResponseStatusCodeSame($expectedCode), $message);
}
public static function assertResponseFormatSame(?string $expectedFormat, string $message = ''): void
{
self::assertThatForResponse(new ResponseConstraint\ResponseFormatSame(self::getRequest(), $expectedFormat), $message);
}
public static function assertResponseRedirects(string $expectedLocation = null, int $expectedCode = null, string $message = ''): void
{
$constraint = new ResponseConstraint\ResponseIsRedirected();

View File

@ -23,6 +23,7 @@ use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\HttpFoundation\Cookie as HttpFoundationCookie;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseFormatSame;
class WebTestCaseTest extends TestCase
{
@ -75,6 +76,20 @@ class WebTestCaseTest extends TestCase
$this->getResponseTester(new Response('', 302))->assertResponseRedirects('https://example.com/', 301);
}
public function testAssertResponseFormat()
{
if (!class_exists(ResponseFormatSame::class)) {
$this->markTestSkipped('Too old version of HttpFoundation.');
}
$this->getResponseTester(new Response('', 200, ['Content-Type' => 'application/vnd.myformat']))->assertResponseFormatSame('custom');
$this->getResponseTester(new Response('', 200, ['Content-Type' => 'application/ld+json']))->assertResponseFormatSame('jsonld');
$this->getResponseTester(new Response())->assertResponseFormatSame(null);
$this->expectException(AssertionFailedError::class);
$this->expectExceptionMessage("Failed asserting that the Response format is jsonld.\nHTTP/1.0 200 OK");
$this->getResponseTester(new Response())->assertResponseFormatSame('jsonld');
}
public function testAssertResponseHasHeader()
{
$this->getResponseTester(new Response())->assertResponseHasHeader('Date');
@ -284,6 +299,10 @@ class WebTestCaseTest extends TestCase
$client = $this->createMock(KernelBrowser::class);
$client->expects($this->any())->method('getResponse')->willReturn($response);
$request = new Request();
$request->setFormat('custom', ['application/vnd.myformat']);
$client->expects($this->any())->method('getRequest')->willReturn($request);
return $this->getTester($client);
}

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
5.3.0
-----
* added `ResponseFormatSame` PHPUnit constraint
5.2.0
-----

View File

@ -0,0 +1,71 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation\Test\Constraint;
use PHPUnit\Framework\Constraint\Constraint;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Asserts that the response is in the given format.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
final class ResponseFormatSame extends Constraint
{
private $request;
private $format;
public function __construct(Request $request, ?string $format)
{
$this->request = $request;
$this->format = $format;
}
/**
* {@inheritdoc}
*/
public function toString(): string
{
return 'format is '.($this->format ?? 'null');
}
/**
* @param Response $response
*
* {@inheritdoc}
*/
protected function matches($response): bool
{
return $this->format === $this->request->getFormat($response->headers->get('Content-Type'));
}
/**
* @param Response $response
*
* {@inheritdoc}
*/
protected function failureDescription($response): string
{
return 'the Response '.$this->toString();
}
/**
* @param Response $response
*
* {@inheritdoc}
*/
protected function additionalFailureDescription($response): string
{
return (string) $response;
}
}

View File

@ -0,0 +1,61 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint;
use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\TestFailure;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Test\Constraint\ResponseFormatSame;
/**
* @author Kévin Dunglas <kevin@dunglas.fr>
*/
class ResponseFormatSameTest extends TestCase
{
public function testConstraint()
{
$request = new Request();
$request->setFormat('custom', ['application/vnd.myformat']);
$constraint = new ResponseFormatSame($request, 'custom');
$this->assertTrue($constraint->evaluate(new Response('', 200, ['Content-Type' => 'application/vnd.myformat']), '', true));
$this->assertFalse($constraint->evaluate(new Response(), '', true));
try {
$constraint->evaluate(new Response('', 200, ['Content-Type' => 'application/ld+json']));
} catch (ExpectationFailedException $e) {
$this->assertStringContainsString("Failed asserting that the Response format is custom.\nHTTP/1.0 200 OK", TestFailure::exceptionToString($e));
return;
}
$this->fail();
}
public function testNullFormat()
{
$constraint = new ResponseFormatSame(new Request(), null);
$this->assertTrue($constraint->evaluate(new Response(), '', true));
try {
$constraint->evaluate(new Response('', 200, ['Content-Type' => 'application/ld+json']));
} catch (ExpectationFailedException $e) {
$this->assertStringContainsString("Failed asserting that the Response format is null.\nHTTP/1.0 200 OK", TestFailure::exceptionToString($e));
return;
}
$this->fail();
}
}