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 @@

PEST

- GitHub Workflow Status (master) + GitHub Workflow Status (4.x) Total Downloads Latest Version License 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'] Tests: 3 failed, 1 risky, 2 todos, 1 skipped, 1 passed (3 assertions) Duration: 1.00s - - Tests: 3 failed, 1 risky, 2 todos, 1 skipped, 1 passed (3 assertions) - Duration: 1.00s - 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'] Tests: 4 passed (4 assertions) Duration: 1.00s - - Tests: 4 passed (4 assertions) - Duration: 1.00s -