diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 98c08e1..3400115 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -28,7 +28,7 @@ jobs:
steps:
- name: Checkout code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
@@ -41,9 +41,52 @@ 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
+ composer update --with=laravel/framework=^${{ matrix.laravel }} --with=phpunit/phpunit:^${{ matrix.phpunit }} --prefer-dist --no-interaction --no-progress
- name: Execute tests
run: vendor/bin/phpunit
+
+ paratests:
+ runs-on: ubuntu-22.04
+
+ strategy:
+ fail-fast: true
+ matrix:
+ php: [8.2, 8.3]
+
+ name: PHP ${{ matrix.php }} Paratest
+
+ services:
+ mysql:
+ image: mysql:8
+ env:
+ MYSQL_ALLOW_EMPTY_PASSWORD: yes
+ MYSQL_DATABASE: laravel
+ ports:
+ - 3306:3306
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ extensions: dom, curl, libxml, mbstring, zip
+ ini-values: error_reporting=E_ALL
+ tools: composer:v2
+ coverage: none
+
+ - name: Install dependencies
+ run: |
+ composer require "nunomaduro/collision" "brianium/paratest" --no-update
+ composer update --prefer-dist --no-interaction --no-progress -W
+
+ - name: Execute tests
+ run: php vendor/bin/testbench package:test --parallel
+ env:
+ DB_CONNECTION: mysql
+ DB_USERNAME: root
+ DB_DATABASE: laravel
diff --git a/composer.json b/composer.json
index e3310ce..12fe36d 100644
--- a/composer.json
+++ b/composer.json
@@ -12,13 +12,9 @@
"require": {
"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",
+ "laravel/framework": "^10.44|^11.0",
"mockery/mockery": "^1.0",
- "phpunit/phpunit": "^10.4|^11.0",
+ "phpunit/phpunit": "^10.4|^11.0.1",
"symfony/console": "^6.2|^7.0",
"symfony/css-selector": "^6.2|^7.0",
"symfony/dom-crawler": "^6.2|^7.0",
@@ -26,7 +22,7 @@
"symfony/http-kernel": "^6.2|^7.0"
},
"require-dev": {
- "laravel/framework": "^10.0|^11.0"
+ "orchestra/testbench-core": "^8.21|^9.0"
},
"autoload": {
"psr-4": {
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index c98a67a..aec5f6c 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -10,7 +10,7 @@
>
- ./tests
+ ./tests
diff --git a/src/Constraints/Concerns/FormFieldConstraint.php b/src/Constraints/Concerns/FormFieldConstraint.php
deleted file mode 100644
index fc83ae7..0000000
--- a/src/Constraints/Concerns/FormFieldConstraint.php
+++ /dev/null
@@ -1,82 +0,0 @@
-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();
- }
-}
diff --git a/src/Constraints/Concerns/HasElement.php b/src/Constraints/Concerns/HasElement.php
deleted file mode 100644
index e7246b0..0000000
--- a/src/Constraints/Concerns/HasElement.php
+++ /dev/null
@@ -1,99 +0,0 @@
-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;
- }
-}
diff --git a/src/Constraints/Concerns/HasInElement.php b/src/Constraints/Concerns/HasInElement.php
deleted file mode 100644
index 751e4fd..0000000
--- a/src/Constraints/Concerns/HasInElement.php
+++ /dev/null
@@ -1,78 +0,0 @@
-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);
- }
-}
diff --git a/src/Constraints/Concerns/HasLink.php b/src/Constraints/Concerns/HasLink.php
deleted file mode 100644
index 1e81908..0000000
--- a/src/Constraints/Concerns/HasLink.php
+++ /dev/null
@@ -1,116 +0,0 @@
- tag.
- *
- * @var string|null
- */
- protected readonly string|null $url;
-
- /**
- * Create a new constraint instance.
- *
- * @param string $text
- * @param string|null $url
- * @return void
- */
- public function __construct($text, $url = null)
- {
- $this->url = $url;
- $this->text = $text;
- }
-
- /**
- * Check if the link is found in the given crawler.
- *
- * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
- * @return bool
- */
- public function matches($crawler): bool
- {
- $links = $this->crawler($crawler)->selectLink($this->text);
-
- if ($links->count() == 0) {
- return false;
- }
-
- // If the URL is null we assume the developer only wants to find a link
- // with the given text regardless of the URL. So if we find the link
- // we will return true. Otherwise, we will look for the given URL.
- if ($this->url == null) {
- return true;
- }
-
- $absoluteUrl = $this->absoluteUrl();
-
- foreach ($links as $link) {
- $linkHref = $link->getAttribute('href');
-
- if ($linkHref == $this->url || $linkHref == $absoluteUrl) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Add a root if the URL is relative (helper method of the hasLink function).
- *
- * @return string
- */
- protected function absoluteUrl()
- {
- if (! Str::startsWith($this->url, ['http', 'https'])) {
- return URL::to($this->url);
- }
-
- return $this->url;
- }
-
- /**
- * Returns the description of the failure.
- *
- * @return string
- */
- public function getFailureDescription()
- {
- $description = "has a link with the text [{$this->text}]";
-
- if ($this->url) {
- $description .= " and the URL [{$this->url}]";
- }
-
- return $description;
- }
-
- /**
- * Returns the reversed description of the failure.
- *
- * @return string
- */
- protected function getReverseFailureDescription()
- {
- $description = "does not have a link with the text [{$this->text}]";
-
- if ($this->url) {
- $description .= " and the URL [{$this->url}]";
- }
-
- return $description;
- }
-}
diff --git a/src/Constraints/Concerns/HasSource.php b/src/Constraints/Concerns/HasSource.php
deleted file mode 100644
index 10be19f..0000000
--- a/src/Constraints/Concerns/HasSource.php
+++ /dev/null
@@ -1,47 +0,0 @@
-source = $source;
- }
-
- /**
- * Check if the source is found in the given crawler.
- *
- * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
- * @return bool
- */
- protected function matches($crawler): bool
- {
- $pattern = $this->getEscapedPattern($this->source);
-
- return preg_match("/{$pattern}/i", $this->html($crawler));
- }
-
- /**
- * Returns a string representation of the object.
- *
- * @return string
- */
- public function toString(): string
- {
- return "the HTML [{$this->source}]";
- }
-}
diff --git a/src/Constraints/Concerns/HasText.php b/src/Constraints/Concerns/HasText.php
deleted file mode 100644
index 53bf717..0000000
--- a/src/Constraints/Concerns/HasText.php
+++ /dev/null
@@ -1,47 +0,0 @@
-text = $text;
- }
-
- /**
- * Check if the plain text is found in the given crawler.
- *
- * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
- * @return bool
- */
- protected function matches($crawler): bool
- {
- $pattern = $this->getEscapedPattern($this->text);
-
- return preg_match("/{$pattern}/i", $this->text($crawler));
- }
-
- /**
- * Returns a string representation of the object.
- *
- * @return string
- */
- public function toString(): string
- {
- return "the text [{$this->text}]";
- }
-}
diff --git a/src/Constraints/Concerns/HasValue.php b/src/Constraints/Concerns/HasValue.php
deleted file mode 100644
index 8b62e9f..0000000
--- a/src/Constraints/Concerns/HasValue.php
+++ /dev/null
@@ -1,74 +0,0 @@
-crawler($crawler);
-
- return $this->getInputOrTextAreaValue($crawler) == $this->value;
- }
-
- /**
- * Get the value of an input or textarea.
- *
- * @param \Symfony\Component\DomCrawler\Crawler $crawler
- * @return string
- *
- * @throws \PHPUnit\Framework\ExpectationFailedException
- */
- public function getInputOrTextAreaValue(Crawler $crawler)
- {
- $field = $this->field($crawler);
-
- return $field->nodeName() == 'input'
- ? $field->attr('value')
- : $field->text();
- }
-
- /**
- * Return the description of the failure.
- *
- * @return string
- */
- protected function getFailureDescription()
- {
- return sprintf(
- 'the field [%s] contains the expected value [%s]',
- $this->selector, $this->value
- );
- }
-
- /**
- * Returns the reversed description of the failure.
- *
- * @return string
- */
- protected function getReverseFailureDescription()
- {
- return sprintf(
- 'the field [%s] does not contain the expected value [%s]',
- $this->selector, $this->value
- );
- }
-}
diff --git a/src/Constraints/Concerns/IsChecked.php b/src/Constraints/Concerns/IsChecked.php
deleted file mode 100644
index 4cf376c..0000000
--- a/src/Constraints/Concerns/IsChecked.php
+++ /dev/null
@@ -1,60 +0,0 @@
-crawler($crawler);
-
- return ! is_null($this->field($crawler)->attr('checked'));
- }
-
- /**
- * Return the description of the failure.
- *
- * @return string
- */
- protected function getFailureDescription()
- {
- return "the checkbox [{$this->selector}] is checked";
- }
-
- /**
- * Returns the reversed description of the failure.
- *
- * @return string
- */
- protected function getReverseFailureDescription()
- {
- return "the checkbox [{$this->selector}] is not checked";
- }
-}
diff --git a/src/Constraints/Concerns/IsSelected.php b/src/Constraints/Concerns/IsSelected.php
deleted file mode 100644
index 4d32853..0000000
--- a/src/Constraints/Concerns/IsSelected.php
+++ /dev/null
@@ -1,130 +0,0 @@
-crawler($crawler);
-
- return in_array($this->value, $this->getSelectedValue($crawler));
- }
-
- /**
- * Get the selected value of a select field or radio group.
- *
- * @param \Symfony\Component\DomCrawler\Crawler $crawler
- * @return array
- *
- * @throws \PHPUnit\Framework\ExpectationFailedException
- */
- public function getSelectedValue(Crawler $crawler)
- {
- $field = $this->field($crawler);
-
- return $field->nodeName() == 'select'
- ? $this->getSelectedValueFromSelect($field)
- : [$this->getCheckedValueFromRadioGroup($field)];
- }
-
- /**
- * Get the selected value from a select field.
- *
- * @param \Symfony\Component\DomCrawler\Crawler $select
- * @return array
- */
- protected function getSelectedValueFromSelect(Crawler $select)
- {
- $selected = [];
-
- foreach ($select->children() as $option) {
- if ($option->nodeName === 'optgroup') {
- foreach ($option->childNodes as $child) {
- if ($child->hasAttribute('selected')) {
- $selected[] = $this->getOptionValue($child);
- }
- }
- } elseif ($option->hasAttribute('selected')) {
- $selected[] = $this->getOptionValue($option);
- }
- }
-
- return $selected;
- }
-
- /**
- * Get the selected value from an option element.
- *
- * @param \DOMElement $option
- * @return string
- */
- protected function getOptionValue(DOMElement $option)
- {
- if ($option->hasAttribute('value')) {
- return $option->getAttribute('value');
- }
-
- return $option->textContent;
- }
-
- /**
- * Get the checked value from a radio group.
- *
- * @param \Symfony\Component\DomCrawler\Crawler $radioGroup
- * @return string|null
- */
- protected function getCheckedValueFromRadioGroup(Crawler $radioGroup)
- {
- foreach ($radioGroup as $radio) {
- if ($radio->hasAttribute('checked')) {
- return $radio->getAttribute('value');
- }
- }
- }
-
- /**
- * Returns the description of the failure.
- *
- * @return string
- */
- protected function getFailureDescription()
- {
- return sprintf(
- 'the element [%s] has the selected value [%s]',
- $this->selector, $this->value
- );
- }
-
- /**
- * Returns the reversed description of the failure.
- *
- * @return string
- */
- protected function getReverseFailureDescription()
- {
- return sprintf(
- 'the element [%s] does not have the selected value [%s]',
- $this->selector, $this->value
- );
- }
-}
diff --git a/src/Constraints/Concerns/PageConstraint.php b/src/Constraints/Concerns/PageConstraint.php
deleted file mode 100644
index 0cadce3..0000000
--- a/src/Constraints/Concerns/PageConstraint.php
+++ /dev/null
@@ -1,123 +0,0 @@
-html() : $crawler;
- }
-
- /**
- * Make sure we obtain the HTML from the crawler or the response.
- *
- * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
- * @return string
- */
- protected function text($crawler)
- {
- return is_object($crawler) ? $crawler->text() : strip_tags($crawler);
- }
-
- /**
- * Create a crawler instance if the given value is not already a Crawler.
- *
- * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
- * @return \Symfony\Component\DomCrawler\Crawler
- */
- protected function crawler($crawler)
- {
- return is_object($crawler) ? $crawler : new Crawler($crawler);
- }
-
- /**
- * Get the escaped text pattern for the constraint.
- *
- * @param string $text
- * @return string
- */
- protected function getEscapedPattern($text)
- {
- $rawPattern = preg_quote($text, '/');
-
- $escapedPattern = preg_quote(e($text), '/');
-
- return $rawPattern == $escapedPattern
- ? $rawPattern : "({$rawPattern}|{$escapedPattern})";
- }
-
- /**
- * Throw an exception for the given comparison and test description.
- *
- * @param mixed $other
- * @param string $description
- * @param \SebastianBergmann\Comparator\ComparisonFailure|null $comparisonFailure
- * @return void
- *
- * @throws \PHPUnit\Framework\ExpectationFailedException
- */
- protected function fail(mixed $other, string $description, ?ComparisonFailure $comparisonFailure = null): never
- {
- $html = $this->html($other);
-
- $failureDescription = sprintf(
- "%s\n\n\nFailed asserting that %s",
- $html, $this->getFailureDescription()
- );
-
- if (! empty($description)) {
- $failureDescription .= ": {$description}";
- }
-
- if (trim($html) != '') {
- $failureDescription .= '. Please check the content above.';
- } else {
- $failureDescription .= '. The response is empty.';
- }
-
- throw new ExpectationFailedException($failureDescription, $comparisonFailure);
- }
-
- /**
- * Get the description of the failure.
- *
- * @return string
- */
- protected function getFailureDescription()
- {
- return 'the page contains '.$this->toString();
- }
-
- /**
- * Returns the reversed description of the failure.
- *
- * @return string
- */
- protected function getReverseFailureDescription()
- {
- return 'the page does not contain '.$this->toString();
- }
-
- /**
- * Get a string representation of the object.
- *
- * Placeholder method to avoid forcing definition of this method.
- *
- * @return string
- */
- public function toString(): string
- {
- return '';
- }
-}
diff --git a/src/Constraints/Concerns/ReversePageConstraint.php b/src/Constraints/Concerns/ReversePageConstraint.php
deleted file mode 100644
index 26142d6..0000000
--- a/src/Constraints/Concerns/ReversePageConstraint.php
+++ /dev/null
@@ -1,59 +0,0 @@
-pageConstraint = $pageConstraint;
- }
-
- /**
- * Reverse the original page constraint result.
- *
- * @param \Symfony\Component\DomCrawler\Crawler $crawler
- * @return bool
- */
- public function matches($crawler): bool
- {
- return ! (fn () => $this->matches($crawler))->call($this->pageConstraint);
- }
-
- /**
- * Get the description of the failure.
- *
- * This method will attempt to negate the original description.
- *
- * @return string
- */
- protected function getFailureDescription()
- {
- return (fn () => $this->getReverseFailureDescription())->call($this->pageConstraint);
- }
-
- /**
- * Get a string representation of the object.
- *
- * @return string
- */
- public function toString(): string
- {
- return $this->pageConstraint->toString();
- }
-}
diff --git a/src/Constraints/FormFieldConstraint.php b/src/Constraints/FormFieldConstraint.php
index 6be7fdd..75362ae 100644
--- a/src/Constraints/FormFieldConstraint.php
+++ b/src/Constraints/FormFieldConstraint.php
@@ -2,16 +2,81 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+use Symfony\Component\DomCrawler\Crawler;
-if (str_starts_with(Version::series(), '10')) {
- abstract class FormFieldConstraint extends PageConstraint
+abstract class FormFieldConstraint extends PageConstraint
+{
+ /**
+ * 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)
{
- use Concerns\FormFieldConstraint;
+ $this->selector = $selector;
+ $this->value = (string) $value;
}
-} else {
- abstract readonly class FormFieldConstraint extends PageConstraint
+
+ /**
+ * 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)
{
- use Concerns\FormFieldConstraint;
+ $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();
}
}
diff --git a/src/Constraints/HasElement.php b/src/Constraints/HasElement.php
index cf22cdb..4ff43cd 100644
--- a/src/Constraints/HasElement.php
+++ b/src/Constraints/HasElement.php
@@ -2,16 +2,98 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+use Symfony\Component\DomCrawler\Crawler;
-if (str_starts_with(Version::series(), '10')) {
- class HasElement extends PageConstraint
+class HasElement extends PageConstraint
+{
+ /**
+ * 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)
{
- use Concerns\HasElement;
+ 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;
}
-} else {
- readonly class HasElement extends PageConstraint
+
+ /**
+ * Returns a string representation of the object.
+ *
+ * @return string
+ */
+ public function toString(): string
{
- use Concerns\HasElement;
+ $message = "the element [{$this->selector}]";
+
+ if (! empty($this->attributes)) {
+ $message .= ' with the attributes '.json_encode($this->attributes);
+ }
+
+ return $message;
}
}
diff --git a/src/Constraints/HasInElement.php b/src/Constraints/HasInElement.php
index d5f17b2..45ffee2 100644
--- a/src/Constraints/HasInElement.php
+++ b/src/Constraints/HasInElement.php
@@ -2,16 +2,77 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+use Symfony\Component\DomCrawler\Crawler;
-if (str_starts_with(Version::series(), '10')) {
- class HasInElement extends PageConstraint
+class HasInElement extends PageConstraint
+{
+ /**
+ * 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)
{
- use Concerns\HasInElement;
+ $this->text = $text;
+ $this->element = $element;
}
-} else {
- readonly class HasInElement extends PageConstraint
+
+ /**
+ * 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()
{
- use Concerns\HasInElement;
+ return sprintf('[%s] does not contain %s', $this->element, $this->text);
}
}
diff --git a/src/Constraints/HasLink.php b/src/Constraints/HasLink.php
index 676185e..783e509 100644
--- a/src/Constraints/HasLink.php
+++ b/src/Constraints/HasLink.php
@@ -2,16 +2,115 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+use Illuminate\Support\Facades\URL;
+use Illuminate\Support\Str;
-if (str_starts_with(Version::series(), '10')) {
- class HasLink extends PageConstraint
+class HasLink extends PageConstraint
+{
+ /**
+ * The text expected to be found.
+ *
+ * @var string
+ */
+ protected readonly string $text;
+
+ /**
+ * The URL expected to be linked in the tag.
+ *
+ * @var string|null
+ */
+ protected readonly string|null $url;
+
+ /**
+ * Create a new constraint instance.
+ *
+ * @param string $text
+ * @param string|null $url
+ * @return void
+ */
+ public function __construct($text, $url = null)
+ {
+ $this->url = $url;
+ $this->text = $text;
+ }
+
+ /**
+ * Check if the link is found in the given crawler.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
+ * @return bool
+ */
+ public function matches($crawler): bool
{
- use Concerns\HasLink;
+ $links = $this->crawler($crawler)->selectLink($this->text);
+
+ if ($links->count() == 0) {
+ return false;
+ }
+
+ // If the URL is null we assume the developer only wants to find a link
+ // with the given text regardless of the URL. So if we find the link
+ // we will return true. Otherwise, we will look for the given URL.
+ if ($this->url == null) {
+ return true;
+ }
+
+ $absoluteUrl = $this->absoluteUrl();
+
+ foreach ($links as $link) {
+ $linkHref = $link->getAttribute('href');
+
+ if ($linkHref == $this->url || $linkHref == $absoluteUrl) {
+ return true;
+ }
+ }
+
+ return false;
}
-} else {
- readonly class HasLink extends PageConstraint
+
+ /**
+ * Add a root if the URL is relative (helper method of the hasLink function).
+ *
+ * @return string
+ */
+ protected function absoluteUrl()
{
- use Concerns\HasLink;
+ if (! Str::startsWith($this->url, ['http', 'https'])) {
+ return URL::to($this->url);
+ }
+
+ return $this->url;
+ }
+
+ /**
+ * Returns the description of the failure.
+ *
+ * @return string
+ */
+ public function getFailureDescription()
+ {
+ $description = "has a link with the text [{$this->text}]";
+
+ if ($this->url) {
+ $description .= " and the URL [{$this->url}]";
+ }
+
+ return $description;
+ }
+
+ /**
+ * Returns the reversed description of the failure.
+ *
+ * @return string
+ */
+ protected function getReverseFailureDescription()
+ {
+ $description = "does not have a link with the text [{$this->text}]";
+
+ if ($this->url) {
+ $description .= " and the URL [{$this->url}]";
+ }
+
+ return $description;
}
}
diff --git a/src/Constraints/HasSource.php b/src/Constraints/HasSource.php
index 51d20a9..d5a170f 100644
--- a/src/Constraints/HasSource.php
+++ b/src/Constraints/HasSource.php
@@ -2,16 +2,46 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+class HasSource extends PageConstraint
+{
+ /**
+ * The expected HTML source.
+ *
+ * @var string
+ */
+ protected readonly string $source;
-if (str_starts_with(Version::series(), '10')) {
- class HasSource extends PageConstraint
+ /**
+ * Create a new constraint instance.
+ *
+ * @param string $source
+ * @return void
+ */
+ public function __construct($source)
{
- use Concerns\HasSource;
+ $this->source = $source;
}
-} else {
- readonly class HasSource extends PageConstraint
+
+ /**
+ * Check if the source is found in the given crawler.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
+ * @return bool
+ */
+ protected function matches($crawler): bool
+ {
+ $pattern = $this->getEscapedPattern($this->source);
+
+ return preg_match("/{$pattern}/i", $this->html($crawler));
+ }
+
+ /**
+ * Returns a string representation of the object.
+ *
+ * @return string
+ */
+ public function toString(): string
{
- use Concerns\HasSource;
+ return "the HTML [{$this->source}]";
}
}
diff --git a/src/Constraints/HasText.php b/src/Constraints/HasText.php
index ff83f87..a6f463c 100644
--- a/src/Constraints/HasText.php
+++ b/src/Constraints/HasText.php
@@ -2,16 +2,46 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+class HasText extends PageConstraint
+{
+ /**
+ * The expected text.
+ *
+ * @var string
+ */
+ protected readonly string $text;
-if (str_starts_with(Version::series(), '10')) {
- class HasText extends PageConstraint
+ /**
+ * Create a new constraint instance.
+ *
+ * @param string $text
+ * @return void
+ */
+ public function __construct($text)
{
- use Concerns\HasText;
+ $this->text = $text;
}
-} else {
- readonly class HasText extends PageConstraint
+
+ /**
+ * Check if the plain text is found in the given crawler.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
+ * @return bool
+ */
+ protected function matches($crawler): bool
+ {
+ $pattern = $this->getEscapedPattern($this->text);
+
+ return preg_match("/{$pattern}/i", $this->text($crawler));
+ }
+
+ /**
+ * Returns a string representation of the object.
+ *
+ * @return string
+ */
+ public function toString(): string
{
- use Concerns\HasText;
+ return "the text [{$this->text}]";
}
}
diff --git a/src/Constraints/HasValue.php b/src/Constraints/HasValue.php
index b8401f8..f09bcec 100644
--- a/src/Constraints/HasValue.php
+++ b/src/Constraints/HasValue.php
@@ -2,16 +2,73 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+use Symfony\Component\DomCrawler\Crawler;
-if (str_starts_with(Version::series(), '10')) {
- class HasValue extends FormFieldConstraint
+class HasValue extends FormFieldConstraint
+{
+ /**
+ * Get the valid elements.
+ *
+ * @return string
+ */
+ protected function validElements()
{
- use Concerns\HasValue;
+ return 'input,textarea';
}
-} else {
- readonly class HasValue extends FormFieldConstraint
+
+ /**
+ * Check if the input contains the expected value.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
+ * @return bool
+ */
+ public function matches($crawler): bool
+ {
+ $crawler = $this->crawler($crawler);
+
+ return $this->getInputOrTextAreaValue($crawler) == $this->value;
+ }
+
+ /**
+ * Get the value of an input or textarea.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler $crawler
+ * @return string
+ *
+ * @throws \PHPUnit\Framework\ExpectationFailedException
+ */
+ public function getInputOrTextAreaValue(Crawler $crawler)
+ {
+ $field = $this->field($crawler);
+
+ return $field->nodeName() == 'input'
+ ? $field->attr('value')
+ : $field->text();
+ }
+
+ /**
+ * Return the description of the failure.
+ *
+ * @return string
+ */
+ protected function getFailureDescription()
+ {
+ return sprintf(
+ 'the field [%s] contains the expected value [%s]',
+ $this->selector, $this->value
+ );
+ }
+
+ /**
+ * Returns the reversed description of the failure.
+ *
+ * @return string
+ */
+ protected function getReverseFailureDescription()
{
- use Concerns\HasValue;
+ return sprintf(
+ 'the field [%s] does not contain the expected value [%s]',
+ $this->selector, $this->value
+ );
}
}
diff --git a/src/Constraints/IsChecked.php b/src/Constraints/IsChecked.php
index c22f865..b925cd3 100644
--- a/src/Constraints/IsChecked.php
+++ b/src/Constraints/IsChecked.php
@@ -2,16 +2,59 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+class IsChecked extends FormFieldConstraint
+{
+ /**
+ * Create a new constraint instance.
+ *
+ * @param string $selector
+ * @return void
+ */
+ public function __construct($selector)
+ {
+ parent::__construct($selector, null);
+ }
+
+ /**
+ * Get the valid elements.
+ *
+ * @return string
+ */
+ protected function validElements()
+ {
+ return "input[type='checkbox']";
+ }
-if (str_starts_with(Version::series(), '10')) {
- class IsChecked extends FormFieldConstraint
+ /**
+ * Determine if the checkbox is checked.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
+ * @return bool
+ */
+ public function matches($crawler): bool
{
- use Concerns\IsChecked;
+ $crawler = $this->crawler($crawler);
+
+ return ! is_null($this->field($crawler)->attr('checked'));
}
-} else {
- readonly class IsChecked extends FormFieldConstraint
+
+ /**
+ * Return the description of the failure.
+ *
+ * @return string
+ */
+ protected function getFailureDescription()
+ {
+ return "the checkbox [{$this->selector}] is checked";
+ }
+
+ /**
+ * Returns the reversed description of the failure.
+ *
+ * @return string
+ */
+ protected function getReverseFailureDescription()
{
- use Concerns\IsChecked;
+ return "the checkbox [{$this->selector}] is not checked";
}
}
diff --git a/src/Constraints/IsSelected.php b/src/Constraints/IsSelected.php
index 058265e..d228f5b 100644
--- a/src/Constraints/IsSelected.php
+++ b/src/Constraints/IsSelected.php
@@ -2,16 +2,129 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+use DOMElement;
+use Symfony\Component\DomCrawler\Crawler;
-if (str_starts_with(Version::series(), '10')) {
- class IsSelected extends FormFieldConstraint
+class IsSelected extends FormFieldConstraint
+{
+ /**
+ * Get the valid elements.
+ *
+ * @return string
+ */
+ protected function validElements()
{
- use Concerns\IsSelected;
+ return 'select,input[type="radio"]';
}
-} else {
- readonly class IsSelected extends FormFieldConstraint
+
+ /**
+ * Determine if the select or radio element is selected.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
+ * @return bool
+ */
+ protected function matches($crawler): bool
+ {
+ $crawler = $this->crawler($crawler);
+
+ return in_array($this->value, $this->getSelectedValue($crawler));
+ }
+
+ /**
+ * Get the selected value of a select field or radio group.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler $crawler
+ * @return array
+ *
+ * @throws \PHPUnit\Framework\ExpectationFailedException
+ */
+ public function getSelectedValue(Crawler $crawler)
+ {
+ $field = $this->field($crawler);
+
+ return $field->nodeName() == 'select'
+ ? $this->getSelectedValueFromSelect($field)
+ : [$this->getCheckedValueFromRadioGroup($field)];
+ }
+
+ /**
+ * Get the selected value from a select field.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler $select
+ * @return array
+ */
+ protected function getSelectedValueFromSelect(Crawler $select)
+ {
+ $selected = [];
+
+ foreach ($select->children() as $option) {
+ if ($option->nodeName === 'optgroup') {
+ foreach ($option->childNodes as $child) {
+ if ($child->hasAttribute('selected')) {
+ $selected[] = $this->getOptionValue($child);
+ }
+ }
+ } elseif ($option->hasAttribute('selected')) {
+ $selected[] = $this->getOptionValue($option);
+ }
+ }
+
+ return $selected;
+ }
+
+ /**
+ * Get the selected value from an option element.
+ *
+ * @param \DOMElement $option
+ * @return string
+ */
+ protected function getOptionValue(DOMElement $option)
+ {
+ if ($option->hasAttribute('value')) {
+ return $option->getAttribute('value');
+ }
+
+ return $option->textContent;
+ }
+
+ /**
+ * Get the checked value from a radio group.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler $radioGroup
+ * @return string|null
+ */
+ protected function getCheckedValueFromRadioGroup(Crawler $radioGroup)
+ {
+ foreach ($radioGroup as $radio) {
+ if ($radio->hasAttribute('checked')) {
+ return $radio->getAttribute('value');
+ }
+ }
+ }
+
+ /**
+ * Returns the description of the failure.
+ *
+ * @return string
+ */
+ protected function getFailureDescription()
+ {
+ return sprintf(
+ 'the element [%s] has the selected value [%s]',
+ $this->selector, $this->value
+ );
+ }
+
+ /**
+ * Returns the reversed description of the failure.
+ *
+ * @return string
+ */
+ protected function getReverseFailureDescription()
{
- use Concerns\IsSelected;
+ return sprintf(
+ 'the element [%s] does not have the selected value [%s]',
+ $this->selector, $this->value
+ );
}
}
diff --git a/src/Constraints/PageConstraint.php b/src/Constraints/PageConstraint.php
index 6165969..121724b 100644
--- a/src/Constraints/PageConstraint.php
+++ b/src/Constraints/PageConstraint.php
@@ -3,16 +3,122 @@
namespace Laravel\BrowserKitTesting\Constraints;
use PHPUnit\Framework\Constraint\Constraint;
-use PHPUnit\Runner\Version;
+use PHPUnit\Framework\ExpectationFailedException;
+use SebastianBergmann\Comparator\ComparisonFailure;
+use Symfony\Component\DomCrawler\Crawler;
-if (str_starts_with(Version::series(), '10')) {
- abstract class PageConstraint extends Constraint
+abstract class PageConstraint extends Constraint
+{
+ /**
+ * Make sure we obtain the HTML from the crawler or the response.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
+ * @return string
+ */
+ protected function html($crawler)
{
- use Concerns\PageConstraint;
+ return is_object($crawler) ? $crawler->html() : $crawler;
}
-} else {
- abstract readonly class PageConstraint extends Constraint
+
+ /**
+ * Make sure we obtain the HTML from the crawler or the response.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
+ * @return string
+ */
+ protected function text($crawler)
+ {
+ return is_object($crawler) ? $crawler->text() : strip_tags($crawler);
+ }
+
+ /**
+ * Create a crawler instance if the given value is not already a Crawler.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler|string $crawler
+ * @return \Symfony\Component\DomCrawler\Crawler
+ */
+ protected function crawler($crawler)
+ {
+ return is_object($crawler) ? $crawler : new Crawler($crawler);
+ }
+
+ /**
+ * Get the escaped text pattern for the constraint.
+ *
+ * @param string $text
+ * @return string
+ */
+ protected function getEscapedPattern($text)
+ {
+ $rawPattern = preg_quote($text, '/');
+
+ $escapedPattern = preg_quote(e($text), '/');
+
+ return $rawPattern == $escapedPattern
+ ? $rawPattern : "({$rawPattern}|{$escapedPattern})";
+ }
+
+ /**
+ * Throw an exception for the given comparison and test description.
+ *
+ * @param mixed $other
+ * @param string $description
+ * @param \SebastianBergmann\Comparator\ComparisonFailure|null $comparisonFailure
+ * @return void
+ *
+ * @throws \PHPUnit\Framework\ExpectationFailedException
+ */
+ protected function fail(mixed $other, string $description, ?ComparisonFailure $comparisonFailure = null): never
+ {
+ $html = $this->html($other);
+
+ $failureDescription = sprintf(
+ "%s\n\n\nFailed asserting that %s",
+ $html, $this->getFailureDescription()
+ );
+
+ if (! empty($description)) {
+ $failureDescription .= ": {$description}";
+ }
+
+ if (trim($html) != '') {
+ $failureDescription .= '. Please check the content above.';
+ } else {
+ $failureDescription .= '. The response is empty.';
+ }
+
+ throw new ExpectationFailedException($failureDescription, $comparisonFailure);
+ }
+
+ /**
+ * Get the description of the failure.
+ *
+ * @return string
+ */
+ protected function getFailureDescription()
+ {
+ return 'the page contains '.$this->toString();
+ }
+
+ /**
+ * Returns the reversed description of the failure.
+ *
+ * @return string
+ */
+ protected function getReverseFailureDescription()
+ {
+ return 'the page does not contain '.$this->toString();
+ }
+
+ /**
+ * Get a string representation of the object.
+ *
+ * Placeholder method to avoid forcing definition of this method.
+ *
+ * @return string
+ */
+ public function toString(): string
{
- use Concerns\PageConstraint;
+ return '';
}
}
diff --git a/src/Constraints/ReversePageConstraint.php b/src/Constraints/ReversePageConstraint.php
index 9031e16..790d322 100644
--- a/src/Constraints/ReversePageConstraint.php
+++ b/src/Constraints/ReversePageConstraint.php
@@ -2,16 +2,56 @@
namespace Laravel\BrowserKitTesting\Constraints;
-use PHPUnit\Runner\Version;
+class ReversePageConstraint extends PageConstraint
+{
+ /**
+ * The page constraint instance.
+ *
+ * @var \Laravel\BrowserKitTesting\Constraints\PageConstraint
+ */
+ protected readonly PageConstraint $pageConstraint;
-if (str_starts_with(Version::series(), '10')) {
- class ReversePageConstraint extends PageConstraint
+ /**
+ * Create a new reverse page constraint instance.
+ *
+ * @param \Laravel\BrowserKitTesting\Constraints\PageConstraint $pageConstraint
+ * @return void
+ */
+ public function __construct(PageConstraint $pageConstraint)
{
- use Concerns\ReversePageConstraint;
+ $this->pageConstraint = $pageConstraint;
}
-} else {
- readonly class ReversePageConstraint extends PageConstraint
+
+ /**
+ * Reverse the original page constraint result.
+ *
+ * @param \Symfony\Component\DomCrawler\Crawler $crawler
+ * @return bool
+ */
+ public function matches($crawler): bool
+ {
+ return ! (fn () => $this->matches($crawler))->call($this->pageConstraint);
+ }
+
+ /**
+ * Get the description of the failure.
+ *
+ * This method will attempt to negate the original description.
+ *
+ * @return string
+ */
+ protected function getFailureDescription()
+ {
+ return (fn () => $this->getReverseFailureDescription())->call($this->pageConstraint);
+ }
+
+ /**
+ * Get a string representation of the object.
+ *
+ * @return string
+ */
+ public function toString(): string
{
- use Concerns\ReversePageConstraint;
+ return $this->pageConstraint->toString();
}
}
diff --git a/src/TestCase.php b/src/TestCase.php
index 661cee5..9831fdd 100755
--- a/src/TestCase.php
+++ b/src/TestCase.php
@@ -3,16 +3,8 @@
namespace Laravel\BrowserKitTesting;
use Illuminate\Contracts\Console\Kernel;
-use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Application;
-use Illuminate\Foundation\Testing\DatabaseMigrations;
-use Illuminate\Foundation\Testing\DatabaseTransactions;
-use Illuminate\Foundation\Testing\RefreshDatabase;
-use Illuminate\Foundation\Testing\WithFaker;
-use Illuminate\Foundation\Testing\WithoutEvents;
-use Illuminate\Foundation\Testing\WithoutMiddleware;
-use Illuminate\Support\Facades\Facade;
-use Mockery;
+use Illuminate\Foundation\Testing\Concerns\InteractsWithTestCaseLifecycle;
use PHPUnit\Framework\TestCase as BaseTestCase;
use RuntimeException;
@@ -25,35 +17,8 @@ abstract class TestCase extends BaseTestCase
Concerns\InteractsWithConsole,
Concerns\InteractsWithDatabase,
Concerns\InteractsWithExceptionHandling,
- Concerns\InteractsWithSession;
-
- /**
- * The Illuminate application instance.
- *
- * @var \Illuminate\Foundation\Application
- */
- protected $app;
-
- /**
- * The callbacks that should be run after the application is created.
- *
- * @var array
- */
- protected $afterApplicationCreatedCallbacks = [];
-
- /**
- * The callbacks that should be run before the application is destroyed.
- *
- * @var array
- */
- protected $beforeApplicationDestroyedCallbacks = [];
-
- /**
- * Indicates if we have made it through the base setUp function.
- *
- * @var bool
- */
- protected $setUpHasRun = false;
+ Concerns\InteractsWithSession,
+ InteractsWithTestCaseLifecycle;
/**
* Creates the application.
@@ -82,21 +47,7 @@ public function createApplication()
*/
protected function setUp(): void
{
- if (! $this->app) {
- $this->refreshApplication();
- }
-
- $this->setUpTraits();
-
- foreach ($this->afterApplicationCreatedCallbacks as $callback) {
- call_user_func($callback);
- }
-
- Facade::clearResolvedInstances();
-
- Model::setEventDispatcher($this->app['events']);
-
- $this->setUpHasRun = true;
+ $this->setUpTheTestEnvironment();
}
/**
@@ -111,42 +62,6 @@ protected function refreshApplication()
$this->app = $this->createApplication();
}
- /**
- * Boot the testing helper traits.
- *
- * @return array
- */
- protected function setUpTraits()
- {
- $uses = array_flip(class_uses_recursive(static::class));
-
- if (isset($uses[RefreshDatabase::class])) {
- $this->refreshDatabase();
- }
-
- if (isset($uses[DatabaseMigrations::class])) {
- $this->runDatabaseMigrations();
- }
-
- if (isset($uses[DatabaseTransactions::class])) {
- $this->beginDatabaseTransaction();
- }
-
- if (isset($uses[WithoutMiddleware::class])) {
- $this->disableMiddlewareForAllTests();
- }
-
- if (isset($uses[WithoutEvents::class])) {
- $this->disableEventsForAllTests();
- }
-
- if (isset($uses[WithFaker::class])) {
- $this->setUpFaker();
- }
-
- return $uses;
- }
-
/**
* Clean up the testing environment before the next test.
*
@@ -154,57 +69,6 @@ protected function setUpTraits()
*/
protected function tearDown(): void
{
- if ($this->app) {
- foreach ($this->beforeApplicationDestroyedCallbacks as $callback) {
- call_user_func($callback);
- }
-
- $this->app->flush();
-
- $this->app = null;
- }
-
- $this->setUpHasRun = false;
-
- if (property_exists($this, 'serverVariables')) {
- $this->serverVariables = [];
- }
-
- if (class_exists('Mockery')) {
- if ($container = Mockery::getContainer()) {
- $this->addToAssertionCount($container->mockery_getExpectationCount());
- }
-
- Mockery::close();
- }
-
- $this->afterApplicationCreatedCallbacks = [];
- $this->beforeApplicationDestroyedCallbacks = [];
- }
-
- /**
- * Register a callback to be run after the application is created.
- *
- * @param callable $callback
- * @return void
- */
- public function afterApplicationCreated(callable $callback)
- {
- $this->afterApplicationCreatedCallbacks[] = $callback;
-
- if ($this->setUpHasRun) {
- call_user_func($callback);
- }
- }
-
- /**
- * Register a callback to be run before the application is destroyed.
- *
- * @param callable $callback
- * @return void
- */
- protected function beforeApplicationDestroyed(callable $callback)
- {
- $this->beforeApplicationDestroyedCallbacks[] = $callback;
+ $this->tearDownTheTestEnvironment();
}
}
diff --git a/tests/CreatesApplication.php b/tests/CreatesApplication.php
new file mode 100644
index 0000000..2c1c5a9
--- /dev/null
+++ b/tests/CreatesApplication.php
@@ -0,0 +1,23 @@
+make(Kernel::class)->bootstrap();
+
+ return $app;
+ }
+}
diff --git a/tests/Feature/ParallelTestingTest.php b/tests/Feature/ParallelTestingTest.php
new file mode 100644
index 0000000..c3475c1
--- /dev/null
+++ b/tests/Feature/ParallelTestingTest.php
@@ -0,0 +1,31 @@
+markTestSkipped('Requires paratest to execute the tests');
+ }
+
+ parent::setUp();
+ }
+
+ public function test_database_connection_name()
+ {
+ $databaseName = (new User)->getConnection()->getDatabaseName();
+
+ $this->assertStringContainsString('_test_', $databaseName);
+ }
+}
diff --git a/tests/TestCaseTest.php b/tests/TestCaseTest.php
index 0ac8e72..1f4f2b6 100644
--- a/tests/TestCaseTest.php
+++ b/tests/TestCaseTest.php
@@ -7,13 +7,7 @@
class TestCaseTest extends TestCase
{
- /**
- * {@inheritdoc}
- */
- public function createApplication()
- {
- return new Application();
- }
+ use CreatesApplication;
public function test_refresh_application()
{