mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 07:47:22 +01:00
Compare commits
264 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b8feed08a | |||
| 2fe8e07cf3 | |||
| d2c907868e | |||
| a2900a5e09 | |||
| df934bacd9 | |||
| b0f03c278d | |||
| b59b321249 | |||
| 82d6991cf8 | |||
| d693d99379 | |||
| 50c1136be8 | |||
| dd491e516c | |||
| 078aab0d3d | |||
| 89c9f4b428 | |||
| 2148e896e2 | |||
| 7ba49b2e3e | |||
| 54a285f7e3 | |||
| 3ed20d059c | |||
| 92b6800f28 | |||
| 29cfd1a2dc | |||
| 45c09ea0ed | |||
| 424e24d530 | |||
| 26b2e3561a | |||
| 60aea6798d | |||
| fac3fe3f55 | |||
| 17fac0a488 | |||
| 6abc2207b2 | |||
| 885d224c5d | |||
| 12441deab8 | |||
| 8852fd14ce | |||
| e3814e6d9c | |||
| e19eba0942 | |||
| b6e2763731 | |||
| f75a3ee865 | |||
| d707c2f208 | |||
| a43b86d9eb | |||
| 5279d5e913 | |||
| df7fb92e03 | |||
| 95c3418313 | |||
| 67a8be9347 | |||
| 5d7f262f4a | |||
| 23eebc8127 | |||
| 3b435e460e | |||
| b52e9826e7 | |||
| ba49dd0499 | |||
| f9f6f28950 | |||
| f017015d1e | |||
| 29b4ee33bb | |||
| 03dc11c2f6 | |||
| b79ba5098b | |||
| 3c418d82e6 | |||
| 73ede2e344 | |||
| 266d891488 | |||
| c71490b472 | |||
| 07705079e2 | |||
| d88c268426 | |||
| a1b142e885 | |||
| a50d739e50 | |||
| f82bb56d89 | |||
| de593c3b93 | |||
| eedd5d80a0 | |||
| 5bbdd4f41e | |||
| 3fd24d96d3 | |||
| 7bea51fe09 | |||
| cdf0a38145 | |||
| bb2474ccbe | |||
| 01143a6f84 | |||
| b93485c2ed | |||
| 04681690b6 | |||
| 200877d691 | |||
| feb6417f45 | |||
| e7585a4ba2 | |||
| c33ab0f670 | |||
| 78181f66f6 | |||
| 925636be61 | |||
| 6be131d602 | |||
| f950f57eed | |||
| c6369feaea | |||
| 1bdd3f4908 | |||
| 924e095dfc | |||
| 72041a4a21 | |||
| d576446639 | |||
| 3fbec70ed3 | |||
| d177ab5ec2 | |||
| ba08f2c11e | |||
| 13a8aee049 | |||
| e4f5a284a6 | |||
| 6671b266da | |||
| 3728bd8e0f | |||
| c3616edbc8 | |||
| 21143b2693 | |||
| 006f9232cc | |||
| d1b61a34de | |||
| 896317ac97 | |||
| 4fd5c0edd4 | |||
| e2c5d6d857 | |||
| 8057fe4bc2 | |||
| ebc9690301 | |||
| 049ce1845e | |||
| faa6cd7deb | |||
| 1f9362c4e7 | |||
| 36fd18bcc8 | |||
| aa352317cb | |||
| edcd2cb50e | |||
| be8a64e4b8 | |||
| 2336bc0f65 | |||
| da82eecbae | |||
| 4855987ba8 | |||
| a493db1873 | |||
| 4f677a6cc2 | |||
| 228f2deb64 | |||
| 0fadf9a02c | |||
| 2b138ad76b | |||
| e3e4815b55 | |||
| f76f353c32 | |||
| 16b9f54dc3 | |||
| 281166475e | |||
| 23805cb5d6 | |||
| 76d0f9cfc1 | |||
| 5b083e4eb1 | |||
| f48694b18a | |||
| 8fa59ddbf0 | |||
| 2619db4026 | |||
| f3a71fb100 | |||
| 04fafe742c | |||
| cad8a41e6d | |||
| 1567923cda | |||
| c7116afcae | |||
| 4e184b2f90 | |||
| 9b5f664f00 | |||
| 0e89525ea8 | |||
| 0b6cdf8f02 | |||
| 5f63d959e1 | |||
| be7fe41179 | |||
| 204f343831 | |||
| aa230a1716 | |||
| 97f98569bc | |||
| 1318bf9830 | |||
| 3b58f946f1 | |||
| dfc2470764 | |||
| f650978dd0 | |||
| c6ba469e68 | |||
| 3a9997f9af | |||
| fb6cb891be | |||
| 76beda74c9 | |||
| 0398d4223b | |||
| 360eeb4c7d | |||
| 79b4224a35 | |||
| 3c79c893c9 | |||
| a11f507191 | |||
| 6413f7040f | |||
| 278af4b835 | |||
| fe885fbfb6 | |||
| 61b2c426e4 | |||
| 4272d49fb7 | |||
| 014ab3b957 | |||
| 09a0a64f20 | |||
| bf79f7c63f | |||
| 36b879f97d | |||
| bcc206d183 | |||
| 1e7b6a0396 | |||
| 57a1ccd213 | |||
| 708b4b1d49 | |||
| 3695736b3a | |||
| 8cc9580253 | |||
| e1fbf56f3d | |||
| 50cd1056eb | |||
| cfe6a6728f | |||
| 38344c99f1 | |||
| 98ed779424 | |||
| 943707cbcd | |||
| 940e246f27 | |||
| 439ebcdcaf | |||
| d2db71bb78 | |||
| d85432933c | |||
| 3cfadee2bb | |||
| 051ca73cae | |||
| 50a273f1f1 | |||
| ffe5dde7f0 | |||
| 7e1747a364 | |||
| 356b9c01c7 | |||
| 4009177e56 | |||
| 46d1d46384 | |||
| 128ff1006f | |||
| 64bb853720 | |||
| 330dafa294 | |||
| a51c354268 | |||
| cc1abe7f06 | |||
| 0c16942d37 | |||
| fa413aafbb | |||
| 75f17bb118 | |||
| 19ce733207 | |||
| 7529d44f81 | |||
| e4e4eb0a57 | |||
| c8eb1397b4 | |||
| c4c768dcaa | |||
| 8c60a9fff5 | |||
| 206e613711 | |||
| 5fb81e9eb4 | |||
| d130a1aea0 | |||
| 03201cb8b7 | |||
| 46e900e8d2 | |||
| f0f79ab244 | |||
| 1e61144cd2 | |||
| 2751bc9674 | |||
| e2deaae6c9 | |||
| 1aec8bac55 | |||
| 32ef377284 | |||
| ab017e17e2 | |||
| 832882160f | |||
| e03d015120 | |||
| 819825bdd2 | |||
| d29c789788 | |||
| b4c45af785 | |||
| b4bf799d75 | |||
| 9f62f2d483 | |||
| 679082e805 | |||
| 42f0bd052e | |||
| 01b9bab55f | |||
| 3eb0a95955 | |||
| d11157f7b2 | |||
| 1f2ec74d6c | |||
| 1241e929b1 | |||
| db7c4b174f | |||
| 460ce45349 | |||
| 8e203e914e | |||
| 64a8ed04ff | |||
| 234b6847ad | |||
| 933820c8d3 | |||
| 4e9587da59 | |||
| 60a5db14ba | |||
| 7ea3e02afa | |||
| 421c52fb74 | |||
| a3644f7efa | |||
| c7326f430b | |||
| 9ea51caf3f | |||
| cb4c9563bd | |||
| fac44d9afe | |||
| 6e27c6d85d | |||
| 9a0cfaf339 | |||
| 321b3e8df3 | |||
| bff97418ed | |||
| a47ad6a1d3 | |||
| 74c14808cf | |||
| eff2d7f613 | |||
| e135979f34 | |||
| 15edde8e87 | |||
| 211f5c2433 | |||
| 5d58d58f71 | |||
| d5a4008d3e | |||
| 1bf802268f | |||
| 807a4b004f | |||
| 53a8c7b05e | |||
| ef5715ce10 | |||
| 0c04882389 | |||
| 323c5f211f | |||
| f7a3fa15f4 | |||
| 6dd3ca20e4 | |||
| d9ea378819 | |||
| 6aa0356570 | |||
| 45b0d5d899 | |||
| 5be1edd7b7 | |||
| 75f7ee0acf | |||
| d0a74931dd | |||
| 0738e113ad |
@ -14,5 +14,5 @@ trim_trailing_whitespace = true
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -1,5 +1,5 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: nunomaduro
|
||||
github: [nunomaduro,owenvoke,olivernybroe,octoper]
|
||||
patreon: nunomaduro
|
||||
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L
|
||||
|
||||
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
| Q | A
|
||||
| ------------- | ---
|
||||
| Bug fix? | yes/no
|
||||
| New feature? | yes/no
|
||||
| Fixed tickets | #... <!-- #-prefixed issue number(s), if any -->
|
||||
|
||||
<!--
|
||||
- Replace this comment by a description of what your PR is solving.
|
||||
-->
|
||||
|
||||
25
.github/workflows/changelog.yml
vendored
25
.github/workflows/changelog.yml
vendored
@ -5,6 +5,7 @@ on:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
- CHANGELOG.md
|
||||
- .github/workflows/changelog.yml
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
paths:
|
||||
@ -13,19 +14,25 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
if: github.repository == 'pestphp/pest'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Checkout website repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
token: ${{ secrets.CHANGELOG_KEY }}
|
||||
repository: pestphp/website
|
||||
path: pestphp-website
|
||||
repository: pestphp/docs
|
||||
path: pestphp-docs
|
||||
ref: master
|
||||
|
||||
- name: Read CHANGELOG.md
|
||||
id: package
|
||||
uses: juliangruber/read-file-action@v1
|
||||
with:
|
||||
path: ./CHANGELOG.md
|
||||
|
||||
- name: Add file headers
|
||||
uses: DamianReeves/write-file-action@v1.0
|
||||
with:
|
||||
@ -34,19 +41,23 @@ jobs:
|
||||
---
|
||||
title: Changelog
|
||||
description: Changelog
|
||||
extends: _layouts.documentation
|
||||
section: content
|
||||
---
|
||||
${{ steps.package.outputs.content }}
|
||||
|
||||
----
|
||||
|
||||
Next section: [Upgrade Guide →](/docs/upgrade-guide)
|
||||
write-mode: overwrite
|
||||
|
||||
- name: Copy CHANGELOG to website repository
|
||||
run: cp CHANGELOG.md pestphp-website/source/docs/changelog.md
|
||||
run: cp CHANGELOG.md pestphp-docs/changelog.md
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
token: ${{ secrets.CHANGELOG_KEY }}
|
||||
commit-message: Update changelog.md
|
||||
committer: GitHub Action <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
title: 'Update changelog.md'
|
||||
path: ./pestphp-website
|
||||
path: ./pestphp-docs
|
||||
|
||||
46
.github/workflows/formats.yml
vendored
46
.github/workflows/formats.yml
vendored
@ -1,46 +0,0 @@
|
||||
name: Formats
|
||||
|
||||
on: ['push', 'pull_request']
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
php: [7.4]
|
||||
dependency-version: [prefer-lowest, prefer-stable]
|
||||
|
||||
name: Formats P${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }}
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.composer/cache/files
|
||||
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: dom, mbstring, zip
|
||||
tools: prestissimo
|
||||
coverage: pcov
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer update --${{ matrix.dependency-version }} --no-interaction --prefer-dist
|
||||
|
||||
- name: Coding Style Checks
|
||||
run: |
|
||||
vendor/bin/rector process src --dry-run
|
||||
vendor/bin/php-cs-fixer fix -v --dry-run
|
||||
|
||||
- name: Type Checks
|
||||
run: vendor/bin/phpstan analyse --ansi
|
||||
51
.github/workflows/static.yml
vendored
Normal file
51
.github/workflows/static.yml
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
name: Static Analysis
|
||||
|
||||
on: ['push', 'pull_request']
|
||||
|
||||
jobs:
|
||||
cs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
name: Code Style
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.4
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
|
||||
- name: Install Dependencies
|
||||
run: composer update --no-interaction --no-progress
|
||||
|
||||
- name: Run PHP-CS-Fixer
|
||||
run: vendor/bin/php-cs-fixer fix -v --allow-risky=yes --dry-run
|
||||
|
||||
phpstan:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
dependency-version: [prefer-lowest, prefer-stable]
|
||||
|
||||
name: PHPStan ${{ matrix.dependency-version }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.4
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
|
||||
- name: Install Dependencies
|
||||
run: composer update --prefer-stable --no-interaction --no-progress
|
||||
|
||||
- name: Run PHPStan
|
||||
run: vendor/bin/phpstan analyse --no-progress
|
||||
34
.github/workflows/tests.yml
vendored
34
.github/workflows/tests.yml
vendored
@ -6,43 +6,39 @@ jobs:
|
||||
ci:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
php: [7.3, 7.4]
|
||||
php: ['7.3', '7.4', '8.0']
|
||||
dependency-version: [prefer-lowest, prefer-stable]
|
||||
|
||||
name: Tests P${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }}
|
||||
name: PHP ${{ matrix.php }} - ${{ matrix.os }} - ${{ matrix.dependency-version }}
|
||||
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ~/.composer/cache/files
|
||||
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: dom, mbstring, zip
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
|
||||
- name: Install Composer dependencies
|
||||
run: composer update --${{ matrix.dependency-version }} --no-interaction --prefer-dist
|
||||
- name: Setup Problem Matches
|
||||
run: |
|
||||
echo "::add-matcher::${{ runner.tool_cache }}/php.json"
|
||||
echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
- name: Install PHP 7 dependencies
|
||||
run: composer update --${{ matrix.dependency-version }} --no-interaction --no-progress
|
||||
if: "matrix.php < 8"
|
||||
|
||||
- name: Install PHP 8 dependencies
|
||||
run: composer update --${{ matrix.dependency-version }} --ignore-platform-req=php --no-interaction --no-progress
|
||||
if: "matrix.php >= 8"
|
||||
|
||||
- name: Unit Tests
|
||||
run: php bin/pest --colors=always --exclude-group=integration
|
||||
|
||||
- name: Integration Tests
|
||||
run: php bin/pest --colors=always --group=integration
|
||||
|
||||
- name: Setup problem matchers for PHP
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
|
||||
|
||||
- name: Setup problem matchers for Pest
|
||||
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
1
.php_cs
1
.php_cs
@ -3,7 +3,6 @@
|
||||
$finder = PhpCsFixer\Finder::create()
|
||||
->in(__DIR__ . DIRECTORY_SEPARATOR . 'tests')
|
||||
->in(__DIR__ . DIRECTORY_SEPARATOR . 'bin')
|
||||
->in(__DIR__ . DIRECTORY_SEPARATOR . 'compiled')
|
||||
->in(__DIR__ . DIRECTORY_SEPARATOR . 'scripts')
|
||||
->in(__DIR__ . DIRECTORY_SEPARATOR . 'stubs')
|
||||
->in(__DIR__ . DIRECTORY_SEPARATOR . 'src')
|
||||
|
||||
127
CHANGELOG.md
127
CHANGELOG.md
@ -4,7 +4,132 @@ 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/).
|
||||
|
||||
## [Unreleased]
|
||||
## [v1.0.0 (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))
|
||||
- Fowards `$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 conflit ([#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
|
||||
|
||||
11
README.md
11
README.md
@ -1,7 +1,7 @@
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/pestphp/art/master/readme.png" width="600" alt="PEST">
|
||||
<p align="center">
|
||||
<a href="https://github.com/pestphp/pest/actions"><img alt="GitHub Workflow Status (master)" src="https://img.shields.io/github/workflow/status/pestphp/pest/Continuous Integration/master"></a>
|
||||
<a href="https://github.com/pestphp/pest/actions"><img alt="GitHub Workflow Status (master)" src="https://img.shields.io/github/workflow/status/pestphp/pest/Tests/master"></a>
|
||||
<a href="https://packagist.org/packages/pestphp/pest"><img alt="Total Downloads" src="https://img.shields.io/packagist/dt/pestphp/pest"></a>
|
||||
<a href="https://packagist.org/packages/pestphp/pest"><img alt="Latest Version" src="https://img.shields.io/packagist/v/pestphp/pest"></a>
|
||||
<a href="https://packagist.org/packages/pestphp/pest"><img alt="License" src="https://img.shields.io/packagist/l/pestphp/pest"></a>
|
||||
@ -15,4 +15,13 @@
|
||||
- Follow us on Twitter: **[@pestphp »](https://twitter.com/pestphp)**
|
||||
- Join us on the Discord Server: **[discord.gg/bMAJv82 »](https://discord.gg/bMAJv82)**
|
||||
|
||||
## Pest Sponsors
|
||||
|
||||
We would like to extend our thanks to the following sponsors for funding Pest development. If you are interested in becoming a sponsor, please visit the Nuno Maduro's [Sponsors page](https://github.com/sponsors/nunomaduro).
|
||||
|
||||
### Premium Sponsors
|
||||
|
||||
- **[Scout APM](https://scoutapm.com)**
|
||||
- **[Akaunting](https://akaunting.com)**
|
||||
|
||||
Pest was created by **[Nuno Maduro](https://twitter.com/enunomaduro)** under the **[Sponsorware license](https://github.com/sponsorware/docs)**. It got open-sourced and is now licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.
|
||||
|
||||
16
RELEASE.md
Normal file
16
RELEASE.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Release process
|
||||
|
||||
When releasing a new version of Pest there are some checks and updates that need to be done:
|
||||
|
||||
- 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
|
||||
- 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 "docs: update changelog"`
|
||||
- Push the changes to GitHub
|
||||
- Check that the CI is passing as expected: [github.com/pestphp/pest/actions](https://github.com/pestphp/pest/actions)
|
||||
- Tag and push the tag with `git tag vX.X.X && git push --tags`
|
||||
|
||||
### Plugins
|
||||
|
||||
Plugins should be versioned using the same major (or minor for `0.x` releases) version as Pest core.
|
||||
10
bin/pest
10
bin/pest
@ -6,6 +6,7 @@ use Pest\Actions\ValidatesEnvironment;
|
||||
use Pest\Console\Command;
|
||||
use Pest\Support\Container;
|
||||
use Pest\TestSuite;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
@ -18,16 +19,21 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
if (file_exists($vendorPath)) {
|
||||
include_once $vendorPath;
|
||||
$autoloadPath = $vendorPath;
|
||||
} else {
|
||||
include_once $localPath;
|
||||
$autoloadPath = $localPath;
|
||||
}
|
||||
|
||||
(new Provider())->register();
|
||||
|
||||
$rootPath = getcwd();
|
||||
// get $rootPath based on $autoloadPath
|
||||
$rootPath = dirname($autoloadPath, 2);
|
||||
|
||||
$testSuite = TestSuite::getInstance($rootPath);
|
||||
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, true);
|
||||
|
||||
$isDecorated = (new ArgvInput())->getParameterOption('--colors', 'always') !== 'never';
|
||||
$output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated);
|
||||
|
||||
$container = Container::getInstance();
|
||||
$container->add(TestSuite::class, $testSuite);
|
||||
|
||||
1926
compiled/globals.php
1926
compiled/globals.php
File diff suppressed because it is too large
Load Diff
@ -17,21 +17,21 @@
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.3",
|
||||
"nunomaduro/collision": "^5.0.0-BETA2",
|
||||
"pestphp/pest-plugin": "^0.2",
|
||||
"pestphp/pest-plugin-coverage": "^0.2",
|
||||
"pestphp/pest-plugin-init": "^0.2",
|
||||
"phpunit/phpunit": "^9.1.4",
|
||||
"sebastian/environment": "^5.1"
|
||||
"php": "^7.3 || ^8.0",
|
||||
"nunomaduro/collision": "^5.0",
|
||||
"pestphp/pest-plugin": "^1.0",
|
||||
"pestphp/pest-plugin-coverage": "^1.0",
|
||||
"pestphp/pest-plugin-expectations": "^1.0",
|
||||
"pestphp/pest-plugin-init": "^1.0",
|
||||
"phpunit/phpunit": ">= 9.3.7 <= 9.5.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Pest\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/globals.php",
|
||||
"compiled/globals.php"
|
||||
"src/Functions.php",
|
||||
"src/Pest.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
@ -43,16 +43,11 @@
|
||||
]
|
||||
},
|
||||
"require-dev": {
|
||||
"ergebnis/phpstan-rules": "^0.14.4",
|
||||
"friendsofphp/php-cs-fixer": "^2.16.3",
|
||||
"illuminate/console": "^7.10.3",
|
||||
"illuminate/support": "^7.10.3",
|
||||
"mockery/mockery": "^1.3.1",
|
||||
"phpstan/phpstan": "^0.12.25",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.2",
|
||||
"rector/rector": "^0.7.25",
|
||||
"symfony/var-dumper": "^5.0.8",
|
||||
"thecodingmachine/phpstan-strict-rules": "^0.12.0"
|
||||
"illuminate/console": "^8.0",
|
||||
"illuminate/support": "^8.0",
|
||||
"laravel/dusk": "^6.9.1",
|
||||
"mockery/mockery": "^1.4.1",
|
||||
"pestphp/pest-dev-tools": "dev-master"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
@ -64,13 +59,12 @@
|
||||
"bin/pest"
|
||||
],
|
||||
"scripts": {
|
||||
"compile": "@php ./scripts/compile.php",
|
||||
"lint": "rector process src && php-cs-fixer fix -v",
|
||||
"test:lint": "php-cs-fixer fix -v --dry-run && rector process src --dry-run",
|
||||
"test:types": "phpstan analyse --ansi",
|
||||
"lint": "php-cs-fixer fix -v",
|
||||
"test:lint": "php-cs-fixer fix -v --dry-run",
|
||||
"test:types": "phpstan analyse --ansi --memory-limit=0",
|
||||
"test:unit": "php bin/pest --colors=always --exclude-group=integration",
|
||||
"test:integration": "php bin/pest --colors=always --group=integration",
|
||||
"test:update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always",
|
||||
"update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always",
|
||||
"test": [
|
||||
"@test:lint",
|
||||
"@test:types",
|
||||
@ -80,7 +74,12 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.2.x-dev"
|
||||
"dev-master": "1.x-dev"
|
||||
},
|
||||
"pest": {
|
||||
"plugins": [
|
||||
"Pest\\Plugins\\Version"
|
||||
]
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
|
||||
15
phpstan.neon
15
phpstan.neon
@ -7,17 +7,26 @@ parameters:
|
||||
level: max
|
||||
paths:
|
||||
- src
|
||||
excludes_analyse:
|
||||
- src/globals.php
|
||||
|
||||
checkMissingIterableValueType: true
|
||||
checkGenericClassInNonGenericObjectType: false
|
||||
reportUnmatchedIgnoredErrors: true
|
||||
|
||||
ignoreErrors:
|
||||
- "#type mixed is not subtype of native#"
|
||||
- "#Undefined variable: \\$this#"
|
||||
- "#is not allowed to extend#"
|
||||
- "#Language construct eval#"
|
||||
- "# with null as default value#"
|
||||
- "#Using \\$this in static method#"
|
||||
- "#has parameter \\$closure with default value.#"
|
||||
- "#has parameter \\$description with default value.#"
|
||||
- "#Method Pest\\\\Support\\\\Reflection::getParameterClassName\\(\\) has a nullable return type declaration.#"
|
||||
-
|
||||
message: '#Call to an undefined method PHPUnit\\Framework\\Test::getName\(\)#'
|
||||
path: src/TeamCity.php
|
||||
-
|
||||
message: '#invalid typehint type Pest\\Concerns\\TestCase#'
|
||||
path: src/TeamCity.php
|
||||
-
|
||||
message: '#is not subtype of native type PHPUnit\\Framework\\Test#'
|
||||
path: src/TeamCity.php
|
||||
|
||||
@ -8,9 +8,9 @@
|
||||
<directory suffix=".php">./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">./src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</include>
|
||||
</coverage>
|
||||
</phpunit>
|
||||
|
||||
16
rector.yaml
16
rector.yaml
@ -1,16 +0,0 @@
|
||||
# rector.yaml
|
||||
parameters:
|
||||
sets:
|
||||
- 'action-injection-to-constructor-injection'
|
||||
- 'array-str-functions-to-static-call'
|
||||
- 'celebrity'
|
||||
- 'doctrine'
|
||||
- 'phpstan'
|
||||
- 'phpunit-code-quality'
|
||||
- 'solid'
|
||||
- 'early-return'
|
||||
- 'doctrine-code-quality'
|
||||
- 'code-quality'
|
||||
- 'php71'
|
||||
- 'php72'
|
||||
- 'php73'
|
||||
@ -5,12 +5,16 @@ declare(strict_types=1);
|
||||
namespace Pest\Actions;
|
||||
|
||||
use NunoMaduro\Collision\Adapters\Phpunit\Printer;
|
||||
use Pest\TeamCity;
|
||||
use PHPUnit\TextUI\DefaultResultPrinter;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class AddsDefaults
|
||||
{
|
||||
private const PRINTER = 'printer';
|
||||
|
||||
/**
|
||||
* Adds default arguments to the given `arguments` array.
|
||||
*
|
||||
@ -20,8 +24,12 @@ final class AddsDefaults
|
||||
*/
|
||||
public static function to(array $arguments): array
|
||||
{
|
||||
if (!array_key_exists('printer', $arguments)) {
|
||||
$arguments['printer'] = new Printer(null, $arguments['verbose'] ?? false, $arguments['colors'] ?? 'always');
|
||||
if (!array_key_exists(self::PRINTER, $arguments)) {
|
||||
$arguments[self::PRINTER] = new Printer(null, $arguments['verbose'] ?? false, $arguments['colors'] ?? DefaultResultPrinter::COLOR_ALWAYS);
|
||||
}
|
||||
|
||||
if ($arguments[self::PRINTER] === \PHPUnit\Util\Log\TeamCity::class) {
|
||||
$arguments[self::PRINTER] = new TeamCity($arguments['verbose'] ?? false, $arguments['colors'] ?? DefaultResultPrinter::COLOR_ALWAYS);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
|
||||
@ -21,6 +21,7 @@ final class LoadStructure
|
||||
* @var array<int, string>
|
||||
*/
|
||||
private const STRUCTURE = [
|
||||
'Expectations.php',
|
||||
'Datasets.php',
|
||||
'Helpers.php',
|
||||
'Pest.php',
|
||||
|
||||
@ -6,8 +6,7 @@ namespace Pest\Actions;
|
||||
|
||||
use Pest\Exceptions\AttributeNotSupportedYet;
|
||||
use Pest\Exceptions\FileOrFolderNotFound;
|
||||
use PHPUnit\TextUI\Configuration\Configuration;
|
||||
use PHPUnit\TextUI\Configuration\Registry;
|
||||
use PHPUnit\TextUI\XmlConfiguration\Loader;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -30,9 +29,7 @@ final class ValidatesConfiguration
|
||||
throw new FileOrFolderNotFound('phpunit.xml');
|
||||
}
|
||||
|
||||
$configuration = Registry::getInstance()
|
||||
->get($arguments[self::CONFIGURATION_KEY])
|
||||
->phpunit();
|
||||
$configuration = (new Loader())->load($arguments[self::CONFIGURATION_KEY])->phpunit();
|
||||
|
||||
if ($configuration->processIsolation()) {
|
||||
throw new AttributeNotSupportedYet('processIsolation', 'true');
|
||||
|
||||
@ -7,7 +7,9 @@ namespace Pest\Concerns;
|
||||
use Closure;
|
||||
use Pest\Support\ExceptionTrace;
|
||||
use Pest\TestSuite;
|
||||
use PHPUnit\Framework\ExecutionOrderDependency;
|
||||
use PHPUnit\Util\Test;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* To avoid inheritance conflicts, all the fields related
|
||||
@ -53,6 +55,24 @@ trait TestCase
|
||||
$this->setGroups($groups);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add dependencies to the test case and map them to instances of ExecutionOrderDependency.
|
||||
*/
|
||||
public function addDependencies(array $tests): void
|
||||
{
|
||||
$className = get_class($this);
|
||||
|
||||
$tests = array_map(function (string $test) use ($className): ExecutionOrderDependency {
|
||||
if (strpos($test, '::') === false) {
|
||||
$test = "{$className}::{$test}";
|
||||
}
|
||||
|
||||
return new ExecutionOrderDependency($test, null, '');
|
||||
}, $tests);
|
||||
|
||||
$this->setDependencies($tests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the test case name. Note that, in Pest
|
||||
* we ignore withDataset argument as the description
|
||||
@ -63,6 +83,11 @@ trait TestCase
|
||||
return $this->__description;
|
||||
}
|
||||
|
||||
public static function __getFileName(): string
|
||||
{
|
||||
return self::$__filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called before the first test of this test class is run.
|
||||
*/
|
||||
@ -129,16 +154,25 @@ trait TestCase
|
||||
|
||||
/**
|
||||
* Runs the test.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function __test(): void
|
||||
public function __test()
|
||||
{
|
||||
$this->__callClosure($this->__test, func_get_args());
|
||||
return $this->__callClosure($this->__test, func_get_args());
|
||||
}
|
||||
|
||||
private function __callClosure(Closure $closure, array $arguments): void
|
||||
/**
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Throwable
|
||||
*/
|
||||
private function __callClosure(Closure $closure, array $arguments)
|
||||
{
|
||||
ExceptionTrace::ensure(function () use ($closure, $arguments) {
|
||||
call_user_func_array(Closure::bind($closure, $this, get_class($this)), $arguments);
|
||||
return ExceptionTrace::ensure(function () use ($closure, $arguments) {
|
||||
return call_user_func_array(Closure::bind($closure, $this, get_class($this)), $arguments);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,8 @@ use Pest\Actions\ValidatesConfiguration;
|
||||
use Pest\Contracts\Plugins\AddsOutput;
|
||||
use Pest\Contracts\Plugins\HandlesArguments;
|
||||
use Pest\Plugin\Loader;
|
||||
use Pest\Plugins\Version;
|
||||
use Pest\Support\Container;
|
||||
use Pest\TestSuite;
|
||||
use PHPUnit\Framework\TestSuite as BaseTestSuite;
|
||||
use PHPUnit\TextUI\Command as BaseCommand;
|
||||
@ -139,4 +141,14 @@ final class Command extends BaseCommand
|
||||
|
||||
exit($result);
|
||||
}
|
||||
|
||||
protected function showHelp(): void
|
||||
{
|
||||
/** @var Version $version */
|
||||
$version = Container::getInstance()->get(Version::class);
|
||||
$version->handleArguments(['--version']);
|
||||
parent::showHelp();
|
||||
|
||||
(new Help($this->output))();
|
||||
}
|
||||
}
|
||||
|
||||
37
src/Console/Help.php
Normal file
37
src/Console/Help.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Console;
|
||||
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Help
|
||||
{
|
||||
/** @var array<int, string> */
|
||||
private const HELP_MESSAGES = [
|
||||
'<comment>Pest Options:</comment>',
|
||||
' <info>--init</info> Initialise a standard Pest configuration',
|
||||
' <info>--coverage</info> Enable coverage and output to standard output',
|
||||
' <info>--min=<fg=cyan><N></></info> Set the minimum required coverage percentage (<N>), and fail if not met',
|
||||
' <info>--group=<fg=cyan><name></></info> Only runs tests from the specified group(s)',
|
||||
];
|
||||
|
||||
/** @var OutputInterface */
|
||||
private $output;
|
||||
|
||||
public function __construct(OutputInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
public function __invoke(): void
|
||||
{
|
||||
foreach (self::HELP_MESSAGES as $message) {
|
||||
$this->output->writeln($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
66
src/Console/Thanks.php
Normal file
66
src/Console/Thanks.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Console;
|
||||
|
||||
use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Thanks
|
||||
{
|
||||
/** @var array<int, string> */
|
||||
private const FUNDING_MESSAGES = [
|
||||
'',
|
||||
' - Star or contribute to Pest:',
|
||||
' <options=bold>https://github.com/pestphp/pest</>',
|
||||
' - Tweet something about Pest on Twitter:',
|
||||
' <options=bold>https://twitter.com/pestphp</>',
|
||||
' - Sponsor the creator:',
|
||||
' <options=bold>https://github.com/sponsors/nunomaduro</>',
|
||||
];
|
||||
|
||||
/** @var OutputInterface */
|
||||
private $output;
|
||||
|
||||
public function __construct(OutputInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the user to support Pest.
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
$wantsToSupport = (new SymfonyQuestionHelper())->ask(
|
||||
new ArrayInput([]),
|
||||
$this->output,
|
||||
new ConfirmationQuestion(
|
||||
'Can you quickly <options=bold>star our GitHub repository</>? 🙏🏻',
|
||||
true,
|
||||
)
|
||||
);
|
||||
|
||||
if ($wantsToSupport === true) {
|
||||
if (PHP_OS_FAMILY == 'Darwin') {
|
||||
exec('open https://github.com/pestphp/pest');
|
||||
}
|
||||
if (PHP_OS_FAMILY == 'Windows') {
|
||||
exec('start https://github.com/pestphp/pest');
|
||||
}
|
||||
if (PHP_OS_FAMILY == 'Linux') {
|
||||
exec('xdg-open https://github.com/pestphp/pest');
|
||||
}
|
||||
}
|
||||
|
||||
foreach (self::FUNDING_MESSAGES as $message) {
|
||||
$this->output->writeln($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,14 +18,14 @@ final class Datasets
|
||||
/**
|
||||
* Holds the datasets.
|
||||
*
|
||||
* @var array<string, \Closure|iterable<int, mixed>>
|
||||
* @var array<int|string, Closure|iterable<int|string, mixed>>
|
||||
*/
|
||||
private static $datasets = [];
|
||||
|
||||
/**
|
||||
* Sets the given.
|
||||
*
|
||||
* @param Closure|iterable<int, mixed> $data
|
||||
* @param Closure|iterable<int|string, mixed> $data
|
||||
*/
|
||||
public static function set(string $name, $data): void
|
||||
{
|
||||
@ -37,7 +37,7 @@ final class Datasets
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Closure|iterable<int, mixed>
|
||||
* @return Closure|iterable<int|string, mixed>
|
||||
*/
|
||||
public static function get(string $name)
|
||||
{
|
||||
@ -51,7 +51,7 @@ final class Datasets
|
||||
/**
|
||||
* Resolves the current dataset to an array value.
|
||||
*
|
||||
* @param Traversable<int, mixed>|Closure|iterable<int, mixed>|string|null $data
|
||||
* @param Traversable<int|string, mixed>|Closure|iterable<int|string, mixed>|string|null $data
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
@ -74,24 +74,45 @@ final class Datasets
|
||||
$data = iterator_to_array($data);
|
||||
}
|
||||
|
||||
$namedData = [];
|
||||
foreach ($data as $values) {
|
||||
$dataSetDescriptions = [];
|
||||
$dataSetValues = [];
|
||||
|
||||
foreach ($data as $key => $values) {
|
||||
$values = is_array($values) ? $values : [$values];
|
||||
|
||||
$name = $description . self::getDataSetDescription($values);
|
||||
$namedData[$name] = $values;
|
||||
$dataSetDescriptions[] = $description . self::getDataSetDescription($key, $values);
|
||||
$dataSetValues[] = $values;
|
||||
}
|
||||
|
||||
foreach (array_count_values($dataSetDescriptions) as $descriptionToCheck => $count) {
|
||||
if ($count > 1) {
|
||||
$index = 1;
|
||||
foreach ($dataSetDescriptions as $i => $dataSetDescription) {
|
||||
if ($dataSetDescription === $descriptionToCheck) {
|
||||
$dataSetDescriptions[$i] .= sprintf(' #%d', $index++);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$namedData = [];
|
||||
foreach ($dataSetDescriptions as $i => $dataSetDescription) {
|
||||
$namedData[$dataSetDescription] = $dataSetValues[$i];
|
||||
}
|
||||
|
||||
return $namedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $key
|
||||
* @param array<int, mixed> $data
|
||||
*/
|
||||
private static function getDataSetDescription(array $data): string
|
||||
private static function getDataSetDescription($key, array $data): string
|
||||
{
|
||||
$exporter = new Exporter();
|
||||
|
||||
return \sprintf(' with (%s)', $exporter->shortenedRecursiveExport($data));
|
||||
$nameInsert = is_string($key) ? \sprintf('data set "%s" ', $key) : '';
|
||||
|
||||
return \sprintf(' with %s(%s)', $nameInsert, $exporter->shortenedRecursiveExport($data));
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ final class TestCaseFactory
|
||||
/**
|
||||
* Holds the dataset, if any.
|
||||
*
|
||||
* @var Closure|iterable<int, mixed>|string|null
|
||||
* @var Closure|iterable<int|string, mixed>|string|null
|
||||
*/
|
||||
public $dataset;
|
||||
|
||||
@ -132,10 +132,14 @@ final class TestCaseFactory
|
||||
$proxies = $this->proxies;
|
||||
$factoryTest = $this->test;
|
||||
|
||||
$test = function () use ($chains, $proxies, $factoryTest): void {
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
$test = function () use ($chains, $proxies, $factoryTest) {
|
||||
$proxies->proxy($this);
|
||||
$chains->chain($this);
|
||||
call_user_func(Closure::bind($factoryTest, $this, get_class($this)), ...func_get_args());
|
||||
|
||||
return call_user_func(Closure::bind($factoryTest, $this, get_class($this)), ...func_get_args());
|
||||
};
|
||||
|
||||
$className = $this->makeClassFromFilename($this->filename);
|
||||
@ -153,8 +157,7 @@ final class TestCaseFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a fully qualified class name
|
||||
* from the given filename.
|
||||
* Makes a fully qualified class name from the given filename.
|
||||
*/
|
||||
public function makeClassFromFilename(string $filename): string
|
||||
{
|
||||
|
||||
@ -35,7 +35,7 @@ function beforeEach(Closure $closure = null): BeforeEachCall
|
||||
/**
|
||||
* Registers the given dataset.
|
||||
*
|
||||
* @param Closure|iterable $dataset
|
||||
* @param Closure|iterable<int|string, mixed> $dataset
|
||||
*/
|
||||
function dataset(string $name, $dataset): void
|
||||
{
|
||||
@ -43,8 +43,8 @@ function dataset(string $name, $dataset): void
|
||||
}
|
||||
|
||||
/**
|
||||
* The uses function adds the binds the
|
||||
* given arguments to test closures.
|
||||
* The uses function binds the given
|
||||
* arguments to test closures.
|
||||
*/
|
||||
function uses(string ...$classAndTraits): UsesCall
|
||||
{
|
||||
@ -62,7 +62,7 @@ function uses(string ...$classAndTraits): UsesCall
|
||||
*/
|
||||
function test(string $description = null, Closure $closure = null)
|
||||
{
|
||||
if ($description === null && TestSuite::getInstance()->test) {
|
||||
if ($description === null && TestSuite::getInstance()->test !== null) {
|
||||
return new HigherOrderTapProxy(TestSuite::getInstance()->test);
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ function afterEach(Closure $closure = null): AfterEachCall
|
||||
/**
|
||||
* Runs the given closure after all tests in the current file.
|
||||
*/
|
||||
function afterAll(Closure $closure = null): void
|
||||
function afterAll(Closure $closure): void
|
||||
{
|
||||
TestSuite::getInstance()->afterAll->set($closure);
|
||||
}
|
||||
@ -61,7 +61,8 @@ final class PestDatasetCommand extends Command
|
||||
$element = Str::singular($name);
|
||||
$contents = str_replace('{dataset_element}', $element, $contents);
|
||||
File::put($target, str_replace('{dataset_name}', $name, $contents));
|
||||
$message = sprintf('`%s` created successfully.', $relativePath);
|
||||
|
||||
$this->output->success(sprintf('`%s` created successfully.', $relativePath));
|
||||
$this->output->success($message);
|
||||
}
|
||||
}
|
||||
|
||||
41
src/Laravel/Commands/PestDuskCommand.php
Normal file
41
src/Laravel/Commands/PestDuskCommand.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Laravel\Commands;
|
||||
|
||||
use Laravel\Dusk\Console\DuskCommand;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class PestDuskCommand extends DuskCommand
|
||||
{
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'pest:dusk {--without-tty : Disable output to TTY}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Run the Dusk tests for the application with Pest';
|
||||
|
||||
/**
|
||||
* Get the PHP binary to execute.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
protected function binary()
|
||||
{
|
||||
if ('phpdbg' === PHP_SAPI) {
|
||||
return [PHP_BINARY, '-qrr', 'vendor/pestphp/pest/bin/pest'];
|
||||
}
|
||||
|
||||
return [PHP_BINARY, 'vendor/pestphp/pest/bin/pest'];
|
||||
}
|
||||
}
|
||||
@ -6,8 +6,8 @@ namespace Pest\Laravel\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Pest\Console\Thanks;
|
||||
use Pest\Exceptions\InvalidConsoleArgument;
|
||||
use Pest\Support\Str;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -35,14 +35,10 @@ final class PestInstallCommand extends Command
|
||||
{
|
||||
/* @phpstan-ignore-next-line */
|
||||
$pest = base_path('tests/Pest.php');
|
||||
/* @phpstan-ignore-next-line */
|
||||
$helpers = base_path('tests/Helpers.php');
|
||||
$stubs = $this->isLumen() ? 'stubs/Lumen' : 'stubs/Laravel';
|
||||
$stubs = 'stubs/Laravel';
|
||||
|
||||
foreach ([$pest, $helpers] as $file) {
|
||||
if (File::exists($file)) {
|
||||
throw new InvalidConsoleArgument(sprintf('%s already exist', $file));
|
||||
}
|
||||
if (File::exists($pest)) {
|
||||
throw new InvalidConsoleArgument(sprintf('%s already exist', $pest));
|
||||
}
|
||||
|
||||
File::copy(implode(DIRECTORY_SEPARATOR, [
|
||||
@ -51,22 +47,10 @@ final class PestInstallCommand extends Command
|
||||
'Pest.php',
|
||||
]), $pest);
|
||||
|
||||
File::copy(implode(DIRECTORY_SEPARATOR, [
|
||||
dirname(__DIR__, 3),
|
||||
$stubs,
|
||||
'Helpers.php',
|
||||
]), $helpers);
|
||||
|
||||
$this->output->success('`tests/Pest.php` created successfully.');
|
||||
$this->output->success('`tests/Helpers.php` created successfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this is a Lumen application.
|
||||
*/
|
||||
private function isLumen(): bool
|
||||
{
|
||||
/* @phpstan-ignore-next-line */
|
||||
return Str::startsWith(app()->version(), 'Lumen');
|
||||
if (!(bool) $this->option('no-interaction')) {
|
||||
(new Thanks($this->output))();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ final class PestTestCommand extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'pest:test {name : The name of the file} {--unit : Create a unit test}';
|
||||
protected $signature = 'pest:test {name : The name of the file} {--unit : Create a unit test} {--dusk : Create a Dusk test}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@ -36,7 +36,7 @@ final class PestTestCommand extends Command
|
||||
/** @var string $name */
|
||||
$name = $this->argument('name');
|
||||
|
||||
$type = ((bool) $this->option('unit')) ? 'Unit' : 'Feature';
|
||||
$type = ((bool) $this->option('unit')) ? 'Unit' : (((bool) $this->option('dusk')) ? 'Browser' : 'Feature');
|
||||
|
||||
$relativePath = sprintf('tests/%s/%s.php',
|
||||
$type,
|
||||
@ -64,7 +64,8 @@ final class PestTestCommand extends Command
|
||||
$name = Str::endsWith($name, 'test') ? mb_substr($name, 0, -4) : $name;
|
||||
|
||||
File::put($target, str_replace('{name}', $name, $contents));
|
||||
$message = sprintf('`%s` created successfully.', $relativePath);
|
||||
|
||||
$this->output->success(sprintf('`%s` created successfully.', $relativePath));
|
||||
$this->output->success($message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,9 @@ declare(strict_types=1);
|
||||
namespace Pest\Laravel;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Laravel\Dusk\Console\DuskCommand;
|
||||
use Pest\Laravel\Commands\PestDatasetCommand;
|
||||
use Pest\Laravel\Commands\PestDuskCommand;
|
||||
use Pest\Laravel\Commands\PestInstallCommand;
|
||||
use Pest\Laravel\Commands\PestTestCommand;
|
||||
|
||||
@ -22,6 +24,12 @@ final class PestServiceProvider extends ServiceProvider
|
||||
PestTestCommand::class,
|
||||
PestDatasetCommand::class,
|
||||
]);
|
||||
|
||||
if (class_exists(DuskCommand::class)) {
|
||||
$this->commands([
|
||||
PestDuskCommand::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,8 @@ use Pest\TestSuite;
|
||||
use SebastianBergmann\Exporter\Exporter;
|
||||
|
||||
/**
|
||||
* @method \Pest\Expectations\Expectation expect(mixed $value)
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class TestCall
|
||||
@ -75,7 +77,7 @@ final class TestCall
|
||||
* Runs the current test multiple times with
|
||||
* each item of the given `iterable`.
|
||||
*
|
||||
* @param \Closure|iterable<int, mixed>|string $data
|
||||
* @param \Closure|iterable<int|string, mixed>|string $data
|
||||
*/
|
||||
public function with($data): TestCall
|
||||
{
|
||||
@ -84,6 +86,18 @@ final class TestCall
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the test depends.
|
||||
*/
|
||||
public function depends(string ...$tests): TestCall
|
||||
{
|
||||
$this->testCaseFactory
|
||||
->factoryProxies
|
||||
->add(Backtrace::file(), Backtrace::line(), 'addDependencies', [$tests]);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the test suite only this test case.
|
||||
*/
|
||||
@ -95,7 +109,7 @@ final class TestCall
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the test groups(s).
|
||||
* Sets the test group(s).
|
||||
*/
|
||||
public function group(string ...$groups): TestCall
|
||||
{
|
||||
|
||||
10
src/Pest.php
Normal file
10
src/Pest.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest;
|
||||
|
||||
function version(): string
|
||||
{
|
||||
return '1.0.1';
|
||||
}
|
||||
39
src/Plugins/Version.php
Normal file
39
src/Plugins/Version.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Plugins;
|
||||
|
||||
use Pest\Contracts\Plugins\HandlesArguments;
|
||||
use function Pest\version;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Version implements HandlesArguments
|
||||
{
|
||||
/**
|
||||
* @var OutputInterface
|
||||
*/
|
||||
private $output;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the plugin.
|
||||
*/
|
||||
public function __construct(OutputInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
public function handleArguments(array $arguments): array
|
||||
{
|
||||
if (in_array('--version', $arguments, true)) {
|
||||
$this->output->writeln(
|
||||
sprintf('Pest %s', version()),
|
||||
);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ use Pest\Exceptions\TestCaseClassOrTraitNotFound;
|
||||
use Pest\Factories\TestCaseFactory;
|
||||
use Pest\Support\Str;
|
||||
use Pest\TestSuite;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -52,7 +53,7 @@ final class TestRepository
|
||||
if ((!is_dir($path) && $filename === $path) || (is_dir($path) && $startsWith($filename, $path))) {
|
||||
foreach ($classOrTraits as $class) {
|
||||
if (class_exists($class)) {
|
||||
if ($testCase->class !== \PHPUnit\Framework\TestCase::class) {
|
||||
if ($testCase->class !== TestCase::class) {
|
||||
throw new TestCaseAlreadyInUse($testCase->class, $class, $filename);
|
||||
}
|
||||
$testCase->class = $class;
|
||||
|
||||
@ -75,14 +75,15 @@ final class Container
|
||||
if ($constructor !== null) {
|
||||
$params = array_map(
|
||||
function (ReflectionParameter $param) use ($id) {
|
||||
$candidate = null;
|
||||
$candidate = Reflection::getParameterClassName($param);
|
||||
|
||||
if ($param->getType() !== null && $param->getType()->isBuiltin()) {
|
||||
$candidate = $param->getName();
|
||||
} elseif ($param->getClass() !== null) {
|
||||
$candidate = $param->getClass()->getName();
|
||||
} else {
|
||||
throw ShouldNotHappen::fromMessage(sprintf('The type of `$%s` in `%s` cannot be determined.', $id, $param->getName()));
|
||||
if ($candidate === null) {
|
||||
$type = $param->getType();
|
||||
if ($type !== null && $type->isBuiltin()) {
|
||||
$candidate = $param->getName();
|
||||
} else {
|
||||
throw ShouldNotHappen::fromMessage(sprintf('The type of `$%s` in `%s` cannot be determined.', $id, $param->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->get($candidate);
|
||||
|
||||
@ -17,11 +17,15 @@ final class ExceptionTrace
|
||||
/**
|
||||
* Ensures the given closure reports
|
||||
* the good execution context.
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Throwable
|
||||
*/
|
||||
public static function ensure(Closure $closure): void
|
||||
public static function ensure(Closure $closure)
|
||||
{
|
||||
try {
|
||||
$closure();
|
||||
return $closure();
|
||||
} catch (Throwable $throwable) {
|
||||
if (Str::startsWith($message = $throwable->getMessage(), self::UNDEFINED_METHOD)) {
|
||||
$message = str_replace(self::UNDEFINED_METHOD, 'Call to undefined method ', $message);
|
||||
|
||||
@ -76,8 +76,8 @@ final class HigherOrderMessage
|
||||
Reflection::setPropertyValue($throwable, 'file', $this->filename);
|
||||
Reflection::setPropertyValue($throwable, 'line', $this->line);
|
||||
|
||||
if ($throwable->getMessage() === sprintf(self::UNDEFINED_METHOD, $this->methodName)) {
|
||||
/** @var \ReflectionClass $reflection */
|
||||
if ($throwable->getMessage() === self::getUndefinedMethodMessage($target, $this->methodName)) {
|
||||
/** @var ReflectionClass $reflection */
|
||||
$reflection = new ReflectionClass($target);
|
||||
/* @phpstan-ignore-next-line */
|
||||
$reflection = $reflection->getParentClass() ?: $reflection;
|
||||
@ -87,4 +87,13 @@ final class HigherOrderMessage
|
||||
throw $throwable;
|
||||
}
|
||||
}
|
||||
|
||||
private static function getUndefinedMethodMessage(object $target, string $methodName): string
|
||||
{
|
||||
if (\PHP_MAJOR_VERSION >= 8) {
|
||||
return sprintf(sprintf(self::UNDEFINED_METHOD, sprintf('%s::%s()', get_class($target), $methodName)));
|
||||
}
|
||||
|
||||
return sprintf(self::UNDEFINED_METHOD, $methodName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ final class HigherOrderMessageCollection
|
||||
public function chain(object $target): void
|
||||
{
|
||||
foreach ($this->messages as $message) {
|
||||
$target = $message->call($target);
|
||||
$target = $message->call($target) ?? $target;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace Pest\Support;
|
||||
|
||||
use ReflectionClass;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -51,12 +52,12 @@ final class HigherOrderTapProxy
|
||||
try {
|
||||
// @phpstan-ignore-next-line
|
||||
return $this->target->{$property};
|
||||
} catch (\Throwable $throwable) {
|
||||
} catch (Throwable $throwable) {
|
||||
Reflection::setPropertyValue($throwable, 'file', Backtrace::file());
|
||||
Reflection::setPropertyValue($throwable, 'line', Backtrace::line());
|
||||
|
||||
if (Str::startsWith($message = $throwable->getMessage(), self::UNDEFINED_PROPERTY)) {
|
||||
/** @var \ReflectionClass $reflection */
|
||||
/** @var ReflectionClass $reflection */
|
||||
$reflection = (new ReflectionClass($this->target))->getParentClass();
|
||||
Reflection::setPropertyValue($throwable, 'message', sprintf('Undefined property %s::$%s', $reflection->getName(), $property));
|
||||
}
|
||||
|
||||
@ -6,9 +6,12 @@ namespace Pest\Support;
|
||||
|
||||
use Closure;
|
||||
use Pest\Exceptions\ShouldNotHappen;
|
||||
use Pest\TestSuite;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionFunction;
|
||||
use ReflectionNamedType;
|
||||
use ReflectionParameter;
|
||||
use ReflectionProperty;
|
||||
|
||||
/**
|
||||
@ -27,11 +30,25 @@ final class Reflection
|
||||
{
|
||||
$reflectionClass = new ReflectionClass($object);
|
||||
|
||||
$reflectionMethod = $reflectionClass->getMethod($method);
|
||||
try {
|
||||
$reflectionMethod = $reflectionClass->getMethod($method);
|
||||
|
||||
$reflectionMethod->setAccessible(true);
|
||||
$reflectionMethod->setAccessible(true);
|
||||
|
||||
return $reflectionMethod->invoke($object, ...$args);
|
||||
return $reflectionMethod->invoke($object, ...$args);
|
||||
} catch (ReflectionException $exception) {
|
||||
if (method_exists($object, '__call')) {
|
||||
return $object->__call($method, $args);
|
||||
}
|
||||
|
||||
if (is_callable($method)) {
|
||||
return Closure::fromCallable($method)->bindTo(
|
||||
TestSuite::getInstance()->test
|
||||
)(...$args);
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -109,4 +126,32 @@ final class Reflection
|
||||
$reflectionProperty->setAccessible(true);
|
||||
$reflectionProperty->setValue($object, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class name of the given parameter's type, if possible.
|
||||
*
|
||||
* @see https://github.com/laravel/framework/blob/v6.18.25/src/Illuminate/Support/Reflector.php
|
||||
*/
|
||||
public static function getParameterClassName(ReflectionParameter $parameter): ?string
|
||||
{
|
||||
$type = $parameter->getType();
|
||||
|
||||
if (!$type instanceof ReflectionNamedType || $type->isBuiltin()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$name = $type->getName();
|
||||
|
||||
if (($class = $parameter->getDeclaringClass()) instanceof ReflectionClass) {
|
||||
if ($name === 'self') {
|
||||
return $class->getName();
|
||||
}
|
||||
|
||||
if ($name === 'parent' && ($parent = $class->getParentClass()) instanceof ReflectionClass) {
|
||||
return $parent->getName();
|
||||
}
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
||||
213
src/TeamCity.php
Normal file
213
src/TeamCity.php
Normal file
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest;
|
||||
|
||||
use function getmypid;
|
||||
use Pest\Concerns\TestCase;
|
||||
use PHPUnit\Framework\AssertionFailedError;
|
||||
use PHPUnit\Framework\Test;
|
||||
use PHPUnit\Framework\TestResult;
|
||||
use PHPUnit\Framework\TestSuite;
|
||||
use PHPUnit\Framework\Warning;
|
||||
use PHPUnit\TextUI\DefaultResultPrinter;
|
||||
use function round;
|
||||
use function str_replace;
|
||||
use Throwable;
|
||||
|
||||
final class TeamCity extends DefaultResultPrinter
|
||||
{
|
||||
private const PROTOCOL = 'pest_qn://';
|
||||
private const NAME = 'name';
|
||||
private const LOCATION_HINT = 'locationHint';
|
||||
private const DURATION = 'duration';
|
||||
private const TEST_SUITE_STARTED = 'testSuiteStarted';
|
||||
private const TEST_SUITE_FINISHED = 'testSuiteFinished';
|
||||
|
||||
/** @var int */
|
||||
private $flowId;
|
||||
|
||||
/** @var bool */
|
||||
private $isSummaryTestCountPrinted = false;
|
||||
|
||||
/** @var \PHPUnit\Util\Log\TeamCity */
|
||||
private $phpunitTeamCity;
|
||||
|
||||
public function __construct(bool $verbose, string $colors)
|
||||
{
|
||||
parent::__construct(null, $verbose, $colors, false, 80, false);
|
||||
$this->phpunitTeamCity = new \PHPUnit\Util\Log\TeamCity(
|
||||
null,
|
||||
$verbose,
|
||||
$colors,
|
||||
false,
|
||||
80,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
public function printResult(TestResult $result): void
|
||||
{
|
||||
$this->printHeader($result);
|
||||
$this->printFooter($result);
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
public function startTestSuite(TestSuite $suite): void
|
||||
{
|
||||
$this->flowId = (int) getmypid();
|
||||
|
||||
if (!$this->isSummaryTestCountPrinted) {
|
||||
$this->printEvent(
|
||||
'testCount',
|
||||
['count' => $suite->count()]
|
||||
);
|
||||
$this->isSummaryTestCountPrinted = true;
|
||||
}
|
||||
|
||||
$suiteName = $suite->getName();
|
||||
|
||||
if (file_exists($suiteName) || !method_exists($suiteName, '__getFileName')) {
|
||||
$this->printEvent(
|
||||
self::TEST_SUITE_STARTED, [
|
||||
self::NAME => $suiteName,
|
||||
self::LOCATION_HINT => self::PROTOCOL . $suiteName,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$fileName = $suiteName::__getFileName();
|
||||
|
||||
$this->printEvent(
|
||||
self::TEST_SUITE_STARTED, [
|
||||
self::NAME => substr($suiteName, 2),
|
||||
self::LOCATION_HINT => self::PROTOCOL . $fileName,
|
||||
]);
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
public function endTestSuite(TestSuite $suite): void
|
||||
{
|
||||
$suiteName = $suite->getName();
|
||||
|
||||
if (file_exists($suiteName) || !method_exists($suiteName, '__getFileName')) {
|
||||
$this->printEvent(
|
||||
self::TEST_SUITE_FINISHED, [
|
||||
self::NAME => $suiteName,
|
||||
self::LOCATION_HINT => self::PROTOCOL . $suiteName,
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->printEvent(
|
||||
self::TEST_SUITE_FINISHED, [
|
||||
self::NAME => substr($suiteName, 2),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Test|TestCase $test
|
||||
*/
|
||||
public function startTest(Test $test): void
|
||||
{
|
||||
if (!TeamCity::isPestTest($test)) {
|
||||
$this->phpunitTeamCity->startTest($test);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->printEvent('testStarted', [
|
||||
self::NAME => $test->getName(),
|
||||
/* @phpstan-ignore-next-line */
|
||||
self::LOCATION_HINT => self::PROTOCOL . $test->toString(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Test|TestCase $test
|
||||
*/
|
||||
public function endTest(Test $test, float $time): void
|
||||
{
|
||||
if (!TeamCity::isPestTest($test)) {
|
||||
$this->phpunitTeamCity->endTest($test, $time);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->printEvent('testFinished', [
|
||||
self::NAME => $test->getName(),
|
||||
self::DURATION => self::toMilliseconds($time),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Test|TestCase $test
|
||||
*/
|
||||
public function addError(Test $test, Throwable $t, float $time): void
|
||||
{
|
||||
$this->phpunitTeamCity->addError($test, $t, $time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @phpstan-ignore-next-line
|
||||
*
|
||||
* @param Test|TestCase $test
|
||||
*/
|
||||
public function addWarning(Test $test, Warning $e, float $time): void
|
||||
{
|
||||
$this->phpunitTeamCity->addWarning($test, $e, $time);
|
||||
}
|
||||
|
||||
public function addFailure(Test $test, AssertionFailedError $e, float $time): void
|
||||
{
|
||||
$this->phpunitTeamCity->addFailure($test, $e, $time);
|
||||
}
|
||||
|
||||
protected function writeProgress(string $progress): void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string|int> $params
|
||||
*/
|
||||
private function printEvent(string $eventName, array $params = []): void
|
||||
{
|
||||
$this->write("\n##teamcity[{$eventName}");
|
||||
|
||||
if ($this->flowId !== 0) {
|
||||
$params['flowId'] = $this->flowId;
|
||||
}
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
$escapedValue = self::escapeValue((string) $value);
|
||||
$this->write(" {$key}='{$escapedValue}'");
|
||||
}
|
||||
|
||||
$this->write("]\n");
|
||||
}
|
||||
|
||||
private static function escapeValue(string $text): string
|
||||
{
|
||||
return str_replace(
|
||||
['|', "'", "\n", "\r", ']', '['],
|
||||
['||', "|'", '|n', '|r', '|]', '|['],
|
||||
$text
|
||||
);
|
||||
}
|
||||
|
||||
private static function toMilliseconds(float $time): int
|
||||
{
|
||||
return (int) round($time * 1000);
|
||||
}
|
||||
|
||||
private static function isPestTest(Test $test): bool
|
||||
{
|
||||
/** @var array<string, string> $uses */
|
||||
$uses = class_uses($test);
|
||||
|
||||
return in_array(TestCase::class, $uses, true);
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,7 @@ use Pest\Repositories\AfterEachRepository;
|
||||
use Pest\Repositories\BeforeAllRepository;
|
||||
use Pest\Repositories\BeforeEachRepository;
|
||||
use Pest\Repositories\TestRepository;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -19,7 +20,7 @@ final class TestSuite
|
||||
/**
|
||||
* Holds the current test case.
|
||||
*
|
||||
* @var \PHPUnit\Framework\TestCase|null
|
||||
* @var TestCase|null
|
||||
*/
|
||||
public $test;
|
||||
|
||||
|
||||
10
stubs/Browser.php
Normal file
10
stubs/Browser.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
use Laravel\Dusk\Browser;
|
||||
|
||||
it('has {name} page', function () {
|
||||
$this->browse(function (Browser $browser) {
|
||||
$browser->visit('/{name}')
|
||||
->assertSee('{name}');
|
||||
});
|
||||
});
|
||||
@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
/**
|
||||
* A basic assert example.
|
||||
*/
|
||||
function assertExample(): void
|
||||
{
|
||||
test()->assertTrue(true);
|
||||
}
|
||||
@ -1,3 +1,45 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Test Case
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The closure you provide to your test functions is always bound to a specific PHPUnit test
|
||||
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
|
||||
| need to change it using the "uses()" function to bind a different classes or traits.
|
||||
|
|
||||
*/
|
||||
|
||||
uses(Tests\TestCase::class)->in('Feature');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Expectations
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When you're writing tests, you often need to check that values meet certain conditions. The
|
||||
| "expect()" function gives you access to a set of "expectations" methods that you can use
|
||||
| to assert different things. Of course, you may extend the Expectation API at any time.
|
||||
|
|
||||
*/
|
||||
|
||||
expect()->extend('toBeOne', function () {
|
||||
return $this->toBe(1);
|
||||
});
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Functions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
|
||||
| project that you don't want to repeat in every file. Here you can also expose helpers as
|
||||
| global functions to help you to reduce the number of lines of code in your test files.
|
||||
|
|
||||
*/
|
||||
|
||||
function something()
|
||||
{
|
||||
// ..
|
||||
}
|
||||
|
||||
@ -12,10 +12,10 @@
|
||||
<directory suffix="Test.php">./tests/Feature</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">./app</directory>
|
||||
<directory suffix=".php">./src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</include>
|
||||
</coverage>
|
||||
</phpunit>
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Tests;
|
||||
|
||||
/**
|
||||
* A basic assert example.
|
||||
*/
|
||||
function assertExample(): void
|
||||
{
|
||||
test()->assertTrue(true);
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
<?php
|
||||
|
||||
uses(TestCase::class)->in(__DIR__);
|
||||
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Application Test Suite">
|
||||
<directory suffix="Test.php">./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">./app</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
5
tests/.snapshots/help-command.txt
Normal file
5
tests/.snapshots/help-command.txt
Normal file
@ -0,0 +1,5 @@
|
||||
Pest Options:
|
||||
--init Initialise a standard Pest configuration
|
||||
--coverage Enable coverage and output to standard output
|
||||
--min=<N> Set the minimum required coverage percentage (<N>), and fail if not met
|
||||
--group=<name> Only runs tests from the specified group(s)
|
||||
@ -40,7 +40,17 @@
|
||||
✓ eager wrapped registered datasets with (1)
|
||||
✓ eager wrapped registered datasets with (2)
|
||||
✓ eager registered wrapped datasets did the job right
|
||||
✓ named datasets with data set "one" (1)
|
||||
✓ named datasets with data set "two" (2)
|
||||
✓ named datasets did the job right
|
||||
✓ lazy named datasets with (Bar Object (...))
|
||||
✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), true) #1
|
||||
✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), true) #2
|
||||
✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), false)
|
||||
✓ it creates unique test case names with ('Name 2', Pest\Plugin Object (), false)
|
||||
✓ it creates unique test case names with ('Name 2', Pest\Plugin Object (), true)
|
||||
✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), true) #3
|
||||
✓ it creates unique test case names - count
|
||||
|
||||
PASS Tests\Features\Exceptions
|
||||
✓ it gives access the the underlying expectException
|
||||
@ -52,29 +62,36 @@
|
||||
✓ it throws error if property do not exist
|
||||
✓ it allows to call underlying protected/private methods
|
||||
✓ it throws error if method do not exist
|
||||
✓ it can forward unexpected calls to any global function
|
||||
|
||||
PASS Tests\Features\HigherOrderTests
|
||||
✓ it proxies calls to object
|
||||
✓ it is capable doing multiple assertions
|
||||
|
||||
PASS Tests\Features\It
|
||||
✓ it is a test
|
||||
✓ it is a higher order message test
|
||||
|
||||
PASS Tests\Features\Macro
|
||||
✓ it can call chained macro method
|
||||
✓ it will throw exception from call if no macro exists
|
||||
|
||||
PASS Tests\Features\Mocks
|
||||
✓ it has bar
|
||||
|
||||
PASS Tests\Features\PendingHigherOrderTests
|
||||
✓ get 'foo' → get 'bar' → assertTrue true
|
||||
✓ get 'foo' → assertTrue true
|
||||
✓ get 'foo' → get 'bar' → expect true → toBeTrue
|
||||
✓ get 'foo' → expect true → toBeTrue
|
||||
|
||||
WARN Tests\Features\Skip
|
||||
✓ it do not skips
|
||||
s it skips with truthy
|
||||
s it skips with truthy condition by default
|
||||
s it skips with message → skipped because bar
|
||||
s it skips with truthy closure condition
|
||||
- it skips with truthy
|
||||
- it skips with truthy condition by default
|
||||
- it skips with message → skipped because bar
|
||||
- it skips with truthy closure condition
|
||||
✓ it do not skips with falsy closure condition
|
||||
s it skips with condition and message → skipped because foo
|
||||
- it skips with condition and message → skipped because foo
|
||||
- it skips when skip after assertion
|
||||
|
||||
PASS Tests\Features\Test
|
||||
✓ a test
|
||||
@ -116,6 +133,16 @@
|
||||
✓ it throws exception when `process isolation` is true
|
||||
✓ it do not throws exception when `process isolation` is false
|
||||
|
||||
PASS Tests\Unit\Console\Help
|
||||
✓ it outputs the help information when --help is used
|
||||
|
||||
PASS Tests\Unit\Datasets
|
||||
✓ it show the names of named datasets in their description
|
||||
|
||||
PASS Tests\Unit\Plugins\Version
|
||||
✓ it outputs the version when --version is used
|
||||
✓ it do not outputs version when --version is not used
|
||||
|
||||
PASS Tests\Unit\Support\Backtrace
|
||||
✓ it gets file name from called file
|
||||
|
||||
@ -135,6 +162,9 @@
|
||||
PASS Tests\Unit\TestSuite
|
||||
✓ it does not allow to add the same test description twice
|
||||
|
||||
PASS Tests\Visual\Help
|
||||
✓ visual snapshot of help command output
|
||||
|
||||
PASS Tests\Visual\SingleTestOrDirectory
|
||||
✓ allows to run a single test
|
||||
✓ allows to run a directory
|
||||
@ -142,7 +172,21 @@
|
||||
✓ it disable decorating printer when colors is set to never
|
||||
|
||||
WARN Tests\Visual\Success
|
||||
s visual snapshot of test suite on success
|
||||
- visual snapshot of test suite on success
|
||||
|
||||
Tests: 6 skipped, 79 passed
|
||||
Time: 3.44s
|
||||
PASS Tests\Features\Depends
|
||||
✓ first
|
||||
✓ second
|
||||
✓ it asserts true is true
|
||||
✓ depends
|
||||
✓ depends with ...params
|
||||
✓ depends with defined arguments
|
||||
✓ depends run test only once
|
||||
✓ depends works with the correct test name
|
||||
|
||||
PASS Tests\Features\DependsInheritance
|
||||
✓ it is a test
|
||||
✓ it uses correct parent class
|
||||
|
||||
Tests: 7 skipped, 108 passed
|
||||
|
||||
@ -8,7 +8,7 @@ trait PluginTrait
|
||||
{
|
||||
public function assertPluginTraitGotRegistered(): void
|
||||
{
|
||||
assertTrue(true);
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,9 +16,14 @@ trait SecondPluginTrait
|
||||
{
|
||||
public function assertSecondPluginTraitGotRegistered(): void
|
||||
{
|
||||
assertTrue(true);
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
Pest\Plugin::uses(PluginTrait::class);
|
||||
Pest\Plugin::uses(SecondPluginTrait::class);
|
||||
|
||||
function _assertThat()
|
||||
{
|
||||
expect(true)->toBeTrue();
|
||||
}
|
||||
|
||||
@ -8,8 +8,8 @@ afterAll(function () use ($file) {
|
||||
|
||||
test('deletes file after all', function () use ($file) {
|
||||
file_put_contents($file, 'foo');
|
||||
assertFileExists($file);
|
||||
$this->assertFileExists($file);
|
||||
register_shutdown_function(function () use ($file) {
|
||||
assertFileNotExists($file);
|
||||
$this->assertFileNotExists($file);
|
||||
});
|
||||
});
|
||||
|
||||
@ -6,15 +6,15 @@ beforeEach(function () use ($state) {
|
||||
$this->state = $state;
|
||||
});
|
||||
|
||||
afterEach(function () use ($state) {
|
||||
afterEach(function () {
|
||||
$this->state->bar = 2;
|
||||
});
|
||||
|
||||
it('does not get executed before the test', function () {
|
||||
assertFalse(property_exists($this->state, 'bar'));
|
||||
expect($this->state)->not->toHaveProperty('bar');
|
||||
});
|
||||
|
||||
it('gets executed after the test', function () {
|
||||
assertTrue(property_exists($this->state, 'bar'));
|
||||
assertEquals(2, $this->state->bar);
|
||||
expect($this->state)->toHaveProperty('bar');
|
||||
expect($this->state->bar)->toBe(2);
|
||||
});
|
||||
|
||||
@ -8,11 +8,11 @@ beforeAll(function () use ($foo) {
|
||||
});
|
||||
|
||||
it('gets executed before tests', function () use ($foo) {
|
||||
assertEquals($foo->bar, 1);
|
||||
expect($foo->bar)->toBe(1);
|
||||
|
||||
$foo->bar = 'changed';
|
||||
});
|
||||
|
||||
it('do not get executed before each test', function () use ($foo) {
|
||||
assertEquals($foo->bar, 'changed');
|
||||
expect($foo->bar)->toBe('changed');
|
||||
});
|
||||
|
||||
@ -5,11 +5,11 @@ beforeEach(function () {
|
||||
});
|
||||
|
||||
it('gets executed before each test', function () {
|
||||
assertEquals($this->bar, 2);
|
||||
expect($this->bar)->toBe(2);
|
||||
|
||||
$this->bar = 'changed';
|
||||
});
|
||||
|
||||
it('gets executed before each test once again', function () {
|
||||
assertEquals($this->bar, 2);
|
||||
expect($this->bar)->toBe(2);
|
||||
});
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
use Pest\Datasets;
|
||||
use Pest\Exceptions\DatasetAlreadyExist;
|
||||
use Pest\Exceptions\DatasetDoesNotExist;
|
||||
use Pest\Plugin;
|
||||
|
||||
it('throws exception if dataset does not exist', function () {
|
||||
$this->expectException(DatasetDoesNotExist::class);
|
||||
@ -22,13 +23,13 @@ it('sets closures', function () {
|
||||
yield [1];
|
||||
});
|
||||
|
||||
assertEquals([[1]], iterator_to_array(Datasets::get('foo')()));
|
||||
expect(iterator_to_array(Datasets::get('foo')()))->toBe([[1]]);
|
||||
});
|
||||
|
||||
it('sets arrays', function () {
|
||||
Datasets::set('bar', [[2]]);
|
||||
|
||||
assertEquals([[2]], Datasets::get('bar'));
|
||||
expect(Datasets::get('bar'))->toBe([[2]]);
|
||||
});
|
||||
|
||||
it('gets bound to test case object', function () {
|
||||
@ -36,7 +37,7 @@ it('gets bound to test case object', function () {
|
||||
})->with([['a'], ['b']]);
|
||||
|
||||
test('it truncates the description', function () {
|
||||
assertTrue(true);
|
||||
expect(true)->toBe(true);
|
||||
// it gets tested by the integration test
|
||||
})->with([str_repeat('Fooo', 10000000)]);
|
||||
|
||||
@ -47,51 +48,63 @@ $datasets = [[1], [2]];
|
||||
|
||||
test('lazy datasets', function ($text) use ($state, $datasets) {
|
||||
$state->text .= $text;
|
||||
assertTrue(in_array([$text], $datasets));
|
||||
expect(in_array([$text], $datasets))->toBe(true);
|
||||
})->with($datasets);
|
||||
|
||||
test('lazy datasets did the job right', function () use ($state) {
|
||||
assertEquals('12', $state->text);
|
||||
expect($state->text)->toBe('12');
|
||||
});
|
||||
|
||||
$state->text = '';
|
||||
|
||||
test('eager datasets', function ($text) use ($state, $datasets) {
|
||||
$state->text .= $text;
|
||||
assertTrue(in_array([$text], $datasets));
|
||||
expect($datasets)->toContain([$text]);
|
||||
})->with(function () use ($datasets) {
|
||||
return $datasets;
|
||||
});
|
||||
|
||||
test('eager datasets did the job right', function () use ($state) {
|
||||
assertEquals('1212', $state->text);
|
||||
expect($state->text)->toBe('1212');
|
||||
});
|
||||
|
||||
test('lazy registered datasets', function ($text) use ($state, $datasets) {
|
||||
$state->text .= $text;
|
||||
assertTrue(in_array([$text], $datasets));
|
||||
expect($datasets)->toContain([$text]);
|
||||
})->with('numbers.array');
|
||||
|
||||
test('lazy registered datasets did the job right', function () use ($state) {
|
||||
assertEquals('121212', $state->text);
|
||||
expect($state->text)->toBe('121212');
|
||||
});
|
||||
|
||||
test('eager registered datasets', function ($text) use ($state, $datasets) {
|
||||
$state->text .= $text;
|
||||
assertTrue(in_array([$text], $datasets));
|
||||
expect($datasets)->toContain([$text]);
|
||||
})->with('numbers.closure');
|
||||
|
||||
test('eager registered datasets did the job right', function () use ($state) {
|
||||
assertEquals('12121212', $state->text);
|
||||
expect($state->text)->toBe('12121212');
|
||||
});
|
||||
|
||||
test('eager wrapped registered datasets', function ($text) use ($state, $datasets) {
|
||||
$state->text .= $text;
|
||||
assertTrue(in_array([$text], $datasets));
|
||||
expect($datasets)->toContain([$text]);
|
||||
})->with('numbers.closure.wrapped');
|
||||
|
||||
test('eager registered wrapped datasets did the job right', function () use ($state) {
|
||||
assertEquals('1212121212', $state->text);
|
||||
expect($state->text)->toBe('1212121212');
|
||||
});
|
||||
|
||||
test('named datasets', function ($text) use ($state, $datasets) {
|
||||
$state->text .= $text;
|
||||
expect($datasets)->toContain([$text]);
|
||||
})->with([
|
||||
'one' => [1],
|
||||
'two' => [2],
|
||||
]);
|
||||
|
||||
test('named datasets did the job right', function () use ($state) {
|
||||
expect($state->text)->toBe('121212121212');
|
||||
});
|
||||
|
||||
class Bar
|
||||
@ -103,6 +116,24 @@ $namedDatasets = [
|
||||
new Bar(),
|
||||
];
|
||||
|
||||
test('lazy named datasets', function ($text) use ($state, $datasets) {
|
||||
assertTrue(true);
|
||||
test('lazy named datasets', function ($text) {
|
||||
expect(true)->toBeTrue();
|
||||
})->with($namedDatasets);
|
||||
|
||||
$counter = 0;
|
||||
|
||||
it('creates unique test case names', function (string $name, Plugin $plugin, bool $bool) use (&$counter) {
|
||||
expect(true)->toBeTrue();
|
||||
$counter++;
|
||||
})->with([
|
||||
['Name 1', new Plugin(), true],
|
||||
['Name 1', new Plugin(), true],
|
||||
['Name 1', new Plugin(), false],
|
||||
['Name 2', new Plugin(), false],
|
||||
['Name 2', new Plugin(), true],
|
||||
['Name 1', new Plugin(), true],
|
||||
]);
|
||||
|
||||
it('creates unique test case names - count', function () use (&$counter) {
|
||||
expect($counter)->toBe(6);
|
||||
});
|
||||
|
||||
38
tests/Features/Depends.php
Normal file
38
tests/Features/Depends.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
$runCounter = 0;
|
||||
|
||||
test('first', function () use (&$runCounter) {
|
||||
expect(true)->toBeTrue();
|
||||
$runCounter++;
|
||||
|
||||
return 'first';
|
||||
});
|
||||
|
||||
test('second', function () use (&$runCounter) {
|
||||
expect(true)->toBeTrue();
|
||||
$runCounter++;
|
||||
|
||||
return 'second';
|
||||
});
|
||||
|
||||
test('depends', function () {
|
||||
expect(func_get_args())->toBe(['first', 'second']);
|
||||
})->depends('first', 'second');
|
||||
|
||||
test('depends with ...params', function (string ...$params) {
|
||||
expect(func_get_args())->toBe($params);
|
||||
})->depends('first', 'second');
|
||||
|
||||
test('depends with defined arguments', function (string $first, string $second) {
|
||||
expect($first)->toBe('first');
|
||||
expect($second)->toBe('second');
|
||||
})->depends('first', 'second');
|
||||
|
||||
test('depends run test only once', function () use (&$runCounter) {
|
||||
expect($runCounter)->toBe(2);
|
||||
})->depends('first', 'second');
|
||||
|
||||
// Regression tests. See https://github.com/pestphp/pest/pull/216
|
||||
it('asserts true is true')->assertTrue(true);
|
||||
test('depends works with the correct test name')->assertTrue(true)->depends('it asserts true is true');
|
||||
22
tests/Features/DependsInheritance.php
Normal file
22
tests/Features/DependsInheritance.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class InheritanceTest extends TestCase
|
||||
{
|
||||
public function foo()
|
||||
{
|
||||
return 'bar';
|
||||
}
|
||||
}
|
||||
|
||||
uses(InheritanceTest::class);
|
||||
|
||||
it('is a test', function () {
|
||||
expect(true)->toBeTrue();
|
||||
});
|
||||
|
||||
it('uses correct parent class', function () {
|
||||
expect(get_parent_class($this))->toEqual(InheritanceTest::class);
|
||||
expect($this->foo())->toEqual('bar');
|
||||
})->depends('it is a test');
|
||||
@ -7,7 +7,7 @@ function addUser()
|
||||
|
||||
it('can set/get properties on $this', function () {
|
||||
addUser();
|
||||
assertEquals('nuno', $this->user);
|
||||
expect($this->user)->toBe('nuno');
|
||||
});
|
||||
|
||||
it('throws error if property do not exist', function () {
|
||||
@ -27,17 +27,18 @@ function mockUser()
|
||||
$mock = test()->createMock(User::class);
|
||||
|
||||
$mock->method('getName')
|
||||
->willReturn('maduro');
|
||||
->willReturn('maduro');
|
||||
|
||||
return $mock;
|
||||
}
|
||||
|
||||
it('allows to call underlying protected/private methods', function () {
|
||||
$user = mockUser();
|
||||
|
||||
assertEquals('maduro', $user->getName());
|
||||
expect($user->getName())->toBe('maduro');
|
||||
});
|
||||
|
||||
it('throws error if method do not exist', function () {
|
||||
test()->name();
|
||||
})->throws(\ReflectionException::class, 'Call to undefined method PHPUnit\Framework\TestCase::name()');
|
||||
|
||||
it('can forward unexpected calls to any global function')->_assertThat();
|
||||
|
||||
@ -4,4 +4,8 @@ beforeEach()->assertTrue(true);
|
||||
|
||||
it('proxies calls to object')->assertTrue(true);
|
||||
|
||||
it('is capable doing multiple assertions')
|
||||
->assertTrue(true)
|
||||
->assertFalse(false);
|
||||
|
||||
afterEach()->assertTrue(true);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
it('is a test', function () {
|
||||
assertArrayHasKey('key', ['key' => 'foo']);
|
||||
$this->assertArrayHasKey('key', ['key' => 'foo']);
|
||||
});
|
||||
|
||||
it('is a higher order message test')->assertTrue(true);
|
||||
it('is a higher order message test')->expect(true)->toBeTrue();
|
||||
|
||||
16
tests/Features/Macro.php
Normal file
16
tests/Features/Macro.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Traits\Macroable;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
uses(Macroable::class);
|
||||
|
||||
beforeEach()->macro('bar', function () {
|
||||
expect($this)->toBeInstanceOf(TestCase::class);
|
||||
});
|
||||
|
||||
it('can call chained macro method')->bar();
|
||||
|
||||
it('will throw exception from call if no macro exists')
|
||||
->throws(BadMethodCallException::class)
|
||||
->foo();
|
||||
@ -1,11 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Pest\PendingObjects\TestCall;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
uses(Gettable::class);
|
||||
|
||||
/**
|
||||
* @return TestCase|Gettable
|
||||
* @return TestCase|TestCall|Gettable
|
||||
*/
|
||||
function get(string $route)
|
||||
{
|
||||
@ -15,15 +16,15 @@ function get(string $route)
|
||||
trait Gettable
|
||||
{
|
||||
/**
|
||||
* @return TestCase|Gettable
|
||||
* @return TestCase|TestCall|Gettable
|
||||
*/
|
||||
public function get(string $route)
|
||||
{
|
||||
assertNotEmpty($route);
|
||||
expect($route)->not->toBeEmpty();
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
get('foo')->get('bar')->assertTrue(true);
|
||||
get('foo')->assertTrue(true);
|
||||
get('foo')->get('bar')->expect(true)->toBeTrue();
|
||||
get('foo')->expect(true)->toBeTrue();
|
||||
|
||||
@ -27,3 +27,7 @@ it('do not skips with falsy closure condition')
|
||||
it('skips with condition and message')
|
||||
->skip(true, 'skipped because foo')
|
||||
->assertTrue(false);
|
||||
|
||||
it('skips when skip after assertion')
|
||||
->assertTrue(true)
|
||||
->skip();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
test('a test', function () {
|
||||
assertArrayHasKey('key', ['key' => 'foo']);
|
||||
$this->assertArrayHasKey('key', ['key' => 'foo']);
|
||||
});
|
||||
|
||||
test('higher order message test')->assertTrue(true);
|
||||
test('higher order message test')->expect(true)->toBeTrue();
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use function PHPUnit\Framework\assertFalse;
|
||||
|
||||
$foo = new stdClass();
|
||||
$foo->beforeAll = false;
|
||||
$foo->beforeEach = false;
|
||||
|
||||
@ -10,6 +10,6 @@ class CustomTestCaseInSubFolder extends TestCase
|
||||
{
|
||||
public function assertCustomInSubFolderTrue()
|
||||
{
|
||||
assertTrue(true);
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ class MyCustomClass extends PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function assertTrueIsTrue()
|
||||
{
|
||||
assertTrue(true);
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<?php
|
||||
|
||||
test('basic', function () {
|
||||
assertTrue(true);
|
||||
expect(true)->toBeTrue();
|
||||
});
|
||||
|
||||
@ -7,14 +7,14 @@ use PHPUnit\TextUI\DefaultResultPrinter;
|
||||
it('sets defaults', function () {
|
||||
$arguments = AddsDefaults::to(['bar' => 'foo']);
|
||||
|
||||
assertInstanceOf(Printer::class, $arguments['printer']);
|
||||
assertEquals($arguments['bar'], 'foo');
|
||||
expect($arguments['printer'])->toBeInstanceOf(Printer::class);
|
||||
expect($arguments['bar'])->toBe('foo');
|
||||
});
|
||||
|
||||
it('does not override options', function () {
|
||||
$defaultResultPrinter = new DefaultResultPrinter();
|
||||
|
||||
assertEquals(AddsDefaults::to(['printer' => $defaultResultPrinter]), [
|
||||
expect(AddsDefaults::to(['printer' => $defaultResultPrinter]))->tobe([
|
||||
'printer' => $defaultResultPrinter,
|
||||
]);
|
||||
});
|
||||
|
||||
@ -16,17 +16,17 @@ test('default php unit tests', function () {
|
||||
$phpUnitTestCase = new class() extends PhpUnitTestCase {
|
||||
};
|
||||
$testSuite->addTest($phpUnitTestCase);
|
||||
assertCount(1, $testSuite->tests());
|
||||
expect($testSuite->tests())->toHaveCount(1);
|
||||
|
||||
AddsTests::to($testSuite, new \Pest\TestSuite(getcwd()));
|
||||
assertCount(1, $testSuite->tests());
|
||||
expect($testSuite->tests())->toHaveCount(1);
|
||||
});
|
||||
|
||||
it('removes warnings', function () use ($pestTestCase) {
|
||||
it('removes warnings', function () {
|
||||
$testSuite = new TestSuite();
|
||||
$warningTestCase = new WarningTestCase('No tests found in class "Pest\TestCase".');
|
||||
$testSuite->addTest($warningTestCase);
|
||||
|
||||
AddsTests::to($testSuite, new \Pest\TestSuite(getcwd()));
|
||||
assertCount(0, $testSuite->tests());
|
||||
expect($testSuite->tests())->toHaveCount(0);
|
||||
});
|
||||
|
||||
@ -38,5 +38,5 @@ it('do not throws exception when `process isolation` is false', function () {
|
||||
'configuration' => $filename,
|
||||
]);
|
||||
|
||||
assertTrue(true);
|
||||
expect(true)->toBeTrue();
|
||||
});
|
||||
|
||||
12
tests/Unit/Console/Help.php
Normal file
12
tests/Unit/Console/Help.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
use Pest\Console\Help;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
|
||||
it('outputs the help information when --help is used', function () {
|
||||
$output = new BufferedOutput();
|
||||
$plugin = new Help($output);
|
||||
|
||||
$plugin();
|
||||
expect($output->fetch())->toContain('Pest Options:');
|
||||
});
|
||||
13
tests/Unit/Datasets.php
Normal file
13
tests/Unit/Datasets.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
use Pest\Datasets;
|
||||
|
||||
it('show the names of named datasets in their description', function () {
|
||||
$descriptions = array_keys(Datasets::resolve('test description', [
|
||||
'one' => [1],
|
||||
'two' => [[2]],
|
||||
]));
|
||||
|
||||
expect($descriptions[0])->toBe('test description with data set "one" (1)');
|
||||
expect($descriptions[1])->toBe('test description with data set "two" (array(2))');
|
||||
});
|
||||
21
tests/Unit/Plugins/Version.php
Normal file
21
tests/Unit/Plugins/Version.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
use Pest\Plugins\Version;
|
||||
use function Pest\version;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
|
||||
it('outputs the version when --version is used', function () {
|
||||
$output = new BufferedOutput();
|
||||
$plugin = new Version($output);
|
||||
|
||||
$plugin->handleArguments(['foo', '--version']);
|
||||
expect($output->fetch())->toContain('Pest ' . version());
|
||||
});
|
||||
|
||||
it('do not outputs version when --version is not used', function () {
|
||||
$output = new BufferedOutput();
|
||||
$plugin = new Version($output);
|
||||
|
||||
$plugin->handleArguments(['foo', 'bar']);
|
||||
expect($output->fetch())->toBe('');
|
||||
});
|
||||
@ -7,5 +7,5 @@ it('gets file name from called file', function () {
|
||||
return Backtrace::file();
|
||||
};
|
||||
|
||||
assertEquals(__FILE__, $a());
|
||||
expect($a())->toBe(__FILE__);
|
||||
});
|
||||
|
||||
@ -15,32 +15,32 @@ it('exists')
|
||||
|
||||
it('gets an instance', function () {
|
||||
$this->container->add(Container::class, $this->container);
|
||||
assertSame($this->container, $this->container->get(Container::class));
|
||||
expect($this->container->get(Container::class))->toBe($this->container);
|
||||
});
|
||||
|
||||
test('autowire', function () {
|
||||
assertInstanceOf(Container::class, $this->container->get(Container::class));
|
||||
expect($this->container->get(Container::class))->toBeInstanceOf(Container::class);
|
||||
});
|
||||
|
||||
it('creates an instance and resolves parameters', function () {
|
||||
$this->container->add(Container::class, $this->container);
|
||||
$instance = $this->container->get(ClassWithDependency::class);
|
||||
|
||||
assertInstanceOf(ClassWithDependency::class, $instance);
|
||||
expect($instance)->toBeInstanceOf(ClassWithDependency::class);
|
||||
});
|
||||
|
||||
it('creates an instance and resolves also sub parameters', function () {
|
||||
$this->container->add(Container::class, $this->container);
|
||||
$instance = $this->container->get(ClassWithSubDependency::class);
|
||||
|
||||
assertInstanceOf(ClassWithSubDependency::class, $instance);
|
||||
expect($instance)->toBeInstanceOf(ClassWithSubDependency::class);
|
||||
});
|
||||
|
||||
it('can resolve builtin value types', function () {
|
||||
$this->container->add('rootPath', getcwd());
|
||||
|
||||
$instance = $this->container->get(TestSuite::class);
|
||||
assertInstanceOf(TestSuite::class, $instance);
|
||||
expect($instance)->toBeInstanceOf(TestSuite::class);
|
||||
});
|
||||
|
||||
it('cannot resolve a parameter without type', function () {
|
||||
|
||||
@ -3,9 +3,10 @@
|
||||
use Pest\Support\Reflection;
|
||||
|
||||
it('gets file name from closure', function () {
|
||||
$fileName = Reflection::getFileNameFromClosure(function () {});
|
||||
$fileName = Reflection::getFileNameFromClosure(function () {
|
||||
});
|
||||
|
||||
assertEquals(__FILE__, $fileName);
|
||||
expect($fileName)->toBe(__FILE__);
|
||||
});
|
||||
|
||||
it('gets property values', function () {
|
||||
@ -15,5 +16,5 @@ it('gets property values', function () {
|
||||
|
||||
$value = Reflection::getPropertyValue($class, 'foo');
|
||||
|
||||
assertEquals('bar', $value);
|
||||
expect($value)->toBe('bar');
|
||||
});
|
||||
|
||||
27
tests/Visual/Help.php
Normal file
27
tests/Visual/Help.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use Pest\Console\Help;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
|
||||
test('visual snapshot of help command output', function () {
|
||||
$snapshot = __DIR__ . '/../.snapshots/help-command.txt';
|
||||
|
||||
if (getenv('REBUILD_SNAPSHOTS')) {
|
||||
$outputBuffer = new BufferedOutput();
|
||||
$plugin = new Help($outputBuffer);
|
||||
|
||||
$plugin();
|
||||
|
||||
file_put_contents($snapshot, $outputBuffer->fetch());
|
||||
}
|
||||
|
||||
$output = function () {
|
||||
$process = (new Symfony\Component\Process\Process(['php', 'bin/pest', '--help']));
|
||||
|
||||
$process->run();
|
||||
|
||||
return preg_replace('#\\x1b[[][^A-Za-z]*[A-Za-z]#', '', $process->getOutput());
|
||||
};
|
||||
|
||||
expect($output())->toContain(file_get_contents($snapshot));
|
||||
})->skip(PHP_OS_FAMILY === 'Windows');
|
||||
@ -10,7 +10,7 @@ $run = function (string $target, $decorated = false) {
|
||||
return $decorated ? $process->getOutput() : preg_replace('#\\x1b[[][^A-Za-z]*[A-Za-z]#', '', $process->getOutput());
|
||||
};
|
||||
|
||||
$snapshot = function ($name) {
|
||||
$snapshot = function ($name) {
|
||||
$testsPath = dirname(__DIR__);
|
||||
|
||||
return file_get_contents(implode(DIRECTORY_SEPARATOR, [
|
||||
@ -21,23 +21,15 @@ $snapshot = function ($name) {
|
||||
};
|
||||
|
||||
test('allows to run a single test', function () use ($run, $snapshot) {
|
||||
assertStringContainsString(
|
||||
$snapshot('allows-to-run-a-single-test'),
|
||||
$run('tests/Fixtures/DirectoryWithTests/ExampleTest.php'));
|
||||
expect($run('tests/Fixtures/DirectoryWithTests/ExampleTest.php'))->toContain($snapshot('allows-to-run-a-single-test'));
|
||||
})->skip(PHP_OS_FAMILY === 'Windows');
|
||||
|
||||
test('allows to run a directory', function () use ($run, $snapshot) {
|
||||
assertStringContainsString(
|
||||
$snapshot('allows-to-run-a-directory'),
|
||||
$run('tests/Fixtures')
|
||||
);
|
||||
expect($run('tests/Fixtures'))->toContain($snapshot('allows-to-run-a-directory'));
|
||||
})->skip(PHP_OS_FAMILY === 'Windows');
|
||||
|
||||
it('has ascii chars', function () use ($run, $snapshot) {
|
||||
assertStringContainsString(
|
||||
$snapshot('has-ascii-chars'),
|
||||
$run('tests/Fixtures/DirectoryWithTests/ExampleTest.php', true)
|
||||
);
|
||||
expect($run('tests/Fixtures/DirectoryWithTests/ExampleTest.php', true))->toContain($snapshot('has-ascii-chars'));
|
||||
})->skip(PHP_OS_FAMILY === 'Windows');
|
||||
|
||||
it('disable decorating printer when colors is set to never', function () use ($snapshot) {
|
||||
@ -49,9 +41,5 @@ it('disable decorating printer when colors is set to never', function () use ($s
|
||||
], dirname(__DIR__, 2));
|
||||
$process->run();
|
||||
$output = $process->getOutput();
|
||||
|
||||
assertStringContainsString(
|
||||
$snapshot('disable-decorating-printer'),
|
||||
$output
|
||||
);
|
||||
expect($output)->toContain($snapshot('disable-decorating-printer'));
|
||||
})->skip(PHP_OS_FAMILY === 'Windows');
|
||||
|
||||
@ -17,12 +17,16 @@ test('visual snapshot of test suite on success', function () {
|
||||
};
|
||||
|
||||
if (getenv('REBUILD_SNAPSHOTS')) {
|
||||
file_put_contents($snapshot, $output());
|
||||
// Strip time from end of snapshot
|
||||
$outputContent = preg_replace('/Time\: \s+\d+\.\d+s\s+/m', '', $output());
|
||||
|
||||
file_put_contents($snapshot, $outputContent);
|
||||
} elseif (!getenv('EXCLUDE')) {
|
||||
$output = explode("\n", $output());
|
||||
array_pop($output);
|
||||
array_pop($output);
|
||||
assertStringContainsString(implode("\n", $output), file_get_contents($snapshot));
|
||||
|
||||
expect(implode("\n", $output))->toContain(file_get_contents($snapshot));
|
||||
}
|
||||
})->skip(!getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE'))
|
||||
->skip(PHP_OS_FAMILY === 'Windows');
|
||||
|
||||
Reference in New Issue
Block a user