diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 396ce8e0..8a84d7f1 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -21,14 +21,32 @@ jobs: token: ${{ secrets.CHANGELOG_KEY }} repository: pestphp/website path: pestphp-website + - 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: + path: ./CHANGELOG.md + contents: | + --- + title: Changelog + description: Changelog + extends: _layouts.documentation + section: content + --- + ${{ steps.package.outputs.content }} + write-mode: overwrite - name: Copy CHANGELOG to website repository run: cp CHANGELOG.md pestphp-website/source/docs/changelog.md - name: Create Pull Request uses: peter-evans/create-pull-request@v2 with: - token: ${{ secrets.CHANGELOG_KEY }} - commit-message: Update changelog.md - committer: GitHub Action - author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> - title: 'Update changelog.md' - path: ./pestphp-website + token: ${{ secrets.CHANGELOG_KEY }} + commit-message: Update changelog.md + committer: GitHub Action + author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> + title: 'Update changelog.md' + path: ./pestphp-website diff --git a/.github/workflows/formats.yml b/.github/workflows/formats.yml index f3598b3b..bbdd5771 100644 --- a/.github/workflows/formats.yml +++ b/.github/workflows/formats.yml @@ -30,7 +30,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: mbstring, zip + extensions: dom, mbstring, zip tools: prestissimo coverage: pcov diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 10188221..8c600d9d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: mbstring, zip + extensions: dom, mbstring, zip coverage: none - name: Install Composer dependencies diff --git a/bin/pest b/bin/pest index ddb68f81..6c704ca1 100755 --- a/bin/pest +++ b/bin/pest @@ -1,6 +1,7 @@ #!/usr/bin/env php register(); + (new Provider())->register(); $rootPath = getcwd(); diff --git a/composer.json b/composer.json index 29ecbb4d..cdbfcec8 100644 --- a/composer.json +++ b/composer.json @@ -18,9 +18,9 @@ ], "require": { "php": "^7.3", - "nunomaduro/collision": "^5.0", - "pestphp/pest-plugin": "dev-master", - "pestphp/pest-plugin-coverage": "dev-master", + "nunomaduro/collision": "^5.0.0-BETA2", + "pestphp/pest-plugin": "^0.2", + "pestphp/pest-plugin-coverage": "^0.2", "phpunit/phpunit": "^9.1.4", "sebastian/environment": "^5.1" }, @@ -67,9 +67,9 @@ "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", - "test:unit": "bin/pest --colors=always --exclude-group=integration", - "test:integration": "bin/pest --colors=always --group=integration", - "test:integration:snapshots": "REBUILD_SNAPSHOTS=true bin/pest --colors=always", + "test:unit": "php bin/pest --colors=always --exclude-group=integration", + "test:integration": "php bin/pest --colors=always --group=integration", + "test:integration:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always", "test": [ "@test:lint", "@test:types", diff --git a/src/Factories/TestCaseFactory.php b/src/Factories/TestCaseFactory.php index e36613ab..49c6eaad 100644 --- a/src/Factories/TestCaseFactory.php +++ b/src/Factories/TestCaseFactory.php @@ -158,16 +158,25 @@ final class TestCaseFactory */ public function makeClassFromFilename(string $filename): string { + if ('\\' === DIRECTORY_SEPARATOR) { + // In case Windows, strtolower drive name, like in UsesCall. + $filename = (string) preg_replace_callback('~^(?P[a-z]+:\\\)~i', function ($match): string { + return strtolower($match['drive']); + }, $filename); + } + + $filename = (string) realpath($filename); $rootPath = TestSuite::getInstance()->rootPath; $relativePath = str_replace($rootPath . DIRECTORY_SEPARATOR, '', $filename); + $relativePath = dirname(ucfirst($relativePath)) . DIRECTORY_SEPARATOR . basename($relativePath, '.php'); + $relativePath = str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath); + // Strip out any %-encoded octets. $relativePath = (string) preg_replace('|%[a-fA-F0-9][a-fA-F0-9]|', '', $relativePath); - // Limit to A-Z, a-z, 0-9, '_', '-'. - $relativePath = (string) preg_replace('/[^A-Za-z0-9.\/]/', '', $relativePath); - - $classFQN = 'P\\' . basename(ucfirst(str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath)), '.php'); + $relativePath = (string) preg_replace('/[^A-Za-z0-9.\\\]/', '', $relativePath); + $classFQN = 'P\\' . $relativePath; if (class_exists($classFQN)) { return $classFQN; } diff --git a/src/PendingObjects/UsesCall.php b/src/PendingObjects/UsesCall.php index d7cfc1f6..f9418fd5 100644 --- a/src/PendingObjects/UsesCall.php +++ b/src/PendingObjects/UsesCall.php @@ -59,7 +59,17 @@ final class UsesCall public function in(string ...$targets): void { $targets = array_map(function ($path): string { - return $path[0] === DIRECTORY_SEPARATOR + $startChar = DIRECTORY_SEPARATOR; + + if ('\\' === DIRECTORY_SEPARATOR || preg_match('~\A[A-Z]:(?![^/\\\\])~i', $path) > 0) { + $path = (string) preg_replace_callback('~^(?P[a-z]+:\\\)~i', function ($match): string { + return strtolower($match['drive']); + }, $path); + + $startChar = strtolower((string) preg_replace('~^([a-z]+:\\\).*$~i', '$1', __DIR__)); + } + + return 0 === strpos($path, $startChar) ? $path : implode(DIRECTORY_SEPARATOR, [ dirname($this->filename), @@ -68,12 +78,12 @@ final class UsesCall }, $targets); $this->targets = array_map(function ($target): string { - $realTarget = realpath($target); - if ($realTarget === false) { + $isValid = is_dir($target) || file_exists($target); + if (!$isValid) { throw new InvalidUsesPath($target); } - return $realTarget; + return (string) realpath($target); }, $targets); } diff --git a/src/Support/Backtrace.php b/src/Support/Backtrace.php index 0347932f..cf90ab03 100644 --- a/src/Support/Backtrace.php +++ b/src/Support/Backtrace.php @@ -24,7 +24,7 @@ final class Backtrace $current = null; foreach (debug_backtrace() as $trace) { - if (Str::endsWith($trace[self::FILE], 'vendor/phpunit/phpunit/src/Util/FileLoader.php')) { + if (Str::endsWith($trace[self::FILE], (string) realpath('vendor/phpunit/phpunit/src/Util/FileLoader.php'))) { break; } diff --git a/src/TestSuite.php b/src/TestSuite.php index 2d2bbfd8..b9c232b2 100644 --- a/src/TestSuite.php +++ b/src/TestSuite.php @@ -83,7 +83,7 @@ final class TestSuite $this->afterEach = new AfterEachRepository(); $this->afterAll = new AfterAllRepository(); - $this->rootPath = $rootPath; + $this->rootPath = (string) realpath($rootPath); } /** diff --git a/tests/.snapshots/allows-to-run-a-directory.txt b/tests/.snapshots/allows-to-run-a-directory.txt new file mode 100644 index 00000000..aaf96389 --- /dev/null +++ b/tests/.snapshots/allows-to-run-a-directory.txt @@ -0,0 +1,7 @@ + PASS Tests\Fixtures\DirectoryWithTests\ExampleTest + ✓ it example 1 + + PASS Tests\Fixtures\ExampleTest + ✓ it example 2 + + Tests: 2 passed diff --git a/tests/.snapshots/allows-to-run-a-single-test.txt b/tests/.snapshots/allows-to-run-a-single-test.txt new file mode 100644 index 00000000..0812d708 --- /dev/null +++ b/tests/.snapshots/allows-to-run-a-single-test.txt @@ -0,0 +1,4 @@ + PASS Tests\Fixtures\DirectoryWithTests\ExampleTest + ✓ it example 1 + + Tests: 1 passed diff --git a/tests/.snapshots/disable-decorating-printer.txt b/tests/.snapshots/disable-decorating-printer.txt new file mode 100644 index 00000000..dc804c2f --- /dev/null +++ b/tests/.snapshots/disable-decorating-printer.txt @@ -0,0 +1,5 @@ + + PASS Tests\Fixtures\DirectoryWithTests\ExampleTest + ✓ it example 1 + + Tests: 1 passed diff --git a/tests/.snapshots/has-ascii-chars.txt b/tests/.snapshots/has-ascii-chars.txt new file mode 100644 index 00000000..403f6ac7 --- /dev/null +++ b/tests/.snapshots/has-ascii-chars.txt @@ -0,0 +1,5 @@ + +  PASS  Tests\Fixtures\DirectoryWithTests\ExampleTest + ✓ it example 1 + + Tests: 1 passed diff --git a/tests/.snapshots/success.txt b/tests/.snapshots/success.txt index 6140e1b2..1db9c356 100644 --- a/tests/.snapshots/success.txt +++ b/tests/.snapshots/success.txt @@ -1,5 +1,5 @@ - PASS Tests\CustomTestCase\PhpunitTest + PASS Tests\CustomTestCase\ExecutedTest ✓ that gets executed PASS Tests\Features\AfterAll @@ -24,7 +24,7 @@ ✓ it sets arrays ✓ it gets bound to test case object with ('a') ✓ it gets bound to test case object with ('b') - ✓ it truncates the description with (' fooo fooo fooo fooo fooo fooo fooo f...oo fooo') + ✓ it truncates the description with ('FoooFoooFoooFoooFoooFoooFoooF...ooFooo') ✓ lazy datasets with (1) ✓ lazy datasets with (2) ✓ lazy datasets did the job right @@ -40,10 +40,10 @@ ✓ eager wrapped registered datasets with (1) ✓ eager wrapped registered datasets with (2) ✓ eager registered wrapped datasets did the job right - ✓ lazy named datasets with ( bar object (...)) + ✓ lazy named datasets with (Bar Object (...)) PASS Tests\Features\Exceptions - ✓ it gives access the the underlying expect exception + ✓ it gives access the the underlying expectException ✓ it catch exceptions ✓ it catch exceptions and messages @@ -64,8 +64,8 @@ ✓ it has bar PASS Tests\Features\PendingHigherOrderTests - ✓ get 'foo' → get 'bar' → assert true true - ✓ get 'foo' → assert true true + ✓ get 'foo' → get 'bar' → assertTrue true + ✓ get 'foo' → assertTrue true WARN Tests\Features\Skip ✓ it do not skips @@ -81,16 +81,16 @@ ✓ higher order message test PASS Tests\Fixtures\DirectoryWithTests\ExampleTest - ✓ it example + ✓ it example 1 PASS Tests\Fixtures\ExampleTest - ✓ it example + ✓ it example 2 PASS Tests\PHPUnit\CustomTestCase\UsesPerDirectory - ✓ closure was bound to custom test case + ✓ closure was bound to CustomTestCase PASS Tests\PHPUnit\CustomTestCaseInSubFolders\SubFolder\SubFolder\UsesPerSubDirectory - ✓ closure was bound to custom test case + ✓ closure was bound to CustomTestCase PASS Tests\PHPUnit\CustomTestCaseInSubFolders\SubFolder2\UsesPerFile ✓ custom traits can be used @@ -137,7 +137,7 @@ PASS Tests\Visual\SingleTestOrDirectory ✓ allows to run a single test ✓ allows to run a directory - ✓ it has ascii chars (decorated printer) + ✓ it has ascii chars ✓ it disable decorating printer when colors is set to never WARN Tests\Visual\Success diff --git a/tests/Fixtures/DirectoryWithTests/ExampleTest.php b/tests/Fixtures/DirectoryWithTests/ExampleTest.php index 8553ad34..81ce02ff 100644 --- a/tests/Fixtures/DirectoryWithTests/ExampleTest.php +++ b/tests/Fixtures/DirectoryWithTests/ExampleTest.php @@ -1,3 +1,3 @@ assertTrue(true); +it('example 1')->assertTrue(true); diff --git a/tests/Fixtures/ExampleTest.php b/tests/Fixtures/ExampleTest.php index 8553ad34..a2704020 100644 --- a/tests/Fixtures/ExampleTest.php +++ b/tests/Fixtures/ExampleTest.php @@ -1,3 +1,3 @@ assertTrue(true); +it('example 2')->assertTrue(true); diff --git a/tests/PHPUnit/CustomTestCase/PhpunitTest.php b/tests/PHPUnit/CustomTestCase/ExecutedTest.php similarity index 67% rename from tests/PHPUnit/CustomTestCase/PhpunitTest.php rename to tests/PHPUnit/CustomTestCase/ExecutedTest.php index 233da16d..71a32980 100644 --- a/tests/PHPUnit/CustomTestCase/PhpunitTest.php +++ b/tests/PHPUnit/CustomTestCase/ExecutedTest.php @@ -7,7 +7,7 @@ namespace Tests\CustomTestCase; use function PHPUnit\Framework\assertTrue; use PHPUnit\Framework\TestCase; -class PhpunitTest extends TestCase +class ExecutedTest extends TestCase { public static $executed = false; @@ -16,8 +16,8 @@ class PhpunitTest extends TestCase { self::$executed = true; - $this->assertTrue(true); + assertTrue(true); } } -// register_shutdown_function(fn () => assertTrue(PhpunitTest::$executed)); +// register_shutdown_function(fn () => assertTrue(ExecutedTest::$executed)); diff --git a/tests/Visual/SingleTestOrDirectory.php b/tests/Visual/SingleTestOrDirectory.php index d86fc4c9..261318c3 100644 --- a/tests/Visual/SingleTestOrDirectory.php +++ b/tests/Visual/SingleTestOrDirectory.php @@ -2,53 +2,47 @@ use Symfony\Component\Process\Process; -$run = function (string $target) { - $process = new Process(['./bin/pest', $target], dirname(__DIR__, 2)); +$run = function (string $target, $decorated = false) { + $process = new Process(['php', 'bin/pest', $target], dirname(__DIR__, 2)); $process->run(); - return preg_replace('#\\x1b[[][^A-Za-z]*[A-Za-z]#', '', $process->getOutput()); + return $decorated ? $process->getOutput() : preg_replace('#\\x1b[[][^A-Za-z]*[A-Za-z]#', '', $process->getOutput()); }; -test('allows to run a single test', function () use ($run) { - assertStringContainsString(<<run(); - $output = $process->getOutput(); - assertStringContainsString(<<run(); $output = $process->getOutput(); - assertStringContainsString(<< 'integration', 'REBUILD_SNAPSHOTS' => false])); + $process = (new Symfony\Component\Process\Process(['php', 'bin/pest'], dirname($testsPath), ['EXCLUDE' => 'integration', 'REBUILD_SNAPSHOTS' => false])); $process->run(); @@ -24,4 +24,5 @@ test('visual snapshot of test suite on success', function () { array_pop($output); assertStringContainsString(implode("\n", $output), file_get_contents($snapshot)); } -})->skip(!getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE')); +})->skip(!getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE')) + ->skip(PHP_OS_FAMILY === 'Windows', 'File sorting algorithm causes different test order on Windows'); diff --git a/tests/Visual/foo.txt b/tests/Visual/foo.txt new file mode 100644 index 00000000..f57f729a --- /dev/null +++ b/tests/Visual/foo.txt @@ -0,0 +1,6 @@ + +  PASS  Tests\Fixtures\DirectoryWithTests\ExampleTest + ✓ it example 1 + + Tests: 1 passed + Time: 0.04s