Skip to content

Commit

Permalink
Adds PHPUnit 11 support
Browse files Browse the repository at this point in the history
  • Loading branch information
nunomaduro committed Jan 10, 2024
1 parent 26396c2 commit da4e2eb
Show file tree
Hide file tree
Showing 24 changed files with 1,006 additions and 805 deletions.
10 changes: 6 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ jobs:
strategy:
fail-fast: true
matrix:
php: [8.1, 8.2, 8.3]
php: [8.2, 8.3]
phpunit: [10, 11]
laravel: [10, 11]
exclude:
- php: 8.1
laravel: 11
- phpunit: 11
laravel: 10

name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
name: PHP ${{ matrix.php }} - PHPUnit ${{ matrix.phpunit }} - Laravel ${{ matrix.laravel }}

steps:
- name: Checkout code
Expand All @@ -40,6 +41,7 @@ jobs:

- name: Install dependencies
run: |
composer require phpunit/phpunit:^${{ matrix.phpunit }} --no-update
composer require "laravel/framework=^${{ matrix.laravel }}" --no-update
composer update --prefer-dist --no-interaction --no-progress
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
}
],
"require": {
"php": "^8.1",
"php": "^8.2",
"ext-dom": "*",
"illuminate/contracts": "^10.0|^11.0",
"illuminate/database": "^10.0|^11.0",
"illuminate/http": "^10.0|^11.0",
"illuminate/support": "^10.0|^11.0",
"illuminate/testing": "^10.0|^11.0",
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^10.0.7",
"phpunit/phpunit": "^10.4|^11.0",
"symfony/console": "^6.2|^7.0",
"symfony/css-selector": "^6.2|^7.0",
"symfony/dom-crawler": "^6.2|^7.0",
Expand Down
82 changes: 82 additions & 0 deletions src/Constraints/Concerns/FormFieldConstraint.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

namespace Laravel\BrowserKitTesting\Constraints\Concerns;

use Symfony\Component\DomCrawler\Crawler;

trait FormFieldConstraint
{
/**
* The name or ID of the element.
*
* @var string
*/
protected readonly string $selector;

/**
* The expected value.
*
* @var string
*/
protected readonly string $value;

/**
* Create a new constraint instance.
*
* @param string $selector
* @param mixed $value
* @return void
*/
public function __construct($selector, $value)
{
$this->selector = $selector;
$this->value = (string) $value;
}

/**
* Get the valid elements.
*
* Multiple elements should be separated by commas without spaces.
*
* @return string
*/
abstract protected function validElements();

/**
* Get the form field.
*
* @param \Symfony\Component\DomCrawler\Crawler $crawler
* @return \Symfony\Component\DomCrawler\Crawler
*
* @throws \PHPUnit\Framework\ExpectationFailedException
*/
protected function field(Crawler $crawler)
{
$field = $crawler->filter(implode(', ', $this->getElements()));

if ($field->count() > 0) {
return $field;
}

$this->fail($crawler, sprintf(
'There is no %s with the name or ID [%s]',
$this->validElements(), $this->selector
));
}

/**
* Get the elements relevant to the selector.
*
* @return array
*/
protected function getElements()
{
$name = str_replace('#', '', $this->selector);

$id = str_replace(['[', ']'], ['\\[', '\\]'], $name);

return collect(explode(',', $this->validElements()))->map(function ($element) use ($name, $id) {
return "{$element}#{$id}, {$element}[name='{$name}']";
})->all();
}
}
99 changes: 99 additions & 0 deletions src/Constraints/Concerns/HasElement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

namespace Laravel\BrowserKitTesting\Constraints\Concerns;

use Symfony\Component\DomCrawler\Crawler;

trait HasElement
{
/**
* The name or ID of the element.
*
* @var string
*/
protected readonly string $selector;

/**
* The attributes the element should have.
*
* @var array
*/
protected readonly array $attributes;

/**
* Create a new constraint instance.
*
* @param string $selector
* @param array $attributes
* @return void
*/
public function __construct($selector, array $attributes = [])
{
$this->selector = $selector;
$this->attributes = $attributes;
}

/**
* Check if the element is found in the given crawler.
*
* @param \Symfony\Component\DomCrawler\Crawler|string $crawler
* @return bool
*/
public function matches($crawler): bool
{
$elements = $this->crawler($crawler)->filter($this->selector);

if ($elements->count() == 0) {
return false;
}

if (empty($this->attributes)) {
return true;
}

$elements = $elements->reduce(function ($element) {
return $this->hasAttributes($element);
});

return $elements->count() > 0;
}

/**
* Determines if the given element has the attributes.
*
* @param \Symfony\Component\DomCrawler\Crawler $element
* @return bool
*/
protected function hasAttributes(Crawler $element)
{
foreach ($this->attributes as $name => $value) {
if (is_numeric($name)) {
if (is_null($element->attr($value))) {
return false;
}
} else {
if ($element->attr($name) != $value) {
return false;
}
}
}

return true;
}

/**
* Returns a string representation of the object.
*
* @return string
*/
public function toString(): string
{
$message = "the element [{$this->selector}]";

if (! empty($this->attributes)) {
$message .= ' with the attributes '.json_encode($this->attributes);
}

return $message;
}
}
78 changes: 78 additions & 0 deletions src/Constraints/Concerns/HasInElement.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace Laravel\BrowserKitTesting\Constraints\Concerns;

use Symfony\Component\DomCrawler\Crawler;

trait HasInElement
{
/**
* The name or ID of the element.
*
* @var string
*/
protected readonly string $element;

/**
* The text expected to be found.
*
* @var string
*/
protected readonly string $text;

/**
* Create a new constraint instance.
*
* @param string $element
* @param string $text
* @return void
*/
public function __construct($element, $text)
{
$this->text = $text;
$this->element = $element;
}

/**
* Check if the source or text is found within the element in the given crawler.
*
* @param \Symfony\Component\DomCrawler\Crawler|string $crawler
* @return bool
*/
public function matches($crawler): bool
{
$elements = $this->crawler($crawler)->filter($this->element);

$pattern = $this->getEscapedPattern($this->text);

foreach ($elements as $element) {
$element = new Crawler($element);

if (preg_match("/$pattern/i", $element->html())) {
return true;
}
}

return false;
}

/**
* Returns the description of the failure.
*
* @return string
*/
protected function getFailureDescription()
{
return sprintf('[%s] contains %s', $this->element, $this->text);
}

/**
* Returns the reversed description of the failure.
*
* @return string
*/
protected function getReverseFailureDescription()
{
return sprintf('[%s] does not contain %s', $this->element, $this->text);
}
}
Loading

0 comments on commit da4e2eb

Please sign in to comment.