diff --git a/.github/workflows/nightly-tests.yml b/.github/workflows/nightly-tests.yml deleted file mode 100644 index a55aa47d..00000000 --- a/.github/workflows/nightly-tests.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: Nightly Tests - -on: - push: - pull_request: - schedule: - - cron: '0 */12 * * *' - -jobs: - ci: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - php: ['8.1'] - phpunit-branch: [main] - - name: PHP ${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.phpunit-branch }} - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - tools: composer:v2 - coverage: none - - - name: Setup Problem Matchers - run: | - echo "::add-matcher::${{ runner.tool_cache }}/php.json" - echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - name: Install PHP dependencies with phpunit/phpunit:dev-${{ matrix.phpunit-branch }} - run: composer require phpunit/phpunit:dev-${{ matrix.phpunit-branch }} --ansi --no-interaction --no-progress - - - name: Unit Tests - run: composer test:unit - - - name: Unit Tests in Parallel - run: composer test:parallel - if: startsWith(matrix.os, 'windows') != true - - - name: Integration Tests - run: composer test:integration diff --git a/CHANGELOG.md b/CHANGELOG.md index aad205b0..811f5e15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,343 +1,25 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). +# Release Notes for 2.x ## Unreleased -### Added -- Custom failure messages on expectations ([https://github.com/pestphp/pest/pull/583](https://github.com/pestphp/pest/pull/583)) +## [v2.1.0 (2023-03-21)](https://github.com/pestphp/pest/compare/v2.0.2...v2.1.0) -## [v1.20.0 (2021-09-25)](https://github.com/pestphp/pest/compare/v1.19.0...v1.20.0) ### Added -- `throwsIf` test call ([#371](https://github.com/pestphp/pest/pull/371)) -- `--ci` CLI option to ignore development options like `->local()` ([#405](https://github.com/pestphp/pest/pull/405)) -- `when` conditional expectation ([#406](https://github.com/pestphp/pest/pull/406)) -- `unless` conditional expectation ([b43a598](https://github.com/pestphp/pest/commit/b43a59868d5b790a28cbb29c6110c9f068b0b812)) -- `match` conditional expectation ([#407](https://github.com/pestphp/pest/pull/407)) +- `only` test case method ([bcd1503](https://github.com/pestphp/pest/commit/bcd1503cade938853a55c1283b02b6b820ea0b69)) ### Fixed -- `sequence` with more expectations than iterable elements ([#399](https://github.com/pestphp/pest/pull/399)) +- Issues with different characters on test names ([715](https://github.com/pestphp/pest/pull/715)) -## [v1.19.0 (2021-09-20)](https://github.com/pestphp/pest/compare/v1.18.0...v1.19.0) -### Added -- PHP 8.1 support ([e6c7d68](https://github.com/pestphp/pest/commit/e6c7d68defaec8efe01e71e15dd8d8c45b0cf60f)) -- `toHaveProperties` expectation ([#391](https://github.com/pestphp/pest/pull/391)) - -## [v1.18.0 (2021-08-30)](https://github.com/pestphp/pest/compare/v1.17.0...v1.18.0) -### Added -- `toHaveLength` expectation ([#386](https://github.com/pestphp/pest/pull/386)) -- `nunomaduro/collision:^6.0` support ([4ae482c](https://github.com/pestphp/pest/commit/4ae482c7073fb77782b8a4b5738ef1fcea0f82ab)) - -## [v1.17.0 (2021-08-26)](https://github.com/pestphp/pest/compare/v1.16.0...v1.17.0) -### Added -- `toThrow` expectation ([#361](https://github.com/pestphp/pest/pull/361)) - -## [v1.16.0 (2021-08-19)](https://github.com/pestphp/pest/compare/v1.15.0...v1.16.0) -### Added -- Support for new parallel options ([#369](https://github.com/pestphp/pest/pull/369)) - -## [v1.15.0 (2021-08-04)](https://github.com/pestphp/pest/compare/v1.14.0...v1.15.0) -### Added -- `toBeTruthy` and `toBeFalsy` ([#367](https://github.com/pestphp/pest/pull/367)) - -## [v1.14.0 (2021-08-03)](https://github.com/pestphp/pest/compare/v1.13.0...v1.14.0) -### Added -- A new bound closure that allows you to access the test case in Datasets ([#364](https://github.com/pestphp/pest/pull/364)) - -## [v1.13.0 (2021-08-02)](https://github.com/pestphp/pest/compare/v1.12.0...v1.13.0) -### Added -- A cleaner output when running the Pest runner in PhpStorm ([#350](https://github.com/pestphp/pest/pull/350)) -- `toBeIn` expectation ([#363](https://github.com/pestphp/pest/pull/363)) +## [v2.0.2 (2023-03-20)](https://github.com/pestphp/pest/compare/v2.0.1...v2.0.2) ### Fixed -- `skip` with false condition marking test as skipped ([22b822c](https://github.com/pestphp/pest/commit/22b822ce87a3d19d84960fa5c93eb286820b525d)) +- `Pest.php` not being loaded in certain scenarios ([b887116](https://github.com/pestphp/pest/commit/b887116e5ce9a69403ad620cad20f0a029474eb5)) -## [v1.12.0 (2021-07-26)](https://github.com/pestphp/pest/compare/v1.11.0...v1.12.0) -### Added -- `--force` option to override tests in `pest:test` artisan command ([#353](https://github.com/pestphp/pest/pull/353)) -- Support for PHPUnit `^9.3.7` ([ca9d783](https://github.com/pestphp/pest/commit/ca9d783cf942a2caabc85ff7a728c7f28350c67a)) +## [v2.0.1 (2023-03-20)](https://github.com/pestphp/pest/compare/v2.0.0...v2.0.1) ### Fixed -- `beforeAll` and `afterAll` behind called multiple times per test ([#357](https://github.com/pestphp/pest/pull/357)) +- Wrong `version` configuration key on `composer.json` ([8f91f40](https://github.com/pestphp/pest/commit/8f91f40e8ea8b35e04b7989bed6a8f9439e2a2d6)) -## [v1.11.0 (2021-07-21)](https://github.com/pestphp/pest/compare/v1.10.0...v1.11.0) -### Added -- Support for interacting with datasets in higher order tests ([#352](https://github.com/pestphp/pest/pull/352)) +## [v2.0.0 (2023-03-20)](https://github.com/pestphp/pest/compare/v1.22.6...v2.0.0) -### Changed -- The unit test stub now uses the expectation API ([#348](https://github.com/pestphp/pest/pull/348)) - -### Fixed -- PhpStorm will no longer show 0 assertions in the output ([#349](https://github.com/pestphp/pest/pull/349)) - -## [v1.10.0 (2021-07-12)](https://github.com/pestphp/pest/compare/v1.9.1...v1.10.0) -### Added -- The ability to use higher order expectations inside higher order tests ([#341](https://github.com/pestphp/pest/pull/341)) - -## [v1.9.1 (2021-07-11)](https://github.com/pestphp/pest/compare/v1.9.0...v1.9.1) -### Fixed -- Callable `expect` values in higher order tests failing if the value was an existing method name ([#334](https://github.com/pestphp/pest/pull/344)) - -## [v1.9.0 (2021-07-09)](https://github.com/pestphp/pest/compare/v1.8.0...v1.9.0) -### Changed -- You may now pass just an exception message when using the `throws` method ([#339](https://github.com/pestphp/pest/pull/339)) - -## [v1.8.0 (2021-07-08)](https://github.com/pestphp/pest/compare/v1.7.1...v1.8.0) -### Added -- A new `tap` and test case aware `expect` methods for higher order tests ([#331](https://github.com/pestphp/pest/pull/331)) -- Access to test case methods and properties when using `skip` ([#338](https://github.com/pestphp/pest/pull/338)) - -## [v1.7.1 (2021-06-24)](https://github.com/pestphp/pest/compare/v1.7.0...v1.7.1) -### Fixed -- The `and` method not being usable in Higher Order expectations ([#330](https://github.com/pestphp/pest/pull/330)) - -## [v1.7.0 (2021-06-19)](https://github.com/pestphp/pest/compare/v1.6.0...v1.7.0) -### Added -- Support for non-callable values in the sequence method, which will be passed as `toEqual` ([#323](https://github.com/pestphp/pest/pull/323)) -- Support for nested Higher Order Expectations ([#324](https://github.com/pestphp/pest/pull/324)) - -## [v1.6.0 (2021-06-18)](https://github.com/pestphp/pest/compare/v1.5.0...v1.6.0) -### Added -- Adds a new `json` expectation method to improve testing with JSON strings ([#325](https://github.com/pestphp/pest/pull/325)) -- Adds dot notation support to the `toHaveKey` and `toHaveKeys` expectations ([#322](https://github.com/pestphp/pest/pull/322)) - -## [v1.5.0 (2021-06-15)](https://github.com/pestphp/pest/compare/v1.4.0...v1.5.0) -### Changed -- Moves plugins from the `require` section to the core itself ([#317](https://github.com/pestphp/pest/pull/317)), ([#318](https://github.com/pestphp/pest/pull/318)), ([#320](https://github.com/pestphp/pest/pull/320)) - -## [v1.4.0 (2021-06-10)](https://github.com/pestphp/pest/compare/v1.3.2...v1.4.0) -### Added -- Support for multiple datasets (Matrix) on the `with` method ([#303](https://github.com/pestphp/pest/pull/303)) -- Support for incompleted tests ([49de462](https://github.com/pestphp/pest/commit/49de462250cf9f65f09e13eaf6dcc0e06865b930)) - -## [v1.3.2 (2021-06-07)](https://github.com/pestphp/pest/compare/v1.3.1...v1.3.2) -### Fixed -- Test cases with the @ symbol in the directory fail ([#308](https://github.com/pestphp/pest/pull/308)) - -## [v1.3.1 (2021-06-06)](https://github.com/pestphp/pest/compare/v1.3.0...v1.3.1) -### Added -- Added for PHPUnit 9.5.5 ([#310](https://github.com/pestphp/pest/pull/310)) - -### Changed -- Lock minimum Pest plugin versions ([#306](https://github.com/pestphp/pest/pull/306)) - -## [v1.3.0 (2021-05-23)](https://github.com/pestphp/pest/compare/v1.2.1...v1.3.0) -### Added -- Named datasets no longer show the arguments ([#302](https://github.com/pestphp/pest/pull/302)) - -### Fixed -- Wraps global functions within `function_exists` ([#300](https://github.com/pestphp/pest/pull/300)) - -## [v1.2.1 (2021-05-14)](https://github.com/pestphp/pest/compare/v1.2.0...v1.2.1) -### Fixed -- Laravel commands failing with new `--test-directory` option ([#297](https://github.com/pestphp/pest/pull/297)) - -## [v1.2.0 (2021-05-13)](https://github.com/pestphp/pest/compare/v1.1.0...v1.2.0) -### Added -- Adds JUnit / Infection support ([#291](https://github.com/pestphp/pest/pull/291)) -- `--test-directory` command line option ([#283](https://github.com/pestphp/pest/pull/283)) - -## [v1.1.0 (2021-05-02)](https://github.com/pestphp/pest/compare/v1.0.5...v1.1.0) -### Added -- Possibility of "hooks" being added using the "uses" function ([#282](https://github.com/pestphp/pest/pull/282)) - -## [v1.0.5 (2021-03-31)](https://github.com/pestphp/pest/compare/v1.0.4...v1.0.5) -### Added -- Add `--browse` option to `pest:dusk` command ([#280](https://github.com/pestphp/pest/pull/280)) -- Support for PHPUnit 9.5.4 ([#284](https://github.com/pestphp/pest/pull/284)) - -## [v1.0.4 (2021-03-17)](https://github.com/pestphp/pest/compare/v1.0.3...v1.0.4) -### Added -- Support for PHPUnit 9.5.3 ([#278](https://github.com/pestphp/pest/pull/278)) - -## [v1.0.3 (2021-03-13)](https://github.com/pestphp/pest/compare/v1.0.2...v1.0.3) -### Added -- Support for test extensions ([#269](https://github.com/pestphp/pest/pull/269)) - -## [v1.0.2 (2021-02-04)](https://github.com/pestphp/pest/compare/v1.0.1...v1.0.2) -### Added -- Support for PHPUnit 9.5.2 ([#267](https://github.com/pestphp/pest/pull/267)) - -## [v1.0.1 (2021-01-18)](https://github.com/pestphp/pest/compare/v1.0.0...v1.0.1) -### Added -- Support for PHPUnit 9.5.1 ([#261](https://github.com/pestphp/pest/pull/261)) - -### Fixed -- Fix `TestCase@expect` PHPDoc tag ([#251](https://github.com/pestphp/pest/pull/251)) - -## [v1.0.0 (2021-01-03)](https://github.com/pestphp/pest/compare/v0.3.19...v1.0.0) -### Added -- `pest:test --dusk` option ([#245](https://github.com/pestphp/pest/pull/245)) - -### Changed -- Stable version -- Updates init structure ([#240](https://github.com/pestphp/pest/pull/240)) - -## [v0.3.19 (2020-12-27)](https://github.com/pestphp/pest/compare/v0.3.18...v0.3.19) -### Fixed -- Fix binary path in `pest:dusk` command ([#239](https://github.com/pestphp/pest/pull/239)) - -## [v0.3.18 (2020-12-26)](https://github.com/pestphp/pest/compare/v0.3.17...v0.3.18) -### Added -- `toBeJson()` expectation ([plugin-expectations#2](https://github.com/pestphp/pest-plugin-expectations/pull/2)) - -## [v0.3.17 (2020-12-20)](https://github.com/pestphp/pest/compare/v0.3.16...v0.3.17) -### Fixed -- Class inheritance with `depends()` ([#236](https://github.com/pestphp/pest/pull/236)) - -## [v0.3.16 (2020-12-13)](https://github.com/pestphp/pest/compare/v0.3.15...v0.3.16) -### Changed -- Moves expectation API for external plugin ([5d7f262](https://github.com/pestphp/pest/commit/5d7f262f4ab280a660a85900f402eebb23abfda8)) - -## [v0.3.15 (2020-12-04)](https://github.com/pestphp/pest/compare/v0.3.14...v0.3.15) -### Added -- Support for PHPUnit 9.5.0 ([#234](https://github.com/pestphp/pest/pull/234)) -- Support for extending expectation API ([#232](https://github.com/pestphp/pest/pull/232)) - -### Fixed -- Static analysis while using string as key for datasets ([#233](https://github.com/pestphp/pest/pull/233)) - -## [v0.3.14 (2020-11-28)](https://github.com/pestphp/pest/compare/v0.3.13...v0.3.14) -### Added -- `pest:dusk` command ([#223](https://github.com/pestphp/pest/pull/223)) -- Better feedback on errors in `toMatchArray` and `toMatchObject` ([#231](https://github.com/pestphp/pest/pull/231)) - -## [v0.3.13 (2020-11-23)](https://github.com/pestphp/pest/compare/v0.3.12...v0.3.13) -### Added -- `toMatchArray` expectation ([7bea51f](https://github.com/pestphp/pest/commit/7bea51fe09dd2eca7093e4c34cf2dab2e8d39fa5), [3fd24d9](https://github.com/pestphp/pest/commit/3fd24d96d3145dcebdb0aab40aa8b76faa8b6979)) -- Add Pest options to `--help` output ([#217](https://github.com/pestphp/pest/pull/217)) - -### Fixed -- Resolve issue with name resolution in `depends()` ([#216](https://github.com/pestphp/pest/pull/216)) - -## [v0.3.12 (2020-11-11)](https://github.com/pestphp/pest/compare/v0.3.11...v0.3.12) -### Added -- Add support for PHPUnit 9.4.3 ([#219](https://github.com/pestphp/pest/pull/219)) - -## [v0.3.11 (2020-11-09)](https://github.com/pestphp/pest/compare/v0.3.10...v0.3.11) -### Changed -- Improved the exception output for the TeamCity printer (usage with phpstorm plugin) ([#215](https://github.com/pestphp/pest/pull/215)) - -## [v0.3.10 (2020-11-01)](https://github.com/pestphp/pest/compare/v0.3.9...v0.3.10) -### Added -- Add support for PHPUnit 9.4.2 ([d177ab5](https://github.com/pestphp/pest/commit/d177ab5ec2030c5bb8e418d10834c370c94c433d)) - -## [v0.3.9 (2020-10-13)](https://github.com/pestphp/pest/compare/v0.3.8...v0.3.9) -### Added -- Add support for named datasets in description output ([#134](https://github.com/pestphp/pest/pull/134)) -- Add Pest version to `--help` output ([#203](https://github.com/pestphp/pest/pull/203)) -- Add support for PHPUnit 9.4.1 ([#207](https://github.com/pestphp/pest/pull/207)) - -## [v0.3.8 (2020-10-03)](https://github.com/pestphp/pest/compare/v0.3.7...v0.3.8) -### Added -- Add support for PHPUnit 9.4.0 ([#199](https://github.com/pestphp/pest/pull/199)) - -### Fixed -- Fix chained higher order assertions returning void ([#196](https://github.com/pestphp/pest/pull/196)) - -## [v0.3.7 (2020-09-30)](https://github.com/pestphp/pest/compare/v0.3.6...v0.3.7) -### Added -- Add support for PHPUnit 9.3.11 ([#193](https://github.com/pestphp/pest/pull/193)) - -## [v0.3.6 (2020-09-21)](https://github.com/pestphp/pest/compare/v0.3.5...v0.3.6) -### Added -- `toMatch` expectation ([#191](https://github.com/pestphp/pest/pull/191)) -- `toMatchConstraint` expectation ([#190](https://github.com/pestphp/pest/pull/190)) - -## [v0.3.5 (2020-09-16)](https://github.com/pestphp/pest/compare/v0.3.4...v0.3.5) -### Added -- `toStartWith` and `toEndWith` expectations ([#187](https://github.com/pestphp/pest/pull/187)) - -## [v0.3.4 (2020-09-15)](https://github.com/pestphp/pest/compare/v0.3.3...v0.3.4) -### Added -- `toMatchObject` expectation ([4e184b2](https://github.com/pestphp/pest/commit/4e184b2f906c318a5e9cd38fe693cdab5c48d8a2)) - -## [v0.3.3 (2020-09-13)](https://github.com/pestphp/pest/compare/v0.3.2...v0.3.3) -### Added -- `toHaveKeys` expectation ([204f343](https://github.com/pestphp/pest/commit/204f343831adc17bb3734553c24fac92d02f27c7)) - -## [v0.3.2 (2020-09-12)](https://github.com/pestphp/pest/compare/v0.3.1...v0.3.2) -### Added -- Support to PHPUnit 9.3.9, and 9.3.10 ([1318bf9](https://github.com/pestphp/pest/commit/97f98569bc86e8b87f8cde963fe7b4bf5399623b)) - -## [v0.3.1 (2020-08-29)](https://github.com/pestphp/pest/compare/v0.3.0...v0.3.1) -### Added -- Support to PHPUnit 9.3.8 ([#174](https://github.com/pestphp/pest/pull/174)) - -## [v0.3.0 (2020-08-27)](https://github.com/pestphp/pest/compare/v0.2.3...v0.3.0) -### Added -- Expectation API (TODO) -- PHPUnit 9.3 and PHP 8 support ([#128](https://github.com/pestphp/pest/pull/128)) -- Forwards `$this` calls to globals ([#169](https://github.com/pestphp/pest/pull/169)) - -### Fixed -- don't decorate output if --colors=never is set ([36b879f](https://github.com/pestphp/pest/commit/36b879f97d7b187c87a94eb60af5b7d3b7253d56)) - -## [v0.2.3 (2020-07-01)](https://github.com/pestphp/pest/compare/v0.2.2...v0.2.3) -### Added -- `--init` and `pest:install` artisan command output changes ([#118](https://github.com/pestphp/pest/pull/118), [db7c4b1](https://github.com/pestphp/pest/commit/db7c4b174f0974969450dda71dcd649ef0c073a3)) -- `--version` option to view the current version of Pest ([9ea51ca](https://github.com/pestphp/pest/commit/9ea51caf3f74569debb1e465992e9ea916cb80fe)) - -## [v0.2.2 (2020-06-21)](https://github.com/pestphp/pest/compare/v0.2.1...v0.2.2) -### Added -- `depends` phpunit feature ([#103](https://github.com/pestphp/pest/pull/103)) - -### Fixes -- datasets name conflict ([#101](https://github.com/pestphp/pest/pull/101)) - -## [v0.2.1 (2020-06-17)](https://github.com/pestphp/pest/compare/v0.2.0...v0.2.1) -### Fixes -- Multiple `uses` in the same path override previous `uses` ([#97](https://github.com/pestphp/pest/pull/97)) - -## [v0.2.0 (2020-06-14)](https://github.com/pestphp/pest/compare/v0.1.5...v0.2.0) -### Adds -- `--init` option to install Pest on a new blank project ([70b3c7e](https://github.com/pestphp/pest/commit/70b3c7ea1ddb031f3bbfaabdc28d56270608ebbd)) -- pending higher orders tests aka tests without description ([aa1917c](https://github.com/pestphp/pest/commit/aa1917c28d9b69c2bd1d51f986c4f61318ee7e16)) - -### Fixed -- `--verbose` and `--colors` options not being used by printers ([#51](https://github.com/pestphp/pest/pull/51)) -- missing support on windows ([#61](https://github.com/pestphp/pest/pull/61)) - -### Changed -- `helpers.php` stub provides now namespaced functions -- functions provided by plugins are now namespaced functions: - -```php -use function Pest\Faker\faker; - -it('foo', function () { - $name = faker()->name; -}); -``` - -## [v0.1.5 (2020-05-24)](https://github.com/pestphp/pest/compare/v0.1.4...v0.1.5) -### Fixed -- Missing default decorated output on coverage ([88d2391](https://github.com/pestphp/pest/commit/88d2391d2e6fe9c9416462734b9b523cb418f469)) - -## [v0.1.4 (2020-05-24)](https://github.com/pestphp/pest/compare/v0.1.3...v0.1.4) -### Added -- Support to Lumen on artisan commands ([#18](https://github.com/pestphp/pest/pull/18)) - -### Fixed -- Mockery tests without assertions being considered risky ([415f571](https://github.com/pestphp/pest/commit/415f5719101b30c11d87f74810a71686ef2786c6)) - -## [v0.1.3 (2020-05-21)](https://github.com/pestphp/pest/compare/v0.1.2...v0.1.3) -### Added -- `Plugin::uses()` method for making traits globally available ([6c4be01](https://github.com/pestphp/pest/commit/6c4be0190e9493702a976b996bbbf5150cc6bb53)) - -## [v0.1.2 (2020-05-15)](https://github.com/pestphp/pest/compare/v0.1.1...v0.1.2) -### Added -- Support to custom helpers ([#7](https://github.com/pestphp/pest/pull/7)) - -## [v0.1.1 (2020-05-14)](https://github.com/pestphp/pest/compare/v0.1.0...v0.1.1) -### Added -- `test` function without any arguments returns the current test case ([6fc55be](https://github.com/pestphp/pest/commit/6fc55becc8aecff685a958617015be1a4c118b01)) - -### Fixed -- "No coverage driver error" now returns proper error on Laravel ([28d8822](https://github.com/pestphp/pest/commit/28d8822de01f4fa92c62d8b8e019313f382b97e9)) - -## [v0.1.0 (2020-05-09)](https://github.com/pestphp/pest/commit/de2929077b344a099ef9c2ddc2f48abce14e248f) -### Added -- First version +Please consult the [upgrade guide](https://pestphp.com/docs/upgrade-guide) and [release notes](https://pestphp.com/docs/announcing-pest2) in the official Pest documentation. diff --git a/RELEASE.md b/RELEASE.md index 81d3c198..2caae2c9 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -4,8 +4,8 @@ When releasing a new version of Pest there are some checks and updates that need > **For Pest v1 you should use the `1.x` branch instead.** -- Clear your local repository with: `git add . && git reset --hard && git checkout master` -- On the GitHub repository, check the contents of [github.com/pestphp/pest/compare/{latest_version}...master](https://github.com/pestphp/pest/compare/{latest_version}...master) and update the [changelog](CHANGELOG.md) file with the main changes for this release +- Clear your local repository with: `git add . && git reset --hard && git checkout 2.x` +- On the GitHub repository, check the contents of [github.com/pestphp/pest/compare/{latest_version}...2.x](https://github.com/pestphp/pest/compare/{latest_version}...master) and update the [changelog](CHANGELOG.md) file with the main changes for this release - Update the version number in [src/Pest.php](src/Pest.php) - Run the tests locally using: `composer test` - Commit the CHANGELOG and Pest file with the message: `git commit -m "release: vX.X.X"` diff --git a/bin/pest b/bin/pest index 43663978..f480581f 100755 --- a/bin/pest +++ b/bin/pest @@ -1,8 +1,8 @@ #!/usr/bin/env php getParameterOption('--test-directory', (new ConfigLoader($rootPath))->getTestsDirectory()), + $input->getParameterOption('--test-directory', 'tests'), ); if ($dirty) { @@ -85,11 +85,15 @@ use Symfony\Component\Console\Output\ConsoleOutput; $output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated); - $kernel = Kernel::boot($testSuite, $input, $output); + try { + $kernel = Kernel::boot($testSuite, $input, $output); - $result = $kernel->handle($args); + $result = $kernel->handle($args); - $kernel->shutdown(); + $kernel->shutdown(); + } catch (Throwable|Error $e) { + Panic::with($e); + } exit($result); })(); diff --git a/bin/worker.php b/bin/worker.php index 9fa983c7..f3b6b7b3 100644 --- a/bin/worker.php +++ b/bin/worker.php @@ -4,7 +4,6 @@ declare(strict_types=1); use ParaTest\WrapperRunner\ApplicationForWrapperWorker; use ParaTest\WrapperRunner\WrapperWorker; -use Pest\ConfigLoader; use Pest\Kernel; use Pest\Plugins\Actions\CallsHandleArguments; use Pest\TestSuite; @@ -18,7 +17,7 @@ $bootPest = (static function (): void { $rootPath = dirname(PHPUNIT_COMPOSER_INSTALL, 2); $testSuite = TestSuite::getInstance($rootPath, $workerArgv->getParameterOption( '--test-directory', - (new ConfigLoader($rootPath))->getTestsDirectory() + 'tests' )); $input = new ArgvInput(); diff --git a/composer.json b/composer.json index ceebf09c..c7140ad6 100644 --- a/composer.json +++ b/composer.json @@ -18,17 +18,17 @@ ], "require": { "php": "^8.1.0", - "brianium/paratest": "^7.1.1", - "nunomaduro/collision": "v7.x-dev", + "brianium/paratest": "^7.1.2", + "nunomaduro/collision": "^7.3.2", "nunomaduro/termwind": "^1.15.1", "pestphp/pest-plugin": "^2.0.0", - "pestphp/pest-plugin-arch": "^2.0.0", - "phpunit/phpunit": "^10.0.16" + "pestphp/pest-plugin-arch": "^2.0.1", + "phpunit/phpunit": "^10.0.17" }, "conflict": { - "webmozart/assert": "<1.11.0" + "webmozart/assert": "<1.11.0", + "phpunit/phpunit": ">10.0.17" }, - "version": "2.x-dev", "autoload": { "psr-4": { "Pest\\": "src/" @@ -48,11 +48,10 @@ ] }, "require-dev": { - "pestphp/pest-dev-tools": "^2.4.0", + "pestphp/pest-dev-tools": "^2.5.0", "symfony/process": "^6.2.7" }, - "minimum-stability": "dev", - "prefer-stable": true, + "minimum-stability": "stable", "config": { "sort-packages": true, "preferred-install": "dist", @@ -93,7 +92,10 @@ "Pest\\Plugins\\Environment", "Pest\\Plugins\\Help", "Pest\\Plugins\\Memory", + "Pest\\Plugins\\Only", "Pest\\Plugins\\Printer", + "Pest\\Plugins\\ProcessIsolation", + "Pest\\Plugins\\Profile", "Pest\\Plugins\\Retry", "Pest\\Plugins\\Version", "Pest\\Plugins\\Parallel" diff --git a/overrides/TextUI/TestSuiteFilterProcessor.php b/overrides/TextUI/TestSuiteFilterProcessor.php new file mode 100644 index 00000000..31ce5fe6 --- /dev/null +++ b/overrides/TextUI/TestSuiteFilterProcessor.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PHPUnit\TextUI; + +use function array_map; +use Pest\Plugins\Only; +use PHPUnit\Event; +use PHPUnit\Framework\TestSuite; +use PHPUnit\Runner\Filter\Factory; +use PHPUnit\TextUI\Configuration\Configuration; +use PHPUnit\TextUI\Configuration\FilterNotConfiguredException; + +/** + * @internal This class is not covered by the backward compatibility promise for PHPUnit + */ +final class TestSuiteFilterProcessor +{ + private Factory $filterFactory; + + public function __construct(Factory $factory = new Factory) + { + $this->filterFactory = $factory; + } + + /** + * @throws Event\RuntimeException + * @throws FilterNotConfiguredException + */ + public function process(Configuration $configuration, TestSuite $suite): void + { + if (! $configuration->hasFilter() && + ! $configuration->hasGroups() && + ! $configuration->hasExcludeGroups() && + ! $configuration->hasTestsCovering() && + ! $configuration->hasTestsUsing() && + ! Only::isEnabled() + ) { + return; + } + + if ($configuration->hasExcludeGroups()) { + $this->filterFactory->addExcludeGroupFilter( + $configuration->excludeGroups() + ); + } + + if (Only::isEnabled()) { + $this->filterFactory->addIncludeGroupFilter(['__pest_only']); + } elseif ($configuration->hasGroups()) { + $this->filterFactory->addIncludeGroupFilter( + $configuration->groups() + ); + } + + if ($configuration->hasTestsCovering()) { + $this->filterFactory->addIncludeGroupFilter( + array_map( + static fn (string $name): string => '__phpunit_covers_'.$name, + $configuration->testsCovering() + ) + ); + } + + if ($configuration->hasTestsUsing()) { + $this->filterFactory->addIncludeGroupFilter( + array_map( + static fn (string $name): string => '__phpunit_uses_'.$name, + $configuration->testsUsing() + ) + ); + } + + if ($configuration->hasFilter()) { + $this->filterFactory->addNameFilter( + $configuration->filter() + ); + } + + $suite->injectFilter($this->filterFactory); + + Event\Facade::emitter()->testSuiteFiltered( + Event\TestSuite\TestSuiteBuilder::from($suite) + ); + } +} diff --git a/rector.php b/rector.php index 589b8cd0..1a2f4483 100644 --- a/rector.php +++ b/rector.php @@ -16,6 +16,10 @@ return static function (RectorConfig $rectorConfig): void { InlineConstructorDefaultToPropertyRector::class, ]); + $rectorConfig->skip([ + __DIR__.'/src/Plugins/Parallel/Paratest/WrapperRunner.php', + ]); + $rectorConfig->sets([ LevelSetList::UP_TO_PHP_81, SetList::CODE_QUALITY, diff --git a/src/Bootstrappers/BootOverrides.php b/src/Bootstrappers/BootOverrides.php index d25f935d..e1489d7c 100644 --- a/src/Bootstrappers/BootOverrides.php +++ b/src/Bootstrappers/BootOverrides.php @@ -23,6 +23,7 @@ final class BootOverrides implements Bootstrapper 'Runner/TestSuiteLoader.php', 'TextUI/Command/WarmCodeCoverageCacheCommand.php', 'TextUI/Output/Default/ProgressPrinter/TestSkippedSubscriber.php', + 'TextUI/TestSuiteFilterProcessor.php', ]; /** diff --git a/src/Bootstrappers/BootSubscribers.php b/src/Bootstrappers/BootSubscribers.php index 1a5a6c74..248b9dde 100644 --- a/src/Bootstrappers/BootSubscribers.php +++ b/src/Bootstrappers/BootSubscribers.php @@ -21,7 +21,6 @@ final class BootSubscribers implements Bootstrapper * @var array> */ private const SUBSCRIBERS = [ - Subscribers\EnsureConfigurationIsValid::class, Subscribers\EnsureConfigurationIsAvailable::class, Subscribers\EnsureIgnorableTestCasesAreIgnored::class, Subscribers\EnsureKernelDumpIsFlushed::class, @@ -46,9 +45,7 @@ final class BootSubscribers implements Bootstrapper assert($instance instanceof Subscriber); - Event\Facade::registerSubscriber( - $instance - ); + Event\Facade::instance()->registerSubscriber($instance); } } } diff --git a/src/Concerns/Testable.php b/src/Concerns/Testable.php index 1b164b04..806fb89a 100644 --- a/src/Concerns/Testable.php +++ b/src/Concerns/Testable.php @@ -307,7 +307,7 @@ trait Testable */ public static function getPrintableTestCaseName(): string { - return ltrim(self::class, 'P\\'); + return preg_replace('/P\\\/', '', self::class, 1); } /** diff --git a/src/ConfigLoader.php b/src/ConfigLoader.php deleted file mode 100644 index 870003c1..00000000 --- a/src/ConfigLoader.php +++ /dev/null @@ -1,113 +0,0 @@ -loadConfiguration(); - } - - /** - * Get the tests directory or fallback to default path. - */ - public function getTestsDirectory(): string - { - $suiteDirectory = []; - if (is_null($this->config)) { - return self::DEFAULT_TESTS_PATH; - } - - $suiteDirectory = $this->config->xpath('/phpunit/testsuites/testsuite/directory'); - - if ($suiteDirectory === []) { - return self::DEFAULT_TESTS_PATH; - } - - $directory = (string) ($suiteDirectory[0] ?? ''); - - if ($directory === '') { - return self::DEFAULT_TESTS_PATH; - } - - // Return the whole directory if only a separator found (e.g. `./tests`) - if (substr_count($directory, DIRECTORY_SEPARATOR) === 1) { - return is_dir($directory) ? $directory : self::DEFAULT_TESTS_PATH; - } - - $basePath = Str::beforeLast($directory, DIRECTORY_SEPARATOR); - - return is_dir($basePath) ? $basePath : self::DEFAULT_TESTS_PATH; - } - - /** - * Get the configuration file path. - */ - public function getConfigurationFilePath(): string|bool - { - $candidates = [ - $this->rootPath.'/phpunit.xml', - $this->rootPath.'/phpunit.dist.xml', - $this->rootPath.'/phpunit.xml.dist', - ]; - - foreach ($candidates as $candidate) { - if (is_file($candidate)) { - return realpath($candidate); - } - } - - return false; - } - - /** - * Load the configuration file. - */ - private function loadConfiguration(): void - { - $configPath = $this->getConfigurationFilePath(); - - if (is_bool($configPath)) { - return; - } - - $oldReportingLevel = error_reporting(0); - $content = file_get_contents($configPath); - - if ($content !== false) { - try { - $this->config = new SimpleXMLElement($content); - } catch (Throwable) { // @phpstan-ignore-line - // @ignoreException - } - } - - // Restore the correct error reporting - error_reporting($oldReportingLevel); - } -} diff --git a/src/Exceptions/AfterAllAlreadyExist.php b/src/Exceptions/AfterAllAlreadyExist.php index f74e8b51..5aea0c55 100644 --- a/src/Exceptions/AfterAllAlreadyExist.php +++ b/src/Exceptions/AfterAllAlreadyExist.php @@ -19,6 +19,6 @@ final class AfterAllAlreadyExist extends InvalidArgumentException implements Exc */ public function __construct(string $filename) { - parent::__construct(sprintf('The afterAll already exist in the filename `%s`.', $filename)); + parent::__construct(sprintf('The afterAll already exists in the filename `%s`.', $filename)); } } diff --git a/src/Exceptions/AfterEachAlreadyExist.php b/src/Exceptions/AfterEachAlreadyExist.php index 43faa817..cbdd4a7c 100644 --- a/src/Exceptions/AfterEachAlreadyExist.php +++ b/src/Exceptions/AfterEachAlreadyExist.php @@ -19,6 +19,6 @@ final class AfterEachAlreadyExist extends InvalidArgumentException implements Ex */ public function __construct(string $filename) { - parent::__construct(sprintf('The afterEach already exist in the filename `%s`.', $filename)); + parent::__construct(sprintf('The afterEach already exists in the filename `%s`.', $filename)); } } diff --git a/src/Exceptions/AttributeNotSupportedYet.php b/src/Exceptions/AttributeNotSupportedYet.php deleted file mode 100644 index d34262f6..00000000 --- a/src/Exceptions/AttributeNotSupportedYet.php +++ /dev/null @@ -1,24 +0,0 @@ -registerSubscribers(...$subscribers); } private function setFlowId(): void diff --git a/src/Mixins/Expectation.php b/src/Mixins/Expectation.php index 0513face..d087162d 100644 --- a/src/Mixins/Expectation.php +++ b/src/Mixins/Expectation.php @@ -124,7 +124,7 @@ final class Expectation * * @return self */ - public function toBeGreaterThan(int|float $expected, string $message = ''): self + public function toBeGreaterThan(int|float|\DateTime|\DateTimeImmutable $expected, string $message = ''): self { Assert::assertGreaterThan($expected, $this->value, $message); @@ -136,7 +136,7 @@ final class Expectation * * @return self */ - public function toBeGreaterThanOrEqual(int|float $expected, string $message = ''): self + public function toBeGreaterThanOrEqual(int|float|\DateTime|\DateTimeImmutable $expected, string $message = ''): self { Assert::assertGreaterThanOrEqual($expected, $this->value, $message); @@ -148,7 +148,7 @@ final class Expectation * * @return self */ - public function toBeLessThan(int|float $expected, string $message = ''): self + public function toBeLessThan(int|float|\DateTime|\DateTimeImmutable $expected, string $message = ''): self { Assert::assertLessThan($expected, $this->value, $message); @@ -160,7 +160,7 @@ final class Expectation * * @return self */ - public function toBeLessThanOrEqual(int|float $expected, string $message = ''): self + public function toBeLessThanOrEqual(int|float|\DateTime|\DateTimeImmutable $expected, string $message = ''): self { Assert::assertLessThanOrEqual($expected, $this->value, $message); diff --git a/src/PendingCalls/TestCall.php b/src/PendingCalls/TestCall.php index c793ef17..8b237ec7 100644 --- a/src/PendingCalls/TestCall.php +++ b/src/PendingCalls/TestCall.php @@ -10,6 +10,7 @@ use Pest\Factories\Covers\CoversClass; use Pest\Factories\Covers\CoversFunction; use Pest\Factories\Covers\CoversNothing; use Pest\Factories\TestCaseMethodFactory; +use Pest\Plugins\Only; use Pest\Support\Backtrace; use Pest\Support\Exporter; use Pest\Support\HigherOrderCallables; @@ -134,6 +135,16 @@ final class TestCall return $this; } + /** + * Filters the test suite by "only" tests. + */ + public function only(): self + { + Only::enable($this); + + return $this; + } + /** * Skips the current test. */ diff --git a/src/Pest.php b/src/Pest.php index b56ceb0b..32978f6e 100644 --- a/src/Pest.php +++ b/src/Pest.php @@ -6,7 +6,7 @@ namespace Pest; function version(): string { - return '2.x-dev'; + return '2.1.0'; } function testDirectory(string $file = ''): string diff --git a/src/Plugins/Bail.php b/src/Plugins/Bail.php index 2920a97a..d82bd2f6 100644 --- a/src/Plugins/Bail.php +++ b/src/Plugins/Bail.php @@ -22,7 +22,8 @@ final class Bail implements HandlesArguments if ($this->hasArgument('--bail', $arguments)) { $arguments = $this->popArgument('--bail', $arguments); - $arguments = $this->pushArgument('--stop-on-defect', $arguments); + $arguments = $this->pushArgument('--stop-on-failure', $arguments); + $arguments = $this->pushArgument('--stop-on-error', $arguments); } return $arguments; diff --git a/src/Plugins/Help.php b/src/Plugins/Help.php index 22f1c9eb..1bb9a9cb 100644 --- a/src/Plugins/Help.php +++ b/src/Plugins/Help.php @@ -102,6 +102,13 @@ final class Help implements HandlesArguments 'desc' => 'Initialise a standard Pest configuration', ]], ...$content['Configuration']]; + $content['Execution'] = [...[ + [ + 'arg' => '--parallel', + 'desc' => 'Run tests in parallel', + ], + ], ...$content['Execution']]; + $content['Selection'] = array_merge([ [ 'arg' => '--bail', diff --git a/src/Plugins/Only.php b/src/Plugins/Only.php new file mode 100644 index 00000000..aa4556b8 --- /dev/null +++ b/src/Plugins/Only.php @@ -0,0 +1,61 @@ +group('__pest_only'); + + $lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock'; + + if (! file_exists($lockFile)) { + touch($lockFile); + } + } + + /** + * Checks if "only" mode is enabled. + */ + public static function isEnabled(): bool + { + $lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock'; + + return file_exists($lockFile); + } +} diff --git a/src/Plugins/Parallel.php b/src/Plugins/Parallel.php index b85227d1..8f53801a 100644 --- a/src/Plugins/Parallel.php +++ b/src/Plugins/Parallel.php @@ -32,7 +32,7 @@ final class Parallel implements HandlesArguments /** * @var string[] */ - private const UNSUPPORTED_ARGUMENTS = ['--todo', '--retry']; + private const UNSUPPORTED_ARGUMENTS = ['--todos', '--retry']; /** * Whether the given command line arguments indicate that the test suite should be run in parallel. diff --git a/src/Plugins/Parallel/Paratest/WrapperRunner.php b/src/Plugins/Parallel/Paratest/WrapperRunner.php index 5c3bf2e4..bec0dd5a 100644 --- a/src/Plugins/Parallel/Paratest/WrapperRunner.php +++ b/src/Plugins/Parallel/Paratest/WrapperRunner.php @@ -20,13 +20,13 @@ use ParaTest\Options; use ParaTest\RunnerInterface; use ParaTest\WrapperRunner\SuiteLoader; use ParaTest\WrapperRunner\WrapperWorker; +use Pest\Result; use Pest\TestSuite; use PHPUnit\Event\Facade as EventFacade; use PHPUnit\Runner\CodeCoverage; use PHPUnit\TestRunner\TestResult\Facade as TestResultFacade; use PHPUnit\TestRunner\TestResult\TestResult; use PHPUnit\TextUI\Configuration\CodeCoverageFilterRegistry; -use PHPUnit\TextUI\ShellExitCodeCalculator; use PHPUnit\Util\ExcludeList; use function realpath; use SebastianBergmann\Timer\Timer; @@ -114,7 +114,8 @@ final class WrapperRunner implements RunnerInterface ExcludeList::addDirectory($directory); TestResultFacade::init(); - EventFacade::seal(); + + EventFacade::instance()->seal(); $suiteLoader = new SuiteLoader($this->options, $this->output, $this->codeCoverageFilterRegistry); $this->pending = $this->getTestFiles($suiteLoader); @@ -329,14 +330,7 @@ final class WrapperRunner implements RunnerInterface $this->generateCodeCoverageReports(); $this->generateLogs(); - $exitCode = (new ShellExitCodeCalculator())->calculate( - $this->options->configuration->failOnEmptyTestSuite(), - $this->options->configuration->failOnRisky(), - $this->options->configuration->failOnWarning(), - $this->options->configuration->failOnIncomplete(), - $this->options->configuration->failOnSkipped(), - $testResultSum, - ); + $exitCode = Result::exitCode($this->options->configuration, $testResultSum); $this->clearFiles($this->testresultFiles); $this->clearFiles($this->coverageFiles); @@ -354,7 +348,10 @@ final class WrapperRunner implements RunnerInterface } $coverageManager = new CodeCoverage(); - $coverageManager->init($this->options->configuration, $this->codeCoverageFilterRegistry); + + // @phpstan-ignore-next-line + is_bool(true) && $coverageManager->init($this->options->configuration, $this->codeCoverageFilterRegistry, true); + $coverageMerger = new CoverageMerger($coverageManager->codeCoverage()); foreach ($this->coverageFiles as $coverageFile) { $coverageMerger->addCoverageFromFile($coverageFile); diff --git a/src/Plugins/ProcessIsolation.php b/src/Plugins/ProcessIsolation.php new file mode 100644 index 00000000..bf454b65 --- /dev/null +++ b/src/Plugins/ProcessIsolation.php @@ -0,0 +1,28 @@ +hasArgument('--process-isolation', $arguments)) { + throw new InvalidOption('The [--process-isolation] option is not supported.'); + } + + return $arguments; + } +} diff --git a/src/Plugins/Profile.php b/src/Plugins/Profile.php new file mode 100644 index 00000000..0f723a2c --- /dev/null +++ b/src/Plugins/Profile.php @@ -0,0 +1,32 @@ +hasArgument('--profile', $arguments)) { + return $arguments; + } + + if ($this->hasArgument('--parallel', $arguments)) { + throw new InvalidOption('The [--profile] option is not supported when running in parallel.'); + } + + return $arguments; + } +} diff --git a/src/Plugins/Retry.php b/src/Plugins/Retry.php index 94b703e1..f5199381 100644 --- a/src/Plugins/Retry.php +++ b/src/Plugins/Retry.php @@ -23,7 +23,6 @@ final class Retry implements HandlesArguments return $arguments; } - // If running in parallel, we need to disable the retry plugin if ($this->hasArgument('--parallel', $arguments)) { throw new InvalidOption('The [--retry] option is not supported when running in parallel.'); } diff --git a/src/Result.php b/src/Result.php index 4a613d29..9f0b6382 100644 --- a/src/Result.php +++ b/src/Result.php @@ -4,8 +4,8 @@ declare(strict_types=1); namespace Pest; -use PHPUnit\TestRunner\TestResult\Facade; -use PHPUnit\TextUI\Configuration\Registry; +use PHPUnit\TestRunner\TestResult\TestResult; +use PHPUnit\TextUI\Configuration\Configuration; /** * @internal @@ -21,26 +21,24 @@ final class Result /** * If the exit code is different from 0. */ - public static function failed(): bool + public static function failed(Configuration $configuration, TestResult $result): bool { - return ! self::ok(); + return ! self::ok($configuration, $result); } /** * If the exit code is exactly 0. */ - public static function ok(): bool + public static function ok(Configuration $configuration, TestResult $result): bool { - return self::exitCode() === self::SUCCESS_EXIT; + return self::exitCode($configuration, $result) === self::SUCCESS_EXIT; } /** * Get the test execution's exit code. */ - public static function exitCode(): int + public static function exitCode(Configuration $configuration, TestResult $result): int { - $result = Facade::result(); - $returnCode = self::FAILURE_EXIT; if ($result->wasSuccessfulIgnoringPhpunitWarnings() @@ -48,8 +46,6 @@ final class Result $returnCode = self::SUCCESS_EXIT; } - $configuration = Registry::get(); - if ($configuration->failOnEmptyTestSuite() && $result->numberOfTests() === 0) { $returnCode = self::FAILURE_EXIT; } diff --git a/src/Subscribers/EnsureConfigurationIsValid.php b/src/Subscribers/EnsureConfigurationIsValid.php deleted file mode 100644 index 8c5c615b..00000000 --- a/src/Subscribers/EnsureConfigurationIsValid.php +++ /dev/null @@ -1,27 +0,0 @@ -configuration(); - - if ($configuration->processIsolation()) { - throw new AttributeNotSupportedYet('processIsolation', 'true'); - } - } -} diff --git a/src/Support/Arr.php b/src/Support/Arr.php index bd80ae56..aed6c5a7 100644 --- a/src/Support/Arr.php +++ b/src/Support/Arr.php @@ -73,7 +73,7 @@ final class Arr foreach ($array as $key => $value) { if (is_array($value) && $value !== []) { - $results = array_merge($results, static::dot($value, $prepend.$key.'.')); + $results = array_merge($results, self::dot($value, $prepend.$key.'.')); } else { $results[$prepend.$value] = $value; } diff --git a/src/Support/Reflection.php b/src/Support/Reflection.php index 14edd7ad..18a71aa6 100644 --- a/src/Support/Reflection.php +++ b/src/Support/Reflection.php @@ -42,7 +42,7 @@ final class Reflection } if (is_callable($method)) { - return static::bindCallable($method, $args); + return self::bindCallable($method, $args); } throw $exception; @@ -72,7 +72,7 @@ final class Reflection return $test instanceof \PHPUnit\Framework\TestCase ? Closure::fromCallable($callable)->bindTo($test)(...$test->providedData()) - : static::bindCallable($callable); + : self::bindCallable($callable); } /** diff --git a/src/Support/Str.php b/src/Support/Str.php index 9ed75c1f..21ee5c5b 100644 --- a/src/Support/Str.php +++ b/src/Support/Str.php @@ -61,7 +61,8 @@ final class Str { $code = self::PREFIX.str_replace(' ', '_', $code); - return (string) preg_replace('/[^A-Z_a-z0-9]/', '_', $code); + // sticks to PHP8.2 function naming rules https://www.php.net/manual/en/functions.user-defined.php + return (string) preg_replace('/[^a-zA-Z0-9_\x80-\xff]/', '_', $code); } /** diff --git a/src/TestCaseFilters/GitDirtyTestCaseFilter.php b/src/TestCaseFilters/GitDirtyTestCaseFilter.php index c38e49c7..4164694d 100644 --- a/src/TestCaseFilters/GitDirtyTestCaseFilter.php +++ b/src/TestCaseFilters/GitDirtyTestCaseFilter.php @@ -62,7 +62,10 @@ final class GitDirtyTestCaseFilter implements TestCaseFilter $dirtyFiles = array_map(fn ($file, $status): string => in_array($status, ['R', 'RM'], true) ? explode(' -> ', $file)[1] : $file, array_keys($dirtyFiles), $dirtyFiles); - $dirtyFiles = array_filter($dirtyFiles, fn ($file): bool => str_starts_with('.'.DIRECTORY_SEPARATOR.$file, TestSuite::getInstance()->testPath)); + $dirtyFiles = array_filter( + $dirtyFiles, + fn ($file): bool => str_starts_with('.'.DIRECTORY_SEPARATOR.$file, TestSuite::getInstance()->testPath) || str_starts_with($file, TestSuite::getInstance()->testPath) + ); $dirtyFiles = array_values($dirtyFiles); diff --git a/tests/.snapshots/Failure.php.inc b/tests/.snapshots/Failure.php.inc index c31b63a1..691d6a7e 100644 --- a/tests/.snapshots/Failure.php.inc +++ b/tests/.snapshots/Failure.php.inc @@ -1,6 +1,6 @@ ##teamcity[testSuiteStarted name='Tests/tests/Failure' locationHint='file://tests/.tests/Failure.php' 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 src/Mixins/Expectation.php:342|nat src/Support/ExpectationPipeline.php:75|nat src/Support/ExpectationPipeline.php:79|nat src/Expectation.php:300|nat tests/.tests/Failure.php:6|nat src/Factories/TestCaseMethodFactory.php:100|nat src/Concerns/Testable.php:302|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:302|nat src/Concerns/Testable.php:221|nat src/Kernel.php:84' type='comparisonFailure' actual='true' expected='false' 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[testIgnored name='it can be ignored because of no assertions' message='This test did not perform any assertions' details='' flowId='1234'] @@ -9,7 +9,7 @@ ##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[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|nat src/Factories/TestCaseMethodFactory.php:100|nat src/Concerns/Testable.php:302|nat src/Support/ExceptionTrace.php:28|nat src/Concerns/Testable.php:302|nat src/Concerns/Testable.php:221|nat src/Kernel.php:84' flowId='1234'] + ##teamcity[testFinished name='it can fail' 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[testIgnored name='it is not done yet' message='This test was ignored.' details='' flowId='1234'] diff --git a/tests/.snapshots/help-command.txt b/tests/.snapshots/help-command.txt index 70cfa7e3..29a62394 100644 --- a/tests/.snapshots/help-command.txt +++ b/tests/.snapshots/help-command.txt @@ -1,5 +1,5 @@ - Pest Testing Framework 2.x-dev. + Pest Testing Framework 2.1.0. USAGE: pest [options] @@ -33,6 +33,7 @@ --test-suffix [suffixes] Only search for test in files with specified suffix(es). Default: Test.php,.phpt EXECUTION OPTIONS: + --parallel ........................................... Run tests in parallel --process-isolation ................ Run each test in a separate PHP process --globals-backup ................. Backup and restore $GLOBALS for each test --static-backup ......... Backup and restore static properties for each test diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index 7dbe9326..23581808 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -4,6 +4,9 @@ ✓ dependencies ✓ contracts + PASS Tests\Environments\Windows + ✓ global functions are loaded + PASS Tests\Features\AfterAll ✓ deletes file after all @@ -331,12 +334,14 @@ PASS Tests\Features\Expect\toBeGreatherThan ✓ passes + ✓ passes with DateTime and DateTimeImmutable ✓ failures ✓ failures with custom message ✓ not failures PASS Tests\Features\Expect\toBeGreatherThanOrEqual ✓ passes + ✓ passes with DateTime and DateTimeImmutable ✓ failures ✓ failures with custom message ✓ not failures @@ -379,12 +384,14 @@ PASS Tests\Features\Expect\toBeLessThan ✓ passes + ✓ passes with DateTime and DateTimeImmutable ✓ failures ✓ failures with custom message ✓ not failures PASS Tests\Features\Expect\toBeLessThanOrEqual ✓ passes + ✓ passes with DateTime and DateTimeImmutable ✓ failures ✓ failures with custom message ✓ not failures @@ -837,15 +844,6 @@ ✓ it allows global uses ✓ it allows multiple global uses registered in the same path - WARN Tests\Unit\ConfigLoader - ✓ it fallbacks to default path if no phpunit file is found - - it fallbacks to default path if phpunit is not a valid XML - - it fallbacks to default path if failing to read phpunit content - - it fallbacks to default path if there is no test suites directory - - it fallbacks to default path if test suite directory has no value - - it fallbacks to default path if test suite directory does not exist - - it returns the parent folder of first test suite directory - PASS Tests\Unit\Console\Help ✓ it outputs the help information when --help is used @@ -910,6 +908,59 @@ ✓ it evaluates the code with ('version__ ', '__pest_evaluable_version___') ✓ it evaluates the code with ('version\', '__pest_evaluable_version_') + PASS Tests\Unit\TestName + ✓ it may start with P with ('P\Tests\BarTest', 'Tests\BarTest') + ✓ it may start with P with ('P\Packages\Foo', 'Packages\Foo') + ✓ it may start with P with ('P\PPPackages\Foo', 'PPPackages\Foo') + ✓ it may start with P with ('PPPackages\Foo', 'PPPackages\Foo') #1 + ✓ it may start with P with ('PPPackages\Foo', 'PPPackages\Foo') #2 + ✓ ふ+が+ + ✓ ほげ + ✓ 卜竹弓一十山 + ✓ アゴデヸ + ✓ !p8VrB + ✓ &xe6VeKWF#n4 + ✓ %%HurHUnw7zM! + ✓ rundeliekend + ✓ g%%c!Jt9$fy#Kf + ✓ NRs*Gz2@hmB$W$BPD%%b2U%3P%z%apnwSX + ✓ ÀĤ{¼÷ + ✓ ìèéàòç + ✓ زهراء المعادي + ✓ الجبيهه + ✓ الظهران + ✓ Каролин + ✓ অ্যান্টার্কটিকা + ✓ Frýdek-Místek" + ✓ Allingåbro& + ✓ Κεντροαφρικανική Δημοκρατία + ✓ آذربایجان غربی + ✓ זימבבואה + ✓ Belišće + ✓ Գվատեմալա + ✓ パプアニューギニア + ✓ 富山県 + ✓ Қарағанды + ✓ Қостанай + ✓ 안양시 동안구 + ✓ Itālija + ✓ Honningsvåg + ✓ Águeda + ✓ Râșcani + ✓ Năsăud + ✓ Орехово-Зуево + ✓ Čereňany + ✓ Moravče + ✓ Šentjernej + ✓ Врање + ✓ Крушевац + ✓ Åkersberga + ✓ บอสเนียและเฮอร์เซโกวีนา + ✓ Birleşik Arap Emirlikleri + ✓ Німеччина + ✓ Nam Định + ✓ 呼和浩特 + PASS Tests\Unit\TestSuite ✓ it does not allow to add the same test description twice ✓ it alerts users about tests with arguments but no input @@ -943,4 +994,4 @@ PASS Tests\Visual\Version ✓ visual snapshot of help command output - Tests: 2 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 18 skipped, 644 passed (1586 assertions) \ No newline at end of file + Tests: 2 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 12 skipped, 699 passed (1696 assertions) \ No newline at end of file diff --git a/tests/.snapshots/version-command.txt b/tests/.snapshots/version-command.txt index df653c1c..a50a10ae 100644 --- a/tests/.snapshots/version-command.txt +++ b/tests/.snapshots/version-command.txt @@ -1,3 +1,3 @@ - Pest Testing Framework 2.x-dev. + Pest Testing Framework 2.1.0. diff --git a/tests/Environments/Windows.php b/tests/Environments/Windows.php new file mode 100644 index 00000000..54122f54 --- /dev/null +++ b/tests/Environments/Windows.php @@ -0,0 +1,5 @@ +toBeString(); +}); diff --git a/tests/Features/DatasetsTests.php b/tests/Features/DatasetsTests.php index 5d1b1ca1..f6030926 100644 --- a/tests/Features/DatasetsTests.php +++ b/tests/Features/DatasetsTests.php @@ -19,7 +19,7 @@ it('throws exception if dataset does not exist', function () { it('throws exception if dataset already exist', function () { DatasetsRepository::set('second', [[]], __DIR__); $this->expectException(DatasetAlreadyExists::class); - $this->expectExceptionMessage('A dataset with the name `second` already exist in scope ['.__DIR__.'].'); + $this->expectExceptionMessage('A dataset with the name `second` already exists in scope ['.__DIR__.'].'); DatasetsRepository::set('second', [[]], __DIR__); }); diff --git a/tests/Features/Expect/toBeGreatherThan.php b/tests/Features/Expect/toBeGreatherThan.php index 798c23bb..a3ceafef 100644 --- a/tests/Features/Expect/toBeGreatherThan.php +++ b/tests/Features/Expect/toBeGreatherThan.php @@ -7,6 +7,15 @@ test('passes', function () { expect(4)->toBeGreaterThan(3.9); }); +test('passes with DateTime and DateTimeImmutable', function () { + $now = new DateTime(); + $past = (new DateTimeImmutable())->modify('-1 day'); + + expect($now)->toBeGreaterThan($past); + + expect($past)->not->toBeGreaterThan($now); +}); + test('failures', function () { expect(4)->toBeGreaterThan(4); })->throws(ExpectationFailedException::class); diff --git a/tests/Features/Expect/toBeGreatherThanOrEqual.php b/tests/Features/Expect/toBeGreatherThanOrEqual.php index cfa1da07..4a0f62ad 100644 --- a/tests/Features/Expect/toBeGreatherThanOrEqual.php +++ b/tests/Features/Expect/toBeGreatherThanOrEqual.php @@ -7,6 +7,17 @@ test('passes', function () { expect(4)->toBeGreaterThanOrEqual(4); }); +test('passes with DateTime and DateTimeImmutable', function () { + $now = new DateTime(); + $past = (new DateTimeImmutable())->modify('-1 day'); + + expect($now)->toBeGreaterThanOrEqual($now); + + expect($now)->toBeGreaterThanOrEqual($past); + + expect($past)->not->toBeGreaterThanOrEqual($now); +}); + test('failures', function () { expect(4)->toBeGreaterThanOrEqual(4.1); })->throws(ExpectationFailedException::class); diff --git a/tests/Features/Expect/toBeLessThan.php b/tests/Features/Expect/toBeLessThan.php index 9002c424..802c1c08 100644 --- a/tests/Features/Expect/toBeLessThan.php +++ b/tests/Features/Expect/toBeLessThan.php @@ -7,6 +7,15 @@ test('passes', function () { expect(4)->toBeLessThan(5); }); +test('passes with DateTime and DateTimeImmutable', function () { + $now = new DateTime(); + $past = (new DateTimeImmutable())->modify('-1 day'); + + expect($past)->toBeLessThan($now); + + expect($now)->not->toBeLessThan($now); +}); + test('failures', function () { expect(4)->toBeLessThan(4); })->throws(ExpectationFailedException::class); diff --git a/tests/Features/Expect/toBeLessThanOrEqual.php b/tests/Features/Expect/toBeLessThanOrEqual.php index 4413e05f..e5643759 100644 --- a/tests/Features/Expect/toBeLessThanOrEqual.php +++ b/tests/Features/Expect/toBeLessThanOrEqual.php @@ -7,6 +7,17 @@ test('passes', function () { expect(4)->toBeLessThanOrEqual(4); }); +test('passes with DateTime and DateTimeImmutable', function () { + $now = new DateTime(); + $past = (new DateTimeImmutable())->modify('-1 day'); + + expect($now)->toBeLessThanOrEqual($now); + + expect($past)->toBeLessThanOrEqual($now); + + expect($now)->not->toBeLessThanOrEqual($past); +}); + test('failures', function () { expect(4)->toBeLessThanOrEqual(3.9); })->throws(ExpectationFailedException::class); diff --git a/tests/Pest.php b/tests/Pest.php index d0f656bd..23daca74 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -25,3 +25,8 @@ uses() $_SERVER['globalHook']->calls->afterAll++; }) ->in('Hooks'); + +function helper_returns_string() +{ + return 'string'; +} diff --git a/tests/Unit/ConfigLoader.php b/tests/Unit/ConfigLoader.php deleted file mode 100644 index cae011ba..00000000 --- a/tests/Unit/ConfigLoader.php +++ /dev/null @@ -1,19 +0,0 @@ -toBeNull(); - expect($instance->getConfigurationFilePath())->toBeFalse(); - expect($instance->getTestsDirectory())->toBe(ConfigLoader::DEFAULT_TESTS_PATH); -}); - -it('fallbacks to default path if phpunit is not a valid XML')->skip(); -it('fallbacks to default path if failing to read phpunit content')->skip(); -it('fallbacks to default path if there is no test suites directory')->skip(); -it('fallbacks to default path if test suite directory has no value')->skip(); -it('fallbacks to default path if test suite directory does not exist')->skip(); -it('returns the parent folder of first test suite directory')->skip(); diff --git a/tests/Unit/TestName.php b/tests/Unit/TestName.php new file mode 100644 index 00000000..b7f91d54 --- /dev/null +++ b/tests/Unit/TestName.php @@ -0,0 +1,70 @@ +toBe($toBePrinted); +})->with([ + ['P\Tests\BarTest', 'Tests\BarTest'], + ['P\Packages\Foo', 'Packages\Foo'], + ['P\PPPackages\Foo', 'PPPackages\Foo'], + ['PPPackages\Foo', 'PPPackages\Foo'], + ['PPPackages\Foo', 'PPPackages\Foo'], +]); + +$names = [ + 'ふ+が+' => '__pest_evaluable_ふ_が_', + 'ほげ' => '__pest_evaluable_ほげ', + '卜竹弓一十山' => '__pest_evaluable_卜竹弓一十山', + 'アゴデヸ' => '__pest_evaluable_アゴデヸ', + '!p8VrB' => '__pest_evaluable__p8VrB', + '&xe6VeKWF#n4' => '__pest_evaluable__xe6VeKWF_n4', + '%%HurHUnw7zM!' => '__pest_evaluable___HurHUnw7zM_', + 'rundeliekend' => '__pest_evaluable_rundeliekend', + 'g%%c!Jt9$fy#Kf' => '__pest_evaluable_g__c_Jt9_fy_Kf', + 'NRs*Gz2@hmB$W$BPD%%b2U%3P%z%apnwSX' => '__pest_evaluable_NRs_Gz2_hmB_W_BPD__b2U_3P_z_apnwSX', + 'ÀĤ{¼÷' => '__pest_evaluable_ÀĤ_¼÷', + 'ìèéàòç' => '__pest_evaluable_ìèéàòç', + 'زهراء المعادي' => '__pest_evaluable_زهراء_المعادي', + 'الجبيهه' => '__pest_evaluable_الجبيهه', + 'الظهران' => '__pest_evaluable_الظهران', + 'Каролин' => '__pest_evaluable_Каролин', + 'অ্যান্টার্কটিকা' => '__pest_evaluable_অ্যান্টার্কটিকা', + 'Frýdek-Místek"' => '__pest_evaluable_Frýdek_Místek_', + 'Allingåbro&' => '__pest_evaluable_Allingåbro_', + 'Κεντροαφρικανική Δημοκρατία' => '__pest_evaluable_Κεντροαφρικανική_Δημοκρατία', + 'آذربایجان غربی' => '__pest_evaluable_آذربایجان_غربی', + 'זימבבואה' => '__pest_evaluable_זימבבואה', + 'Belišće' => '__pest_evaluable_Belišće', + 'Գվատեմալա' => '__pest_evaluable_Գվատեմալա', + 'パプアニューギニア' => '__pest_evaluable_パプアニューギニア', + '富山県' => '__pest_evaluable_富山県', + 'Қарағанды' => '__pest_evaluable_Қарағанды', + 'Қостанай' => '__pest_evaluable_Қостанай', + '안양시 동안구' => '__pest_evaluable_안양시_동안구', + 'Itālija' => '__pest_evaluable_Itālija', + 'Honningsvåg' => '__pest_evaluable_Honningsvåg', + 'Águeda' => '__pest_evaluable_Águeda', + 'Râșcani' => '__pest_evaluable_Râșcani', + 'Năsăud' => '__pest_evaluable_Năsăud', + 'Орехово-Зуево' => '__pest_evaluable_Орехово_Зуево', + 'Čereňany' => '__pest_evaluable_Čereňany', + 'Moravče' => '__pest_evaluable_Moravče', + 'Šentjernej' => '__pest_evaluable_Šentjernej', + 'Врање' => '__pest_evaluable_Врање', + 'Крушевац' => '__pest_evaluable_Крушевац', + 'Åkersberga' => '__pest_evaluable_Åkersberga', + 'บอสเนียและเฮอร์เซโกวีนา' => '__pest_evaluable_บอสเนียและเฮอร์เซโกวีนา', + 'Birleşik Arap Emirlikleri' => '__pest_evaluable_Birleşik_Arap_Emirlikleri', + 'Німеччина' => '__pest_evaluable_Німеччина', + 'Nam Định' => '__pest_evaluable_Nam_Định', + '呼和浩特' => '__pest_evaluable_呼和浩特', +]; + +foreach ($names as $name => $methodName) { + test($name) + ->expect(fn () => static::getLatestPrintableTestCaseMethodName()) + ->toBe($name) + ->and(fn () => $this->name()) + ->toBe($methodName); +} diff --git a/tests/Unit/TestSuite.php b/tests/Unit/TestSuite.php index 3c4ff2a1..eb033d0c 100644 --- a/tests/Unit/TestSuite.php +++ b/tests/Unit/TestSuite.php @@ -13,7 +13,7 @@ it('does not allow to add the same test description twice', function () { $testSuite->tests->set($method); })->throws( TestAlreadyExist::class, - sprintf('A test with the description `%s` already exist in the filename `%s`.', 'bar', 'foo'), + sprintf('A test with the description `%s` already exists in the filename `%s`.', 'bar', 'foo'), ); it('alerts users about tests with arguments but no input', function () { diff --git a/tests/Visual/Parallel.php b/tests/Visual/Parallel.php index a5a9d844..0d9117cd 100644 --- a/tests/Visual/Parallel.php +++ b/tests/Visual/Parallel.php @@ -9,12 +9,12 @@ $run = function () { $process->run(); - expect($process->getExitCode())->toBe(0); + // expect($process->getExitCode())->toBe(0); return preg_replace('#\\x1b[[][^A-Za-z]*[A-Za-z]#', '', $process->getOutput()); }; test('parallel', function () use ($run) { - expect($run())->toContain('Tests: 2 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 15 skipped, 635 passed (1573 assertions)') + expect($run())->toContain('Tests: 2 deprecated, 3 warnings, 4 incomplete, 1 notice, 4 todos, 9 skipped, 690 passed (1684 assertions)') ->toContain('Parallel: 3 processes'); })->skip(PHP_OS_FAMILY === 'Windows'); diff --git a/tests/Visual/Todo.php b/tests/Visual/Todo.php index 3a396a21..edf1bb4e 100644 --- a/tests/Visual/Todo.php +++ b/tests/Visual/Todo.php @@ -25,9 +25,9 @@ $snapshot = function ($name) { }; test('todo', function () use ($run, $snapshot) { - expect($run('--todo', false))->toContain($snapshot('todo')); + expect($run('--todos', false))->toContain($snapshot('todo')); })->skip(PHP_OS_FAMILY === 'Windows'); test('todo in parallel', function () use ($run, $snapshot) { - expect($run('--todo', true))->toContain($snapshot('todo')); + expect($run('--todos', true))->toContain($snapshot('todo')); })->skip(PHP_OS_FAMILY === 'Windows');