3 use \Illuminate\Foundation\Testing\TestResponse as BaseTestResponse;
4 use Symfony\Component\DomCrawler\Crawler;
5 use PHPUnit\Framework\Assert as PHPUnit;
9 * Custom extension of the default Laravel TestResponse class.
12 class TestResponse extends BaseTestResponse {
14 protected $crawlerInstance;
17 * Get the DOM Crawler for the response content.
19 protected function crawler(): Crawler
21 if (!is_object($this->crawlerInstance)) {
22 $this->crawlerInstance = new Crawler($this->getContent());
24 return $this->crawlerInstance;
28 * Assert the response contains the specified element.
31 public function assertElementExists(string $selector)
33 $elements = $this->crawler()->filter($selector);
35 $elements->count() > 0,
36 'Unable to find element matching the selector: '.PHP_EOL.PHP_EOL.
37 "[{$selector}]".PHP_EOL.PHP_EOL.
38 'within'.PHP_EOL.PHP_EOL.
39 "[{$this->getContent()}]."
45 * Assert the response does not contain the specified element.
48 public function assertElementNotExists(string $selector)
50 $elements = $this->crawler()->filter($selector);
52 $elements->count() === 0,
53 'Found elements matching the selector: '.PHP_EOL.PHP_EOL.
54 "[{$selector}]".PHP_EOL.PHP_EOL.
55 'within'.PHP_EOL.PHP_EOL.
56 "[{$this->getContent()}]."
62 * Assert the response includes a specific element containing the given text.
63 * If an nth match is provided, only that will be checked otherwise all matching
64 * elements will be checked for the given text.
67 public function assertElementContains(string $selector, string $text, ?int $nthMatch = null)
69 $elements = $this->crawler()->filter($selector);
71 $pattern = $this->getEscapedPattern($text);
73 if (!is_null($nthMatch)) {
74 $elements = $elements->eq($nthMatch - 1);
77 foreach ($elements as $element) {
78 $element = new Crawler($element);
79 if (preg_match("/$pattern/i", $element->html())) {
87 'Unable to find element of selector: '.PHP_EOL.PHP_EOL.
88 ($nthMatch ? ("at position {$nthMatch}".PHP_EOL.PHP_EOL) : '') .
89 "[{$selector}]".PHP_EOL.PHP_EOL.
90 'containing text'.PHP_EOL.PHP_EOL.
91 "[{$text}]".PHP_EOL.PHP_EOL.
92 'within'.PHP_EOL.PHP_EOL.
93 "[{$this->getContent()}]."
100 * Assert the response does not include a specific element containing the given text.
101 * If an nth match is provided, only that will be checked otherwise all matching
102 * elements will be checked for the given text.
105 public function assertElementNotContains(string $selector, string $text, ?int $nthMatch = null)
107 $elements = $this->crawler()->filter($selector);
109 $pattern = $this->getEscapedPattern($text);
111 if (!is_null($nthMatch)) {
112 $elements = $elements->eq($nthMatch - 1);
115 foreach ($elements as $element) {
116 $element = new Crawler($element);
117 if (preg_match("/$pattern/i", $element->html())) {
125 'Found element of selector: '.PHP_EOL.PHP_EOL.
126 ($nthMatch ? ("at position {$nthMatch}".PHP_EOL.PHP_EOL) : '') .
127 "[{$selector}]".PHP_EOL.PHP_EOL.
128 'containing text'.PHP_EOL.PHP_EOL.
129 "[{$text}]".PHP_EOL.PHP_EOL.
130 'within'.PHP_EOL.PHP_EOL.
131 "[{$this->getContent()}]."
138 * Assert there's a notification within the view containing the given text.
141 public function assertNotificationContains(string $text)
143 return $this->assertElementContains('[notification]', $text);
147 * Get the escaped text pattern for the constraint.
150 protected function getEscapedPattern(string $text)
152 $rawPattern = preg_quote($text, '/');
153 $escapedPattern = preg_quote(e($text), '/');
154 return $rawPattern == $escapedPattern
155 ? $rawPattern : "({$rawPattern}|{$escapedPattern})";