BrowserKitAssertionsTrait.php 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Bundle\FrameworkBundle\Test;
  11. use PHPUnit\Framework\Constraint\Constraint;
  12. use PHPUnit\Framework\Constraint\LogicalAnd;
  13. use PHPUnit\Framework\Constraint\LogicalNot;
  14. use PHPUnit\Framework\ExpectationFailedException;
  15. use Symfony\Component\BrowserKit\AbstractBrowser;
  16. use Symfony\Component\BrowserKit\Test\Constraint as BrowserKitConstraint;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\Response;
  19. use Symfony\Component\HttpFoundation\Test\Constraint as ResponseConstraint;
  20. /**
  21. * Ideas borrowed from Laravel Dusk's assertions.
  22. *
  23. * @see https://laravel.com/docs/5.7/dusk#available-assertions
  24. */
  25. trait BrowserKitAssertionsTrait
  26. {
  27. public static function assertResponseIsSuccessful(string $message = ''): void
  28. {
  29. self::assertThatForResponse(new ResponseConstraint\ResponseIsSuccessful(), $message);
  30. }
  31. public static function assertResponseStatusCodeSame(int $expectedCode, string $message = ''): void
  32. {
  33. self::assertThatForResponse(new ResponseConstraint\ResponseStatusCodeSame($expectedCode), $message);
  34. }
  35. public static function assertResponseRedirects(string $expectedLocation = null, int $expectedCode = null, string $message = ''): void
  36. {
  37. $constraint = new ResponseConstraint\ResponseIsRedirected();
  38. if ($expectedLocation) {
  39. $constraint = LogicalAnd::fromConstraints($constraint, new ResponseConstraint\ResponseHeaderSame('Location', $expectedLocation));
  40. }
  41. if ($expectedCode) {
  42. $constraint = LogicalAnd::fromConstraints($constraint, new ResponseConstraint\ResponseStatusCodeSame($expectedCode));
  43. }
  44. self::assertThatForResponse($constraint, $message);
  45. }
  46. public static function assertResponseHasHeader(string $headerName, string $message = ''): void
  47. {
  48. self::assertThatForResponse(new ResponseConstraint\ResponseHasHeader($headerName), $message);
  49. }
  50. public static function assertResponseNotHasHeader(string $headerName, string $message = ''): void
  51. {
  52. self::assertThatForResponse(new LogicalNot(new ResponseConstraint\ResponseHasHeader($headerName)), $message);
  53. }
  54. public static function assertResponseHeaderSame(string $headerName, string $expectedValue, string $message = ''): void
  55. {
  56. self::assertThatForResponse(new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue), $message);
  57. }
  58. public static function assertResponseHeaderNotSame(string $headerName, string $expectedValue, string $message = ''): void
  59. {
  60. self::assertThatForResponse(new LogicalNot(new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue)), $message);
  61. }
  62. public static function assertResponseHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void
  63. {
  64. self::assertThatForResponse(new ResponseConstraint\ResponseHasCookie($name, $path, $domain), $message);
  65. }
  66. public static function assertResponseNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void
  67. {
  68. self::assertThatForResponse(new LogicalNot(new ResponseConstraint\ResponseHasCookie($name, $path, $domain)), $message);
  69. }
  70. public static function assertResponseCookieValueSame(string $name, string $expectedValue, string $path = '/', string $domain = null, string $message = ''): void
  71. {
  72. self::assertThatForResponse(LogicalAnd::fromConstraints(
  73. new ResponseConstraint\ResponseHasCookie($name, $path, $domain),
  74. new ResponseConstraint\ResponseCookieValueSame($name, $expectedValue, $path, $domain)
  75. ), $message);
  76. }
  77. public static function assertBrowserHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void
  78. {
  79. self::assertThat(self::getClient(), new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), $message);
  80. }
  81. public static function assertBrowserNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void
  82. {
  83. self::assertThat(self::getClient(), new LogicalNot(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain)), $message);
  84. }
  85. public static function assertBrowserCookieValueSame(string $name, string $expectedValue, bool $raw = false, string $path = '/', string $domain = null, string $message = ''): void
  86. {
  87. self::assertThat(self::getClient(), LogicalAnd::fromConstraints(
  88. new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain),
  89. new BrowserKitConstraint\BrowserCookieValueSame($name, $expectedValue, $raw, $path, $domain)
  90. ), $message);
  91. }
  92. public static function assertRequestAttributeValueSame(string $name, string $expectedValue, string $message = ''): void
  93. {
  94. self::assertThat(self::getRequest(), new ResponseConstraint\RequestAttributeValueSame($name, $expectedValue), $message);
  95. }
  96. public static function assertRouteSame($expectedRoute, array $parameters = [], string $message = ''): void
  97. {
  98. $constraint = new ResponseConstraint\RequestAttributeValueSame('_route', $expectedRoute);
  99. $constraints = [];
  100. foreach ($parameters as $key => $value) {
  101. $constraints[] = new ResponseConstraint\RequestAttributeValueSame($key, $value);
  102. }
  103. if ($constraints) {
  104. $constraint = LogicalAnd::fromConstraints($constraint, ...$constraints);
  105. }
  106. self::assertThat(self::getRequest(), $constraint, $message);
  107. }
  108. public static function assertThatForResponse(Constraint $constraint, string $message = ''): void
  109. {
  110. try {
  111. self::assertThat(self::getResponse(), $constraint, $message);
  112. } catch (ExpectationFailedException $exception) {
  113. if (($serverExceptionMessage = self::getResponse()->headers->get('X-Debug-Exception'))
  114. && ($serverExceptionFile = self::getResponse()->headers->get('X-Debug-Exception-File'))) {
  115. $serverExceptionFile = explode(':', $serverExceptionFile);
  116. $exception->__construct($exception->getMessage(), $exception->getComparisonFailure(), new \ErrorException(rawurldecode($serverExceptionMessage), 0, 1, rawurldecode($serverExceptionFile[0]), $serverExceptionFile[1]), $exception->getPrevious());
  117. }
  118. throw $exception;
  119. }
  120. }
  121. private static function getClient(AbstractBrowser $newClient = null): ?AbstractBrowser
  122. {
  123. static $client;
  124. if (0 < \func_num_args()) {
  125. return $client = $newClient;
  126. }
  127. if (!$client instanceof AbstractBrowser) {
  128. static::fail(sprintf('A client must be set to make assertions on it. Did you forget to call "%s::createClient()"?', __CLASS__));
  129. }
  130. return $client;
  131. }
  132. private static function getResponse(): Response
  133. {
  134. if (!$response = self::getClient()->getResponse()) {
  135. static::fail('A client must have an HTTP Response to make assertions. Did you forget to make an HTTP request?');
  136. }
  137. return $response;
  138. }
  139. private static function getRequest(): Request
  140. {
  141. if (!$request = self::getClient()->getRequest()) {
  142. static::fail('A client must have an HTTP Request to make assertions. Did you forget to make an HTTP request?');
  143. }
  144. return $request;
  145. }
  146. }