BookStack/tests/TestResponse.php
Dan Brown 49498cfaf9
Fixed entity-specific tag counts listing
Was reporting wrong due to use of old polymorphic namespace references.
Test was not picking up as assertElementContains had wider scope than
expected, looking within the HTML of the element instead of the text
which you might expect. Updated test helper to look at text instead.
2022-05-16 14:05:21 +01:00

197 lines
5.7 KiB
PHP

<?php
namespace Tests;
use Illuminate\Testing\TestResponse as BaseTestResponse;
use PHPUnit\Framework\Assert as PHPUnit;
use Symfony\Component\DomCrawler\Crawler;
/**
* Class TestResponse
* Custom extension of the default Laravel TestResponse class.
*/
class TestResponse extends BaseTestResponse
{
protected $crawlerInstance;
/**
* Get the DOM Crawler for the response content.
*/
protected function crawler(): Crawler
{
if (!is_object($this->crawlerInstance)) {
$this->crawlerInstance = new Crawler($this->getContent());
}
return $this->crawlerInstance;
}
/**
* Get the HTML of the first element at the given selector.
*/
public function getElementHtml(string $selector): string
{
return $this->crawler()->filter($selector)->first()->outerHtml();
}
/**
* Assert the response contains the specified element.
*
* @return $this
*/
public function assertElementExists(string $selector)
{
$elements = $this->crawler()->filter($selector);
PHPUnit::assertTrue(
$elements->count() > 0,
'Unable to find element matching the selector: ' . PHP_EOL . PHP_EOL .
"[{$selector}]" . PHP_EOL . PHP_EOL .
'within' . PHP_EOL . PHP_EOL .
"[{$this->getContent()}]."
);
return $this;
}
/**
* Assert the response contains the given count of elements
* that match the given css selector.
*
* @return $this
*/
public function assertElementCount(string $selector, int $count)
{
$elements = $this->crawler()->filter($selector);
PHPUnit::assertTrue(
$elements->count() === $count,
'Unable to ' . $count . ' element(s) matching the selector: ' . PHP_EOL . PHP_EOL .
"[{$selector}]" . PHP_EOL . PHP_EOL .
'found ' . $elements->count() . ' within' . PHP_EOL . PHP_EOL .
"[{$this->getContent()}]."
);
return $this;
}
/**
* Assert the response does not contain the specified element.
*
* @return $this
*/
public function assertElementNotExists(string $selector)
{
$elements = $this->crawler()->filter($selector);
PHPUnit::assertTrue(
$elements->count() === 0,
'Found elements matching the selector: ' . PHP_EOL . PHP_EOL .
"[{$selector}]" . PHP_EOL . PHP_EOL .
'within' . PHP_EOL . PHP_EOL .
"[{$this->getContent()}]."
);
return $this;
}
/**
* Assert the response includes a specific element containing the given text.
* If an nth match is provided, only that will be checked otherwise all matching
* elements will be checked for the given text.
*
* @return $this
*/
public function assertElementContains(string $selector, string $text, ?int $nthMatch = null)
{
$elements = $this->crawler()->filter($selector);
$matched = false;
$pattern = $this->getEscapedPattern($text);
if (!is_null($nthMatch)) {
$elements = $elements->eq($nthMatch - 1);
}
foreach ($elements as $element) {
$element = new Crawler($element);
if (preg_match("/$pattern/i", $element->text())) {
$matched = true;
break;
}
}
PHPUnit::assertTrue(
$matched,
'Unable to find element of selector: ' . PHP_EOL . PHP_EOL .
($nthMatch ? ("at position {$nthMatch}" . PHP_EOL . PHP_EOL) : '') .
"[{$selector}]" . PHP_EOL . PHP_EOL .
'containing text' . PHP_EOL . PHP_EOL .
"[{$text}]" . PHP_EOL . PHP_EOL .
'within' . PHP_EOL . PHP_EOL .
"[{$this->getContent()}]."
);
return $this;
}
/**
* Assert the response does not include a specific element containing the given text.
* If an nth match is provided, only that will be checked otherwise all matching
* elements will be checked for the given text.
*
* @return $this
*/
public function assertElementNotContains(string $selector, string $text, ?int $nthMatch = null)
{
$elements = $this->crawler()->filter($selector);
$matched = false;
$pattern = $this->getEscapedPattern($text);
if (!is_null($nthMatch)) {
$elements = $elements->eq($nthMatch - 1);
}
foreach ($elements as $element) {
$element = new Crawler($element);
if (preg_match("/$pattern/i", $element->html())) {
$matched = true;
break;
}
}
PHPUnit::assertTrue(
!$matched,
'Found element of selector: ' . PHP_EOL . PHP_EOL .
($nthMatch ? ("at position {$nthMatch}" . PHP_EOL . PHP_EOL) : '') .
"[{$selector}]" . PHP_EOL . PHP_EOL .
'containing text' . PHP_EOL . PHP_EOL .
"[{$text}]" . PHP_EOL . PHP_EOL .
'within' . PHP_EOL . PHP_EOL .
"[{$this->getContent()}]."
);
return $this;
}
/**
* Assert there's a notification within the view containing the given text.
*
* @return $this
*/
public function assertNotificationContains(string $text)
{
return $this->assertElementContains('[notification]', $text);
}
/**
* Get the escaped text pattern for the constraint.
*
* @return string
*/
protected function getEscapedPattern(string $text)
{
$rawPattern = preg_quote($text, '/');
$escapedPattern = preg_quote(e($text), '/');
return $rawPattern == $escapedPattern
? $rawPattern : "({$rawPattern}|{$escapedPattern})";
}
}