]> BookStack Code Mirror - bookstack/blob - tests/TestResponse.php
Apply column fix to all tables
[bookstack] / tests / TestResponse.php
1 <?php namespace Tests;
2
3 use \Illuminate\Foundation\Testing\TestResponse as BaseTestResponse;
4 use Symfony\Component\DomCrawler\Crawler;
5 use PHPUnit\Framework\Assert as PHPUnit;
6
7 /**
8  * Class TestResponse
9  * Custom extension of the default Laravel TestResponse class.
10  * @package Tests
11  */
12 class TestResponse extends BaseTestResponse {
13
14     protected $crawlerInstance;
15
16     /**
17      * Get the DOM Crawler for the response content.
18      */
19     protected function crawler(): Crawler
20     {
21         if (!is_object($this->crawlerInstance)) {
22             $this->crawlerInstance = new Crawler($this->getContent());
23         }
24         return $this->crawlerInstance;
25     }
26
27     /**
28      * Assert the response contains the specified element.
29      * @return $this
30      */
31     public function assertElementExists(string $selector)
32     {
33         $elements = $this->crawler()->filter($selector);
34         PHPUnit::assertTrue(
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()}]."
40         );
41         return $this;
42     }
43
44     /**
45      * Assert the response does not contain the specified element.
46      * @return $this
47      */
48     public function assertElementNotExists(string $selector)
49     {
50         $elements = $this->crawler()->filter($selector);
51         PHPUnit::assertTrue(
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()}]."
57         );
58         return $this;
59     }
60
61     /**
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.
65      * @return $this
66      */
67     public function assertElementContains(string $selector, string $text, ?int $nthMatch = null)
68     {
69         $elements = $this->crawler()->filter($selector);
70         $matched = false;
71         $pattern = $this->getEscapedPattern($text);
72
73         if (!is_null($nthMatch)) {
74             $elements = $elements->eq($nthMatch - 1);
75         }
76
77         foreach ($elements as $element) {
78             $element = new Crawler($element);
79             if (preg_match("/$pattern/i", $element->html())) {
80                 $matched = true;
81                 break;
82             }
83         }
84
85         PHPUnit::assertTrue(
86             $matched,
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()}]."
94         );
95
96         return $this;
97     }
98
99     /**
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.
103      * @return $this
104      */
105     public function assertElementNotContains(string $selector, string $text, ?int $nthMatch = null)
106     {
107         $elements = $this->crawler()->filter($selector);
108         $matched = false;
109         $pattern = $this->getEscapedPattern($text);
110
111         if (!is_null($nthMatch)) {
112             $elements = $elements->eq($nthMatch - 1);
113         }
114
115         foreach ($elements as $element) {
116             $element = new Crawler($element);
117             if (preg_match("/$pattern/i", $element->html())) {
118                 $matched = true;
119                 break;
120             }
121         }
122
123         PHPUnit::assertTrue(
124             !$matched,
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()}]."
132         );
133
134         return $this;
135     }
136
137     /**
138      * Assert there's a notification within the view containing the given text.
139      * @return $this
140      */
141     public function assertNotificationContains(string $text)
142     {
143         return $this->assertElementContains('[notification]', $text);
144     }
145
146     /**
147      * Get the escaped text pattern for the constraint.
148      * @return string
149      */
150     protected function getEscapedPattern(string $text)
151     {
152         $rawPattern = preg_quote($text, '/');
153         $escapedPattern = preg_quote(e($text), '/');
154         return $rawPattern == $escapedPattern
155             ? $rawPattern : "({$rawPattern}|{$escapedPattern})";
156     }
157
158 }