diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 4ec17cfa..f104951e 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -4,16 +4,9 @@ updates:
directory: "/"
schedule:
interval: "weekly"
+ cooldown:
+ default-days: 5
groups:
github-actions:
patterns:
- - "*"
- - package-ecosystem: "github-actions"
- directory: "/"
- schedule:
- interval: "weekly"
- target-branch: "5.x"
- groups:
- github-actions:
- patterns:
- - "*"
+ - "*"
\ No newline at end of file
diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml
index a39df88a..2b8e299b 100644
--- a/.github/workflows/static.yml
+++ b/.github/workflows/static.yml
@@ -28,10 +28,10 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- name: Setup PHP
- uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # v2
+ uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2
with:
php-version: 8.4
tools: composer:v2
@@ -53,6 +53,8 @@ jobs:
static-php-8.4-composer-
- name: Install Dependencies
+ env:
+ COMPOSER_ROOT_VERSION: 4.x-dev
run: composer update --${{ matrix.dependency-version }} --no-interaction --no-progress --ansi
- name: Profanity Check
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index de74351c..5f74ea4d 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -32,10 +32,10 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- name: Setup PHP
- uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # v2
+ uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2
@@ -63,6 +63,8 @@ jobs:
- name: Install PHP dependencies
shell: bash
+ env:
+ COMPOSER_ROOT_VERSION: 4.x-dev
run: composer update --${{ matrix.dependency_version }} --no-interaction --no-progress --ansi --with="symfony/console:^${{ matrix.symfony }}"
- name: Unit Tests
diff --git a/README.md b/README.md
index 1967de7b..717ba81d 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-
+
diff --git a/composer.json b/composer.json
index 8913e1e7..986461d4 100644
--- a/composer.json
+++ b/composer.json
@@ -59,7 +59,7 @@
},
"require-dev": {
"mrpunyapal/peststan": "^0.2.10",
- "laravel/pao": "^1.0.6",
+ "laravel/pao": "^1.1.0",
"pestphp/pest-dev-tools": "^5.0.0",
"pestphp/pest-plugin-browser": "^5.0.0",
"pestphp/pest-plugin-type-coverage": "^5.0.0",
diff --git a/src/Concerns/Testable.php b/src/Concerns/Testable.php
index a6f78d25..b978139c 100644
--- a/src/Concerns/Testable.php
+++ b/src/Concerns/Testable.php
@@ -435,6 +435,11 @@ trait Testable
if ($hasOutputExpectation) {
ob_clean();
+
+ Closure::bind(function (): void {
+ $this->outputExpectedString = null;
+ $this->outputExpectedRegex = null;
+ }, $this, TestCase::class)();
}
$this->setUp();
diff --git a/src/Configuration/Project.php b/src/Configuration/Project.php
index 936c37c6..9a735b48 100644
--- a/src/Configuration/Project.php
+++ b/src/Configuration/Project.php
@@ -59,12 +59,15 @@ final class Project
/**
* Sets the test project to GitLab.
*/
- public function gitlab(string $project): self
+ public function gitlab(string $project, string $hostname = 'gitlab.com'): self
{
- $this->issues = "https://gitlab.com/{$project}/issues/%s";
- $this->prs = "https://gitlab.com/{$project}/merge_requests/%s";
+ // Simple way to ensure only the host is used
+ $hostname = parse_url($hostname, PHP_URL_HOST) ?? $hostname;
- $this->assignees = 'https://gitlab.com/%s';
+ $this->issues = "https://{$hostname}/{$project}/-/work_items/%s";
+ $this->prs = "https://{$hostname}/{$project}/-/merge_requests/%s";
+
+ $this->assignees = "https://{$hostname}/%s";
return $this;
}
diff --git a/src/Expectation.php b/src/Expectation.php
index 22b244f8..d98ff842 100644
--- a/src/Expectation.php
+++ b/src/Expectation.php
@@ -112,7 +112,7 @@ final class Expectation
if (function_exists('dump')) {
dump($this->value, ...$arguments);
} else {
- var_dump($this->value);
+ var_dump($this->value, ...$arguments);
}
return $this;
@@ -120,16 +120,22 @@ final class Expectation
/**
* Dump the expectation value and end the script.
- *
- * @return never
*/
- public function dd(mixed ...$arguments): void
+ public function dd(mixed ...$arguments): never
{
if (function_exists('dd')) {
dd($this->value, ...$arguments);
}
- var_dump($this->value);
+ if (getenv('PARATEST') !== false || isset($_SERVER['COLLISION_PRINTER'])) {
+ ob_start();
+ var_dump($this->value, ...$arguments);
+ $output = (string) ob_get_clean();
+
+ throw new ExpectationFailedException($output);
+ }
+
+ var_dump($this->value, ...$arguments);
exit(1);
}
diff --git a/src/Pest.php b/src/Pest.php
index 476616a4..1aff5b90 100644
--- a/src/Pest.php
+++ b/src/Pest.php
@@ -6,7 +6,7 @@ namespace Pest;
function version(): string
{
- return '5.0.0-rc.9';
+ return '5.0.0-rc.10';
}
function testDirectory(string $file = ''): string
diff --git a/src/Subscribers/EnsureTeamCityEnabled.php b/src/Subscribers/EnsureTeamCityEnabled.php
index 0b9591d2..89793d31 100644
--- a/src/Subscribers/EnsureTeamCityEnabled.php
+++ b/src/Subscribers/EnsureTeamCityEnabled.php
@@ -15,15 +15,20 @@ use Symfony\Component\Console\Output\OutputInterface;
/**
* @internal
*/
-final readonly class EnsureTeamCityEnabled implements ConfiguredSubscriber
+final class EnsureTeamCityEnabled implements ConfiguredSubscriber
{
+ /**
+ * Indicates if the TeamCity logger has already been registered.
+ */
+ private static bool $registered = false;
+
/**
* Creates a new Configured Subscriber instance.
*/
public function __construct(
- private InputInterface $input,
- private OutputInterface $output,
- private TestSuite $testSuite,
+ private readonly InputInterface $input,
+ private readonly OutputInterface $output,
+ private readonly TestSuite $testSuite,
) {}
/**
@@ -31,10 +36,16 @@ final readonly class EnsureTeamCityEnabled implements ConfiguredSubscriber
*/
public function notify(Configured $event): void
{
+ if (self::$registered) {
+ return;
+ }
+
if (! $this->input->hasParameterOption('--teamcity')) {
return;
}
+ self::$registered = true;
+
$flowId = getenv('FLOW_ID');
$flowId = is_string($flowId) ? (int) $flowId : getmypid();
diff --git a/tests/.pest/snapshots/Visual/Help/visual_snapshot_of_help_command_output.snap b/tests/.pest/snapshots/Visual/Help/visual_snapshot_of_help_command_output.snap
index a2d965e7..72156a98 100644
--- a/tests/.pest/snapshots/Visual/Help/visual_snapshot_of_help_command_output.snap
+++ b/tests/.pest/snapshots/Visual/Help/visual_snapshot_of_help_command_output.snap
@@ -1,5 +1,5 @@
- Pest Testing Framework 5.0.0-rc.9.
+ Pest Testing Framework 5.0.0-rc.10.
USAGE: pest [options]
diff --git a/tests/.pest/snapshots/Visual/Version/visual_snapshot_of_help_command_output.snap b/tests/.pest/snapshots/Visual/Version/visual_snapshot_of_help_command_output.snap
index 682606ef..719dd9c0 100644
--- a/tests/.pest/snapshots/Visual/Version/visual_snapshot_of_help_command_output.snap
+++ b/tests/.pest/snapshots/Visual/Version/visual_snapshot_of_help_command_output.snap
@@ -1,3 +1,3 @@
- Pest Testing Framework 5.0.0-rc.9.
+ Pest Testing Framework 5.0.0-rc.10.
diff --git a/tests/.snapshots/Failure.php.inc b/tests/.snapshots/Failure.php.inc
index 5c3878fa..efd42309 100644
--- a/tests/.snapshots/Failure.php.inc
+++ b/tests/.snapshots/Failure.php.inc
@@ -1,56 +1,28 @@
##teamcity[testSuiteStarted name='Tests/tests/Failure' locationHint='pest_qn://tests/.tests/Failure.php' flowId='1234']
##teamcity[testCount count='8' flowId='1234']
-##teamcity[testSuiteStarted name='Tests/tests/Failure' locationHint='pest_qn://tests/.tests/Failure.php' flowId='1234']
-##teamcity[testCount count='8' flowId='1234']
##teamcity[testStarted name='it can fail with comparison' locationHint='pest_qn://tests/.tests/Failure.php::it can fail with comparison' flowId='1234']
-##teamcity[testStarted name='it can fail with comparison' locationHint='pest_qn://tests/.tests/Failure.php::it can fail with comparison' flowId='1234']
-##teamcity[testFailed name='it can fail with comparison' message='Failed asserting that true matches expected false.' details='at tests/.tests/Failure.php:6' type='comparisonFailure' actual='true' expected='false' flowId='1234']
##teamcity[testFailed name='it can fail with comparison' message='Failed asserting that true matches expected false.' details='at tests/.tests/Failure.php:6' type='comparisonFailure' actual='true' expected='false' flowId='1234']
##teamcity[testFinished name='it can fail with comparison' duration='100000' flowId='1234']
-##teamcity[testFinished name='it can fail with comparison' duration='100000' flowId='1234']
-##teamcity[testStarted name='it can be ignored because of no assertions' locationHint='pest_qn://tests/.tests/Failure.php::it can be ignored because of no assertions' flowId='1234']
##teamcity[testStarted name='it can be ignored because of no assertions' locationHint='pest_qn://tests/.tests/Failure.php::it can be ignored because of no assertions' flowId='1234']
##teamcity[testIgnored name='it can be ignored because of no assertions' message='This test did not perform any assertions' details='' flowId='1234']
-##teamcity[testIgnored name='it can be ignored because of no assertions' message='This test did not perform any assertions' details='' flowId='1234']
-##teamcity[testFinished name='it can be ignored because of no assertions' duration='100000' flowId='1234']
##teamcity[testFinished name='it can be ignored because of no assertions' duration='100000' flowId='1234']
##teamcity[testStarted name='it can be ignored because it is skipped' locationHint='pest_qn://tests/.tests/Failure.php::it can be ignored because it is skipped' flowId='1234']
-##teamcity[testStarted name='it can be ignored because it is skipped' locationHint='pest_qn://tests/.tests/Failure.php::it can be ignored because it is skipped' flowId='1234']
-##teamcity[testIgnored name='it can be ignored because it is skipped' message='This test was ignored.' details='' flowId='1234']
##teamcity[testIgnored name='it can be ignored because it is skipped' message='This test was ignored.' details='' flowId='1234']
##teamcity[testFinished name='it can be ignored because it is skipped' duration='100000' flowId='1234']
-##teamcity[testFinished name='it can be ignored because it is skipped' duration='100000' flowId='1234']
-##teamcity[testStarted name='it can fail' locationHint='pest_qn://tests/.tests/Failure.php::it can fail' flowId='1234']
##teamcity[testStarted name='it can fail' locationHint='pest_qn://tests/.tests/Failure.php::it can fail' flowId='1234']
##teamcity[testFailed name='it can fail' message='oh noo' details='at tests/.tests/Failure.php:18' flowId='1234']
-##teamcity[testFailed name='it can fail' message='oh noo' details='at tests/.tests/Failure.php:18' flowId='1234']
-##teamcity[testFinished name='it can fail' duration='100000' flowId='1234']
##teamcity[testFinished name='it can fail' duration='100000' flowId='1234']
##teamcity[testStarted name='it throws exception' locationHint='pest_qn://tests/.tests/Failure.php::it throws exception' flowId='1234']
-##teamcity[testStarted name='it throws exception' locationHint='pest_qn://tests/.tests/Failure.php::it throws exception' flowId='1234']
-##teamcity[testFailed name='it throws exception' message='Exception: test error' details='at tests/.tests/Failure.php:22' flowId='1234']
##teamcity[testFailed name='it throws exception' message='Exception: test error' details='at tests/.tests/Failure.php:22' flowId='1234']
##teamcity[testFinished name='it throws exception' duration='100000' flowId='1234']
-##teamcity[testFinished name='it throws exception' duration='100000' flowId='1234']
-##teamcity[testStarted name='it is not done yet' locationHint='pest_qn://tests/.tests/Failure.php::it is not done yet' flowId='1234']
##teamcity[testStarted name='it is not done yet' locationHint='pest_qn://tests/.tests/Failure.php::it is not done yet' flowId='1234']
##teamcity[testFinished name='it is not done yet' duration='100000' flowId='1234']
-##teamcity[testFinished name='it is not done yet' duration='100000' flowId='1234']
-##teamcity[testStarted name='build this one.' locationHint='pest_qn://tests/.tests/Failure.php::build this one.' flowId='1234']
##teamcity[testStarted name='build this one.' locationHint='pest_qn://tests/.tests/Failure.php::build this one.' flowId='1234']
##teamcity[testFinished name='build this one.' duration='100000' flowId='1234']
-##teamcity[testFinished name='build this one.' duration='100000' flowId='1234']
-##teamcity[testStarted name='it is passing' locationHint='pest_qn://tests/.tests/Failure.php::it is passing' flowId='1234']
##teamcity[testStarted name='it is passing' locationHint='pest_qn://tests/.tests/Failure.php::it is passing' flowId='1234']
##teamcity[testFinished name='it is passing' duration='100000' flowId='1234']
-##teamcity[testFinished name='it is passing' duration='100000' flowId='1234']
-##teamcity[testSuiteFinished name='Tests/tests/Failure' flowId='1234']
##teamcity[testSuiteFinished name='Tests/tests/Failure' flowId='1234']
[90mTests:[39m [31;1m3 failed[39;22m[90m,[39m[39m [39m[33;1m1 risky[39;22m[90m,[39m[39m [39m[36;1m2 todos[39;22m[90m,[39m[39m [39m[33;1m1 skipped[39;22m[90m,[39m[39m [39m[32;1m1 passed[39;22m[90m (3 assertions)[39m
[90mDuration:[39m [39m1.00s[39m
-
- [90mTests:[39m [31;1m3 failed[39;22m[90m,[39m[39m [39m[33;1m1 risky[39;22m[90m,[39m[39m [39m[36;1m2 todos[39;22m[90m,[39m[39m [39m[33;1m1 skipped[39;22m[90m,[39m[39m [39m[32;1m1 passed[39;22m[90m (3 assertions)[39m
- [90mDuration:[39m [39m1.00s[39m
-
diff --git a/tests/.snapshots/SuccessOnly.php.inc b/tests/.snapshots/SuccessOnly.php.inc
index ca959e33..b940b7b6 100644
--- a/tests/.snapshots/SuccessOnly.php.inc
+++ b/tests/.snapshots/SuccessOnly.php.inc
@@ -1,38 +1,19 @@
##teamcity[testSuiteStarted name='Tests/tests/SuccessOnly' locationHint='pest_qn://tests/.tests/SuccessOnly.php' flowId='1234']
##teamcity[testCount count='4' flowId='1234']
-##teamcity[testSuiteStarted name='Tests/tests/SuccessOnly' locationHint='pest_qn://tests/.tests/SuccessOnly.php' flowId='1234']
-##teamcity[testCount count='4' flowId='1234']
##teamcity[testStarted name='it can pass with comparison' locationHint='pest_qn://tests/.tests/SuccessOnly.php::it can pass with comparison' flowId='1234']
-##teamcity[testStarted name='it can pass with comparison' locationHint='pest_qn://tests/.tests/SuccessOnly.php::it can pass with comparison' flowId='1234']
-##teamcity[testFinished name='it can pass with comparison' duration='100000' flowId='1234']
##teamcity[testFinished name='it can pass with comparison' duration='100000' flowId='1234']
##teamcity[testStarted name='can also pass' locationHint='pest_qn://tests/.tests/SuccessOnly.php::can also pass' flowId='1234']
-##teamcity[testStarted name='can also pass' locationHint='pest_qn://tests/.tests/SuccessOnly.php::can also pass' flowId='1234']
-##teamcity[testFinished name='can also pass' duration='100000' flowId='1234']
##teamcity[testFinished name='can also pass' duration='100000' flowId='1234']
##teamcity[testSuiteStarted name='can pass with dataset' locationHint='pest_qn://tests/.tests/SuccessOnly.php::can pass with dataset' flowId='1234']
-##teamcity[testSuiteStarted name='can pass with dataset' locationHint='pest_qn://tests/.tests/SuccessOnly.php::can pass with dataset' flowId='1234']
-##teamcity[testStarted name='can pass with dataset with data set "(true)"' locationHint='pest_qn://tests/.tests/SuccessOnly.php::can pass with dataset with data set "(true)"' flowId='1234']
##teamcity[testStarted name='can pass with dataset with data set "(true)"' locationHint='pest_qn://tests/.tests/SuccessOnly.php::can pass with dataset with data set "(true)"' flowId='1234']
##teamcity[testFinished name='can pass with dataset with data set "(true)"' duration='100000' flowId='1234']
-##teamcity[testFinished name='can pass with dataset with data set "(true)"' duration='100000' flowId='1234']
-##teamcity[testSuiteFinished name='can pass with dataset' flowId='1234']
##teamcity[testSuiteFinished name='can pass with dataset' flowId='1234']
##teamcity[testSuiteStarted name='`block` → can pass with dataset in describe block' locationHint='pest_qn://tests/.tests/SuccessOnly.php::`block` → can pass with dataset in describe block' flowId='1234']
-##teamcity[testSuiteStarted name='`block` → can pass with dataset in describe block' locationHint='pest_qn://tests/.tests/SuccessOnly.php::`block` → can pass with dataset in describe block' flowId='1234']
-##teamcity[testStarted name='`block` → can pass with dataset in describe block with data set "(1)"' locationHint='pest_qn://tests/.tests/SuccessOnly.php::`block` → can pass with dataset in describe block with data set "(1)"' flowId='1234']
##teamcity[testStarted name='`block` → can pass with dataset in describe block with data set "(1)"' locationHint='pest_qn://tests/.tests/SuccessOnly.php::`block` → can pass with dataset in describe block with data set "(1)"' flowId='1234']
##teamcity[testFinished name='`block` → can pass with dataset in describe block with data set "(1)"' duration='100000' flowId='1234']
-##teamcity[testFinished name='`block` → can pass with dataset in describe block with data set "(1)"' duration='100000' flowId='1234']
##teamcity[testSuiteFinished name='`block` → can pass with dataset in describe block' flowId='1234']
-##teamcity[testSuiteFinished name='`block` → can pass with dataset in describe block' flowId='1234']
-##teamcity[testSuiteFinished name='Tests/tests/SuccessOnly' flowId='1234']
##teamcity[testSuiteFinished name='Tests/tests/SuccessOnly' flowId='1234']
[90mTests:[39m [32;1m4 passed[39;22m[90m (4 assertions)[39m
[90mDuration:[39m [39m1.00s[39m
-
- [90mTests:[39m [32;1m4 passed[39;22m[90m (4 assertions)[39m
- [90mDuration:[39m [39m1.00s[39m
-