]> BookStack Code Mirror - bookstack/blob - tests/TestResponse.php
Merge pull request #2868 from ffranchina/master
[bookstack] / tests / TestResponse.php
1 <?php
2
3 namespace Tests;
4
5 use Illuminate\Foundation\Testing\TestResponse as BaseTestResponse;
6 use PHPUnit\Framework\Assert as PHPUnit;
7 use Symfony\Component\DomCrawler\Crawler;
8
9 /**
10  * Class TestResponse
11  * Custom extension of the default Laravel TestResponse class.
12  */
13 class TestResponse extends BaseTestResponse
14 {
15     protected $crawlerInstance;
16
17     /**
18      * Get the DOM Crawler for the response content.
19      */
20     protected function crawler(): Crawler
21     {
22         if (!is_object($this->crawlerInstance)) {
23             $this->crawlerInstance = new Crawler($this->getContent());
24         }
25
26         return $this->crawlerInstance;
27     }
28
29     /**
30      * Get the HTML of the first element at the given selector.
31      */
32     public function getElementHtml(string $selector): string
33     {
34         return $this->crawler()->filter($selector)->first()->outerHtml();
35     }
36
37     /**
38      * Assert the response contains the specified element.
39      *
40      * @return $this
41      */
42     public function assertElementExists(string $selector)
43     {
44         $elements = $this->crawler()->filter($selector);
45         PHPUnit::assertTrue(
46             $elements->count() > 0,
47             'Unable to find element matching the selector: ' . PHP_EOL . PHP_EOL .
48             "[{$selector}]" . PHP_EOL . PHP_EOL .
49             'within' . PHP_EOL . PHP_EOL .
50             "[{$this->getContent()}]."
51         );
52
53         return $this;
54     }
55
56     /**
57      * Assert the response does not contain the specified element.
58      *
59      * @return $this
60      */
61     public function assertElementNotExists(string $selector)
62     {
63         $elements = $this->crawler()->filter($selector);
64         PHPUnit::assertTrue(
65             $elements->count() === 0,
66             'Found elements matching the selector: ' . PHP_EOL . PHP_EOL .
67             "[{$selector}]" . PHP_EOL . PHP_EOL .
68             'within' . PHP_EOL . PHP_EOL .
69             "[{$this->getContent()}]."
70         );
71
72         return $this;
73     }
74
75     /**
76      * Assert the response includes a specific element containing the given text.
77      * If an nth match is provided, only that will be checked otherwise all matching
78      * elements will be checked for the given text.
79      *
80      * @return $this
81      */
82     public function assertElementContains(string $selector, string $text, ?int $nthMatch = null)
83     {
84         $elements = $this->crawler()->filter($selector);
85         $matched = false;
86         $pattern = $this->getEscapedPattern($text);
87
88         if (!is_null($nthMatch)) {
89             $elements = $elements->eq($nthMatch - 1);
90         }
91
92         foreach ($elements as $element) {
93             $element = new Crawler($element);
94             if (preg_match("/$pattern/i", $element->html())) {
95                 $matched = true;
96                 break;
97             }
98         }
99
100         PHPUnit::assertTrue(
101             $matched,
102             'Unable to find element of selector: ' . PHP_EOL . PHP_EOL .
103             ($nthMatch ? ("at position {$nthMatch}" . PHP_EOL . PHP_EOL) : '') .
104             "[{$selector}]" . PHP_EOL . PHP_EOL .
105             'containing text' . PHP_EOL . PHP_EOL .
106             "[{$text}]" . PHP_EOL . PHP_EOL .
107             'within' . PHP_EOL . PHP_EOL .
108             "[{$this->getContent()}]."
109         );
110
111         return $this;
112     }
113
114     /**
115      * Assert the response does not include a specific element containing the given text.
116      * If an nth match is provided, only that will be checked otherwise all matching
117      * elements will be checked for the given text.
118      *
119      * @return $this
120      */
121     public function assertElementNotContains(string $selector, string $text, ?int $nthMatch = null)
122     {
123         $elements = $this->crawler()->filter($selector);
124         $matched = false;
125         $pattern = $this->getEscapedPattern($text);
126
127         if (!is_null($nthMatch)) {
128             $elements = $elements->eq($nthMatch - 1);
129         }
130
131         foreach ($elements as $element) {
132             $element = new Crawler($element);
133             if (preg_match("/$pattern/i", $element->html())) {
134                 $matched = true;
135                 break;
136             }
137         }
138
139         PHPUnit::assertTrue(
140             !$matched,
141             'Found element of selector: ' . PHP_EOL . PHP_EOL .
142             ($nthMatch ? ("at position {$nthMatch}" . PHP_EOL . PHP_EOL) : '') .
143             "[{$selector}]" . PHP_EOL . PHP_EOL .
144             'containing text' . PHP_EOL . PHP_EOL .
145             "[{$text}]" . PHP_EOL . PHP_EOL .
146             'within' . PHP_EOL . PHP_EOL .
147             "[{$this->getContent()}]."
148         );
149
150         return $this;
151     }
152
153     /**
154      * Assert there's a notification within the view containing the given text.
155      *
156      * @return $this
157      */
158     public function assertNotificationContains(string $text)
159     {
160         return $this->assertElementContains('[notification]', $text);
161     }
162
163     /**
164      * Get the escaped text pattern for the constraint.
165      *
166      * @return string
167      */
168     protected function getEscapedPattern(string $text)
169     {
170         $rawPattern = preg_quote($text, '/');
171         $escapedPattern = preg_quote(e($text), '/');
172
173         return $rawPattern == $escapedPattern
174             ? $rawPattern : "({$rawPattern}|{$escapedPattern})";
175     }
176 }