[
  {
    "path": ".editorconfig",
    "content": "; This file is for unifying the coding style for different editors and IDEs.\n; More information at http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\ninsert_final_newline = true\nindent_style = space\nindent_size = 4\ntrim_trailing_whitespace = true\n\n[*.md]\ntrim_trailing_whitespace = false\n\n[*.{yml,yaml}]\nindent_size = 2\n"
  },
  {
    "path": ".gitattributes",
    "content": "/docker                  export-ignore\n/docs                    export-ignore\n/tests                   export-ignore\n/scripts                 export-ignore\n/.github                 export-ignore\n.editorconfig            export-ignore\n.gitattributes           export-ignore\n.gitignore               export-ignore\n/phpstan.neon            export-ignore\n/phpunit.xml             export-ignore\n/CHANGELOG.md            export-ignore\n/CONTRIBUTING.md         export-ignore\n/docker-compose.yml      export-ignore\n/Makefile                export-ignore\n/rector.php              export-ignore\n/README.md               export-ignore\n/RELEASE.md              export-ignore\n\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [nunomaduro]\ncustom: https://www.paypal.com/paypalme/enunomaduro\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: Bug Report\ndescription: Report an Issue or Bug with the Pest\ntitle: \"[Bug]: \"\nlabels: [\"bug\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        We're sorry to hear you have a problem. Can you help us solve it by providing the following details.\n  - type: textarea\n    id: what-happened\n    attributes:\n      label: What Happened\n      description: What did you expect to happen?\n      placeholder: When I use expect()->toBeTrue() in my tests, I get an error\n    validations:\n      required: true\n  - type: textarea\n    id: how-to-reproduce\n    attributes:\n      label: How to Reproduce\n      description: How did this occur, please add any config values used and provide a set of reliable steps if possible.\n      placeholder: Install a fresh Laravel app, add Pest, add a test that uses expect()->toBeTrue()\n    validations:\n      required: true\n  - type: input\n    id: repository-sample\n    attributes:\n      label: Sample Repository\n      description: If possible, please provide a sample repository that reproduces the issue.\n      placeholder: https://github.com.br/your-username/your-repository\n  - type: input\n    id: pest-version\n    attributes:\n      label: Pest Version\n      description: What version of our Package are you running? Please be as specific as possible\n      placeholder: 2.14.1\n    validations:\n      required: true\n  - type: input\n    id: php-version\n    attributes:\n      label: PHP Version\n      description: What version of PHP are you running? Please be as specific as possible\n      placeholder: 8.1.20\n    validations:\n      required: true\n  - type: dropdown\n    id: operating-systems\n    attributes:\n      label: Operation System\n      description: On which operating systems does the problem occur? You can select more than one.\n      multiple: true\n      options:\n        - macOS\n        - Windows\n        - Linux\n    validations:\n      required: true\n  - type: textarea\n    id: notes\n    attributes:\n      label: Notes\n      description: Use this field to provide any other notes that you feel might be relevant to the issue.\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\n- Fill in the form below correctly. This will help the Pest team to understand the PR and also work on it.\n-->\n\n### What:\n\n- [ ] Bug Fix\n- [ ] New Feature\n\n### Description:\n\n<!-- describe what your PR is solving -->\n\n### Related:\n\n<!-- link to the issue(s) your PR is solving. If it doesn't exist, remove the \"Related\" section. -->\n"
  },
  {
    "path": ".github/workflows/static.yml",
    "content": "name: Static Analysis\n\non:\n  push:\n    branches: [4.x]\n  pull_request:\n  schedule:\n    - cron: '0 0 * * *'\n\nconcurrency:\n  group: static-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  static:\n    if: github.event_name != 'schedule' || github.repository == 'pestphp/pest'\n    name: Static Tests\n\n    runs-on: ubuntu-latest\n    strategy:\n      fail-fast: true\n      matrix:\n        dependency-version: [prefer-lowest, prefer-stable]\n\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n\n    - name: Setup PHP\n      uses: shivammathur/setup-php@v2\n      with:\n        php-version: 8.3\n        tools: composer:v2\n        coverage: none\n        extensions: sockets\n\n    - name: Get Composer cache directory\n      id: composer-cache\n      shell: bash\n      run: echo \"dir=$(composer config cache-files-dir)\" >> $GITHUB_OUTPUT\n\n    - name: Cache Composer dependencies\n      uses: actions/cache@v4\n      with:\n        path: ${{ steps.composer-cache.outputs.dir }}\n        key: static-php-8.3-${{ matrix.dependency-version }}-composer-${{ hashFiles('**/composer.json') }}\n        restore-keys: |\n          static-php-8.3-${{ matrix.dependency-version }}-composer-\n          static-php-8.3-composer-\n\n    - name: Install Dependencies\n      run: composer update --${{ matrix.dependency-version }} --no-interaction --no-progress --ansi\n\n    - name: Profanity Check\n      run: composer test:profanity\n\n    - name: Type Check\n      run: composer test:type:check\n\n    - name: Type Coverage\n      run: composer test:type:coverage\n\n    - name: Refacto\n      run: composer test:refacto\n\n    - name: Style\n      run: composer test:lint\n"
  },
  {
    "path": ".github/workflows/tests.yml",
    "content": "name: Tests\n\non:\n  push:\n    branches: [4.x]\n  pull_request:\n\nconcurrency:\n  group: tests-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  tests:\n    if: github.event_name != 'schedule' || github.repository == 'pestphp/pest'\n\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: true\n      matrix:\n        os: [ubuntu-latest, macos-latest] # windows-latest\n        symfony: ['7.4', '8.0']\n        php: ['8.3', '8.4', '8.5']\n        dependency_version: [prefer-stable]\n        exclude:\n          - php: '8.3'\n            symfony: '8.0'\n\n    name: PHP ${{ matrix.php }} - Symfony ^${{ matrix.symfony }} - ${{ matrix.os }} - ${{ matrix.dependency_version }}\n\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6\n\n    - name: Setup PHP\n      uses: shivammathur/setup-php@v2\n      with:\n        php-version: ${{ matrix.php }}\n        tools: composer:v2\n        coverage: none\n        extensions: sockets\n\n    - name: Get Composer cache directory\n      id: composer-cache\n      shell: bash\n      run: echo \"dir=$(composer config cache-files-dir)\" >> $GITHUB_OUTPUT\n\n    - name: Cache Composer dependencies\n      uses: actions/cache@v4\n      with:\n        path: ${{ steps.composer-cache.outputs.dir }}\n        key: ${{ matrix.os }}-php-${{ matrix.php }}-symfony-${{ matrix.symfony }}-composer-${{ hashFiles('**/composer.json') }}\n        restore-keys: |\n          ${{ matrix.os }}-php-${{ matrix.php }}-symfony-${{ matrix.symfony }}-composer-\n          ${{ matrix.os }}-php-${{ matrix.php }}-composer-\n\n    - name: Setup Problem Matches\n      run: |\n        echo \"::add-matcher::${{ runner.tool_cache }}/php.json\"\n        echo \"::add-matcher::${{ runner.tool_cache }}/phpunit.json\"\n\n    - name: Install PHP dependencies\n      shell: bash\n      run: composer update --${{ matrix.dependency_version }} --no-interaction --no-progress --ansi --with=\"symfony/console:^${{ matrix.symfony }}\"\n\n    - name: Unit Tests\n      run: composer test:unit\n\n    - name: Parallel Tests\n      run: composer test:parallel\n\n    - name: Integration Tests\n      run: composer test:integration\n"
  },
  {
    "path": ".gitignore",
    "content": ".idea/*\n.idea/codeStyleSettings.xml\n.temp/*\ncomposer.lock\n/vendor/\ncoverage.xml\n.phpunit.result.cache\n.phpunit.cache\n/.php-cs-fixer.php\n.php-cs-fixer.cache\n.temp/coverage.php\n*.swp\n*.swo\n.vscode/\n.STREAM.md\n\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# CONTRIBUTING\n\nContributions are welcome, and are accepted via pull requests.\nPlease review these guidelines before submitting any pull requests.\n\n## Process\n\n1. Fork the project\n1. Create a new branch\n1. Code, test, commit and push\n1. Open a pull request detailing your changes. Make sure to follow the [template](.github/PULL_REQUEST_TEMPLATE.md)\n\n## Guidelines\n\n* Please ensure the coding style running `composer lint`.\n* Send a coherent commit history, making sure each individual commit in your pull request is meaningful.\n* You may need to [rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) to avoid merge conflicts.\n* Please remember that we follow [SemVer](http://semver.org/).\n\n## Setup\n\nClone your fork, then install the dev dependencies:\n```bash\ncomposer install\n```\n## Lint\n\nLint your code:\n```bash\ncomposer lint\n```\n## Tests\n\nUpdate the snapshots:\n```bash\ncomposer update:snapshots\n```\nRun all tests:\n```bash\ncomposer test\n```\n\nCheck types:\n```bash\ncomposer test:type:check\n```\n\nUnit tests:\n```bash\ncomposer test:unit\n```\n\nIntegration tests:\n```bash\ncomposer test:integration\n```\n\n## Simplified setup using Docker\n\nIf you have Docker installed, you can quickly get all dependencies for Pest in place using\nour Docker files. Assuming you have the repository cloned, you may run the following\ncommands:\n\n1. `make build` to build the Docker image\n2. `make install` to install Composer dependencies\n3. `make test` to run the project tests and analysis tools\n\nIf you want to check things work against a specific version of PHP, you may include\nthe `PHP` build argument when building the image:\n\n```bash\nmake build ARGS=\"--build-arg PHP=8.3\"\n```\n\nThe default PHP version will always be the lowest version of PHP supported by Pest.\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) Nuno Maduro <enunomaduro@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n    <img src=\"https://raw.githubusercontent.com/pestphp/art/master/v4/social.png\" width=\"600\" alt=\"PEST\">\n    <p align=\"center\">\n        <a href=\"https://github.com/pestphp/pest/actions\"><img alt=\"GitHub Workflow Status (master)\" src=\"https://img.shields.io/github/actions/workflow/status/pestphp/pest/tests.yml?branch=4.x&label=Tests%204.x\"></a>\n        <a href=\"https://packagist.org/packages/pestphp/pest\"><img alt=\"Total Downloads\" src=\"https://img.shields.io/packagist/dt/pestphp/pest\"></a>\n        <a href=\"https://packagist.org/packages/pestphp/pest\"><img alt=\"Latest Version\" src=\"https://img.shields.io/packagist/v/pestphp/pest\"></a>\n        <a href=\"https://packagist.org/packages/pestphp/pest\"><img alt=\"License\" src=\"https://img.shields.io/packagist/l/pestphp/pest\"></a>\n        <a href=\"https://whyphp.dev\"><img src=\"https://img.shields.io/badge/Why_PHP-in_2026-7A86E8?style=flat-square&labelColor=18181b\" alt=\"Why PHP in 2026\"></a>\n    </p>\n</p>\n\n------\n\n> Pest v4 Now Available: **[Read the announcement »](https://pestphp.com/docs/pest-v4-is-here-now-with-browser-testing)**.\n\n**Pest** is an elegant PHP testing Framework with a focus on simplicity, meticulously designed to bring back the joy of testing in PHP.\n\n- Explore our docs at **[pestphp.com »](https://pestphp.com)**\n- Follow the creator Nuno Maduro:\n    - YouTube: **[youtube.com/@nunomaduro](https://youtube.com/@nunomaduro)** — Videos every week\n    - Twitch: **[twitch.tv/nunomaduro](https://twitch.tv/nunomaduro)** — Live coding on Mondays, Wednesdays, and Fridays at 9PM UTC\n    - Twitter / X: **[x.com/enunomaduro](https://x.com/enunomaduro)**\n    - LinkedIn: **[linkedin.com/in/nunomaduro](https://www.linkedin.com/in/nunomaduro)**\n    - Instagram: **[instagram.com/enunomaduro](https://www.instagram.com/enunomaduro)**\n    - Tiktok: **[tiktok.com/@enunomaduro](https://www.tiktok.com/@enunomaduro)**\n\n## Sponsors\n\nWe cannot thank our sponsors enough for their incredible support in funding Pest's development. Their contributions have been instrumental in making Pest the best it can be. For those who are interested in becoming a sponsor, please visit Nuno Maduro's Sponsor page at **[github.com/sponsors/nunomaduro](https://github.com/sponsors/nunomaduro)**.\n\n\n### Platinum Sponsors\n\n- **[CodeRabbit](https://coderabbit.ai/?ref=pestphp)**\n- **[Mailtrap](https://l.rw.rw/pestphp)**\n- **[SerpApi](https://serpapi.com/?ref=nunomaduro)**\n- **[Tighten](https://tighten.com/?ref=nunomaduro)**\n- **[Redberry](https://redberry.international/laravel-development/?utm_source=pest&utm_medium=banner&utm_campaign=pest_sponsorship)**\n\n### Gold Sponsors\n\n- **[CMS Max](https://cmsmax.com/?ref=pestphp)**\n\n### Premium Sponsors\n\n- [Zapiet](https://zapiet.com/?ref=pestphp)\n- [Load Forge](https://loadforge.com/?ref=pestphp)\n- [Route4Me](https://route4me.com/pt?ref=pestphp)\n- [Nerdify](https://getnerdify.com/?ref=pestphp)\n- [Akaunting](https://akaunting.com/?ref=pestphp)\n- [TestMu AI](https://www.testmuai.com/?utm_medium=sponsor&utm_source=pest)\n\nPest is an open-sourced software licensed under the **[MIT license](https://opensource.org/licenses/MIT)**.\n"
  },
  {
    "path": "RELEASE.md",
    "content": "# Release process\n\nWhen releasing a new version of Pest there are some checks and updates that need to be done:\n\n> **For Pest v3 you should use the `3.x` branch instead.**\n\n- Clear your local repository with: `git add . && git reset --hard && git checkout 4.x`\n- On the GitHub repository, check the contents of [github.com/pestphp/pest/compare/{latest_version}...4.x](https://github.com/pestphp/pest/compare/{latest_version}...4.x)\n- Update the version number in [src/Pest.php](src/Pest.php)\n- Run the tests locally using: `composer test`\n- Commit the Pest file with the message: `git commit -m \"release: vX.X.X\"`\n- Push the changes to GitHub\n- Check that the CI is passing as expected: [github.com/pestphp/pest/actions](https://github.com/pestphp/pest/actions)\n- Tag and push the tag with `git tag vX.X.X && git push --tags`\n- Publish release here: [github.com/pestphp/pest/releases/new](https://github.com/pestphp/pest/releases/new).\n\n### Plugins\n\nPlugins should be versioned using the same major (or minor for `0.x` releases) version as Pest core.\n"
  },
  {
    "path": "bin/pest",
    "content": "#!/usr/bin/env php\n<?php\n\ndeclare(strict_types=1);\n\nuse Pest\\Kernel;\nuse Pest\\Panic;\nuse Pest\\TestCaseFilters\\GitDirtyTestCaseFilter;\nuse Pest\\TestCaseMethodFilters\\AssigneeTestCaseFilter;\nuse Pest\\TestCaseMethodFilters\\IssueTestCaseFilter;\nuse Pest\\TestCaseMethodFilters\\NotesTestCaseFilter;\nuse Pest\\TestCaseMethodFilters\\PrTestCaseFilter;\nuse Pest\\TestCaseMethodFilters\\TodoTestCaseFilter;\nuse Pest\\TestSuite;\nuse Symfony\\Component\\Console\\Input\\ArgvInput;\nuse Symfony\\Component\\Console\\Output\\ConsoleOutput;\n\n(static function () {\n    // Ensures Collision's Printer is registered.\n    $_SERVER['COLLISION_PRINTER'] = 'DefaultPrinter';\n\n    $arguments = $originalArguments = $_SERVER['argv'];\n\n    $dirty = false;\n    $todo = false;\n    $notes = false;\n\n    foreach ($arguments as $key => $value) {\n\n        if ($value === '--compact') {\n            $_SERVER['COLLISION_PRINTER_COMPACT'] = 'true';\n            unset($arguments[$key]);\n        }\n\n        if ($value === '--profile') {\n            $_SERVER['COLLISION_PRINTER_PROFILE'] = 'true';\n            unset($arguments[$key]);\n        }\n\n        if (str_contains($value, '--test-directory=')) {\n            unset($arguments[$key]);\n        } elseif ($value === '--test-directory') {\n            unset($arguments[$key]);\n\n            if (isset($arguments[$key + 1])) {\n                unset($arguments[$key + 1]);\n            }\n        }\n\n        if ($value === '--dirty') {\n            $dirty = true;\n            unset($arguments[$key]);\n        }\n\n        if (in_array($value, ['--todo', '--todos'], true)) {\n            $todo = true;\n            unset($arguments[$key]);\n        }\n\n        if ($value === '--notes') {\n            $notes = true;\n            unset($arguments[$key]);\n        }\n\n        if (str_contains($value, '--assignee=')) {\n            unset($arguments[$key]);\n        } elseif ($value === '--assignee') {\n            unset($arguments[$key]);\n\n            if (isset($arguments[$key + 1])) {\n                unset($arguments[$key + 1]);\n            }\n        }\n\n        if (str_contains($value, '--issue=')) {\n            unset($arguments[$key]);\n        } elseif ($value === '--issue') {\n            unset($arguments[$key]);\n\n            if (isset($arguments[$key + 1])) {\n                unset($arguments[$key + 1]);\n            }\n        }\n\n        if (str_contains($value, '--ticket=')) {\n            unset($arguments[$key]);\n        } elseif ($value === '--ticket') {\n            unset($arguments[$key]);\n\n            if (isset($arguments[$key + 1])) {\n                unset($arguments[$key + 1]);\n            }\n        }\n\n        if (str_contains($value, '--pr=')) {\n            unset($arguments[$key]);\n        } elseif ($value === '--pr') {\n            unset($arguments[$key]);\n\n            if (isset($arguments[$key + 1])) {\n                unset($arguments[$key + 1]);\n            }\n        }\n\n        if (str_contains($value, '--pull-request=')) {\n            unset($arguments[$key]);\n        } elseif ($value === '--pull-request') {\n            unset($arguments[$key]);\n\n            if (isset($arguments[$key + 1])) {\n                unset($arguments[$key + 1]);\n            }\n        }\n\n        if (str_contains($value, '--teamcity')) {\n            unset($arguments[$key]);\n            $arguments[] = '--no-output';\n            unset($_SERVER['COLLISION_PRINTER']);\n        }\n    }\n\n    // Used when Pest is required using composer.\n    $vendorPath = dirname(__DIR__, 4).'/vendor/autoload.php';\n\n    // Used when Pest maintainers are running Pest tests.\n    $localPath = dirname(__DIR__).'/vendor/autoload.php';\n\n    if (file_exists($vendorPath)) {\n        include_once $vendorPath;\n        $autoloadPath = $vendorPath;\n    } else {\n        include_once $localPath;\n        $autoloadPath = $localPath;\n    }\n\n    // Get $rootPath based on $autoloadPath\n    $rootPath = dirname($autoloadPath, 2);\n    $input = new ArgvInput;\n\n    $testSuite = TestSuite::getInstance(\n        $rootPath,\n        $input->getParameterOption('--test-directory', 'tests'),\n    );\n\n    if ($dirty) {\n        $testSuite->tests->addTestCaseFilter(new GitDirtyTestCaseFilter($rootPath));\n    }\n\n    if ($todo) {\n        $testSuite->tests->addTestCaseMethodFilter(new TodoTestCaseFilter);\n    }\n\n    if ($notes) {\n        $testSuite->tests->addTestCaseMethodFilter(new NotesTestCaseFilter);\n    }\n\n    if ($assignee = $input->getParameterOption('--assignee')) {\n        $testSuite->tests->addTestCaseMethodFilter(new AssigneeTestCaseFilter((string) $assignee));\n    }\n\n    if ($issue = $input->getParameterOption('--issue')) {\n        $testSuite->tests->addTestCaseMethodFilter(new IssueTestCaseFilter((int) $issue));\n    }\n\n    if ($issue = $input->getParameterOption('--ticket')) {\n        $testSuite->tests->addTestCaseMethodFilter(new IssueTestCaseFilter((int) $issue));\n    }\n\n    if ($pr = $input->getParameterOption('--pr')) {\n        $testSuite->tests->addTestCaseMethodFilter(new PrTestCaseFilter((int) $pr));\n    }\n\n    if ($pr = $input->getParameterOption('--pull-request')) {\n        $testSuite->tests->addTestCaseMethodFilter(new PrTestCaseFilter((int) $pr));\n    }\n\n    $isDecorated = $input->getParameterOption('--colors', 'always') !== 'never';\n\n    $output = new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, $isDecorated);\n\n    try {\n        $kernel = Kernel::boot($testSuite, $input, $output);\n\n        $result = $kernel->handle($originalArguments, $arguments);\n\n        $kernel->terminate();\n    } catch (Throwable|Error $e) {\n        Panic::with($e);\n    }\n\n    exit($result);\n})();\n"
  },
  {
    "path": "bin/worker.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nuse ParaTest\\WrapperRunner\\ApplicationForWrapperWorker;\nuse ParaTest\\WrapperRunner\\WrapperWorker;\nuse Pest\\Kernel;\nuse Pest\\Plugins\\Actions\\CallsHandleArguments;\nuse Pest\\TestSuite;\nuse Symfony\\Component\\Console\\Input\\ArgvInput;\nuse Symfony\\Component\\Console\\Output\\ConsoleOutput;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n$bootPest = (static function (): void {\n    $workerArgv = new ArgvInput;\n\n    $rootPath = dirname(PHPUNIT_COMPOSER_INSTALL, 2);\n    $testSuite = TestSuite::getInstance($rootPath, $workerArgv->getParameterOption(\n        '--test-directory',\n        'tests'\n    ));\n\n    $input = new ArgvInput;\n\n    $output = new ConsoleOutput(OutputInterface::VERBOSITY_NORMAL, true);\n\n    Kernel::boot($testSuite, $input, $output);\n});\n\n(static function () use ($bootPest): void {\n    $getopt = getopt('', [\n        'status-file:',\n        'progress-file:',\n        'unexpected-output-file:',\n        'test-result-file:',\n        'result-cache-file:',\n        'teamcity-file:',\n        'testdox-file:',\n        'testdox-color',\n        'testdox-columns:',\n        'testdox-summary',\n        'phpunit-argv:',\n    ]);\n\n    $composerAutoloadFiles = [\n        dirname(__DIR__, 3).DIRECTORY_SEPARATOR.'autoload.php',\n        dirname(__DIR__, 2).DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'autoload.php',\n        dirname(__DIR__).DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'autoload.php',\n    ];\n\n    foreach ($composerAutoloadFiles as $file) {\n\n        if (file_exists($file)) {\n            require_once $file;\n            define('PHPUNIT_COMPOSER_INSTALL', $file);\n\n            break;\n        }\n    }\n\n    assert(isset($getopt['status-file']) && is_string($getopt['status-file']));\n    $statusFile = fopen($getopt['status-file'], 'wb');\n    assert(is_resource($statusFile));\n\n    assert(isset($getopt['progress-file']) && is_string($getopt['progress-file']));\n    assert(isset($getopt['unexpected-output-file']) && is_string($getopt['unexpected-output-file']));\n    assert(isset($getopt['test-result-file']) && is_string($getopt['test-result-file']));\n    assert(! isset($getopt['result-cache-file']) || is_string($getopt['result-cache-file']));\n    assert(! isset($getopt['teamcity-file']) || is_string($getopt['teamcity-file']));\n    assert(! isset($getopt['testdox-file']) || is_string($getopt['testdox-file']));\n\n    assert(isset($getopt['phpunit-argv']) && is_string($getopt['phpunit-argv']));\n    $phpunitArgv = unserialize($getopt['phpunit-argv'], ['allowed_classes' => false]);\n    assert(is_array($phpunitArgv));\n\n    $bootPest();\n\n    $phpunitArgv = CallsHandleArguments::execute($phpunitArgv);\n\n    $application = new ApplicationForWrapperWorker(\n        $phpunitArgv,\n        $getopt['progress-file'],\n        $getopt['unexpected-output-file'],\n        $getopt['test-result-file'],\n        $getopt['result-cache-file'] ?? null,\n        $getopt['teamcity-file'] ?? null,\n        $getopt['testdox-file'] ?? null,\n        isset($getopt['testdox-color']),\n        (int) ($getopt['testdox-columns'] ?? null),\n    );\n\n    while (true) {\n        if (feof(STDIN)) {\n            $application->end();\n            exit;\n        }\n\n        $testPath = fgets(STDIN);\n        if ($testPath === false || $testPath === WrapperWorker::COMMAND_EXIT) {\n            $application->end();\n            exit;\n        }\n\n        // It must be a 1 byte string to ensure filesize() is equal to the number of tests executed\n        $exitCode = $application->runTest(realpath(trim($testPath)));\n\n        fwrite($statusFile, (string) $exitCode);\n        fflush($statusFile);\n    }\n})();\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"pestphp/pest\",\n    \"description\": \"The elegant PHP Testing Framework.\",\n    \"keywords\": [\n        \"php\",\n        \"framework\",\n        \"pest\",\n        \"unit\",\n        \"test\",\n        \"testing\"\n    ],\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"Nuno Maduro\",\n            \"email\": \"enunomaduro@gmail.com\"\n        }\n    ],\n    \"require\": {\n        \"php\": \"^8.3.0\",\n        \"brianium/paratest\": \"^7.19.0\",\n        \"nunomaduro/collision\": \"^8.9.1\",\n        \"nunomaduro/termwind\": \"^2.4.0\",\n        \"pestphp/pest-plugin\": \"^4.0.0\",\n        \"pestphp/pest-plugin-arch\": \"^4.0.0\",\n        \"pestphp/pest-plugin-mutate\": \"^4.0.1\",\n        \"pestphp/pest-plugin-profanity\": \"^4.2.1\",\n        \"phpunit/phpunit\": \"^12.5.12\",\n        \"symfony/process\": \"^7.4.5|^8.0.5\"\n    },\n    \"conflict\": {\n        \"filp/whoops\": \"<2.18.3\",\n        \"phpunit/phpunit\": \">12.5.12\",\n        \"sebastian/exporter\": \"<7.0.0\",\n        \"webmozart/assert\": \"<1.11.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Pest\\\\\": \"src/\"\n        },\n        \"files\": [\n            \"src/Functions.php\",\n            \"src/Pest.php\"\n        ]\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"Tests\\\\Fixtures\\\\Covers\\\\\": \"tests/Fixtures/Covers\",\n            \"Tests\\\\Fixtures\\\\Inheritance\\\\\": \"tests/Fixtures/Inheritance\",\n            \"Tests\\\\Fixtures\\\\Arch\\\\\": \"tests/Fixtures/Arch\",\n            \"Tests\\\\\": \"tests/PHPUnit/\"\n        },\n        \"files\": [\n            \"tests/Autoload.php\"\n        ]\n    },\n    \"require-dev\": {\n        \"pestphp/pest-dev-tools\": \"^4.1.0\",\n        \"pestphp/pest-plugin-browser\": \"^4.3.0\",\n        \"pestphp/pest-plugin-type-coverage\": \"^4.0.3\",\n        \"psy/psysh\": \"^0.12.21\"\n    },\n    \"minimum-stability\": \"dev\",\n    \"prefer-stable\": true,\n    \"config\": {\n        \"sort-packages\": true,\n        \"preferred-install\": \"dist\",\n        \"allow-plugins\": {\n            \"pestphp/pest-plugin\": true\n        }\n    },\n    \"bin\": [\n        \"bin/pest\"\n    ],\n    \"scripts\": {\n        \"refacto\": \"rector\",\n        \"lint\": \"pint --parallel\",\n        \"test:refacto\": \"rector --dry-run\",\n        \"test:lint\": \"pint --parallel --test\",\n        \"test:profanity\": \"php bin/pest --profanity --compact\",\n        \"test:type:check\": \"phpstan analyse --ansi --memory-limit=-1 --debug\",\n        \"test:type:coverage\": \"php -d memory_limit=-1  bin/pest --type-coverage --min=100\",\n        \"test:unit\": \"php bin/pest --exclude-group=integration --compact\",\n        \"test:inline\": \"php bin/pest --configuration=phpunit.inline.xml\",\n        \"test:parallel\": \"php bin/pest --exclude-group=integration --parallel --processes=3\",\n        \"test:integration\": \"php bin/pest --group=integration -v\",\n        \"update:snapshots\": \"REBUILD_SNAPSHOTS=true php bin/pest --update-snapshots\",\n        \"test\": [\n            \"@test:refacto\",\n            \"@test:lint\",\n            \"@test:type:check\",\n            \"@test:type:coverage\",\n            \"@test:unit\",\n            \"@test:parallel\",\n            \"@test:integration\"\n        ]\n    },\n    \"extra\": {\n        \"pest\": {\n            \"plugins\": [\n                \"Pest\\\\Mutate\\\\Plugins\\\\Mutate\",\n                \"Pest\\\\Plugins\\\\Configuration\",\n                \"Pest\\\\Plugins\\\\Bail\",\n                \"Pest\\\\Plugins\\\\Cache\",\n                \"Pest\\\\Plugins\\\\Coverage\",\n                \"Pest\\\\Plugins\\\\Init\",\n                \"Pest\\\\Plugins\\\\Environment\",\n                \"Pest\\\\Plugins\\\\Help\",\n                \"Pest\\\\Plugins\\\\Memory\",\n                \"Pest\\\\Plugins\\\\Only\",\n                \"Pest\\\\Plugins\\\\Printer\",\n                \"Pest\\\\Plugins\\\\ProcessIsolation\",\n                \"Pest\\\\Plugins\\\\Profile\",\n                \"Pest\\\\Plugins\\\\Retry\",\n                \"Pest\\\\Plugins\\\\Snapshot\",\n                \"Pest\\\\Plugins\\\\Verbose\",\n                \"Pest\\\\Plugins\\\\Version\",\n                \"Pest\\\\Plugins\\\\Shard\",\n                \"Pest\\\\Plugins\\\\Parallel\"\n            ]\n        },\n        \"phpstan\": {\n            \"includes\": [\n                \"extension.neon\"\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "docker/Dockerfile",
    "content": "ARG PHP=8.1\nFROM php:${PHP}-cli-alpine\n\nRUN apk update && apk add \\\n    zip libzip-dev icu-dev git\n\nRUN docker-php-ext-install zip intl\n\nRUN apk add --no-cache linux-headers autoconf build-base\nRUN pecl install xdebug\nRUN docker-php-ext-enable xdebug\nCOPY --from=composer:2 /usr/bin/composer /usr/bin/composer\n\nWORKDIR /var/www/html\n\nENTRYPOINT [\"php\"]\n"
  },
  {
    "path": "extension.neon",
    "content": "parameters:\n    universalObjectCratesClasses:\n        - Pest\\Support\\HigherOrderTapProxy\n        - Pest\\Expectation\n"
  },
  {
    "path": "overrides/Event/Value/ThrowableBuilder.php",
    "content": "<?php\n\n/*\n * BSD 3-Clause License\n *\n * Copyright (c) 2001-2023, Sebastian Bergmann\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\ndeclare(strict_types=1);\n\n/*\n * This file is part of PHPUnit.\n *\n * (c) Sebastian Bergmann <sebastian@phpunit.de>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace PHPUnit\\Event\\Code;\n\nuse NunoMaduro\\Collision\\Contracts\\RenderableOnCollisionEditor;\nuse PHPUnit\\Event\\NoPreviousThrowableException;\nuse PHPUnit\\Framework\\Exception;\nuse PHPUnit\\Util\\Filter;\nuse PHPUnit\\Util\\ThrowableToStringMapper;\n\n/**\n * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit\n *\n * @internal This class is not covered by the backward compatibility promise for PHPUnit\n */\nfinal readonly class ThrowableBuilder\n{\n    /**\n     * @throws Exception\n     * @throws NoPreviousThrowableException\n     */\n    public static function from(\\Throwable $t): Throwable\n    {\n        $previous = $t->getPrevious();\n\n        if ($previous !== null) {\n            $previous = self::from($previous);\n        }\n\n        $trace = Filter::stackTraceFromThrowableAsString($t);\n\n        if ($t instanceof RenderableOnCollisionEditor && $frame = $t->toCollisionEditor()) {\n            $file = $frame->getFile();\n            $line = $frame->getLine();\n\n            $trace = \"$file:$line\\n$trace\";\n        }\n\n        return new Throwable(\n            $t::class,\n            $t->getMessage(),\n            ThrowableToStringMapper::map($t),\n            $trace,\n            $previous,\n        );\n    }\n}\n"
  },
  {
    "path": "overrides/Logging/JUnit/JunitXmlLogger.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n/*\n * This file is part of PHPUnit.\n *\n * (c) Sebastian Bergmann <sebastian@phpunit.de>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace PHPUnit\\Logging\\JUnit;\n\nuse DOMDocument;\nuse DOMElement;\nuse Pest\\Logging\\Converter;\nuse Pest\\Support\\Container;\nuse Pest\\TestSuite;\nuse PHPUnit\\Event\\Code\\Test;\nuse PHPUnit\\Event\\Code\\TestMethod;\nuse PHPUnit\\Event\\EventFacadeIsSealedException;\nuse PHPUnit\\Event\\Facade;\nuse PHPUnit\\Event\\InvalidArgumentException;\nuse PHPUnit\\Event\\Telemetry\\HRTime;\nuse PHPUnit\\Event\\Telemetry\\Info;\nuse PHPUnit\\Event\\Test\\Errored;\nuse PHPUnit\\Event\\Test\\Failed;\nuse PHPUnit\\Event\\Test\\Finished;\nuse PHPUnit\\Event\\Test\\MarkedIncomplete;\nuse PHPUnit\\Event\\Test\\PreparationStarted;\nuse PHPUnit\\Event\\Test\\Prepared;\nuse PHPUnit\\Event\\Test\\PrintedUnexpectedOutput;\nuse PHPUnit\\Event\\Test\\Skipped;\nuse PHPUnit\\Event\\TestSuite\\Started;\nuse PHPUnit\\Event\\UnknownSubscriberTypeException;\nuse PHPUnit\\TextUI\\Output\\Printer;\nuse PHPUnit\\Util\\Xml;\n\nuse function assert;\nuse function basename;\nuse function is_int;\nuse function sprintf;\nuse function str_replace;\nuse function trim;\n\n/**\n * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit\n *\n * @internal This class is not covered by the backward compatibility promise for PHPUnit\n */\nfinal class JunitXmlLogger\n{\n    private readonly Printer $printer;\n\n    private readonly Converter $converter; // pest-added\n\n    private DOMDocument $document;\n\n    private DOMElement $root;\n\n    /**\n     * @var DOMElement[]\n     */\n    private array $testSuites = [];\n\n    /**\n     * @var array<int,int>\n     */\n    private array $testSuiteTests = [0];\n\n    /**\n     * @var array<int,int>\n     */\n    private array $testSuiteAssertions = [0];\n\n    /**\n     * @var array<int,int>\n     */\n    private array $testSuiteErrors = [0];\n\n    /**\n     * @var array<int,int>\n     */\n    private array $testSuiteFailures = [0];\n\n    /**\n     * @var array<int,int>\n     */\n    private array $testSuiteSkipped = [0];\n\n    /**\n     * @var array<int,int>\n     */\n    private array $testSuiteTimes = [0];\n\n    private int $testSuiteLevel = 0;\n\n    private ?DOMElement $currentTestCase = null;\n\n    private ?HRTime $time = null;\n\n    private bool $prepared = false;\n\n    private bool $preparationFailed = false;\n\n    /**\n     * @throws EventFacadeIsSealedException\n     * @throws UnknownSubscriberTypeException\n     */\n    public function __construct(Printer $printer, Facade $facade)\n    {\n        $this->printer = $printer;\n        $this->converter = new Converter(Container::getInstance()->get(TestSuite::class)->rootPath); // pest-added\n\n        $this->registerSubscribers($facade);\n        $this->createDocument();\n    }\n\n    public function flush(): void\n    {\n        $this->printer->print($this->document->saveXML() ?: '');\n\n        $this->printer->flush();\n    }\n\n    public function testSuiteStarted(Started $event): void\n    {\n        $testSuite = $this->document->createElement('testsuite');\n        $testSuite->setAttribute('name', $this->converter->getTestSuiteName($event->testSuite())); // pest-changed\n\n        if ($event->testSuite()->isForTestClass()) {\n            $testSuite->setAttribute('file', $this->converter->getTestSuiteLocation($event->testSuite()) ?? ''); // pest-changed\n        }\n\n        if ($this->testSuiteLevel > 0) {\n            $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite);\n        } else {\n            $this->root->appendChild($testSuite);\n        }\n\n        $this->testSuiteLevel++;\n        $this->testSuites[$this->testSuiteLevel] = $testSuite;\n        $this->testSuiteTests[$this->testSuiteLevel] = 0;\n        $this->testSuiteAssertions[$this->testSuiteLevel] = 0;\n        $this->testSuiteErrors[$this->testSuiteLevel] = 0;\n        $this->testSuiteFailures[$this->testSuiteLevel] = 0;\n        $this->testSuiteSkipped[$this->testSuiteLevel] = 0;\n        $this->testSuiteTimes[$this->testSuiteLevel] = 0;\n    }\n\n    public function testSuiteFinished(): void\n    {\n        $this->testSuites[$this->testSuiteLevel]->setAttribute(\n            'tests',\n            (string) $this->testSuiteTests[$this->testSuiteLevel],\n        );\n\n        $this->testSuites[$this->testSuiteLevel]->setAttribute(\n            'assertions',\n            (string) $this->testSuiteAssertions[$this->testSuiteLevel],\n        );\n\n        $this->testSuites[$this->testSuiteLevel]->setAttribute(\n            'errors',\n            (string) $this->testSuiteErrors[$this->testSuiteLevel],\n        );\n\n        $this->testSuites[$this->testSuiteLevel]->setAttribute(\n            'failures',\n            (string) $this->testSuiteFailures[$this->testSuiteLevel],\n        );\n\n        $this->testSuites[$this->testSuiteLevel]->setAttribute(\n            'skipped',\n            (string) $this->testSuiteSkipped[$this->testSuiteLevel],\n        );\n\n        $this->testSuites[$this->testSuiteLevel]->setAttribute(\n            'time',\n            sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel]),\n        );\n\n        if ($this->testSuiteLevel > 1) {\n            $this->testSuiteTests[$this->testSuiteLevel - 1] += $this->testSuiteTests[$this->testSuiteLevel];\n            $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel];\n            $this->testSuiteErrors[$this->testSuiteLevel - 1] += $this->testSuiteErrors[$this->testSuiteLevel];\n            $this->testSuiteFailures[$this->testSuiteLevel - 1] += $this->testSuiteFailures[$this->testSuiteLevel];\n            $this->testSuiteSkipped[$this->testSuiteLevel - 1] += $this->testSuiteSkipped[$this->testSuiteLevel];\n            $this->testSuiteTimes[$this->testSuiteLevel - 1] += $this->testSuiteTimes[$this->testSuiteLevel];\n        }\n\n        $this->testSuiteLevel--;\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    public function testPreparationStarted(PreparationStarted $event): void\n    {\n        $this->createTestCase($event);\n    }\n\n    public function testPreparationFailed(): void\n    {\n        $this->preparationFailed = true;\n    }\n\n    public function testPrepared(): void\n    {\n        $this->prepared = true;\n    }\n\n    public function testPrintedUnexpectedOutput(PrintedUnexpectedOutput $event): void\n    {\n        assert($this->currentTestCase !== null);\n\n        $systemOut = $this->document->createElement(\n            'system-out',\n            Xml::prepareString($event->output()),\n        );\n\n        $this->currentTestCase->appendChild($systemOut);\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    public function testFinished(Finished $event): void\n    {\n        if (! $this->prepared || $this->preparationFailed) {\n            return;\n        }\n\n        $this->handleFinish($event->telemetryInfo(), $event->numberOfAssertionsPerformed());\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    public function testMarkedIncomplete(MarkedIncomplete $event): void\n    {\n        $this->handleIncompleteOrSkipped($event);\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    public function testSkipped(Skipped $event): void\n    {\n        $this->handleIncompleteOrSkipped($event);\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    public function testErrored(Errored $event): void\n    {\n        $this->handleFault($event, 'error');\n\n        $this->testSuiteErrors[$this->testSuiteLevel]++;\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    public function testFailed(Failed $event): void\n    {\n        $this->handleFault($event, 'failure');\n\n        $this->testSuiteFailures[$this->testSuiteLevel]++;\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    private function handleFinish(Info $telemetryInfo, int $numberOfAssertionsPerformed): void\n    {\n        assert($this->currentTestCase !== null);\n        assert($this->time !== null);\n\n        $time = $telemetryInfo->time()->duration($this->time)->asFloat();\n\n        $this->testSuiteAssertions[$this->testSuiteLevel] += $numberOfAssertionsPerformed;\n\n        $this->currentTestCase->setAttribute(\n            'assertions',\n            (string) $numberOfAssertionsPerformed,\n        );\n\n        $this->currentTestCase->setAttribute(\n            'time',\n            sprintf('%F', $time),\n        );\n\n        $this->testSuites[$this->testSuiteLevel]->appendChild(\n            $this->currentTestCase,\n        );\n\n        $this->testSuiteTests[$this->testSuiteLevel]++;\n        $this->testSuiteTimes[$this->testSuiteLevel] += $time;\n\n        $this->currentTestCase = null;\n        $this->time = null;\n        $this->prepared = false;\n    }\n\n    /**\n     * @throws EventFacadeIsSealedException\n     * @throws UnknownSubscriberTypeException\n     */\n    private function registerSubscribers(Facade $facade): void\n    {\n        $facade->registerSubscribers(\n            new TestSuiteStartedSubscriber($this),\n            new TestSuiteFinishedSubscriber($this),\n            new TestPreparationStartedSubscriber($this),\n            new TestPreparationFailedSubscriber($this),\n            new TestPreparedSubscriber($this),\n            new TestPrintedUnexpectedOutputSubscriber($this),\n            new TestFinishedSubscriber($this),\n            new TestErroredSubscriber($this),\n            new TestFailedSubscriber($this),\n            new TestMarkedIncompleteSubscriber($this),\n            new TestSkippedSubscriber($this),\n            new TestRunnerExecutionFinishedSubscriber($this),\n        );\n    }\n\n    private function createDocument(): void\n    {\n        $this->document = new DOMDocument('1.0', 'UTF-8');\n        $this->document->formatOutput = true;\n\n        $this->root = $this->document->createElement('testsuites');\n        $this->document->appendChild($this->root);\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    private function handleFault(Errored|Failed $event, string $type): void\n    {\n        if (! $this->prepared) {\n            $this->createTestCase($event);\n        }\n\n        assert($this->currentTestCase !== null);\n\n        $buffer = $this->converter->getTestCaseMethodName($event->test()); // pest-changed\n\n        $throwable = $event->throwable();\n        $buffer .= trim(\n            $this->converter->getExceptionMessage($throwable).PHP_EOL. // pest-changed\n            $this->converter->getExceptionDetails($throwable), // pest-changed\n        );\n\n        $fault = $this->document->createElement(\n            $type,\n            Xml::prepareString($buffer),\n        );\n\n        $fault->setAttribute('type', $throwable->className());\n\n        $this->currentTestCase->appendChild($fault);\n\n        if (! $this->prepared) {\n            $this->handleFinish($event->telemetryInfo(), 0);\n        }\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    private function handleIncompleteOrSkipped(MarkedIncomplete|Skipped $event): void\n    {\n        if (! $this->prepared) {\n            $this->createTestCase($event);\n        }\n\n        assert($this->currentTestCase !== null);\n\n        $skipped = $this->document->createElement('skipped');\n\n        $this->currentTestCase->appendChild($skipped);\n\n        $this->testSuiteSkipped[$this->testSuiteLevel]++;\n\n        if (! $this->prepared) {\n            $this->handleFinish($event->telemetryInfo(), 0);\n        }\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    private function testAsString(Test $test): string\n    {\n        if ($test->isPhpt()) {\n            return basename($test->file());\n        }\n\n        assert($test instanceof TestMethod);\n\n        return sprintf(\n            '%s::%s%s',\n            $test->className(),\n            $this->name($test),\n            PHP_EOL,\n        );\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     */\n    private function name(Test $test): string\n    {\n        if ($test->isPhpt()) {\n            return basename($test->file());\n        }\n\n        assert($test instanceof TestMethod);\n\n        if (! $test->testData()->hasDataFromDataProvider()) {\n            return $test->methodName();\n        }\n\n        $dataSetName = $test->testData()->dataFromDataProvider()->dataSetName();\n\n        if (is_int($dataSetName)) {\n            return sprintf(\n                '%s with data set #%d',\n                $test->methodName(),\n                $dataSetName,\n            );\n        }\n\n        return sprintf(\n            '%s with data set \"%s\"',\n            $test->methodName(),\n            $dataSetName,\n        );\n    }\n\n    /**\n     * @throws InvalidArgumentException\n     *\n     * @phpstan-assert !null $this->currentTestCase\n     */\n    private function createTestCase(Errored|Failed|MarkedIncomplete|PreparationStarted|Prepared|Skipped $event): void\n    {\n        $testCase = $this->document->createElement('testcase');\n\n        $test = $event->test();\n        $file = $this->converter->getTestCaseLocation($test); // pest-added\n\n        $testCase->setAttribute('name', $this->converter->getTestCaseMethodName($test)); // pest-changed\n        $testCase->setAttribute('file', $file); // pest-changed\n\n        if ($test->isTestMethod()) {\n            assert($test instanceof TestMethod);\n\n            // $testCase->setAttribute('line', (string) $test->line()); // pest-removed\n            $className = $this->converter->getTrimmedTestClassName($test); // pest-added\n            $testCase->setAttribute('class', $className); // pest-changed\n            $testCase->setAttribute('classname', str_replace('\\\\', '.', $className)); // pest-changed\n        }\n\n        $this->currentTestCase = $testCase;\n        $this->time = $event->telemetryInfo()->time();\n    }\n}\n"
  },
  {
    "path": "overrides/Runner/Filter/NameFilterIterator.php",
    "content": "<?php\n\n/*\n * BSD 3-Clause License\n *\n * Copyright (c) 2001-2023, Sebastian Bergmann\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\ndeclare(strict_types=1);\n\n/*\n * This file is part of PHPUnit.\n *\n * (c) Sebastian Bergmann <sebastian@phpunit.de>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace PHPUnit\\Runner\\Filter;\n\nuse Pest\\Contracts\\HasPrintableTestCaseName;\nuse PHPUnit\\Framework\\Test;\nuse PHPUnit\\Framework\\TestSuite;\nuse PHPUnit\\Runner\\PhptTestCase;\nuse RecursiveFilterIterator;\nuse RecursiveIterator;\n\nuse function end;\nuse function preg_match;\nuse function sprintf;\nuse function str_replace;\n\n/**\n * @internal This class is not covered by the backward compatibility promise for PHPUnit\n */\nabstract class NameFilterIterator extends RecursiveFilterIterator\n{\n    /**\n     * @psalm-var non-empty-string\n     */\n    private readonly string $regularExpression;\n\n    private readonly ?int $dataSetMinimum;\n\n    private readonly ?int $dataSetMaximum;\n\n    /**\n     * @psalm-param RecursiveIterator<int, Test> $iterator\n     * @psalm-param non-empty-string $filter\n     */\n    public function __construct(RecursiveIterator $iterator, string $filter)\n    {\n        parent::__construct($iterator);\n\n        $preparedFilter = $this->prepareFilter($filter);\n\n        $this->regularExpression = $preparedFilter['regularExpression'];\n        $this->dataSetMinimum = $preparedFilter['dataSetMinimum'];\n        $this->dataSetMaximum = $preparedFilter['dataSetMaximum'];\n    }\n\n    public function accept(): bool\n    {\n        $test = $this->getInnerIterator()->current();\n\n        if ($test instanceof TestSuite) {\n            return true;\n        }\n\n        if ($test instanceof PhptTestCase) {\n            return false;\n        }\n\n        if ($test instanceof HasPrintableTestCaseName) {\n            $name = trim(\n                $test::getPrintableTestCaseName().'::'.$test->getPrintableTestCaseMethodName().$test->dataSetAsString()\n            );\n        } else {\n            $name = $test::class.'::'.$test->nameWithDataSet();\n        }\n\n        $accepted = @preg_match($this->regularExpression, $name, $matches) === 1;\n\n        if ($accepted && isset($this->dataSetMaximum)) {\n            $set = end($matches);\n            $accepted = $set >= $this->dataSetMinimum && $set <= $this->dataSetMaximum;\n        }\n\n        return $this->doAccept($accepted);\n    }\n\n    abstract protected function doAccept(bool $result): bool;\n\n    /**\n     * @psalm-param non-empty-string $filter\n     *\n     * @psalm-return array{regularExpression: non-empty-string, dataSetMinimum: ?int, dataSetMaximum: ?int}\n     */\n    private function prepareFilter(string $filter): array\n    {\n        $dataSetMinimum = null;\n        $dataSetMaximum = null;\n\n        if (@preg_match($filter, '') === false) {\n            // Handles:\n            //  * testAssertEqualsSucceeds#4\n            //  * testAssertEqualsSucceeds#4-8\n            if (preg_match('/^(.*?)#(\\d+)(?:-(\\d+))?$/', $filter, $matches)) {\n                if (isset($matches[3]) && $matches[2] < $matches[3]) {\n                    $filter = sprintf(\n                        '%s.*with data set #(\\d+)$',\n                        $matches[1],\n                    );\n\n                    $dataSetMinimum = (int) $matches[2];\n                    $dataSetMaximum = (int) $matches[3];\n                } else {\n                    $filter = sprintf(\n                        '%s.*with data set #%s$',\n                        $matches[1],\n                        $matches[2],\n                    );\n                }\n            } // Handles:\n            //  * testDetermineJsonError@JSON_ERROR_NONE\n            //  * testDetermineJsonError@JSON.*\n            elseif (preg_match('/^(.*?)@(.+)$/', $filter, $matches)) {\n                $filter = sprintf(\n                    '%s.*with data set \"%s\"$',\n                    $matches[1],\n                    $matches[2],\n                );\n            }\n\n            // Escape delimiters in regular expression. Do NOT use preg_quote,\n            // to keep magic characters.\n            $filter = sprintf(\n                '/%s/i',\n                str_replace(\n                    '/',\n                    '\\\\/',\n                    $filter,\n                ),\n            );\n        }\n\n        return [\n            'regularExpression' => $filter,\n            'dataSetMinimum' => $dataSetMinimum,\n            'dataSetMaximum' => $dataSetMaximum,\n        ];\n    }\n}\n"
  },
  {
    "path": "overrides/Runner/ResultCache/DefaultResultCache.php",
    "content": "<?php\n\n/*\n * BSD 3-Clause License\n *\n * Copyright (c) 2001-2023, Sebastian Bergmann\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\ndeclare(strict_types=1);\n\n/*\n * This file is part of PHPUnit.\n *\n * (c) Sebastian Bergmann <sebastian@phpunit.de>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace PHPUnit\\Runner\\ResultCache;\n\nuse const DIRECTORY_SEPARATOR;\nuse const LOCK_EX;\n\nuse PHPUnit\\Framework\\TestStatus\\TestStatus;\nuse PHPUnit\\Runner\\DirectoryDoesNotExistException;\nuse PHPUnit\\Runner\\Exception;\nuse PHPUnit\\Util\\Filesystem;\n\nuse function array_keys;\nuse function assert;\nuse function dirname;\nuse function file_get_contents;\nuse function file_put_contents;\nuse function is_array;\nuse function is_dir;\nuse function is_file;\nuse function json_decode;\nuse function json_encode;\nuse function Pest\\version;\n\n/**\n * @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit\n *\n * @internal This class is not covered by the backward compatibility promise for PHPUnit\n */\nfinal class DefaultResultCache implements ResultCache\n{\n    private const string DEFAULT_RESULT_CACHE_FILENAME = '.phpunit.result.cache';\n\n    private readonly string $cacheFilename;\n\n    /**\n     * @var array<string, TestStatus>\n     */\n    private array $defects = [];\n\n    /**\n     * @var array<string, float>\n     */\n    private array $times = [];\n\n    public function __construct(?string $filepath = null)\n    {\n        if ($filepath !== null && is_dir($filepath)) {\n            $filepath .= DIRECTORY_SEPARATOR.self::DEFAULT_RESULT_CACHE_FILENAME;\n        }\n\n        $this->cacheFilename = $filepath ?? $_ENV['PHPUNIT_RESULT_CACHE'] ?? self::DEFAULT_RESULT_CACHE_FILENAME;\n    }\n\n    public function setStatus(ResultCacheId $id, TestStatus $status): void\n    {\n        if ($status->isSuccess()) {\n            return;\n        }\n\n        $this->defects[$id->asString()] = $status;\n    }\n\n    public function status(ResultCacheId $id): TestStatus\n    {\n        return $this->defects[$id->asString()] ?? TestStatus::unknown();\n    }\n\n    public function setTime(ResultCacheId $id, float $time): void\n    {\n        $this->times[$id->asString()] = $time;\n    }\n\n    public function time(ResultCacheId $id): float\n    {\n        return $this->times[$id->asString()] ?? 0.0;\n    }\n\n    public function mergeWith(self $other): void\n    {\n        foreach ($other->defects as $id => $defect) {\n            $this->defects[$id] = $defect;\n        }\n\n        foreach ($other->times as $id => $time) {\n            $this->times[$id] = $time;\n        }\n    }\n\n    public function load(): void\n    {\n        if (! is_file($this->cacheFilename)) {\n            return;\n        }\n\n        $contents = file_get_contents($this->cacheFilename);\n\n        if ($contents === false) {\n            return;\n        }\n\n        $data = json_decode(\n            $contents,\n            true,\n        );\n\n        if ($data === null) {\n            return;\n        }\n\n        if (! isset($data['version'])) {\n            return;\n        }\n\n        if ($data['version'] !== $this->cacheVersion()) {\n            return;\n        }\n\n        assert(isset($data['defects']) && is_array($data['defects']));\n        assert(isset($data['times']) && is_array($data['times']));\n\n        foreach (array_keys($data['defects']) as $test) {\n            $data['defects'][$test] = TestStatus::from($data['defects'][$test]);\n        }\n\n        $this->defects = $data['defects'];\n        $this->times = $data['times'];\n    }\n\n    /**\n     * @throws Exception\n     */\n    public function persist(): void\n    {\n        if (! Filesystem::createDirectory(dirname($this->cacheFilename))) {\n            throw new DirectoryDoesNotExistException(dirname($this->cacheFilename));\n        }\n\n        $data = [\n            'version' => $this->cacheVersion(),\n            'defects' => [],\n            'times' => $this->times,\n        ];\n\n        foreach ($this->defects as $test => $status) {\n            $data['defects'][$test] = $status->asInt();\n        }\n\n        file_put_contents(\n            $this->cacheFilename,\n            json_encode($data),\n            LOCK_EX,\n        );\n    }\n\n    /**\n     * Returns the cache version.\n     */\n    private function cacheVersion(): string\n    {\n        return 'pest_'.version();\n    }\n}\n"
  },
  {
    "path": "overrides/Runner/TestSuiteLoader.php",
    "content": "<?php\n\n/*\n * BSD 3-Clause License\n *\n * Copyright (c) 2001-2023, Sebastian Bergmann\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\ndeclare(strict_types=1);\n\nnamespace PHPUnit\\Runner;\n\nuse Exception;\nuse Pest\\Contracts\\HasPrintableTestCaseName;\nuse Pest\\Panic;\nuse Pest\\TestCases\\IgnorableTestCase;\nuse Pest\\TestSuite;\nuse PHPUnit\\Framework\\TestCase;\nuse ReflectionClass;\nuse ReflectionException;\nuse Throwable;\n\nuse function array_diff;\nuse function array_values;\nuse function basename;\nuse function class_exists;\nuse function get_declared_classes;\nuse function substr;\n\n/**\n * @internal This class is not covered by the backward compatibility promise for PHPUnit\n */\nfinal class TestSuiteLoader\n{\n    /**\n     * @psalm-var list<class-string>\n     */\n    private static array $loadedClasses = [];\n\n    /**\n     * @psalm-var array<string, array<class-string>>\n     */\n    private static array $loadedClassesByFilename = [];\n\n    /**\n     * @psalm-var list<class-string>\n     */\n    private static array $declaredClasses = [];\n\n    public function __construct()\n    {\n        if (empty(self::$declaredClasses)) {\n            self::$declaredClasses = get_declared_classes();\n        }\n    }\n\n    /**\n     * @throws Exception\n     */\n    public function load(string $suiteClassFile): ReflectionClass\n    {\n        $suiteClassName = $this->classNameFromFileName($suiteClassFile);\n\n        (static function () use ($suiteClassFile) {\n            try {\n                include_once $suiteClassFile;\n            } catch (Throwable $e) {\n                Panic::with($e);\n            }\n\n            TestSuite::getInstance()->tests->makeIfNeeded($suiteClassFile);\n        })();\n\n        $loadedClasses = array_values(\n            array_diff(\n                get_declared_classes(),\n                array_merge(\n                    self::$declaredClasses,\n                    self::$loadedClasses\n                )\n            )\n        );\n\n        self::$loadedClasses = array_merge($loadedClasses, self::$loadedClasses);\n\n        foreach ($loadedClasses as $loadedClass) {\n            $reflection = new ReflectionClass($loadedClass);\n            $filename = $reflection->getFileName();\n            self::$loadedClassesByFilename[$filename] = [\n                $loadedClass,\n                ...self::$loadedClassesByFilename[$filename] ?? [],\n            ];\n        }\n\n        $loadedClasses = array_merge(self::$loadedClassesByFilename[$suiteClassFile] ?? [], $loadedClasses);\n\n        if (empty($loadedClasses)) {\n            return $this->exceptionFor($suiteClassName, $suiteClassFile);\n        }\n\n        $testCaseFound = false;\n        $class = false;\n\n        foreach (array_reverse($loadedClasses) as $loadedClass) {\n            if (\n                is_subclass_of($loadedClass, HasPrintableTestCaseName::class)\n                || is_subclass_of($loadedClass, TestCase::class)) {\n                try {\n                    $class = new ReflectionClass($loadedClass);\n                    // @codeCoverageIgnoreStart\n                } catch (ReflectionException) {\n                    continue;\n                }\n\n                if ($class->isAbstract() || ($suiteClassFile !== $class->getFileName())) {\n                    if (! str_contains($class->getFileName(), 'TestCaseFactory.php')) {\n                        continue;\n                    }\n                }\n\n                $suiteClassName = $loadedClass;\n                $testCaseFound = true;\n\n                break;\n            }\n        }\n\n        if (! $testCaseFound) {\n            foreach (array_reverse($loadedClasses) as $loadedClass) {\n                $offset = 0 - strlen($suiteClassName);\n\n                if (stripos(substr($loadedClass, $offset - 1), '\\\\'.$suiteClassName) === 0 ||\n                    stripos(substr($loadedClass, $offset - 1), '_'.$suiteClassName) === 0) {\n                    try {\n                        $class = new ReflectionClass($loadedClass);\n                        // @codeCoverageIgnoreStart\n                    } catch (ReflectionException) {\n                        continue;\n                    }\n\n                    $suiteClassName = $loadedClass;\n                    $testCaseFound = true;\n\n                    break;\n                }\n            }\n        }\n\n        if (! $testCaseFound) {\n            return $this->exceptionFor($suiteClassName, $suiteClassFile);\n        }\n\n        if (! class_exists($suiteClassName, false)) {\n            return $this->exceptionFor($suiteClassName, $suiteClassFile);\n        }\n\n        // @codeCoverageIgnoreEnd\n\n        if ($class->isSubclassOf(TestCase::class) && ! $class->isAbstract()) {\n            return $class;\n        }\n\n        if ($class->hasMethod('suite')) {\n            try {\n                $method = $class->getMethod('suite');\n                // @codeCoverageIgnoreStart\n            } catch (ReflectionException $e) {\n                throw new Exception($e->getMessage(), (int) $e->getCode(), $e);\n            }\n            // @codeCoverageIgnoreEnd\n\n            if (! $method->isAbstract() && $method->isPublic() && $method->isStatic()) {\n                return $class;\n            }\n        }\n\n        return $this->exceptionFor($suiteClassName, $suiteClassFile);\n    }\n\n    public function reload(ReflectionClass $aClass): ReflectionClass\n    {\n        return $aClass;\n    }\n\n    private function classNameFromFileName(string $suiteClassFile): string\n    {\n        $className = basename($suiteClassFile, '.php');\n        $dotPos = strpos($className, '.');\n\n        if ($dotPos !== false) {\n            $className = substr($className, 0, $dotPos);\n        }\n\n        return $className;\n    }\n\n    private function exceptionFor(string $className, string $filename): ReflectionClass\n    {\n        return new ReflectionClass(IgnorableTestCase::class);\n    }\n}\n"
  },
  {
    "path": "overrides/TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php",
    "content": "<?php\n\n/*\n * BSD 3-Clause License\n *\n * Copyright (c) 2001-2023, Sebastian Bergmann\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\ndeclare(strict_types=1);\n\n/*\n * This file is part of PHPUnit.\n *\n * (c) Sebastian Bergmann <sebastian@phpunit.de>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace PHPUnit\\TextUI\\Command;\n\nuse const PHP_EOL;\n\nuse PHPUnit\\TextUI\\Configuration\\CodeCoverageFilterRegistry;\nuse PHPUnit\\TextUI\\Configuration\\Configuration;\nuse PHPUnit\\TextUI\\Configuration\\NoCoverageCacheDirectoryException;\nuse SebastianBergmann\\CodeCoverage\\StaticAnalysis\\CacheWarmer;\nuse SebastianBergmann\\Timer\\NoActiveTimerException;\nuse SebastianBergmann\\Timer\\Timer;\n\n/**\n * @internal This class is not covered by the backward compatibility promise for PHPUnit\n */\nfinal readonly class WarmCodeCoverageCacheCommand implements Command\n{\n    private Configuration $configuration;\n\n    private CodeCoverageFilterRegistry $codeCoverageFilterRegistry;\n\n    public function __construct(Configuration $configuration, CodeCoverageFilterRegistry $codeCoverageFilterRegistry)\n    {\n        $this->configuration = $configuration;\n        $this->codeCoverageFilterRegistry = $codeCoverageFilterRegistry;\n    }\n\n    /**\n     * @throws NoActiveTimerException\n     * @throws NoCoverageCacheDirectoryException\n     */\n    public function execute(): Result\n    {\n        if (! $this->configuration->hasCoverageCacheDirectory()) {\n            return Result::from(\n                'Cache for static analysis has not been configured'.PHP_EOL,\n                Result::FAILURE,\n            );\n        }\n\n        $this->codeCoverageFilterRegistry->init($this->configuration, true);\n\n        if (! $this->codeCoverageFilterRegistry->configured()) {\n            return Result::from(\n                'Filter for code coverage has not been configured'.PHP_EOL,\n                Result::FAILURE,\n            );\n        }\n\n        $timer = new Timer;\n        $timer->start();\n\n        (new CacheWarmer)->warmCache(\n            $this->configuration->coverageCacheDirectory(),\n            ! $this->configuration->disableCodeCoverageIgnore(),\n            $this->configuration->ignoreDeprecatedCodeUnitsFromCodeCoverage(),\n            $this->codeCoverageFilterRegistry->get(),\n        );\n\n        return Result::from();\n    }\n}\n"
  },
  {
    "path": "overrides/TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php",
    "content": "<?php\n\n/*\n * BSD 3-Clause License\n *\n * Copyright (c) 2001-2023, Sebastian Bergmann\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\ndeclare(strict_types=1);\n\n/*\n * This file is part of PHPUnit.\n *\n * (c) Sebastian Bergmann <sebastian@phpunit.de>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\Test\\Skipped;\nuse PHPUnit\\Event\\Test\\SkippedSubscriber;\nuse ReflectionClass;\n\n/**\n * @internal This class is not covered by the backward compatibility promise for PHPUnit\n */\nfinal class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber\n{\n    public function notify(Skipped $event): void\n    {\n        if (str_contains($event->message(), '__TODO__')) {\n            $this->printTodoItem();\n        }\n\n        $this->logger()->testSkipped($event);\n    }\n\n    /**\n     * Prints a \"T\" to the standard PHPUnit output to indicate a todo item.\n     */\n    private function printTodoItem(): void\n    {\n        $mirror = new ReflectionClass($this->printer());\n        $printerMirror = $mirror->getMethod('printProgress');\n        $printerMirror->invoke($this->printer(), 'T');\n    }\n}\n"
  },
  {
    "path": "overrides/TextUI/TestSuiteFilterProcessor.php",
    "content": "<?php\n\n/*\n * BSD 3-Clause License\n *\n * Copyright (c) 2001-2023, Sebastian Bergmann\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n *    list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n *    this list of conditions and the following disclaimer in the documentation\n *    and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\ndeclare(strict_types=1);\n/*\n * This file is part of PHPUnit.\n *\n * (c) Sebastian Bergmann <sebastian@phpunit.de>\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nnamespace PHPUnit\\TextUI;\n\nuse Pest\\Plugins\\Only;\nuse Pest\\Runner\\Filter\\EnsureTestCaseIsInitiatedFilter;\nuse PHPUnit\\Event;\nuse PHPUnit\\Framework\\TestSuite;\nuse PHPUnit\\Runner\\Filter\\Factory;\nuse PHPUnit\\TextUI\\Configuration\\Configuration;\nuse PHPUnit\\TextUI\\Configuration\\FilterNotConfiguredException;\n\nuse function array_map;\n\n/**\n * @internal This class is not covered by the backward compatibility promise for PHPUnit\n */\nfinal readonly class TestSuiteFilterProcessor\n{\n    /**\n     * @throws Event\\RuntimeException\n     * @throws FilterNotConfiguredException\n     */\n    public function process(Configuration $configuration, TestSuite $suite): void\n    {\n        $factory = new Factory;\n\n        // @phpstan-ignore-next-line\n        (fn () => $this->filters[] = [\n            'className' => EnsureTestCaseIsInitiatedFilter::class,\n            'argument' => '',\n        ])->call($factory);\n\n        if (! $configuration->hasFilter() &&\n            ! $configuration->hasGroups() &&\n            ! $configuration->hasExcludeGroups() &&\n            ! $configuration->hasExcludeFilter() &&\n            ! $configuration->hasTestsCovering() &&\n            ! $configuration->hasTestsUsing() &&\n            ! Only::isEnabled()) {\n            $suite->injectFilter($factory);\n\n            return;\n        }\n\n        if ($configuration->hasExcludeGroups()) {\n            $factory->addExcludeGroupFilter(\n                $configuration->excludeGroups(),\n            );\n        }\n\n        if (Only::isEnabled()) {\n            $factory->addIncludeGroupFilter([Only::group()]);\n        } elseif ($configuration->hasGroups()) {\n            $factory->addIncludeGroupFilter(\n                $configuration->groups(),\n            );\n        }\n\n        if ($configuration->hasTestsCovering()) {\n            $factory->addIncludeGroupFilter(\n                array_map(\n                    static fn (string $name): string => '__phpunit_covers_'.$name,\n                    $configuration->testsCovering(),\n                ),\n            );\n        }\n\n        if ($configuration->hasTestsUsing()) {\n            $factory->addIncludeGroupFilter(\n                array_map(\n                    static fn (string $name): string => '__phpunit_uses_'.$name,\n                    $configuration->testsUsing(),\n                ),\n            );\n        }\n\n        if ($configuration->hasExcludeFilter()) {\n            $factory->addExcludeNameFilter(\n                $configuration->excludeFilter(),\n            );\n        }\n\n        if ($configuration->hasFilter()) {\n            $factory->addIncludeNameFilter(\n                $configuration->filter(),\n            );\n        }\n\n        $suite->injectFilter($factory);\n\n        Event\\Facade::emitter()->testSuiteFiltered(\n            Event\\TestSuite\\TestSuiteBuilder::from($suite),\n        );\n    }\n}\n"
  },
  {
    "path": "phpstan-baseline.neon",
    "content": "parameters:\n\tignoreErrors:\n\t\t-\n\t\t\tmessage: '#^Parameter \\#1 of callable callable\\(Pest\\\\Expectation\\<string\\|null\\>\\)\\: Pest\\\\Arch\\\\Contracts\\\\ArchExpectation expects Pest\\\\Expectation\\<string\\|null\\>, Pest\\\\Expectation\\<string\\|null\\> given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/ArchPresets/AbstractPreset.php\n\n\t\t-\n\t\t\tmessage: '#^Trait Pest\\\\Concerns\\\\Expectable is used zero times and is not analysed\\.$#'\n\t\t\tidentifier: trait.unused\n\t\t\tcount: 1\n\t\t\tpath: src/Concerns/Expectable.php\n\n\t\t-\n\t\t\tmessage: '#^Trait Pest\\\\Concerns\\\\Logging\\\\WritesToConsole is used zero times and is not analysed\\.$#'\n\t\t\tidentifier: trait.unused\n\t\t\tcount: 1\n\t\t\tpath: src/Concerns/Logging/WritesToConsole.php\n\n\t\t-\n\t\t\tmessage: '#^Trait Pest\\\\Concerns\\\\Testable is used zero times and is not analysed\\.$#'\n\t\t\tidentifier: trait.unused\n\t\t\tcount: 1\n\t\t\tpath: src/Concerns/Testable.php\n\n\t\t-\n\t\t\tmessage: '#^Loose comparison using \\!\\= between \\(Closure\\|null\\) and false will always evaluate to false\\.$#'\n\t\t\tidentifier: notEqual.alwaysFalse\n\t\t\tcount: 1\n\t\t\tpath: src/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^Method Pest\\\\Expectation\\:\\:and\\(\\) should return Pest\\\\Expectation\\<TAndValue\\> but returns \\(Pest\\\\Expectation&TAndValue\\)\\|Pest\\\\Expectation\\<TAndValue of mixed\\>\\.$#'\n\t\t\tidentifier: return.type\n\t\t\tcount: 1\n\t\t\tpath: src/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^PHPDoc tag @property for property Pest\\\\Expectation\\:\\:\\$each contains generic class Pest\\\\Expectations\\\\EachExpectation but does not specify its types\\: TValue$#'\n\t\t\tidentifier: missingType.generics\n\t\t\tcount: 1\n\t\t\tpath: src/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^PHPDoc tag @property for property Pest\\\\Expectation\\:\\:\\$not contains generic class Pest\\\\Expectations\\\\OppositeExpectation but does not specify its types\\: TValue$#'\n\t\t\tidentifier: missingType.generics\n\t\t\tcount: 1\n\t\t\tpath: src/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#2 \\$newScope of method Closure\\:\\:bindTo\\(\\) expects ''static''\\|class\\-string\\|object\\|null, string given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^Function expect\\(\\) should return Pest\\\\Expectation\\<TValue\\|null\\> but returns Pest\\\\Expectation\\<TValue\\|null\\>\\.$#'\n\t\t\tidentifier: return.type\n\t\t\tcount: 1\n\t\t\tpath: src/Functions.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#1 \\$argv of method PHPUnit\\\\TextUI\\\\Application\\:\\:run\\(\\) expects list\\<string\\>, array\\<int, string\\> given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Kernel.php\n\n\t\t-\n\t\t\tmessage: '#^Call to an undefined method object&TValue of mixed\\:\\:__toString\\(\\)\\.$#'\n\t\t\tidentifier: method.notFound\n\t\t\tcount: 1\n\t\t\tpath: src/Mixins/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^Call to an undefined method object&TValue of mixed\\:\\:toArray\\(\\)\\.$#'\n\t\t\tidentifier: method.notFound\n\t\t\tcount: 4\n\t\t\tpath: src/Mixins/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^Call to an undefined method object&TValue of mixed\\:\\:toSnapshot\\(\\)\\.$#'\n\t\t\tidentifier: method.notFound\n\t\t\tcount: 1\n\t\t\tpath: src/Mixins/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^Call to an undefined method object&TValue of mixed\\:\\:toString\\(\\)\\.$#'\n\t\t\tidentifier: method.notFound\n\t\t\tcount: 1\n\t\t\tpath: src/Mixins/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertTrue\\(\\) with true will always evaluate to true\\.$#'\n\t\t\tidentifier: staticMethod.alreadyNarrowedType\n\t\t\tcount: 2\n\t\t\tpath: src/Mixins/Expectation.php\n\n\t\t-\n\t\t\tmessage: '#^PHPDoc tag @var with type callable\\(\\)\\: bool is not subtype of native type Closure\\|null\\.$#'\n\t\t\tidentifier: varTag.nativeType\n\t\t\tcount: 1\n\t\t\tpath: src/PendingCalls/TestCall.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#1 \\$argv of class Symfony\\\\Component\\\\Console\\\\Input\\\\ArgvInput constructor expects list\\<string\\>\\|null, array\\<int, string\\> given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#13 \\$testRunnerTriggeredDeprecationEvents of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\Event\\\\TestRunner\\\\DeprecationTriggered\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#14 \\$testRunnerTriggeredWarningEvents of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\Event\\\\TestRunner\\\\WarningTriggered\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#15 \\$errors of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\TestRunner\\\\TestResult\\\\Issues\\\\Issue\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#16 \\$deprecations of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\TestRunner\\\\TestResult\\\\Issues\\\\Issue\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#17 \\$notices of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\TestRunner\\\\TestResult\\\\Issues\\\\Issue\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#18 \\$warnings of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\TestRunner\\\\TestResult\\\\Issues\\\\Issue\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#19 \\$phpDeprecations of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\TestRunner\\\\TestResult\\\\Issues\\\\Issue\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#20 \\$phpNotices of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\TestRunner\\\\TestResult\\\\Issues\\\\Issue\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#21 \\$phpWarnings of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\TestRunner\\\\TestResult\\\\Issues\\\\Issue\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#4 \\$testErroredEvents of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\Event\\\\Test\\\\AfterLastTestMethodErrored\\|PHPUnit\\\\Event\\\\Test\\\\BeforeFirstTestMethodErrored\\|PHPUnit\\\\Event\\\\Test\\\\Errored\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#5 \\$testFailedEvents of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\Event\\\\Test\\\\Failed\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#7 \\$testSuiteSkippedEvents of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\Event\\\\TestSuite\\\\Skipped\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#8 \\$testSkippedEvents of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\Event\\\\Test\\\\Skipped\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Parameter \\#9 \\$testMarkedIncompleteEvents of class PHPUnit\\\\TestRunner\\\\TestResult\\\\TestResult constructor expects list\\<PHPUnit\\\\Event\\\\Test\\\\MarkedIncomplete\\>, array given\\.$#'\n\t\t\tidentifier: argument.type\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n\n\t\t-\n\t\t\tmessage: '#^Property Pest\\\\Plugins\\\\Parallel\\\\Paratest\\\\WrapperRunner\\:\\:\\$pending \\(list\\<non\\-empty\\-string\\>\\) does not accept array\\<int, non\\-empty\\-string\\>\\.$#'\n\t\t\tidentifier: assign.propertyType\n\t\t\tcount: 1\n\t\t\tpath: src/Plugins/Parallel/Paratest/WrapperRunner.php\n"
  },
  {
    "path": "phpstan.neon",
    "content": "includes:\n    - phpstan-baseline.neon\n\nparameters:\n    level: 7\n    paths:\n        - src\n\n    reportUnmatchedIgnoredErrors: false\n\n    ignoreErrors:\n        - \"#type mixed is not subtype of native#\"\n"
  },
  {
    "path": "phpunit.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"https://schema.phpunit.de/10.0/phpunit.xsd\"\n         backupGlobals=\"false\"\n         beStrictAboutTestsThatDoNotTestAnything=\"true\"\n         beStrictAboutOutputDuringTests=\"true\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n         failOnRisky=\"true\"\n         failOnWarning=\"false\"\n         processIsolation=\"false\"\n         stopOnError=\"false\"\n         stopOnFailure=\"false\"\n         backupStaticProperties=\"false\"\n>\n  <testsuites>\n    <testsuite name=\"default\">\n      <directory suffix=\".php\">./tests</directory>\n      <directory suffix=\".php\">./tests-external</directory>\n      <exclude>./tests/.snapshots</exclude>\n      <exclude>./tests/.tests</exclude>\n      <exclude>./tests/Fixtures/Inheritance</exclude>\n    </testsuite>\n  </testsuites>\n  <source>\n    <include>\n      <directory suffix=\".php\">./src</directory>\n    </include>\n  </source>\n</phpunit>\n"
  },
  {
    "path": "rector.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nuse Rector\\CodingStyle\\Rector\\ArrowFunction\\ArrowFunctionDelegatingCallToFirstClassCallableRector;\nuse Rector\\Config\\RectorConfig;\nuse Rector\\DeadCode\\Rector\\ClassMethod\\RemoveParentDelegatingConstructorRector;\nuse Rector\\TypeDeclaration\\Rector\\ClassMethod\\NarrowObjectReturnTypeRector;\nuse Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnNeverTypeRector;\n\nreturn RectorConfig::configure()\n    ->withPaths([\n        __DIR__.'/src',\n    ])\n    ->withSkip([\n        __DIR__.'/src/Plugins/Parallel/Paratest/WrapperRunner.php',\n        ReturnNeverTypeRector::class,\n        ArrowFunctionDelegatingCallToFirstClassCallableRector::class,\n        NarrowObjectReturnTypeRector::class,\n        RemoveParentDelegatingConstructorRector::class,\n    ])\n    ->withPreparedSets(\n        deadCode: true,\n        codeQuality: true,\n        typeDeclarations: true,\n        privatization: true,\n        earlyReturn: true,\n    )\n    ->withPhpSets();\n"
  },
  {
    "path": "resources/base-phpunit.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"vendor/phpunit/phpunit/phpunit.xsd\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n>\n    <testsuites>\n        <testsuite name=\"Default\">\n            <directory>tests/</directory>\n        </testsuite>\n    </testsuites>\n    <source>\n        <include>\n            <directory>app</directory>\n            <directory>src</directory>\n        </include>\n    </source>\n    <php>\n        <env name=\"APP_ENV\" value=\"testing\"/>\n        <env name=\"APP_MAINTENANCE_DRIVER\" value=\"file\"/>\n        <env name=\"BCRYPT_ROUNDS\" value=\"4\"/>\n        <env name=\"CACHE_STORE\" value=\"array\"/>\n        <!-- <env name=\"DB_CONNECTION\" value=\"sqlite\"/> -->\n        <!-- <env name=\"DB_DATABASE\" value=\":memory:\"/> -->\n        <env name=\"MAIL_MAILER\" value=\"array\"/>\n        <env name=\"PULSE_ENABLED\" value=\"false\"/>\n        <env name=\"QUEUE_CONNECTION\" value=\"sync\"/>\n        <env name=\"SESSION_DRIVER\" value=\"array\"/>\n        <env name=\"TELESCOPE_ENABLED\" value=\"false\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "resources/views/components/badge.php",
    "content": "<?php\n\n/** @var string $type */\n/** @var string $content */\n[$bgBadgeColor, $bgBadgeText] = match ($type) {\n    'INFO' => ['blue', 'INFO'],\n    'ERROR' => ['red', 'ERROR'],\n};\n\n?>\n\n<div class=\"my-1\">\n    <span class=\"ml-2 px-1 bg-<?php echo $bgBadgeColor ?> font-bold\"><?php echo htmlspecialchars($bgBadgeText) ?></span>\n    <span class=\"ml-1\">\n        <?php echo htmlspecialchars($content) ?>\n    </span>\n</div>\n"
  },
  {
    "path": "resources/views/components/new-line.php",
    "content": "<div></div>\n"
  },
  {
    "path": "resources/views/components/two-column-detail.php",
    "content": "<div class=\"flex mx-2 max-w-150\">\n    <span>\n        <?php echo htmlspecialchars($left) ?>\n    </span>\n    <span class=\"flex-1 content-repeat-[.] text-gray ml-1\"></span>\n    <?php if ($right !== '') { ?>\n        <span class=\"ml-1 text-gray\">\n            <?php echo htmlspecialchars($right) ?>\n        </span>\n    <?php } ?>\n</div>\n\n"
  },
  {
    "path": "resources/views/installers/plugin-browser.php",
    "content": "<div class=\"mx-2 mb-1\">\n    <p>\n        <span>Using the <span class=\"text-yellow font-bold\">visit()</span> function requires the Pest Plugin Browser to be installed.</span>\n\n        <span class=\"ml-1 text-yellow font-bold\">Run:</span>\n    </p>\n\n    <div>\n        <span class=\"text-gray mr-1\">- </span>\n        <span>composer require pestphp/pest-plugin-browser:^4.0 --dev</span>\n    </div>\n\n    <div>\n        <span class=\"text-gray mr-1\">- </span>\n        <span>npm install playwright@latest</span>\n    </div>\n\n    <div>\n        <span class=\"text-gray mr-1\">- </span>\n        <span>npx playwright install</span>\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/usage.php",
    "content": "<div class=\"mx-2\">\n    <span class=\"text-yellow font-bold\">USAGE:</span><span class=\"ml-1\">pest</span><span class=\"ml-1 text-gray\"><?php echo htmlspecialchars('<file>') ?> [options]</span>\n</div>\n\n"
  },
  {
    "path": "resources/views/version.php",
    "content": "<div class=\"my-1 mx-2\">\n    <span>Pest Testing Framework</span><span class=\"ml-1 text-blue font-bold\"><?php echo htmlspecialchars($version) ?></span><span>.</span>\n</div>\n"
  },
  {
    "path": "src/ArchPresets/AbstractPreset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\ArchPresets;\n\nuse Pest\\Arch\\Contracts\\ArchExpectation;\nuse Pest\\Expectation;\n\n/**\n * @internal\n */\nabstract class AbstractPreset // @pest-arch-ignore-line\n{\n    /**\n     * The expectations.\n     *\n     * @var array<int, Expectation<mixed>|ArchExpectation>\n     */\n    protected array $expectations = [];\n\n    /**\n     * Creates a new preset instance.\n     *\n     * @param  array<int, string>  $userNamespaces\n     */\n    public function __construct(\n        private readonly array $userNamespaces,\n    ) {\n        //\n    }\n\n    /**\n     * Executes the arch preset.\n     *\n     * @internal\n     */\n    abstract public function execute(): void;\n\n    /**\n     * Ignores the given \"targets\" or \"dependencies\".\n     *\n     * @param  array<int, string>|string  $targetsOrDependencies\n     */\n    final public function ignoring(array|string $targetsOrDependencies): void\n    {\n        $this->expectations = array_map(\n            fn (ArchExpectation|Expectation $expectation): Expectation|ArchExpectation => $expectation instanceof ArchExpectation ? $expectation->ignoring($targetsOrDependencies) : $expectation,\n            $this->expectations,\n        );\n    }\n\n    /**\n     * Runs the given callback for each namespace.\n     *\n     * @param  callable(Expectation<string|null>): ArchExpectation  ...$callbacks\n     */\n    final public function eachUserNamespace(callable ...$callbacks): void\n    {\n        foreach ($this->userNamespaces as $namespace) {\n            foreach ($callbacks as $callback) {\n                $this->expectations[] = $callback(expect($namespace));\n            }\n        }\n    }\n\n    /**\n     * Flushes the expectations.\n     */\n    final public function flush(): void\n    {\n        $this->expectations = [];\n    }\n}\n"
  },
  {
    "path": "src/ArchPresets/Custom.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\ArchPresets;\n\nuse Closure;\nuse Pest\\Arch\\Contracts\\ArchExpectation;\nuse Pest\\Expectation;\n\n/**\n * @internal\n */\nfinal class Custom extends AbstractPreset\n{\n    /**\n     * Creates a new preset instance.\n     *\n     * @param  array<int, string>  $userNamespaces\n     * @param  Closure(array<int, string>): array<Expectation<mixed>|ArchExpectation>  $execute\n     */\n    public function __construct(\n        private readonly array $userNamespaces,\n        private readonly string $name,\n        private readonly Closure $execute,\n    ) {\n        parent::__construct($userNamespaces);\n    }\n\n    /**\n     * Returns the name of the preset.\n     */\n    public function name(): string\n    {\n        return $this->name;\n    }\n\n    /**\n     * Executes the arch preset.\n     */\n    public function execute(): void\n    {\n        $this->expectations = ($this->execute)($this->userNamespaces);\n    }\n}\n"
  },
  {
    "path": "src/ArchPresets/Laravel.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\ArchPresets;\n\nuse Throwable;\n\n/**\n * @internal\n */\nfinal class Laravel extends AbstractPreset\n{\n    /**\n     * Executes the arch preset.\n     */\n    public function execute(): void\n    {\n        $this->expectations[] = expect('App\\Traits')\n            ->toBeTraits();\n\n        $this->expectations[] = expect('App\\Concerns')\n            ->toBeTraits();\n\n        $this->expectations[] = expect('App')\n            ->not->toBeEnums()\n            ->ignoring('App\\Enums');\n\n        $this->expectations[] = expect('App\\Enums')\n            ->toBeEnums()\n            ->ignoring('App\\Enums\\Concerns');\n\n        $this->expectations[] = expect('App\\Features')\n            ->toBeClasses()\n            ->ignoring('App\\Features\\Concerns');\n\n        $this->expectations[] = expect('App\\Features')\n            ->toHaveMethod('resolve')\n            ->ignoring('App\\Features\\Concerns');\n\n        $this->expectations[] = expect('App\\Exceptions')\n            ->classes()\n            ->toImplement('Throwable')\n            ->ignoring('App\\Exceptions\\Handler');\n\n        $this->expectations[] = expect('App')\n            ->not->toImplement(Throwable::class)\n            ->ignoring('App\\Exceptions');\n\n        $this->expectations[] = expect('App\\Http\\Middleware')\n            ->classes()\n            ->toHaveMethod('handle');\n\n        $this->expectations[] = expect('App\\Models')\n            ->classes()\n            ->toExtend('Illuminate\\Database\\Eloquent\\Model')\n            ->ignoring('App\\Models\\Scopes');\n\n        $this->expectations[] = expect('App\\Models')\n            ->classes()\n            ->not->toHaveSuffix('Model');\n\n        $this->expectations[] = expect('App')\n            ->not->toExtend('Illuminate\\Database\\Eloquent\\Model')\n            ->ignoring('App\\Models');\n\n        $this->expectations[] = expect('App\\Http\\Requests')\n            ->classes()\n            ->toHaveSuffix('Request');\n\n        $this->expectations[] = expect('App\\Http\\Requests')\n            ->toExtend('Illuminate\\Foundation\\Http\\FormRequest');\n\n        $this->expectations[] = expect('App\\Http\\Requests')\n            ->toHaveMethod('rules');\n\n        $this->expectations[] = expect('App')\n            ->not->toExtend('Illuminate\\Foundation\\Http\\FormRequest')\n            ->ignoring('App\\Http\\Requests');\n\n        $this->expectations[] = expect('App\\Console\\Commands')\n            ->classes()\n            ->toHaveSuffix('Command');\n\n        $this->expectations[] = expect('App\\Console\\Commands')\n            ->classes()\n            ->toExtend('Illuminate\\Console\\Command');\n\n        $this->expectations[] = expect('App\\Console\\Commands')\n            ->classes()\n            ->toHaveMethod('handle');\n\n        $this->expectations[] = expect('App')\n            ->not->toExtend('Illuminate\\Console\\Command')\n            ->ignoring('App\\Console\\Commands');\n\n        $this->expectations[] = expect('App\\Mail')\n            ->classes()\n            ->toExtend('Illuminate\\Mail\\Mailable');\n\n        $this->expectations[] = expect('App\\Mail')\n            ->classes()\n            ->toImplement('Illuminate\\Contracts\\Queue\\ShouldQueue');\n\n        $this->expectations[] = expect('App')\n            ->not->toExtend('Illuminate\\Mail\\Mailable')\n            ->ignoring('App\\Mail');\n\n        $this->expectations[] = expect('App\\Jobs')\n            ->classes()\n            ->toImplement('Illuminate\\Contracts\\Queue\\ShouldQueue');\n\n        $this->expectations[] = expect('App\\Jobs')\n            ->classes()\n            ->toHaveMethod('handle');\n\n        $this->expectations[] = expect('App\\Listeners')\n            ->toHaveMethod('handle');\n\n        $this->expectations[] = expect('App\\Notifications')\n            ->toExtend('Illuminate\\Notifications\\Notification');\n\n        $this->expectations[] = expect('App')\n            ->not->toExtend('Illuminate\\Notifications\\Notification')\n            ->ignoring('App\\Notifications');\n\n        $this->expectations[] = expect('App\\Providers')\n            ->toHaveSuffix('ServiceProvider');\n\n        $this->expectations[] = expect('App\\Providers')\n            ->toExtend('Illuminate\\Support\\ServiceProvider');\n\n        $this->expectations[] = expect('App\\Providers')\n            ->not->toBeUsed();\n\n        $this->expectations[] = expect('App')\n            ->not->toExtend('Illuminate\\Support\\ServiceProvider')\n            ->ignoring('App\\Providers');\n\n        $this->expectations[] = expect('App')\n            ->not->toHaveSuffix('ServiceProvider')\n            ->ignoring('App\\Providers');\n\n        $this->expectations[] = expect('App')\n            ->not->toHaveSuffix('Controller')\n            ->ignoring('App\\Http\\Controllers');\n\n        $this->expectations[] = expect('App\\Http\\Controllers')\n            ->classes()\n            ->toHaveSuffix('Controller');\n\n        $this->expectations[] = expect('App\\Http')\n            ->toOnlyBeUsedIn(['App\\Http', 'App\\Providers']);\n\n        $this->expectations[] = expect('App\\Http\\Controllers')\n            ->not->toHavePublicMethodsBesides(['__construct', '__invoke', 'index', 'show', 'create', 'store', 'edit', 'update', 'destroy', 'middleware']);\n\n        $this->expectations[] = expect([\n            'dd',\n            'ddd',\n            'dump',\n            'env',\n            'exit',\n            'ray',\n        ])->not->toBeUsed();\n\n        $this->expectations[] = expect('App\\Policies')\n            ->classes()\n            ->toHaveSuffix('Policy');\n\n        $this->expectations[] = expect('App\\Attributes')\n            ->classes()\n            ->toImplement('Illuminate\\Contracts\\Container\\ContextualAttribute')\n            ->toHaveAttribute('Attribute')\n            ->toHaveMethod('resolve');\n    }\n}\n"
  },
  {
    "path": "src/ArchPresets/Php.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\ArchPresets;\n\n/**\n * @internal\n */\nfinal class Php extends AbstractPreset\n{\n    /**\n     * Executes the arch preset.\n     */\n    public function execute(): void\n    {\n        $this->expectations[] = expect([\n            'debug_zval_dump',\n            'debug_backtrace',\n            'debug_print_backtrace',\n            'dump',\n            'ray',\n            'ds',\n            'die',\n            'goto',\n            'global',\n            'var_dump',\n            'phpinfo',\n            'echo',\n            'ereg',\n            'eregi',\n            'mysql_connect',\n            'mysql_pconnect',\n            'mysql_query',\n            'mysql_select_db',\n            'mysql_fetch_array',\n            'mysql_fetch_assoc',\n            'mysql_fetch_object',\n            'mysql_fetch_row',\n            'mysql_num_rows',\n            'mysql_affected_rows',\n            'mysql_free_result',\n            'mysql_insert_id',\n            'mysql_error',\n            'mysql_real_escape_string',\n            'print',\n            'print_r',\n            'var_export',\n            'xdebug_break',\n            'xdebug_call_class',\n            'xdebug_call_file',\n            'xdebug_call_int',\n            'xdebug_call_line',\n            'xdebug_code_coverage_started',\n            'xdebug_connect_to_client',\n            'xdebug_debug_zval',\n            'xdebug_debug_zval_stdout',\n            'xdebug_dump_superglobals',\n            'xdebug_get_code_coverage',\n            'xdebug_get_collected_errors',\n            'xdebug_get_function_count',\n            'xdebug_get_function_stack',\n            'xdebug_get_gc_run_count',\n            'xdebug_get_gc_total_collected_roots',\n            'xdebug_get_gcstats_filename',\n            'xdebug_get_headers',\n            'xdebug_get_monitored_functions',\n            'xdebug_get_profiler_filename',\n            'xdebug_get_stack_depth',\n            'xdebug_get_tracefile_name',\n            'xdebug_info',\n            'xdebug_is_debugger_active',\n            'xdebug_memory_usage',\n            'xdebug_notify',\n            'xdebug_peak_memory_usage',\n            'xdebug_print_function_stack',\n            'xdebug_set_filter',\n            'xdebug_start_code_coverage',\n            'xdebug_start_error_collection',\n            'xdebug_start_function_monitor',\n            'xdebug_start_gcstats',\n            'xdebug_start_trace',\n            'xdebug_stop_code_coverage',\n            'xdebug_stop_error_collection',\n            'xdebug_stop_function_monitor',\n            'xdebug_stop_gcstats',\n            'xdebug_stop_trace',\n            'xdebug_time_index',\n            'xdebug_var_dump',\n            'trap',\n        ])->not->toBeUsed();\n    }\n}\n"
  },
  {
    "path": "src/ArchPresets/Relaxed.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\ArchPresets;\n\nuse Pest\\Arch\\Contracts\\ArchExpectation;\nuse Pest\\Expectation;\n\n/**\n * @internal\n */\nfinal class Relaxed extends AbstractPreset\n{\n    /**\n     * Executes the arch preset.\n     */\n    public function execute(): void\n    {\n        $this->eachUserNamespace(\n            fn (Expectation $namespace): ArchExpectation => $namespace->not->toUseStrictTypes(),\n            fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toBeFinal(),\n            fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toHavePrivateMethods(),\n        );\n    }\n}\n"
  },
  {
    "path": "src/ArchPresets/Security.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\ArchPresets;\n\n/**\n * @internal\n */\nfinal class Security extends AbstractPreset\n{\n    /**\n     * Executes the arch preset.\n     */\n    public function execute(): void\n    {\n        $this->expectations[] = expect([\n            'md5',\n            'sha1',\n            'uniqid',\n            'rand',\n            'mt_rand',\n            'tempnam',\n            'str_shuffle',\n            'shuffle',\n            'array_rand',\n            'eval',\n            'exec',\n            'shell_exec',\n            'system',\n            'passthru',\n            'create_function',\n            'unserialize',\n            'extract',\n            'mb_parse_str',\n            'dl',\n            'assert',\n        ])->not->toBeUsed();\n    }\n}\n"
  },
  {
    "path": "src/ArchPresets/Strict.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\ArchPresets;\n\nuse Pest\\Arch\\Contracts\\ArchExpectation;\nuse Pest\\Expectation;\n\n/**\n * @internal\n */\nfinal class Strict extends AbstractPreset\n{\n    /**\n     * Executes the arch preset.\n     */\n    public function execute(): void\n    {\n        $this->eachUserNamespace(\n            fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toHaveProtectedMethods(),\n            fn (Expectation $namespace): ArchExpectation => $namespace->classes()->not->toBeAbstract(),\n            fn (Expectation $namespace): ArchExpectation => $namespace->toUseStrictTypes(),\n            fn (Expectation $namespace): ArchExpectation => $namespace->toUseStrictEquality(),\n            fn (Expectation $namespace): ArchExpectation => $namespace->classes()->toBeFinal(),\n        );\n\n        $this->expectations[] = expect([\n            'sleep',\n            'usleep',\n        ])->not->toBeUsed();\n    }\n}\n"
  },
  {
    "path": "src/Bootstrappers/BootExcludeList.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Bootstrappers;\n\nuse Pest\\Contracts\\Bootstrapper;\nuse PHPUnit\\Util\\ExcludeList;\n\n/**\n * @internal\n */\nfinal class BootExcludeList implements Bootstrapper\n{\n    /**\n     * The directories to exclude.\n     *\n     * @var array<int, non-empty-string>\n     */\n    private const array EXCLUDE_LIST = [\n        'bin',\n        'overrides',\n        'resources',\n        'src',\n        'stubs',\n    ];\n\n    /**\n     * Boots the \"exclude list\" for PHPUnit to ignore Pest files.\n     */\n    public function boot(): void\n    {\n        $baseDirectory = dirname(__DIR__, 2);\n\n        foreach (self::EXCLUDE_LIST as $directory) {\n            ExcludeList::addDirectory($baseDirectory.DIRECTORY_SEPARATOR.$directory);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Bootstrappers/BootFiles.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Bootstrappers;\n\nuse Pest\\Contracts\\Bootstrapper;\nuse Pest\\Exceptions\\FatalException;\nuse Pest\\Support\\DatasetInfo;\nuse Pest\\Support\\Str;\nuse Pest\\TestSuite;\nuse RecursiveDirectoryIterator;\nuse RecursiveIteratorIterator;\nuse SebastianBergmann\\FileIterator\\Facade as PhpUnitFileIterator;\n\nuse function Pest\\testDirectory;\n\n/**\n * @internal\n */\nfinal class BootFiles implements Bootstrapper\n{\n    /**\n     * The structure of the tests directory.\n     *\n     * @var array<int, string>\n     */\n    private const array STRUCTURE = [\n        'Expectations',\n        'Expectations.php',\n        'Helpers',\n        'Helpers.php',\n        'Pest.php',\n    ];\n\n    /**\n     * Boots the structure of the tests directory.\n     */\n    public function boot(): void\n    {\n        $rootPath = TestSuite::getInstance()->rootPath;\n        $testsPath = $rootPath.DIRECTORY_SEPARATOR.testDirectory();\n\n        if (! is_dir($testsPath)) {\n            throw new FatalException(sprintf('The test directory [%s] does not exist.', $testsPath));\n        }\n\n        foreach (self::STRUCTURE as $filename) {\n            $filename = sprintf('%s%s%s', $testsPath, DIRECTORY_SEPARATOR, $filename);\n\n            if (! file_exists($filename)) {\n                continue;\n            }\n\n            if (is_dir($filename)) {\n                $directory = new RecursiveDirectoryIterator($filename);\n                $iterator = new RecursiveIteratorIterator($directory);\n                /** @var \\DirectoryIterator $file */\n                foreach ($iterator as $file) {\n                    $this->load($file->__toString());\n                }\n            } else {\n                $this->load($filename);\n            }\n        }\n\n        $this->bootDatasets($testsPath);\n    }\n\n    /**\n     * Loads, if possible, the given file.\n     */\n    private function load(string $filename): void\n    {\n        if (! Str::endsWith($filename, '.php')) {\n            return;\n        }\n        if (! file_exists($filename)) {\n            return;\n        }\n        include_once $filename;\n    }\n\n    private function bootDatasets(string $testsPath): void\n    {\n        assert($testsPath !== '');\n\n        $files = (new PhpUnitFileIterator)->getFilesAsArray($testsPath, '.php');\n\n        foreach ($files as $file) {\n            if (DatasetInfo::isADatasetsFile($file) || DatasetInfo::isInsideADatasetsDirectory($file)) {\n                $this->load($file);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Bootstrappers/BootKernelDump.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Bootstrappers;\n\nuse Pest\\Contracts\\Bootstrapper;\nuse Pest\\KernelDump;\nuse Pest\\Support\\Container;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal readonly class BootKernelDump implements Bootstrapper\n{\n    /**\n     * Creates a new Boot Kernel Dump instance.\n     */\n    public function __construct(\n        private OutputInterface $output,\n    ) {\n        // ...\n    }\n\n    /**\n     * Boots the kernel dump.\n     */\n    public function boot(): void\n    {\n        Container::getInstance()->add(KernelDump::class, $kernelDump = new KernelDump(\n            $this->output,\n        ));\n\n        $kernelDump->enable();\n    }\n}\n"
  },
  {
    "path": "src/Bootstrappers/BootOverrides.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Bootstrappers;\n\nuse Pest\\Contracts\\Bootstrapper;\nuse Pest\\Exceptions\\ShouldNotHappen;\n\n/**\n * @internal\n */\nfinal class BootOverrides implements Bootstrapper\n{\n    /**\n     * The list of files to be overridden.\n     *\n     * @var array<int, string>\n     */\n    public const array FILES = [\n        'Runner/Filter/NameFilterIterator.php',\n        'Runner/ResultCache/DefaultResultCache.php',\n        'Runner/TestSuiteLoader.php',\n        'TextUI/Command/Commands/WarmCodeCoverageCacheCommand.php',\n        'TextUI/Output/Default/ProgressPrinter/Subscriber/TestSkippedSubscriber.php',\n        'TextUI/TestSuiteFilterProcessor.php',\n        'Event/Value/ThrowableBuilder.php',\n        'Logging/JUnit/JunitXmlLogger.php',\n    ];\n\n    /**\n     * Boots the list of files to be overridden.\n     */\n    public function boot(): void\n    {\n        foreach (self::FILES as $file) {\n            $file = __DIR__.\"/../../overrides/$file\";\n\n            if (! file_exists($file)) {\n                throw ShouldNotHappen::fromMessage(sprintf('File [%s] does not exist.', $file));\n            }\n\n            require_once $file;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Bootstrappers/BootSubscribers.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Bootstrappers;\n\nuse Pest\\Contracts\\Bootstrapper;\nuse Pest\\Subscribers;\nuse Pest\\Support\\Container;\nuse PHPUnit\\Event;\nuse PHPUnit\\Event\\Subscriber;\n\n/**\n * @internal\n */\nfinal readonly class BootSubscribers implements Bootstrapper\n{\n    /**\n     * The list of Subscribers.\n     *\n     * @var array<int, class-string<Subscriber>>\n     */\n    private const array SUBSCRIBERS = [\n        Subscribers\\EnsureConfigurationIsAvailable::class,\n        Subscribers\\EnsureIgnorableTestCasesAreIgnored::class,\n        Subscribers\\EnsureKernelDumpIsFlushed::class,\n        Subscribers\\EnsureTeamCityEnabled::class,\n    ];\n\n    /**\n     * Creates a new instance of the Boot Subscribers.\n     */\n    public function __construct(\n        private Container $container,\n    ) {}\n\n    /**\n     * Boots the list of Subscribers.\n     */\n    public function boot(): void\n    {\n        foreach (self::SUBSCRIBERS as $subscriber) {\n            $instance = $this->container->get($subscriber);\n\n            assert($instance instanceof Subscriber);\n\n            Event\\Facade::instance()->registerSubscriber($instance);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Bootstrappers/BootView.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Bootstrappers;\n\nuse Pest\\Contracts\\Bootstrapper;\nuse Pest\\Support\\View;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal readonly class BootView implements Bootstrapper\n{\n    /**\n     * Creates a new instance of the Boot View.\n     */\n    public function __construct(\n        private OutputInterface $output\n    ) {\n        // ..\n    }\n\n    /**\n     * Boots the view renderer.\n     */\n    public function boot(): void\n    {\n        View::renderUsing($this->output);\n    }\n}\n"
  },
  {
    "path": "src/Collision/Events.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Collision;\n\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\TestResult;\nuse Pest\\Configuration\\Project;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\nuse function Termwind\\render;\nuse function Termwind\\renderUsing;\n\n/**\n * @internal\n */\nfinal class Events\n{\n    /**\n     * Sets the output.\n     */\n    private static ?OutputInterface $output = null;\n\n    /**\n     * Sets the output.\n     */\n    public static function setOutput(OutputInterface $output): void\n    {\n        self::$output = $output;\n    }\n\n    /**\n     * Fires before the test method description is printed.\n     */\n    public static function beforeTestMethodDescription(TestResult $result, string $description): string\n    {\n        if (($context = $result->context) === []) {\n            return $description;\n        }\n\n        renderUsing(self::$output);\n\n        [\n            'assignees' => $assignees,\n            'issues' => $issues,\n            'prs' => $prs,\n        ] = $context;\n\n        if (($link = Project::getInstance()->issues) !== '') {\n            $issuesDescription = array_map(fn (int $issue): string => sprintf('<a href=\"%s\">#%s</a>', sprintf($link, $issue), $issue), $issues);\n        }\n\n        if (($link = Project::getInstance()->prs) !== '') {\n            $prsDescription = array_map(fn (int $pr): string => sprintf('<a href=\"%s\">#%s</a>', sprintf($link, $pr), $pr), $prs);\n        }\n\n        if (($link = Project::getInstance()->assignees) !== '' && count($assignees) > 0) {\n            $assigneesDescription = array_map(fn (string $assignee): string => sprintf(\n                '<a href=\"%s\">@%s</a>',\n                sprintf($link, $assignee),\n                $assignee,\n            ), $assignees);\n        }\n\n        if (count($assignees) > 0 || count($issues) > 0 || count($prs) > 0) {\n            $description .= ' '.implode(', ', array_merge(\n                $issuesDescription ?? [],\n                $prsDescription ?? [],\n                isset($assigneesDescription) ? ['['.implode(', ', $assigneesDescription).']'] : [],\n            ));\n        }\n\n        return $description;\n    }\n\n    /**\n     * Fires after the test method description is printed.\n     */\n    public static function afterTestMethodDescription(TestResult $result): void\n    {\n        if (($context = $result->context) === []) {\n            return;\n        }\n\n        renderUsing(self::$output);\n\n        [\n            'notes' => $notes,\n        ] = $context;\n\n        foreach ($notes as $note) {\n            render(sprintf(<<<'HTML'\n                <div class=\"ml-2\">\n                    <span class=\"text-gray\"> // %s</span>\n                </div>\n                HTML, $note,\n            ));\n        }\n    }\n}\n"
  },
  {
    "path": "src/Concerns/Expectable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Concerns;\n\nuse Pest\\Expectation;\n\n/**\n * @internal\n */\ntrait Expectable\n{\n    /**\n     * @template TValue\n     *\n     * Creates a new Expectation.\n     *\n     * @param  TValue  $value\n     * @return Expectation<TValue>\n     */\n    public function expect(mixed $value): Expectation\n    {\n        return new Expectation($value);\n    }\n}\n"
  },
  {
    "path": "src/Concerns/Extendable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Concerns;\n\nuse Closure;\n\n/**\n * @internal\n *\n * @template T of object\n */\ntrait Extendable\n{\n    /**\n     * The list of extends.\n     *\n     * @var array<string, Closure>\n     */\n    private static array $extends = [];\n\n    /**\n     * Register a new extend.\n     *\n     * @param-closure-this T $extend\n     */\n    public function extend(string $name, Closure $extend): void\n    {\n        static::$extends[$name] = $extend;\n    }\n\n    /**\n     * Checks if given extend name is registered.\n     */\n    public static function hasExtend(string $name): bool\n    {\n        return array_key_exists($name, static::$extends);\n    }\n}\n"
  },
  {
    "path": "src/Concerns/Logging/WritesToConsole.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Concerns\\Logging;\n\n/**\n * @internal\n */\ntrait WritesToConsole\n{\n    /**\n     * Writes the given success message to the console.\n     */\n    private function writeSuccess(string $message): void\n    {\n        $this->writePestTestOutput($message, 'fg-green, bold', '✓');\n    }\n\n    /**\n     * Writes the given error message to the console.\n     */\n    private function writeError(string $message): void\n    {\n        $this->writePestTestOutput($message, 'fg-red, bold', '⨯');\n    }\n\n    /**\n     * Writes the given warning message to the console.\n     */\n    private function writeWarning(string $message): void\n    {\n        $this->writePestTestOutput($message, 'fg-yellow, bold', '-');\n    }\n\n    /**\n     * Writes the give message to the console.\n     */\n    private function writePestTestOutput(string $message, string $color, string $symbol): void\n    {\n        $this->writeWithColor($color, \"$symbol \", false);\n        $this->write($message);\n        $this->writeNewLine();\n    }\n}\n"
  },
  {
    "path": "src/Concerns/Pipeable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Concerns;\n\nuse Closure;\n\n/**\n * @internal\n */\ntrait Pipeable\n{\n    /**\n     * The list of pipes.\n     *\n     * @var array<string, array<Closure(Closure, mixed ...$arguments): void>>\n     */\n    private static array $pipes = [];\n\n    /**\n     * The list of interceptors.\n     *\n     * @var array<string, array<Closure(Closure, mixed ...$arguments): void>>\n     */\n    private static array $interceptors = [];\n\n    /**\n     * Register a pipe to be applied before an expectation is checked.\n     */\n    public function pipe(string $name, Closure $pipe): void\n    {\n        self::$pipes[$name][] = $pipe;\n    }\n\n    /**\n     * Register an interceptor that should replace an existing expectation.\n     *\n     * @param  string|Closure(mixed $value, mixed ...$arguments):bool  $filter\n     */\n    public function intercept(string $name, string|Closure $filter, Closure $handler): void\n    {\n        if (is_string($filter)) {\n            $filter = fn ($value): bool => $value instanceof $filter;\n        }\n\n        self::$interceptors[$name][] = $handler;\n\n        $this->pipe($name, function ($next, ...$arguments) use ($handler, $filter): void {\n            /* @phpstan-ignore-next-line */\n            if ($filter($this->value, ...$arguments)) {\n                // @phpstan-ignore-next-line\n                $handler->bindTo($this, $this::class)(...$arguments);\n\n                return;\n            }\n\n            $next();\n        });\n    }\n\n    /**\n     * Get the list of pipes by the given name.\n     *\n     * @return array<int, Closure>\n     */\n    private function pipes(string $name, object $context, string $scope): array\n    {\n        return array_map(fn (Closure $pipe): Closure => $pipe->bindTo($context, $scope), self::$pipes[$name] ?? []);\n    }\n}\n"
  },
  {
    "path": "src/Concerns/Retrievable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Concerns;\n\n/**\n * @internal\n */\ntrait Retrievable\n{\n    /**\n     * @template TRetrievableValue\n     *\n     * Safely retrieve the value at the given key from an object or array.\n     * @template TRetrievableValue\n     *\n     * @param  array<string, TRetrievableValue>|object  $value\n     * @param  TRetrievableValue|null  $default\n     * @return TRetrievableValue|null\n     */\n    private function retrieve(string $key, mixed $value, mixed $default = null): mixed\n    {\n        if (is_array($value)) {\n            return $value[$key] ?? $default;\n        }\n\n        // @phpstan-ignore-next-line\n        return $value->$key ?? $default;\n    }\n}\n"
  },
  {
    "path": "src/Concerns/Testable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Concerns;\n\nuse Closure;\nuse Pest\\Exceptions\\DatasetArgumentsMismatch;\nuse Pest\\Panic;\nuse Pest\\Preset;\nuse Pest\\Support\\ChainableClosure;\nuse Pest\\Support\\ExceptionTrace;\nuse Pest\\Support\\Reflection;\nuse Pest\\Support\\Shell;\nuse Pest\\TestSuite;\nuse PHPUnit\\Framework\\Attributes\\PostCondition;\nuse PHPUnit\\Framework\\TestCase;\nuse ReflectionException;\nuse ReflectionFunction;\nuse ReflectionParameter;\nuse Throwable;\n\n/**\n * @internal\n *\n * @mixin TestCase\n */\ntrait Testable\n{\n    /**\n     * The test's description.\n     */\n    private string $__description;\n\n    /**\n     * The test's latest description.\n     */\n    private static string $__latestDescription;\n\n    /**\n     * The test's assignees.\n     */\n    private static array $__latestAssignees = [];\n\n    /**\n     * The test's notes.\n     */\n    private static array $__latestNotes = [];\n\n    /**\n     * The test's issues.\n     *\n     * @var array<int, int>\n     */\n    private static array $__latestIssues = [];\n\n    /**\n     * The test's PRs.\n     *\n     * @var array<int, int>\n     */\n    private static array $__latestPrs = [];\n\n    /**\n     * The test's describing, if any.\n     *\n     * @var array<int, string>\n     */\n    public array $__describing = [];\n\n    /**\n     * Whether the test has ran or not.\n     */\n    public bool $__ran = false;\n\n    /**\n     * The test's test closure.\n     */\n    private Closure $__test;\n\n    /**\n     * The test's before each closure.\n     */\n    private ?Closure $__beforeEach = null;\n\n    /**\n     * The test's after each closure.\n     */\n    private ?Closure $__afterEach = null;\n\n    /**\n     * The test's before all closure.\n     */\n    private static ?Closure $__beforeAll = null;\n\n    /**\n     * The test's after all closure.\n     */\n    private static ?Closure $__afterAll = null;\n\n    /**\n     * The list of snapshot changes, if any.\n     */\n    private array $__snapshotChanges = [];\n\n    /**\n     * Resets the test case static properties.\n     */\n    public static function flush(): void\n    {\n        self::$__beforeAll = null;\n        self::$__afterAll = null;\n    }\n\n    /**\n     * Adds a new \"note\" to the Test Case.\n     */\n    public function note(array|string $note): self\n    {\n        $note = is_array($note) ? $note : [$note];\n\n        self::$__latestNotes = array_merge(self::$__latestNotes, $note);\n\n        return $this;\n    }\n\n    /**\n     * Adds a new \"setUpBeforeClass\" to the Test Case.\n     */\n    public function __addBeforeAll(?Closure $hook): void\n    {\n        if (! $hook instanceof Closure) {\n            return;\n        }\n\n        self::$__beforeAll = (self::$__beforeAll instanceof Closure)\n            ? ChainableClosure::boundStatically(self::$__beforeAll, $hook)\n            : $hook;\n    }\n\n    /**\n     * Adds a new \"tearDownAfterClass\" to the Test Case.\n     */\n    public function __addAfterAll(?Closure $hook): void\n    {\n        if (! $hook instanceof Closure) {\n            return;\n        }\n\n        self::$__afterAll = (self::$__afterAll instanceof Closure)\n            ? ChainableClosure::boundStatically(self::$__afterAll, $hook)\n            : $hook;\n    }\n\n    /**\n     * Adds a new \"setUp\" to the Test Case.\n     */\n    public function __addBeforeEach(?Closure $hook): void\n    {\n        $this->__addHook('__beforeEach', $hook);\n    }\n\n    /**\n     * Adds a new \"tearDown\" to the Test Case.\n     */\n    public function __addAfterEach(?Closure $hook): void\n    {\n        $this->__addHook('__afterEach', $hook);\n    }\n\n    /**\n     * Adds a new \"hook\" to the Test Case.\n     */\n    private function __addHook(string $property, ?Closure $hook): void\n    {\n        if (! $hook instanceof Closure) {\n            return;\n        }\n\n        $this->{$property} = ($this->{$property} instanceof Closure)\n            ? ChainableClosure::bound($this->{$property}, $hook)\n            : $hook;\n    }\n\n    /**\n     * This method is called before the first test of this Test Case is run.\n     */\n    public static function setUpBeforeClass(): void\n    {\n        parent::setUpBeforeClass();\n\n        $beforeAll = TestSuite::getInstance()->beforeAll->get(self::$__filename);\n\n        if (self::$__beforeAll instanceof Closure) {\n            $beforeAll = ChainableClosure::boundStatically(self::$__beforeAll, $beforeAll);\n        }\n\n        try {\n            call_user_func(Closure::bind($beforeAll, null, self::class));\n        } catch (Throwable $e) {\n            Panic::with($e);\n        }\n    }\n\n    /**\n     * This method is called after the last test of this Test Case is run.\n     */\n    public static function tearDownAfterClass(): void\n    {\n        $afterAll = TestSuite::getInstance()->afterAll->get(self::$__filename);\n\n        if (self::$__afterAll instanceof Closure) {\n            $afterAll = ChainableClosure::boundStatically(self::$__afterAll, $afterAll);\n        }\n\n        call_user_func(Closure::bind($afterAll, null, self::class));\n\n        parent::tearDownAfterClass();\n    }\n\n    /**\n     * Gets executed before the Test Case.\n     */\n    protected function setUp(...$arguments): void\n    {\n        TestSuite::getInstance()->test = $this;\n\n        $method = TestSuite::getInstance()->tests->get(self::$__filename)->getMethod($this->name());\n\n        $description = $method->description;\n        if ($this->dataName()) {\n            $description = str_contains((string) $description, ':dataset')\n                ? str_replace(':dataset', str_replace('dataset ', '', $this->dataName()), (string) $description)\n                : $description.' with '.$this->dataName();\n        }\n\n        $description = htmlspecialchars(html_entity_decode((string) $description), ENT_NOQUOTES);\n\n        if ($method->repetitions > 1) {\n            $matches = [];\n            preg_match('/\\((.*?)\\)/', $description, $matches);\n\n            if (count($matches) > 1) {\n                if (str_contains($description, 'with '.$matches[0].' /')) {\n                    $description = str_replace('with '.$matches[0].' /', '', $description);\n                } else {\n                    $description = str_replace('with '.$matches[0], '', $description);\n                }\n            }\n\n            $description .= ' @ repetition '.($matches[1].' of '.$method->repetitions);\n        }\n\n        $this->__description = self::$__latestDescription = $description;\n        self::$__latestAssignees = $method->assignees;\n        self::$__latestNotes = $method->notes;\n        self::$__latestIssues = $method->issues;\n        self::$__latestPrs = $method->prs;\n\n        parent::setUp();\n\n        $beforeEach = TestSuite::getInstance()->beforeEach->get(self::$__filename)[1];\n\n        if ($this->__beforeEach instanceof Closure) {\n            $beforeEach = ChainableClosure::bound($this->__beforeEach, $beforeEach);\n        }\n\n        $this->__callClosure($beforeEach, $arguments);\n    }\n\n    /**\n     * Initialize test case properties from TestSuite.\n     */\n    public function __initializeTestCase(): void\n    {\n        // Return if the test case has already been initialized\n        if (isset($this->__test)) {\n            return;\n        }\n\n        $name = $this->name();\n        $test = TestSuite::getInstance()->tests->get(self::$__filename);\n\n        if ($test->hasMethod($name)) {\n            $method = $test->getMethod($name);\n            $this->__description = self::$__latestDescription = $method->description;\n            self::$__latestAssignees = $method->assignees;\n            self::$__latestNotes = $method->notes;\n            self::$__latestIssues = $method->issues;\n            self::$__latestPrs = $method->prs;\n            $this->__describing = $method->describing;\n            $this->__test = $method->getClosure();\n\n            $method->setUp($this);\n        }\n    }\n\n    /**\n     * Gets executed after the Test Case.\n     */\n    protected function tearDown(...$arguments): void\n    {\n        $afterEach = TestSuite::getInstance()->afterEach->get(self::$__filename);\n\n        if ($this->__afterEach instanceof Closure) {\n            $afterEach = ChainableClosure::bound($this->__afterEach, $afterEach);\n        }\n\n        try {\n            $this->__callClosure($afterEach, func_get_args());\n        } finally {\n            parent::tearDown();\n\n            TestSuite::getInstance()->test = null;\n\n            $method = TestSuite::getInstance()->tests->get(self::$__filename)->getMethod($this->name());\n            $method->tearDown($this);\n        }\n    }\n\n    /**\n     * Executes the Test Case current test.\n     *\n     * @throws Throwable\n     */\n    private function __runTest(Closure $closure, ...$args): mixed\n    {\n        $arguments = $this->__resolveTestArguments($args);\n        $this->__ensureDatasetArgumentNameAndNumberMatches($arguments);\n\n        return $this->__callClosure($closure, $arguments);\n    }\n\n    /**\n     * Resolve the passed arguments. Any Closures will be bound to the testcase and resolved.\n     *\n     * @throws Throwable\n     */\n    private function __resolveTestArguments(array $arguments): array\n    {\n        $method = TestSuite::getInstance()->tests->get(self::$__filename)->getMethod($this->name());\n\n        if ($method->repetitions > 1) {\n            // If the test is repeated, the first argument is the iteration number\n            // we need to move it to the end of the arguments list\n            // so that the datasets are the first n arguments\n            // and the iteration number is the last argument\n            $firstArgument = array_shift($arguments);\n            $arguments[] = $firstArgument;\n        }\n\n        $underlyingTest = Reflection::getFunctionVariable($this->__test, 'closure');\n        $testParameterTypes = array_values(Reflection::getFunctionArguments($underlyingTest));\n\n        if (count($arguments) !== 1) {\n            foreach ($arguments as $argumentIndex => $argumentValue) {\n                if (! $argumentValue instanceof Closure) {\n                    continue;\n                }\n\n                if (in_array($testParameterTypes[$argumentIndex], [Closure::class, 'callable', 'mixed'])) {\n                    continue;\n                }\n\n                $arguments[$argumentIndex] = $this->__callClosure($argumentValue, []);\n            }\n\n            return $arguments;\n        }\n\n        if (! isset($arguments[0]) || ! $arguments[0] instanceof Closure) {\n            return $arguments;\n        }\n\n        if (isset($testParameterTypes[0]) && in_array($testParameterTypes[0], [Closure::class, 'callable'])) {\n            return $arguments;\n        }\n\n        $boundDatasetResult = $this->__callClosure($arguments[0], []);\n        if (count($testParameterTypes) === 1) {\n            return [$boundDatasetResult];\n        }\n        if (! is_array($boundDatasetResult)) {\n            return [$boundDatasetResult];\n        }\n\n        return array_values($boundDatasetResult);\n    }\n\n    /**\n     * Ensures dataset items count matches underlying test case required parameters\n     *\n     * @throws ReflectionException\n     * @throws DatasetArgumentsMismatch\n     */\n    private function __ensureDatasetArgumentNameAndNumberMatches(array $arguments): void\n    {\n        if ($arguments === []) {\n            return;\n        }\n\n        $underlyingTest = Reflection::getFunctionVariable($this->__test, 'closure');\n        $testReflection = new ReflectionFunction($underlyingTest);\n        $requiredParametersCount = $testReflection->getNumberOfRequiredParameters();\n        $suppliedParametersCount = count($arguments);\n\n        $datasetParameterNames = array_keys($arguments);\n        $testParameterNames = array_map(\n            fn (ReflectionParameter $reflectionParameter): string => $reflectionParameter->getName(),\n            array_filter($testReflection->getParameters(), fn (ReflectionParameter $reflectionParameter): bool => ! $reflectionParameter->isOptional()),\n        );\n\n        if (array_diff($testParameterNames, $datasetParameterNames) === []) {\n            return;\n        }\n\n        if (isset($testParameterNames[0]) && $suppliedParametersCount >= $requiredParametersCount) {\n            return;\n        }\n\n        throw new DatasetArgumentsMismatch($requiredParametersCount, $suppliedParametersCount);\n    }\n\n    /**\n     * @throws Throwable\n     */\n    private function __callClosure(Closure $closure, array $arguments): mixed\n    {\n        return ExceptionTrace::ensure(fn (): mixed => call_user_func_array(Closure::bind($closure, $this, $this::class), $arguments));\n    }\n\n    /**\n     * Uses the given preset on the test.\n     */\n    public function preset(): Preset\n    {\n        return new Preset;\n    }\n\n    #[PostCondition]\n    protected function __MarkTestIncompleteIfSnapshotHaveChanged(): void\n    {\n        if (count($this->__snapshotChanges) === 0) {\n            return;\n        }\n\n        $this->markTestIncomplete(implode('. ', $this->__snapshotChanges));\n    }\n\n    /**\n     * The printable test case name.\n     */\n    public static function getPrintableTestCaseName(): string\n    {\n        return preg_replace('/P\\\\\\/', '', self::class, 1);\n    }\n\n    /**\n     * The printable test case method name.\n     */\n    public function getPrintableTestCaseMethodName(): string\n    {\n        return $this->__description;\n    }\n\n    /**\n     * The latest printable test case method name.\n     */\n    public static function getLatestPrintableTestCaseMethodName(): string\n    {\n        return self::$__latestDescription ?? '';\n    }\n\n    /**\n     * The printable test case method context.\n     */\n    public static function getPrintableContext(): array\n    {\n        return [\n            'assignees' => self::$__latestAssignees,\n            'issues' => self::$__latestIssues,\n            'prs' => self::$__latestPrs,\n            'notes' => self::$__latestNotes,\n        ];\n    }\n\n    /**\n     * Opens a shell for the test case.\n     */\n    public function shell(): void\n    {\n        Shell::open();\n    }\n}\n"
  },
  {
    "path": "src/Configuration/Presets.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Configuration;\n\nuse Closure;\nuse Pest\\Preset;\n\nfinal class Presets\n{\n    /**\n     * Creates a custom preset instance, and adds it to the list of presets.\n     */\n    public function custom(string $name, Closure $execute): void\n    {\n        Preset::custom($name, $execute);\n    }\n}\n"
  },
  {
    "path": "src/Configuration/Printer.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Configuration;\n\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\Printers\\DefaultPrinter;\n\n/**\n * @internal\n */\nfinal readonly class Printer\n{\n    /**\n     * Sets the theme to compact.\n     */\n    public function compact(): self\n    {\n        DefaultPrinter::compact(true);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Configuration/Project.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Configuration;\n\n/**\n * @internal\n */\nfinal class Project\n{\n    /**\n     * The assignees link.\n     *\n     * @internal\n     */\n    public string $assignees = '';\n\n    /**\n     * The issues link.\n     *\n     * @internal\n     */\n    public string $issues = '';\n\n    /**\n     * The PRs link.\n     *\n     * @internal\n     */\n    public string $prs = '';\n\n    /**\n     * The singleton instance.\n     */\n    private static ?self $instance = null;\n\n    /**\n     * Creates a new instance of the project.\n     */\n    public static function getInstance(): self\n    {\n        return self::$instance ??= new self;\n    }\n\n    /**\n     * Sets the test project to GitHub.\n     */\n    public function github(string $project): self\n    {\n        $this->issues = \"https://github.com/{$project}/issues/%s\";\n        $this->prs = \"https://github.com/{$project}/pull/%s\";\n\n        $this->assignees = 'https://github.com/%s';\n\n        return $this;\n    }\n\n    /**\n     * Sets the test project to GitLab.\n     */\n    public function gitlab(string $project): self\n    {\n        $this->issues = \"https://gitlab.com/{$project}/issues/%s\";\n        $this->prs = \"https://gitlab.com/{$project}/merge_requests/%s\";\n\n        $this->assignees = 'https://gitlab.com/%s';\n\n        return $this;\n    }\n\n    /**\n     * Sets the test project to Bitbucket.\n     */\n    public function bitbucket(string $project): self\n    {\n        $this->issues = \"https://bitbucket.org/{$project}/issues/%s\";\n        $this->prs = \"https://bitbucket.org/{$project}/pull-requests/%s\";\n\n        $this->assignees = 'https://bitbucket.org/%s';\n\n        return $this;\n    }\n\n    /**\n     * Sets the test project to Jira.\n     */\n    public function jira(string $namespace, string $project): self\n    {\n        $this->issues = \"https://{$namespace}.atlassian.net/browse/{$project}-%s\";\n\n        $this->assignees = \"https://{$namespace}.atlassian.net/secure/ViewProfile.jspa?name=%s\";\n\n        return $this;\n    }\n\n    /**\n     * Sets the test project to custom.\n     */\n    public function custom(string $issues, string $prs, string $assignees): self\n    {\n        $this->issues = $issues;\n        $this->prs = $prs;\n\n        $this->assignees = $assignees;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Configuration.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nuse Pest\\PendingCalls\\BeforeEachCall;\nuse Pest\\PendingCalls\\UsesCall;\n\n/**\n * @internal\n *\n * @mixin UsesCall\n */\nfinal readonly class Configuration\n{\n    /**\n     * The filename of the configuration.\n     */\n    private string $filename;\n\n    /**\n     * Creates a new configuration instance.\n     */\n    public function __construct(\n        string $filename,\n    ) {\n        $this->filename = str_ends_with($filename, DIRECTORY_SEPARATOR.'Pest.php') ? dirname($filename) : $filename;\n    }\n\n    /**\n     * Use the given classes and traits in the given targets.\n     */\n    public function in(string ...$targets): UsesCall\n    {\n        return (new UsesCall($this->filename, []))->in(...$targets);\n    }\n\n    /**\n     * Depending on where is called, it will extend the given classes and traits globally or locally.\n     */\n    public function extend(string ...$classAndTraits): UsesCall\n    {\n        return new UsesCall(\n            $this->filename,\n            array_values($classAndTraits)\n        );\n    }\n\n    /**\n     * Depending on where is called, it will extend the given classes and traits globally or locally.\n     */\n    public function extends(string ...$classAndTraits): UsesCall\n    {\n        return $this->extend(...$classAndTraits);\n    }\n\n    /**\n     * Depending on where is called, it will add the given groups globally or locally.\n     */\n    public function group(string ...$groups): UsesCall\n    {\n        return (new UsesCall($this->filename, []))->group(...$groups);\n    }\n\n    /**\n     * Marks all tests in the current file to be run exclusively.\n     */\n    public function only(): void\n    {\n        (new BeforeEachCall(TestSuite::getInstance(), $this->filename))->only();\n    }\n\n    /**\n     * Depending on where is called, it will extend the given classes and traits globally or locally.\n     */\n    public function use(string ...$classAndTraits): UsesCall\n    {\n        return $this->extend(...$classAndTraits);\n    }\n\n    /**\n     * Depending on where is called, it will extend the given classes and traits globally or locally.\n     */\n    public function uses(string ...$classAndTraits): UsesCall\n    {\n        return $this->extends(...$classAndTraits);\n    }\n\n    /**\n     * Gets the printer configuration.\n     */\n    public function printer(): Configuration\\Printer\n    {\n        return new Configuration\\Printer;\n    }\n\n    /**\n     * Gets the presets configuration.\n     */\n    public function presets(): Configuration\\Presets\n    {\n        return new Configuration\\Presets;\n    }\n\n    /**\n     * Gets the project configuration.\n     */\n    public function project(): Configuration\\Project\n    {\n        return Configuration\\Project::getInstance();\n    }\n\n    /**\n     * Gets the browser configuration.\n     */\n    public function browser(): Browser\\Configuration\n    {\n        return new Browser\\Configuration;\n    }\n\n    /**\n     * Proxies calls to the uses method.\n     *\n     * @param  array<array-key, mixed>  $arguments\n     */\n    public function __call(string $name, array $arguments): mixed\n    {\n        return $this->uses()->$name(...$arguments); // @phpstan-ignore-line\n    }\n}\n"
  },
  {
    "path": "src/Console/Help.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Console;\n\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal readonly class Help\n{\n    /**\n     * The Command messages.\n     *\n     * @var array<int, string>\n     */\n    private const array HELP_MESSAGES = [\n        '<comment>Pest Options:</comment>',\n        '  <info>--init</info>                      Initialise a standard Pest configuration',\n        '  <info>--coverage</info>                  Enable coverage and output to standard output',\n        '  <info>--min=<fg=cyan><N></></info>                   Set the minimum required coverage percentage (<N>), and fail if not met',\n        '  <info>--group=<fg=cyan><name></></info>              Only runs tests from the specified group(s)',\n    ];\n\n    /**\n     * Creates a new Console Command instance.\n     */\n    public function __construct(private OutputInterface $output)\n    {\n        // ..\n    }\n\n    /**\n     * Executes the Console Command.\n     */\n    public function __invoke(): void\n    {\n        foreach (self::HELP_MESSAGES as $message) {\n            $this->output->writeln($message);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Console/Thanks.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Console;\n\nuse Pest\\Bootstrappers\\BootView;\nuse Pest\\Support\\View;\nuse Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper;\nuse Symfony\\Component\\Console\\Input\\ArrayInput;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Console\\Question\\ConfirmationQuestion;\n\n/**\n * @internal\n */\nfinal readonly class Thanks\n{\n    /**\n     * The support options.\n     *\n     * @var array<string, string>\n     */\n    private const array FUNDING_MESSAGES = [\n        'Star' => 'https://github.com/pestphp/pest',\n        'YouTube' => 'https://youtube.com/@nunomaduro',\n        'TikTok' => 'https://tiktok.com/@enunomaduro',\n        'Twitch' => 'https://twitch.tv/nunomaduro',\n        'LinkedIn' => 'https://linkedin.com/in/nunomaduro',\n        'Instagram' => 'https://instagram.com/enunomaduro',\n        'X' => 'https://x.com/enunomaduro',\n        'Sponsor' => 'https://github.com/sponsors/nunomaduro',\n    ];\n\n    /**\n     * Creates a new Console Command instance.\n     */\n    public function __construct(\n        private InputInterface $input,\n        private OutputInterface $output\n    ) {\n        // ..\n    }\n\n    /**\n     * Executes the Console Command.\n     */\n    public function __invoke(): void\n    {\n        $bootstrapper = new BootView($this->output);\n        $bootstrapper->boot();\n\n        $wantsToSupport = false;\n\n        if (getenv('PEST_NO_SUPPORT') !== 'true' && $this->input->isInteractive()) {\n            $wantsToSupport = (new SymfonyQuestionHelper)->ask(\n                new ArrayInput([]),\n                $this->output,\n                new ConfirmationQuestion(\n                    ' <options=bold>Wanna show Pest some love by starring it on GitHub?</>',\n                    false,\n                )\n            );\n\n            View::render('components.new-line');\n\n            foreach (self::FUNDING_MESSAGES as $message => $link) {\n                View::render('components.two-column-detail', [\n                    'left' => $message,\n                    'right' => $link,\n                ]);\n            }\n\n            View::render('components.new-line');\n        }\n\n        if ($wantsToSupport === true) {\n            if (PHP_OS_FAMILY === 'Darwin') {\n                exec('open https://github.com/pestphp/pest');\n            }\n            if (PHP_OS_FAMILY === 'Windows') {\n                exec('start https://github.com/pestphp/pest');\n            }\n            if (PHP_OS_FAMILY === 'Linux') {\n                exec('xdg-open https://github.com/pestphp/pest');\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Contracts/ArchPreset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts;\n\n/**\n * @internal\n */\ninterface ArchPreset {}\n"
  },
  {
    "path": "src/Contracts/Bootstrapper.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts;\n\n/**\n * @internal\n */\ninterface Bootstrapper\n{\n    /**\n     * Boots the bootstrapper.\n     */\n    public function boot(): void;\n}\n"
  },
  {
    "path": "src/Contracts/HasPrintableTestCaseName.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts;\n\nuse NunoMaduro\\Collision\\Contracts\\Adapters\\Phpunit\\HasPrintableTestCaseName as BaseHasPrintableTestCaseName;\n\n/**\n * @internal\n */\ninterface HasPrintableTestCaseName extends BaseHasPrintableTestCaseName\n{\n    // ..\n}\n"
  },
  {
    "path": "src/Contracts/Panicable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts;\n\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\ninterface Panicable\n{\n    /**\n     * Renders the panic on the given output.\n     */\n    public function render(OutputInterface $output): void;\n\n    /**\n     * The exit code to be used.\n     */\n    public function exitCode(): int;\n}\n"
  },
  {
    "path": "src/Contracts/Plugins/AddsOutput.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts\\Plugins;\n\n/**\n * @internal\n */\ninterface AddsOutput\n{\n    /**\n     * Adds output after the Test Suite execution.\n     */\n    public function addOutput(int $exitCode): int;\n}\n"
  },
  {
    "path": "src/Contracts/Plugins/Bootable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts\\Plugins;\n\n/**\n * @internal\n */\ninterface Bootable\n{\n    /**\n     * Boots the plugin.\n     */\n    public function boot(): void;\n}\n"
  },
  {
    "path": "src/Contracts/Plugins/HandlesArguments.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts\\Plugins;\n\n/**\n * @internal\n */\ninterface HandlesArguments\n{\n    /**\n     * Adds arguments before the Test Suite execution.\n     *\n     * @param  array<int, string>  $arguments\n     * @return array<int, string>\n     */\n    public function handleArguments(array $arguments): array;\n}\n"
  },
  {
    "path": "src/Contracts/Plugins/HandlesOriginalArguments.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts\\Plugins;\n\n/**\n * @internal\n */\ninterface HandlesOriginalArguments\n{\n    /**\n     * Adds original arguments before the Test Suite execution.\n     *\n     * @param  array<int, string>  $arguments\n     */\n    public function handleOriginalArguments(array $arguments): void;\n}\n"
  },
  {
    "path": "src/Contracts/Plugins/Terminable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts\\Plugins;\n\n/**\n * @internal\n */\ninterface Terminable\n{\n    /**\n     * Terminates the plugin.\n     */\n    public function terminate(): void;\n}\n"
  },
  {
    "path": "src/Contracts/TestCaseFilter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts;\n\ninterface TestCaseFilter\n{\n    /**\n     * Whether the test case is accepted.\n     */\n    public function accept(string $testCaseFilename): bool;\n}\n"
  },
  {
    "path": "src/Contracts/TestCaseMethodFilter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Contracts;\n\nuse Pest\\Factories\\TestCaseMethodFactory;\n\ninterface TestCaseMethodFilter\n{\n    /**\n     * Whether the test case method is accepted.\n     */\n    public function accept(TestCaseMethodFactory $factory): bool;\n}\n"
  },
  {
    "path": "src/Evaluators/Attributes.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Evaluators;\n\nuse Pest\\Factories\\Attribute;\n\n/**\n * @internal\n */\nfinal class Attributes\n{\n    /**\n     * Evaluates the given attributes and returns the code.\n     *\n     * @param  iterable<int, Attribute>  $attributes\n     */\n    public static function code(iterable $attributes): string\n    {\n        return implode(PHP_EOL, array_map(function (Attribute $attribute): string {\n            $name = $attribute->name;\n\n            if ($attribute->arguments === []) {\n                return \"    #[\\\\{$name}]\";\n            }\n\n            $arguments = array_map(fn (string $argument): string => var_export($argument, true), iterator_to_array($attribute->arguments));\n\n            return sprintf('    #[\\\\%s(%s)]', $name, implode(', ', $arguments));\n        }, iterator_to_array($attributes)));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/AfterAllAlreadyExist.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class AfterAllAlreadyExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $filename)\n    {\n        parent::__construct(sprintf('The afterAll already exists in the filename `%s`.', $filename));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/AfterAllWithinDescribe.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class AfterAllWithinDescribe extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $filename)\n    {\n        parent::__construct(sprintf('The afterAll method can not be used within describe functions. Filename `%s`.', $filename));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/AfterBeforeTestFunction.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class AfterBeforeTestFunction extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $filename)\n    {\n        parent::__construct('After method cannot be used with before the [test|it] functions in the filename `['.$filename.']`.');\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/BeforeAllAlreadyExist.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class BeforeAllAlreadyExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $filename)\n    {\n        parent::__construct(sprintf('The beforeAll already exists in the filename `%s`.', $filename));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/BeforeAllWithinDescribe.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class BeforeAllWithinDescribe extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $filename)\n    {\n        parent::__construct(sprintf('The beforeAll method can not be used within describe functions. Filename `%s`.', $filename));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/DatasetAlreadyExists.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class DatasetAlreadyExists extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $name, string $scope)\n    {\n        parent::__construct(sprintf('A dataset with the name `%s` already exists in scope [%s].', $name, $scope));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/DatasetArgumentsMismatch.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse Exception;\n\nfinal class DatasetArgumentsMismatch extends Exception\n{\n    public function __construct(int $requiredCount, int $suppliedCount)\n    {\n        if ($requiredCount <= $suppliedCount) {\n            parent::__construct('Test argument names and dataset keys do not match');\n        } else {\n            parent::__construct(sprintf('Test expects %d arguments but dataset only provides %d', $requiredCount, $suppliedCount));\n        }\n    }\n\n    //\n}\n"
  },
  {
    "path": "src/Exceptions/DatasetDoesNotExist.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class DatasetDoesNotExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $name)\n    {\n        parent::__construct(sprintf(\"A dataset with the name `%s` does not exist. You can create it using `dataset('%s', ['a', 'b']);`.\", $name, $name));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/DatasetMissing.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse BadFunctionCallException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class DatasetMissing extends BadFunctionCallException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     *\n     * @param  array<string, string>  $arguments\n     */\n    public function __construct(string $file, string $name, array $arguments)\n    {\n        parent::__construct(sprintf(\n            'A test with the description [%s] has [%d] argument(s) ([%s]) and no dataset(s) provided in [%s]',\n            $name,\n            count($arguments),\n            implode(', ', array_map(static fn (string $arg, string $type): string => sprintf('%s $%s', $type, $arg), array_keys($arguments), $arguments)),\n            $file,\n        ));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/ExpectationNotFound.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse Exception;\n\n/**\n * @internal\n */\nfinal class ExpectationNotFound extends Exception\n{\n    /**\n     * Creates a new ExpectationNotFound instance from the given name.\n     */\n    public static function fromName(string $name): ExpectationNotFound\n    {\n        return new self(\"Expectation [$name] does not exist.\");\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/FatalException.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse RuntimeException;\n\n/**\n * @internal\n */\nfinal class FatalException extends RuntimeException implements RenderlessTrace\n{\n    //\n}\n"
  },
  {
    "path": "src/Exceptions/FileOrFolderNotFound.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class FileOrFolderNotFound extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $filename)\n    {\n        parent::__construct(sprintf('The file or folder with the name `%s` could not be found.', $filename));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/InvalidArgumentException.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException as BaseInvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $message)\n    {\n        parent::__construct($message, 1);\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/InvalidExpectation.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse LogicException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class InvalidExpectation extends LogicException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * @param  array<int, string>  $methods\n     *\n     * @throws self\n     */\n    public static function fromMethods(array $methods): never\n    {\n        throw new self(sprintf('Expectation [%s] is not valid.', implode('->', $methods)));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/InvalidExpectationValue.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\n\n/**\n * @internal\n */\nfinal class InvalidExpectationValue extends InvalidArgumentException\n{\n    /**\n     * @throws self\n     */\n    public static function expected(string $type): never\n    {\n        throw new self(sprintf('Invalid expectation value type. Expected [%s].', $type));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/InvalidOption.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class InvalidOption extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $message)\n    {\n        parent::__construct($message, 1);\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/InvalidPestCommand.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class InvalidPestCommand extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct()\n    {\n        parent::__construct('Please run [./vendor/bin/pest] instead.');\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/MissingDependency.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class MissingDependency extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $feature, string $dependency)\n    {\n        parent::__construct(sprintf('The feature \"%s\" requires \"%s\".', $feature, $dependency));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/NoDirtyTestsFound.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Pest\\Contracts\\Panicable;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal class NoDirtyTestsFound extends InvalidArgumentException implements ExceptionInterface, Panicable, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Renders the panic on the given output.\n     */\n    public function render(OutputInterface $output): void\n    {\n        $output->writeln([\n            '',\n            '  <fg=white;options=bold;bg=blue> INFO </> No \"dirty\" tests found.',\n            '',\n        ]);\n    }\n\n    /**\n     * The exit code to be used.\n     */\n    public function exitCode(): int\n    {\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/ShouldNotHappen.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse Exception;\nuse RuntimeException;\n\n/**\n * @internal\n */\nfinal class ShouldNotHappen extends RuntimeException\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(Exception $exception)\n    {\n        $message = $exception->getMessage();\n\n        parent::__construct(sprintf(<<<'EOF'\nThis should not happen - please create an new issue here: https://github.com/pestphp/pest/issues\n\n  Issue: %s\n  PHP version: %s\n  Operating system: %s\nEOF\n            , $message, phpversion(), PHP_OS), 1, $exception);\n    }\n\n    /**\n     * Creates a new instance of should not happen without a specific exception.\n     */\n    public static function fromMessage(string $message): ShouldNotHappen\n    {\n        return new ShouldNotHappen(new Exception($message));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/TestAlreadyExist.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class TestAlreadyExist extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $fileName, string $description)\n    {\n        parent::__construct(sprintf('A test with the description `%s` already exists in the filename `%s`.', $description, $fileName));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/TestCaseAlreadyInUse.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class TestCaseAlreadyInUse extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $inUse, string $newOne, string $folder)\n    {\n        parent::__construct(sprintf(\n            'Test case [%s] can not be used. The folder [%s] already uses the test case [%s].',\n            $newOne,\n            $folder,\n            $inUse,\n        ));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/TestCaseClassOrTraitNotFound.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class TestCaseClassOrTraitNotFound extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $testCaseClass)\n    {\n        parent::__construct(sprintf('The class `%s` was not found.', $testCaseClass));\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/TestClosureMustNotBeStatic.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Pest\\Factories\\TestCaseMethodFactory;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class TestClosureMustNotBeStatic extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(TestCaseMethodFactory $method)\n    {\n        parent::__construct(\n            sprintf(\n                'Test closure must not be static. Please remove the [static] keyword from the [%s] method in [%s].',\n                $method->description,\n                $method->filename\n            )\n        );\n    }\n}\n"
  },
  {
    "path": "src/Exceptions/TestDescriptionMissing.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Exceptions;\n\nuse InvalidArgumentException;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessEditor;\nuse NunoMaduro\\Collision\\Contracts\\RenderlessTrace;\nuse Symfony\\Component\\Console\\Exception\\ExceptionInterface;\n\n/**\n * @internal\n */\nfinal class TestDescriptionMissing extends InvalidArgumentException implements ExceptionInterface, RenderlessEditor, RenderlessTrace\n{\n    /**\n     * Creates a new Exception instance.\n     */\n    public function __construct(string $fileName)\n    {\n        parent::__construct(sprintf('Test description is missing in the filename `%s`.', $fileName));\n    }\n}\n"
  },
  {
    "path": "src/Expectation.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nuse Attribute;\nuse BadMethodCallException;\nuse Closure;\nuse InvalidArgumentException;\nuse OutOfRangeException;\nuse Pest\\Arch\\Contracts\\ArchExpectation;\nuse Pest\\Arch\\Expectations\\Targeted;\nuse Pest\\Arch\\Expectations\\ToBeUsedIn;\nuse Pest\\Arch\\Expectations\\ToBeUsedInNothing;\nuse Pest\\Arch\\Expectations\\ToOnlyBeUsedIn;\nuse Pest\\Arch\\Expectations\\ToOnlyUse;\nuse Pest\\Arch\\Expectations\\ToUse;\nuse Pest\\Arch\\Expectations\\ToUseNothing;\nuse Pest\\Arch\\PendingArchExpectation;\nuse Pest\\Arch\\Support\\FileLineFinder;\nuse Pest\\Concerns\\Extendable;\nuse Pest\\Concerns\\Pipeable;\nuse Pest\\Concerns\\Retrievable;\nuse Pest\\Exceptions\\ExpectationNotFound;\nuse Pest\\Exceptions\\InvalidExpectation;\nuse Pest\\Exceptions\\InvalidExpectationValue;\nuse Pest\\Expectations\\EachExpectation;\nuse Pest\\Expectations\\HigherOrderExpectation;\nuse Pest\\Expectations\\OppositeExpectation;\nuse Pest\\Matchers\\Any;\nuse Pest\\Support\\ExpectationPipeline;\nuse Pest\\Support\\Reflection;\nuse PHPUnit\\Architecture\\Elements\\ObjectDescription;\nuse PHPUnit\\Framework\\ExpectationFailedException;\nuse ReflectionEnum;\nuse ReflectionMethod;\nuse ReflectionProperty;\n\n/**\n * @template TValue\n *\n * @property OppositeExpectation $not Creates the opposite expectation.\n * @property EachExpectation $each Creates an expectation on each element on the traversable value.\n * @property PendingArchExpectation $classes\n * @property PendingArchExpectation $traits\n * @property PendingArchExpectation $interfaces\n * @property PendingArchExpectation $enums\n *\n * @mixin Mixins\\Expectation<TValue>\n * @mixin PendingArchExpectation\n */\nfinal class Expectation\n{\n    /** @use Extendable<self<TValue>> */\n    use Extendable;\n\n    use Pipeable;\n    use Retrievable;\n\n    /**\n     * Creates a new expectation.\n     *\n     * @param  TValue  $value\n     */\n    public function __construct(\n        public mixed $value\n    ) {\n        // ..\n    }\n\n    /**\n     * Creates a new expectation.\n     *\n     * @template TAndValue\n     *\n     * @param  TAndValue  $value\n     * @return self<TAndValue>\n     */\n    public function and(mixed $value): Expectation\n    {\n        return $value instanceof self ? $value : new self($value);\n    }\n\n    /**\n     * Creates a new expectation with the decoded JSON value.\n     *\n     * @return self<array<int|string, mixed>|bool>\n     */\n    public function json(): Expectation\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n\n        $this->toBeJson();\n\n        /** @var array<int|string, mixed>|bool $value */\n        $value = json_decode($this->value, true, 512, JSON_THROW_ON_ERROR);\n\n        return $this->and($value);\n    }\n\n    /**\n     * Dump the expectation value.\n     *\n     * @return self<TValue>\n     */\n    public function dump(mixed ...$arguments): self\n    {\n        if (function_exists('dump')) {\n            dump($this->value, ...$arguments);\n        } else {\n            var_dump($this->value);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Dump the expectation value and end the script.\n     *\n     * @return never\n     */\n    public function dd(mixed ...$arguments): void\n    {\n        if (function_exists('dd')) {\n            dd($this->value, ...$arguments);\n        }\n\n        var_dump($this->value);\n\n        exit(1);\n    }\n\n    /**\n     * Dump the expectation value when the result of the condition is truthy.\n     *\n     * @param  (Closure(TValue): bool)|bool  $condition\n     * @return self<TValue>\n     */\n    public function ddWhen(Closure|bool $condition, mixed ...$arguments): Expectation\n    {\n        $condition = $condition instanceof Closure ? $condition($this->value) : $condition;\n\n        if (! $condition) {\n            return $this;\n        }\n\n        $this->dd(...$arguments);\n    }\n\n    /**\n     * Dump the expectation value when the result of the condition is falsy.\n     *\n     * @param  (Closure(TValue): bool)|bool  $condition\n     * @return self<TValue>\n     */\n    public function ddUnless(Closure|bool $condition, mixed ...$arguments): Expectation\n    {\n        $condition = $condition instanceof Closure ? $condition($this->value) : $condition;\n\n        if ($condition) {\n            return $this;\n        }\n\n        $this->dd(...$arguments);\n    }\n\n    /**\n     * Send the expectation value to Ray along with all given arguments.\n     *\n     * @return self<TValue>\n     */\n    public function ray(mixed ...$arguments): self\n    {\n        if (function_exists('ray')) {\n            ray($this->value, ...$arguments);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Creates the opposite expectation for the value.\n     *\n     * @return OppositeExpectation<TValue>\n     */\n    public function not(): OppositeExpectation\n    {\n        return new OppositeExpectation($this);\n    }\n\n    /**\n     * Creates an expectation on each item of the iterable \"value\".\n     *\n     * @return EachExpectation<TValue>\n     */\n    public function each(?callable $callback = null): EachExpectation\n    {\n        if (! is_iterable($this->value)) {\n            throw new BadMethodCallException('Expectation value is not iterable.');\n        }\n\n        if (is_callable($callback)) {\n            foreach ($this->value as $key => $item) {\n                $callback(new self($item), $key);\n            }\n        }\n\n        return new EachExpectation($this);\n    }\n\n    /**\n     * Allows you to specify a sequential set of expectations for each item in a iterable \"value\".\n     *\n     * @template TSequenceValue\n     *\n     * @param  (callable(self<TValue>, self<string|int>): void)|TSequenceValue  ...$callbacks\n     * @return self<TValue>\n     */\n    public function sequence(mixed ...$callbacks): self\n    {\n        if (! is_iterable($this->value)) {\n            throw new BadMethodCallException('Expectation value is not iterable.');\n        }\n\n        if ($callbacks === []) {\n            throw new InvalidArgumentException('No sequence expectations defined.');\n        }\n\n        $index = $valuesCount = 0;\n\n        foreach ($this->value as $key => $value) {\n            $valuesCount++;\n\n            if ($callbacks[$index] instanceof Closure) {\n                $callbacks[$index](new self($value), new self($key));\n            } else {\n                (new self($value))->toEqual($callbacks[$index]);\n            }\n\n            $index = isset($callbacks[$index + 1]) ? $index + 1 : 0;\n        }\n\n        if ($valuesCount < count($callbacks)) {\n            throw new OutOfRangeException('Sequence expectations are more than the iterable items.');\n        }\n\n        return $this;\n    }\n\n    /**\n     * If the subject matches one of the given \"expressions\", the expression callback will run.\n     *\n     * @template TMatchSubject of array-key\n     *\n     * @param  (callable(): TMatchSubject)|TMatchSubject  $subject\n     * @param  array<TMatchSubject, (callable(self<TValue>): mixed)|TValue>  $expressions\n     * @return self<TValue>\n     */\n    public function match(mixed $subject, array $expressions): self\n    {\n        $subject = $subject instanceof Closure ? $subject() : $subject;\n\n        $matched = false;\n\n        foreach ($expressions as $key => $callback) {\n            if ($subject != $key) { // @pest-arch-ignore-line\n                continue;\n            }\n\n            $matched = true;\n\n            if (is_callable($callback)) {\n                $callback(new self($this->value));\n\n                continue;\n            }\n\n            $this->and($this->value)->toEqual($callback);\n\n            break;\n        }\n\n        if ($matched === false) {\n            throw new ExpectationFailedException('Unhandled match value.');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Apply the callback if the given \"condition\" is falsy.\n     *\n     * @param  (callable(): bool)|bool  $condition\n     * @param  callable(Expectation<TValue>): mixed  $callback\n     * @return self<TValue>\n     */\n    public function unless(callable|bool $condition, callable $callback): Expectation\n    {\n        $condition = is_callable($condition)\n            ? $condition\n            : static fn (): bool => $condition;\n\n        return $this->when(! $condition(), $callback);\n    }\n\n    /**\n     * Apply the callback if the given \"condition\" is truthy.\n     *\n     * @param  (callable(): bool)|bool  $condition\n     * @param  callable(self<TValue>): mixed  $callback\n     * @return self<TValue>\n     */\n    public function when(callable|bool $condition, callable $callback): self\n    {\n        $condition = is_callable($condition)\n            ? $condition\n            : static fn (): bool => $condition;\n\n        if ($condition()) {\n            $callback($this->and($this->value));\n        }\n\n        return $this;\n    }\n\n    /**\n     * Dynamically calls methods on the class or creates a new higher order expectation.\n     *\n     * @param  array<int, mixed>  $parameters\n     * @return Expectation<TValue>|HigherOrderExpectation<Expectation<TValue>, TValue>\n     */\n    public function __call(string $method, array $parameters): Expectation|HigherOrderExpectation|PendingArchExpectation|ArchExpectation\n    {\n        if (! self::hasMethod($method)) {\n            if (! is_object($this->value) && method_exists(PendingArchExpectation::class, $method)) {\n                $pendingArchExpectation = new PendingArchExpectation($this, []);\n\n                return $pendingArchExpectation->$method(...$parameters); // @phpstan-ignore-line\n            }\n\n            if (! is_object($this->value)) {\n                throw new BadMethodCallException(sprintf(\n                    'Method \"%s\" does not exist in %s.',\n                    $method,\n                    gettype($this->value)\n                ));\n            }\n\n            /* @phpstan-ignore-next-line */\n            return new HigherOrderExpectation($this, call_user_func_array($this->value->$method(...), $parameters));\n        }\n\n        $closure = $this->getExpectationClosure($method);\n        $reflectionClosure = new \\ReflectionFunction($closure);\n        $expectation = $reflectionClosure->getClosureThis();\n\n        if ($reflectionClosure->getReturnType()?->__toString() === ArchExpectation::class) {\n            return $closure(...$parameters);\n        }\n\n        assert(is_object($expectation));\n\n        ExpectationPipeline::for($closure)\n            ->send(...$parameters)\n            ->through($this->pipes($method, $expectation, Expectation::class))\n            ->run();\n\n        return $this;\n    }\n\n    /**\n     * Creates a new expectation closure from the given name.\n     *\n     * @throws ExpectationNotFound\n     */\n    private function getExpectationClosure(string $name): Closure\n    {\n        if (method_exists(Mixins\\Expectation::class, $name)) {\n            // @phpstan-ignore-next-line\n            return Closure::fromCallable([new Mixins\\Expectation($this->value), $name]);\n        }\n\n        if (self::hasExtend($name)) {\n            $extend = self::$extends[$name]->bindTo($this, Expectation::class);\n\n            if ($extend != false) { // @pest-arch-ignore-line\n                return $extend;\n            }\n        }\n\n        throw ExpectationNotFound::fromName($name);\n    }\n\n    /**\n     * Dynamically calls methods on the class without any arguments or creates a new higher order expectation.\n     *\n     * @return Expectation<TValue>|OppositeExpectation<TValue>|EachExpectation<TValue>|HigherOrderExpectation<Expectation<TValue>, TValue|null>|TValue\n     */\n    public function __get(string $name): mixed\n    {\n        if (! self::hasMethod($name)) {\n            if (! is_object($this->value) && method_exists(PendingArchExpectation::class, $name)) {\n                /* @phpstan-ignore-next-line */\n                return $this->{$name}();\n            }\n\n            /* @phpstan-ignore-next-line */\n            return new HigherOrderExpectation($this, $this->retrieve($name, $this->value));\n        }\n\n        /* @phpstan-ignore-next-line */\n        return $this->{$name}();\n    }\n\n    /**\n     * Checks if the given expectation method exists.\n     */\n    public static function hasMethod(string $name): bool\n    {\n        return method_exists(self::class, $name)\n            || method_exists(Mixins\\Expectation::class, $name)\n            || self::hasExtend($name);\n    }\n\n    /**\n     * Matches any value.\n     */\n    public function any(): Any\n    {\n        return new Any;\n    }\n\n    /**\n     * Asserts that the given expectation target use the given dependencies.\n     *\n     * @param  array<int, string>|string  $targets\n     */\n    public function toUse(array|string $targets): ArchExpectation\n    {\n        return ToUse::make($this, $targets);\n    }\n\n    /**\n     * Asserts that the given expectation target does have the given permissions\n     */\n    public function toHaveFileSystemPermissions(string $permissions): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => substr(sprintf('%o', fileperms($object->path)), -4) === $permissions,\n            sprintf('permissions to be [%s]', $permissions),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to have line count less than the given number.\n     */\n    public function toHaveLineCountLessThan(int $lines): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => count(file($object->path)) < $lines, // @phpstan-ignore-line\n            sprintf('to have less than %d lines of code', $lines),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target have all methods documented.\n     */\n    public function toHaveMethodsDocumented(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false\n                || array_filter(\n                    Reflection::getMethodsFromReflectionClass($object->reflectionClass),\n                    fn (ReflectionMethod $method): bool => (enum_exists($object->name) === false || in_array($method->name, ['from', 'tryFrom', 'cases'], true) === false)\n                        && realpath($method->getFileName() ?: '/') === realpath($object->path) // @phpstan-ignore-line\n                        && $method->getDocComment() === false,\n                ) === [],\n            'to have methods with documentation / annotations',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target have all properties documented.\n     */\n    public function toHavePropertiesDocumented(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false\n                || array_filter(\n                    Reflection::getPropertiesFromReflectionClass($object->reflectionClass),\n                    fn (ReflectionProperty $property): bool => (enum_exists($object->name) === false || in_array($property->name, ['value', 'name'], true) === false)\n                        && realpath($property->getDeclaringClass()->getFileName() ?: '/') === realpath($object->path) // @phpstan-ignore-line\n                        && $property->isPromoted() === false\n                        && $property->getDocComment() === false,\n                ) === [],\n            'to have properties with documentation / annotations',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target use the \"declare(strict_types=1)\" declaration.\n     */\n    public function toUseStrictTypes(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => (bool) preg_match('/^<\\?php\\s*(\\/\\*[\\s\\S]*?\\*\\/|\\/\\/[^\\r\\n]*(?:\\r?\\n|$)|\\s)*declare\\s*\\(\\s*strict_types\\s*=\\s*1\\s*\\)\\s*;/m', (string) file_get_contents($object->path)),\n            'to use strict types',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target uses strict equality.\n     */\n    public function toUseStrictEquality(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => ! str_contains((string) file_get_contents($object->path), ' == ') && ! str_contains((string) file_get_contents($object->path), ' != '),\n            'to use strict equality',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, ' == ') || str_contains($line, ' != ')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target is final.\n     */\n    public function toBeFinal(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => ! enum_exists($object->name) && isset($object->reflectionClass) && $object->reflectionClass->isFinal(),\n            'to be final',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target is readonly.\n     */\n    public function toBeReadonly(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => ! enum_exists($object->name) && isset($object->reflectionClass) && $object->reflectionClass->isReadOnly() && assert(true), // @phpstan-ignore-line\n            'to be readonly',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target is trait.\n     */\n    public function toBeTrait(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isTrait(),\n            'to be trait',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are traits.\n     */\n    public function toBeTraits(): ArchExpectation\n    {\n        return $this->toBeTrait();\n    }\n\n    /**\n     * Asserts that the given expectation target is abstract.\n     */\n    public function toBeAbstract(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isAbstract(),\n            'to be abstract',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target has a specific method.\n     *\n     * @param  array<int, string>|string  $method\n     */\n    public function toHaveMethod(array|string $method): ArchExpectation\n    {\n        $methods = is_array($method) ? $method : [$method];\n\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => count(array_filter($methods, fn (string $method): bool => isset($object->reflectionClass) && $object->reflectionClass->hasMethod($method))) === count($methods),\n            sprintf(\"to have method '%s'\", implode(\"', '\", $methods)),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target has a specific methods.\n     *\n     * @param  array<int, string>  $methods\n     */\n    public function toHaveMethods(array $methods): ArchExpectation\n    {\n        return $this->toHaveMethod($methods);\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toHavePublicMethodsBesides(): void\n    {\n        throw InvalidExpectation::fromMethods(['toHavePublicMethodsBesides']);\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toHavePublicMethods(): void\n    {\n        throw InvalidExpectation::fromMethods(['toHavePublicMethods']);\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toHaveProtectedMethodsBesides(): void\n    {\n        throw InvalidExpectation::fromMethods(['toHaveProtectedMethodsBesides']);\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toHaveProtectedMethods(): void\n    {\n        throw InvalidExpectation::fromMethods(['toHaveProtectedMethods']);\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toHavePrivateMethodsBesides(): void\n    {\n        throw InvalidExpectation::fromMethods(['toHavePrivateMethodsBesides']);\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toHavePrivateMethods(): void\n    {\n        throw InvalidExpectation::fromMethods(['toHavePrivateMethods']);\n    }\n\n    /**\n     * Asserts that the given expectation target is enum.\n     */\n    public function toBeEnum(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isEnum(),\n            'to be enum',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are enums.\n     */\n    public function toBeEnums(): ArchExpectation\n    {\n        return $this->toBeEnum();\n    }\n\n    /**\n     * Asserts that the given expectation target is a class.\n     */\n    public function toBeClass(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => class_exists($object->name) && ! enum_exists($object->name),\n            'to be class',\n            FileLineFinder::where(fn (string $line): bool => true),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are classes.\n     */\n    public function toBeClasses(): ArchExpectation\n    {\n        return $this->toBeClass();\n    }\n\n    /**\n     * Asserts that the given expectation target is interface.\n     */\n    public function toBeInterface(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->isInterface(),\n            'to be interface',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are interfaces.\n     */\n    public function toBeInterfaces(): ArchExpectation\n    {\n        return $this->toBeInterface();\n    }\n\n    /**\n     * Asserts that the given expectation target to be subclass of the given class.\n     */\n    public function toExtend(string $class): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && ($class === $object->reflectionClass->getName() || $object->reflectionClass->isSubclassOf($class)),\n            sprintf(\"to extend '%s'\", $class),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to be have a parent class.\n     */\n    public function toExtendNothing(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => $object->reflectionClass->getParentClass() === false,\n            'to extend nothing',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to use the given trait.\n     */\n    public function toUseTrait(string $trait): ArchExpectation\n    {\n        return $this->toUseTraits($trait);\n    }\n\n    /**\n     * Asserts that the given expectation target to use the given traits.\n     *\n     * @param  array<int, string>|string  $traits\n     */\n    public function toUseTraits(array|string $traits): ArchExpectation\n    {\n        $traits = is_array($traits) ? $traits : [$traits];\n\n        return Targeted::make(\n            $this,\n            function (ObjectDescription $object) use ($traits): bool {\n                foreach ($traits as $trait) {\n                    if (isset($object->reflectionClass) === false) {\n                        return false;\n                    }\n\n                    if (! in_array($trait, $object->reflectionClass->getTraitNames(), true)) {\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            \"to use traits '\".implode(\"', '\", $traits).\"'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to not implement any interfaces.\n     */\n    public function toImplementNothing(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getInterfaceNames() === [],\n            'to implement nothing',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to only implement the given interfaces.\n     *\n     * @param  array<int, string>|string  $interfaces\n     */\n    public function toOnlyImplement(array|string $interfaces): ArchExpectation\n    {\n        $interfaces = is_array($interfaces) ? $interfaces : [$interfaces];\n\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass)\n                && (count($interfaces) === count($object->reflectionClass->getInterfaceNames()))\n                && array_diff($interfaces, $object->reflectionClass->getInterfaceNames()) === [],\n            \"to only implement '\".implode(\"', '\", $interfaces).\"'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to have the given prefix.\n     */\n    public function toHavePrefix(string $prefix): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && str_starts_with($object->reflectionClass->getShortName(), $prefix),\n            \"to have prefix '{$prefix}'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to have the given suffix.\n     */\n    public function toHaveSuffix(string $suffix): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && str_ends_with($object->reflectionClass->getName(), $suffix),\n            \"to have suffix '{$suffix}'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to implement the given interfaces.\n     *\n     * @param  array<int, string>|string  $interfaces\n     */\n    public function toImplement(array|string $interfaces): ArchExpectation\n    {\n        $interfaces = is_array($interfaces) ? $interfaces : [$interfaces];\n\n        return Targeted::make(\n            $this,\n            function (ObjectDescription $object) use ($interfaces): bool {\n                foreach ($interfaces as $interface) {\n                    if (! isset($object->reflectionClass) || ! $object->reflectionClass->implementsInterface($interface)) {\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            \"to implement '\".implode(\"', '\", $interfaces).\"'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target \"only\" use on the given dependencies.\n     *\n     * @param  array<int, string>|string  $targets\n     */\n    public function toOnlyUse(array|string $targets): ArchExpectation\n    {\n        return ToOnlyUse::make($this, $targets);\n    }\n\n    /**\n     * Asserts that the given expectation target does not use any dependencies.\n     */\n    public function toUseNothing(): ArchExpectation\n    {\n        return ToUseNothing::make($this);\n    }\n\n    /**\n     * Asserts that the source code of the given expectation target does not include suspicious characters.\n     */\n    public function toHaveSuspiciousCharacters(): ArchExpectation\n    {\n        throw InvalidExpectation::fromMethods(['toHaveSuspiciousCharacters']);\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toBeUsed(): void\n    {\n        throw InvalidExpectation::fromMethods(['toBeUsed']);\n    }\n\n    /**\n     * Asserts that the given expectation dependency is used by the given targets.\n     *\n     * @param  array<int, string>|string  $targets\n     */\n    public function toBeUsedIn(array|string $targets): ArchExpectation\n    {\n        return ToBeUsedIn::make($this, $targets);\n    }\n\n    /**\n     * Asserts that the given expectation dependency is \"only\" used by the given targets.\n     *\n     * @param  array<int, string>|string  $targets\n     */\n    public function toOnlyBeUsedIn(array|string $targets): ArchExpectation\n    {\n        return ToOnlyBeUsedIn::make($this, $targets);\n    }\n\n    /**\n     * Asserts that the given expectation dependency is not used.\n     */\n    public function toBeUsedInNothing(): ArchExpectation\n    {\n        return ToBeUsedInNothing::make($this);\n    }\n\n    /**\n     * Asserts that the given expectation dependency is an invokable class.\n     */\n    public function toBeInvokable(): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->hasMethod('__invoke'),\n            'to be invokable',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))\n        );\n    }\n\n    /**\n     * Asserts that the given expectation is iterable and contains snake_case keys.\n     *\n     * @return self<TValue>\n     */\n    public function toHaveSnakeCaseKeys(string $message = ''): self\n    {\n        if (! is_iterable($this->value)) {\n            InvalidExpectationValue::expected('iterable');\n        }\n\n        foreach ($this->value as $k => $item) {\n            if (is_string($k)) {\n                $this->and($k)->toBeSnakeCase($message);\n            }\n\n            if (is_array($item)) {\n                $this->and($item)->toHaveSnakeCaseKeys($message);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the given expectation is iterable and contains kebab-case keys.\n     *\n     * @return self<TValue>\n     */\n    public function toHaveKebabCaseKeys(string $message = ''): self\n    {\n        if (! is_iterable($this->value)) {\n            InvalidExpectationValue::expected('iterable');\n        }\n\n        foreach ($this->value as $k => $item) {\n            if (is_string($k)) {\n                $this->and($k)->toBeKebabCase($message);\n            }\n\n            if (is_array($item)) {\n                $this->and($item)->toHaveKebabCaseKeys($message);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the given expectation is iterable and contains camelCase keys.\n     *\n     * @return self<TValue>\n     */\n    public function toHaveCamelCaseKeys(string $message = ''): self\n    {\n        if (! is_iterable($this->value)) {\n            InvalidExpectationValue::expected('iterable');\n        }\n\n        foreach ($this->value as $k => $item) {\n            if (is_string($k)) {\n                $this->and($k)->toBeCamelCase($message);\n            }\n\n            if (is_array($item)) {\n                $this->and($item)->toHaveCamelCaseKeys($message);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the given expectation is iterable and contains StudlyCase keys.\n     *\n     * @return self<TValue>\n     */\n    public function toHaveStudlyCaseKeys(string $message = ''): self\n    {\n        if (! is_iterable($this->value)) {\n            InvalidExpectationValue::expected('iterable');\n        }\n\n        foreach ($this->value as $k => $item) {\n            if (is_string($k)) {\n                $this->and($k)->toBeStudlyCase($message);\n            }\n\n            if (is_array($item)) {\n                $this->and($item)->toHaveStudlyCaseKeys($message);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the given expectation target to have the given attribute.\n     */\n    public function toHaveAttribute(string $attribute): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) && $object->reflectionClass->getAttributes($attribute) !== [],\n            \"to have attribute '{$attribute}'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target has a constructor method.\n     */\n    public function toHaveConstructor(): ArchExpectation\n    {\n        return $this->toHaveMethod('__construct');\n    }\n\n    /**\n     * Asserts that the given expectation target has a destructor method.\n     */\n    public function toHaveDestructor(): ArchExpectation\n    {\n        return $this->toHaveMethod('__destruct');\n    }\n\n    /**\n     * Asserts that the given expectation target is a backed enum of given type.\n     */\n    private function toBeBackedEnum(string $backingType): ArchExpectation\n    {\n        return Targeted::make(\n            $this,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass)\n                && $object->reflectionClass->isEnum()\n                && (new ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line\n                && (string) (new ReflectionEnum($object->name))->getBackingType() === $backingType, // @phpstan-ignore-line\n            'to be '.$backingType.' backed enum',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are string backed enums.\n     */\n    public function toBeStringBackedEnums(): ArchExpectation\n    {\n        return $this->toBeStringBackedEnum();\n    }\n\n    /**\n     * Asserts that the given expectation targets are int backed enums.\n     */\n    public function toBeIntBackedEnums(): ArchExpectation\n    {\n        return $this->toBeIntBackedEnum();\n    }\n\n    /**\n     * Asserts that the given expectation target is a string backed enum.\n     */\n    public function toBeStringBackedEnum(): ArchExpectation\n    {\n        return $this->toBeBackedEnum('string');\n    }\n\n    /**\n     * Asserts that the given expectation target is an int backed enum.\n     */\n    public function toBeIntBackedEnum(): ArchExpectation\n    {\n        return $this->toBeBackedEnum('int');\n    }\n}\n"
  },
  {
    "path": "src/Expectations/EachExpectation.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Expectations;\n\nuse Pest\\Expectation;\n\nuse function expect;\n\n/**\n * @internal\n *\n * @template TValue\n *\n * @mixin Expectation<TValue>\n */\nfinal class EachExpectation\n{\n    /**\n     * Indicates if the expectation is the opposite.\n     */\n    private bool $opposite = false;\n\n    /**\n     * Creates an expectation on each item of the iterable \"value\".\n     *\n     * @param  Expectation<TValue>  $original\n     */\n    public function __construct(private readonly Expectation $original) {}\n\n    /**\n     * Creates a new expectation.\n     *\n     * @template TAndValue\n     *\n     * @param  TAndValue  $value\n     * @return Expectation<TAndValue>\n     */\n    public function and(mixed $value): Expectation\n    {\n        return $this->original->and($value);\n    }\n\n    /**\n     * Creates the opposite expectation for the value.\n     *\n     * @return self<TValue>\n     */\n    public function not(): self\n    {\n        $this->opposite = true;\n\n        return $this;\n    }\n\n    /**\n     * Dynamically calls methods on the class with the given arguments on each item.\n     *\n     * @param  array<int|string, mixed>  $arguments\n     * @return self<TValue>\n     */\n    public function __call(string $name, array $arguments): self\n    {\n        foreach ($this->original->value as $item) {\n            /* @phpstan-ignore-next-line */\n            $this->opposite ? expect($item)->not()->$name(...$arguments) : expect($item)->$name(...$arguments);\n        }\n\n        $this->opposite = false;\n\n        return $this;\n    }\n\n    /**\n     * Dynamically calls methods on the class without any arguments on each item.\n     *\n     * @return self<TValue>\n     */\n    public function __get(string $name): self\n    {\n        /* @phpstan-ignore-next-line */\n        return $this->$name();\n    }\n}\n"
  },
  {
    "path": "src/Expectations/HigherOrderExpectation.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Expectations;\n\nuse Closure;\nuse Pest\\Concerns\\Retrievable;\nuse Pest\\Expectation;\n\n/**\n * @internal\n *\n * @template TOriginalValue\n * @template TValue\n *\n * @mixin Expectation<TOriginalValue>\n */\nfinal class HigherOrderExpectation\n{\n    use Retrievable;\n\n    /**\n     * @var Expectation<TValue>|EachExpectation<TValue>\n     */\n    private Expectation|EachExpectation $expectation;\n\n    /**\n     * Indicates if the expectation is the opposite.\n     */\n    private bool $opposite = false;\n\n    /**\n     * Indicates if the expectation should reset the value.\n     */\n    private bool $shouldReset = false;\n\n    /**\n     * Creates a new higher order expectation.\n     *\n     * @param  Expectation<TOriginalValue>  $original\n     * @param  TValue  $value\n     */\n    public function __construct(private readonly Expectation $original, mixed $value)\n    {\n        $this->expectation = $this->expect($value);\n    }\n\n    /**\n     * Creates the opposite expectation for the value.\n     *\n     * @return self<TOriginalValue, TValue>\n     */\n    public function not(): self\n    {\n        $this->opposite = ! $this->opposite;\n\n        return $this;\n    }\n\n    /**\n     * Creates a new Expectation.\n     *\n     * @template TExpectValue\n     *\n     * @param  TExpectValue  $value\n     * @return Expectation<TExpectValue>\n     */\n    public function expect(mixed $value): Expectation\n    {\n        return new Expectation($value);\n    }\n\n    /**\n     * Creates a new expectation.\n     *\n     * @template TExpectValue\n     *\n     * @param  TExpectValue  $value\n     * @return Expectation<TExpectValue>\n     */\n    public function and(mixed $value): Expectation\n    {\n        return $this->expect($value);\n    }\n\n    /**\n     * Scope an expectation callback to the current value in\n     * the HigherOrderExpectation chain.\n     *\n     * @param  Closure(Expectation<TValue>): void  $expectation\n     * @return HigherOrderExpectation<TOriginalValue, TOriginalValue>\n     */\n    public function scoped(Closure $expectation): self\n    {\n        $expectation->__invoke($this->expectation);\n\n        return new self($this->original, $this->original->value);\n    }\n\n    /**\n     * Creates a new expectation with the decoded JSON value.\n     *\n     * @return self<TOriginalValue, array<string|int, mixed>|bool>\n     */\n    public function json(): self\n    {\n        return new self($this->original, $this->expectation->json()->value);\n    }\n\n    /**\n     * Dynamically calls methods on the class with the given arguments.\n     *\n     * @param  array<int, mixed>  $arguments\n     * @return self<TOriginalValue, mixed>|self<TOriginalValue, TValue>\n     */\n    public function __call(string $name, array $arguments): self\n    {\n        if (! $this->expectationHasMethod($name)) {\n            /* @phpstan-ignore-next-line */\n            return new self($this->original, $this->getValue()->$name(...$arguments));\n        }\n\n        return $this->performAssertion($name, $arguments);\n    }\n\n    /**\n     * Accesses properties in the value or in the expectation.\n     *\n     * @return self<TOriginalValue, mixed>|self<TOriginalValue, TValue>\n     */\n    public function __get(string $name): self\n    {\n        if ($name === 'not') {\n            return $this->not();\n        }\n\n        if (! $this->expectationHasMethod($name)) {\n            /** @var array<string, mixed>|object $value */\n            $value = $this->getValue();\n\n            return new self($this->original, $this->retrieve($name, $value));\n        }\n\n        return $this->performAssertion($name, []);\n    }\n\n    /**\n     * Determines if the original expectation has the given method name.\n     */\n    private function expectationHasMethod(string $name): bool\n    {\n        if (method_exists($this->original, $name)) {\n            return true;\n        }\n        if ($this->original::hasMethod($name)) {\n            return true;\n        }\n\n        return $this->original::hasExtend($name);\n    }\n\n    /**\n     * Retrieve the applicable value based on the current reset condition.\n     *\n     * @return TOriginalValue|TValue\n     */\n    private function getValue(): mixed\n    {\n        return $this->shouldReset ? $this->original->value : $this->expectation->value;\n    }\n\n    /**\n     * Performs the given assertion with the current expectation.\n     *\n     * @param  array<int, mixed>  $arguments\n     * @return self<TOriginalValue, TValue>\n     */\n    private function performAssertion(string $name, array $arguments): self\n    {\n        /* @phpstan-ignore-next-line */\n        $this->expectation = ($this->opposite ? $this->expectation->not() : $this->expectation)->{$name}(...$arguments);\n\n        $this->opposite = false;\n        $this->shouldReset = true;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Expectations/OppositeExpectation.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Expectations;\n\nuse Attribute;\nuse Pest\\Arch\\Contracts\\ArchExpectation;\nuse Pest\\Arch\\Expectations\\Targeted;\nuse Pest\\Arch\\Expectations\\ToBeUsedIn;\nuse Pest\\Arch\\Expectations\\ToBeUsedInNothing;\nuse Pest\\Arch\\Expectations\\ToUse;\nuse Pest\\Arch\\GroupArchExpectation;\nuse Pest\\Arch\\PendingArchExpectation;\nuse Pest\\Arch\\SingleArchExpectation;\nuse Pest\\Arch\\Support\\FileLineFinder;\nuse Pest\\Exceptions\\InvalidExpectation;\nuse Pest\\Exceptions\\MissingDependency;\nuse Pest\\Expectation;\nuse Pest\\Support\\Arr;\nuse Pest\\Support\\Exporter;\nuse Pest\\Support\\Reflection;\nuse PHPUnit\\Architecture\\Elements\\ObjectDescription;\nuse PHPUnit\\Framework\\AssertionFailedError;\nuse PHPUnit\\Framework\\ExpectationFailedException;\nuse ReflectionMethod;\nuse ReflectionProperty;\nuse Spoofchecker;\nuse stdClass;\n\n/**\n * @internal\n *\n * @template TValue\n *\n * @mixin Expectation<TValue>\n */\nfinal readonly class OppositeExpectation\n{\n    /**\n     * Creates a new opposite expectation.\n     *\n     * @param  Expectation<TValue>  $original\n     */\n    public function __construct(private Expectation $original) {}\n\n    /**\n     * Asserts that the value array not has the provided $keys.\n     *\n     * @param  array<int, int|string|array<int-string, mixed>>  $keys\n     * @return Expectation<TValue>\n     */\n    public function toHaveKeys(array $keys): Expectation\n    {\n        foreach ($keys as $k => $key) {\n            try {\n                if (is_array($key)) {\n                    $this->toHaveKeys(array_keys(Arr::dot($key, $k.'.')));\n                } else {\n                    $this->original->toHaveKey($key);\n                }\n            } catch (ExpectationFailedException) {\n                continue;\n            }\n\n            $this->throwExpectationFailedException('toHaveKey', [$key]);\n        }\n\n        return $this->original;\n    }\n\n    /**\n     * Asserts that the given expectation target does not use any of the given dependencies.\n     *\n     * @param  array<int, string>|string  $targets\n     */\n    public function toUse(array|string $targets): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return GroupArchExpectation::fromExpectations($original, array_map(fn (string $target): SingleArchExpectation => ToUse::make($original, $target)->opposite(\n            fn () => $this->throwExpectationFailedException('toUse', $target),\n        ), is_string($targets) ? [$targets] : $targets));\n    }\n\n    /**\n     * Asserts that the given expectation target does not have the given permissions\n     */\n    public function toHaveFileSystemPermissions(string $permissions): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => substr(sprintf('%o', fileperms($object->path)), -4) !== $permissions,\n            sprintf('permissions not to be [%s]', $permissions),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),\n        );\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toHaveLineCountLessThan(): ArchExpectation\n    {\n        throw InvalidExpectation::fromMethods(['not', 'toHaveLineCountLessThan']);\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toHaveMethodsDocumented(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false\n                || array_filter(\n                    Reflection::getMethodsFromReflectionClass($object->reflectionClass),\n                    fn (ReflectionMethod $method): bool => (enum_exists($object->name) === false || in_array($method->name, ['from', 'tryFrom', 'cases'], true) === false)\n                        && realpath($method->getFileName() ?: '/') === realpath($object->path) // @phpstan-ignore-line\n                        && $method->getDocComment() !== false,\n                ) === [],\n            'to have methods without documentation / annotations',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))\n        );\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toHavePropertiesDocumented(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false\n                || array_filter(\n                    Reflection::getPropertiesFromReflectionClass($object->reflectionClass),\n                    fn (ReflectionProperty $property): bool => (enum_exists($object->name) === false || in_array($property->name, ['value', 'name'], true) === false)\n                        && realpath($property->getDeclaringClass()->getFileName() ?: '/') === realpath($object->path) // @phpstan-ignore-line\n                        && $property->isPromoted() === false\n                        && $property->getDocComment() !== false,\n                ) === [],\n            'to have properties without documentation / annotations',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target does not use the \"declare(strict_types=1)\" declaration.\n     */\n    public function toUseStrictTypes(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => ! (bool) preg_match('/^<\\?php\\s+declare\\(.*?strict_types\\s?=\\s?1.*?\\);/', (string) file_get_contents($object->path)),\n            'not to use strict types',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, '<?php')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target does not use the strict equality operator.\n     */\n    public function toUseStrictEquality(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => ! str_contains((string) file_get_contents($object->path), ' === ') && ! str_contains((string) file_get_contents($object->path), ' !== '),\n            'to use strict equality',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, ' === ') || str_contains($line, ' !== ')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target is not final.\n     */\n    public function toBeFinal(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => ! enum_exists($object->name) && (isset($object->reflectionClass) === false || ! $object->reflectionClass->isFinal()),\n            'not to be final',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target is not readonly.\n     */\n    public function toBeReadonly(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => ! enum_exists($object->name) && (isset($object->reflectionClass) === false || ! $object->reflectionClass->isReadOnly()) && assert(true), // @phpstan-ignore-line\n            'not to be readonly',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target is not trait.\n     */\n    public function toBeTrait(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isTrait(),\n            'not to be trait',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are not traits.\n     */\n    public function toBeTraits(): ArchExpectation\n    {\n        return $this->toBeTrait();\n    }\n\n    /**\n     * Asserts that the given expectation target is not abstract.\n     */\n    public function toBeAbstract(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isAbstract(),\n            'not to be abstract',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target does not have a specific method.\n     *\n     * @param  array<int, string>|string  $method\n     */\n    public function toHaveMethod(array|string $method): ArchExpectation\n    {\n        $methods = is_array($method) ? $method : [$method];\n\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => array_filter(\n                $methods,\n                fn (string $method): bool => isset($object->reflectionClass) === false || $object->reflectionClass->hasMethod($method),\n            ) === [],\n            'to not have methods: '.implode(', ', $methods),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target does not have suspicious characters.\n     */\n    public function toHaveSuspiciousCharacters(): ArchExpectation\n    {\n        if (! class_exists(Spoofchecker::class)) {\n            throw new MissingDependency(__FUNCTION__, 'ext-intl >= 2.0');\n        }\n\n        $checker = new Spoofchecker;\n\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => ! $checker->isSuspicious((string) file_get_contents($object->path)),\n            'to not include suspicious characters',\n            FileLineFinder::where(fn (string $line): bool => $checker->isSuspicious($line)),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target does not have the given methods.\n     *\n     * @param  array<int, string>  $methods\n     */\n    public function toHaveMethods(array $methods): ArchExpectation\n    {\n        return $this->toHaveMethod($methods);\n    }\n\n    /**\n     * Asserts that the given expectation target not to have the public methods besides the given methods.\n     *\n     * @param  array<int, string>|string  $methods\n     */\n    public function toHavePublicMethodsBesides(array|string $methods): ArchExpectation\n    {\n        $methods = is_array($methods) ? $methods : [$methods];\n\n        $state = new stdClass;\n\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            function (ObjectDescription $object) use ($methods, &$state): bool {\n                $reflectionMethods = isset($object->reflectionClass)\n                    ? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PUBLIC)\n                    : [];\n\n                foreach ($reflectionMethods as $reflectionMethod) {\n                    if (! in_array($reflectionMethod->name, $methods, true)) {\n                        $state->contains = 'public function '.$reflectionMethod->name;\n\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            $methods === []\n                ? 'not to have public methods'\n                : sprintf(\"not to have public methods besides '%s'\", implode(\"', '\", $methods)),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, (string) $state->contains)),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target not to have the public methods.\n     */\n    public function toHavePublicMethods(): ArchExpectation\n    {\n        return $this->toHavePublicMethodsBesides([]);\n    }\n\n    /**\n     * Asserts that the given expectation target not to have the protected methods besides the given methods.\n     *\n     * @param  array<int, string>|string  $methods\n     */\n    public function toHaveProtectedMethodsBesides(array|string $methods): ArchExpectation\n    {\n        $methods = is_array($methods) ? $methods : [$methods];\n\n        $state = new stdClass;\n\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            function (ObjectDescription $object) use ($methods, &$state): bool {\n                $reflectionMethods = isset($object->reflectionClass)\n                    ? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PROTECTED)\n                    : [];\n\n                foreach ($reflectionMethods as $reflectionMethod) {\n                    if (! in_array($reflectionMethod->name, $methods, true)) {\n                        $state->contains = 'protected function '.$reflectionMethod->name;\n\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            $methods === []\n                ? 'not to have protected methods'\n                : sprintf(\"not to have protected methods besides '%s'\", implode(\"', '\", $methods)),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, (string) $state->contains)),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target not to have the protected methods.\n     */\n    public function toHaveProtectedMethods(): ArchExpectation\n    {\n        return $this->toHaveProtectedMethodsBesides([]);\n    }\n\n    /**\n     * Asserts that the given expectation target not to have the private methods besides the given methods.\n     *\n     * @param  array<int, string>|string  $methods\n     */\n    public function toHavePrivateMethodsBesides(array|string $methods): ArchExpectation\n    {\n        $methods = is_array($methods) ? $methods : [$methods];\n\n        $state = new stdClass;\n\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            function (ObjectDescription $object) use ($methods, &$state): bool {\n                $reflectionMethods = isset($object->reflectionClass)\n                    ? Reflection::getMethodsFromReflectionClass($object->reflectionClass, ReflectionMethod::IS_PRIVATE)\n                    : [];\n\n                foreach ($reflectionMethods as $reflectionMethod) {\n                    if (! in_array($reflectionMethod->name, $methods, true)) {\n                        $state->contains = 'private function '.$reflectionMethod->name;\n\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            $methods === []\n                ? 'not to have private methods'\n                : sprintf(\"not to have private methods besides '%s'\", implode(\"', '\", $methods)),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, (string) $state->contains)),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target not to have the private methods.\n     */\n    public function toHavePrivateMethods(): ArchExpectation\n    {\n        return $this->toHavePrivateMethodsBesides([]);\n    }\n\n    /**\n     * Asserts that the given expectation target is not enum.\n     */\n    public function toBeEnum(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isEnum(),\n            'not to be enum',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are not enums.\n     */\n    public function toBeEnums(): ArchExpectation\n    {\n        return $this->toBeEnum();\n    }\n\n    /**\n     * Asserts that the given expectation targets is not class.\n     */\n    public function toBeClass(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => ! class_exists($object->name),\n            'not to be class',\n            FileLineFinder::where(fn (string $line): bool => true),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are not classes.\n     */\n    public function toBeClasses(): ArchExpectation\n    {\n        return $this->toBeClass();\n    }\n\n    /**\n     * Asserts that the given expectation target is not interface.\n     */\n    public function toBeInterface(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isInterface(),\n            'not to be interface',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are not interfaces.\n     */\n    public function toBeInterfaces(): ArchExpectation\n    {\n        return $this->toBeInterface();\n    }\n\n    /**\n     * Asserts that the given expectation target to be not subclass of the given class.\n     */\n    public function toExtend(string $class): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->isSubclassOf($class),\n            sprintf(\"not to extend '%s'\", $class),\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to be not have any parent class.\n     */\n    public function toExtendNothing(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getParentClass() !== false,\n            'to extend a class',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target not to use the given trait.\n     */\n    public function toUseTrait(string $trait): ArchExpectation\n    {\n        return $this->toUseTraits($trait);\n    }\n\n    /**\n     * Asserts that the given expectation target not to use the given traits.\n     *\n     * @param  array<int, string>|string  $traits\n     */\n    public function toUseTraits(array|string $traits): ArchExpectation\n    {\n        $traits = is_array($traits) ? $traits : [$traits];\n\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            function (ObjectDescription $object) use ($traits): bool {\n                foreach ($traits as $trait) {\n                    if (isset($object->reflectionClass) && in_array($trait, $object->reflectionClass->getTraitNames(), true)) {\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            \"not to use traits '\".implode(\"', '\", $traits).\"'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target not to implement the given interfaces.\n     *\n     * @param  array<int, string>|string  $interfaces\n     */\n    public function toImplement(array|string $interfaces): ArchExpectation\n    {\n        $interfaces = is_array($interfaces) ? $interfaces : [$interfaces];\n\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            function (ObjectDescription $object) use ($interfaces): bool {\n                foreach ($interfaces as $interface) {\n                    if (isset($object->reflectionClass) && $object->reflectionClass->implementsInterface($interface)) {\n                        return false;\n                    }\n                }\n\n                return true;\n            },\n            \"not to implement '\".implode(\"', '\", $interfaces).\"'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to not implement any interfaces.\n     */\n    public function toImplementNothing(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getInterfaceNames() !== [],\n            'to implement an interface',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toOnlyImplement(): void\n    {\n        throw InvalidExpectation::fromMethods(['not', 'toOnlyImplement']);\n    }\n\n    /**\n     * Asserts that the given expectation target to not have the given prefix.\n     */\n    public function toHavePrefix(string $prefix): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! str_starts_with($object->reflectionClass->getShortName(), $prefix),\n            \"not to have prefix '{$prefix}'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target to not have the given suffix.\n     */\n    public function toHaveSuffix(string $suffix): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! str_ends_with($object->reflectionClass->getName(), $suffix),\n            \"not to have suffix '{$suffix}'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toOnlyUse(): void\n    {\n        throw InvalidExpectation::fromMethods(['not', 'toOnlyUse']);\n    }\n\n    /**\n     * Not supported.\n     */\n    public function toUseNothing(): void\n    {\n        throw InvalidExpectation::fromMethods(['not', 'toUseNothing']);\n    }\n\n    /**\n     * Asserts that the given expectation dependency is not used.\n     */\n    public function toBeUsed(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return ToBeUsedInNothing::make($original);\n    }\n\n    /**\n     * Asserts that the given expectation dependency is not used by any of the given targets.\n     *\n     * @param  array<int, string>|string  $targets\n     */\n    public function toBeUsedIn(array|string $targets): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return GroupArchExpectation::fromExpectations($original, array_map(fn (string $target): GroupArchExpectation => ToBeUsedIn::make($original, $target)->opposite(\n            fn () => $this->throwExpectationFailedException('toBeUsedIn', $target),\n        ), is_string($targets) ? [$targets] : $targets));\n    }\n\n    public function toOnlyBeUsedIn(): void\n    {\n        throw InvalidExpectation::fromMethods(['not', 'toOnlyBeUsedIn']);\n    }\n\n    /**\n     * Asserts that the given expectation dependency is not used.\n     */\n    public function toBeUsedInNothing(): void\n    {\n        throw InvalidExpectation::fromMethods(['not', 'toBeUsedInNothing']);\n    }\n\n    /**\n     * Asserts that the given expectation dependency is not an invokable class.\n     */\n    public function toBeInvokable(): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || ! $object->reflectionClass->hasMethod('__invoke'),\n            'to not be invokable',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))\n        );\n    }\n\n    /**\n     * Asserts that the given expectation target not to have the given attribute.\n     */\n    public function toHaveAttribute(string $attribute): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false || $object->reflectionClass->getAttributes($attribute) === [],\n            \"to not have attribute '{$attribute}'\",\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class'))\n        );\n    }\n\n    /**\n     * Handle dynamic method calls into the original expectation.\n     *\n     * @param  array<int, mixed>  $arguments\n     * @return Expectation<TValue>|Expectation<mixed>|never\n     */\n    public function __call(string $name, array $arguments): Expectation\n    {\n        try {\n            if (! is_object($this->original->value) && method_exists(PendingArchExpectation::class, $name)) {\n                throw InvalidExpectation::fromMethods(['not', $name]);\n            }\n\n            /* @phpstan-ignore-next-line */\n            $this->original->{$name}(...$arguments);\n        } catch (ExpectationFailedException|AssertionFailedError) {\n            return $this->original;\n        }\n\n        $this->throwExpectationFailedException($name, $arguments);\n    }\n\n    /**\n     * Handle dynamic properties gets into the original expectation.\n     *\n     * @return Expectation<TValue>|Expectation<mixed>|never\n     */\n    public function __get(string $name): Expectation\n    {\n        try {\n            if (! is_object($this->original->value) && method_exists(PendingArchExpectation::class, $name)) {\n                throw InvalidExpectation::fromMethods(['not', $name]);\n            }\n\n            $this->original->{$name}; // @phpstan-ignore-line\n        } catch (ExpectationFailedException) {\n            return $this->original;\n        }\n\n        $this->throwExpectationFailedException($name);\n    }\n\n    /**\n     * Creates a new expectation failed exception with a nice readable message.\n     *\n     * @param  array<int, mixed>|string  $arguments\n     */\n    public function throwExpectationFailedException(string $name, array|string $arguments = []): never\n    {\n        $arguments = is_array($arguments) ? $arguments : [$arguments];\n\n        $exporter = Exporter::default();\n\n        $toString = fn (mixed $argument): string => $exporter->shortenedExport($argument);\n\n        throw new ExpectationFailedException(sprintf(\n            'Expecting %s not %s %s.',\n            $toString($this->original->value),\n            strtolower((string) preg_replace('/(?<!\\ )[A-Z]/', ' $0', $name)),\n            implode(' ', array_map(fn (mixed $argument): string => $toString($argument), $arguments)),\n        ));\n    }\n\n    /**\n     * Asserts that the given expectation target does not have a constructor method.\n     */\n    public function toHaveConstructor(): ArchExpectation\n    {\n        return $this->toHaveMethod('__construct');\n    }\n\n    /**\n     * Asserts that the given expectation target does not have a destructor method.\n     */\n    public function toHaveDestructor(): ArchExpectation\n    {\n        return $this->toHaveMethod('__destruct');\n    }\n\n    /**\n     * Asserts that the given expectation target is not a backed enum of given type.\n     */\n    private function toBeBackedEnum(string $backingType): ArchExpectation\n    {\n        /** @var Expectation<array<int, string>|string> $original */\n        $original = $this->original;\n\n        return Targeted::make(\n            $original,\n            fn (ObjectDescription $object): bool => isset($object->reflectionClass) === false\n                || ! $object->reflectionClass->isEnum()\n                || ! (new \\ReflectionEnum($object->name))->isBacked() // @phpstan-ignore-line\n                || (string) (new \\ReflectionEnum($object->name))->getBackingType() !== $backingType, // @phpstan-ignore-line\n            'not to be '.$backingType.' backed enum',\n            FileLineFinder::where(fn (string $line): bool => str_contains($line, 'class')),\n        );\n    }\n\n    /**\n     * Asserts that the given expectation targets are not string backed enums.\n     */\n    public function toBeStringBackedEnums(): ArchExpectation\n    {\n        return $this->toBeStringBackedEnum();\n    }\n\n    /**\n     * Asserts that the given expectation targets are not int backed enums.\n     */\n    public function toBeIntBackedEnums(): ArchExpectation\n    {\n        return $this->toBeIntBackedEnum();\n    }\n\n    /**\n     * Asserts that the given expectation target is not a string backed enum.\n     */\n    public function toBeStringBackedEnum(): ArchExpectation\n    {\n        return $this->toBeBackedEnum('string');\n    }\n\n    /**\n     * Asserts that the given expectation target is not an int backed enum.\n     */\n    public function toBeIntBackedEnum(): ArchExpectation\n    {\n        return $this->toBeBackedEnum('int');\n    }\n}\n"
  },
  {
    "path": "src/Factories/Attribute.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Factories;\n\n/**\n * @internal\n */\nfinal class Attribute\n{\n    /**\n     * @param  iterable<int, string>  $arguments\n     */\n    public function __construct(public string $name, public iterable $arguments)\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "src/Factories/Concerns/HigherOrderable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Factories\\Concerns;\n\nuse Pest\\Support\\HigherOrderMessageCollection;\n\ntrait HigherOrderable\n{\n    /**\n     * The higher order messages that are chainable.\n     */\n    public HigherOrderMessageCollection $chains;\n\n    /**\n     * The higher order messages that are \"factory\" proxyable.\n     */\n    public HigherOrderMessageCollection $factoryProxies;\n\n    /**\n     * The higher order messages that are proxyable.\n     */\n    public HigherOrderMessageCollection $proxies;\n\n    /**\n     * Boot the higher order properties.\n     */\n    private function bootHigherOrderable(): void\n    {\n        $this->chains = new HigherOrderMessageCollection;\n        $this->factoryProxies = new HigherOrderMessageCollection;\n        $this->proxies = new HigherOrderMessageCollection;\n    }\n}\n"
  },
  {
    "path": "src/Factories/Covers/CoversClass.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Factories\\Covers;\n\n/**\n * @internal\n */\nfinal class CoversClass\n{\n    public function __construct(public string $class) {}\n}\n"
  },
  {
    "path": "src/Factories/Covers/CoversFunction.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Factories\\Covers;\n\n/**\n * @internal\n */\nfinal class CoversFunction\n{\n    public function __construct(public string $function) {}\n}\n"
  },
  {
    "path": "src/Factories/TestCaseFactory.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Factories;\n\nuse ParseError;\nuse Pest\\Concerns;\nuse Pest\\Contracts\\HasPrintableTestCaseName;\nuse Pest\\Evaluators\\Attributes;\nuse Pest\\Exceptions\\DatasetMissing;\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse Pest\\Exceptions\\TestAlreadyExist;\nuse Pest\\Exceptions\\TestClosureMustNotBeStatic;\nuse Pest\\Exceptions\\TestDescriptionMissing;\nuse Pest\\Factories\\Concerns\\HigherOrderable;\nuse Pest\\Support\\Reflection;\nuse Pest\\Support\\Str;\nuse Pest\\TestSuite;\nuse PHPUnit\\Framework\\Attributes\\TestDox;\nuse PHPUnit\\Framework\\TestCase;\nuse RuntimeException;\n\n/**\n * @internal\n */\nfinal class TestCaseFactory\n{\n    use HigherOrderable;\n\n    /**\n     * The list of attributes.\n     *\n     * @var array<int, Attribute>\n     */\n    public array $attributes = [];\n\n    /**\n     * The FQN of the Test Case class.\n     *\n     * @var class-string\n     */\n    public string $class = TestCase::class;\n\n    /**\n     * The list of class methods.\n     *\n     * @var array<string, TestCaseMethodFactory>\n     */\n    public array $methods = [];\n\n    /**\n     * The list of class traits.\n     *\n     * @var array <int, class-string>\n     */\n    public array $traits = [\n        Concerns\\Testable::class,\n        Concerns\\Expectable::class,\n    ];\n\n    /**\n     * Creates a new Factory instance.\n     */\n    public function __construct(\n        public string $filename\n    ) {\n        $this->bootHigherOrderable();\n    }\n\n    public function make(): void\n    {\n        $methods = $this->methods;\n\n        if ($methods !== []) {\n            $this->evaluate($this->filename, $methods);\n        }\n    }\n\n    /**\n     * Creates a Test Case class using a runtime evaluate.\n     *\n     * @param  array<string, TestCaseMethodFactory>  $methods\n     */\n    public function evaluate(string $filename, array $methods): void\n    {\n        if ('\\\\' === DIRECTORY_SEPARATOR) {\n            // In case Windows, strtolower drive name, like in UsesCall.\n            $filename = (string) preg_replace_callback('~^(?P<drive>[a-z]+:\\\\\\)~i', static fn (array $match): string => strtolower($match['drive']), $filename);\n        }\n\n        $filename = str_replace('\\\\\\\\', '\\\\', addslashes((string) realpath($filename)));\n        $rootPath = TestSuite::getInstance()->rootPath;\n        $relativePath = str_replace($rootPath.DIRECTORY_SEPARATOR, '', $filename);\n\n        $relativePath = ltrim($relativePath, DIRECTORY_SEPARATOR);\n\n        $basename = basename($relativePath, '.php');\n\n        $dotPos = strpos($basename, '.');\n\n        if ($dotPos !== false) {\n            $basename = substr($basename, 0, $dotPos);\n        }\n\n        $relativePath = dirname(ucfirst($relativePath)).DIRECTORY_SEPARATOR.$basename;\n\n        $relativePath = str_replace(DIRECTORY_SEPARATOR, '\\\\', $relativePath);\n\n        // Strip out any %-encoded octets.\n        $relativePath = (string) preg_replace('|%[a-fA-F0-9][a-fA-F0-9]|', '', $relativePath);\n        // Remove escaped quote sequences (maintain namespace)\n        $relativePath = str_replace(array_map(fn (string $quote): string => sprintf('\\\\%s', $quote), ['\\'', '\"']), '', $relativePath);\n        // Limit to A-Z, a-z, 0-9, '_', '-'.\n        $relativePath = (string) preg_replace('/[^A-Za-z0-9\\\\\\\\]/', '', $relativePath);\n\n        $classFQN = 'P\\\\'.$relativePath;\n\n        if (class_exists($classFQN)) {\n            return;\n        }\n\n        $hasPrintableTestCaseClassFQN = sprintf('\\%s', HasPrintableTestCaseName::class);\n        $traitsCode = sprintf('use %s;', implode(', ', array_map(\n            static fn (string $trait): string => sprintf('\\%s', $trait), $this->traits))\n        );\n\n        $partsFQN = explode('\\\\', $classFQN);\n        $className = array_pop($partsFQN);\n        $namespace = implode('\\\\', $partsFQN);\n        $baseClass = sprintf('\\%s', $this->class);\n\n        if (trim($className) === '') {\n            $className = 'InvalidTestName'.Str::random();\n        }\n\n        $this->attributes = [\n            new Attribute(\n                TestDox::class,\n                [$this->filename],\n            ),\n            ...$this->attributes,\n        ];\n\n        $attributesCode = Attributes::code($this->attributes);\n\n        $methodsCode = implode('', array_map(\n            fn (TestCaseMethodFactory $methodFactory): string => $methodFactory->buildForEvaluation(),\n            $methods\n        ));\n\n        try {\n            $classCode = <<<PHP\n            namespace $namespace;\n\n            use Pest\\Repositories\\DatasetsRepository as __PestDatasets;\n            use Pest\\TestSuite as __PestTestSuite;\n\n            $attributesCode\n            #[\\AllowDynamicProperties]\n            final class $className extends $baseClass implements $hasPrintableTestCaseClassFQN {\n                $traitsCode\n\n                private static \\$__filename = '$filename';\n\n                $methodsCode\n            }\n            PHP;\n\n            eval($classCode);\n        } catch (ParseError $caught) {\n            throw new RuntimeException(sprintf(\n                \"Unable to create test case for test file at %s. \\n %s\",\n                $filename,\n                $classCode\n            ), 1, $caught);\n        }\n    }\n\n    /**\n     * Adds the given Method to the Test Case.\n     */\n    public function addMethod(TestCaseMethodFactory $method): void\n    {\n        if ($method->description === null) {\n            throw new TestDescriptionMissing($method->filename);\n        }\n\n        if (array_key_exists($method->description, $this->methods)) {\n            throw new TestAlreadyExist($method->filename, $method->description);\n        }\n\n        if (\n            $method->closure instanceof \\Closure &&\n            (new \\ReflectionFunction($method->closure))->isStatic()\n        ) {\n\n            throw new TestClosureMustNotBeStatic($method);\n        }\n\n        if (! $method->receivesArguments()) {\n            if (! $method->closure instanceof \\Closure) {\n                throw ShouldNotHappen::fromMessage('The test closure may not be empty.');\n            }\n\n            $arguments = Reflection::getFunctionArguments($method->closure);\n\n            if ($arguments !== []) {\n                throw new DatasetMissing($method->filename, $method->description, $arguments);\n            }\n        }\n\n        $this->methods[$method->description] = $method;\n    }\n\n    /**\n     * Checks if a test case has a method.\n     */\n    public function hasMethod(string $methodName): bool\n    {\n        foreach ($this->methods as $method) {\n            if ($method->description === null) {\n                throw ShouldNotHappen::fromMessage('The test description may not be empty.');\n            }\n\n            if ($methodName === Str::evaluable($method->description)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Gets a Method by the given name.\n     */\n    public function getMethod(string $methodName): TestCaseMethodFactory\n    {\n        foreach ($this->methods as $method) {\n            if ($method->description === null) {\n                throw ShouldNotHappen::fromMessage('The test description may not be empty.');\n            }\n\n            if ($methodName === Str::evaluable($method->description)) {\n                return $method;\n            }\n        }\n\n        throw ShouldNotHappen::fromMessage(sprintf('Method %s not found.', $methodName));\n    }\n}\n"
  },
  {
    "path": "src/Factories/TestCaseMethodFactory.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Factories;\n\nuse Closure;\nuse Pest\\Evaluators\\Attributes;\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse Pest\\Factories\\Concerns\\HigherOrderable;\nuse Pest\\Repositories\\DatasetsRepository;\nuse Pest\\Support\\Description;\nuse Pest\\Support\\Str;\nuse Pest\\TestSuite;\nuse PHPUnit\\Framework\\Assert;\nuse PHPUnit\\Framework\\Attributes\\DataProvider;\nuse PHPUnit\\Framework\\Attributes\\Depends;\nuse PHPUnit\\Framework\\Attributes\\Test;\nuse PHPUnit\\Framework\\Attributes\\TestDox;\nuse PHPUnit\\Framework\\TestCase;\n\n/**\n * @internal\n */\nfinal class TestCaseMethodFactory\n{\n    use HigherOrderable;\n\n    /**\n     * The list of attributes.\n     *\n     * @var array<int, Attribute>\n     */\n    public array $attributes = [];\n\n    /**\n     * The test's describing, if any.\n     *\n     * @var array<int, Description>\n     */\n    public array $describing = [];\n\n    /**\n     * The test's description, if any.\n     */\n    public ?string $description = null;\n\n    /**\n     * The test's number of repetitions.\n     */\n    public int $repetitions = 1;\n\n    /**\n     * Determines if the test is a \"todo\".\n     */\n    public bool $todo = false;\n\n    /**\n     * The associated issue numbers.\n     *\n     * @var array<int, int>\n     */\n    public array $issues = [];\n\n    /**\n     * The test assignees.\n     *\n     * @var array<int, string>\n     */\n    public array $assignees = [];\n\n    /**\n     * The associated PRs numbers.\n     *\n     * @var array<int, int>\n     */\n    public array $prs = [];\n\n    /**\n     * The test's notes.\n     *\n     * @var array<int, string>\n     */\n    public array $notes = [];\n\n    /**\n     * The test's datasets.\n     *\n     * @var array<Closure|iterable<int|string, mixed>|string>\n     */\n    public array $datasets = [];\n\n    /**\n     * The test's dependencies.\n     *\n     * @var array<int, string>\n     */\n    public array $depends = [];\n\n    /**\n     * The test's groups.\n     *\n     * @var array<int, string>\n     */\n    public array $groups = [];\n\n    /**\n     * @see This property is not actually used in the codebase, it's only here to make Rector happy.\n     */\n    public bool $__ran = false;\n\n    /**\n     * Creates a new test case method factory instance.\n     */\n    public function __construct(\n        public string $filename,\n        public ?Closure $closure,\n    ) {\n        $this->closure ??= function (): void {\n            (Assert::getCount() > 0 || $this->doesNotPerformAssertions()) ?: self::markTestIncomplete(); // @phpstan-ignore-line\n        };\n\n        $this->bootHigherOrderable();\n    }\n\n    /**\n     * Sets the test's hooks, and runs any proxy to the test case.\n     */\n    public function setUp(TestCase $concrete): void\n    {\n        $concrete::flush(); // @phpstan-ignore-line\n\n        if ($this->description === null) {\n            throw ShouldNotHappen::fromMessage('Description can not be empty.');\n        }\n\n        $testCase = TestSuite::getInstance()->tests->get($this->filename);\n\n        assert($testCase instanceof TestCaseFactory);\n        $testCase->factoryProxies->proxy($concrete);\n        $this->factoryProxies->proxy($concrete);\n    }\n\n    /**\n     * Flushes the test case.\n     */\n    public function tearDown(TestCase $concrete): void\n    {\n        $concrete::flush(); // @phpstan-ignore-line\n    }\n\n    /**\n     * Creates the test's closure.\n     */\n    public function getClosure(): Closure\n    {\n        $closure = $this->closure;\n        $testCase = TestSuite::getInstance()->tests->get($this->filename);\n        assert($testCase instanceof TestCaseFactory);\n        $method = $this;\n\n        return function (...$arguments) use ($testCase, $method, $closure): mixed {\n            /* @var TestCase $this */\n            $testCase->proxies->proxy($this);\n            $method->proxies->proxy($this);\n\n            $testCase->chains->chain($this);\n            $method->chains->chain($this);\n\n            $this->__ran = true;\n\n            return \\Pest\\Support\\Closure::bind($closure, $this, self::class)(...$arguments);\n        };\n    }\n\n    /**\n     * Determine if the test case will receive argument input from Pest, or not.\n     */\n    public function receivesArguments(): bool\n    {\n        return $this->datasets !== [] || $this->depends !== [] || $this->repetitions > 1;\n    }\n\n    /**\n     * Creates a PHPUnit method as a string ready for evaluation.\n     */\n    public function buildForEvaluation(): string\n    {\n        if ($this->description === null) {\n            throw ShouldNotHappen::fromMessage('The test description may not be empty.');\n        }\n\n        $methodName = Str::evaluable($this->description);\n\n        $datasetsCode = '';\n\n        $this->attributes = [\n            new Attribute(\n                Test::class,\n                [],\n            ),\n            new Attribute(\n                TestDox::class,\n                [str_replace('*/', '{@*}', $this->description)],\n            ),\n            ...$this->attributes,\n        ];\n\n        foreach ($this->depends as $depend) {\n            $depend = Str::evaluable($this->describing === [] ? $depend : Str::describe($this->describing, $depend));\n\n            $this->attributes[] = new Attribute(\n                Depends::class,\n                [$depend],\n            );\n        }\n\n        if ($this->datasets !== [] || $this->repetitions > 1) {\n            $dataProviderName = $methodName.'_dataset';\n            $this->attributes[] = new Attribute(\n                DataProvider::class,\n                [$dataProviderName],\n            );\n            $datasetsCode = $this->buildDatasetForEvaluation($methodName, $dataProviderName);\n        }\n\n        $attributesCode = Attributes::code($this->attributes);\n\n        return <<<PHP\n            $attributesCode\n                public function $methodName(...\\$arguments)\n                {\n                    return \\$this->__runTest(\n                        \\$this->__test,\n                        ...\\$arguments,\n                    );\n                }\n            $datasetsCode\n            PHP;\n    }\n\n    /**\n     * Creates a PHPUnit Data Provider as a string ready for evaluation.\n     */\n    private function buildDatasetForEvaluation(string $methodName, string $dataProviderName): string\n    {\n        $datasets = $this->datasets;\n\n        if ($this->repetitions > 1) {\n            $datasets = [range(1, $this->repetitions), ...$datasets];\n        }\n\n        DatasetsRepository::with($this->filename, $methodName, $datasets);\n\n        return <<<EOF\n\n                public static function $dataProviderName()\n                {\n                    return __PestDatasets::get(self::\\$__filename, \"$methodName\");\n                }\n\n        EOF;\n    }\n}\n"
  },
  {
    "path": "src/Functions.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nuse Pest\\Browser\\Api\\ArrayablePendingAwaitablePage;\nuse Pest\\Browser\\Api\\PendingAwaitablePage;\nuse Pest\\Concerns\\Expectable;\nuse Pest\\Configuration;\nuse Pest\\Exceptions\\AfterAllWithinDescribe;\nuse Pest\\Exceptions\\BeforeAllWithinDescribe;\nuse Pest\\Expectation;\nuse Pest\\Installers\\PluginBrowser;\nuse Pest\\Mutate\\Contracts\\MutationTestRunner;\nuse Pest\\Mutate\\Repositories\\ConfigurationRepository;\nuse Pest\\PendingCalls\\AfterEachCall;\nuse Pest\\PendingCalls\\BeforeEachCall;\nuse Pest\\PendingCalls\\DescribeCall;\nuse Pest\\PendingCalls\\TestCall;\nuse Pest\\PendingCalls\\UsesCall;\nuse Pest\\Repositories\\DatasetsRepository;\nuse Pest\\Support\\Backtrace;\nuse Pest\\Support\\Container;\nuse Pest\\Support\\DatasetInfo;\nuse Pest\\Support\\Description;\nuse Pest\\Support\\HigherOrderTapProxy;\nuse Pest\\TestSuite;\nuse PHPUnit\\Framework\\TestCase;\n\nif (! function_exists('expect')) {\n    /**\n     * Creates a new expectation.\n     *\n     * @template TValue\n     *\n     * @param  TValue|null  $value\n     * @return Expectation<TValue|null>\n     */\n    function expect(mixed $value = null): Expectation\n    {\n        return new Expectation($value);\n    }\n}\n\nif (! function_exists('beforeAll')) {\n    /**\n     * Runs the given closure before all tests in the current file.\n     */\n    function beforeAll(Closure $closure): void\n    {\n        if (DescribeCall::describing() !== []) {\n            $filename = Backtrace::file();\n\n            throw new BeforeAllWithinDescribe($filename);\n        }\n\n        TestSuite::getInstance()->beforeAll->set($closure);\n    }\n}\n\nif (! function_exists('beforeEach')) {\n    /**\n     * Runs the given closure before each test in the current file.\n     *\n     * @param-closure-this TestCase  $closure\n     *\n     * @return HigherOrderTapProxy<Expectable|TestCall|TestCase>|Expectable|TestCall|TestCase|mixed\n     */\n    function beforeEach(?Closure $closure = null): BeforeEachCall\n    {\n        $filename = Backtrace::file();\n\n        return new BeforeEachCall(TestSuite::getInstance(), $filename, $closure);\n    }\n}\n\nif (! function_exists('dataset')) {\n    /**\n     * Registers the given dataset.\n     *\n     * @param  Closure|iterable<int|string, mixed>  $dataset\n     */\n    function dataset(string $name, Closure|iterable $dataset): void\n    {\n        $scope = DatasetInfo::scope(Backtrace::datasetsFile());\n\n        DatasetsRepository::set($name, $dataset, $scope);\n    }\n}\n\nif (! function_exists('describe')) {\n    /**\n     * Adds the given closure as a group of tests. The first argument\n     * is the group description; the second argument is a closure\n     * that contains the group tests.\n     *\n     * @return HigherOrderTapProxy<Expectable|TestCall|TestCase>|Expectable|TestCall|TestCase|mixed\n     */\n    function describe(string $description, Closure $tests): DescribeCall\n    {\n        $filename = Backtrace::testFile();\n\n        return new DescribeCall(TestSuite::getInstance(), $filename, new Description($description), $tests);\n    }\n}\n\nif (! function_exists('uses')) {\n    /**\n     * The uses function binds the given\n     * arguments to test closures.\n     *\n     * @param  class-string  ...$classAndTraits\n     */\n    function uses(string ...$classAndTraits): UsesCall\n    {\n        $filename = Backtrace::file();\n\n        return new UsesCall($filename, array_values($classAndTraits));\n    }\n}\n\nif (! function_exists('pest')) {\n    /**\n     * Creates a new Pest configuration instance.\n     */\n    function pest(): Configuration\n    {\n        return new Configuration(Backtrace::file());\n    }\n}\n\nif (! function_exists('test')) {\n    /**\n     * Adds the given closure as a test. The first argument\n     * is the test description; the second argument is\n     * a closure that contains the test expectations.\n     *\n     * @param-closure-this TestCase  $closure\n     *\n     * @return Expectable|TestCall|TestCase|mixed\n     */\n    function test(?string $description = null, ?Closure $closure = null): HigherOrderTapProxy|TestCall\n    {\n        if ($description === null && TestSuite::getInstance()->test instanceof TestCase) {\n            return new HigherOrderTapProxy(TestSuite::getInstance()->test);\n        }\n\n        $filename = Backtrace::testFile();\n\n        return new TestCall(TestSuite::getInstance(), $filename, $description, $closure);\n    }\n}\n\nif (! function_exists('it')) {\n    /**\n     * Adds the given closure as a test. The first argument\n     * is the test description; the second argument is\n     * a closure that contains the test expectations.\n     *\n     * @param-closure-this TestCase  $closure\n     *\n     * @return Expectable|TestCall|TestCase|mixed\n     */\n    function it(string $description, ?Closure $closure = null): TestCall\n    {\n        $description = sprintf('it %s', $description);\n\n        /** @var TestCall $test */\n        $test = test($description, $closure);\n\n        return $test;\n    }\n}\n\nif (! function_exists('todo')) {\n    /**\n     * Creates a new test that is marked as \"todo\".\n     *\n     * @return Expectable|TestCall|TestCase|mixed\n     */\n    function todo(string $description): TestCall\n    {\n        $test = test($description);\n\n        assert($test instanceof TestCall);\n\n        return $test->todo();\n    }\n}\n\nif (! function_exists('afterEach')) {\n    /**\n     * Runs the given closure after each test in the current file.\n     *\n     * @param-closure-this TestCase  $closure\n     *\n     * @return Expectable|HigherOrderTapProxy<Expectable|TestCall|TestCase>|TestCall|mixed\n     */\n    function afterEach(?Closure $closure = null): AfterEachCall\n    {\n        $filename = Backtrace::file();\n\n        return new AfterEachCall(TestSuite::getInstance(), $filename, $closure);\n    }\n}\n\nif (! function_exists('afterAll')) {\n    /**\n     * Runs the given closure after all tests in the current file.\n     */\n    function afterAll(Closure $closure): void\n    {\n        if (DescribeCall::describing() !== []) {\n            $filename = Backtrace::file();\n\n            throw new AfterAllWithinDescribe($filename);\n        }\n\n        TestSuite::getInstance()->afterAll->set($closure);\n    }\n}\n\nif (! function_exists('covers')) {\n    /**\n     * Specifies which classes, or functions, a test case covers.\n     *\n     * @param  array<int, string>|string  $classesOrFunctions\n     */\n    function covers(array|string ...$classesOrFunctions): void\n    {\n        $filename = Backtrace::file();\n\n        $beforeEachCall = (new BeforeEachCall(TestSuite::getInstance(), $filename));\n\n        $beforeEachCall->covers(...$classesOrFunctions);\n        $beforeEachCall->group('__pest_mutate_only');\n\n        /** @var MutationTestRunner $runner */\n        $runner = Container::getInstance()->get(MutationTestRunner::class);\n        /** @var ConfigurationRepository $configurationRepository */\n        $configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);\n        $everything = $configurationRepository->cliConfiguration->toArray()['everything'] ?? false;\n        $classes = $configurationRepository->cliConfiguration->toArray()['classes'] ?? false;\n        $paths = $configurationRepository->cliConfiguration->toArray()['paths'] ?? false;\n\n        if ($runner->isEnabled() && ! $everything && ! is_array($classes) && ! is_array($paths)) {\n            $beforeEachCall->only('__pest_mutate_only');\n        }\n    }\n}\n\nif (! function_exists('mutates')) {\n    /**\n     * Specifies which classes, enums, or traits a test case mutates.\n     *\n     * @param  array<int, string>|string  $targets\n     */\n    function mutates(array|string ...$targets): void\n    {\n        $filename = Backtrace::file();\n\n        $beforeEachCall = (new BeforeEachCall(TestSuite::getInstance(), $filename));\n        $beforeEachCall->group('__pest_mutate_only');\n\n        /** @var MutationTestRunner $runner */\n        $runner = Container::getInstance()->get(MutationTestRunner::class);\n        /** @var ConfigurationRepository $configurationRepository */\n        $configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);\n        $everything = $configurationRepository->cliConfiguration->toArray()['everything'] ?? false;\n        $classes = $configurationRepository->cliConfiguration->toArray()['classes'] ?? false;\n        $paths = $configurationRepository->cliConfiguration->toArray()['paths'] ?? false;\n\n        if ($runner->isEnabled() && ! $everything && ! is_array($classes) && ! is_array($paths)) {\n            $beforeEachCall->only('__pest_mutate_only');\n        }\n\n        /** @var ConfigurationRepository $configurationRepository */\n        $configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);\n        $paths = $configurationRepository->cliConfiguration->toArray()['paths'] ?? false;\n\n        if (! is_array($paths)) {\n            $configurationRepository->globalConfiguration('default')->class(...$targets); // @phpstan-ignore-line\n        }\n    }\n}\n\nif (! function_exists('fixture')) {\n    /**\n     * Returns the absolute path to a fixture file.\n     */\n    function fixture(string $file): string\n    {\n        $file = implode(DIRECTORY_SEPARATOR, [\n            TestSuite::getInstance()->rootPath,\n            TestSuite::getInstance()->testPath,\n            'Fixtures',\n            str_replace(['/', '\\\\'], DIRECTORY_SEPARATOR, $file),\n        ]);\n\n        $fileRealPath = realpath($file);\n\n        if ($fileRealPath === false) {\n            throw new InvalidArgumentException(\n                'The fixture file ['.$file.'] does not exist.',\n            );\n        }\n\n        return $fileRealPath;\n    }\n}\n\nif (! function_exists('visit')) {\n    /**\n     * Browse to the given URL.\n     *\n     * @template TUrl of array<int, string>|string\n     *\n     * @param  TUrl  $url\n     * @param  array<string, mixed>  $options\n     * @return (TUrl is array<int, string> ? ArrayablePendingAwaitablePage : PendingAwaitablePage)\n     */\n    function visit(array|string $url, array $options = []): ArrayablePendingAwaitablePage|PendingAwaitablePage\n    {\n        if (! class_exists(Pest\\Browser\\Configuration::class)) {\n            PluginBrowser::install();\n\n            exit(0);\n        }\n\n        // @phpstan-ignore-next-line\n        return test()->visit($url, $options);\n    }\n}\n"
  },
  {
    "path": "src/Installers/PluginBrowser.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Installers;\n\nuse Pest\\Support\\View;\n\nfinal readonly class PluginBrowser\n{\n    public static function install(): void\n    {\n        View::render('installers/plugin-browser');\n    }\n}\n"
  },
  {
    "path": "src/Kernel.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nuse NunoMaduro\\Collision\\Writer;\nuse Pest\\Contracts\\Bootstrapper;\nuse Pest\\Exceptions\\FatalException;\nuse Pest\\Exceptions\\NoDirtyTestsFound;\nuse Pest\\Plugins\\Actions\\CallsAddsOutput;\nuse Pest\\Plugins\\Actions\\CallsBoot;\nuse Pest\\Plugins\\Actions\\CallsHandleArguments;\nuse Pest\\Plugins\\Actions\\CallsHandleOriginalArguments;\nuse Pest\\Plugins\\Actions\\CallsTerminable;\nuse Pest\\Support\\Container;\nuse Pest\\Support\\Reflection;\nuse Pest\\Support\\View;\nuse PHPUnit\\TestRunner\\TestResult\\Facade;\nuse PHPUnit\\TextUI\\Application;\nuse PHPUnit\\TextUI\\Configuration\\Registry;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Throwable;\nuse Whoops\\Exception\\Inspector;\n\n/**\n * @internal\n */\nfinal readonly class Kernel\n{\n    /**\n     * The Kernel bootstrappers.\n     *\n     * @var array<int, class-string>\n     */\n    private const array BOOTSTRAPPERS = [\n        Bootstrappers\\BootOverrides::class,\n        Bootstrappers\\BootSubscribers::class,\n        Bootstrappers\\BootFiles::class,\n        Bootstrappers\\BootView::class,\n        Bootstrappers\\BootKernelDump::class,\n        Bootstrappers\\BootExcludeList::class,\n    ];\n\n    /**\n     * Creates a new Kernel instance.\n     */\n    public function __construct(\n        private Application $application,\n        private OutputInterface $output,\n    ) {\n        //\n    }\n\n    /**\n     * Boots the Kernel.\n     */\n    public static function boot(TestSuite $testSuite, InputInterface $input, OutputInterface $output): self\n    {\n        $container = Container::getInstance();\n\n        $container\n            ->add(TestSuite::class, $testSuite)\n            ->add(InputInterface::class, $input)\n            ->add(OutputInterface::class, $output)\n            ->add(Container::class, $container);\n\n        $kernel = new self(\n            new Application,\n            $output,\n        );\n\n        register_shutdown_function($kernel->shutdown(...));\n\n        foreach (self::BOOTSTRAPPERS as $bootstrapper) {\n            $bootstrapper = Container::getInstance()->get($bootstrapper);\n            assert($bootstrapper instanceof Bootstrapper);\n\n            $bootstrapper->boot();\n        }\n\n        CallsBoot::execute();\n\n        Container::getInstance()->add(self::class, $kernel);\n\n        return $kernel;\n    }\n\n    /**\n     * Runs the application, and returns the exit code.\n     *\n     * @param  array<int, string>  $originalArguments\n     * @param  array<int, string>  $arguments\n     */\n    public function handle(array $originalArguments, array $arguments): int\n    {\n        CallsHandleOriginalArguments::execute($originalArguments);\n\n        $arguments = CallsHandleArguments::execute($arguments);\n\n        try {\n            $this->application->run($arguments);\n        } catch (NoDirtyTestsFound) {\n            $this->output->writeln([\n                '',\n                '  <fg=white;options=bold;bg=blue> INFO </> No tests found.',\n                '',\n            ]);\n        }\n\n        $configuration = Registry::get();\n        $result = Facade::result();\n\n        return CallsAddsOutput::execute(\n            Result::exitCode($configuration, $result),\n        );\n    }\n\n    /**\n     * Terminate the Kernel.\n     */\n    public function terminate(): void\n    {\n        $preBufferOutput = Container::getInstance()->get(KernelDump::class);\n\n        assert($preBufferOutput instanceof KernelDump);\n\n        $preBufferOutput->terminate();\n\n        CallsTerminable::execute();\n    }\n\n    /**\n     * Shutdowns unexpectedly the Kernel.\n     */\n    public function shutdown(): void\n    {\n        $this->terminate();\n\n        if (is_array($error = error_get_last())) {\n            if (! in_array($error['type'], [E_ERROR, E_CORE_ERROR], true)) {\n                return;\n            }\n\n            $message = $error['message'];\n            $file = $error['file'];\n            $line = $error['line'];\n\n            try {\n                $writer = new Writer(null, $this->output);\n\n                $throwable = new FatalException($message);\n\n                Reflection::setPropertyValue($throwable, 'line', $line);\n                Reflection::setPropertyValue($throwable, 'file', $file);\n\n                $inspector = new Inspector($throwable);\n\n                $writer->write($inspector);\n            } catch (Throwable) { // @phpstan-ignore-line\n                View::render('components.badge', [\n                    'type' => 'ERROR',\n                    'content' => sprintf('%s in %s:%d', $message, $file, $line),\n                ]);\n            }\n\n            exit(1);\n        }\n    }\n}\n"
  },
  {
    "path": "src/KernelDump.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nuse Pest\\Support\\View;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\nfinal class KernelDump\n{\n    /**\n     * The output buffer, if any.\n     */\n    private string $buffer = '';\n\n    /**\n     * Creates a new Kernel Dump instance.\n     */\n    public function __construct(\n        private readonly OutputInterface $output,\n    ) {\n        // ...\n    }\n\n    /**\n     * Enable the output buffering.\n     */\n    public function enable(): void\n    {\n        ob_start(function (string $message): string {\n            $this->buffer .= $message;\n\n            return '';\n        });\n    }\n\n    /**\n     * Disable the output buffering.\n     */\n    public function disable(): void\n    {\n        @ob_clean();\n\n        if ($this->buffer !== '') {\n            $this->flush();\n        }\n    }\n\n    /**\n     * Terminate the output buffering.\n     */\n    public function terminate(): void\n    {\n        $this->disable();\n    }\n\n    /**\n     * Flushes the buffer.\n     */\n    private function flush(): void\n    {\n        View::renderUsing($this->output);\n\n        if ($this->isOpeningHeadline($this->buffer)) {\n            $this->buffer = implode(PHP_EOL, array_slice(explode(PHP_EOL, $this->buffer), 2));\n        }\n\n        $type = 'INFO';\n\n        if ($this->isInternalError($this->buffer)) {\n            $type = 'ERROR';\n            $this->buffer = str_replace(\n                sprintf('An error occurred inside PHPUnit.%s%sMessage:  ', PHP_EOL, PHP_EOL), '', $this->buffer,\n            );\n        }\n\n        $this->buffer = trim($this->buffer);\n        $this->buffer = rtrim($this->buffer, '.').'.';\n\n        $lines = explode(PHP_EOL, $this->buffer);\n\n        $lines = array_reverse($lines);\n        $firstLine = array_pop($lines);\n        $lines = array_reverse($lines);\n\n        View::render('components.badge', [\n            'type' => $type,\n            'content' => $firstLine,\n        ]);\n\n        $this->output->writeln($lines);\n\n        $this->buffer = '';\n    }\n\n    /**\n     * Checks if the given output contains an opening headline.\n     */\n    private function isOpeningHeadline(string $output): bool\n    {\n        return str_contains($output, 'by Sebastian Bergmann and contributors.');\n    }\n\n    /**\n     * Checks if the given output contains an opening headline.\n     */\n    private function isInternalError(string $output): bool\n    {\n        return str_contains($output, 'An error occurred inside PHPUnit.')\n            || str_contains($output, 'Fatal error');\n    }\n}\n"
  },
  {
    "path": "src/Logging/Converter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging;\n\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\State;\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse Pest\\Support\\StateGenerator;\nuse Pest\\Support\\Str;\nuse PHPUnit\\Event\\Code\\Test;\nuse PHPUnit\\Event\\Code\\TestMethod;\nuse PHPUnit\\Event\\Code\\Throwable;\nuse PHPUnit\\Event\\Test\\AfterLastTestMethodErrored;\nuse PHPUnit\\Event\\Test\\BeforeFirstTestMethodErrored;\nuse PHPUnit\\Event\\Test\\ConsideredRisky;\nuse PHPUnit\\Event\\Test\\Errored;\nuse PHPUnit\\Event\\Test\\Failed;\nuse PHPUnit\\Event\\Test\\MarkedIncomplete;\nuse PHPUnit\\Event\\Test\\Skipped;\nuse PHPUnit\\Event\\TestSuite\\TestSuite;\nuse PHPUnit\\Event\\TestSuite\\TestSuiteForTestMethodWithDataProvider;\nuse PHPUnit\\Framework\\Exception as FrameworkException;\nuse PHPUnit\\TestRunner\\TestResult\\TestResult as PhpUnitTestResult;\n\n/**\n * @internal\n */\nfinal readonly class Converter\n{\n    /**\n     * The prefix for the test suite name.\n     */\n    private const string PREFIX = 'P\\\\';\n\n    /**\n     *  The state generator.\n     */\n    private StateGenerator $stateGenerator;\n\n    /**\n     * Creates a new instance of the Converter.\n     */\n    public function __construct(\n        private string $rootPath,\n    ) {\n        $this->stateGenerator = new StateGenerator;\n    }\n\n    /**\n     * Gets the test case method name.\n     */\n    public function getTestCaseMethodName(Test $test): string\n    {\n        if (! $test instanceof TestMethod) {\n            throw ShouldNotHappen::fromMessage('Not an instance of TestMethod');\n        }\n\n        return $test->testDox()->prettifiedMethodName();\n    }\n\n    /**\n     * Gets the test case location.\n     */\n    public function getTestCaseLocation(Test $test): string\n    {\n        if (! $test instanceof TestMethod) {\n            throw ShouldNotHappen::fromMessage('Not an instance of TestMethod');\n        }\n\n        $path = $test->testDox()->prettifiedClassName();\n        $relativePath = $this->toRelativePath($path);\n\n        // TODO: Get the description without the dataset.\n        $description = $test->testDox()->prettifiedMethodName();\n\n        return \"$relativePath::$description\";\n    }\n\n    /**\n     * Gets the exception message.\n     */\n    public function getExceptionMessage(Throwable $throwable): string\n    {\n        if (is_a($throwable->className(), FrameworkException::class, true)) {\n            return $throwable->message();\n        }\n\n        $buffer = $throwable->className();\n        $throwableMessage = $throwable->message();\n\n        if ($throwableMessage !== '') {\n            $buffer .= \": $throwableMessage\";\n        }\n\n        return $buffer;\n    }\n\n    /**\n     * Gets the exception details.\n     */\n    public function getExceptionDetails(Throwable $throwable): string\n    {\n        $buffer = $this->getStackTrace($throwable);\n\n        while ($throwable->hasPrevious()) {\n            $throwable = $throwable->previous();\n\n            $buffer .= sprintf(\n                \"\\nCaused by\\n%s\\n%s\",\n                $throwable->description(),\n                $this->getStackTrace($throwable)\n            );\n        }\n\n        return $buffer;\n    }\n\n    /**\n     * Gets the stack trace.\n     */\n    public function getStackTrace(Throwable $throwable): string\n    {\n        $stackTrace = $throwable->stackTrace();\n\n        // Split stacktrace per frame.\n        $frames = explode(\"\\n\", $stackTrace);\n\n        // Remove empty lines\n        $frames = array_filter($frames);\n\n        // clean the paths of each frame.\n        $frames = array_map(\n            $this->toRelativePath(...),\n            $frames\n        );\n\n        // Format stacktrace as `at <path>`\n        $frames = array_map(\n            fn (string $frame): string => \"at $frame\",\n            $frames\n        );\n\n        return implode(\"\\n\", $frames);\n    }\n\n    /**\n     * Gets the test suite name.\n     */\n    public function getTestSuiteName(TestSuite $testSuite): string\n    {\n        if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) {\n            $firstTest = $this->getFirstTest($testSuite);\n            if ($firstTest instanceof TestMethod) {\n                return $this->getTestMethodNameWithoutDatasetSuffix($firstTest);\n            }\n        }\n\n        $name = $testSuite->name();\n\n        if (! str_starts_with($name, self::PREFIX)) {\n            return $name;\n        }\n\n        return Str::after($name, self::PREFIX);\n    }\n\n    /**\n     * Gets the trimmed test class name.\n     */\n    public function getTrimmedTestClassName(TestMethod $test): string\n    {\n        return Str::after($test->className(), self::PREFIX);\n    }\n\n    /**\n     * Gets the test suite location.\n     */\n    public function getTestSuiteLocation(TestSuite $testSuite): ?string\n    {\n        $firstTest = $this->getFirstTest($testSuite);\n        if (! $firstTest instanceof TestMethod) {\n            return null;\n        }\n        $path = $firstTest->testDox()->prettifiedClassName();\n        $classRelativePath = $this->toRelativePath($path);\n\n        if ($testSuite instanceof TestSuiteForTestMethodWithDataProvider) {\n            $methodName = $this->getTestMethodNameWithoutDatasetSuffix($firstTest);\n\n            return \"$classRelativePath::$methodName\";\n        }\n\n        return $classRelativePath;\n    }\n\n    /**\n     * Gets the prettified test method name without dataset-related suffix.\n     */\n    private function getTestMethodNameWithoutDatasetSuffix(TestMethod $testMethod): string\n    {\n        return Str::beforeLast($testMethod->testDox()->prettifiedMethodName(), ' with data set ');\n    }\n\n    /**\n     * Gets the first test from the test suite.\n     */\n    private function getFirstTest(TestSuite $testSuite): ?TestMethod\n    {\n        $tests = $testSuite->tests()->asArray();\n\n        // TODO: figure out how to get the file path without a test being there.\n        if ($tests === []) {\n            return null;\n        }\n\n        $firstTest = $tests[0];\n        if (! $firstTest instanceof TestMethod) {\n            throw ShouldNotHappen::fromMessage('Not an instance of TestMethod');\n        }\n\n        return $firstTest;\n    }\n\n    /**\n     * Gets the test suite size.\n     */\n    public function getTestSuiteSize(TestSuite $testSuite): int\n    {\n        return $testSuite->count();\n    }\n\n    /**\n     * Transforms the given path in relative path.\n     */\n    private function toRelativePath(string $path): string\n    {\n        // Remove cwd from the path.\n        return str_replace(\"$this->rootPath\".DIRECTORY_SEPARATOR, '', $path);\n    }\n\n    /**\n     * Get the test result.\n     */\n    public function getStateFromResult(PhpUnitTestResult $result): State\n    {\n        $events = [\n            ...$result->testErroredEvents(),\n            ...$result->testFailedEvents(),\n            ...$result->testSkippedEvents(),\n            ...array_merge(...array_values($result->testConsideredRiskyEvents())),\n            ...$result->testMarkedIncompleteEvents(),\n        ];\n\n        $numberOfNotPassedTests = count(\n            array_unique(\n                array_map(\n                    function (AfterLastTestMethodErrored|BeforeFirstTestMethodErrored|Errored|Failed|Skipped|ConsideredRisky|MarkedIncomplete $event): string {\n                        if ($event instanceof BeforeFirstTestMethodErrored\n                            || $event instanceof AfterLastTestMethodErrored) {\n                            return $event->testClassName();\n                        }\n\n                        return $this->getTestCaseLocation($event->test());\n                    },\n                    $events\n                )\n            )\n        );\n\n        $numberOfPassedTests = $result->numberOfTestsRun() - $numberOfNotPassedTests;\n\n        return $this->stateGenerator->fromPhpUnitTestResult($numberOfPassedTests, $result);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/ServiceMessage.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity;\n\n/**\n * @internal\n */\nfinal class ServiceMessage\n{\n    /**\n     * The flow ID.\n     */\n    private static ?int $flowId = null;\n\n    /**\n     * @param  array<string, string|int|null>  $parameters\n     */\n    public function __construct(\n        private readonly string $type,\n        private readonly array $parameters,\n    ) {}\n\n    public function toString(): string\n    {\n        $paramsToString = '';\n\n        foreach ([...$this->parameters, 'flowId' => self::$flowId] as $key => $value) {\n            $value = $this->escapeServiceMessage((string) $value);\n            $paramsToString .= \" $key='$value'\";\n        }\n\n        return \"##teamcity[$this->type$paramsToString]\";\n    }\n\n    public static function testSuiteStarted(string $name, ?string $location): self\n    {\n        return new self('testSuiteStarted', [\n            'name' => $name,\n            'locationHint' => $location === null ? null : \"pest_qn://$location\",\n        ]);\n    }\n\n    public static function testSuiteCount(int $count): self\n    {\n        return new self('testCount', [\n            'count' => $count,\n        ]);\n    }\n\n    public static function testSuiteFinished(string $name): self\n    {\n        return new self('testSuiteFinished', [\n            'name' => $name,\n        ]);\n    }\n\n    public static function testStarted(string $name, string $location): self\n    {\n        return new self('testStarted', [\n            'name' => $name,\n            'locationHint' => \"pest_qn://$location\",\n        ]);\n    }\n\n    /**\n     * @param  int  $duration  in milliseconds\n     */\n    public static function testFinished(string $name, int $duration): self\n    {\n        return new self('testFinished', [\n            'name' => $name,\n            'duration' => $duration,\n        ]);\n    }\n\n    public static function testStdOut(string $name, string $data): self\n    {\n        if (! str_ends_with($data, \"\\n\")) {\n            $data .= \"\\n\";\n        }\n\n        return new self('testStdOut', [\n            'name' => $name,\n            'out' => $data,\n        ]);\n    }\n\n    public static function testFailed(string $name, string $message, string $details): self\n    {\n        return new self('testFailed', [\n            'name' => $name,\n            'message' => $message,\n            'details' => $details,\n        ]);\n    }\n\n    public static function testStdErr(string $name, string $data): self\n    {\n        if (! str_ends_with($data, \"\\n\")) {\n            $data .= \"\\n\";\n        }\n\n        return new self('testStdErr', [\n            'name' => $name,\n            'out' => $data,\n        ]);\n    }\n\n    public static function testIgnored(string $name, string $message, ?string $details = null): self\n    {\n        return new self('testIgnored', [\n            'name' => $name,\n            'message' => $message,\n            'details' => $details,\n        ]);\n    }\n\n    public static function comparisonFailure(string $name, string $message, string $details, string $actual, string $expected): self\n    {\n        return new self('testFailed', [\n            'name' => $name,\n            'message' => $message,\n            'details' => $details,\n            'type' => 'comparisonFailure',\n            'actual' => $actual,\n            'expected' => $expected,\n        ]);\n    }\n\n    private function escapeServiceMessage(string $text): string\n    {\n        return str_replace(\n            ['|', \"'\", \"\\n\", \"\\r\", ']', '['],\n            ['||', \"|'\", '|n', '|r', '|]', '|['],\n            $text\n        );\n    }\n\n    public static function setFlowId(int $flowId): void\n    {\n        self::$flowId = $flowId;\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/Subscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse Pest\\Logging\\TeamCity\\TeamCityLogger;\n\n/**\n * @internal\n */\nabstract class Subscriber // @pest-arch-ignore-line\n{\n    /**\n     * Creates a new Subscriber instance.\n     */\n    public function __construct(private readonly TeamCityLogger $logger) {}\n\n    /**\n     * Creates a new TeamCityLogger instance.\n     */\n    final protected function logger(): TeamCityLogger // @pest-arch-ignore-line\n    {\n        return $this->logger;\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/TestConsideredRiskySubscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\Test\\ConsideredRisky;\nuse PHPUnit\\Event\\Test\\ConsideredRiskySubscriber;\n\n/**\n * @internal\n */\nfinal class TestConsideredRiskySubscriber extends Subscriber implements ConsideredRiskySubscriber\n{\n    public function notify(ConsideredRisky $event): void\n    {\n        $this->logger()->testConsideredRisky($event);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/TestErroredSubscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\Test\\Errored;\nuse PHPUnit\\Event\\Test\\ErroredSubscriber;\n\n/**\n * @internal\n */\nfinal class TestErroredSubscriber extends Subscriber implements ErroredSubscriber\n{\n    public function notify(Errored $event): void\n    {\n        $this->logger()->testErrored($event);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/TestExecutionFinishedSubscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\TestRunner\\ExecutionFinished;\nuse PHPUnit\\Event\\TestRunner\\ExecutionFinishedSubscriber;\n\n/**\n * @internal\n */\nfinal class TestExecutionFinishedSubscriber extends Subscriber implements ExecutionFinishedSubscriber\n{\n    public function notify(ExecutionFinished $event): void\n    {\n        $this->logger()->testExecutionFinished($event);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/TestFailedSubscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\Test\\Failed;\nuse PHPUnit\\Event\\Test\\FailedSubscriber;\n\n/**\n * @internal\n */\nfinal class TestFailedSubscriber extends Subscriber implements FailedSubscriber\n{\n    public function notify(Failed $event): void\n    {\n        $this->logger()->testFailed($event);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/TestFinishedSubscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\Test\\Finished;\nuse PHPUnit\\Event\\Test\\FinishedSubscriber;\n\n/**\n * @internal\n */\nfinal class TestFinishedSubscriber extends Subscriber implements FinishedSubscriber\n{\n    public function notify(Finished $event): void\n    {\n        $this->logger()->testFinished($event);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/TestPreparedSubscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\Test\\Prepared;\nuse PHPUnit\\Event\\Test\\PreparedSubscriber;\n\n/**\n * @internal\n */\nfinal class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber\n{\n    public function notify(Prepared $event): void\n    {\n        $this->logger()->testPrepared($event);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/TestSkippedSubscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\Test\\Skipped;\nuse PHPUnit\\Event\\Test\\SkippedSubscriber;\n\n/**\n * @internal\n */\nfinal class TestSkippedSubscriber extends Subscriber implements SkippedSubscriber\n{\n    public function notify(Skipped $event): void\n    {\n        $this->logger()->testSkipped($event);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/TestSuiteFinishedSubscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\TestSuite\\Finished;\nuse PHPUnit\\Event\\TestSuite\\FinishedSubscriber;\n\n/**\n * @internal\n */\nfinal class TestSuiteFinishedSubscriber extends Subscriber implements FinishedSubscriber\n{\n    public function notify(Finished $event): void\n    {\n        $this->logger()->testSuiteFinished($event);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/Subscriber/TestSuiteStartedSubscriber.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity\\Subscriber;\n\nuse PHPUnit\\Event\\TestSuite\\Started;\nuse PHPUnit\\Event\\TestSuite\\StartedSubscriber;\n\n/**\n * @internal\n */\nfinal class TestSuiteStartedSubscriber extends Subscriber implements StartedSubscriber\n{\n    public function notify(Started $event): void\n    {\n        $this->logger()->testSuiteStarted($event);\n    }\n}\n"
  },
  {
    "path": "src/Logging/TeamCity/TeamCityLogger.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Logging\\TeamCity;\n\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\Style;\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse Pest\\Logging\\Converter;\nuse Pest\\Logging\\TeamCity\\Subscriber\\TestConsideredRiskySubscriber;\nuse Pest\\Logging\\TeamCity\\Subscriber\\TestErroredSubscriber;\nuse Pest\\Logging\\TeamCity\\Subscriber\\TestExecutionFinishedSubscriber;\nuse Pest\\Logging\\TeamCity\\Subscriber\\TestFailedSubscriber;\nuse Pest\\Logging\\TeamCity\\Subscriber\\TestFinishedSubscriber;\nuse Pest\\Logging\\TeamCity\\Subscriber\\TestPreparedSubscriber;\nuse Pest\\Logging\\TeamCity\\Subscriber\\TestSkippedSubscriber;\nuse Pest\\Logging\\TeamCity\\Subscriber\\TestSuiteFinishedSubscriber;\nuse Pest\\Logging\\TeamCity\\Subscriber\\TestSuiteStartedSubscriber;\nuse PHPUnit\\Event\\Code\\Test;\nuse PHPUnit\\Event\\EventFacadeIsSealedException;\nuse PHPUnit\\Event\\Facade;\nuse PHPUnit\\Event\\Telemetry\\Duration;\nuse PHPUnit\\Event\\Telemetry\\HRTime;\nuse PHPUnit\\Event\\Telemetry\\Info;\nuse PHPUnit\\Event\\Telemetry\\Snapshot;\nuse PHPUnit\\Event\\Test\\ConsideredRisky;\nuse PHPUnit\\Event\\Test\\Errored;\nuse PHPUnit\\Event\\Test\\Failed;\nuse PHPUnit\\Event\\Test\\Finished;\nuse PHPUnit\\Event\\Test\\Prepared;\nuse PHPUnit\\Event\\Test\\Skipped;\nuse PHPUnit\\Event\\TestRunner\\ExecutionFinished;\nuse PHPUnit\\Event\\TestSuite\\Finished as TestSuiteFinished;\nuse PHPUnit\\Event\\TestSuite\\Started as TestSuiteStarted;\nuse PHPUnit\\Event\\UnknownSubscriberTypeException;\nuse PHPUnit\\TestRunner\\TestResult\\Facade as TestResultFacade;\nuse ReflectionClass;\nuse Symfony\\Component\\Console\\Output\\ConsoleOutput;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal class TeamCityLogger\n{\n    /**\n     * The current time.\n     */\n    private ?HRTime $time = null;\n\n    /**\n     * Indicates if the summary test count has been printed.\n     */\n    private bool $isSummaryTestCountPrinted = false;\n\n    /**\n     * @var array<string, bool>\n     */\n    private array $testEvents = [];\n\n    /**\n     * @throws EventFacadeIsSealedException\n     * @throws UnknownSubscriberTypeException\n     */\n    public function __construct(\n        private readonly OutputInterface $output,\n        private readonly Converter $converter,\n        private readonly ?int $flowId,\n        private readonly bool $withoutDuration,\n    ) {\n        $this->registerSubscribers();\n        $this->setFlowId();\n    }\n\n    public function testSuiteStarted(TestSuiteStarted $event): void\n    {\n        $message = ServiceMessage::testSuiteStarted(\n            $this->converter->getTestSuiteName($event->testSuite()),\n            $this->converter->getTestSuiteLocation($event->testSuite())\n        );\n\n        $this->output($message);\n\n        if (! $this->isSummaryTestCountPrinted) {\n            $this->isSummaryTestCountPrinted = true;\n            $message = ServiceMessage::testSuiteCount(\n                $this->converter->getTestSuiteSize($event->testSuite())\n            );\n\n            $this->output($message);\n        }\n    }\n\n    public function testSuiteFinished(TestSuiteFinished $event): void\n    {\n        $message = ServiceMessage::testSuiteFinished(\n            $this->converter->getTestSuiteName($event->testSuite()),\n        );\n\n        $this->output($message);\n    }\n\n    public function testPrepared(Prepared $event): void\n    {\n        $message = ServiceMessage::testStarted(\n            $this->converter->getTestCaseMethodName($event->test()),\n            $this->converter->getTestCaseLocation($event->test()),\n        );\n\n        $this->output($message);\n\n        $this->time = $event->telemetryInfo()->time();\n    }\n\n    public function testMarkedIncomplete(): never\n    {\n        throw ShouldNotHappen::fromMessage('testMarkedIncomplete not implemented.');\n    }\n\n    public function testSkipped(Skipped $event): void\n    {\n        $this->whenFirstEventForTest($event->test(), function () use ($event): void {\n            $message = ServiceMessage::testIgnored(\n                $this->converter->getTestCaseMethodName($event->test()),\n                'This test was ignored.'\n            );\n\n            $this->output($message);\n        });\n    }\n\n    /**\n     * This will trigger in the following scenarios\n     * - When an exception is thrown\n     */\n    public function testErrored(Errored $event): void\n    {\n        $this->whenFirstEventForTest($event->test(), function () use ($event): void {\n            $testName = $this->converter->getTestCaseMethodName($event->test());\n            $message = $this->converter->getExceptionMessage($event->throwable());\n            $details = $this->converter->getExceptionDetails($event->throwable());\n\n            $message = ServiceMessage::testFailed(\n                $testName,\n                $message,\n                $details,\n            );\n\n            $this->output($message);\n        });\n    }\n\n    /**\n     * This will trigger in the following scenarios\n     * - When an assertion fails\n     */\n    public function testFailed(Failed $event): void\n    {\n        $this->whenFirstEventForTest($event->test(), function () use ($event): void {\n            $testName = $this->converter->getTestCaseMethodName($event->test());\n            $message = $this->converter->getExceptionMessage($event->throwable());\n            $details = $this->converter->getExceptionDetails($event->throwable());\n\n            if ($event->hasComparisonFailure()) {\n                $comparison = $event->comparisonFailure();\n                $message = ServiceMessage::comparisonFailure(\n                    $testName,\n                    $message,\n                    $details,\n                    $comparison->actual(),\n                    $comparison->expected()\n                );\n            } else {\n                $message = ServiceMessage::testFailed(\n                    $testName,\n                    $message,\n                    $details,\n                );\n            }\n\n            $this->output($message);\n        });\n    }\n\n    /**\n     * This will trigger in the following scenarios\n     * - When no assertions in a test\n     */\n    public function testConsideredRisky(ConsideredRisky $event): void\n    {\n        $this->whenFirstEventForTest($event->test(), function () use ($event): void {\n            $message = ServiceMessage::testIgnored(\n                $this->converter->getTestCaseMethodName($event->test()),\n                $event->message()\n            );\n\n            $this->output($message);\n        });\n    }\n\n    public function testFinished(Finished $event): void\n    {\n        if (! $this->time instanceof HRTime) {\n            throw ShouldNotHappen::fromMessage('Start time has not been set.');\n        }\n\n        $testName = $this->converter->getTestCaseMethodName($event->test());\n        $duration = $event->telemetryInfo()->time()->duration($this->time)->asFloat();\n        if ($this->withoutDuration) {\n            $duration = 100;\n        }\n\n        $message = ServiceMessage::testFinished(\n            $testName,\n            (int) ($duration * 1000)\n        );\n\n        $this->output($message);\n    }\n\n    public function testExecutionFinished(ExecutionFinished $event): void\n    {\n        $result = TestResultFacade::result();\n        $state = $this->converter->getStateFromResult($result);\n\n        assert($this->output instanceof ConsoleOutput);\n        $style = new Style($this->output);\n\n        $telemetry = $event->telemetryInfo();\n\n        if ($this->withoutDuration) {\n            $reflector = new ReflectionClass($telemetry);\n\n            $property = $reflector->getProperty('current');\n            $snapshot = $property->getValue($telemetry);\n            assert($snapshot instanceof Snapshot);\n\n            $telemetry = new Info(\n                $snapshot,\n                Duration::fromSecondsAndNanoseconds(1, 0),\n                $telemetry->memoryUsageSinceStart(),\n                $telemetry->durationSincePrevious(),\n                $telemetry->memoryUsageSincePrevious(),\n            );\n        }\n\n        $style->writeRecap($state, $telemetry, $result);\n    }\n\n    public function output(ServiceMessage $message): void\n    {\n        $this->output->writeln(\"{$message->toString()}\");\n    }\n\n    /**\n     * @throws EventFacadeIsSealedException\n     * @throws UnknownSubscriberTypeException\n     */\n    private function registerSubscribers(): void\n    {\n        $subscribers = [\n            new TestSuiteStartedSubscriber($this),\n            new TestSuiteFinishedSubscriber($this),\n            new TestPreparedSubscriber($this),\n            new TestFinishedSubscriber($this),\n            new TestErroredSubscriber($this),\n            new TestFailedSubscriber($this),\n            new TestSkippedSubscriber($this),\n            new TestConsideredRiskySubscriber($this),\n            new TestExecutionFinishedSubscriber($this),\n        ];\n\n        Facade::instance()->registerSubscribers(...$subscribers);\n    }\n\n    private function setFlowId(): void\n    {\n        if ($this->flowId === null) {\n            return;\n        }\n\n        ServiceMessage::setFlowId($this->flowId);\n    }\n\n    private function whenFirstEventForTest(Test $test, callable $callback): void\n    {\n        $testIdentifier = $this->converter->getTestCaseLocation($test);\n\n        if (! isset($this->testEvents[$testIdentifier])) {\n            $this->testEvents[$testIdentifier] = true;\n            $callback();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Matchers/Any.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Matchers;\n\n/**\n * @internal\n */\nfinal class Any {}\n"
  },
  {
    "path": "src/Mixins/Expectation.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Mixins;\n\nuse BadMethodCallException;\nuse Closure;\nuse Countable;\nuse DateTimeInterface;\nuse Error;\nuse Illuminate\\Testing\\TestResponse;\nuse InvalidArgumentException;\nuse JsonSerializable;\nuse Pest\\Exceptions\\InvalidExpectationValue;\nuse Pest\\Matchers\\Any;\nuse Pest\\Support\\Arr;\nuse Pest\\Support\\Exporter;\nuse Pest\\Support\\NullClosure;\nuse Pest\\Support\\Str;\nuse Pest\\TestSuite;\nuse PHPUnit\\Framework\\Assert;\nuse PHPUnit\\Framework\\Constraint\\Constraint;\nuse PHPUnit\\Framework\\ExpectationFailedException;\nuse PHPUnit\\Framework\\TestCase;\nuse ReflectionFunction;\nuse ReflectionNamedType;\nuse Throwable;\nuse Traversable;\n\n/**\n * @internal\n *\n * @template TValue\n *\n * @mixin \\Pest\\Expectation<TValue>\n */\nfinal class Expectation\n{\n    /**\n     * The exporter instance, if any.\n     */\n    private ?Exporter $exporter = null;\n\n    /**\n     * Creates a new expectation.\n     *\n     * @param  TValue  $value\n     */\n    public function __construct(\n        public mixed $value\n    ) {\n        // ..\n    }\n\n    /**\n     * Asserts that two variables have the same type and\n     * value. Used on objects, it asserts that two\n     * variables reference the same object.\n     *\n     * @return self<TValue>\n     */\n    public function toBe(mixed $expected, string $message = ''): self\n    {\n        Assert::assertSame($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is empty.\n     *\n     * @return self<TValue>\n     */\n    public function toBeEmpty(string $message = ''): self\n    {\n        Assert::assertEmpty($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is true.\n     *\n     * @return self<TValue>\n     */\n    public function toBeTrue(string $message = ''): self\n    {\n        Assert::assertTrue($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is truthy.\n     *\n     * @return self<TValue>\n     */\n    public function toBeTruthy(string $message = ''): self\n    {\n        Assert::assertTrue((bool) $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is false.\n     *\n     * @return self<TValue>\n     */\n    public function toBeFalse(string $message = ''): self\n    {\n        Assert::assertFalse($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is falsy.\n     *\n     * @return self<TValue>\n     */\n    public function toBeFalsy(string $message = ''): self\n    {\n        Assert::assertFalse((bool) $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is greater than $expected.\n     *\n     * @return self<TValue>\n     */\n    public function toBeGreaterThan(int|float|string|DateTimeInterface $expected, string $message = ''): self\n    {\n        Assert::assertGreaterThan($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is greater than or equal to $expected.\n     *\n     * @return self<TValue>\n     */\n    public function toBeGreaterThanOrEqual(int|float|string|DateTimeInterface $expected, string $message = ''): self\n    {\n        Assert::assertGreaterThanOrEqual($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is less than or equal to $expected.\n     *\n     * @return self<TValue>\n     */\n    public function toBeLessThan(int|float|string|DateTimeInterface $expected, string $message = ''): self\n    {\n        Assert::assertLessThan($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is less than $expected.\n     *\n     * @return self<TValue>\n     */\n    public function toBeLessThanOrEqual(int|float|string|DateTimeInterface $expected, string $message = ''): self\n    {\n        Assert::assertLessThanOrEqual($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that $needle is an element of the value.\n     *\n     * @return self<TValue>\n     */\n    public function toContain(mixed ...$needles): self\n    {\n        foreach ($needles as $needle) {\n            if (is_string($this->value)) {\n                Assert::assertStringContainsString((string) $needle, $this->value);\n            } else {\n                if (! is_iterable($this->value)) {\n                    InvalidExpectationValue::expected('iterable');\n                }\n                Assert::assertContains($needle, $this->value);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that $needle equal an element of the value.\n     *\n     * @return self<TValue>\n     */\n    public function toContainEqual(mixed ...$needles): self\n    {\n        if (! is_iterable($this->value)) {\n            InvalidExpectationValue::expected('iterable');\n        }\n\n        foreach ($needles as $needle) {\n            Assert::assertContainsEquals($needle, $this->value);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value starts with $expected.\n     *\n     * @param  non-empty-string  $expected\n     * @return self<TValue>\n     */\n    public function toStartWith(string $expected, string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n\n        Assert::assertStringStartsWith($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value ends with $expected.\n     *\n     * @param  non-empty-string  $expected\n     * @return self<TValue>\n     */\n    public function toEndWith(string $expected, string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n\n        Assert::assertStringEndsWith($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that $number matches value's Length.\n     *\n     * @return self<TValue>\n     */\n    public function toHaveLength(int $number, string $message = ''): self\n    {\n        if (is_string($this->value)) {\n            Assert::assertEquals($number, mb_strlen($this->value), $message);\n\n            return $this;\n        }\n\n        if (is_iterable($this->value)) {\n            return $this->toHaveCount($number, $message);\n        }\n\n        if (is_object($this->value)) {\n            $array = method_exists($this->value, 'toArray') ? $this->value->toArray() : (array) $this->value;\n\n            Assert::assertCount($number, $array, $message);\n\n            return $this;\n        }\n\n        throw new BadMethodCallException('Expectation value length is not countable.');\n    }\n\n    /**\n     * Asserts that $count matches the number of elements of the value.\n     *\n     * @return self<TValue>\n     */\n    public function toHaveCount(int $count, string $message = ''): self\n    {\n        if (! is_countable($this->value) && ! is_iterable($this->value)) {\n            InvalidExpectationValue::expected('countable|iterable');\n        }\n\n        Assert::assertCount($count, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the size of the value and $expected are the same.\n     *\n     * @param  Countable|iterable<mixed>  $expected\n     * @return self<TValue>\n     */\n    public function toHaveSameSize(Countable|iterable $expected, string $message = ''): self\n    {\n        if (! is_countable($this->value) && ! is_iterable($this->value)) {\n            InvalidExpectationValue::expected('countable|iterable');\n        }\n\n        Assert::assertSameSize($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value contains the property $name.\n     *\n     * @return self<TValue>\n     */\n    public function toHaveProperty(string $name, mixed $value = new Any, string $message = ''): self\n    {\n        $this->toBeObject();\n\n        // @phpstan-ignore-next-line\n        Assert::assertTrue(property_exists($this->value, $name), $message);\n\n        if (! $value instanceof Any) {\n            /* @phpstan-ignore-next-line */\n            Assert::assertEquals($value, $this->value->{$name}, $message);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value contains the provided properties $names.\n     *\n     * @param  iterable<string, mixed>|iterable<int, string>  $names\n     * @return self<TValue>\n     */\n    public function toHaveProperties(iterable $names, string $message = ''): self\n    {\n        foreach ($names as $name => $value) {\n            is_int($name) ? $this->toHaveProperty($value, message: $message) : $this->toHaveProperty($name, $value, $message); // @phpstan-ignore-line\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that two variables have the same value.\n     *\n     * @return self<TValue>\n     */\n    public function toEqual(mixed $expected, string $message = ''): self\n    {\n        Assert::assertEquals($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that two variables have the same value.\n     * The contents of $expected and the $this->value are\n     * canonicalized before they are compared. For instance, when the two\n     * variables $expected and $this->value are arrays, then these arrays\n     * are sorted before they are compared. When $expected and $this->value\n     * are objects, each object is converted to an array containing all\n     * private, protected and public attributes.\n     *\n     * @return self<TValue>\n     */\n    public function toEqualCanonicalizing(mixed $expected, string $message = ''): self\n    {\n        Assert::assertEqualsCanonicalizing($expected, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the absolute difference between the value and $expected\n     * is lower than $delta.\n     *\n     * @return self<TValue>\n     */\n    public function toEqualWithDelta(mixed $expected, float $delta, string $message = ''): self\n    {\n        Assert::assertEqualsWithDelta($expected, $this->value, $delta, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is one of the given values.\n     *\n     * @param  iterable<int|string, mixed>  $values\n     * @return self<TValue>\n     */\n    public function toBeIn(iterable $values, string $message = ''): self\n    {\n        Assert::assertContains($this->value, $values, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is infinite.\n     *\n     * @return self<TValue>\n     */\n    public function toBeInfinite(string $message = ''): self\n    {\n        Assert::assertInfinite($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is an instance of $class.\n     *\n     * @param  class-string  $class\n     * @return self<TValue>\n     */\n    public function toBeInstanceOf(string $class, string $message = ''): self\n    {\n        Assert::assertInstanceOf($class, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is an array.\n     *\n     * @return self<TValue>\n     */\n    public function toBeArray(string $message = ''): self\n    {\n        Assert::assertIsArray($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is a list.\n     *\n     * @return self<TValue>\n     */\n    public function toBeList(string $message = ''): self\n    {\n        Assert::assertIsList($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type bool.\n     *\n     * @return self<TValue>\n     */\n    public function toBeBool(string $message = ''): self\n    {\n        Assert::assertIsBool($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type callable.\n     *\n     * @return self<TValue>\n     */\n    public function toBeCallable(string $message = ''): self\n    {\n        Assert::assertIsCallable($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type float.\n     *\n     * @return self<TValue>\n     */\n    public function toBeFloat(string $message = ''): self\n    {\n        Assert::assertIsFloat($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type int.\n     *\n     * @return self<TValue>\n     */\n    public function toBeInt(string $message = ''): self\n    {\n        Assert::assertIsInt($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type iterable.\n     *\n     * @return self<TValue>\n     */\n    public function toBeIterable(string $message = ''): self\n    {\n        Assert::assertIsIterable($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type numeric.\n     *\n     * @return self<TValue>\n     */\n    public function toBeNumeric(string $message = ''): self\n    {\n        Assert::assertIsNumeric($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value contains only digits.\n     *\n     * @return self<TValue>\n     */\n    public function toBeDigits(string $message = ''): self\n    {\n        Assert::assertTrue(ctype_digit((string) $this->value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type object.\n     *\n     * @return self<TValue>\n     */\n    public function toBeObject(string $message = ''): self\n    {\n        Assert::assertIsObject($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type resource.\n     *\n     * @return self<TValue>\n     */\n    public function toBeResource(string $message = ''): self\n    {\n        Assert::assertIsResource($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type scalar.\n     *\n     * @return self<TValue>\n     */\n    public function toBeScalar(string $message = ''): self\n    {\n        Assert::assertIsScalar($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is of type string.\n     *\n     * @return self<TValue>\n     */\n    public function toBeString(string $message = ''): self\n    {\n        Assert::assertIsString($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is a JSON string.\n     *\n     * @return self<TValue>\n     */\n    public function toBeJson(string $message = ''): self\n    {\n        Assert::assertIsString($this->value, $message);\n\n        Assert::assertJson($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is NAN.\n     *\n     * @return self<TValue>\n     */\n    public function toBeNan(string $message = ''): self\n    {\n        Assert::assertNan($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is null.\n     *\n     * @return self<TValue>\n     */\n    public function toBeNull(string $message = ''): self\n    {\n        Assert::assertNull($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value array has the provided $key.\n     *\n     * @return self<TValue>\n     */\n    public function toHaveKey(string|int $key, mixed $value = new Any, string $message = ''): self\n    {\n        if (is_object($this->value) && method_exists($this->value, 'toArray')) {\n            $array = $this->value->toArray();\n        } else {\n            $array = (array) $this->value;\n        }\n\n        try {\n            Assert::assertTrue(Arr::has($array, $key));\n\n            /* @phpstan-ignore-next-line */\n        } catch (ExpectationFailedException $exception) {\n            if ($message === '') {\n                $message = \"Failed asserting that an array has the key '$key'\";\n            }\n\n            throw new ExpectationFailedException($message, $exception->getComparisonFailure());\n        }\n\n        if (! $value instanceof Any) {\n            Assert::assertEquals($value, Arr::get($array, $key), $message);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value array has the provided $keys.\n     *\n     * @param  array<int, int|string|array<array-key, mixed>>  $keys\n     * @return self<TValue>\n     */\n    public function toHaveKeys(array $keys, string $message = ''): self\n    {\n        foreach ($keys as $k => $key) {\n            if (is_array($key)) {\n                $this->toHaveKeys(array_keys(Arr::dot($key, $k.'.')), $message);\n            } else {\n                $this->toHaveKey($key, message: $message);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is a directory.\n     *\n     * @return self<TValue>\n     */\n    public function toBeDirectory(string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n\n        Assert::assertDirectoryExists($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is a directory and is readable.\n     *\n     * @return self<TValue>\n     */\n    public function toBeReadableDirectory(string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n\n        Assert::assertDirectoryIsReadable($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is a directory and is writable.\n     *\n     * @return self<TValue>\n     */\n    public function toBeWritableDirectory(string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n\n        Assert::assertDirectoryIsWritable($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is a file.\n     *\n     * @return self<TValue>\n     */\n    public function toBeFile(string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n\n        Assert::assertFileExists($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is a file and is readable.\n     *\n     * @return self<TValue>\n     */\n    public function toBeReadableFile(string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n\n        Assert::assertFileIsReadable($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is a file and is writable.\n     *\n     * @return self<TValue>\n     */\n    public function toBeWritableFile(string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n        Assert::assertFileIsWritable($this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value array matches the given array subset.\n     *\n     * @param  iterable<int|string, mixed>  $array\n     * @return self<TValue>\n     */\n    public function toMatchArray(iterable $array, string $message = ''): self\n    {\n        if (is_object($this->value) && method_exists($this->value, 'toArray')) {\n            $valueAsArray = $this->value->toArray();\n        } else {\n            $valueAsArray = (array) $this->value;\n        }\n\n        foreach ($array as $key => $value) {\n            Assert::assertArrayHasKey($key, $valueAsArray, $message);\n\n            $assertMessage = $message !== '' ? $message : sprintf(\n                'Failed asserting that an array has a key %s with the value %s.',\n                $this->export($key),\n                $this->export($valueAsArray[$key]),\n            );\n\n            Assert::assertEquals($value, $valueAsArray[$key], $assertMessage);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value object matches a subset\n     * of the properties of an given object.\n     *\n     * @param  iterable<string, mixed>  $object\n     * @return self<TValue>\n     */\n    public function toMatchObject(object|iterable $object, string $message = ''): self\n    {\n        foreach ((array) $object as $property => $value) {\n            if (! is_object($this->value) && ! is_string($this->value)) {\n                InvalidExpectationValue::expected('object|string');\n            }\n\n            Assert::assertTrue(property_exists($this->value, $property), $message);\n\n            /* @phpstan-ignore-next-line */\n            $propertyValue = $this->value->{$property};\n\n            $assertMessage = $message !== '' ? $message : sprintf(\n                'Failed asserting that an object has a property %s with the value %s.',\n                $this->export($property),\n                $this->export($propertyValue),\n            );\n\n            Assert::assertEquals($value, $propertyValue, $assertMessage);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value \"stringable\" matches the given snapshot..\n     *\n     * @return self<TValue>\n     */\n    public function toMatchSnapshot(string $message = ''): self\n    {\n        $snapshots = TestSuite::getInstance()->snapshots;\n        $snapshots->startNewExpectation();\n\n        $testCase = TestSuite::getInstance()->test;\n        assert($testCase instanceof TestCase);\n\n        $string = match (true) {\n            is_string($this->value) => $this->value,\n            is_object($this->value) && method_exists($this->value, 'toSnapshot') => $this->value->toSnapshot(),\n            is_object($this->value) && method_exists($this->value, '__toString') => $this->value->__toString(),\n            is_object($this->value) && method_exists($this->value, 'toString') => $this->value->toString(),\n            $this->value instanceof TestResponse => $this->value->getContent(), // @phpstan-ignore-line\n            is_array($this->value) => json_encode($this->value, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),\n            $this->value instanceof Traversable => json_encode(iterator_to_array($this->value), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),\n            $this->value instanceof JsonSerializable => json_encode($this->value->jsonSerialize(), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),\n            is_object($this->value) && method_exists($this->value, 'toArray') => json_encode($this->value->toArray(), JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT),\n            default => InvalidExpectationValue::expected('array|object|string'),\n        };\n\n        if ($snapshots->has()) {\n            [$filename, $content] = $snapshots->get();\n\n            Assert::assertSame(\n                strtr($content, [\"\\r\\n\" => \"\\n\", \"\\r\" => \"\\n\"]),\n                strtr($string, [\"\\r\\n\" => \"\\n\", \"\\r\" => \"\\n\"]),\n                $message === '' ? \"Failed asserting that the string value matches its snapshot ($filename).\" : $message\n            );\n        } else {\n            $filename = $snapshots->save($string);\n\n            TestSuite::getInstance()->registerSnapshotChange(\"Snapshot created at [$filename]\");\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value matches a regular expression.\n     *\n     * @return self<TValue>\n     */\n    public function toMatch(string $expression, string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n        Assert::assertMatchesRegularExpression($expression, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value matches a constraint.\n     *\n     * @return self<TValue>\n     */\n    public function toMatchConstraint(Constraint $constraint, string $message = ''): self\n    {\n        Assert::assertThat($this->value, $constraint, $message);\n\n        return $this;\n    }\n\n    /**\n     * @param  class-string  $class\n     * @return self<TValue>\n     */\n    public function toContainOnlyInstancesOf(string $class, string $message = ''): self\n    {\n        if (! is_iterable($this->value)) {\n            InvalidExpectationValue::expected('iterable');\n        }\n\n        Assert::assertContainsOnlyInstancesOf($class, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that executing value throws an exception.\n     *\n     * @param  (Closure(Throwable): mixed)|string  $exception\n     * @return self<TValue>\n     */\n    public function toThrow(callable|string|Throwable $exception, ?string $exceptionMessage = null, string $message = ''): self\n    {\n        $callback = NullClosure::create();\n\n        if ($exception instanceof Closure) {\n            $callback = $exception;\n            $parameters = (new ReflectionFunction($exception))->getParameters();\n\n            if (count($parameters) !== 1) {\n                throw new InvalidArgumentException('The given closure must have a single parameter type-hinted as the class string.');\n            }\n\n            if (! ($type = $parameters[0]->getType()) instanceof ReflectionNamedType) {\n                throw new InvalidArgumentException('The given closure\\'s parameter must be type-hinted as the class string.');\n            }\n\n            $exception = $type->getName();\n        }\n\n        try {\n            ($this->value)();\n        } catch (Throwable $e) {\n\n            if ($exception instanceof Throwable) {\n                expect($e)\n                    ->toBeInstanceOf($exception::class, $message)\n                    ->and($e->getMessage())->toBe($exceptionMessage ?? $exception->getMessage(), $message);\n\n                return $this;\n            }\n\n            if (! class_exists($exception)) {\n                if ($e instanceof Error && \"Class \\\"$exception\\\" not found\" === $e->getMessage()) {\n                    Assert::assertTrue(true);\n\n                    throw $e;\n                }\n\n                Assert::assertStringContainsString($exception, $e->getMessage(), $message);\n\n                return $this;\n            }\n\n            if ($exceptionMessage !== null) {\n                Assert::assertStringContainsString($exceptionMessage, $e->getMessage(), $message);\n            }\n\n            Assert::assertInstanceOf($exception, $e, $message);\n\n            $callback($e);\n\n            return $this;\n        }\n\n        Assert::assertTrue(true);\n\n        if (! $exception instanceof Throwable && ! class_exists($exception)) {\n            throw new ExpectationFailedException(\"Exception with message \\\"$exception\\\" not thrown.\");\n        }\n\n        throw new ExpectationFailedException(\"Exception \\\"$exception\\\" not thrown.\");\n    }\n\n    /**\n     * Exports the given value.\n     */\n    private function export(mixed $value): string\n    {\n        if (! $this->exporter instanceof Exporter) {\n            $this->exporter = Exporter::default();\n        }\n\n        return $this->exporter->shortenedExport($value);\n    }\n\n    /**\n     * Asserts that the value is uppercase.\n     *\n     * @return self<TValue>\n     */\n    public function toBeUppercase(string $message = ''): self\n    {\n        Assert::assertTrue(ctype_upper((string) $this->value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is lowercase.\n     *\n     * @return self<TValue>\n     */\n    public function toBeLowercase(string $message = ''): self\n    {\n        Assert::assertTrue(ctype_lower((string) $this->value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is alphanumeric.\n     *\n     * @return self<TValue>\n     */\n    public function toBeAlphaNumeric(string $message = ''): self\n    {\n        Assert::assertTrue(ctype_alnum((string) $this->value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is alpha.\n     *\n     * @return self<TValue>\n     */\n    public function toBeAlpha(string $message = ''): self\n    {\n        Assert::assertTrue(ctype_alpha((string) $this->value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is snake_case.\n     *\n     * @return self<TValue>\n     */\n    public function toBeSnakeCase(string $message = ''): self\n    {\n        $value = (string) $this->value;\n\n        if ($message === '') {\n            $message = \"Failed asserting that {$value} is snake_case.\";\n        }\n\n        Assert::assertTrue((bool) preg_match('/^[\\p{Ll}_]+$/u', $value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is kebab-case.\n     *\n     * @return self<TValue>\n     */\n    public function toBeKebabCase(string $message = ''): self\n    {\n        $value = (string) $this->value;\n\n        if ($message === '') {\n            $message = \"Failed asserting that {$value} is kebab-case.\";\n        }\n\n        Assert::assertTrue((bool) preg_match('/^[\\p{Ll}-]+$/u', $value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is camelCase.\n     *\n     * @return self<TValue>\n     */\n    public function toBeCamelCase(string $message = ''): self\n    {\n        $value = (string) $this->value;\n\n        if ($message === '') {\n            $message = \"Failed asserting that {$value} is camelCase.\";\n        }\n\n        Assert::assertTrue((bool) preg_match('/^\\p{Ll}[\\p{Ll}\\p{Lu}]+$/u', $value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is StudlyCase.\n     *\n     * @return self<TValue>\n     */\n    public function toBeStudlyCase(string $message = ''): self\n    {\n        $value = (string) $this->value;\n\n        if ($message === '') {\n            $message = \"Failed asserting that {$value} is StudlyCase.\";\n        }\n\n        Assert::assertTrue((bool) preg_match('/^\\p{Lu}+\\p{Ll}[\\p{Ll}\\p{Lu}]+$/u', $value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is UUID.\n     *\n     * @return self<TValue>\n     */\n    public function toBeUuid(string $message = ''): self\n    {\n        if (! is_string($this->value)) {\n            InvalidExpectationValue::expected('string');\n        }\n\n        Assert::assertTrue(Str::isUuid($this->value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is between 2 specified values\n     *\n     * @return self<TValue>\n     */\n    public function toBeBetween(int|float|DateTimeInterface $lowestValue, int|float|DateTimeInterface $highestValue, string $message = ''): self\n    {\n        Assert::assertGreaterThanOrEqual($lowestValue, $this->value, $message);\n        Assert::assertLessThanOrEqual($highestValue, $this->value, $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value is a url\n     *\n     * @return self<TValue>\n     */\n    public function toBeUrl(string $message = ''): self\n    {\n        if ($message === '') {\n            $message = \"Failed asserting that {$this->value} is a url.\";\n        }\n\n        Assert::assertTrue(Str::isUrl((string) $this->value), $message);\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the value can be converted to a slug\n     *\n     * @return self<TValue>\n     */\n    public function toBeSlug(string $message = ''): self\n    {\n        if ($message === '') {\n            $message = \"Failed asserting that {$this->value} can be converted to a slug.\";\n        }\n\n        $slug = Str::slugify((string) $this->value);\n        Assert::assertNotEmpty($slug, $message);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Panic.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nuse NunoMaduro\\Collision\\Writer;\nuse Pest\\Exceptions\\TestDescriptionMissing;\nuse Pest\\Support\\Container;\nuse Symfony\\Component\\Console\\Output\\ConsoleOutput;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Throwable;\nuse Whoops\\Exception\\Inspector;\n\nfinal readonly class Panic\n{\n    /**\n     * Creates a new Panic instance.\n     */\n    private function __construct(\n        private Throwable $throwable\n    ) {\n        // ...\n    }\n\n    /**\n     * Creates a new Panic instance, and exits the application.\n     */\n    public static function with(Throwable $throwable): never\n    {\n        if ($throwable instanceof TestDescriptionMissing && ! is_null($previous = $throwable->getPrevious())) {\n            $throwable = $previous;\n        }\n\n        $panic = new self($throwable);\n\n        $panic->handle();\n\n        exit(1);\n    }\n\n    /**\n     * Handles the panic.\n     */\n    private function handle(): void\n    {\n        try {\n            $output = Container::getInstance()->get(OutputInterface::class);\n        } catch (Throwable) {\n            $output = new ConsoleOutput;\n        }\n\n        assert($output instanceof OutputInterface);\n\n        if ($this->throwable instanceof Contracts\\Panicable) {\n            $this->throwable->render($output);\n\n            exit($this->throwable->exitCode());\n        }\n\n        $writer = new Writer(null, $output);\n\n        $inspector = new Inspector($this->throwable);\n\n        $writer->write($inspector);\n        $output->writeln('');\n\n        exit(1);\n    }\n}\n"
  },
  {
    "path": "src/PendingCalls/AfterEachCall.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\PendingCalls;\n\nuse Closure;\nuse Pest\\PendingCalls\\Concerns\\Describable;\nuse Pest\\Support\\Arr;\nuse Pest\\Support\\Backtrace;\nuse Pest\\Support\\ChainableClosure;\nuse Pest\\Support\\HigherOrderMessageCollection;\nuse Pest\\Support\\NullClosure;\nuse Pest\\TestSuite;\n\n/**\n * @internal\n */\nfinal class AfterEachCall\n{\n    use Describable;\n\n    /**\n     * The \"afterEach\" closure.\n     */\n    private readonly Closure $closure;\n\n    /**\n     * The calls that should be proxied.\n     */\n    private readonly HigherOrderMessageCollection $proxies;\n\n    /**\n     * Creates a new Pending Call.\n     */\n    public function __construct(\n        private readonly TestSuite $testSuite,\n        private readonly string $filename,\n        ?Closure $closure = null\n    ) {\n        $this->closure = $closure instanceof Closure ? $closure : NullClosure::create();\n\n        $this->proxies = new HigherOrderMessageCollection;\n\n        $this->describing = DescribeCall::describing();\n    }\n\n    /**\n     * Creates the Call.\n     */\n    public function __destruct()\n    {\n        $describing = $this->describing;\n\n        $proxies = $this->proxies;\n\n        $afterEachTestCase = ChainableClosure::boundWhen(\n            fn (): bool => $describing === [] || in_array(Arr::last($describing), $this->__describing, true),\n            ChainableClosure::bound(fn () => $proxies->chain($this), $this->closure)->bindTo($this, self::class),\n        )->bindTo($this, self::class);\n\n        assert($afterEachTestCase instanceof Closure);\n\n        $this->testSuite->afterEach->set(\n            $this->filename,\n            $this,\n            $afterEachTestCase,\n        );\n    }\n\n    /**\n     * Saves the calls to be used on the target.\n     *\n     * @param  array<int, mixed>  $arguments\n     */\n    public function __call(string $name, array $arguments): self\n    {\n        $this->proxies\n            ->add(Backtrace::file(), Backtrace::line(), $name, $arguments);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/PendingCalls/BeforeEachCall.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\PendingCalls;\n\nuse Closure;\nuse Pest\\Exceptions\\AfterBeforeTestFunction;\nuse Pest\\PendingCalls\\Concerns\\Describable;\nuse Pest\\Support\\Arr;\nuse Pest\\Support\\Backtrace;\nuse Pest\\Support\\ChainableClosure;\nuse Pest\\Support\\HigherOrderMessageCollection;\nuse Pest\\Support\\NullClosure;\nuse Pest\\TestSuite;\n\n/**\n * @internal\n *\n * @mixin TestCall\n */\nfinal class BeforeEachCall\n{\n    use Describable;\n\n    /**\n     * Holds the before each closure.\n     */\n    private readonly Closure $closure;\n\n    /**\n     * The test call proxies.\n     */\n    private readonly HigherOrderMessageCollection $testCallProxies;\n\n    /**\n     * The test case proxies.\n     */\n    private readonly HigherOrderMessageCollection $testCaseProxies;\n\n    /**\n     * Creates a new Pending Call.\n     */\n    public function __construct(\n        public readonly TestSuite $testSuite,\n        private readonly string $filename,\n        ?Closure $closure = null\n    ) {\n        $this->closure = $closure instanceof Closure ? $closure : NullClosure::create();\n\n        $this->testCallProxies = new HigherOrderMessageCollection;\n        $this->testCaseProxies = new HigherOrderMessageCollection;\n\n        $this->describing = DescribeCall::describing();\n    }\n\n    /**\n     * Creates the Call.\n     */\n    public function __destruct()\n    {\n        $describing = $this->describing;\n        $testCaseProxies = $this->testCaseProxies;\n\n        $beforeEachTestCall = function (TestCall $testCall) use ($describing): void {\n\n            if ($this->describing !== []) {\n                if (Arr::last($describing) !== Arr::last($this->describing)) {\n                    return;\n                }\n\n                if (! in_array(Arr::last($describing), $testCall->describing, true)) {\n                    return;\n                }\n            }\n\n            $this->testCallProxies->chain($testCall);\n        };\n\n        $beforeEachTestCase = ChainableClosure::boundWhen(\n            fn (): bool => $describing === [] || in_array(Arr::last($describing), $this->__describing, true),\n            ChainableClosure::bound(fn () => $testCaseProxies->chain($this), $this->closure)->bindTo($this, self::class),\n        )->bindTo($this, self::class);\n\n        assert($beforeEachTestCase instanceof Closure);\n\n        $this->testSuite->beforeEach->set(\n            $this->filename,\n            $this,\n            $beforeEachTestCall,\n            $beforeEachTestCase,\n        );\n    }\n\n    /**\n     * Runs the given closure after the test.\n     */\n    public function after(Closure $closure): self\n    {\n        if ($this->describing === []) {\n            throw new AfterBeforeTestFunction($this->filename);\n        }\n\n        return $this->__call('after', [$closure]);\n    }\n\n    /**\n     * Saves the calls to be used on the target.\n     *\n     * @param  array<int, mixed>  $arguments\n     */\n    public function __call(string $name, array $arguments): self\n    {\n        if (method_exists(TestCall::class, $name)) {\n            $this->testCallProxies\n                ->add(Backtrace::file(), Backtrace::line(), $name, $arguments);\n\n            return $this;\n        }\n\n        $this->testCaseProxies\n            ->add(Backtrace::file(), Backtrace::line(), $name, $arguments);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/PendingCalls/Concerns/Describable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\PendingCalls\\Concerns;\n\nuse Pest\\Support\\Description;\n\n/**\n * @internal\n */\ntrait Describable\n{\n    /**\n     * Note: this is property is not used; however, it gets added automatically by rector php.\n     *\n     * @var array<int, Description>\n     */\n    public array $__describing;\n\n    /**\n     * The describing of the test case.\n     *\n     * @var array<int, Description>\n     */\n    public array $describing = [];\n}\n"
  },
  {
    "path": "src/PendingCalls/DescribeCall.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\PendingCalls;\n\nuse Closure;\nuse Pest\\Support\\Backtrace;\nuse Pest\\Support\\Description;\nuse Pest\\TestSuite;\n\n/**\n * @internal\n */\nfinal class DescribeCall\n{\n    /**\n     * The current describe call.\n     *\n     * @var array<int, Description>\n     */\n    private static array $describing = [];\n\n    /**\n     * The describe \"before each\" call.\n     */\n    private ?BeforeEachCall $currentBeforeEachCall = null;\n\n    /**\n     * Creates a new Pending Call.\n     */\n    public function __construct(\n        public readonly TestSuite $testSuite,\n        public readonly string $filename,\n        public readonly Description $description,\n        public readonly Closure $tests\n    ) {\n        //\n    }\n\n    /**\n     * What is the current describing.\n     *\n     * @return array<int, Description>\n     */\n    public static function describing(): array\n    {\n        return self::$describing;\n    }\n\n    /**\n     * Creates the Call.\n     */\n    public function __destruct()\n    {\n        unset($this->currentBeforeEachCall);\n\n        self::$describing[] = $this->description;\n\n        try {\n            ($this->tests)();\n        } finally {\n            array_pop(self::$describing);\n        }\n    }\n\n    /**\n     * Dynamically calls methods on each test call.\n     *\n     * @param  array<int, mixed>  $arguments\n     */\n    public function __call(string $name, array $arguments): self\n    {\n        $filename = Backtrace::file();\n\n        if (! $this->currentBeforeEachCall instanceof BeforeEachCall) {\n            $this->currentBeforeEachCall = new BeforeEachCall(TestSuite::getInstance(), $filename);\n\n            $this->currentBeforeEachCall->describing[] = $this->description;\n        }\n\n        $this->currentBeforeEachCall->{$name}(...$arguments);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/PendingCalls/TestCall.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\PendingCalls;\n\nuse Closure;\nuse Pest\\Concerns\\Testable;\nuse Pest\\Exceptions\\InvalidArgumentException;\nuse Pest\\Exceptions\\TestDescriptionMissing;\nuse Pest\\Factories\\Attribute;\nuse Pest\\Factories\\TestCaseMethodFactory;\nuse Pest\\Mutate\\Repositories\\ConfigurationRepository;\nuse Pest\\PendingCalls\\Concerns\\Describable;\nuse Pest\\Plugins\\Environment;\nuse Pest\\Plugins\\Only;\nuse Pest\\Support\\Backtrace;\nuse Pest\\Support\\Container;\nuse Pest\\Support\\Exporter;\nuse Pest\\Support\\HigherOrderCallables;\nuse Pest\\Support\\NullClosure;\nuse Pest\\Support\\Str;\nuse Pest\\TestSuite;\nuse PHPUnit\\Framework\\AssertionFailedError;\nuse PHPUnit\\Framework\\Attributes\\CoversClass;\nuse PHPUnit\\Framework\\Attributes\\CoversFunction;\nuse PHPUnit\\Framework\\Attributes\\CoversTrait;\nuse PHPUnit\\Framework\\Attributes\\Group;\nuse PHPUnit\\Framework\\TestCase;\n\n/**\n * @internal\n *\n * @mixin HigherOrderCallables|TestCase|Testable\n */\nfinal class TestCall // @phpstan-ignore-line\n{\n    use Describable;\n\n    /**\n     * The list of test case factory attributes.\n     *\n     * @var array<int, Attribute>\n     */\n    private array $testCaseFactoryAttributes = [];\n\n    /**\n     * The Test Case Factory.\n     */\n    public readonly TestCaseMethodFactory $testCaseMethod;\n\n    /**\n     * If test call is descriptionLess.\n     */\n    private readonly bool $descriptionLess;\n\n    /**\n     * Creates a new Pending Call.\n     */\n    public function __construct(\n        private readonly TestSuite $testSuite,\n        private readonly string $filename,\n        private ?string $description = null,\n        ?Closure $closure = null\n    ) {\n        $this->testCaseMethod = new TestCaseMethodFactory($filename, $closure);\n\n        $this->descriptionLess = $description === null;\n\n        $this->describing = DescribeCall::describing();\n\n        $this->testSuite->beforeEach->get($this->filename)[0]($this);\n    }\n\n    /**\n     * Runs the given closure after the test.\n     */\n    public function after(Closure $closure): self\n    {\n        if ($this->description === null) {\n            throw new TestDescriptionMissing($this->filename);\n        }\n\n        $description = $this->describing === []\n            ? $this->description\n            : Str::describe($this->describing, $this->description);\n\n        $filename = $this->filename;\n\n        $when = function () use ($closure, $filename, $description): void {\n            if ($this::$__filename !== $filename) { // @phpstan-ignore-line\n                return;\n            }\n\n            if ($this->__description !== $description) { // @phpstan-ignore-line\n                return;\n            }\n\n            if ($this->__ran !== true) { // @phpstan-ignore-line\n                return;\n            }\n\n            $closure->call($this);\n        };\n\n        new AfterEachCall($this->testSuite, $this->filename, $when->bindTo(new \\stdClass));\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the test fails with the given message.\n     */\n    public function fails(?string $message = null): self\n    {\n        return $this->throws(AssertionFailedError::class, $message);\n    }\n\n    /**\n     * Asserts that the test throws the given `$exceptionClass` when called.\n     */\n    public function throws(string|int $exception, ?string $exceptionMessage = null, ?int $exceptionCode = null): self\n    {\n        if (is_int($exception)) {\n            $exceptionCode = $exception;\n        } elseif (class_exists($exception)) {\n            $this->testCaseMethod\n                ->proxies\n                ->add(Backtrace::file(), Backtrace::line(), 'expectException', [$exception]);\n        } else {\n            $exceptionMessage = $exception;\n        }\n\n        if (is_string($exceptionMessage)) {\n            $this->testCaseMethod\n                ->proxies\n                ->add(Backtrace::file(), Backtrace::line(), 'expectExceptionMessage', [$exceptionMessage]);\n        }\n\n        if (is_int($exceptionCode)) {\n            $this->testCaseMethod\n                ->proxies\n                ->add(Backtrace::file(), Backtrace::line(), 'expectExceptionCode', [$exceptionCode]);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the test throws the given `$exceptionClass` when called if the given condition is true.\n     *\n     * @param  (callable(): bool)|bool  $condition\n     */\n    public function throwsIf(callable|bool $condition, string|int $exception, ?string $exceptionMessage = null, ?int $exceptionCode = null): self\n    {\n        $condition = is_callable($condition)\n            ? $condition\n            : static fn (): bool => $condition;\n\n        if ($condition()) {\n            return $this->throws($exception, $exceptionMessage, $exceptionCode);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Asserts that the test throws the given `$exceptionClass` when called if the given condition is false.\n     *\n     * @param  (callable(): bool)|bool  $condition\n     */\n    public function throwsUnless(callable|bool $condition, string|int $exception, ?string $exceptionMessage = null, ?int $exceptionCode = null): self\n    {\n        $condition = is_callable($condition)\n            ? $condition\n            : static fn (): bool => $condition;\n\n        if (! $condition()) {\n            return $this->throws($exception, $exceptionMessage, $exceptionCode);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Runs the current test multiple times with each item of the given `iterable`.\n     *\n     * @param  Closure|iterable<array-key, mixed>|string  $data\n     */\n    public function with(Closure|iterable|string ...$data): self\n    {\n        foreach ($data as $dataset) {\n            $this->testCaseMethod->datasets[] = $dataset;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Sets the test depends.\n     */\n    public function depends(string ...$depends): self\n    {\n        foreach ($depends as $depend) {\n            $this->testCaseMethod->depends[] = $depend;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Sets the test group(s).\n     */\n    public function group(string ...$groups): self\n    {\n        foreach ($groups as $group) {\n            $this->testCaseMethod->attributes[] = new Attribute(\n                Group::class,\n                [$group],\n            );\n        }\n\n        return $this;\n    }\n\n    /**\n     * Filters the test suite by \"only\" tests.\n     */\n    public function only(): self\n    {\n        Only::enable($this, ...func_get_args());\n\n        return $this;\n    }\n\n    /**\n     * Skips the current test.\n     */\n    public function skip(Closure|bool|string $conditionOrMessage = true, string $message = ''): self\n    {\n        $condition = is_string($conditionOrMessage)\n            ? NullClosure::create()\n            : $conditionOrMessage;\n\n        $condition = is_callable($condition)\n            ? $condition\n            : fn (): bool => $condition;\n\n        $message = is_string($conditionOrMessage)\n            ? $conditionOrMessage\n            : $message;\n\n        /** @var callable(): bool $condition */\n        $condition = $condition->bindTo(null);\n\n        $this->testCaseMethod\n            ->chains\n            ->addWhen($condition, $this->filename, Backtrace::line(), 'markTestSkipped', [$message]);\n\n        return $this;\n    }\n\n    /**\n     * Skips the current test on the given PHP version.\n     */\n    public function skipOnPhp(string $version): self\n    {\n        if (mb_strlen($version) < 2) {\n            throw new InvalidArgumentException('The version must start with [<] or [>].');\n        }\n\n        if (str_starts_with($version, '>=') || str_starts_with($version, '<=')) {\n            $operator = substr($version, 0, 2);\n            $version = substr($version, 2);\n        } elseif (str_starts_with($version, '>') || str_starts_with($version, '<')) {\n            $operator = $version[0];\n            $version = substr($version, 1);\n            // ensure starts with number:\n        } elseif (is_numeric($version[0])) {\n            $operator = '==';\n        } else {\n            throw new InvalidArgumentException('The version must start with [<, >, <=, >=] or a number.');\n        }\n\n        return $this->skip(version_compare(PHP_VERSION, $version, $operator), sprintf('This test is skipped on PHP [%s%s].', $operator, $version));\n    }\n\n    /**\n     * Skips the current test if the given test is running on Windows.\n     */\n    public function skipOnWindows(): self\n    {\n        return $this->skipOnOs('Windows', 'This test is skipped on [Windows].');\n    }\n\n    /**\n     * Skips the current test if the given test is running on Mac OS.\n     */\n    public function skipOnMac(): self\n    {\n        return $this->skipOnOs('Darwin', 'This test is skipped on [Mac].');\n    }\n\n    /**\n     * Skips the current test if the given test is running on Linux.\n     */\n    public function skipOnLinux(): self\n    {\n        return $this->skipOnOs('Linux', 'This test is skipped on [Linux].');\n    }\n\n    /**\n     * Skips the current test if the given test is running on the given operating systems.\n     */\n    private function skipOnOs(string $osFamily, string $message): self\n    {\n        return $osFamily === PHP_OS_FAMILY\n            ? $this->skip($message)\n            : $this;\n    }\n\n    /**\n     * Weather the current test is running on a CI environment.\n     */\n    private function runningOnCI(): bool\n    {\n        foreach ([\n            'CI',\n            'GITHUB_ACTIONS',\n            'GITLAB_CI',\n            'CIRCLECI',\n            'TRAVIS',\n            'APPVEYOR',\n            'BITBUCKET_BUILD_NUMBER',\n            'BUILDKITE',\n            'TEAMCITY_VERSION',\n            'JENKINS_URL',\n            'SYSTEM_COLLECTIONURI',\n            'CI_NAME',\n            'TASKCLUSTER_ROOT_URL',\n            'DRONE',\n            'WERCKER',\n            'NEVERCODE',\n            'SEMAPHORE',\n            'NETLIFY',\n            'NOW_BUILDER',\n        ] as $env) {\n            if (getenv($env) !== false) {\n                return true;\n            }\n        }\n\n        return Environment::name() === Environment::CI;\n    }\n\n    /**\n     * Skips the current test when running on a CI environments.\n     */\n    public function skipOnCI(): self\n    {\n        if ($this->runningOnCI()) {\n            return $this->skip('This test is skipped on [CI].');\n        }\n\n        return $this;\n    }\n\n    public function skipLocally(): self\n    {\n        if ($this->runningOnCI() === false) {\n            return $this->skip('This test is skipped [locally].');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Skips the current test unless the given test is running on Windows.\n     */\n    public function onlyOnWindows(): self\n    {\n        return $this->skipOnMac()->skipOnLinux();\n    }\n\n    /**\n     * Skips the current test unless the given test is running on Mac.\n     */\n    public function onlyOnMac(): self\n    {\n        return $this->skipOnWindows()->skipOnLinux();\n    }\n\n    /**\n     * Skips the current test unless the given test is running on Linux.\n     */\n    public function onlyOnLinux(): self\n    {\n        return $this->skipOnWindows()->skipOnMac();\n    }\n\n    /**\n     * Repeats the current test the given number of times.\n     */\n    public function repeat(int $times): self\n    {\n        if ($times < 1) {\n            throw new InvalidArgumentException('The number of repetitions must be greater than 0.');\n        }\n\n        $this->testCaseMethod->repetitions = $times;\n\n        return $this;\n    }\n\n    /**\n     * Marks the test as \"todo\".\n     */\n    public function todo(// @phpstan-ignore-line\n        array|string|null $note = null,\n        array|string|null $assignee = null,\n        array|string|int|null $issue = null,\n        array|string|int|null $pr = null,\n    ): self {\n        $this->skip('__TODO__');\n\n        $this->testCaseMethod->todo = true;\n\n        if ($issue !== null) {\n            $this->issue($issue);\n        }\n\n        if ($pr !== null) {\n            $this->pr($pr);\n        }\n\n        if ($assignee !== null) {\n            $this->assignee($assignee);\n        }\n\n        if ($note !== null) {\n            $this->note($note);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Sets the test as \"work in progress\".\n     */\n    public function wip(// @phpstan-ignore-line\n        array|string|null $note = null,\n        array|string|null $assignee = null,\n        array|string|int|null $issue = null,\n        array|string|int|null $pr = null,\n    ): self {\n        if ($issue !== null) {\n            $this->issue($issue);\n        }\n\n        if ($pr !== null) {\n            $this->pr($pr);\n        }\n\n        if ($assignee !== null) {\n            $this->assignee($assignee);\n        }\n\n        if ($note !== null) {\n            $this->note($note);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Sets the test as \"done\".\n     */\n    public function done(// @phpstan-ignore-line\n        array|string|null $note = null,\n        array|string|null $assignee = null,\n        array|string|int|null $issue = null,\n        array|string|int|null $pr = null,\n    ): self {\n        if ($issue !== null) {\n            $this->issue($issue);\n        }\n\n        if ($pr !== null) {\n            $this->pr($pr);\n        }\n\n        if ($assignee !== null) {\n            $this->assignee($assignee);\n        }\n\n        if ($note !== null) {\n            $this->note($note);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Associates the test with the given issue(s).\n     *\n     * @param  array<int, string|int>|string|int  $number\n     */\n    public function issue(array|string|int $number): self\n    {\n        $number = is_array($number) ? $number : [$number];\n\n        $number = array_map(fn (string|int $number): int => (int) ltrim((string) $number, '#'), $number);\n\n        $this->testCaseMethod->issues = array_merge($this->testCaseMethod->issues, $number);\n\n        return $this;\n    }\n\n    /**\n     * Associates the test with the given ticket(s). (Alias for `issue`)\n     *\n     * @param  array<int, string|int>|string|int  $number\n     */\n    public function ticket(array|string|int $number): self\n    {\n        return $this->issue($number);\n    }\n\n    /**\n     * Sets the test assignee(s).\n     *\n     * @param  array<int, string>|string  $assignee\n     */\n    public function assignee(array|string $assignee): self\n    {\n        $assignees = is_array($assignee) ? $assignee : [$assignee];\n\n        $this->testCaseMethod->assignees = array_unique(array_merge($this->testCaseMethod->assignees, $assignees));\n\n        return $this;\n    }\n\n    /**\n     * Associates the test with the given pull request(s).\n     *\n     * @param  array<int, string|int>|string|int  $number\n     */\n    public function pr(array|string|int $number): self\n    {\n        $number = is_array($number) ? $number : [$number];\n\n        $number = array_map(fn (string|int $number): int => (int) ltrim((string) $number, '#'), $number);\n\n        $this->testCaseMethod->prs = array_unique(array_merge($this->testCaseMethod->prs, $number));\n\n        return $this;\n    }\n\n    /**\n     * Adds a note to the test.\n     *\n     * @param  array<int, string>|string  $note\n     */\n    public function note(array|string $note): self\n    {\n        $notes = is_array($note) ? $note : [$note];\n\n        $this->testCaseMethod->notes = array_unique(array_merge($this->testCaseMethod->notes, $notes));\n\n        return $this;\n    }\n\n    /**\n     * Sets the covered classes or methods.\n     *\n     * @param  array<int, string>|string  $classesOrFunctions\n     */\n    public function covers(array|string ...$classesOrFunctions): self\n    {\n        /** @var array<int, string> $classesOrFunctions */\n        $classesOrFunctions = array_reduce($classesOrFunctions, fn ($carry, $item): array => is_array($item) ? array_merge($carry, $item) : array_merge($carry, [$item]), []); // @pest-ignore-type\n\n        foreach ($classesOrFunctions as $classOrFunction) {\n            $isClass = class_exists($classOrFunction) || interface_exists($classOrFunction) || enum_exists($classOrFunction);\n            $isTrait = trait_exists($classOrFunction);\n            $isFunction = function_exists($classOrFunction);\n\n            if (! $isClass && ! $isTrait && ! $isFunction) {\n                throw new InvalidArgumentException(sprintf('No class, trait or method named \"%s\" has been found.', $classOrFunction));\n            }\n\n            if ($isClass) {\n                $this->coversClass($classOrFunction);\n            } elseif ($isTrait) {\n                $this->coversTrait($classOrFunction);\n            } else {\n                $this->coversFunction($classOrFunction);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Sets the covered classes.\n     */\n    public function coversClass(string ...$classes): self\n    {\n        foreach ($classes as $class) {\n            $this->testCaseFactoryAttributes[] = new Attribute(\n                CoversClass::class,\n                [$class],\n            );\n        }\n\n        /** @var ConfigurationRepository $configurationRepository */\n        $configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);\n        $paths = $configurationRepository->cliConfiguration->toArray()['paths'] ?? false;\n\n        if (! is_array($paths)) {\n            $configurationRepository->globalConfiguration('default')->class(...$classes); // @phpstan-ignore-line\n        }\n\n        return $this;\n    }\n\n    /**\n     * Sets the covered classes.\n     */\n    public function coversTrait(string ...$traits): self\n    {\n        foreach ($traits as $trait) {\n            $this->testCaseFactoryAttributes[] = new Attribute(\n                CoversTrait::class,\n                [$trait],\n            );\n        }\n\n        /** @var ConfigurationRepository $configurationRepository */\n        $configurationRepository = Container::getInstance()->get(ConfigurationRepository::class);\n        $paths = $configurationRepository->cliConfiguration->toArray()['paths'] ?? false;\n\n        if (! is_array($paths)) {\n            $configurationRepository->globalConfiguration('default')->class(...$traits); // @phpstan-ignore-line\n        }\n\n        return $this;\n    }\n\n    /**\n     * Sets the covered functions.\n     */\n    public function coversFunction(string ...$functions): self\n    {\n        foreach ($functions as $function) {\n            $this->testCaseFactoryAttributes[] = new Attribute(\n                CoversFunction::class,\n                [$function],\n            );\n        }\n\n        return $this;\n    }\n\n    /**\n     * Adds one or more references to the tested method or class. This helps\n     * to link test cases to the source code for easier navigation.\n     *\n     * @param  array<class-string|string>|class-string  ...$classes\n     */\n    public function references(string|array ...$classes): self\n    {\n        assert($classes !== []);\n\n        return $this;\n    }\n\n    /**\n     * Adds one or more references to the tested method or class. This helps\n     * to link test cases to the source code for easier navigation.\n     *\n     * @param  array<class-string|string>|class-string  ...$classes\n     */\n    public function see(string|array ...$classes): self\n    {\n        return $this->references(...$classes);\n    }\n\n    /**\n     * Informs the test runner that no expectations happen in this test,\n     * and its purpose is simply to check whether the given code can\n     * be executed without throwing exceptions.\n     */\n    public function throwsNoExceptions(): self\n    {\n        $this->testCaseMethod->proxies->add(Backtrace::file(), Backtrace::line(), 'expectNotToPerformAssertions', []);\n\n        return $this;\n    }\n\n    /**\n     * Saves the property accessors to be used on the target.\n     */\n    public function __get(string $name): self\n    {\n        return $this->addChain(Backtrace::file(), Backtrace::line(), $name);\n    }\n\n    /**\n     * Saves the calls to be used on the target.\n     *\n     * @param  array<int, mixed>  $arguments\n     */\n    public function __call(string $name, array $arguments): self\n    {\n        return $this->addChain(Backtrace::file(), Backtrace::line(), $name, $arguments);\n    }\n\n    /**\n     * Add a chain to the test case factory. Omitting the arguments will treat it as a property accessor.\n     *\n     * @param  array<int, mixed>|null  $arguments\n     */\n    private function addChain(string $file, int $line, string $name, ?array $arguments = null): self\n    {\n        $exporter = Exporter::default();\n\n        $this->testCaseMethod\n            ->chains\n            ->add($file, $line, $name, $arguments);\n\n        if ($this->descriptionLess) {\n            Exporter::default();\n\n            if ($this->description !== null) {\n                $this->description .= ' → ';\n            }\n\n            $this->description .= $arguments === null\n                ? $name\n                : sprintf('%s %s', $name, $exporter->shortenedRecursiveExport($arguments));\n        }\n\n        return $this;\n    }\n\n    /**\n     * Creates the Call.\n     */\n    public function __destruct()\n    {\n        if ($this->description === null) {\n            throw new TestDescriptionMissing($this->filename);\n        }\n\n        if ($this->describing !== []) {\n            $this->testCaseMethod->describing = $this->describing;\n            $this->testCaseMethod->description = Str::describe($this->describing, $this->description);\n        } else {\n            $this->testCaseMethod->description = $this->description;\n        }\n\n        $this->testSuite->tests->set($this->testCaseMethod);\n\n        if (! is_null($testCase = $this->testSuite->tests->get($this->filename))) {\n            $attributesToMerge = array_filter(\n                $this->testCaseFactoryAttributes,\n                fn (Attribute $attributeToMerge): bool => array_filter($testCase->attributes, fn (Attribute $attribute): bool => serialize($attributeToMerge) === serialize($attribute)) === []\n            );\n\n            $testCase->attributes = array_merge($testCase->attributes, $attributesToMerge);\n        }\n    }\n}\n"
  },
  {
    "path": "src/PendingCalls/UsesCall.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\PendingCalls;\n\nuse Closure;\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\Printers\\DefaultPrinter;\nuse Pest\\TestSuite;\n\n/**\n * @internal\n */\nfinal class UsesCall\n{\n    /**\n     * Contains a global before each hook closure to be executed.\n     *\n     * Array indices here matter. They are mapped as follows:\n     *\n     * - `0` => `beforeAll`\n     * - `1` => `beforeEach`\n     * - `2` => `afterEach`\n     * - `3` => `afterAll`\n     *\n     * @var array<int, Closure>\n     */\n    private array $hooks = [];\n\n    /**\n     * Holds the targets of the uses.\n     *\n     * @var array<int, string>\n     */\n    private array $targets;\n\n    /**\n     * Holds the groups of the uses.\n     *\n     * @var array<int, string>\n     */\n    private array $groups = [];\n\n    /**\n     * Creates a new Pending Call.\n     *\n     * @param  array<int, string>  $classAndTraits\n     */\n    public function __construct(\n        private readonly string $filename,\n        private array $classAndTraits\n    ) {\n        $this->targets = [$filename];\n    }\n\n    /**\n     * @deprecated Use `pest()->printer()->compact()` instead.\n     */\n    public function compact(): self\n    {\n        DefaultPrinter::compact(true);\n\n        return $this;\n    }\n\n    /**\n     * Specifies the class or traits to use.\n     *\n     * @alias extend\n     */\n    public function use(string ...$classAndTraits): self\n    {\n        return $this->extend(...$classAndTraits);\n    }\n\n    /**\n     * Specifies the class or traits to use.\n     */\n    public function extend(string ...$classAndTraits): self\n    {\n        $this->classAndTraits = array_merge($this->classAndTraits, array_values($classAndTraits));\n\n        return $this;\n    }\n\n    /**\n     * The directories or file where the class or traits should be used.\n     */\n    public function in(string ...$targets): self\n    {\n        $targets = array_map(function (string $path): string {\n            $startChar = DIRECTORY_SEPARATOR;\n\n            if ('\\\\' === DIRECTORY_SEPARATOR || preg_match('~\\A[A-Z]:(?![^/\\\\\\\\])~i', $path) > 0) {\n                $path = (string) preg_replace_callback('~^(?P<drive>[a-z]+:\\\\\\)~i', fn (array $match): string => strtolower($match['drive']), $path);\n\n                $startChar = strtolower((string) preg_replace('~^([a-z]+:\\\\\\).*$~i', '$1', __DIR__));\n            }\n\n            return str_starts_with($path, $startChar)\n                ? $path\n                : implode(DIRECTORY_SEPARATOR, [\n                    is_dir($this->filename) ? $this->filename : dirname($this->filename),\n                    $path,\n                ]);\n        }, $targets);\n\n        $this->targets = array_reduce($targets, function (array $accumulator, string $target): array {\n            if (($matches = glob($target)) !== false) {\n                foreach ($matches as $file) {\n                    $accumulator[] = (string) realpath($file);\n                }\n            }\n\n            return $accumulator;\n        }, []);\n\n        return $this;\n    }\n\n    /**\n     * Sets the test group(s).\n     */\n    public function group(string ...$groups): self\n    {\n        $this->groups = array_values($groups);\n\n        return $this;\n    }\n\n    /**\n     * Sets the global beforeAll test hook.\n     */\n    public function beforeAll(Closure $hook): self\n    {\n        $this->hooks[0] = $hook;\n\n        return $this;\n    }\n\n    /**\n     * Sets the global beforeEach test hook.\n     */\n    public function beforeEach(Closure $hook): self\n    {\n        $this->hooks[1] = $hook;\n\n        return $this;\n    }\n\n    /**\n     * Sets the global afterEach test hook.\n     */\n    public function afterEach(Closure $hook): self\n    {\n        $this->hooks[2] = $hook;\n\n        return $this;\n    }\n\n    /**\n     * Sets the global afterAll test hook.\n     */\n    public function afterAll(Closure $hook): self\n    {\n        $this->hooks[3] = $hook;\n\n        return $this;\n    }\n\n    /**\n     * Creates the Call.\n     */\n    public function __destruct()\n    {\n        TestSuite::getInstance()->tests->use(\n            $this->classAndTraits,\n            $this->groups,\n            $this->targets,\n            $this->hooks,\n        );\n    }\n}\n"
  },
  {
    "path": "src/Pest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nfunction version(): string\n{\n    return '4.4.2';\n}\n\nfunction testDirectory(string $file = ''): string\n{\n    return TestSuite::getInstance()->testPath.DIRECTORY_SEPARATOR.$file;\n}\n"
  },
  {
    "path": "src/Plugin.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nfinal class Plugin\n{\n    /**\n     * The lazy callables to be executed once the test suite boots.\n     *\n     * @var array<int, callable>\n     *\n     * @internal\n     */\n    public static array $callables = [];\n\n    /**\n     * Lazy loads an `uses` call on the context of plugins.\n     *\n     * @param  class-string  ...$traits\n     */\n    public static function uses(string ...$traits): void\n    {\n        self::$callables[] = function () use ($traits): void {\n            uses(...$traits)->in(TestSuite::getInstance()->rootPath);\n        };\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Actions/CallsAddsOutput.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Actions;\n\nuse Pest\\Contracts\\Plugins;\nuse Pest\\Plugin\\Loader;\n\n/**\n * @internal\n */\nfinal class CallsAddsOutput\n{\n    /**\n     * Executes the Plugin action.\n     *\n     * Provides an opportunity for any plugins that want to provide additional output after test execution.\n     */\n    public static function execute(int $exitCode): int\n    {\n        $plugins = Loader::getPlugins(Plugins\\AddsOutput::class);\n\n        /** @var Plugins\\AddsOutput $plugin */\n        foreach ($plugins as $plugin) {\n            $exitCode = $plugin->addOutput($exitCode);\n        }\n\n        return $exitCode;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Actions/CallsBoot.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Actions;\n\nuse Pest\\Contracts\\Plugins;\nuse Pest\\Plugin\\Loader;\n\n/**\n * @internal\n */\nfinal class CallsBoot\n{\n    /**\n     * Executes the Plugin action.\n     *\n     * Provides an opportunity for any plugins to boot.\n     */\n    public static function execute(): void\n    {\n        $plugins = Loader::getPlugins(Plugins\\Bootable::class);\n\n        /** @var Plugins\\Bootable $plugin */\n        foreach ($plugins as $plugin) {\n            $plugin->boot();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Actions/CallsHandleArguments.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Actions;\n\nuse Pest\\Contracts\\Plugins;\nuse Pest\\Plugin\\Loader;\n\n/**\n * @internal\n */\nfinal class CallsHandleArguments\n{\n    /**\n     * Executes the Plugin action.\n     *\n     * Transform the input arguments by passing it to the relevant plugins.\n     *\n     * @param  array<int, string>  $argv\n     * @return array<int, string>\n     */\n    public static function execute(array $argv): array\n    {\n        $plugins = Loader::getPlugins(Plugins\\HandlesArguments::class);\n\n        /** @var Plugins\\HandlesArguments $plugin */\n        foreach ($plugins as $plugin) {\n            $argv = $plugin->handleArguments($argv);\n        }\n\n        return $argv;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Actions/CallsHandleOriginalArguments.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Actions;\n\nuse Pest\\Contracts\\Plugins;\nuse Pest\\Plugin\\Loader;\n\n/**\n * @internal\n */\nfinal class CallsHandleOriginalArguments\n{\n    /**\n     * Executes the Plugin action.\n     *\n     * Transform the input arguments by passing it to the relevant plugins.\n     *\n     * @param  array<int, string>  $argv\n     */\n    public static function execute(array $argv): void\n    {\n        $plugins = Loader::getPlugins(Plugins\\HandlesOriginalArguments::class);\n\n        /** @var Plugins\\HandlesOriginalArguments $plugin */\n        foreach ($plugins as $plugin) {\n            $plugin->handleOriginalArguments($argv);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Actions/CallsTerminable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Actions;\n\nuse Pest\\Contracts\\Plugins;\nuse Pest\\Plugin\\Loader;\n\n/**\n * @internal\n */\nfinal class CallsTerminable\n{\n    /**\n     * Executes the Plugin action.\n     *\n     * Provides an opportunity for any plugins to terminate.\n     */\n    public static function execute(): void\n    {\n        $plugins = Loader::getPlugins(Plugins\\Terminable::class);\n\n        /** @var Plugins\\Terminable $plugin */\n        foreach ($plugins as $plugin) {\n            $plugin->terminate();\n        }\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Bail.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Plugins\\Concerns\\HandleArguments;\n\n/**\n * @internal\n */\nfinal class Bail implements HandlesArguments\n{\n    use HandleArguments;\n\n    /**\n     * Handles the arguments, adding the `--stop-on-defect` when the `--bail` argument is present.\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if ($this->hasArgument('--bail', $arguments)) {\n            $arguments = $this->popArgument('--bail', $arguments);\n\n            $arguments = $this->pushArgument('--stop-on-failure', $arguments);\n            $arguments = $this->pushArgument('--stop-on-error', $arguments);\n        }\n\n        return $arguments;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Cache.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Plugins\\Concerns\\HandleArguments;\nuse PHPUnit\\TextUI\\CliArguments\\Builder as CliConfigurationBuilder;\nuse PHPUnit\\TextUI\\CliArguments\\XmlConfigurationFileFinder;\nuse PHPUnit\\TextUI\\XmlConfiguration\\DefaultConfiguration;\nuse PHPUnit\\TextUI\\XmlConfiguration\\Loader;\n\n/**\n * @internal\n */\nfinal class Cache implements HandlesArguments\n{\n    use HandleArguments;\n\n    /**\n     * The temporary folder.\n     */\n    private const string TEMPORARY_FOLDER = __DIR__\n        .DIRECTORY_SEPARATOR\n        .'..'\n        .DIRECTORY_SEPARATOR\n        .'..'\n        .DIRECTORY_SEPARATOR\n        .'.temp';\n\n    /**\n     * Handles the arguments, adding the cache directory and the cache result arguments.\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if (! $this->hasArgument('--cache-directory', $arguments)) {\n\n            $cliConfiguration = (new CliConfigurationBuilder)->fromParameters([]);\n            $configurationFile = (new XmlConfigurationFileFinder)->find($cliConfiguration);\n            $xmlConfiguration = DefaultConfiguration::create();\n\n            if (is_string($configurationFile)) {\n                $xmlConfiguration = (new Loader)->load($configurationFile);\n            }\n\n            if (! $xmlConfiguration->phpunit()->hasCacheDirectory()) {\n                $arguments = $this->pushArgument('--cache-directory', $arguments);\n                $arguments = $this->pushArgument((string) realpath(self::TEMPORARY_FOLDER), $arguments);\n            }\n        }\n\n        if (! $this->hasArgument('--parallel', $arguments)) {\n            return $this->pushArgument('--cache-result', $arguments);\n        }\n\n        return $arguments;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Concerns/HandleArguments.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Concerns;\n\n/**\n * @internal\n */\ntrait HandleArguments\n{\n    /**\n     * Checks if the given argument exists on the arguments.\n     *\n     * @param  array<int, string>  $arguments\n     */\n    public function hasArgument(string $argument, array $arguments): bool\n    {\n        foreach ($arguments as $arg) {\n            if ($arg === $argument) {\n                return true;\n            }\n\n            if (str_starts_with((string) $arg, \"$argument=\")) { // @phpstan-ignore-line\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Adds the given argument and value to the list of arguments.\n     *\n     * @param  array<int, string>  $arguments\n     * @return array<int, string>\n     */\n    public function pushArgument(string $argument, array $arguments): array\n    {\n        $arguments[] = $argument;\n\n        return $arguments;\n    }\n\n    /**\n     * Pops the given argument from the arguments.\n     *\n     * @param  array<int, string>  $arguments\n     * @return array<int, string>\n     */\n    public function popArgument(string $argument, array $arguments): array\n    {\n        $arguments = array_flip($arguments);\n\n        unset($arguments[$argument]);\n\n        return array_values(array_flip($arguments));\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Configuration.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse DOMDocument;\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Contracts\\Plugins\\Terminable;\nuse Pest\\Plugins\\Concerns\\HandleArguments;\nuse PHPUnit\\TextUI\\CliArguments\\Builder as CliConfigurationBuilder;\nuse PHPUnit\\TextUI\\CliArguments\\XmlConfigurationFileFinder;\n\n/**\n * @internal\n */\nfinal class Configuration implements HandlesArguments, Terminable\n{\n    use HandleArguments;\n\n    /**\n     * The base PHPUnit file.\n     */\n    public const string BASE_PHPUNIT_FILE = __DIR__\n        .DIRECTORY_SEPARATOR\n        .'..'\n        .DIRECTORY_SEPARATOR\n        .'..'\n        .DIRECTORY_SEPARATOR\n        .'resources/base-phpunit.xml';\n\n    /**\n     * Handles the arguments, adding the cache directory and the cache result arguments.\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if ($this->hasArgument('--configuration', $arguments) || $this->hasArgument('-c', $arguments) || $this->hasCustomConfigurationFile()) {\n            return $arguments;\n        }\n\n        $arguments = $this->pushArgument('--configuration', $arguments);\n\n        return $this->pushArgument((string) realpath($this->fromGeneratedConfigurationFile()), $arguments);\n    }\n\n    /**\n     * Get the configuration file from the generated configuration file.\n     */\n    private function fromGeneratedConfigurationFile(): string\n    {\n        $path = $this->getTempPhpunitXmlPath();\n        if (file_exists($path)) {\n            unlink($path);\n        }\n\n        $doc = new DOMDocument;\n        $doc->load(self::BASE_PHPUNIT_FILE);\n\n        $contents = $doc->saveXML();\n\n        assert(is_int(file_put_contents($path, $contents)));\n\n        return $path;\n    }\n\n    /**\n     * Check if the configuration file is custom.\n     */\n    private function hasCustomConfigurationFile(): bool\n    {\n        $cliConfiguration = (new CliConfigurationBuilder)->fromParameters([]);\n        $configurationFile = (new XmlConfigurationFileFinder)->find($cliConfiguration);\n\n        return is_string($configurationFile);\n    }\n\n    /**\n     * Get the temporary phpunit.xml path.\n     */\n    private function getTempPhpunitXmlPath(): string\n    {\n        return getcwd().'/.pest.xml';\n    }\n\n    /**\n     * Terminates the plugin.\n     */\n    public function terminate(): void\n    {\n        $path = $this->getTempPhpunitXmlPath();\n\n        if (file_exists($path)) {\n            unlink($path);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Coverage.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\AddsOutput;\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Support\\Str;\nuse Symfony\\Component\\Console\\Input\\ArgvInput;\nuse Symfony\\Component\\Console\\Input\\InputDefinition;\nuse Symfony\\Component\\Console\\Input\\InputOption;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal class Coverage implements AddsOutput, HandlesArguments\n{\n    private const string COVERAGE_OPTION = 'coverage';\n\n    private const string MIN_OPTION = 'min';\n\n    private const string EXACTLY_OPTION = 'exactly';\n\n    /**\n     * Whether it should show the coverage or not.\n     */\n    public bool $coverage = false;\n\n    /**\n     * Whether it should show the coverage or not.\n     */\n    public bool $compact = false;\n\n    /**\n     * The minimum coverage.\n     */\n    public float $coverageMin = 0.0;\n\n    /**\n     * The exactly coverage.\n     */\n    public ?float $coverageExactly = null;\n\n    /**\n     * Creates a new Plugin instance.\n     */\n    public function __construct(private readonly OutputInterface $output)\n    {\n        // ..\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function handleArguments(array $originals): array\n    {\n        $arguments = [...[''], ...array_values(array_filter($originals, function (string $original): bool {\n            foreach ([self::COVERAGE_OPTION, self::MIN_OPTION, self::EXACTLY_OPTION] as $option) {\n                if ($original === sprintf('--%s', $option)) {\n                    return true;\n                }\n\n                if (Str::startsWith($original, sprintf('--%s=', $option))) {\n                    return true;\n                }\n            }\n\n            return false;\n        }))];\n\n        $originals = array_flip($originals);\n        foreach ($arguments as $argument) {\n            unset($originals[$argument]);\n        }\n        $originals = array_flip($originals);\n\n        $inputs = [];\n        $inputs[] = new InputOption(self::COVERAGE_OPTION, null, InputOption::VALUE_NONE);\n        $inputs[] = new InputOption(self::MIN_OPTION, null, InputOption::VALUE_REQUIRED);\n        $inputs[] = new InputOption(self::EXACTLY_OPTION, null, InputOption::VALUE_REQUIRED);\n\n        $input = new ArgvInput($arguments, new InputDefinition($inputs));\n        if ((bool) $input->getOption(self::COVERAGE_OPTION)) {\n            $this->coverage = true;\n            $originals[] = '--coverage-php';\n            $originals[] = \\Pest\\Support\\Coverage::getPath();\n\n            if (! \\Pest\\Support\\Coverage::isAvailable()) {\n                if (\\Pest\\Support\\Coverage::usingXdebug()) {\n                    $this->output->writeln([\n                        '',\n                        \"  <fg=default;bg=red;options=bold> ERROR </> Unable to get coverage using Xdebug. Did you set <href=https://xdebug.org/docs/code_coverage#mode>Xdebug's coverage mode</>?</>\",\n                        '',\n                    ]);\n                } else {\n                    $this->output->writeln([\n                        '',\n                        '  <fg=default;bg=red;options=bold> ERROR </> No code coverage driver is available.</>',\n                        '',\n                    ]);\n                }\n\n                exit(1);\n            }\n        }\n\n        if ($input->getOption(self::MIN_OPTION) !== null) {\n            /** @var int|float $minOption */\n            $minOption = $input->getOption(self::MIN_OPTION);\n\n            $this->coverageMin = (float) $minOption;\n        }\n\n        if ($input->getOption(self::EXACTLY_OPTION) !== null) {\n            /** @var int|float $exactlyOption */\n            $exactlyOption = $input->getOption(self::EXACTLY_OPTION);\n\n            $this->coverageExactly = (float) $exactlyOption;\n        }\n\n        if ($_SERVER['COLLISION_PRINTER_COMPACT'] ?? false) {\n            $this->compact = true;\n        }\n\n        return $originals;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function addOutput(int $exitCode): int\n    {\n        if (Parallel::isWorker()) {\n            return $exitCode;\n        }\n\n        if ($exitCode === 0 && $this->coverage) {\n            if (! \\Pest\\Support\\Coverage::isAvailable()) {\n                $this->output->writeln(\n                    \"\\n  <fg=white;bg=red;options=bold> ERROR </> No code coverage driver is available.</>\",\n                );\n                exit(1);\n            }\n\n            $coverage = \\Pest\\Support\\Coverage::report($this->output, $this->compact);\n            $exitCode = (int) ($coverage < $this->coverageMin);\n\n            if ($exitCode === 0 && $this->coverageExactly !== null) {\n                $comparableCoverage = $this->computeComparableCoverage($coverage);\n                $comparableCoverageExactly = $this->computeComparableCoverage($this->coverageExactly);\n\n                $exitCode = $comparableCoverage === $comparableCoverageExactly ? 0 : 1;\n\n                if ($exitCode === 1) {\n                    $this->output->writeln(sprintf(\n                        \"\\n  <fg=white;bg=red;options=bold> FAIL </> Code coverage not exactly <fg=white;options=bold> %s %%</>, currently <fg=red;options=bold> %s %%</>.\",\n                        number_format($this->coverageExactly, 1),\n                        number_format(floor($coverage * 10) / 10, 1),\n                    ));\n                }\n            } elseif ($exitCode === 1) {\n                $this->output->writeln(sprintf(\n                    \"\\n  <fg=white;bg=red;options=bold> FAIL </> Code coverage below expected <fg=white;options=bold> %s %%</>, currently <fg=red;options=bold> %s %%</>.\",\n                    number_format($this->coverageMin, 1),\n                    number_format(floor($coverage * 10) / 10, 1)\n                ));\n            }\n\n            $this->output->writeln(['']);\n        }\n\n        return $exitCode;\n    }\n\n    /**\n     * Computes the comparable coverage to a percentage with one decimal.\n     */\n    private function computeComparableCoverage(float $coverage): float\n    {\n        return floor($coverage * 10) / 10;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Environment.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\n\n/**\n * @internal\n */\nfinal class Environment implements HandlesArguments\n{\n    /**\n     * The continuous integration environment.\n     */\n    public const string CI = 'ci';\n\n    /**\n     * The local environment.\n     */\n    public const string LOCAL = 'local';\n\n    /**\n     * The current environment.\n     */\n    private static ?string $name = null;\n\n    /**\n     * {@inheritdoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        foreach ($arguments as $index => $argument) {\n            if ($argument === '--ci') {\n                unset($arguments[$index]);\n\n                self::$name = self::CI;\n            }\n        }\n\n        return array_values($arguments);\n    }\n\n    /**\n     * Gets the environment name.\n     */\n    public static function name(?string $name = null): string\n    {\n        if (is_string($name)) {\n            self::$name = $name;\n        }\n\n        return self::$name ?? self::LOCAL;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Help.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Support\\View;\nuse PHPUnit\\TextUI\\Help as PHPUnitHelp;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\nuse function Pest\\version;\n\n/**\n * @internal\n */\nfinal readonly class Help implements HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    /**\n     * Creates a new Plugin instance.\n     */\n    public function __construct(\n        private OutputInterface $output\n    ) {\n        // ..\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if ($this->hasArgument('--help', $arguments)) {\n            View::render('version', [\n                'version' => version(),\n            ]);\n\n            View::render('usage');\n\n            foreach ($this->getContent() as $title => $options) {\n                if ($title === 'Usage') {\n                    continue;\n                }\n\n                $this->output->writeln([\n                    '',\n                    sprintf('  <fg=yellow;options=bold>%s OPTIONS:</>', mb_strtoupper($title)),\n                ]);\n\n                foreach ($options as $option) {\n                    if (! array_key_exists('arg', $option)) {\n                        continue;\n                    }\n\n                    [\n                        'arg' => $argument,\n                        'desc' => $description,\n                    ] = $option;\n\n                    assert(is_string($argument));\n\n                    if (trim($argument) === '--process-isolation') {\n                        continue;\n                    }\n\n                    View::render('components.two-column-detail', [\n                        'left' => $this->colorizeOptions($argument),\n                        'right' => preg_replace(['/</', '/>/'], ['[', ']'], $description),\n                    ]);\n                }\n            }\n\n            $this->output->write('', true);\n\n            exit(0);\n        }\n\n        return $arguments;\n    }\n\n    /**\n     * Colorizes the given string options.\n     */\n    private function colorizeOptions(string $argument): string\n    {\n        return (string) preg_replace(\n            ['/</', '/>/', '/(-+[\\w-]+)/'],\n            ['[', ']', '<fg=blue;options=bold>$1</>'],\n            $argument\n        );\n    }\n\n    /**\n     * @return array<string, array<int, array<'arg'|'desc'|int, array{arg: string, desc: string}|string>>>\n     */\n    private function getContent(): array\n    {\n        $helpReflection = new PHPUnitHelp;\n\n        // @phpstan-ignore-next-line\n        $content = (fn (): array => $this->elements())->call($helpReflection);\n\n        $content['Configuration'] = [...[[\n            'arg' => '--init',\n            'desc' => 'Initialise a standard Pest configuration',\n        ]], ...$content['Configuration']];\n\n        $content['Execution'] = [...[\n            [\n                'arg' => '--parallel',\n                'desc' => 'Run tests in parallel',\n            ],\n            [\n                'arg' => '--update-snapshots',\n                'desc' => 'Update snapshots for tests using the \"toMatchSnapshot\" expectation',\n            ],\n        ], ...$content['Execution']];\n\n        $content['Selection'] = [[\n            'arg' => '--bail',\n            'desc' => 'Stop execution upon first not-passed test',\n        ], [\n            'arg' => '--todos',\n            'desc' => 'Output to standard output the list of todos',\n        ], [\n            'arg' => '--notes',\n            'desc' => 'Output to standard output tests with notes',\n        ], [\n        ], [\n            'arg' => '--issue',\n            'desc' => 'Output to standard output tests with the given issue number',\n        ], [\n        ], [\n            'arg' => '--pr',\n            'desc' => 'Output to standard output tests with the given pull request number',\n        ], [\n        ], [\n            'arg' => '--pull-request',\n            'desc' => 'Output to standard output tests with the given pull request number (alias for --pr)',\n        ], [\n            'arg' => '--retry',\n            'desc' => 'Run non-passing tests first and stop execution upon first error or failure',\n        ], [\n            'arg' => '--dirty',\n            'desc' => 'Only run tests that have uncommitted changes according to Git',\n        ], ...$content['Selection']];\n\n        $content['Reporting'] = [...$content['Reporting'], ...[\n            [\n                'arg' => '--compact',\n                'desc' => 'Replace default result output with Compact format',\n            ],\n        ]];\n\n        $content['Code Coverage'] = [[\n            'arg' => '--coverage ',\n            'desc' => 'Generate code coverage report and output to standard output',\n        ], [\n            'arg' => '--coverage --min',\n            'desc' => 'Set the minimum required coverage percentage, and fail if not met',\n        ], ...$content['Code Coverage']];\n\n        $content['Mutation Testing'] = [[\n            'arg' => '--mutate ',\n            'desc' => 'Runs mutation testing, to understand the quality of your tests',\n        ], [\n            'arg' => '--mutate --parallel',\n            'desc' => 'Runs mutation testing in parallel',\n        ], [\n            'arg' => '--mutate --min',\n            'desc' => 'Set the minimum required mutation score, and fail if not met',\n        ], [\n            'arg' => '--mutate --id',\n            'desc' => 'Run only the mutation with the given ID. But E.g. --id=ecb35ab30ffd3491. Note, you need to provide the same options as the original run',\n        ], [\n            'arg' => '--mutate --covered-only',\n            'desc' => 'Only generate mutations for classes that are covered by tests',\n        ], [\n            'arg' => '--mutate --bail',\n            'desc' => 'Stop mutation testing execution upon first untested or uncovered mutation',\n        ], [\n            'arg' => '--mutate --class',\n            'desc' => 'Generate mutations for the given class(es). E.g. --class=App\\\\\\\\Models',\n        ], [\n            'arg' => '--mutate --ignore',\n            'desc' => 'Ignore the given class(es) when generating mutations. E.g. --ignore=App\\\\\\\\Http\\\\\\\\Requests',\n        ], [\n            'arg' => '--mutate --clear-cache',\n            'desc' => 'Clear the mutation cache',\n        ], [\n            'arg' => '--mutate --no-cache',\n            'desc' => 'Clear the mutation cache',\n        ], [\n            'arg' => '--mutate --ignore-min-score-on-zero-mutations',\n            'desc' => 'Ignore the minimum score requirement when there are no mutations',\n        ], [\n            'arg' => '--mutate --covered-only',\n            'desc' => 'Only generate mutations for classes that are covered by tests',\n        ], [\n            'arg' => '--mutate --everything',\n            'desc' => 'Generate mutations for all classes, even if they are not covered by tests',\n        ], [\n            'arg' => '--mutate --profile',\n            'desc' => 'Output to standard output the top ten slowest mutations',\n        ], [\n            'arg' => '--mutate --retry',\n            'desc' => 'Run untested or uncovered mutations first and stop execution upon first error or failure',\n        ], [\n            'arg' => '--mutate --stop-on-uncovered',\n            'desc' => 'Stop mutation testing execution upon first untested mutation',\n        ], [\n            'arg' => '--mutate --stop-on-untested',\n            'desc' => 'Stop mutation testing execution upon first untested mutation',\n        ]];\n\n        $content['Profiling'] = [\n            [\n                'arg' => '--profile ',\n                'desc' => 'Output to standard output the top ten slowest tests',\n            ],\n        ];\n\n        unset($content['Miscellaneous']);\n\n        return $content;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Init.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Composer\\InstalledVersions;\nuse Pest\\Console\\Thanks;\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Support\\View;\nuse Pest\\TestSuite;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal readonly class Init implements HandlesArguments\n{\n    /**\n     * The option the triggers the init job.\n     */\n    private const string INIT_OPTION = '--init';\n\n    /**\n     * The files that will be created.\n     */\n    private const array STUBS = [\n        'phpunit.xml.stub' => 'phpunit.xml',\n        'Pest.php.stub' => 'tests/Pest.php',\n        'TestCase.php.stub' => 'tests/TestCase.php',\n        'Unit/ExampleTest.php.stub' => 'tests/Unit/ExampleTest.php',\n        'Feature/ExampleTest.php.stub' => 'tests/Feature/ExampleTest.php',\n    ];\n\n    /**\n     * Creates a new Plugin instance.\n     */\n    public function __construct(\n        private TestSuite $testSuite,\n        private InputInterface $input,\n        private OutputInterface $output\n    ) {\n        // ..\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if (! array_key_exists(1, $arguments)) {\n            return $arguments;\n        }\n        if ($arguments[1] !== self::INIT_OPTION) {\n            return $arguments;\n        }\n\n        unset($arguments[1]);\n\n        $this->init();\n\n        exit(0);\n    }\n\n    /**\n     * Initializes the tests directory.\n     */\n    public function init(): void\n    {\n        $testsBaseDir = \"{$this->testSuite->rootPath}/tests\";\n\n        if (! is_dir($testsBaseDir)) {\n            mkdir($testsBaseDir);\n        }\n\n        View::render('components.badge', [\n            'type' => 'INFO',\n            'content' => 'Preparing tests directory.',\n        ]);\n\n        foreach (self::STUBS as $from => $to) {\n            if ($this->isLaravelInstalled()) {\n                $fromPath = __DIR__.\"/../../stubs/init-laravel/{$from}\";\n            } else {\n                $fromPath = __DIR__.\"/../../stubs/init/{$from}\";\n            }\n\n            $toPath = \"{$this->testSuite->rootPath}/{$to}\";\n\n            if (file_exists($toPath)) {\n                View::render('components.two-column-detail', [\n                    'left' => $to,\n                    'right' => 'File already exists.',\n                ]);\n\n                continue;\n            }\n\n            if (! is_dir(dirname($toPath))) {\n                mkdir(dirname($toPath));\n            }\n\n            copy($fromPath, $toPath);\n\n            View::render('components.two-column-detail', [\n                'left' => $to,\n                'right' => 'File created.',\n            ]);\n        }\n\n        View::render('components.new-line');\n\n        (new Thanks($this->input, $this->output))();\n    }\n\n    /**\n     * Checks if laravel is installed through Composer\n     */\n    private function isLaravelInstalled(): bool\n    {\n        return InstalledVersions::isInstalled('laravel/framework');\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Memory.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\AddsOutput;\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal class Memory implements AddsOutput, HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    /**\n     * If memory should be displayed.\n     */\n    private bool $enabled = false;\n\n    /**\n     * Creates a new Plugin instance.\n     */\n    public function __construct(\n        private readonly OutputInterface $output\n    ) {\n        // ..\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        $this->enabled = $this->hasArgument('--memory', $arguments);\n\n        return $this->popArgument('--memory', $arguments);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function addOutput(int $exitCode): int\n    {\n        if ($this->enabled) {\n            $this->output->writeln(sprintf(\n                '  <fg=gray>Memory:</>   <fg=default>%s MB</>',\n                round(memory_get_usage(true) / 1000 ** 2, 3)\n            ));\n        }\n\n        return $exitCode;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Only.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\Terminable;\nuse Pest\\Factories\\Attribute;\nuse Pest\\Factories\\TestCaseMethodFactory;\nuse Pest\\PendingCalls\\TestCall;\nuse PHPUnit\\Framework\\Attributes\\Group;\n\n/**\n * @internal\n */\nfinal class Only implements Terminable\n{\n    /**\n     * The temporary folder.\n     */\n    private const string TEMPORARY_FOLDER = __DIR__\n        .DIRECTORY_SEPARATOR\n        .'..'\n        .DIRECTORY_SEPARATOR\n        .'..'\n        .DIRECTORY_SEPARATOR\n        .'.temp';\n\n    /**\n     * Creates the lock file.\n     */\n    public static function enable(TestCall|TestCaseMethodFactory $testCall, string $group = '__pest_only'): void\n    {\n        if ($testCall instanceof TestCall) {\n            $testCall->group($group);\n        } else {\n            $testCall->attributes[] = new Attribute(\n                Group::class,\n                [$group],\n            );\n        }\n\n        if (Environment::name() === Environment::CI || Parallel::isWorker()) {\n            return;\n        }\n\n        $lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock';\n\n        if (file_exists($lockFile) && $group === '__pest_only') {\n            file_put_contents($lockFile, $group);\n\n            return;\n        }\n\n        if (! file_exists($lockFile)) {\n            touch($lockFile);\n\n            file_put_contents($lockFile, $group);\n        }\n    }\n\n    /**\n     * Checks if \"only\" mode is enabled.\n     */\n    public static function isEnabled(): bool\n    {\n        $lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock';\n\n        return file_exists($lockFile);\n    }\n\n    /**\n     * Returns the group name.\n     */\n    public static function group(): string\n    {\n        $lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock';\n\n        if (! file_exists($lockFile)) {\n            return '__pest_only';\n        }\n\n        return file_get_contents($lockFile) ?: '__pest_only'; // @phpstan-ignore-line\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function terminate(): void\n    {\n        if (Parallel::isWorker()) {\n            return;\n        }\n\n        $lockFile = self::TEMPORARY_FOLDER.DIRECTORY_SEPARATOR.'only.lock';\n\n        if (file_exists($lockFile)) {\n            unlink($lockFile);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Parallel/Contracts/HandlersWorkerArguments.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Parallel\\Contracts;\n\ninterface HandlersWorkerArguments\n{\n    /**\n     * @param  array<int, string>  $arguments\n     * @return array<int, string>\n     */\n    public function handleWorkerArguments(array $arguments): array;\n}\n"
  },
  {
    "path": "src/Plugins/Parallel/Handlers/Laravel.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Parallel\\Handlers;\n\nuse Closure;\nuse Composer\\InstalledVersions;\nuse Illuminate\\Testing\\ParallelRunner;\nuse Orchestra\\Testbench\\TestCase;\nuse ParaTest\\Options;\nuse ParaTest\\RunnerInterface;\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Plugins\\Concerns\\HandleArguments;\nuse Pest\\Plugins\\Parallel\\Paratest\\WrapperRunner;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal class Laravel implements HandlesArguments\n{\n    use HandleArguments;\n\n    /**\n     * {@inheritdoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        return $this->whenUsingLaravel($arguments, function (array $arguments): array {\n            $this->ensureRunnerIsResolvable();\n\n            $arguments = $this->ensureEnvironmentVariables($arguments);\n\n            return $this->ensureRunner($arguments);\n        });\n    }\n\n    /**\n     * Executes the given closure when running Laravel.\n     *\n     * @param  array<int, string>  $arguments\n     * @param  Closure(array<int, string>): array<int, string>  $closure\n     * @return array<int, string>\n     */\n    private function whenUsingLaravel(array $arguments, Closure $closure): array\n    {\n        $isLaravelApplication = InstalledVersions::isInstalled('laravel/framework', false);\n        $isLaravelPackage = class_exists(TestCase::class);\n\n        if ($isLaravelApplication && ! $isLaravelPackage) {\n            return $closure($arguments);\n        }\n\n        return $arguments;\n    }\n\n    /**\n     * Ensures the runner is resolvable.\n     */\n    private function ensureRunnerIsResolvable(): void\n    {\n        ParallelRunner::resolveRunnerUsing( // @phpstan-ignore-line\n            fn (Options $options, OutputInterface $output): RunnerInterface => new WrapperRunner($options, $output)\n        );\n    }\n\n    /**\n     * Ensures the environment variables are set.\n     *\n     * @param  array<int, string>  $arguments\n     * @return array<int, string>\n     */\n    private function ensureEnvironmentVariables(array $arguments): array\n    {\n        $_ENV['LARAVEL_PARALLEL_TESTING'] = 1;\n\n        if ($this->hasArgument('--recreate-databases', $arguments)) {\n            $_ENV['LARAVEL_PARALLEL_TESTING_RECREATE_DATABASES'] = 1;\n        }\n\n        if ($this->hasArgument('--drop-databases', $arguments)) {\n            $_ENV['LARAVEL_PARALLEL_TESTING_DROP_DATABASES'] = 1;\n        }\n\n        $arguments = $this->popArgument('--recreate-databases', $arguments);\n\n        return $this->popArgument('--drop-databases', $arguments);\n    }\n\n    /**\n     * Ensure the runner is set.\n     *\n     * @param  array<int, string>  $arguments\n     * @return array<int, string>\n     */\n    private function ensureRunner(array $arguments): array\n    {\n        foreach ($arguments as $value) {\n            if (str_starts_with($value, '--runner')) {\n                $arguments = $this->popArgument($value, $arguments);\n            }\n        }\n\n        return $this->pushArgument('--runner=\\Illuminate\\Testing\\ParallelRunner', $arguments);\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Parallel/Handlers/Parallel.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Parallel\\Handlers;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Plugins\\Concerns\\HandleArguments;\nuse Pest\\Plugins\\Parallel\\Paratest\\WrapperRunner;\n\n/**\n * @internal\n */\nfinal class Parallel implements HandlesArguments\n{\n    use HandleArguments;\n\n    /**\n     * The list of arguments to remove.\n     */\n    private const array ARGS_TO_REMOVE = [\n        '--parallel',\n        '-p',\n        '--no-output',\n        '--cache-result',\n    ];\n\n    /**\n     * Handles the arguments, removing the ones that are not needed, and adds the \"runner\" argument.\n     */\n    public function handleArguments(array $arguments): array\n    {\n        $args = array_reduce(self::ARGS_TO_REMOVE, fn (array $args, string $arg): array => $this->popArgument($arg, $args), $arguments);\n\n        return $this->pushArgument('--runner='.WrapperRunner::class, $args);\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Parallel/Handlers/Pest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Parallel\\Handlers;\n\nuse Pest\\Plugins\\Concerns\\HandleArguments;\nuse Pest\\Plugins\\Parallel\\Contracts\\HandlersWorkerArguments;\n\nfinal class Pest implements HandlersWorkerArguments\n{\n    use HandleArguments;\n\n    /**\n     * Handles the arguments, adding the \"PEST_PARALLEL\" environment variable to the global $_SERVER.\n     */\n    public function handleWorkerArguments(array $arguments): array\n    {\n        $_SERVER['PEST_PARALLEL'] = '1';\n\n        return $arguments;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Parallel/Paratest/CleanConsoleOutput.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Parallel\\Paratest;\n\nuse Symfony\\Component\\Console\\Output\\ConsoleOutput;\n\nfinal class CleanConsoleOutput extends ConsoleOutput\n{\n    /**\n     * {@inheritdoc}\n     */\n    #[\\Override]\n    protected function doWrite(string $message, bool $newline): void // @pest-arch-ignore-line\n    {\n        if ($this->isOpeningHeadline($message)) {\n            return;\n        }\n\n        parent::doWrite($message, $newline);\n    }\n\n    /**\n     * Removes the opening headline, witch is not needed.\n     */\n    private function isOpeningHeadline(string $message): bool\n    {\n        return str_contains($message, 'by Sebastian Bergmann and contributors.');\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Parallel/Paratest/ResultPrinter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Parallel\\Paratest;\n\nuse ParaTest\\Options;\nuse Pest\\Plugins\\Parallel\\Support\\CompactPrinter;\nuse Pest\\Support\\StateGenerator;\nuse PHPUnit\\TestRunner\\TestResult\\TestResult;\nuse PHPUnit\\TextUI\\Output\\Printer;\nuse SebastianBergmann\\Timer\\Duration;\nuse SplFileInfo;\nuse Symfony\\Component\\Console\\Formatter\\OutputFormatter;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\nuse function assert;\nuse function fclose;\nuse function feof;\nuse function fopen;\nuse function fread;\nuse function fseek;\nuse function ftell;\nuse function fwrite;\nuse function strlen;\n\n/**\n * @internal\n */\nfinal class ResultPrinter\n{\n    /**\n     * If the test should be marked as todo.\n     */\n    public bool $lastWasTodo = false;\n\n    /**\n     * The \"native\" printer.\n     */\n    public readonly Printer $printer;\n\n    /**\n     * The state.\n     */\n    public int $passedTests = 0;\n\n    /**\n     * The \"compact\" printer.\n     */\n    private readonly CompactPrinter $compactPrinter;\n\n    /** @var resource|null */\n    private $teamcityLogFileHandle;\n\n    /** @var array<non-empty-string, int> */\n    private array $tailPositions;\n\n    public function __construct(\n        private readonly OutputInterface $output,\n        private readonly Options $options\n    ) {\n        $this->printer = new readonly class($this->output) implements Printer\n        {\n            public function __construct(\n                private OutputInterface $output,\n            ) {}\n\n            public function print(string $buffer): void\n            {\n                $buffer = OutputFormatter::escape($buffer);\n                if (str_starts_with($buffer, \"\\nGenerating code coverage report\")) {\n                    return;\n                }\n                if (str_starts_with($buffer, 'done [')) {\n                    return;\n                }\n\n                $this->output->write(OutputFormatter::escape($buffer));\n            }\n\n            public function flush(): void {}\n        };\n\n        $this->compactPrinter = CompactPrinter::default();\n\n        if (! $this->options->configuration->hasLogfileTeamcity()) {\n            return;\n        }\n\n        $teamcityLogFileHandle = fopen($this->options->configuration->logfileTeamcity(), 'ab+');\n        assert($teamcityLogFileHandle !== false);\n        $this->teamcityLogFileHandle = $teamcityLogFileHandle;\n    }\n\n    /** @param  list<SplFileInfo>  $teamcityFiles */\n    public function printFeedback(\n        SplFileInfo $progressFile,\n        SplFileInfo $outputFile,\n        array $teamcityFiles\n    ): void {\n        if ($this->options->needsTeamcity) {\n            $teamcityProgress = $this->tailMultiple($teamcityFiles);\n\n            if ($this->teamcityLogFileHandle !== null) {\n                fwrite($this->teamcityLogFileHandle, $teamcityProgress);\n            }\n        }\n\n        if ($this->options->configuration->outputIsTeamCity()) {\n            assert(isset($teamcityProgress));\n            $this->output->write($teamcityProgress);\n\n            return;\n        }\n\n        if ($this->options->configuration->noProgress()) {\n            return;\n        }\n\n        $unexpectedOutput = $this->tail($outputFile);\n        if ($unexpectedOutput !== '') {\n            if (preg_match('/^T+$/', $unexpectedOutput) > 0) {\n                return;\n            }\n\n            $this->output->write($unexpectedOutput);\n        }\n\n        $feedbackItems = $this->tail($progressFile);\n        if ($feedbackItems === '') {\n            return;\n        }\n\n        $feedbackItems = (string) preg_replace('/ +\\\\d+ \\\\/ \\\\d+ \\\\( ?\\\\d+%\\\\)\\\\s*/', '', $feedbackItems);\n\n        $actualTestCount = strlen($feedbackItems);\n        for ($index = 0; $index < $actualTestCount; $index++) {\n            $this->printFeedbackItem($feedbackItems[$index]);\n        }\n    }\n\n    /**\n     * @param  list<SplFileInfo>  $teamcityFiles\n     * @param  list<SplFileInfo>  $testdoxFiles\n     */\n    public function printResults(TestResult $testResult, array $teamcityFiles, array $testdoxFiles, Duration $duration): void\n    {\n        if ($this->options->needsTeamcity) {\n            $teamcityProgress = $this->tailMultiple($teamcityFiles);\n\n            if ($this->teamcityLogFileHandle !== null) {\n                fwrite($this->teamcityLogFileHandle, $teamcityProgress);\n                $resource = $this->teamcityLogFileHandle;\n                $this->teamcityLogFileHandle = null;\n                fclose($resource);\n            }\n        }\n\n        if ($this->options->configuration->outputIsTeamCity()) {\n            assert(isset($teamcityProgress));\n            $this->output->write($teamcityProgress);\n\n            return;\n        }\n\n        if ($this->options->configuration->outputIsTestDox()) {\n            $this->output->write($this->tailMultiple($testdoxFiles));\n\n            return;\n        }\n\n        $state = (new StateGenerator)->fromPhpUnitTestResult($this->passedTests, $testResult);\n\n        $this->compactPrinter->errors($state);\n        $this->compactPrinter->recap($state, $testResult, $duration, $this->options);\n    }\n\n    private function printFeedbackItem(string $item): void\n    {\n        if ($this->lastWasTodo) {\n            $this->lastWasTodo = false;\n\n            return;\n        }\n\n        if ($item === 'T') {\n            $this->lastWasTodo = true;\n        }\n\n        if ($item === '.') {\n            $this->passedTests++;\n        }\n\n        $this->compactPrinter->descriptionItem($item);\n    }\n\n    /** @param  list<SplFileInfo>  $files */\n    private function tailMultiple(array $files): string\n    {\n        $content = '';\n        foreach ($files as $file) {\n            if (! $file->isFile()) {\n                continue;\n            }\n\n            $content .= $this->tail($file);\n        }\n\n        return $content;\n    }\n\n    private function tail(SplFileInfo $file): string\n    {\n        $path = $file->getPathname();\n        assert($path !== '');\n        $handle = fopen($path, 'r');\n        assert($handle !== false);\n        $fseek = fseek($handle, $this->tailPositions[$path] ?? 0);\n        assert($fseek === 0);\n\n        $contents = '';\n        while (! feof($handle)) {\n            $fread = fread($handle, 8192);\n            assert($fread !== false);\n            $contents .= $fread;\n        }\n\n        $ftell = ftell($handle);\n        assert($ftell !== false);\n        $this->tailPositions[$path] = $ftell;\n        fclose($handle);\n\n        return $contents;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Parallel/Paratest/WrapperRunner.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Parallel\\Paratest;\n\nuse const DIRECTORY_SEPARATOR;\n\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\Support\\ResultReflection;\nuse ParaTest\\Coverage\\CoverageMerger;\nuse ParaTest\\JUnit\\LogMerger;\nuse ParaTest\\JUnit\\Writer;\nuse ParaTest\\Options;\nuse ParaTest\\RunnerInterface;\nuse ParaTest\\WrapperRunner\\SuiteLoader;\nuse ParaTest\\WrapperRunner\\WrapperWorker;\nuse Pest\\Result;\nuse Pest\\TestSuite;\nuse PHPUnit\\Event\\Facade as EventFacade;\nuse PHPUnit\\Event\\Test\\AfterLastTestMethodFailed;\nuse PHPUnit\\Event\\TestRunner\\WarningTriggered;\nuse PHPUnit\\Runner\\CodeCoverage;\nuse PHPUnit\\Runner\\ResultCache\\DefaultResultCache;\nuse PHPUnit\\TestRunner\\TestResult\\Facade as TestResultFacade;\nuse PHPUnit\\TestRunner\\TestResult\\TestResult;\nuse PHPUnit\\TextUI\\Configuration\\CodeCoverageFilterRegistry;\nuse PHPUnit\\Util\\ExcludeList;\nuse SebastianBergmann\\Timer\\Timer;\nuse SplFileInfo;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Process\\PhpExecutableFinder;\n\nuse function array_merge;\nuse function array_merge_recursive;\nuse function array_shift;\nuse function assert;\nuse function count;\nuse function dirname;\nuse function file_get_contents;\nuse function max;\nuse function realpath;\nuse function unlink;\nuse function unserialize;\nuse function usleep;\n\n/**\n * @internal\n */\nfinal class WrapperRunner implements RunnerInterface\n{\n    /**\n     * The time to sleep between cycles.\n     */\n    private const int CYCLE_SLEEP = 10000;\n\n    /**\n     * The result printer.\n     */\n    private readonly ResultPrinter $printer;\n\n    /**\n     * The timer.\n     */\n    private readonly Timer $timer;\n\n    /** @var list<non-empty-string> */\n    private array $pending = [];\n\n    /**\n     * The exit code.\n     */\n    private int $exitcode = -1;\n\n    /** @var array<positive-int,WrapperWorker> */\n    private array $workers = [];\n\n    /** @var array<int,int> */\n    private array $batches = [];\n\n    /** @var list<SplFileInfo> */\n    private array $unexpectedOutputFiles = [];\n\n    /** @var list<SplFileInfo> */\n    private array $resultCacheFiles = [];\n\n    /** @var list<SplFileInfo> */\n    private array $testResultFiles = [];\n\n    /** @var list<SplFileInfo> */\n    private array $coverageFiles = [];\n\n    /** @var list<SplFileInfo> */\n    private array $junitFiles = [];\n\n    /** @var list<SplFileInfo> */\n    private array $teamcityFiles = [];\n\n    /** @var list<SplFileInfo> */\n    private array $testdoxFiles = [];\n\n    /** @var non-empty-string[] */\n    private readonly array $parameters;\n\n    /**\n     * The code coverage filter registry.\n     */\n    private CodeCoverageFilterRegistry $codeCoverageFilterRegistry;\n\n    public function __construct(\n        private readonly Options $options,\n        private readonly OutputInterface $output\n    ) {\n        $this->printer = new ResultPrinter($output, $options);\n        $this->timer = new Timer;\n\n        $wrapper = realpath(\n            dirname(__DIR__, 4).DIRECTORY_SEPARATOR.'bin'.DIRECTORY_SEPARATOR.'worker.php',\n        );\n        assert($wrapper !== false);\n        $phpFinder = new PhpExecutableFinder;\n        $phpBin = $phpFinder->find(false);\n        assert($phpBin !== false);\n        $parameters = [$phpBin];\n        $parameters = array_merge($parameters, $phpFinder->findArguments());\n\n        if ($options->passthruPhp !== null) {\n            $parameters = array_merge($parameters, $options->passthruPhp);\n        }\n\n        /** @var array<int, non-empty-string> $parameters */\n        $parameters = $this->handleLaravelHerd($parameters);\n\n        $parameters[] = $wrapper;\n        $parameters[] = '--test-directory='.TestSuite::getInstance()->testPath;\n\n        $this->parameters = $parameters;\n        $this->codeCoverageFilterRegistry = new CodeCoverageFilterRegistry;\n    }\n\n    public function run(): int\n    {\n        $directory = dirname(__DIR__);\n        assert($directory !== '');\n        ExcludeList::addDirectory($directory);\n        TestResultFacade::init();\n        EventFacade::instance()->seal();\n        $suiteLoader = new SuiteLoader(\n            $this->options,\n            $this->output,\n            $this->codeCoverageFilterRegistry,\n        );\n        $this->pending = $this->getTestFiles($suiteLoader);\n\n        $result = TestResultFacade::result();\n\n        $this->timer->start();\n\n        $this->startWorkers();\n        $this->assignAllPendingTests();\n        $this->waitForAllToFinish();\n\n        return $this->complete($result);\n    }\n\n    /**\n     * Handles Laravel Herd's debug and coverage modes.\n     *\n     * @param  array<string>  $parameters\n     * @return array<string>\n     */\n    private function handleLaravelHerd(array $parameters): array\n    {\n        if (isset($_ENV['HERD_DEBUG_INI'])) {\n            return array_merge($parameters, ['-c', $_ENV['HERD_DEBUG_INI']]);\n        }\n\n        return $parameters;\n    }\n\n    private function startWorkers(): void\n    {\n        for ($token = 1; $token <= $this->options->processes; $token++) {\n            $this->startWorker($token);\n        }\n    }\n\n    private function assignAllPendingTests(): void\n    {\n        $batchSize = $this->options->maxBatchSize;\n\n        while (count($this->pending) > 0 && count($this->workers) > 0) {\n            foreach ($this->workers as $token => $worker) {\n                if (! $worker->isRunning()) {\n                    throw $worker->getWorkerCrashedException();\n                }\n\n                if (! $worker->isFree()) {\n                    continue;\n                }\n\n                $this->flushWorker($worker);\n\n                if ($batchSize !== 0 && $this->batches[$token] === $batchSize) {\n                    $this->destroyWorker($token);\n                    $worker = $this->startWorker($token);\n                }\n\n                if (\n                    $this->exitcode > 0\n                    && $this->options->configuration->stopOnFailure()\n                ) {\n                    $this->pending = [];\n                } elseif (($pending = array_shift($this->pending)) !== null) {\n                    $worker->assign($pending);\n                    $this->batches[$token]++;\n                }\n            }\n\n            usleep(self::CYCLE_SLEEP);\n        }\n    }\n\n    private function flushWorker(WrapperWorker $worker): void\n    {\n        $this->exitcode = max($this->exitcode, $worker->getExitCode());\n        $this->printer->printFeedback(\n            $worker->progressFile,\n            $worker->unexpectedOutputFile,\n            $this->teamcityFiles,\n        );\n        $worker->reset();\n    }\n\n    private function waitForAllToFinish(): void\n    {\n        $stopped = [];\n        while (count($this->workers) > 0) {\n            foreach ($this->workers as $index => $worker) {\n                if ($worker->isRunning()) {\n                    if (! isset($stopped[$index]) && $worker->isFree()) {\n                        $worker->stop();\n                        $stopped[$index] = true;\n                    }\n\n                    continue;\n                }\n\n                if (! $worker->isFree()) {\n                    throw $worker->getWorkerCrashedException();\n                }\n\n                $this->flushWorker($worker);\n                unset($this->workers[$index]);\n            }\n\n            usleep(self::CYCLE_SLEEP);\n        }\n    }\n\n    /** @param  positive-int  $token */\n    private function startWorker(int $token): WrapperWorker\n    {\n        $worker = new WrapperWorker(\n            $this->output,\n            $this->options,\n            $this->parameters,\n            $token,\n        );\n        $worker->start();\n        $this->batches[$token] = 0;\n\n        $this->unexpectedOutputFiles[] = $worker->unexpectedOutputFile;\n        $this->unexpectedOutputFiles[] = $worker->unexpectedOutputFile;\n        $this->testResultFiles[] = $worker->testResultFile;\n\n        if (isset($worker->junitFile)) {\n            $this->junitFiles[] = $worker->junitFile;\n        }\n\n        if (isset($worker->coverageFile)) {\n            $this->coverageFiles[] = $worker->coverageFile;\n        }\n\n        if (isset($worker->teamcityFile)) {\n            $this->teamcityFiles[] = $worker->teamcityFile;\n        }\n\n        if (isset($worker->testdoxFile)) {\n            $this->testdoxFiles[] = $worker->testdoxFile;\n        }\n\n        return $this->workers[$token] = $worker;\n    }\n\n    private function destroyWorker(int $token): void\n    {\n        $this->workers[$token]->stop();\n        // We need to wait for ApplicationForWrapperWorker::end to end\n        while ($this->workers[$token]->isRunning()) {\n            usleep(self::CYCLE_SLEEP);\n        }\n\n        unset($this->workers[$token]);\n    }\n\n    private function complete(TestResult $testResultSum): int\n    {\n        foreach ($this->testResultFiles as $testResultFile) {\n            if (! $testResultFile->isFile()) {\n                continue;\n            }\n\n            $contents = file_get_contents($testResultFile->getPathname());\n            assert($contents !== false);\n            $testResult = unserialize($contents);\n            assert($testResult instanceof TestResult);\n\n            /** @var list<AfterLastTestMethodFailed> $failedEvents */\n            $failedEvents = array_merge_recursive($testResultSum->testFailedEvents(), $testResult->testFailedEvents());\n\n            $testResultSum = new TestResult(\n                (int) $testResultSum->hasTests() + (int) $testResult->hasTests(),\n                $testResultSum->numberOfTestsRun() + $testResult->numberOfTestsRun(),\n                $testResultSum->numberOfAssertions() + $testResult->numberOfAssertions(),\n                array_merge_recursive($testResultSum->testErroredEvents(), $testResult->testErroredEvents()),\n                $failedEvents,\n                array_merge_recursive($testResultSum->testConsideredRiskyEvents(), $testResult->testConsideredRiskyEvents()),\n                array_merge_recursive($testResultSum->testSuiteSkippedEvents(), $testResult->testSuiteSkippedEvents()),\n                array_merge_recursive($testResultSum->testSkippedEvents(), $testResult->testSkippedEvents()),\n                array_merge_recursive($testResultSum->testMarkedIncompleteEvents(), $testResult->testMarkedIncompleteEvents()),\n                array_merge_recursive($testResultSum->testTriggeredPhpunitDeprecationEvents(), $testResult->testTriggeredPhpunitDeprecationEvents()),\n                array_merge_recursive($testResultSum->testTriggeredPhpunitErrorEvents(), $testResult->testTriggeredPhpunitErrorEvents()),\n                array_merge_recursive($testResultSum->testTriggeredPhpunitNoticeEvents(), $testResult->testTriggeredPhpunitNoticeEvents()),\n                array_merge_recursive($testResultSum->testTriggeredPhpunitWarningEvents(), $testResult->testTriggeredPhpunitWarningEvents()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->testRunnerTriggeredDeprecationEvents(), $testResult->testRunnerTriggeredDeprecationEvents()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->testRunnerTriggeredNoticeEvents(), $testResult->testRunnerTriggeredNoticeEvents()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->testRunnerTriggeredWarningEvents(), $testResult->testRunnerTriggeredWarningEvents()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->errors(), $testResult->errors()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->deprecations(), $testResult->deprecations()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->notices(), $testResult->notices()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->warnings(), $testResult->warnings()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->phpDeprecations(), $testResult->phpDeprecations()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->phpNotices(), $testResult->phpNotices()),\n                // @phpstan-ignore-next-line\n                array_merge_recursive($testResultSum->phpWarnings(), $testResult->phpWarnings()),\n                $testResultSum->numberOfIssuesIgnoredByBaseline() + $testResult->numberOfIssuesIgnoredByBaseline(),\n            );\n        }\n\n        $testResultSum = new TestResult(\n            ResultReflection::numberOfTests($testResultSum),\n            $testResultSum->numberOfTestsRun(),\n            $testResultSum->numberOfAssertions(),\n            $testResultSum->testErroredEvents(),\n            $testResultSum->testFailedEvents(),\n            $testResultSum->testConsideredRiskyEvents(),\n            $testResultSum->testSuiteSkippedEvents(),\n            $testResultSum->testSkippedEvents(),\n            $testResultSum->testMarkedIncompleteEvents(),\n            $testResultSum->testTriggeredPhpunitDeprecationEvents(),\n            $testResultSum->testTriggeredPhpunitErrorEvents(),\n            $testResultSum->testTriggeredPhpunitNoticeEvents(),\n            $testResultSum->testTriggeredPhpunitWarningEvents(),\n            $testResultSum->testRunnerTriggeredDeprecationEvents(),\n            $testResultSum->testRunnerTriggeredNoticeEvents(),\n            array_values(array_filter(\n                $testResultSum->testRunnerTriggeredWarningEvents(),\n                fn (WarningTriggered $event): bool => ! str_contains($event->message(), 'No tests found')\n            )),\n            $testResultSum->errors(),\n            $testResultSum->deprecations(),\n            $testResultSum->notices(),\n            $testResultSum->warnings(),\n            $testResultSum->phpDeprecations(),\n            $testResultSum->phpNotices(),\n            $testResultSum->phpWarnings(),\n            $testResultSum->numberOfIssuesIgnoredByBaseline(),\n        );\n\n        if ($this->options->configuration->cacheResult()) {\n            $resultCacheSum = new DefaultResultCache($this->options->configuration->testResultCacheFile());\n            foreach ($this->resultCacheFiles as $resultCacheFile) {\n                $resultCache = new DefaultResultCache($resultCacheFile->getPathname());\n                $resultCache->load();\n\n                $resultCacheSum->mergeWith($resultCache);\n            }\n\n            $resultCacheSum->persist();\n        }\n\n        $this->printer->printResults(\n            $testResultSum,\n            $this->teamcityFiles,\n            $this->testdoxFiles,\n            $this->timer->stop(),\n        );\n        $this->generateCodeCoverageReports();\n        $this->generateLogs();\n\n        $exitcode = Result::exitCode($this->options->configuration, $testResultSum);\n\n        $this->clearFiles($this->unexpectedOutputFiles);\n        $this->clearFiles($this->testResultFiles);\n        $this->clearFiles($this->coverageFiles);\n        $this->clearFiles($this->junitFiles);\n        $this->clearFiles($this->teamcityFiles);\n        $this->clearFiles($this->testdoxFiles);\n\n        return $exitcode;\n    }\n\n    private function generateCodeCoverageReports(): void\n    {\n        if ($this->coverageFiles === []) {\n            return;\n        }\n\n        $coverageManager = new CodeCoverage;\n        $coverageManager->init(\n            $this->options->configuration,\n            $this->codeCoverageFilterRegistry,\n            false,\n        );\n        if (! $coverageManager->isActive()) {\n            $this->output->writeln([\n                '',\n                '  <fg=black;bg=yellow;options=bold> WARN </> No code coverage driver is available.</>',\n                '',\n            ]);\n\n            return;\n        }\n        $coverageMerger = new CoverageMerger($coverageManager->codeCoverage());\n        foreach ($this->coverageFiles as $coverageFile) {\n            $coverageMerger->addCoverageFromFile($coverageFile);\n        }\n\n        $coverageManager->generateReports(\n            $this->printer->printer,\n            $this->options->configuration,\n        );\n    }\n\n    private function generateLogs(): void\n    {\n        if ($this->junitFiles === []) {\n            return;\n        }\n\n        $testSuite = (new LogMerger)->merge($this->junitFiles);\n        assert($testSuite instanceof \\ParaTest\\JUnit\\TestSuite);\n        (new Writer)->write(\n            $testSuite,\n            $this->options->configuration->logfileJunit(),\n        );\n    }\n\n    /** @param  list<SplFileInfo>  $files */\n    private function clearFiles(array $files): void\n    {\n        foreach ($files as $file) {\n            if (! $file->isFile()) {\n                continue;\n            }\n\n            unlink($file->getPathname());\n        }\n    }\n\n    /**\n     * Returns the test files to be executed.\n     *\n     * @return array<int, non-empty-string>\n     */\n    private function getTestFiles(SuiteLoader $suiteLoader): array\n    {\n        /** @var array<string, non-empty-string> $files */\n        $files = [\n            ...array_values(array_filter(\n                $suiteLoader->tests,\n                fn (string $filename): bool => ! str_ends_with($filename, \"eval()'d code\")\n            )),\n            ...TestSuite::getInstance()->tests->getFilenames(),\n        ];\n\n        return $files; // @phpstan-ignore-line\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Parallel/Support/CompactPrinter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins\\Parallel\\Support;\n\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\State;\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\Style;\nuse ParaTest\\Options;\nuse PHPUnit\\Event\\Telemetry\\GarbageCollectorStatus;\nuse PHPUnit\\Event\\Telemetry\\HRTime;\nuse PHPUnit\\Event\\Telemetry\\Info;\nuse PHPUnit\\Event\\Telemetry\\MemoryUsage;\nuse PHPUnit\\Event\\Telemetry\\Snapshot;\nuse PHPUnit\\TestRunner\\TestResult\\TestResult as PHPUnitTestResult;\nuse SebastianBergmann\\Timer\\Duration;\nuse Symfony\\Component\\Console\\Output\\ConsoleOutput;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Termwind\\Terminal;\n\nuse function Termwind\\render;\nuse function Termwind\\terminal;\n\n/**\n * @internal\n */\nfinal class CompactPrinter\n{\n    /**\n     * The number of processed tests.\n     */\n    private int $processed = 0;\n\n    /**\n     * @var array<string, array<int, string>>\n     */\n    private const array LOOKUP_TABLE = [\n        '.' => ['gray', '.'],\n        'S' => ['yellow', 's'],\n        'T' => ['cyan', 't'],\n        'I' => ['yellow', '!'],\n        'N' => ['yellow', '!'],\n        'D' => ['yellow', '!'],\n        'R' => ['yellow', '!'],\n        'W' => ['yellow', '!'],\n        'E' => ['red', '⨯'],\n        'F' => ['red', '⨯'],\n    ];\n\n    /**\n     * Creates a new instance of the Compact Printer.\n     */\n    public function __construct(\n        private readonly Terminal $terminal,\n        private readonly OutputInterface $output,\n        private readonly Style $style,\n        private readonly int $compactSymbolsPerLine,\n    ) {\n        // ..\n    }\n\n    /**\n     * Creates a new instance of the Compact Printer.\n     */\n    public static function default(): self\n    {\n        return new self(\n            terminal(),\n            new ConsoleOutput(decorated: true),\n            new Style(new ConsoleOutput(decorated: true)),\n            terminal()->width() - 4,\n        );\n    }\n\n    /**\n     * Output an empty line in the console. Useful for providing a little breathing room.\n     */\n    public function newLine(): void\n    {\n        render('<div class=\"py-1\"></div>');\n    }\n\n    /**\n     * Outputs the given description item from the ProgressPrinter as a gorgeous, colored symbol.\n     */\n    public function descriptionItem(string $item): void\n    {\n        [$color, $icon] = self::LOOKUP_TABLE[$item] ?? self::LOOKUP_TABLE['.'];\n\n        $symbolsOnCurrentLine = $this->processed % $this->compactSymbolsPerLine;\n\n        if ($symbolsOnCurrentLine >= $this->terminal->width() - 4) {\n            $symbolsOnCurrentLine = 0;\n        }\n\n        if ($symbolsOnCurrentLine === 0) {\n            $this->output->writeln('');\n            $this->output->write('  ');\n        }\n\n        $this->output->write(sprintf('<fg=%s;options=bold>%s</>', $color, $icon));\n\n        $this->processed++;\n    }\n\n    /**\n     * Outputs all errors from the given state using Collision's beautiful error output.\n     */\n    public function errors(State $state): void\n    {\n        $this->output->writeln('');\n\n        $this->style->writeErrorsSummary($state);\n    }\n\n    /**\n     * Outputs a clean recap of the test run, including the number of tests, assertions, and failures.\n     */\n    public function recap(State $state, PHPUnitTestResult $testResult, Duration $duration, Options $options): void\n    {\n        assert($this->output instanceof ConsoleOutput);\n\n        $nanoseconds = $duration->asNanoseconds() % 1_000_000_000;\n        $snapshotDuration = HRTime::fromSecondsAndNanoseconds((int) $duration->asSeconds(), $nanoseconds);\n        $telemetryDuration = \\PHPUnit\\Event\\Telemetry\\Duration::fromSecondsAndNanoseconds((int) $duration->asSeconds(), $nanoseconds);\n\n        $status = gc_status();\n\n        $garbageCollectorStatus = new GarbageCollectorStatus(\n            $status['runs'],\n            $status['collected'],\n            $status['threshold'],\n            $status['roots'],\n            0.00,\n            0.00,\n            0.00,\n            0.00,\n            false,\n            false,\n            false,\n            0,\n        );\n\n        $telemetry = new Info(\n            new Snapshot(\n                $snapshotDuration,\n                MemoryUsage::fromBytes(0),\n                MemoryUsage::fromBytes(0),\n                $garbageCollectorStatus,\n            ),\n            $telemetryDuration,\n            MemoryUsage::fromBytes(0),\n            \\PHPUnit\\Event\\Telemetry\\Duration::fromSecondsAndNanoseconds(0, 0),\n            MemoryUsage::fromBytes(0),\n        );\n\n        $this->style->writeRecap($state, $telemetry, $testResult);\n\n        $this->output->write(\"\\033[1A\");\n\n        $this->output->write([\n            sprintf(\n                '  <fg=gray>Parallel:</> <fg=default>%s process%s</>',\n                $options->processes,\n                $options->processes > 1 ? 'es' : '',\n            ),\n            \"\\n\",\n            \"\\n\",\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Parallel.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse ParaTest\\ParaTestCommand;\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Plugins\\Actions\\CallsAddsOutput;\nuse Pest\\Plugins\\Concerns\\HandleArguments;\nuse Pest\\Plugins\\Parallel\\Contracts\\HandlersWorkerArguments;\nuse Pest\\Plugins\\Parallel\\Paratest\\CleanConsoleOutput;\nuse Pest\\Support\\Arr;\nuse Pest\\Support\\Container;\nuse Pest\\TestSuite;\nuse Stringable;\nuse Symfony\\Component\\Console\\Application;\nuse Symfony\\Component\\Console\\Input\\ArgvInput;\n\nuse function Pest\\version;\n\nfinal class Parallel implements HandlesArguments\n{\n    use HandleArguments;\n\n    private const string GLOBAL_PREFIX = 'PEST_PARALLEL_GLOBAL_';\n\n    private const array HANDLERS = [\n        Parallel\\Handlers\\Parallel::class,\n        Parallel\\Handlers\\Pest::class,\n        Parallel\\Handlers\\Laravel::class,\n    ];\n\n    /**\n     * @var string[]\n     */\n    private const array UNSUPPORTED_ARGUMENTS = ['--todo', '--todos', '--retry', '--notes', '--issue', '--pr', '--pull-request'];\n\n    /**\n     * Whether the given command line arguments indicate that the test suite should be run in parallel.\n     */\n    public static function isEnabled(): bool\n    {\n        $argv = new ArgvInput;\n\n        if ($argv->hasParameterOption('--parallel')) {\n            return true;\n        }\n\n        return $argv->hasParameterOption('-p');\n    }\n\n    /**\n     * If this code is running in a worker process rather than the main process.\n     */\n    public static function isWorker(): bool\n    {\n        $argvValue = Arr::get($_SERVER, 'PARATEST');\n\n        assert(is_string($argvValue) || is_int($argvValue) || is_null($argvValue));\n\n        return ((int) $argvValue) === 1;\n    }\n\n    /**\n     * Sets a global value that can be accessed by the parent process and all workers.\n     */\n    public static function setGlobal(string $key, string|int|bool|Stringable $value): void\n    {\n        $data = ['value' => $value instanceof Stringable ? $value->__toString() : $value];\n\n        $_ENV[self::GLOBAL_PREFIX.$key] = json_encode($data, JSON_THROW_ON_ERROR);\n    }\n\n    /**\n     * Returns the given global value if one has been set.\n     */\n    public static function getGlobal(string $key): string|int|bool|null\n    {\n        $placesToCheck = [$_SERVER, $_ENV];\n\n        foreach ($placesToCheck as $location) {\n            if (array_key_exists(self::GLOBAL_PREFIX.$key, $location)) {\n                // @phpstan-ignore-next-line\n                return json_decode((string) $location[self::GLOBAL_PREFIX.$key], true, 512, JSON_THROW_ON_ERROR)['value'] ?? null;\n            }\n        }\n\n        return null;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if ($this->hasArgumentsThatWouldBeFasterWithoutParallel()) {\n            return $this->runTestSuiteInSeries($arguments);\n        }\n\n        if (self::isEnabled()) {\n            exit($this->runTestSuiteInParallel($arguments));\n        }\n\n        if (self::isWorker()) {\n            return $this->runWorkerHandlers($arguments);\n        }\n\n        return $arguments;\n    }\n\n    /**\n     * Runs the test suite in parallel. This method will exit the process upon completion.\n     *\n     * @param  array<int, string>  $arguments\n     */\n    private function runTestSuiteInParallel(array $arguments): int\n    {\n        $handlers = array_filter(\n            array_map(fn (string $handler): object|string => Container::getInstance()->get($handler), self::HANDLERS),\n            fn (object|string $handler): bool => $handler instanceof HandlesArguments,\n        );\n\n        $filteredArguments = array_reduce(\n            $handlers,\n            fn (array $arguments, HandlesArguments $handler): array => $handler->handleArguments($arguments),\n            $arguments\n        );\n\n        $exitCode = $this->paratestCommand()->run(new ArgvInput($filteredArguments), new CleanConsoleOutput);\n\n        return CallsAddsOutput::execute($exitCode);\n    }\n\n    /**\n     * Runs any handlers that have been registered to handle worker arguments, and returns the modified arguments.\n     *\n     * @param  array<int, string>  $arguments\n     * @return array<int, string>\n     */\n    private function runWorkerHandlers(array $arguments): array\n    {\n        $handlers = array_filter(\n            array_map(fn (string $handler): object|string => Container::getInstance()->get($handler), self::HANDLERS),\n            fn (object|string $handler): bool => $handler instanceof HandlersWorkerArguments,\n        );\n\n        return array_reduce(\n            $handlers,\n            fn (array $arguments, HandlersWorkerArguments $handler): array => $handler->handleWorkerArguments($arguments),\n            $arguments\n        );\n    }\n\n    /**\n     * Builds an instance of the Paratest command.\n     */\n    private function paratestCommand(): Application\n    {\n        /** @var non-empty-string $rootPath */\n        $rootPath = TestSuite::getInstance()->rootPath;\n\n        $command = ParaTestCommand::applicationFactory($rootPath);\n        $command->setAutoExit(false);\n        $command->setName('Pest');\n        $command->setVersion(version());\n\n        return $command;\n    }\n\n    /**\n     * Whether the command line arguments contain any arguments that are\n     * not supported or are suboptimal when running in parallel.\n     */\n    private function hasArgumentsThatWouldBeFasterWithoutParallel(): bool\n    {\n        $arguments = new ArgvInput;\n\n        foreach (self::UNSUPPORTED_ARGUMENTS as $unsupportedArgument) {\n            if ($arguments->hasParameterOption($unsupportedArgument)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Removes any parallel arguments.\n     *\n     * @param  array<int, string>  $arguments\n     * @return array<int, string>\n     */\n    private function runTestSuiteInSeries(array $arguments): array\n    {\n        $arguments = $this->popArgument('--parallel', $arguments);\n\n        return $this->popArgument('-p', $arguments);\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Printer.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\n\n/**\n * @internal\n */\nfinal class Printer implements HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if (! array_key_exists('COLLISION_PRINTER', $_SERVER)) {\n            return $arguments;\n        }\n\n        if (in_array('--no-output', $arguments, true)) {\n            return $arguments;\n        }\n\n        return $this->pushArgument('--no-output', $arguments);\n    }\n}\n"
  },
  {
    "path": "src/Plugins/ProcessIsolation.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Exceptions\\InvalidOption;\n\n/**\n * @internal\n */\nfinal class ProcessIsolation implements HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if ($this->hasArgument('--process-isolation', $arguments)) {\n            throw new InvalidOption('The [--process-isolation] option is not supported.');\n        }\n\n        return $arguments;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Profile.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Exceptions\\InvalidOption;\n\n/**\n * @internal\n */\nfinal class Profile implements HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if (! $this->hasArgument('--profile', $arguments)) {\n            return $arguments;\n        }\n\n        if ($this->hasArgument('--parallel', $arguments)) {\n            throw new InvalidOption('The [--profile] option is not supported when running in parallel.');\n        }\n\n        return $arguments;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Retry.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Exceptions\\InvalidOption;\n\n/**\n * @internal\n */\nfinal class Retry implements HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if (! $this->hasArgument('--retry', $arguments)) {\n            return $arguments;\n        }\n\n        if ($this->hasArgument('--parallel', $arguments)) {\n            throw new InvalidOption('The [--retry] option is not supported when running in parallel.');\n        }\n\n        $arguments = $this->popArgument('--retry', $arguments);\n\n        $arguments = $this->pushArgument('--order-by=defects', $arguments);\n\n        return $this->pushArgument('--stop-on-failure', $arguments);\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Shard.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\AddsOutput;\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Exceptions\\InvalidOption;\nuse Symfony\\Component\\Console\\Input\\ArgvInput;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Symfony\\Component\\Process\\Process;\n\n/**\n * @internal\n */\nfinal class Shard implements AddsOutput, HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    private const string SHARD_OPTION = 'shard';\n\n    /**\n     * The shard index and total number of shards.\n     *\n     * @var array{\n     *     index: int,\n     *     total: int,\n     *     testsRan: int,\n     *     testsCount: int\n     * }|null\n     */\n    private static ?array $shard = null;\n\n    /**\n     * Creates a new Plugin instance.\n     */\n    public function __construct(\n        private readonly OutputInterface $output,\n    ) {\n        //\n    }\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if (! $this->hasArgument('--shard', $arguments)) {\n            return $arguments;\n        }\n\n        // @phpstan-ignore-next-line\n        $input = new ArgvInput($arguments);\n\n        ['index' => $index, 'total' => $total] = self::getShard($input);\n\n        $arguments = $this->popArgument(\"--shard=$index/$total\", $this->popArgument('--shard', $this->popArgument(\n            \"$index/$total\",\n            $arguments,\n        )));\n\n        /** @phpstan-ignore-next-line */\n        $tests = $this->allTests($arguments);\n        $testsToRun = (array_chunk($tests, max(1, (int) ceil(count($tests) / $total))))[$index - 1] ?? [];\n\n        self::$shard = [\n            'index' => $index,\n            'total' => $total,\n            'testsRan' => count($testsToRun),\n            'testsCount' => count($tests),\n        ];\n\n        return [...$arguments, '--filter', $this->buildFilterArgument($testsToRun)];\n    }\n\n    /**\n     * Returns all tests that the test suite would run.\n     *\n     * @param  list<string>  $arguments\n     * @return list<string>\n     */\n    private function allTests(array $arguments): array\n    {\n        $output = (new Process([\n            'php',\n            ...$this->removeParallelArguments($arguments),\n            '--list-tests',\n        ]))->mustRun()->getOutput();\n\n        preg_match_all('/ - (?:P\\\\\\\\)?(Tests\\\\\\\\[^:]+)::/', $output, $matches);\n\n        return array_values(array_unique($matches[1]));\n    }\n\n    /**\n     * @param  array<int, string>  $arguments\n     * @return array<int, string>\n     */\n    private function removeParallelArguments(array $arguments): array\n    {\n        return array_filter($arguments, fn (string $argument): bool => ! in_array($argument, ['--parallel', '-p'], strict: true));\n    }\n\n    /**\n     * Builds the filter argument for the given tests to run.\n     */\n    private function buildFilterArgument(mixed $testsToRun): string\n    {\n        return addslashes(implode('|', $testsToRun));\n    }\n\n    /**\n     * Adds output after the Test Suite execution.\n     */\n    public function addOutput(int $exitCode): int\n    {\n        if (self::$shard === null) {\n            return $exitCode;\n        }\n\n        [\n            'index' => $index,\n            'total' => $total,\n            'testsRan' => $testsRan,\n            'testsCount' => $testsCount,\n        ] = self::$shard;\n\n        $this->output->writeln(sprintf(\n            '  <fg=gray>Shard:</>    <fg=default>%d of %d</> — %d file%s ran, out of %d.',\n            $index,\n            $total,\n            $testsRan,\n            $testsRan === 1 ? '' : 's',\n            $testsCount,\n        ));\n\n        return $exitCode;\n    }\n\n    /**\n     * Returns the shard information.\n     *\n     * @return array{index: int, total: int}\n     */\n    public static function getShard(InputInterface $input): array\n    {\n        if ($input->hasParameterOption('--'.self::SHARD_OPTION)) {\n            $shard = $input->getParameterOption('--'.self::SHARD_OPTION);\n        } else {\n            $shard = null;\n        }\n\n        if (! is_string($shard) || ! preg_match('/^\\d+\\/\\d+$/', $shard)) {\n            throw new InvalidOption('The [--shard] option must be in the format \"index/total\".');\n        }\n\n        [$index, $total] = explode('/', $shard);\n\n        if (! is_numeric($index) || ! is_numeric($total)) {\n            throw new InvalidOption('The [--shard] option must be in the format \"index/total\".');\n        }\n\n        if ($index <= 0 || $total <= 0 || $index > $total) {\n            throw new InvalidOption('The [--shard] option index must be a non-negative integer less than the total number of shards.');\n        }\n\n        $index = (int) $index;\n        $total = (int) $total;\n\n        return [\n            'index' => $index,\n            'total' => $total,\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Snapshot.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Exceptions\\InvalidOption;\nuse Pest\\TestSuite;\n\n/**\n * @internal\n */\nfinal class Snapshot implements HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if (! $this->hasArgument('--update-snapshots', $arguments)) {\n            return $arguments;\n        }\n\n        if ($this->hasArgument('--parallel', $arguments)) {\n            throw new InvalidOption('The [--update-snapshots] option is not supported when running in parallel.');\n        }\n\n        TestSuite::getInstance()->snapshots->flush();\n\n        return $this->popArgument('--update-snapshots', $arguments);\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Verbose.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\n\n/**\n * @internal\n */\nfinal class Verbose implements HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    /**\n     * The list of verbosity levels.\n     */\n    private const array VERBOSITY_LEVELS = ['v', 'vv', 'vvv', 'q'];\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        foreach (self::VERBOSITY_LEVELS as $level) {\n            if ($this->hasArgument('-'.$level, $arguments)) {\n                $arguments = $this->popArgument('-'.$level, $arguments);\n            }\n        }\n\n        if ($this->hasArgument('--quiet', $arguments)) {\n            return $this->popArgument('--quiet', $arguments);\n        }\n\n        return $arguments;\n    }\n}\n"
  },
  {
    "path": "src/Plugins/Version.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Plugins;\n\nuse Pest\\Contracts\\Plugins\\HandlesArguments;\nuse Pest\\Support\\View;\n\nuse function Pest\\version;\n\n/**\n * @internal\n */\nfinal class Version implements HandlesArguments\n{\n    use Concerns\\HandleArguments;\n\n    /**\n     * {@inheritDoc}\n     */\n    public function handleArguments(array $arguments): array\n    {\n        if ($this->hasArgument('--version', $arguments)) {\n            View::render('version', [\n                'version' => version(),\n            ]);\n\n            exit(0);\n        }\n\n        return $arguments;\n    }\n}\n"
  },
  {
    "path": "src/Preset.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nuse Closure;\nuse Pest\\Arch\\Support\\Composer;\nuse Pest\\ArchPresets\\AbstractPreset;\nuse Pest\\ArchPresets\\Custom;\nuse Pest\\ArchPresets\\Laravel;\nuse Pest\\ArchPresets\\Php;\nuse Pest\\ArchPresets\\Relaxed;\nuse Pest\\ArchPresets\\Security;\nuse Pest\\ArchPresets\\Strict;\nuse Pest\\Exceptions\\InvalidArgumentException;\nuse Pest\\PendingCalls\\TestCall;\nuse stdClass;\n\n/**\n * @internal\n */\nfinal class Preset\n{\n    /**\n     * The application / package base namespaces.\n     *\n     * @var ?array<int, string>\n     */\n    private static ?array $baseNamespaces = null;\n\n    /**\n     * The custom presets.\n     *\n     * @var array<string, Closure>\n     */\n    private static array $customPresets = [];\n\n    /**\n     * Creates a new preset instance.\n     */\n    public function __construct()\n    {\n        //\n    }\n\n    /**\n     * Uses the Pest php preset and returns the test call instance.\n     */\n    public function php(): Php\n    {\n        return $this->executePreset(new Php($this->baseNamespaces()));\n    }\n\n    /**\n     * Uses the Pest laravel preset and returns the test call instance.\n     */\n    public function laravel(): Laravel\n    {\n        return $this->executePreset(new Laravel($this->baseNamespaces()));\n    }\n\n    /**\n     * Uses the Pest strict preset and returns the test call instance.\n     */\n    public function strict(): Strict\n    {\n        return $this->executePreset(new Strict($this->baseNamespaces()));\n    }\n\n    /**\n     * Uses the Pest security preset and returns the test call instance.\n     */\n    public function security(): AbstractPreset\n    {\n        return $this->executePreset(new Security($this->baseNamespaces()));\n    }\n\n    /**\n     * Uses the Pest relaxed preset and returns the test call instance.\n     */\n    public function relaxed(): AbstractPreset\n    {\n        return $this->executePreset(new Relaxed($this->baseNamespaces()));\n    }\n\n    /**\n     * Uses the Pest custom preset and returns the test call instance.\n     *\n     * @internal\n     */\n    public static function custom(string $name, Closure $execute): void\n    {\n        if (preg_match('/^[a-zA-Z]+$/', $name) === false) {\n            throw new InvalidArgumentException('The preset name must only contain words from a-z or A-Z.');\n        }\n\n        self::$customPresets[$name] = $execute;\n    }\n\n    /**\n     * Dynamically handle calls to the class.\n     *\n     * @param  array<int, mixed>  $arguments\n     *\n     * @throws InvalidArgumentException\n     */\n    public function __call(string $name, array $arguments): AbstractPreset\n    {\n        if (! array_key_exists($name, self::$customPresets)) {\n            $availablePresets = [\n                ...['php', 'laravel', 'strict', 'security', 'relaxed'],\n                ...array_keys(self::$customPresets),\n            ];\n\n            throw new InvalidArgumentException(sprintf('The preset [%s] does not exist. The available presets are [%s].', $name, implode(', ', $availablePresets)));\n        }\n\n        return $this->executePreset(new Custom($this->baseNamespaces(), $name, self::$customPresets[$name]));\n    }\n\n    /**\n     * Executes the given preset.\n     *\n     * @template TPreset of AbstractPreset\n     *\n     * @param  TPreset  $preset\n     * @return TPreset\n     */\n    private function executePreset(AbstractPreset $preset): AbstractPreset\n    {\n        $this->baseNamespaces();\n\n        $preset->execute();\n\n        // $this->testCall->testCaseMethod->closure = (function () use ($preset): void {\n        //    $preset->flush();\n        // })->bindTo(new stdClass);\n\n        return $preset;\n    }\n\n    /**\n     * Get the base namespaces for the application / package.\n     *\n     * @return array<int, string>\n     */\n    private function baseNamespaces(): array\n    {\n        if (self::$baseNamespaces === null) {\n            self::$baseNamespaces = Composer::userNamespaces();\n        }\n\n        return self::$baseNamespaces;\n    }\n}\n"
  },
  {
    "path": "src/Repositories/AfterAllRepository.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Repositories;\n\nuse Closure;\nuse Pest\\Exceptions\\AfterAllAlreadyExist;\nuse Pest\\Support\\NullClosure;\nuse Pest\\Support\\Reflection;\n\n/**\n * @internal\n */\nfinal class AfterAllRepository\n{\n    /**\n     * @var array<string, Closure>\n     */\n    private array $state = [];\n\n    /**\n     * Runs the given closure for each after all.\n     */\n    public function each(callable $each): void\n    {\n        foreach ($this->state as $filename => $closure) {\n            $each($filename, $closure);\n        }\n    }\n\n    /**\n     * Sets a after all closure.\n     */\n    public function set(Closure $closure): void\n    {\n        $filename = Reflection::getFileNameFromClosure($closure);\n\n        if (array_key_exists($filename, $this->state)) {\n            throw new AfterAllAlreadyExist($filename);\n        }\n\n        $this->state[$filename] = $closure;\n    }\n\n    /**\n     * Gets a after all closure by the given filename.\n     */\n    public function get(string $filename): Closure\n    {\n        return $this->state[$filename] ?? NullClosure::create();\n    }\n}\n"
  },
  {
    "path": "src/Repositories/AfterEachRepository.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Repositories;\n\nuse Closure;\nuse Mockery;\nuse Pest\\PendingCalls\\AfterEachCall;\nuse Pest\\Support\\ChainableClosure;\nuse Pest\\Support\\NullClosure;\n\n/**\n * @internal\n */\nfinal class AfterEachRepository\n{\n    /**\n     * @var array<string, Closure>\n     */\n    private array $state = [];\n\n    /**\n     * Sets a after each closure.\n     */\n    public function set(string $filename, AfterEachCall $afterEachCall, Closure $afterEachTestCase): void\n    {\n        if (array_key_exists($filename, $this->state)) {\n            $fromAfterEachTestCase = $this->state[$filename];\n\n            $afterEachTestCase = ChainableClosure::bound($fromAfterEachTestCase, $afterEachTestCase)\n                ->bindTo($afterEachCall, $afterEachCall::class);\n        }\n\n        assert($afterEachTestCase instanceof Closure);\n\n        $this->state[$filename] = $afterEachTestCase;\n    }\n\n    /**\n     * Gets an after each closure by the given filename.\n     */\n    public function get(string $filename): Closure\n    {\n        $afterEach = $this->state[$filename] ?? NullClosure::create();\n\n        return ChainableClosure::bound(function (): void {\n            if (class_exists(Mockery::class)) {\n                if ($container = Mockery::getContainer()) {\n                    /* @phpstan-ignore-next-line */\n                    $this->addToAssertionCount($container->mockery_getExpectationCount());\n                }\n\n                Mockery::close();\n            }\n        }, $afterEach);\n    }\n}\n"
  },
  {
    "path": "src/Repositories/BeforeAllRepository.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Repositories;\n\nuse Closure;\nuse Pest\\Exceptions\\BeforeAllAlreadyExist;\nuse Pest\\Support\\NullClosure;\nuse Pest\\Support\\Reflection;\n\n/**\n * @internal\n */\nfinal class BeforeAllRepository\n{\n    /**\n     * @var array<string, Closure>\n     */\n    private array $state = [];\n\n    /**\n     * Runs one before all closure, and unsets it from the repository.\n     */\n    public function pop(string $filename): Closure\n    {\n        $closure = $this->get($filename);\n\n        unset($this->state[$filename]);\n\n        return $closure;\n    }\n\n    /**\n     * Sets a before all closure.\n     */\n    public function set(Closure $closure): void\n    {\n        $filename = Reflection::getFileNameFromClosure($closure);\n\n        if (array_key_exists($filename, $this->state)) {\n            throw new BeforeAllAlreadyExist($filename);\n        }\n\n        $this->state[$filename] = $closure;\n    }\n\n    /**\n     * Gets a before all closure by the given filename.\n     */\n    public function get(string $filename): Closure\n    {\n        return $this->state[$filename] ?? NullClosure::create();\n    }\n}\n"
  },
  {
    "path": "src/Repositories/BeforeEachRepository.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Repositories;\n\nuse Closure;\nuse Pest\\PendingCalls\\BeforeEachCall;\nuse Pest\\Support\\ChainableClosure;\nuse Pest\\Support\\NullClosure;\n\n/**\n * @internal\n */\nfinal class BeforeEachRepository\n{\n    /**\n     * @var array<string, array{0: Closure, 1: Closure}>\n     */\n    private array $state = [];\n\n    /**\n     * Sets a before each closure.\n     */\n    public function set(string $filename, BeforeEachCall $beforeEachCall, Closure $beforeEachTestCall, Closure $beforeEachTestCase): void\n    {\n        if (array_key_exists($filename, $this->state)) {\n            [$fromBeforeEachTestCall, $fromBeforeEachTestCase] = $this->state[$filename];\n\n            $beforeEachTestCall = ChainableClosure::unbound($fromBeforeEachTestCall, $beforeEachTestCall);\n            $beforeEachTestCase = ChainableClosure::bound($fromBeforeEachTestCase, $beforeEachTestCase)->bindTo($beforeEachCall, $beforeEachCall::class);\n            assert($beforeEachTestCase instanceof Closure);\n        }\n\n        $this->state[$filename] = [$beforeEachTestCall, $beforeEachTestCase];\n    }\n\n    /**\n     * Gets a before each closure by the given filename.\n     *\n     * @return array{0: Closure, 1: Closure}\n     */\n    public function get(string $filename): array\n    {\n        $closures = $this->state[$filename] ?? [];\n\n        return [\n            $closures[0] ?? NullClosure::create(),\n            $closures[1] ?? NullClosure::create(),\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Repositories/DatasetsRepository.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Repositories;\n\nuse Closure;\nuse Generator;\nuse Pest\\Exceptions\\DatasetAlreadyExists;\nuse Pest\\Exceptions\\DatasetDoesNotExist;\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse Pest\\Support\\Exporter;\nuse Traversable;\n\nuse function sprintf;\n\n/**\n * @internal\n */\nfinal class DatasetsRepository\n{\n    private const string SEPARATOR = '>>';\n\n    /**\n     * Holds the datasets.\n     *\n     * @var array<string, Closure|iterable<int|string, mixed>>\n     */\n    private static array $datasets = [];\n\n    /**\n     * Holds the withs.\n     *\n     * @var array<array<string, Closure|iterable<int|string, mixed>|string>>\n     */\n    private static array $withs = [];\n\n    /**\n     * Sets the given.\n     *\n     * @param  Closure|iterable<int|string, mixed>  $data\n     */\n    public static function set(string $name, Closure|iterable $data, string $scope): void\n    {\n        $datasetKey = \"$scope\".self::SEPARATOR.\"$name\";\n\n        if (array_key_exists(\"$datasetKey\", self::$datasets)) {\n            throw new DatasetAlreadyExists($name, $scope);\n        }\n\n        self::$datasets[$datasetKey] = $data;\n    }\n\n    /**\n     * Sets the given \"with\".\n     *\n     * @param  array<Closure|iterable<int|string, mixed>|string>  $with\n     */\n    public static function with(string $filename, string $description, array $with): void\n    {\n        self::$withs[\"$filename\".self::SEPARATOR.\"$description\"] = $with;\n    }\n\n    public static function has(string $filename, string $description): bool\n    {\n        return array_key_exists($filename.self::SEPARATOR.$description, self::$withs);\n    }\n\n    /**\n     * @return array<int|string, mixed>\n     *\n     * @throws ShouldNotHappen\n     */\n    public static function get(string $filename, string $description): array // @phpstan-ignore-line\n    {\n        $dataset = self::$withs[$filename.self::SEPARATOR.$description];\n\n        $dataset = self::resolve($dataset, $filename);\n\n        if ($dataset === null) {\n            throw ShouldNotHappen::fromMessage('Dataset [%s] not resolvable.');\n        }\n\n        return $dataset;\n    }\n\n    /**\n     * Resolves the current dataset to an array value.\n     *\n     * @param  array<Closure|iterable<int|string, mixed>|string>  $dataset\n     * @return array<string, mixed>|null\n     */\n    public static function resolve(array $dataset, string $currentTestFile): ?array\n    {\n        if ($dataset === []) {\n            return null;\n        }\n\n        $dataset = self::processDatasets($dataset, $currentTestFile);\n\n        $datasetCombinations = self::getDatasetsCombinations($dataset);\n\n        $datasetDescriptions = [];\n        $datasetValues = [];\n\n        foreach ($datasetCombinations as $datasetCombination) {\n            $partialDescriptions = [];\n            $values = [];\n\n            foreach ($datasetCombination as $datasetCombinationElement) {\n                $partialDescriptions[] = $datasetCombinationElement['label'];\n\n                $values = array_merge($values, $datasetCombinationElement['values']);\n            }\n\n            $datasetDescriptions[] = implode(' / ', $partialDescriptions);\n            $datasetValues[] = $values;\n        }\n\n        foreach (array_count_values($datasetDescriptions) as $descriptionToCheck => $count) {\n            if ($count > 1) {\n                $index = 1;\n                foreach ($datasetDescriptions as $i => $datasetDescription) {\n                    if ($datasetDescription === $descriptionToCheck) {\n                        $datasetDescriptions[$i] .= sprintf(' #%d', $index++);\n                    }\n                }\n            }\n        }\n\n        $namedData = [];\n        foreach ($datasetDescriptions as $i => $datasetDescription) {\n            $namedData[$datasetDescription] = $datasetValues[$i];\n        }\n\n        return $namedData;\n    }\n\n    /**\n     * @param  array<Closure|iterable<int|string, mixed>|string>  $datasets\n     * @return array<int, array<int, mixed>>\n     */\n    private static function processDatasets(array $datasets, string $currentTestFile): array\n    {\n        $processedDatasets = [];\n\n        foreach ($datasets as $index => $data) {\n            $processedDataset = [];\n\n            if (is_string($data)) {\n                $datasets[$index] = self::getScopedDataset($data, $currentTestFile);\n            }\n\n            if (is_callable($datasets[$index])) {\n                $datasets[$index] = call_user_func($datasets[$index]);\n            }\n\n            if ($datasets[$index] instanceof Traversable) {\n                $preserveKeysForArrayIterator = $datasets[$index] instanceof Generator\n                    && is_string($datasets[$index]->key());\n\n                $datasets[$index] = iterator_to_array($datasets[$index], $preserveKeysForArrayIterator);\n            }\n\n            foreach ($datasets[$index] as $key => $values) {\n                $values = is_array($values) ? $values : [$values];\n                $processedDataset[] = [\n                    'label' => self::getDatasetDescription($key, $values),\n                    'values' => $values,\n                ];\n            }\n\n            $processedDatasets[] = $processedDataset;\n        }\n\n        return $processedDatasets;\n    }\n\n    /**\n     * @return Closure|iterable<int|string, mixed>\n     */\n    private static function getScopedDataset(string $name, string $currentTestFile): Closure|iterable\n    {\n        $matchingDatasets = array_filter(self::$datasets, function (string $key) use ($name, $currentTestFile): bool {\n            [$datasetScope, $datasetName] = explode(self::SEPARATOR, $key);\n\n            if ($name !== $datasetName) {\n                return false;\n            }\n\n            return str_starts_with($currentTestFile, $datasetScope);\n        }, ARRAY_FILTER_USE_KEY);\n\n        /** @var string|null $closestScopeDatasetKey */\n        $closestScopeDatasetKey = array_reduce(\n            array_keys($matchingDatasets),\n            fn (string|int|null $keyA, string|int|null $keyB): string|int|null => $keyA !== null && strlen((string) $keyA) > strlen((string) $keyB) ? $keyA : $keyB\n        );\n\n        if ($closestScopeDatasetKey === null) {\n            throw new DatasetDoesNotExist($name);\n        }\n\n        return $matchingDatasets[$closestScopeDatasetKey];\n    }\n\n    /**\n     * @param  array<array<mixed>>  $combinations\n     * @return array<array<array<mixed>>>\n     */\n    private static function getDatasetsCombinations(array $combinations): array\n    {\n        $result = [[]];\n        foreach ($combinations as $index => $values) {\n            $tmp = [];\n            foreach ($result as $resultItem) {\n                foreach ($values as $value) {\n                    $tmp[] = array_merge($resultItem, [$index => $value]);\n                }\n            }\n            $result = $tmp;\n        }\n\n        return $result;\n    }\n\n    /**\n     * @param  array<int, mixed>  $data\n     */\n    private static function getDatasetDescription(int|string $key, array $data): string\n    {\n        $exporter = Exporter::default();\n\n        if (is_int($key)) {\n            return sprintf('(%s)', $exporter->shortenedRecursiveExport($data));\n        }\n\n        return sprintf('dataset \"%s\"', $key);\n    }\n}\n"
  },
  {
    "path": "src/Repositories/SnapshotRepository.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Repositories;\n\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse Pest\\TestSuite;\n\n/**\n * @internal\n */\nfinal class SnapshotRepository\n{\n    /** @var array<string, int> */\n    private static array $expectationsCounter = [];\n\n    /**\n     * Creates a snapshot repository instance.\n     */\n    public function __construct(\n        private readonly string $rootPath,\n        private readonly string $testsPath,\n        private readonly string $snapshotsPath,\n    ) {}\n\n    /**\n     * Checks if the snapshot exists.\n     */\n    public function has(): bool\n    {\n        return file_exists($this->getSnapshotFilename());\n    }\n\n    /**\n     * Gets the snapshot.\n     *\n     * @return array{0: string, 1: string}\n     *\n     * @throws ShouldNotHappen\n     */\n    public function get(): array\n    {\n        $contents = file_get_contents($snapshotFilename = $this->getSnapshotFilename());\n\n        if ($contents === false) {\n            throw ShouldNotHappen::fromMessage('Snapshot file could not be read.');\n        }\n\n        $snapshot = str_replace(dirname($this->testsPath).'/', '', $snapshotFilename);\n\n        return [$snapshot, $contents];\n    }\n\n    /**\n     * Saves the given snapshot for the given test case.\n     */\n    public function save(string $snapshot): string\n    {\n        $snapshotFilename = $this->getSnapshotFilename();\n\n        if (! file_exists(dirname($snapshotFilename))) {\n            mkdir(dirname($snapshotFilename), 0755, true);\n        }\n\n        file_put_contents($snapshotFilename, $snapshot);\n\n        return str_replace(dirname($this->testsPath).'/', '', $snapshotFilename);\n    }\n\n    /**\n     * Flushes the snapshots.\n     */\n    public function flush(): void\n    {\n        $absoluteSnapshotsPath = $this->testsPath.'/'.$this->snapshotsPath;\n\n        $deleteDirectory = function (string $path) use (&$deleteDirectory): void {\n            if (file_exists($path)) {\n                $scannedDir = scandir($path);\n                assert(is_array($scannedDir));\n\n                $files = array_diff($scannedDir, ['.', '..']);\n\n                foreach ($files as $file) {\n                    if (is_dir($path.'/'.$file)) {\n                        $deleteDirectory($path.'/'.$file);\n                    } else {\n                        unlink($path.'/'.$file);\n                    }\n                }\n\n                rmdir($path);\n            }\n        };\n\n        if (file_exists($absoluteSnapshotsPath)) {\n            $deleteDirectory($absoluteSnapshotsPath);\n        }\n    }\n\n    /**\n     * Gets the snapshot's \"filename\".\n     */\n    private function getSnapshotFilename(): string\n    {\n        $testFile = TestSuite::getInstance()->getFilename();\n\n        if (str_starts_with($testFile, $this->testsPath)) {\n            // if the test file is in the tests directory\n            $startPath = $this->testsPath;\n        } else {\n            // if the test file is in the app, src, etc. directory\n            $startPath = $this->rootPath;\n        }\n\n        // relative path: we use substr() and not str_replace() to remove the start path\n        // for instance, if the $startPath is /app/ and the $testFile is /app/app/tests/Unit/ExampleTest.php, we should only remove the first /app/ from the path\n        $relativePath = substr($testFile, strlen($startPath));\n\n        // remove extension from filename\n        $relativePath = substr($relativePath, 0, (int) strrpos($relativePath, '.'));\n\n        $description = TestSuite::getInstance()->getDescription();\n\n        if ($this->getCurrentSnapshotCounter() > 1) {\n            $description .= '__'.$this->getCurrentSnapshotCounter();\n        }\n\n        return sprintf('%s/%s.snap', $this->testsPath.'/'.$this->snapshotsPath.$relativePath, $description);\n    }\n\n    private function getCurrentSnapshotKey(): string\n    {\n        return TestSuite::getInstance()->getFilename().'###'.TestSuite::getInstance()->getDescription();\n    }\n\n    private function getCurrentSnapshotCounter(): int\n    {\n        return self::$expectationsCounter[$this->getCurrentSnapshotKey()] ?? 0;\n    }\n\n    public function startNewExpectation(): void\n    {\n        $key = $this->getCurrentSnapshotKey();\n\n        if (! isset(self::$expectationsCounter[$key])) {\n            self::$expectationsCounter[$key] = 0;\n        }\n\n        self::$expectationsCounter[$key]++;\n    }\n}\n"
  },
  {
    "path": "src/Repositories/TestRepository.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Repositories;\n\nuse Closure;\nuse Pest\\Contracts\\TestCaseFilter;\nuse Pest\\Contracts\\TestCaseMethodFilter;\nuse Pest\\Exceptions\\TestCaseAlreadyInUse;\nuse Pest\\Exceptions\\TestCaseClassOrTraitNotFound;\nuse Pest\\Factories\\Attribute;\nuse Pest\\Factories\\TestCaseFactory;\nuse Pest\\Factories\\TestCaseMethodFactory;\nuse Pest\\Support\\Str;\nuse PHPUnit\\Framework\\Attributes\\Group;\nuse PHPUnit\\Framework\\TestCase;\n\n/**\n * @internal\n */\nfinal class TestRepository\n{\n    /**\n     * @var array<string, TestCaseFactory>\n     */\n    private array $testCases = [];\n\n    /**\n     * @var array<string, array{0: array<int, string>, 1: array<int, string>, 2: array<int, array<int, string|Closure>>}>\n     */\n    private array $uses = [];\n\n    /**\n     * @var array<int, TestCaseFilter>\n     */\n    private array $testCaseFilters = [];\n\n    /**\n     * @var array<int, TestCaseMethodFilter>\n     */\n    private array $testCaseMethodFilters = [];\n\n    /**\n     * Counts the number of test cases.\n     */\n    public function count(): int\n    {\n        return count($this->testCases);\n    }\n\n    /**\n     * Returns the filename of each test that should be executed in the suite.\n     *\n     * @return array<int, string>\n     */\n    public function getFilenames(): array\n    {\n        return array_values(array_map(static fn (TestCaseFactory $factory): string => $factory->filename, $this->testCases));\n    }\n\n    /**\n     * Uses the given `$testCaseClass` on the given `$paths`.\n     *\n     * @param  array<int, string>  $classOrTraits\n     * @param  array<int, string>  $groups\n     * @param  array<int, string>  $paths\n     * @param  array<int, Closure>  $hooks\n     */\n    public function use(array $classOrTraits, array $groups, array $paths, array $hooks): void\n    {\n        foreach ($classOrTraits as $classOrTrait) {\n            if (class_exists($classOrTrait)) {\n                continue;\n            }\n            if (trait_exists($classOrTrait)) {\n                continue;\n            }\n            throw new TestCaseClassOrTraitNotFound($classOrTrait);\n        }\n\n        $hooks = array_map(fn (Closure $hook): array => [$hook], $hooks);\n\n        foreach ($paths as $path) {\n            if (array_key_exists($path, $this->uses)) {\n                $this->uses[$path] = [\n                    [...$this->uses[$path][0], ...$classOrTraits],\n                    [...$this->uses[$path][1], ...$groups],\n                    array_map(\n                        fn (int $index): array => [...$this->uses[$path][2][$index] ?? [], ...($hooks[$index] ?? [])],\n                        range(0, 3),\n                    ),\n                ];\n            } else {\n                $this->uses[$path] = [$classOrTraits, $groups, $hooks];\n            }\n        }\n    }\n\n    /**\n     * Filters the test cases using the given filter.\n     */\n    public function addTestCaseFilter(TestCaseFilter $filter): void\n    {\n        $this->testCaseFilters[] = $filter;\n    }\n\n    /**\n     * Filters the test cases using the given filter.\n     */\n    public function addTestCaseMethodFilter(TestCaseMethodFilter $filter): void\n    {\n        $this->testCaseMethodFilters[] = $filter;\n    }\n\n    /**\n     * Gets the test case factory from the given filename.\n     */\n    public function get(string $filename): ?TestCaseFactory\n    {\n        return $this->testCases[$filename] ?? null;\n    }\n\n    /**\n     * Sets a new test case method.\n     */\n    public function set(TestCaseMethodFactory $method): void\n    {\n        foreach ($this->testCaseFilters as $filter) {\n            if (! $filter->accept($method->filename)) {\n                return;\n            }\n        }\n\n        foreach ($this->testCaseMethodFilters as $filter) {\n            if (! $filter->accept($method)) {\n                return;\n            }\n        }\n\n        if (! array_key_exists($method->filename, $this->testCases)) {\n            $this->testCases[$method->filename] = new TestCaseFactory($method->filename);\n        }\n\n        $this->testCases[$method->filename]->addMethod($method);\n    }\n\n    /**\n     * Makes a Test Case from the given filename, if exists.\n     */\n    public function makeIfNeeded(string $filename): void\n    {\n        if (! array_key_exists($filename, $this->testCases)) {\n            return;\n        }\n\n        foreach ($this->testCaseFilters as $filter) {\n            if (! $filter->accept($filename)) {\n                return;\n            }\n        }\n\n        $this->make($this->testCases[$filename]);\n    }\n\n    /**\n     * Makes a Test Case using the given factory.\n     */\n    private function make(TestCaseFactory $testCase): void\n    {\n        $startsWith = static fn (string $target, string $directory): bool => Str::startsWith($target, $directory.DIRECTORY_SEPARATOR);\n\n        foreach ($this->uses as $path => $uses) {\n            [$classOrTraits, $groups, $hooks] = $uses;\n\n            if ((! is_dir($path) && $testCase->filename === $path) || (is_dir($path) && $startsWith($testCase->filename, $path))) {\n                foreach ($classOrTraits as $class) {\n                    /** @var string $class */\n                    if (class_exists($class)) {\n                        if ($testCase->class !== TestCase::class) {\n                            throw new TestCaseAlreadyInUse($testCase->class, $class, $testCase->filename);\n                        }\n                        $testCase->class = $class;\n                    } elseif (trait_exists($class)) {\n                        $testCase->traits[] = $class;\n                    }\n                }\n\n                foreach ($testCase->methods as $method) {\n                    foreach ($groups as $group) {\n                        $method->attributes[] = new Attribute(\n                            Group::class,\n                            [$group],\n                        );\n                    }\n                }\n\n                foreach ($testCase->methods as $method) {\n                    $method->groups = [...$groups, ...$method->groups];\n                }\n\n                foreach (['__addBeforeAll', '__addBeforeEach', '__addAfterEach', '__addAfterAll'] as $index => $name) {\n                    foreach ($hooks[$index] ?? [null] as $hook) {\n                        $testCase->factoryProxies->add($testCase->filename, 0, $name, [$hook]);\n                    }\n                }\n            }\n        }\n\n        $testCase->make();\n    }\n}\n"
  },
  {
    "path": "src/Result.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nuse PHPUnit\\TestRunner\\TestResult\\TestResult;\nuse PHPUnit\\TextUI\\Configuration\\Configuration;\nuse PHPUnit\\TextUI\\ShellExitCodeCalculator;\n\n/**\n * @internal\n */\nfinal class Result\n{\n    private const int SUCCESS_EXIT = 0;\n\n    /**\n     * If the exit code is different from 0.\n     */\n    public static function failed(Configuration $configuration, TestResult $result): bool\n    {\n        return ! self::ok($configuration, $result);\n    }\n\n    /**\n     * If the exit code is exactly 0.\n     */\n    public static function ok(Configuration $configuration, TestResult $result): bool\n    {\n        return self::exitCode($configuration, $result) === self::SUCCESS_EXIT;\n    }\n\n    /**\n     * Get the test execution's exit code.\n     */\n    public static function exitCode(Configuration $configuration, TestResult $result): int\n    {\n        $shell = new ShellExitCodeCalculator;\n\n        return $shell->calculate($configuration, $result);\n    }\n}\n"
  },
  {
    "path": "src/Runner/Filter/EnsureTestCaseIsInitiatedFilter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Runner\\Filter;\n\nuse Pest\\Contracts\\HasPrintableTestCaseName;\nuse PHPUnit\\Framework\\Test;\nuse RecursiveFilterIterator;\nuse RecursiveIterator;\n\n/**\n * @internal\n */\nfinal class EnsureTestCaseIsInitiatedFilter extends RecursiveFilterIterator\n{\n    /**\n     * @param  RecursiveIterator<int, Test>  $iterator\n     */\n    public function __construct(RecursiveIterator $iterator)\n    {\n        parent::__construct($iterator);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function accept(): bool\n    {\n        $test = $this->getInnerIterator()->current();\n\n        if ($test instanceof HasPrintableTestCaseName) {\n            /** @phpstan-ignore-next-line */\n            $test->__initializeTestCase();\n        }\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "src/Subscribers/EnsureConfigurationIsAvailable.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Subscribers;\n\nuse Pest\\Support\\Container;\nuse PHPUnit\\Event\\TestRunner\\Configured;\nuse PHPUnit\\Event\\TestRunner\\ConfiguredSubscriber;\nuse PHPUnit\\TextUI\\Configuration\\Configuration;\n\n/**\n * @internal\n */\nfinal class EnsureConfigurationIsAvailable implements ConfiguredSubscriber\n{\n    /**\n     * Runs the subscriber.\n     */\n    public function notify(Configured $event): void\n    {\n        Container::getInstance()->add(Configuration::class, $event->configuration());\n    }\n}\n"
  },
  {
    "path": "src/Subscribers/EnsureIgnorableTestCasesAreIgnored.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Subscribers;\n\nuse PHPUnit\\Event\\TestRunner\\Started;\nuse PHPUnit\\Event\\TestRunner\\StartedSubscriber;\nuse PHPUnit\\Event\\TestRunner\\WarningTriggered;\nuse PHPUnit\\TestRunner\\TestResult\\Collector;\nuse PHPUnit\\TestRunner\\TestResult\\Facade;\nuse ReflectionClass;\n\n/**\n * @internal\n */\nfinal class EnsureIgnorableTestCasesAreIgnored implements StartedSubscriber\n{\n    /**\n     * Runs the subscriber.\n     */\n    public function notify(Started $event): void\n    {\n        $reflection = new ReflectionClass(Facade::class);\n        $property = $reflection->getProperty('collector');\n        $collector = $property->getValue();\n\n        assert($collector instanceof Collector);\n\n        $reflection = new ReflectionClass($collector);\n        $property = $reflection->getProperty('testRunnerTriggeredWarningEvents');\n\n        /** @var array<int, WarningTriggered> $testRunnerTriggeredWarningEvents */\n        $testRunnerTriggeredWarningEvents = $property->getValue($collector);\n\n        $testRunnerTriggeredWarningEvents = array_values(array_filter($testRunnerTriggeredWarningEvents, fn (WarningTriggered $event): bool => str_contains($event->message(), 'No tests found in class') === false));\n\n        $property->setValue($collector, $testRunnerTriggeredWarningEvents);\n    }\n}\n"
  },
  {
    "path": "src/Subscribers/EnsureKernelDumpIsFlushed.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Subscribers;\n\nuse Pest\\KernelDump;\nuse Pest\\Support\\Container;\nuse PHPUnit\\Event\\TestRunner\\Started;\nuse PHPUnit\\Event\\TestRunner\\StartedSubscriber;\n\n/**\n * @internal\n */\nfinal class EnsureKernelDumpIsFlushed implements StartedSubscriber\n{\n    /**\n     * Runs the subscriber.\n     */\n    public function notify(Started $event): void\n    {\n        $kernelDump = Container::getInstance()->get(KernelDump::class);\n\n        assert($kernelDump instanceof KernelDump);\n\n        $kernelDump->disable();\n    }\n}\n"
  },
  {
    "path": "src/Subscribers/EnsureTeamCityEnabled.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Subscribers;\n\nuse Pest\\Logging\\Converter;\nuse Pest\\Logging\\TeamCity\\TeamCityLogger;\nuse Pest\\TestSuite;\nuse PHPUnit\\Event\\TestRunner\\Configured;\nuse PHPUnit\\Event\\TestRunner\\ConfiguredSubscriber;\nuse Symfony\\Component\\Console\\Input\\InputInterface;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\n/**\n * @internal\n */\nfinal readonly class EnsureTeamCityEnabled implements ConfiguredSubscriber\n{\n    /**\n     * Creates a new Configured Subscriber instance.\n     */\n    public function __construct(\n        private InputInterface $input,\n        private OutputInterface $output,\n        private TestSuite $testSuite,\n    ) {}\n\n    /**\n     * Runs the subscriber.\n     */\n    public function notify(Configured $event): void\n    {\n        if (! $this->input->hasParameterOption('--teamcity')) {\n            return;\n        }\n\n        $flowId = getenv('FLOW_ID');\n        $flowId = is_string($flowId) ? (int) $flowId : getmypid();\n\n        new TeamCityLogger(\n            $this->output,\n            new Converter($this->testSuite->rootPath),\n            $flowId === false ? null : $flowId,\n            getenv('COLLISION_IGNORE_DURATION') !== false\n        );\n    }\n}\n"
  },
  {
    "path": "src/Support/Arr.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\n/**\n * @internal\n */\nfinal class Arr\n{\n    /**\n     * Checks if the given array has the given key.\n     *\n     * @param  array<array-key, mixed>  $array\n     */\n    public static function has(array $array, string|int $key): bool\n    {\n        $key = (string) $key;\n\n        if (array_key_exists($key, $array)) {\n            return true;\n        }\n\n        foreach (explode('.', $key) as $segment) {\n            if (is_array($array) && array_key_exists($segment, $array)) {\n                $array = $array[$segment];\n            } else {\n                return false;\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Gets the given key value.\n     *\n     * @param  array<array-key, mixed>  $array\n     */\n    public static function get(array $array, string|int $key, mixed $default = null): mixed\n    {\n        $key = (string) $key;\n\n        if (array_key_exists($key, $array)) {\n            return $array[$key];\n        }\n\n        if (! str_contains($key, '.')) {\n            return $array[$key] ?? $default;\n        }\n\n        foreach (explode('.', $key) as $segment) {\n            if (is_array($array) && array_key_exists($segment, $array)) {\n                $array = $array[$segment];\n            } else {\n                return $default;\n            }\n        }\n\n        return $array;\n    }\n\n    /**\n     * Flatten a multi-dimensional associative array with dots.\n     *\n     * @param  array<array-key, mixed>  $array\n     * @return array<int|string, mixed>\n     */\n    public static function dot(array $array, string $prepend = ''): array\n    {\n        $results = [];\n\n        foreach ($array as $key => $value) {\n            if (is_array($value) && $value !== []) {\n                $results = array_merge($results, self::dot($value, $prepend.$key.'.'));\n            } else {\n                $results[$prepend.$value] = $value;\n            }\n        }\n\n        return $results;\n    }\n\n    /**\n     * Returns the value of the last element or false for empty array\n     *\n     * @param  array<array-key, mixed>  $array\n     */\n    public static function last(array $array): mixed\n    {\n        return end($array);\n    }\n}\n"
  },
  {
    "path": "src/Support/Backtrace.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Pest\\Exceptions\\ShouldNotHappen;\n\n/**\n * @internal\n */\nfinal class Backtrace\n{\n    private const string FILE = 'file';\n\n    private const int BACKTRACE_OPTIONS = DEBUG_BACKTRACE_IGNORE_ARGS;\n\n    /**\n     * Returns the current test file.\n     */\n    public static function testFile(): string\n    {\n        $current = null;\n\n        foreach (debug_backtrace(self::BACKTRACE_OPTIONS) as $trace) {\n            assert(array_key_exists(self::FILE, $trace));\n\n            $traceFile = str_replace(DIRECTORY_SEPARATOR, '/', $trace[self::FILE]);\n\n            if (\n                Str::endsWith($traceFile, 'overrides/Runner/TestSuiteLoader.php') ||\n                Str::endsWith($traceFile, 'src/Bootstrappers/BootFiles.php')\n            ) {\n                break;\n            }\n\n            $current = $trace;\n        }\n\n        if ($current === null) {\n            throw ShouldNotHappen::fromMessage('Test file not found.');\n        }\n\n        return $current[self::FILE];\n    }\n\n    /**\n     * Returns the current datasets file.\n     */\n    public static function datasetsFile(): string\n    {\n        $current = null;\n\n        foreach (debug_backtrace(self::BACKTRACE_OPTIONS) as $trace) {\n            assert(array_key_exists(self::FILE, $trace));\n\n            $traceFile = str_replace(DIRECTORY_SEPARATOR, '/', $trace[self::FILE]);\n\n            if (Str::endsWith($traceFile, 'Bootstrappers/BootFiles.php') || Str::endsWith($traceFile, 'overrides/Runner/TestSuiteLoader.php')) {\n                break;\n            }\n\n            $current = $trace;\n        }\n\n        if ($current === null) {\n            throw ShouldNotHappen::fromMessage('Dataset file not found.');\n        }\n\n        return $current[self::FILE];\n    }\n\n    /**\n     * Returns the filename that called the current function/method.\n     */\n    public static function file(): string\n    {\n        $trace = self::backtrace();\n\n        return $trace[self::FILE];\n    }\n\n    /**\n     * Returns the dirname that called the current function/method.\n     */\n    public static function dirname(): string\n    {\n        $trace = self::backtrace();\n\n        return dirname($trace[self::FILE]);\n    }\n\n    /**\n     * Returns the line that called the current function/method.\n     */\n    public static function line(): int\n    {\n        $trace = self::backtrace();\n\n        return $trace['line'] ?? 0;\n    }\n\n    /**\n     * @return array{function: string, line?: int, file: string, class?: class-string, type?: string, args?: mixed[], object?: object}\n     */\n    private static function backtrace(): array\n    {\n        $backtrace = debug_backtrace(self::BACKTRACE_OPTIONS);\n\n        foreach ($backtrace as $trace) {\n            if (! isset($trace['file'])) {\n                continue;\n            }\n\n            if (($GLOBALS['__PEST_INTERNAL_TEST_SUITE'] ?? false) && str_contains($trace['file'], 'pest'.DIRECTORY_SEPARATOR.'src')) {\n                continue;\n            }\n\n            if (str_contains($trace['file'], DIRECTORY_SEPARATOR.'pestphp'.DIRECTORY_SEPARATOR.'pest'.DIRECTORY_SEPARATOR.'src')) {\n                continue;\n            }\n\n            return $trace;\n        }\n\n        throw ShouldNotHappen::fromMessage('Backtrace not found.');\n    }\n}\n"
  },
  {
    "path": "src/Support/ChainableClosure.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Closure;\nuse Pest\\Exceptions\\ShouldNotHappen;\n\n/**\n * @internal\n */\nfinal class ChainableClosure\n{\n    /**\n     * Calls the given `$closure` when the given condition is true, \"bound\" to the same object.\n     */\n    public static function boundWhen(Closure $condition, Closure $next): Closure\n    {\n        return function (...$arguments) use ($condition, $next): void {\n            if (! is_object($this)) { // @phpstan-ignore-line\n                throw ShouldNotHappen::fromMessage('$this not bound to chainable closure.');\n            }\n\n            if (\\Pest\\Support\\Closure::bind($condition, $this, self::class)(...$arguments)) {\n                \\Pest\\Support\\Closure::bind($next, $this, self::class)(...$arguments);\n            }\n        };\n    }\n\n    /**\n     * Calls the given `$closure` and chains the `$next` closure, \"bound\" to the same object.\n     */\n    public static function bound(Closure $closure, Closure $next): Closure\n    {\n        return function (...$arguments) use ($closure, $next): void {\n            if (! is_object($this)) { // @phpstan-ignore-line\n                throw ShouldNotHappen::fromMessage('$this not bound to chainable closure.');\n            }\n\n            \\Pest\\Support\\Closure::bind($closure, $this, self::class)(...$arguments);\n            \\Pest\\Support\\Closure::bind($next, $this, self::class)(...$arguments);\n        };\n    }\n\n    /**\n     * Calls the given `$closure` and chains the `$next` closure, \"unbound\" of any object.\n     */\n    public static function unbound(Closure $closure, Closure $next): Closure\n    {\n        return function (...$arguments) use ($closure, $next): void {\n            $closure(...$arguments);\n            $next(...$arguments);\n        };\n    }\n\n    /**\n     * Call the given static `$closure` and chains the `$next` closure, \"bound\" to the same object statically.\n     */\n    public static function boundStatically(Closure $closure, Closure $next): Closure\n    {\n        return static function (...$arguments) use ($closure, $next): void {\n            \\Pest\\Support\\Closure::bind($closure, null, self::class)(...$arguments);\n            \\Pest\\Support\\Closure::bind($next, null, self::class)(...$arguments);\n        };\n    }\n}\n"
  },
  {
    "path": "src/Support/Closure.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Closure as BaseClosure;\nuse Pest\\Exceptions\\ShouldNotHappen;\n\n/**\n * @internal\n */\nfinal class Closure\n{\n    /**\n     * Binds the given closure to the given \"this\".\n     *\n     * @throws ShouldNotHappen\n     */\n    public static function bind(?BaseClosure $closure, ?object $newThis, object|string|null $newScope = 'static'): BaseClosure\n    {\n        if (! $closure instanceof BaseClosure) {\n            throw ShouldNotHappen::fromMessage('Could not bind null closure.');\n        }\n\n        // @phpstan-ignore-next-line\n        $closure = BaseClosure::bind($closure, $newThis, $newScope);\n\n        if (! $closure instanceof BaseClosure) {\n            throw ShouldNotHappen::fromMessage('Could not bind closure.');\n        }\n\n        return $closure;\n    }\n}\n"
  },
  {
    "path": "src/Support/Container.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse ReflectionClass;\nuse ReflectionParameter;\n\n/**\n * @internal\n */\nfinal class Container\n{\n    /**\n     * The instance of the container.\n     */\n    private static ?Container $instance = null;\n\n    /**\n     * @var array<string, object|string>\n     */\n    private array $instances = [];\n\n    /**\n     * Gets a new or already existing container.\n     */\n    public static function getInstance(): self\n    {\n        if (! self::$instance instanceof Container) {\n            self::$instance = new self;\n        }\n\n        return self::$instance;\n    }\n\n    /**\n     * Gets a dependency from the container.\n     */\n    public function get(string $id): object|string\n    {\n        if (! array_key_exists($id, $this->instances)) {\n            /** @var class-string $id */\n            $this->instances[$id] = $this->build($id);\n        }\n\n        return $this->instances[$id];\n    }\n\n    /**\n     * Adds the given instance to the container.\n     *\n     * @return $this\n     */\n    public function add(string $id, object|string $instance): self\n    {\n        $this->instances[$id] = $instance;\n\n        return $this;\n    }\n\n    /**\n     * Tries to build the given instance.\n     *\n     * @template TObject of object\n     *\n     * @param  class-string<TObject>  $id\n     * @return TObject\n     */\n    private function build(string $id): object\n    {\n        $reflectionClass = new ReflectionClass($id);\n\n        if ($reflectionClass->isInstantiable()) {\n            $constructor = $reflectionClass->getConstructor();\n\n            if ($constructor instanceof \\ReflectionMethod) {\n                $params = array_map(\n                    function (ReflectionParameter $param) use ($id): object|string {\n                        $candidate = Reflection::getParameterClassName($param);\n\n                        if ($candidate === null) {\n                            $type = $param->getType();\n                            /* @phpstan-ignore-next-line */\n                            if ($type instanceof \\ReflectionType && $type->isBuiltin()) {\n                                $candidate = $param->getName();\n                            } else {\n                                throw ShouldNotHappen::fromMessage(sprintf('The type of `$%s` in `%s` cannot be determined.', $id, $param->getName()));\n                            }\n                        }\n\n                        return $this->get($candidate);\n                    },\n                    $constructor->getParameters()\n                );\n\n                return $reflectionClass->newInstanceArgs($params);\n            }\n\n            return $reflectionClass->newInstance();\n        }\n\n        throw ShouldNotHappen::fromMessage(sprintf('A dependency with the name `%s` cannot be resolved.', $id));\n    }\n}\n"
  },
  {
    "path": "src/Support/Coverage.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse SebastianBergmann\\CodeCoverage\\CodeCoverage;\nuse SebastianBergmann\\CodeCoverage\\Node\\Directory;\nuse SebastianBergmann\\CodeCoverage\\Node\\File;\nuse SebastianBergmann\\Environment\\Runtime;\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\n\nuse function Termwind\\render;\nuse function Termwind\\renderUsing;\nuse function Termwind\\terminal;\n\n/**\n * @internal\n */\nfinal class Coverage\n{\n    /**\n     * Returns the coverage path.\n     */\n    public static function getPath(): string\n    {\n        return implode(DIRECTORY_SEPARATOR, [\n            dirname(__DIR__, 2),\n            '.temp',\n            'coverage.php',\n        ]);\n    }\n\n    /**\n     * Runs true there is any code coverage driver available.\n     */\n    public static function isAvailable(): bool\n    {\n        $runtime = new Runtime;\n\n        if (! $runtime->canCollectCodeCoverage()) {\n            return false;\n        }\n\n        if ($runtime->hasPCOV()) {\n            return true;\n        }\n\n        if ($runtime->hasPHPDBGCodeCoverage()) {\n            return true;\n        }\n\n        if (! $runtime->hasXdebug()) {\n            return true;\n        }\n\n        if (! version_compare((string) phpversion('xdebug'), '3.1', '>=')) {\n            return true;\n        }\n\n        return in_array('coverage', xdebug_info('mode'), true);\n    }\n\n    /**\n     * If the user is using Xdebug.\n     */\n    public static function usingXdebug(): bool\n    {\n        return (new Runtime)->hasXdebug();\n    }\n\n    /**\n     * Reports the code coverage report to the\n     * console and returns the result in float.\n     */\n    public static function report(OutputInterface $output, bool $compact = false): float\n    {\n        if (! file_exists($reportPath = self::getPath())) {\n            if (self::usingXdebug()) {\n                $output->writeln(\n                    \"  <fg=black;bg=yellow;options=bold> WARN </> Unable to get coverage using Xdebug. Did you set <href=https://xdebug.org/docs/code_coverage#mode>Xdebug's coverage mode</>?</>\",\n                );\n\n                return 0.0;\n            }\n\n            throw ShouldNotHappen::fromMessage(sprintf('Coverage not found in path: %s.', $reportPath));\n        }\n\n        /** @var CodeCoverage $codeCoverage */\n        $codeCoverage = require $reportPath;\n        unlink($reportPath);\n\n        $totalCoverage = $codeCoverage->getReport()->percentageOfExecutedLines();\n\n        /** @var Directory<File|Directory> $report */\n        $report = $codeCoverage->getReport();\n\n        foreach ($report->getIterator() as $file) {\n            if (! $file instanceof File) {\n                continue;\n            }\n            $dirname = dirname($file->id());\n            $basename = basename($file->id(), '.php');\n\n            $name = $dirname === '.' ? $basename : implode(DIRECTORY_SEPARATOR, [\n                $dirname,\n                $basename,\n            ]);\n\n            $percentage = $file->numberOfExecutableLines() === 0\n                ? '100.0'\n                : number_format($file->percentageOfExecutedLines()->asFloat(), 1, '.', '');\n\n            if ($percentage === '100.0' && $compact) {\n                continue;\n            }\n\n            $uncoveredLines = '';\n\n            $percentageOfExecutedLinesAsString = $file->percentageOfExecutedLines()->asString();\n\n            if (! in_array($percentageOfExecutedLinesAsString, ['0.00%', '100.00%', '100.0%', ''], true)) {\n                $uncoveredLines = trim(implode(', ', self::getMissingCoverage($file)));\n                $uncoveredLines = sprintf('<span>%s</span>', $uncoveredLines).' <span class=\"text-gray\"> / </span>';\n            }\n\n            $color = $percentage === '100.0' ? 'green' : ($percentage === '0.0' ? 'red' : 'yellow');\n\n            $truncateAt = max(1, terminal()->width() - 12);\n\n            renderUsing($output);\n            render(<<<HTML\n                <div class=\"flex mx-2\">\n                    <span class=\"truncate-{$truncateAt}\">{$name}</span>\n                    <span class=\"flex-1 content-repeat-[.] text-gray mx-1\"></span>\n                    <span class=\"text-{$color}\">$uncoveredLines {$percentage}%</span>\n                </div>\n            HTML);\n        }\n\n        $totalCoverageAsString = $totalCoverage->asFloat() === 0.0\n            ? '0.0'\n            : number_format(floor($totalCoverage->asFloat() * 10) / 10, 1, '.', '');\n\n        renderUsing($output);\n        render(<<<HTML\n            <div class=\"mx-2\">\n                <hr class=\"text-gray\" />\n                <div class=\"w-full text-right\">\n                    <span class=\"ml-1 font-bold\">Total: {$totalCoverageAsString} %</span>\n                </div>\n            </div>\n        HTML);\n\n        return $totalCoverage->asFloat();\n    }\n\n    /**\n     * Generates an array of missing coverage on the following format:.\n     *\n     * ```\n     * ['11', '20..25', '50', '60..80'];\n     * ```\n     *\n     *\n     * @param  File  $file\n     * @return array<int, string>\n     */\n    public static function getMissingCoverage(mixed $file): array\n    {\n        $shouldBeNewLine = true;\n\n        $eachLine = function (array $array, array $tests, int $line) use (&$shouldBeNewLine): array {\n            if ($tests !== []) {\n                $shouldBeNewLine = true;\n\n                return $array;\n            }\n\n            if ($shouldBeNewLine) {\n                $array[] = (string) $line;\n                $shouldBeNewLine = false;\n\n                return $array;\n            }\n\n            $lastKey = count($array) - 1;\n\n            if (array_key_exists($lastKey, $array) && str_contains((string) $array[$lastKey], '..')) {\n                [$from] = explode('..', (string) $array[$lastKey]);\n                $array[$lastKey] = $line > $from ? sprintf('%s..%s', $from, $line) : sprintf('%s..%s', $line, $from);\n\n                return $array;\n            }\n\n            $array[$lastKey] = sprintf('%s..%s', $array[$lastKey], $line);\n\n            return $array;\n        };\n\n        $array = [];\n        foreach (array_filter($file->lineCoverageData(), is_array(...)) as $line => $tests) {\n            $array = $eachLine($array, $tests, $line);\n        }\n\n        return $array;\n    }\n}\n"
  },
  {
    "path": "src/Support/DatasetInfo.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse function Pest\\testDirectory;\n\n/**\n * @internal\n */\nfinal class DatasetInfo\n{\n    public const string DATASETS_DIR_NAME = 'Datasets';\n\n    public const string DATASETS_FILE_NAME = 'Datasets.php';\n\n    public static function isInsideADatasetsDirectory(string $file): bool\n    {\n        return basename(dirname($file)) === self::DATASETS_DIR_NAME;\n    }\n\n    public static function isADatasetsFile(string $file): bool\n    {\n        return basename($file) === self::DATASETS_FILE_NAME;\n    }\n\n    public static function scope(string $file): string\n    {\n        if (Str::endsWith($file, testDirectory('Pest.php'))) {\n            return dirname($file);\n        }\n\n        if (self::isInsideADatasetsDirectory($file)) {\n            return dirname($file, 2);\n        }\n\n        if (self::isADatasetsFile($file)) {\n            return dirname($file);\n        }\n\n        return $file;\n    }\n}\n"
  },
  {
    "path": "src/Support/Description.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nfinal readonly class Description implements \\Stringable\n{\n    /**\n     * Creates a new Description instance.\n     */\n    public function __construct(private string $description) {}\n\n    /**\n     * Returns the description as a string.\n     */\n    public function __toString(): string\n    {\n        return $this->description;\n    }\n}\n"
  },
  {
    "path": "src/Support/ExceptionTrace.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Closure;\nuse PHPUnit\\Framework\\TestCase;\nuse Throwable;\n\n/**\n * @internal\n */\nfinal class ExceptionTrace\n{\n    private const string UNDEFINED_METHOD = 'Call to undefined method P\\\\';\n\n    /**\n     * Ensures the given closure reports the good execution context.\n     *\n     * @throws Throwable\n     */\n    public static function ensure(Closure $closure): mixed\n    {\n        try {\n            return $closure();\n        } catch (Throwable $throwable) {\n            if (Str::startsWith($message = $throwable->getMessage(), self::UNDEFINED_METHOD)) {\n                $class = preg_match('/^Call to undefined method ([^:]+)::/', $message, $matches) === false ? null : $matches[1];\n\n                $message = str_replace(self::UNDEFINED_METHOD, 'Call to undefined method ', $message);\n\n                if (class_exists((string) $class) && (is_countable(class_parents($class)) ? count(class_parents($class)) : 0) > 0 && array_values(class_parents($class))[0] === TestCase::class) { // @phpstan-ignore-line\n                    $message .= '. Did you forget to use the [pest()->extend()] function? Read more at: https://pestphp.com/docs/configuring-tests';\n                }\n\n                Reflection::setPropertyValue($throwable, 'message', $message);\n            }\n\n            throw $throwable;\n        }\n    }\n}\n"
  },
  {
    "path": "src/Support/ExpectationPipeline.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Closure;\n\n/**\n * @internal\n */\nfinal class ExpectationPipeline\n{\n    /**\n     * The list of pipes.\n     *\n     * @var array<int, Closure>\n     */\n    private array $pipes = [];\n\n    /**\n     * The list of passables.\n     *\n     * @var array<array-key, mixed>\n     */\n    private array $passables;\n\n    /**\n     * Creates a new instance of Expectation Pipeline.\n     */\n    public function __construct(\n        private readonly Closure $closure\n    ) {}\n\n    /**\n     * Creates a new instance of Expectation Pipeline with given closure.\n     */\n    public static function for(Closure $closure): self\n    {\n        return new self($closure);\n    }\n\n    /**\n     * Sets the list of passables.\n     */\n    public function send(mixed ...$passables): self\n    {\n        $this->passables = $passables;\n\n        return $this;\n    }\n\n    /**\n     * Sets the list of pipes.\n     *\n     * @param  array<int, Closure>  $pipes\n     */\n    public function through(array $pipes): self\n    {\n        $this->pipes = $pipes;\n\n        return $this;\n    }\n\n    /**\n     * Runs the pipeline.\n     */\n    public function run(): void\n    {\n        $pipeline = array_reduce(\n            array_reverse($this->pipes),\n            $this->carry(),\n            function (): void {\n                call_user_func_array($this->closure, $this->passables);\n            }\n        );\n\n        $pipeline();\n    }\n\n    /**\n     * Get a Closure that will carry of the expectation.\n     */\n    public function carry(): Closure\n    {\n        return fn (mixed $stack, callable $pipe): Closure => fn () => $pipe($stack, ...$this->passables);\n    }\n}\n"
  },
  {
    "path": "src/Support/Exporter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse SebastianBergmann\\Exporter\\Exporter as BaseExporter;\nuse SebastianBergmann\\RecursionContext\\Context;\n\n/**\n * @internal\n */\nfinal readonly class Exporter\n{\n    /**\n     * The maximum number of items in an array to export.\n     */\n    private const int MAX_ARRAY_ITEMS = 3;\n\n    /**\n     * Creates a new Exporter instance.\n     */\n    public function __construct(\n        private BaseExporter $exporter,\n    ) {\n        // ...\n    }\n\n    /**\n     * Creates a new Exporter instance.\n     */\n    public static function default(): self\n    {\n        return new self(\n            new BaseExporter\n        );\n    }\n\n    /**\n     * Exports a value into a single-line string recursively.\n     *\n     * @param  array<int|string, mixed>  $data\n     */\n    public function shortenedRecursiveExport(array &$data, ?Context $context = null): string\n    {\n        $result = [];\n        $array = $data;\n        $itemsCount = 0;\n        $exporter = self::default();\n        $context ??= new Context;\n\n        $context->add($data);\n\n        foreach ($array as $key => $value) {\n            if (++$itemsCount > self::MAX_ARRAY_ITEMS) {\n                $result[] = '…';\n\n                break;\n            }\n\n            if (! is_array($value)) {\n                $result[] = $exporter->shortenedExport($value);\n\n                continue;\n            }\n\n            $result[] = $context->contains($data[$key]) !== false\n                ? '*RECURSION*'\n                // @phpstan-ignore-next-line\n                : sprintf('[%s]', $this->shortenedRecursiveExport($data[$key], $context));\n        }\n\n        return implode(', ', $result);\n    }\n\n    /**\n     * Exports a value into a single-line string.\n     */\n    public function shortenedExport(mixed $value): string\n    {\n        $map = [\n            '#\\.{3}#' => '…',\n            '#\\\\\\n\\s*#' => '',\n            '# Object \\(…\\)#' => '',\n        ];\n\n        return (string) preg_replace(array_keys($map), array_values($map), $this->exporter->shortenedExport($value));\n    }\n}\n"
  },
  {
    "path": "src/Support/HigherOrderCallables.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Closure;\nuse Pest\\Expectation;\n\n/**\n * @internal\n */\nfinal readonly class HigherOrderCallables\n{\n    /**\n     * Creates a new Higher Order Callables instances.\n     */\n    public function __construct(private object $target)\n    {\n        // ..\n    }\n\n    /**\n     * @template TValue\n     *\n     * Create a new expectation. Callable values will be executed prior to returning the new expectation.\n     *\n     * @param  (Closure():TValue)|TValue  $value\n     * @return Expectation<TValue>\n     */\n    public function expect(mixed $value): Expectation\n    {\n        /** @var TValue $value */\n        $value = $value instanceof Closure ? Reflection::bindCallableWithData($value) : $value;\n\n        return new Expectation($value);\n    }\n\n    /**\n     * @template TValue\n     *\n     * Create a new expectation. Callable values will be executed prior to returning the new expectation.\n     *\n     * @param  callable|TValue  $value\n     * @return Expectation<(callable(): mixed)|TValue>\n     */\n    public function and(mixed $value): Expectation\n    {\n        // @phpstan-ignore-next-line\n        return $this->expect($value);\n    }\n\n    /**\n     * Execute the given callable after the test has executed the setup method.\n     */\n    public function defer(callable $callable): object\n    {\n        Reflection::bindCallableWithData($callable);\n\n        return $this->target;\n    }\n}\n"
  },
  {
    "path": "src/Support/HigherOrderMessage.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Closure;\nuse ReflectionClass;\nuse Throwable;\n\n/**\n * @internal\n */\nfinal class HigherOrderMessage\n{\n    public const string UNDEFINED_METHOD = 'Method %s does not exist';\n\n    /**\n     * An optional condition that will determine if the message will be executed.\n     *\n     * @var (Closure(): bool)|null\n     */\n    public ?Closure $condition = null;\n\n    /**\n     * Creates a new higher order message.\n     *\n     * @param  array<int, mixed>|null  $arguments\n     */\n    public function __construct(\n        public string $filename,\n        public int $line,\n        public string $name,\n        public ?array $arguments\n    ) {\n        // ..\n    }\n\n    /**\n     * Re-throws the given `$throwable` with the good line and filename.\n     *\n     * @template TValue of object\n     *\n     * @param  TValue  $target\n     */\n    public function call(object $target): mixed\n    {\n        if (is_callable($this->condition) && call_user_func(Closure::bind($this->condition, $target)) === false) {\n            return $target;\n        }\n\n        if ($this->hasHigherOrderCallable()) {\n            return (new HigherOrderCallables($target))->{$this->name}(...$this->arguments);\n        }\n\n        try {\n            return is_array($this->arguments)\n                ? Reflection::call($target, $this->name, $this->arguments)\n                : $target->{$this->name};\n        } catch (Throwable $throwable) {\n            Reflection::setPropertyValue($throwable, 'file', $this->filename);\n            Reflection::setPropertyValue($throwable, 'line', $this->line);\n\n            if ($throwable->getMessage() === $this->getUndefinedMethodMessage($target, $this->name)) {\n                /** @var ReflectionClass<TValue> $reflection */\n                $reflection = new ReflectionClass($target);\n                $reflection = $reflection->getParentClass() ?: $reflection;\n                Reflection::setPropertyValue($throwable, 'message', sprintf('Call to undefined method %s::%s()', $reflection->getName(), $this->name));\n            }\n\n            throw $throwable;\n        }\n    }\n\n    /**\n     * Indicates that this message should only be called when the given condition is true.\n     *\n     * @param  callable(): bool  $condition\n     */\n    public function when(callable $condition): self\n    {\n        $this->condition = Closure::fromCallable($condition);\n\n        return $this;\n    }\n\n    /**\n     * Determines whether or not there exists a higher order callable with the message name.\n     */\n    private function hasHigherOrderCallable(): bool\n    {\n        return in_array($this->name, get_class_methods(HigherOrderCallables::class), true);\n    }\n\n    private function getUndefinedMethodMessage(object $target, string $methodName): string\n    {\n        return sprintf(self::UNDEFINED_METHOD, sprintf('%s::%s()', $target::class, $methodName));\n    }\n}\n"
  },
  {
    "path": "src/Support/HigherOrderMessageCollection.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\n/**\n * @internal\n */\nfinal class HigherOrderMessageCollection\n{\n    /**\n     * @var array<int, HigherOrderMessage>\n     */\n    private array $messages = [];\n\n    /**\n     * Adds a new higher order message to the collection.\n     *\n     * @param  array<int, mixed>|null  $arguments\n     */\n    public function add(string $filename, int $line, string $name, ?array $arguments): void\n    {\n        $this->messages[] = new HigherOrderMessage($filename, $line, $name, $arguments);\n    }\n\n    /**\n     * Adds a new higher order message to the collection if the callable condition is does not return false.\n     *\n     * @param  array<int, mixed>|null  $arguments\n     */\n    public function addWhen(callable $condition, string $filename, int $line, string $name, ?array $arguments): void\n    {\n        $this->messages[] = (new HigherOrderMessage($filename, $line, $name, $arguments))->when($condition);\n    }\n\n    /**\n     * Proxy all the messages starting from the target.\n     */\n    public function chain(object $target): void\n    {\n        foreach ($this->messages as $message) {\n            $target = $message->call($target) ?? $target;\n        }\n    }\n\n    /**\n     * Proxy all the messages to the target.\n     */\n    public function proxy(object $target): void\n    {\n        foreach ($this->messages as $message) {\n            $message->call($target);\n        }\n    }\n\n    /**\n     * Count the number of messages with the given name.\n     *\n     * @param  string  $name  A higher order message name (usually a method name)\n     */\n    public function count(string $name): int\n    {\n        return array_reduce(\n            $this->messages,\n            static fn (int $total, HigherOrderMessage $message): int => $total + (int) ($name === $message->name),\n            0,\n        );\n    }\n}\n"
  },
  {
    "path": "src/Support/HigherOrderTapProxy.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse PHPUnit\\Framework\\TestCase;\nuse ReflectionClass;\n\n/**\n * @internal\n */\nfinal class HigherOrderTapProxy\n{\n    /**\n     * Create a new tap proxy instance.\n     */\n    public function __construct(\n        public TestCase $target\n    ) {\n        // ..\n    }\n\n    /**\n     * Dynamically sets properties on the target.\n     */\n    public function __set(string $property, mixed $value): void\n    {\n        $this->target->{$property} = $value;\n    }\n\n    /**\n     * Dynamically pass properties gets to the target.\n     */\n    public function __get(string $property): mixed\n    {\n        if (property_exists($this->target, $property)) {\n            return $this->target->{$property};\n        }\n\n        $className = (new ReflectionClass($this->target))->getName();\n\n        if (str_starts_with($className, 'P\\\\')) {\n            $className = substr($className, 2);\n        }\n\n        trigger_error(sprintf('Undefined property %s::$%s', $className, $property), E_USER_WARNING);\n\n        return null;\n    }\n\n    /**\n     * Dynamically pass method calls to the target.\n     *\n     * @param  array<int, mixed>  $arguments\n     * @return mixed\n     */\n    public function __call(string $methodName, array $arguments)\n    {\n        $filename = Backtrace::file();\n        $line = Backtrace::line();\n\n        return (new HigherOrderMessage($filename, $line, $methodName, $arguments))\n            ->call($this->target);\n    }\n}\n"
  },
  {
    "path": "src/Support/NullClosure.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Closure;\n\n/**\n * @internal\n */\nfinal class NullClosure\n{\n    /**\n     * Creates a nullable closure.\n     */\n    public static function create(): Closure\n    {\n        return Closure::fromCallable(function (): void {});\n    }\n}\n"
  },
  {
    "path": "src/Support/Reflection.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Closure;\nuse InvalidArgumentException;\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse Pest\\TestSuite;\nuse PHPUnit\\Framework\\TestCase;\nuse ReflectionClass;\nuse ReflectionException;\nuse ReflectionFunction;\nuse ReflectionMethod;\nuse ReflectionNamedType;\nuse ReflectionParameter;\nuse ReflectionProperty;\nuse ReflectionUnionType;\n\n/**\n * @internal\n */\nfinal class Reflection\n{\n    /**\n     * Calls the given method with args on the given object.\n     *\n     * @param  array<int, mixed>  $args\n     */\n    public static function call(object $object, string $method, array $args = []): mixed\n    {\n        $reflectionClass = new ReflectionClass($object);\n\n        try {\n            $reflectionMethod = $reflectionClass->getMethod($method);\n\n            return $reflectionMethod->invoke($object, ...$args);\n        } catch (ReflectionException $exception) {\n            if (method_exists($object, '__call')) {\n                return $object->__call($method, $args);\n            }\n\n            if (is_callable($method)) {\n                return self::bindCallable($method, $args);\n            }\n\n            throw $exception;\n        }\n    }\n\n    /**\n     * Bind a callable to the TestCase and return the result.\n     *\n     * @param  array<int, mixed>  $args\n     */\n    public static function bindCallable(callable $callable, array $args = []): mixed\n    {\n        return Closure::fromCallable($callable)->bindTo(TestSuite::getInstance()->test)(...$args);\n    }\n\n    /**\n     * Bind a callable to the TestCase and return the result,\n     * passing in the current dataset values as arguments.\n     */\n    public static function bindCallableWithData(callable $callable): mixed\n    {\n        $test = TestSuite::getInstance()->test;\n\n        if (! $test instanceof TestCase) {\n            return self::bindCallable($callable);\n        }\n\n        foreach ($test->providedData() as $value) {\n            if ($value instanceof Closure) {\n                throw new InvalidArgumentException('Bound datasets are not supported while doing high order testing.');\n            }\n        }\n\n        return Closure::fromCallable($callable)->bindTo($test)(...$test->providedData());\n    }\n\n    /**\n     * Infers the file name from the given closure.\n     */\n    public static function getFileNameFromClosure(Closure $closure): string\n    {\n        $reflectionClosure = new ReflectionFunction($closure);\n\n        return (string) $reflectionClosure->getFileName();\n    }\n\n    /**\n     * Gets the property value from of the given object.\n     */\n    public static function getPropertyValue(object $object, string $property): mixed\n    {\n        $reflectionClass = new ReflectionClass($object);\n\n        $reflectionProperty = null;\n\n        while (! $reflectionProperty instanceof ReflectionProperty) {\n            try {\n                /* @var ReflectionProperty $reflectionProperty */\n                $reflectionProperty = $reflectionClass->getProperty($property);\n            } catch (ReflectionException $reflectionException) {\n                $reflectionClass = $reflectionClass->getParentClass();\n\n                if (! $reflectionClass instanceof ReflectionClass) {\n                    throw new ShouldNotHappen($reflectionException);\n                }\n            }\n        }\n\n        return $reflectionProperty->getValue($object);\n    }\n\n    /**\n     * Sets the property value of the given object.\n     *\n     * @template TValue of object\n     *\n     * @param  TValue  $object\n     */\n    public static function setPropertyValue(object $object, string $property, mixed $value): void\n    {\n        /** @var ReflectionClass<TValue> $reflectionClass */\n        $reflectionClass = new ReflectionClass($object);\n\n        $reflectionProperty = null;\n\n        while (! $reflectionProperty instanceof ReflectionProperty) {\n            try {\n                /* @var ReflectionProperty $reflectionProperty */\n                $reflectionProperty = $reflectionClass->getProperty($property);\n            } catch (ReflectionException $reflectionException) {\n                $reflectionClass = $reflectionClass->getParentClass();\n\n                if (! $reflectionClass instanceof ReflectionClass) {\n                    throw new ShouldNotHappen($reflectionException);\n                }\n            }\n        }\n        $reflectionProperty->setValue($object, $value);\n    }\n\n    /**\n     * Get the class name of the given parameter's type, if possible.\n     *\n     * @see https://github.com/laravel/framework/blob/v6.18.25/src/Illuminate/Support/Reflector.php\n     */\n    public static function getParameterClassName(ReflectionParameter $parameter): ?string\n    {\n        $type = $parameter->getType();\n        if (! $type instanceof ReflectionNamedType) {\n            return null;\n        }\n        if ($type->isBuiltin()) {\n            return null;\n        }\n\n        $name = $type->getName();\n\n        if (($class = $parameter->getDeclaringClass()) instanceof ReflectionClass) {\n            if ($name === 'self') {\n                return $class->getName();\n            }\n\n            if ($name === 'parent' && ($parent = $class->getParentClass()) instanceof ReflectionClass) {\n                return $parent->getName();\n            }\n        }\n\n        return $name;\n    }\n\n    /**\n     * Receive a map of function argument names to their types.\n     *\n     * @return array<string, string>\n     */\n    public static function getFunctionArguments(Closure $function): array\n    {\n        $parameters = (new ReflectionFunction($function))->getParameters();\n        $arguments = [];\n\n        foreach ($parameters as $parameter) {\n            /** @var ReflectionNamedType|ReflectionUnionType|null $types */\n            $types = ($parameter->hasType()) ? $parameter->getType() : null;\n\n            if (is_null($types)) {\n                $arguments[$parameter->getName()] = 'mixed';\n\n                continue;\n            }\n\n            $arguments[$parameter->getName()] = implode('|', array_map(\n                static fn (ReflectionNamedType $type): string => $type->getName(), // @phpstan-ignore-line\n                ($types instanceof ReflectionNamedType)\n                    ? [$types] // NOTE: normalize as list of to handle unions\n                    : $types->getTypes(),\n            ));\n        }\n\n        return $arguments;\n    }\n\n    public static function getFunctionVariable(Closure $function, string $key): mixed\n    {\n        return (new ReflectionFunction($function))->getStaticVariables()[$key] ?? null;\n    }\n\n    /**\n     * Get the properties from the given reflection class.\n     *\n     * Used by `expect()->toHavePropertiesDocumented()`.\n     *\n     * @param  ReflectionClass<object>  $reflectionClass\n     * @return array<int, ReflectionProperty>\n     */\n    public static function getPropertiesFromReflectionClass(ReflectionClass $reflectionClass): array\n    {\n        $getProperties = fn (ReflectionClass $reflectionClass): array => array_filter(\n            array_map(\n                fn (ReflectionProperty $property): ReflectionProperty => $property,\n                $reflectionClass->getProperties(),\n            ), fn (ReflectionProperty $property): bool => $property->getDeclaringClass()->getName() === $reflectionClass->getName(),\n        );\n\n        $propertiesFromTraits = [];\n        foreach ($reflectionClass->getTraits() as $trait) {\n            $propertiesFromTraits = array_merge($propertiesFromTraits, $getProperties($trait));\n        }\n\n        $propertiesFromTraits = array_map(\n            fn (ReflectionProperty $property): string => $property->getName(),\n            $propertiesFromTraits,\n        );\n\n        return array_values(\n            array_filter(\n                $getProperties($reflectionClass),\n                fn (ReflectionProperty $property): bool => ! in_array($property->getName(), $propertiesFromTraits, true),\n            ),\n        );\n    }\n\n    /**\n     * Get the methods from the given reflection class.\n     *\n     * Used by `expect()->toHaveMethodsDocumented()`.\n     *\n     * @param  ReflectionClass<object>  $reflectionClass\n     * @return array<int, ReflectionMethod>\n     */\n    public static function getMethodsFromReflectionClass(ReflectionClass $reflectionClass, int $filter = ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED | ReflectionMethod::IS_PRIVATE): array\n    {\n        $getMethods = fn (ReflectionClass $reflectionClass): array => array_filter(\n            array_map(\n                fn (ReflectionMethod $method): ReflectionMethod => $method,\n                $reflectionClass->getMethods($filter),\n            ), fn (ReflectionMethod $method): bool => $method->getDeclaringClass()->getName() === $reflectionClass->getName(),\n        );\n\n        $methodsFromTraits = [];\n        foreach ($reflectionClass->getTraits() as $trait) {\n            $methodsFromTraits = array_merge($methodsFromTraits, $getMethods($trait));\n        }\n\n        $methodsFromTraits = array_map(\n            fn (ReflectionMethod $method): string => $method->getName(),\n            $methodsFromTraits,\n        );\n\n        return array_values(\n            array_filter(\n                $getMethods($reflectionClass),\n                fn (ReflectionMethod $method): bool => ! in_array($method->getName(), $methodsFromTraits, true),\n            ),\n        );\n    }\n}\n"
  },
  {
    "path": "src/Support/Shell.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Illuminate\\Support\\Env;\nuse Laravel\\Tinker\\ClassAliasAutoloader;\nuse Pest\\TestSuite;\nuse Psy\\Configuration;\nuse Psy\\Shell as PsyShell;\nuse Psy\\VersionUpdater\\Checker;\n\n/**\n * @internal\n */\nfinal class Shell\n{\n    /**\n     * Creates a new interactive shell.\n     */\n    public static function open(): void\n    {\n        $config = new Configuration;\n\n        $config->setUpdateCheck(Checker::NEVER);\n\n        $config->getPresenter()->addCasters(self::casters());\n\n        $shell = new PsyShell($config);\n\n        $loader = self::tinkered($shell);\n\n        try {\n            $shell->run();\n        } finally {\n            $loader?->unregister(); // @phpstan-ignore-line\n        }\n    }\n\n    /**\n     * Returns the casters for the Psy Shell.\n     *\n     * @return array<string, callable>\n     */\n    private static function casters(): array\n    {\n        $casters = [\n            'Illuminate\\Support\\Collection' => 'Laravel\\Tinker\\TinkerCaster::castCollection',\n            'Illuminate\\Support\\HtmlString' => 'Laravel\\Tinker\\TinkerCaster::castHtmlString',\n            'Illuminate\\Support\\Stringable' => 'Laravel\\Tinker\\TinkerCaster::castStringable',\n        ];\n\n        if (class_exists('Illuminate\\Database\\Eloquent\\Model')) {\n            $casters['Illuminate\\Database\\Eloquent\\Model'] = 'Laravel\\Tinker\\TinkerCaster::castModel';\n        }\n\n        if (class_exists('Illuminate\\Process\\ProcessResult')) {\n            $casters['Illuminate\\Process\\ProcessResult'] = 'Laravel\\Tinker\\TinkerCaster::castProcessResult';\n        }\n\n        if (class_exists('Illuminate\\Foundation\\Application')) {\n            $casters['Illuminate\\Foundation\\Application'] = 'Laravel\\Tinker\\TinkerCaster::castApplication';\n        }\n\n        if (function_exists('app') === false) {\n            return $casters; // @phpstan-ignore-line\n        }\n\n        $config = app()->make('config');\n\n        return array_merge($casters, (array) $config->get('tinker.casters', []));\n    }\n\n    /**\n     * Tinkers the current shell, if the Tinker package is available.\n     */\n    private static function tinkered(PsyShell $shell): ?object\n    {\n        if (function_exists('app') === false\n            || ! class_exists(Env::class)\n            || ! class_exists(ClassAliasAutoloader::class)\n        ) {\n            return null;\n        }\n\n        $path = Env::get('COMPOSER_VENDOR_DIR', app()->basePath().DIRECTORY_SEPARATOR.'vendor');\n\n        $path .= '/composer/autoload_classmap.php';\n\n        if (! file_exists($path)) {\n            $path = TestSuite::getInstance()->rootPath.DIRECTORY_SEPARATOR.'vendor'.DIRECTORY_SEPARATOR.'composer'.DIRECTORY_SEPARATOR.'autoload_classmap.php';\n        }\n\n        $config = app()->make('config');\n\n        return ClassAliasAutoloader::register(\n            $shell, $path, $config->get('tinker.alias', []), $config->get('tinker.dont_alias', [])\n        );\n    }\n}\n"
  },
  {
    "path": "src/Support/StateGenerator.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\State;\nuse NunoMaduro\\Collision\\Adapters\\Phpunit\\TestResult;\nuse NunoMaduro\\Collision\\Exceptions\\TestOutcome;\nuse PHPUnit\\Event\\Code\\TestDoxBuilder;\nuse PHPUnit\\Event\\Code\\TestMethod;\nuse PHPUnit\\Event\\Code\\ThrowableBuilder;\nuse PHPUnit\\Event\\Test\\Errored;\nuse PHPUnit\\Event\\TestData\\TestDataCollection;\nuse PHPUnit\\Framework\\SkippedWithMessageException;\nuse PHPUnit\\Metadata\\MetadataCollection;\nuse PHPUnit\\TestRunner\\TestResult\\TestResult as PHPUnitTestResult;\n\nfinal class StateGenerator\n{\n    public function fromPhpUnitTestResult(int $passedTests, PHPUnitTestResult $testResult): State\n    {\n        $state = new State;\n\n        foreach ($testResult->testErroredEvents() as $testResultEvent) {\n            if ($testResultEvent instanceof Errored) {\n                $state->add(TestResult::fromPestParallelTestCase(\n                    $testResultEvent->test(),\n                    TestResult::FAIL,\n                    $testResultEvent->throwable()\n                ));\n            } else {\n                // @phpstan-ignore-next-line\n                $state->add(TestResult::fromBeforeFirstTestMethodErrored($testResultEvent));\n            }\n        }\n\n        foreach ($testResult->testFailedEvents() as $testResultEvent) {\n            $state->add(TestResult::fromPestParallelTestCase(\n                $testResultEvent->test(),\n                TestResult::FAIL,\n                $testResultEvent->throwable()\n            ));\n        }\n\n        foreach ($testResult->testMarkedIncompleteEvents() as $testResultEvent) {\n            $state->add(TestResult::fromPestParallelTestCase(\n                $testResultEvent->test(),\n                TestResult::INCOMPLETE,\n                $testResultEvent->throwable()\n            ));\n        }\n\n        foreach ($testResult->testConsideredRiskyEvents() as $riskyEvents) {\n            foreach ($riskyEvents as $riskyEvent) {\n                $state->add(TestResult::fromPestParallelTestCase(\n                    $riskyEvent->test(),\n                    TestResult::RISKY,\n                    ThrowableBuilder::from(new TestOutcome($riskyEvent->message()))\n                ));\n            }\n        }\n\n        foreach ($testResult->testSkippedEvents() as $testResultEvent) {\n            if ($testResultEvent->message() === '__TODO__') {\n                $state->add(TestResult::fromPestParallelTestCase($testResultEvent->test(), TestResult::TODO));\n\n                continue;\n            }\n\n            $state->add(TestResult::fromPestParallelTestCase(\n                $testResultEvent->test(),\n                TestResult::SKIPPED,\n                ThrowableBuilder::from(new SkippedWithMessageException($testResultEvent->message()))\n            ));\n        }\n\n        foreach ($testResult->deprecations() as $testResultEvent) {\n            foreach ($testResultEvent->triggeringTests() as $triggeringTest) {\n                ['test' => $test] = $triggeringTest;\n\n                $state->add(TestResult::fromPestParallelTestCase(\n                    $test,\n                    TestResult::DEPRECATED,\n                    ThrowableBuilder::from(new TestOutcome($testResultEvent->description()))\n                ));\n            }\n        }\n\n        foreach ($testResult->phpDeprecations() as $testResultEvent) {\n            foreach ($testResultEvent->triggeringTests() as $triggeringTest) {\n                ['test' => $test] = $triggeringTest;\n\n                $state->add(TestResult::fromPestParallelTestCase(\n                    $test,\n                    TestResult::DEPRECATED,\n                    ThrowableBuilder::from(new TestOutcome($testResultEvent->description()))\n                ));\n            }\n        }\n\n        foreach ($testResult->notices() as $testResultEvent) {\n            foreach ($testResultEvent->triggeringTests() as $triggeringTest) {\n                ['test' => $test] = $triggeringTest;\n\n                $state->add(TestResult::fromPestParallelTestCase(\n                    $test,\n                    TestResult::NOTICE,\n                    ThrowableBuilder::from(new TestOutcome($testResultEvent->description()))\n                ));\n            }\n        }\n\n        foreach ($testResult->phpNotices() as $testResultEvent) {\n            foreach ($testResultEvent->triggeringTests() as $triggeringTest) {\n                ['test' => $test] = $triggeringTest;\n\n                $state->add(TestResult::fromPestParallelTestCase(\n                    $test,\n                    TestResult::NOTICE,\n                    ThrowableBuilder::from(new TestOutcome($testResultEvent->description()))\n                ));\n            }\n        }\n\n        foreach ($testResult->warnings() as $testResultEvent) {\n            foreach ($testResultEvent->triggeringTests() as $triggeringTest) {\n                ['test' => $test] = $triggeringTest;\n\n                $state->add(TestResult::fromPestParallelTestCase(\n                    $test,\n                    TestResult::WARN,\n                    ThrowableBuilder::from(new TestOutcome($testResultEvent->description()))\n                ));\n            }\n        }\n\n        foreach ($testResult->phpWarnings() as $testResultEvent) {\n            foreach ($testResultEvent->triggeringTests() as $triggeringTest) {\n                ['test' => $test] = $triggeringTest;\n\n                $state->add(TestResult::fromPestParallelTestCase(\n                    $test,\n                    TestResult::WARN,\n                    ThrowableBuilder::from(new TestOutcome($testResultEvent->description()))\n                ));\n            }\n        }\n\n        // for each test that passed, we need to add it to the state\n        for ($i = 0; $i < $passedTests; $i++) {\n            $state->add(TestResult::fromPestParallelTestCase(\n                new TestMethod(\n                    \"$i\", // @phpstan-ignore-line\n                    '', // @phpstan-ignore-line\n                    '', // @phpstan-ignore-line\n                    1,\n                    TestDoxBuilder::fromClassNameAndMethodName('', ''), // @phpstan-ignore-line\n                    MetadataCollection::fromArray([]),\n                    TestDataCollection::fromArray([])\n                ),\n                TestResult::PASS\n            ));\n        }\n\n        return $state;\n    }\n}\n"
  },
  {
    "path": "src/Support/Str.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\n/**\n * @internal\n */\nfinal class Str\n{\n    /**\n     * Pool of alpha-numeric characters for generating (unsafe) random strings\n     * from.\n     */\n    private const string POOL = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\n    private const string PREFIX = '__pest_evaluable_';\n\n    /**\n     * Create a (unsecure & non-cryptographically safe) random alpha-numeric\n     * string value.\n     *\n     * @param  int  $length  the length of the resulting randomized string\n     *\n     * @see https://github.com/laravel/framework/blob/4.2/src/Illuminate/Support/Str.php#L240-L242\n     */\n    public static function random(int $length = 16): string\n    {\n        return substr(str_shuffle(str_repeat(self::POOL, 5)), 0, $length);\n    }\n\n    /**\n     * Checks if the given `$target` starts with the given `$search`.\n     */\n    public static function startsWith(string $target, string $search): bool\n    {\n        return str_starts_with($target, $search);\n    }\n\n    /**\n     * Checks if the given `$target` ends with the given `$search`.\n     */\n    public static function endsWith(string $target, string $search): bool\n    {\n        $length = strlen($search);\n        if ($length === 0) {\n            return true;\n        }\n\n        return $search === substr($target, -$length);\n    }\n\n    /**\n     * Makes the given string evaluable by an `eval`.\n     */\n    public static function evaluable(string $code): string\n    {\n        $code = str_replace('_', '__', $code);\n\n        $code = self::PREFIX.str_replace(' ', '_', $code);\n\n        // sticks to PHP8.2 function naming rules https://www.php.net/manual/en/functions.user-defined.php\n        return (string) preg_replace('/[^a-zA-Z0-9_\\x80-\\xff]/', '_', $code);\n    }\n\n    /**\n     * Get the portion of a string before the last occurrence of a given value.\n     */\n    public static function beforeLast(string $subject, string $search): string\n    {\n        if ($search === '') {\n            return $subject;\n        }\n\n        $pos = mb_strrpos($subject, $search);\n\n        if ($pos === false) {\n            return $subject;\n        }\n\n        return mb_substr($subject, 0, $pos);\n    }\n\n    /**\n     * Returns the content after the given \"search\".\n     */\n    public static function after(string $subject, string $search): string\n    {\n        return $search === '' ? $subject : array_reverse(explode($search, $subject, 2))[0];\n    }\n\n    /**\n     * Determine if a given value is a valid UUID.\n     */\n    public static function isUuid(string $value): bool\n    {\n        return preg_match('/^[\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12}$/iD', $value) > 0;\n    }\n\n    /**\n     * Creates a describe block as `$describeDescription` → `$testDescription` format.\n     *\n     * @param  array<int, Description>  $describeDescriptions\n     */\n    public static function describe(array $describeDescriptions, string $testDescription): string\n    {\n        $descriptionComponents = [...$describeDescriptions, $testDescription];\n\n        return sprintf(str_repeat('`%s` → ', count($describeDescriptions)).'%s', ...$descriptionComponents);\n    }\n\n    /**\n     * Determine if a given value is a valid URL.\n     */\n    public static function isUrl(string $value): bool\n    {\n        return (bool) filter_var($value, FILTER_VALIDATE_URL);\n    }\n\n    /**\n     * Converts the given `$target` to a URL-friendly \"slug\".\n     */\n    public static function slugify(string $target): string\n    {\n        $target = preg_replace('/[^a-zA-Z0-9]+/', '-', $target);\n\n        return strtolower(trim((string) $target, '-'));\n    }\n}\n"
  },
  {
    "path": "src/Support/View.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\Support;\n\nuse Symfony\\Component\\Console\\Output\\OutputInterface;\nuse Termwind\\Termwind;\n\nuse function Termwind\\render;\nuse function Termwind\\renderUsing;\n\n/**\n * @internal\n */\nfinal class View\n{\n    /**\n     * The implementation of the output.\n     */\n    private static OutputInterface $output;\n\n    /**\n     * Renders views using the given Output instance.\n     */\n    public static function renderUsing(OutputInterface $output): void\n    {\n        self::$output = $output;\n    }\n\n    /**\n     * Renders the given view.\n     *\n     * @param  array<string, mixed>  $data\n     */\n    public static function render(string $path, array $data = []): void\n    {\n        $contents = self::compile($path, $data);\n\n        $existing = Termwind::getRenderer();\n\n        renderUsing(self::$output);\n\n        try {\n            render($contents);\n        } finally {\n            renderUsing($existing);\n        }\n    }\n\n    /**\n     * Compiles the given view.\n     *\n     * @param  array<string, mixed>  $data\n     */\n    private static function compile(string $path, array $data): string\n    {\n        extract($data);\n\n        ob_start();\n\n        $path = str_replace('.', '/', $path);\n\n        include sprintf('%s/../../resources/views/%s.php', __DIR__, $path);\n\n        $contents = ob_get_contents();\n\n        ob_clean();\n\n        return (string) $contents;\n    }\n}\n"
  },
  {
    "path": "src/TestCaseFilters/GitDirtyTestCaseFilter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\TestCaseFilters;\n\nuse Pest\\Contracts\\TestCaseFilter;\nuse Pest\\Exceptions\\MissingDependency;\nuse Pest\\Exceptions\\NoDirtyTestsFound;\nuse Pest\\Panic;\nuse Pest\\TestSuite;\nuse Symfony\\Component\\Process\\Process;\n\nfinal class GitDirtyTestCaseFilter implements TestCaseFilter\n{\n    /**\n     * @var array<int, string>|null\n     */\n    private ?array $changedFiles = null;\n\n    /**\n     * Creates a new instance of the filter.\n     */\n    public function __construct(private readonly string $projectRoot)\n    {\n        // ...\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function accept(string $testCaseFilename): bool\n    {\n        if ($this->changedFiles === null) {\n            $this->loadChangedFiles();\n        }\n\n        assert(is_array($this->changedFiles));\n\n        $relativePath = str_replace($this->projectRoot, '', $testCaseFilename);\n        $relativePath = str_replace(DIRECTORY_SEPARATOR, '/', $relativePath);\n\n        if (str_starts_with($relativePath, '/')) {\n            $relativePath = substr($relativePath, 1);\n        }\n\n        return in_array($relativePath, $this->changedFiles, true);\n    }\n\n    /**\n     * Loads the changed files.\n     */\n    private function loadChangedFiles(): void\n    {\n        $process = new Process(['git', 'status', '--short', '--', '*.php']);\n        $process->run();\n\n        if (! $process->isSuccessful()) {\n            throw new MissingDependency('Filter by dirty files', 'git');\n        }\n\n        $output = preg_split('/\\R+/', $process->getOutput(), flags: PREG_SPLIT_NO_EMPTY);\n        assert(is_array($output));\n\n        $dirtyFiles = [];\n\n        foreach ($output as $dirtyFile) {\n            $dirtyFiles[substr($dirtyFile, 3)] = trim(substr($dirtyFile, 0, 3));\n        }\n\n        $dirtyFiles = array_filter($dirtyFiles, fn (string $status): bool => $status !== 'D');\n\n        $dirtyFiles = array_map(\n            fn (string $file, string $status): string => in_array($status, ['R', 'RM'], true)\n                ? explode(' -> ', $file)[1]\n                : $file, array_keys($dirtyFiles), $dirtyFiles,\n        );\n\n        $dirtyFiles = array_filter(\n            $dirtyFiles,\n            fn (string $file): bool => str_starts_with('.'.DIRECTORY_SEPARATOR.$file, TestSuite::getInstance()->testPath)\n                || str_starts_with($file, TestSuite::getInstance()->testPath)\n        );\n\n        $dirtyFiles = array_values($dirtyFiles);\n\n        if ($dirtyFiles === []) {\n            Panic::with(new NoDirtyTestsFound);\n        }\n\n        $this->changedFiles = $dirtyFiles;\n    }\n}\n"
  },
  {
    "path": "src/TestCaseMethodFilters/AssigneeTestCaseFilter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\TestCaseMethodFilters;\n\nuse Pest\\Contracts\\TestCaseMethodFilter;\nuse Pest\\Factories\\TestCaseMethodFactory;\n\nfinal readonly class AssigneeTestCaseFilter implements TestCaseMethodFilter\n{\n    /**\n     * Create a new filter instance.\n     */\n    public function __construct(private string $assignee)\n    {\n        //\n    }\n\n    /**\n     * Filter the test case methods.\n     */\n    public function accept(TestCaseMethodFactory $factory): bool\n    {\n        return array_filter($factory->assignees, fn (string $assignee): bool => str_starts_with($assignee, $this->assignee)) !== [];\n    }\n}\n"
  },
  {
    "path": "src/TestCaseMethodFilters/IssueTestCaseFilter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\TestCaseMethodFilters;\n\nuse Pest\\Contracts\\TestCaseMethodFilter;\nuse Pest\\Factories\\TestCaseMethodFactory;\n\nfinal readonly class IssueTestCaseFilter implements TestCaseMethodFilter\n{\n    /**\n     * Create a new filter instance.\n     */\n    public function __construct(private int $number)\n    {\n        //\n    }\n\n    /**\n     * Filter the test case methods.\n     */\n    public function accept(TestCaseMethodFactory $factory): bool\n    {\n        return in_array($this->number, $factory->issues, true);\n    }\n}\n"
  },
  {
    "path": "src/TestCaseMethodFilters/NotesTestCaseFilter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\TestCaseMethodFilters;\n\nuse Pest\\Contracts\\TestCaseMethodFilter;\nuse Pest\\Factories\\TestCaseMethodFactory;\n\nfinal readonly class NotesTestCaseFilter implements TestCaseMethodFilter\n{\n    /**\n     * Filter the test case methods.\n     */\n    public function accept(TestCaseMethodFactory $factory): bool\n    {\n        return $factory->notes !== [];\n    }\n}\n"
  },
  {
    "path": "src/TestCaseMethodFilters/PrTestCaseFilter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\TestCaseMethodFilters;\n\nuse Pest\\Contracts\\TestCaseMethodFilter;\nuse Pest\\Factories\\TestCaseMethodFactory;\n\nfinal readonly class PrTestCaseFilter implements TestCaseMethodFilter\n{\n    /**\n     * Create a new filter instance.\n     */\n    public function __construct(private int $number)\n    {\n        //\n    }\n\n    /**\n     * Filter the test case methods.\n     */\n    public function accept(TestCaseMethodFactory $factory): bool\n    {\n        return in_array($this->number, $factory->prs, true);\n    }\n}\n"
  },
  {
    "path": "src/TestCaseMethodFilters/TodoTestCaseFilter.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\TestCaseMethodFilters;\n\nuse Pest\\Contracts\\TestCaseMethodFilter;\nuse Pest\\Factories\\TestCaseMethodFactory;\n\nfinal readonly class TodoTestCaseFilter implements TestCaseMethodFilter\n{\n    /**\n     * Filter the test case methods.\n     */\n    public function accept(TestCaseMethodFactory $factory): bool\n    {\n        return $factory->todo;\n    }\n}\n"
  },
  {
    "path": "src/TestCases/IgnorableTestCase.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest\\TestCases;\n\nuse PHPUnit\\Framework\\TestCase;\n\n/**\n * @internal\n */\nfinal class IgnorableTestCase extends TestCase\n{\n    // ...\n}\n"
  },
  {
    "path": "src/TestSuite.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Pest;\n\nuse Pest\\Exceptions\\InvalidPestCommand;\nuse Pest\\Repositories\\AfterAllRepository;\nuse Pest\\Repositories\\AfterEachRepository;\nuse Pest\\Repositories\\BeforeAllRepository;\nuse Pest\\Repositories\\BeforeEachRepository;\nuse Pest\\Repositories\\SnapshotRepository;\nuse Pest\\Repositories\\TestRepository;\nuse Pest\\Support\\Str;\nuse PHPUnit\\Framework\\TestCase;\n\n/**\n * @internal\n */\nfinal class TestSuite\n{\n    /**\n     * Holds the current test case.\n     */\n    public ?TestCase $test = null;\n\n    /**\n     * Holds the tests repository.\n     */\n    public TestRepository $tests;\n\n    /**\n     * Holds the before each repository.\n     */\n    public BeforeEachRepository $beforeEach;\n\n    /**\n     * Holds the before all repository.\n     */\n    public BeforeAllRepository $beforeAll;\n\n    /**\n     * Holds the after each repository.\n     */\n    public AfterEachRepository $afterEach;\n\n    /**\n     * Holds the after all repository.\n     */\n    public AfterAllRepository $afterAll;\n\n    /**\n     * Holds the snapshots repository.\n     */\n    public SnapshotRepository $snapshots;\n\n    /**\n     * Holds the root path.\n     */\n    public string $rootPath;\n\n    /**\n     * Holds an instance of the test suite.\n     */\n    private static ?TestSuite $instance = null;\n\n    /**\n     * Creates a new instance of the test suite.\n     */\n    public function __construct(\n        string $rootPath,\n        public string $testPath,\n    ) {\n        $this->beforeAll = new BeforeAllRepository;\n        $this->beforeEach = new BeforeEachRepository;\n        $this->tests = new TestRepository;\n        $this->afterEach = new AfterEachRepository;\n        $this->afterAll = new AfterAllRepository;\n        $this->rootPath = (string) realpath($rootPath);\n        $this->snapshots = new SnapshotRepository(\n            $this->rootPath,\n            implode(DIRECTORY_SEPARATOR, [$this->rootPath, $this->testPath]),\n            implode(DIRECTORY_SEPARATOR, ['.pest', 'snapshots']),\n        );\n    }\n\n    /**\n     * Returns the current instance of the test suite.\n     */\n    public static function getInstance(\n        ?string $rootPath = null,\n        ?string $testPath = null,\n    ): TestSuite {\n        if (is_string($rootPath) && is_string($testPath)) {\n            self::$instance = new TestSuite($rootPath, $testPath);\n\n            foreach (Plugin::$callables as $callable) {\n                $callable();\n            }\n\n            return self::$instance;\n        }\n\n        if (! self::$instance instanceof self) {\n            throw new InvalidPestCommand;\n        }\n\n        return self::$instance;\n    }\n\n    public function getFilename(): string\n    {\n        assert($this->test instanceof TestCase);\n\n        return (fn () => self::$__filename)->call($this->test, $this->test::class); // @phpstan-ignore-line\n    }\n\n    public function getDescription(): string\n    {\n        assert($this->test instanceof TestCase);\n\n        $description = str_replace('__pest_evaluable_', '', $this->test->name());\n        $datasetAsString = str_replace('__pest_evaluable_', '', Str::evaluable($this->test->dataSetAsString()));\n\n        return str_replace(' ', '_', $description.$datasetAsString);\n    }\n\n    public function registerSnapshotChange(string $message): void\n    {\n        assert($this->test instanceof TestCase);\n\n        (fn (): string => $this->__snapshotChanges[] = $message)->call($this->test, $this->test::class); // @phpstan-ignore-line\n    }\n}\n"
  },
  {
    "path": "stubs/Browser.php",
    "content": "<?php\n\nuse Laravel\\Dusk\\Browser;\n\nit('has {name} page', function () {\n    $this->browse(function (Browser $browser) {\n        $browser->visit('/{name}')\n            ->assertSee('{name}');\n    });\n});\n"
  },
  {
    "path": "stubs/Dataset.php",
    "content": "<?php\n\ndataset('{dataset_name}', function () {\n    return ['{dataset_element} A', '{dataset_element} B'];\n});\n"
  },
  {
    "path": "stubs/Feature.php",
    "content": "<?php\n\nit('has {name} page', function () {\n    $response = $this->get('/{name}');\n\n    $response->assertStatus(200);\n});\n"
  },
  {
    "path": "stubs/Unit.php",
    "content": "<?php\n\ntest('{name}', function () {\n    expect(true)->toBeTrue();\n});\n"
  },
  {
    "path": "stubs/init/Feature/ExampleTest.php.stub",
    "content": "<?php\n\ntest('example', function () {\n    expect(true)->toBeTrue();\n});\n"
  },
  {
    "path": "stubs/init/Pest.php.stub",
    "content": "<?php\n\nuse Tests\\TestCase;\n\n/*\n|--------------------------------------------------------------------------\n| Test Case\n|--------------------------------------------------------------------------\n|\n| The closure you provide to your test functions is always bound to a specific PHPUnit test\n| case class. By default, that class is \"PHPUnit\\Framework\\TestCase\". Of course, you may\n| need to change it using the \"pest()\" function to bind a different classes or traits.\n|\n*/\n\npest()->extend(TestCase::class)->in('Feature');\n\n/*\n|--------------------------------------------------------------------------\n| Expectations\n|--------------------------------------------------------------------------\n|\n| When you're writing tests, you often need to check that values meet certain conditions. The\n| \"expect()\" function gives you access to a set of \"expectations\" methods that you can use\n| to assert different things. Of course, you may extend the Expectation API at any time.\n|\n*/\n\nexpect()->extend('toBeOne', function () {\n    return $this->toBe(1);\n});\n\n/*\n|--------------------------------------------------------------------------\n| Functions\n|--------------------------------------------------------------------------\n|\n| While Pest is very powerful out-of-the-box, you may have some testing code specific to your\n| project that you don't want to repeat in every file. Here you can also expose helpers as\n| global functions to help you to reduce the number of lines of code in your test files.\n|\n*/\n\nfunction something()\n{\n    // ..\n}\n"
  },
  {
    "path": "stubs/init/TestCase.php.stub",
    "content": "<?php\n\nnamespace Tests;\n\nuse PHPUnit\\Framework\\TestCase as BaseTestCase;\n\nabstract class TestCase extends BaseTestCase\n{\n    //\n}\n"
  },
  {
    "path": "stubs/init/Unit/ExampleTest.php.stub",
    "content": "<?php\n\ntest('example', function () {\n    expect(true)->toBeTrue();\n});\n"
  },
  {
    "path": "stubs/init/phpunit.xml.stub",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"vendor/phpunit/phpunit/phpunit.xsd\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n>\n    <testsuites>\n        <testsuite name=\"Test Suite\">\n            <directory suffix=\"Test.php\">./tests</directory>\n        </testsuite>\n    </testsuites>\n    <source>\n        <include>\n            <directory>app</directory>\n            <directory>src</directory>\n        </include>\n    </source>\n</phpunit>\n"
  },
  {
    "path": "stubs/init-laravel/Feature/ExampleTest.php.stub",
    "content": "<?php\n\nit('returns a successful response', function () {\n    $response = $this->get('/');\n\n    $response->assertStatus(200);\n});\n"
  },
  {
    "path": "stubs/init-laravel/Pest.php.stub",
    "content": "<?php\n\nuse Tests\\TestCase;\n\n/*\n|--------------------------------------------------------------------------\n| Test Case\n|--------------------------------------------------------------------------\n|\n| The closure you provide to your test functions is always bound to a specific PHPUnit test\n| case class. By default, that class is \"PHPUnit\\Framework\\TestCase\". Of course, you may\n| need to change it using the \"pest()\" function to bind a different classes or traits.\n|\n*/\n\npest()->extend(TestCase::class)\n // ->use(Illuminate\\Foundation\\Testing\\RefreshDatabase::class)\n    ->in('Feature');\n\n/*\n|--------------------------------------------------------------------------\n| Expectations\n|--------------------------------------------------------------------------\n|\n| When you're writing tests, you often need to check that values meet certain conditions. The\n| \"expect()\" function gives you access to a set of \"expectations\" methods that you can use\n| to assert different things. Of course, you may extend the Expectation API at any time.\n|\n*/\n\nexpect()->extend('toBeOne', function () {\n    return $this->toBe(1);\n});\n\n/*\n|--------------------------------------------------------------------------\n| Functions\n|--------------------------------------------------------------------------\n|\n| While Pest is very powerful out-of-the-box, you may have some testing code specific to your\n| project that you don't want to repeat in every file. Here you can also expose helpers as\n| global functions to help you to reduce the number of lines of code in your test files.\n|\n*/\n\nfunction something()\n{\n    // ..\n}\n"
  },
  {
    "path": "stubs/init-laravel/TestCase.php.stub",
    "content": "<?php\n\nnamespace Tests;\n\nuse Illuminate\\Foundation\\Testing\\TestCase as BaseTestCase;\n\nabstract class TestCase extends BaseTestCase\n{\n    //\n}\n"
  },
  {
    "path": "stubs/init-laravel/Unit/ExampleTest.php.stub",
    "content": "<?php\n\ntest('that true is true', function () {\n    expect(true)->toBeTrue();\n});\n"
  },
  {
    "path": "stubs/init-laravel/phpunit.xml.stub",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"vendor/phpunit/phpunit/phpunit.xsd\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n>\n    <testsuites>\n        <testsuite name=\"Unit\">\n            <directory>tests/Unit</directory>\n        </testsuite>\n        <testsuite name=\"Feature\">\n            <directory>tests/Feature</directory>\n        </testsuite>\n    </testsuites>\n    <source>\n        <include>\n            <directory>app</directory>\n        </include>\n    </source>\n    <php>\n        <env name=\"APP_ENV\" value=\"testing\"/>\n        <env name=\"APP_MAINTENANCE_DRIVER\" value=\"file\"/>\n        <env name=\"BCRYPT_ROUNDS\" value=\"4\"/>\n        <env name=\"CACHE_STORE\" value=\"array\"/>\n        <!-- <env name=\"DB_CONNECTION\" value=\"sqlite\"/> -->\n        <!-- <env name=\"DB_DATABASE\" value=\":memory:\"/> -->\n        <env name=\"MAIL_MAILER\" value=\"array\"/>\n        <env name=\"PULSE_ENABLED\" value=\"false\"/>\n        <env name=\"QUEUE_CONNECTION\" value=\"sync\"/>\n        <env name=\"SESSION_DRIVER\" value=\"array\"/>\n        <env name=\"TELESCOPE_ENABLED\" value=\"false\"/>\n    </php>\n</phpunit>\n"
  },
  {
    "path": "tests/.cache/test-results",
    "content": "{\"version\":\"pest_2.32.2\",\"defects\":[],\"times\":{\"P\\\\Tests\\\\Playground::__pest_evaluable_basic\":0.005}}"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/_describable__→_multiple_snapshot_expectations_with_describe.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/_describable__→_multiple_snapshot_expectations_with_describe__2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/_within_describe__→_pass_with_dataset_with_data_set____my_datas_set_value___.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/failures.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/failures_with_custom_message.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations__2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_datasets_with_data_set___1__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_datasets_with_data_set___1____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_datasets_with_data_set____bar___.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_datasets_with_data_set____bar_____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_datasets_with_data_set____baz___.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_datasets_with_data_set____baz_____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_datasets_with_data_set____foo___.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_datasets_with_data_set____foo_____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___10__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___10____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___1__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___1____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___2__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___2____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___3__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___3____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___4__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___4____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___5__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___5____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___6__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___6____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___7__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___7____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___8__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___8____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___9__.snap",
    "content": "foo bar 1"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/multiple_snapshot_expectations_with_repeat_with_data_set___9____2.snap",
    "content": "foo bar 2"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/not_failures.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/pass.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/pass_using_pipes.snap",
    "content": "<input type=\"hidden\" name=\"_token\" value=\"1\" />"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/pass_with______toString_.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/pass_with__toArray_.snap",
    "content": "{\n    \"key\": \"    <div class=\\\"container\\\">\\n        <div class=\\\"row\\\">\\n            <div class=\\\"col-md-12\\\">\\n                <h1>Snapshot<\\/h1>\\n            <\\/div>\\n        <\\/div>\\n    <\\/div>\"\n}"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/pass_with__toSnapshot_.snap",
    "content": "{\n    \"key\": \"    <div class=\\\"container\\\">\\n        <div class=\\\"row\\\">\\n            <div class=\\\"col-md-12\\\">\\n                <h1>Snapshot<\\/h1>\\n            <\\/div>\\n        <\\/div>\\n    <\\/div>\"\n}"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/pass_with__toString_.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/pass_with_array.snap",
    "content": "{\n    \"key\": \"    <div class=\\\"container\\\">\\n        <div class=\\\"row\\\">\\n            <div class=\\\"col-md-12\\\">\\n                <h1>Snapshot<\\/h1>\\n            <\\/div>\\n        <\\/div>\\n    <\\/div>\"\n}"
  },
  {
    "path": "tests/.pest/snapshots/Features/Expect/toMatchSnapshot/pass_with_dataset_with_data_set____my_datas_set_value___.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots/Visual/Collision/collision_with_data_set_________.snap",
    "content": "\n   FAIL  Tests\\Fixtures\\CollisionTest\n  ⨯ error\n  ✓ success\n  ────────────────────────────────────────────────────────────────────────────  \n   FAILED  Tests\\Fixtures\\CollisionTest > error                     Exception   \n  error\n\n  at tests/Fixtures/CollisionTest.php:4\n      1▕ <?php\n      2▕ \n      3▕ test('error', function () {\n  ➜   4▕     throw new Exception('error');\n      5▕ })->skip(! isset($_SERVER['COLLISION_TEST']));\n      6▕ \n      7▕ test('success', function () {\n      8▕     expect(true)->toBeTrue();\n      9▕ })->skip(! isset($_SERVER['COLLISION_TEST']));\n\n  1   tests/Fixtures/CollisionTest.php:4\n\n\n  Tests:    1 failed, 1 passed (1 assertions)"
  },
  {
    "path": "tests/.pest/snapshots/Visual/Help/visual_snapshot_of_help_command_output.snap",
    "content": "\n  Pest Testing Framework 4.4.2.  \n\n  USAGE: pest <file> [options]  \n\n  CONFIGURATION OPTIONS:\n  --init ............................ Initialise a standard Pest configuration  \n  --bootstrap [file] ...... A PHP script that is included before the tests run  \n  -c|--configuration [file] ................. Read configuration from XML file  \n  --no-configuration ......... Ignore default configuration file (phpunit.xml)  \n  --extension [class] .. Register test runner extension with bootstrap [class]  \n  --no-extensions ..................... Do not register test runner extensions  \n  --include-path [path(s)] ..... Prepend PHP's include_path with given path(s)  \n  -d [key[=value]] ...................................... Sets a php.ini value  \n  --cache-directory [dir] ............................ Specify cache directory  \n  --generate-configuration  Generate configuration file with suggested settings  \n  --migrate-configuration ....... Migrate configuration file to current format  \n  --generate-baseline [file] .................... Generate baseline for issues  \n  --use-baseline [file] ........................ Use baseline to ignore issues  \n  --ignore-baseline ..................... Do not use baseline to ignore issues  \n\n  SELECTION OPTIONS:\n  --bail ........................... Stop execution upon first not-passed test  \n  --todos ........................ Output to standard output the list of todos  \n  --notes ......................... Output to standard output tests with notes  \n  --issue ........ Output to standard output tests with the given issue number  \n  --pr .... Output to standard output tests with the given pull request number  \n  --pull-request  Output to standard output tests with the given pull request number (alias for --pr)  \n  --retry  Run non-passing tests first and stop execution upon first error or failure  \n  --dirty ...... Only run tests that have uncommitted changes according to Git  \n  --all .................... Ignore test selection from XML configuration file  \n  --list-suites ................................... List available test suites  \n  --testsuite [name] ......... Only run tests from the specified test suite(s)  \n  --exclude-testsuite [name] .. Exclude tests from the specified test suite(s)  \n  --list-groups ................................... List available test groups  \n  --group [name] .................. Only run tests from the specified group(s)  \n  --exclude-group [name] ........... Exclude tests from the specified group(s)  \n  --covers [name] ................. Only run tests that intend to cover [name]  \n  --uses [name] ..................... Only run tests that intend to use [name]  \n  --requires-php-extension [name]  Only run tests that require PHP extension [name]  \n  --list-test-files ................................ List available test files  \n  --list-tests .......................................... List available tests  \n  --list-tests-xml [file] ................. List available tests in XML format  \n  --filter [pattern] ............................... Filter which tests to run  \n  --exclude-filter [pattern] .. Exclude tests for the specified filter pattern  \n  --test-suffix [suffixes]  Only search for test in files with specified suffix(es). Default: Test.php,.phpt  \n\n  EXECUTION OPTIONS:\n  --parallel ........................................... Run tests in parallel  \n  --update-snapshots  Update snapshots for tests using the \"toMatchSnapshot\" expectation  \n  --globals-backup ................. Backup and restore $GLOBALS for each test  \n  --static-backup ......... Backup and restore static properties for each test  \n  --strict-coverage ................... Be strict about code coverage metadata  \n  --strict-global-state .............. Be strict about changes to global state  \n  --disallow-test-output ................. Be strict about output during tests  \n  --enforce-time-limit ................. Enforce time limit based on test size  \n  --default-time-limit [sec]  Timeout in seconds for tests that have no declared size  \n  --do-not-report-useless-tests  Do not report tests that do not test anything  \n  --stop-on-defect ... Stop after first error, failure, warning, or risky test  \n  --stop-on-error ..................................... Stop after first error  \n  --stop-on-failure ................................. Stop after first failure  \n  --stop-on-warning ................................. Stop after first warning  \n  --stop-on-risky ................................ Stop after first risky test  \n  --stop-on-deprecation ... Stop after first test that triggered a deprecation  \n  --stop-on-notice ............. Stop after first test that triggered a notice  \n  --stop-on-skipped ............................ Stop after first skipped test  \n  --stop-on-incomplete ...................... Stop after first incomplete test  \n  --fail-on-empty-test-suite  Signal failure using shell exit code when no tests were run  \n  --fail-on-warning  Signal failure using shell exit code when a warning was triggered  \n  --fail-on-risky  Signal failure using shell exit code when a test was considered risky  \n  --fail-on-deprecation  Signal failure using shell exit code when a deprecation was triggered  \n  --fail-on-phpunit-deprecation  Signal failure using shell exit code when a PHPUnit deprecation was triggered  \n  --fail-on-phpunit-notice  Signal failure using shell exit code when a PHPUnit notice was triggered  \n  --fail-on-phpunit-warning  Signal failure using shell exit code when a PHPUnit warning was triggered  \n  --fail-on-notice  Signal failure using shell exit code when a notice was triggered  \n  --fail-on-skipped  Signal failure using shell exit code when a test was skipped  \n  --fail-on-incomplete  Signal failure using shell exit code when a test was marked incomplete  \n  --fail-on-all-issues  Signal failure using shell exit code when an issue is triggered  \n  --do-not-fail-on-empty-test-suite  Do not signal failure using shell exit code when no tests were run  \n  --do-not-fail-on-warning  Do not signal failure using shell exit code when a warning was triggered  \n  --do-not-fail-on-risky  Do not signal failure using shell exit code when a test was considered risky  \n  --do-not-fail-on-deprecation  Do not signal failure using shell exit code when a deprecation was triggered  \n  --do-not-fail-on-phpunit-deprecation  Do not signal failure using shell exit code when a PHPUnit deprecation was triggered  \n  --do-not-fail-on-phpunit-notice  Do not signal failure using shell exit code when a PHPUnit notice was triggered  \n  --do-not-fail-on-phpunit-warning  Do not signal failure using shell exit code when a PHPUnit warning was triggered  \n  --do-not-fail-on-notice  Do not signal failure using shell exit code when a notice was triggered  \n  --do-not-fail-on-skipped  Do not signal failure using shell exit code when a test was skipped  \n  --do-not-fail-on-incomplete  Do not signal failure using shell exit code when a test was marked incomplete  \n  --cache-result ............................ Write test results to cache file  \n  --do-not-cache-result .............. Do not write test results to cache file  \n  --order-by [order]  Run tests in order: default|defects|depends|duration|no-depends|random|reverse|size  \n  --random-order-seed [N]  Use the specified random seed when running tests in random order  \n\n  REPORTING OPTIONS:\n  --colors [flag] ......... Use colors in output (\"never\", \"auto\" or \"always\")  \n  --columns [n] ................. Number of columns to use for progress output  \n  --columns max ............ Use maximum number of columns for progress output  \n  --stderr ................................. Write to STDERR instead of STDOUT  \n  --no-progress .................... Disable output of test execution progress  \n  --no-results ................................ Disable output of test results  \n  --no-output ............................................. Disable all output  \n  --display-incomplete .................. Display details for incomplete tests  \n  --display-skipped ........................ Display details for skipped tests  \n  --display-deprecations . Display details for deprecations triggered by tests  \n  --display-phpunit-deprecations .... Display details for PHPUnit deprecations  \n  --display-phpunit-notices .............. Display details for PHPUnit notices  \n  --display-errors ............. Display details for errors triggered by tests  \n  --display-notices ........... Display details for notices triggered by tests  \n  --display-warnings ......... Display details for warnings triggered by tests  \n  --display-all-issues ..... Display details for all issues that are triggered  \n  --reverse-list .............................. Print defects in reverse order  \n  --teamcity . Replace default progress and result output with TeamCity format  \n  --testdox ................ Replace default result output with TestDox format  \n  --testdox-summary  Repeat TestDox output for tests with errors, failures, or issues  \n  --debug  Replace default progress and result output with debugging information  \n  --with-telemetry  Include telemetry information in debugging information output  \n  --compact ................ Replace default result output with Compact format  \n\n  LOGGING OPTIONS:\n  --log-junit [file] .......... Write test results in JUnit XML format to file  \n  --log-otr [file]  Write test results in Open Test Reporting XML format to file  \n  --include-git-information  Include Git information in Open Test Reporting XML logfile  \n  --log-teamcity [file] ........ Write test results in TeamCity format to file  \n  --testdox-html [file] .. Write test results in TestDox format (HTML) to file  \n  --testdox-text [file]  Write test results in TestDox format (plain text) to file  \n  --log-events-text [file] ............... Stream events as plain text to file  \n  --log-events-verbose-text [file]  Stream events as plain text with extended information to file  \n  --no-logging ....... Ignore logging configured in the XML configuration file  \n\n  CODE COVERAGE OPTIONS:\n  --coverage ..... Generate code coverage report and output to standard output  \n  --coverage --min  Set the minimum required coverage percentage, and fail if not met  \n  --coverage-clover [file]  Write code coverage report in Clover XML format to file  \n  --coverage-openclover [file]  Write code coverage report in OpenClover XML format to file  \n  --coverage-cobertura [file]  Write code coverage report in Cobertura XML format to file  \n  --coverage-crap4j [file]  Write code coverage report in Crap4J XML format to file  \n  --coverage-html [dir]  Write code coverage report in HTML format to directory  \n  --coverage-php [file] .......... Write serialized code coverage data to file  \n  --coverage-text=[file]  Write code coverage report in text format to file [default: standard output]  \n  --only-summary-for-coverage-text  Option for code coverage report in text format: only show summary  \n  --show-uncovered-for-coverage-text  Option for code coverage report in text format: show uncovered files  \n  --coverage-xml [dir] . Write code coverage report in XML format to directory  \n  --exclude-source-from-xml-coverage  Exclude [source] element from code coverage report in XML format  \n  --warm-coverage-cache ........................... Warm static analysis cache  \n  --coverage-filter [dir] ........... Include [dir] in code coverage reporting  \n  --path-coverage .......... Report path coverage in addition to line coverage  \n  --disable-coverage-ignore ...... Disable metadata for ignoring code coverage  \n  --no-coverage  Ignore code coverage reporting configured in the XML configuration file  \n\n  MUTATION TESTING OPTIONS:\n  --mutate .... Runs mutation testing, to understand the quality of your tests  \n  --mutate --parallel ...................... Runs mutation testing in parallel  \n  --mutate --min  Set the minimum required mutation score, and fail if not met  \n  --mutate --id  Run only the mutation with the given ID. But E.g. --id=ecb35ab30ffd3491. Note, you need to provide the same options as the original run  \n  --mutate --covered-only  Only generate mutations for classes that are covered by tests  \n  --mutate --bail  Stop mutation testing execution upon first untested or uncovered mutation  \n  --mutate --class  Generate mutations for the given class(es). E.g. --class=App\\\\Models  \n  --mutate --ignore  Ignore the given class(es) when generating mutations. E.g. --ignore=App\\\\Http\\\\Requests  \n  --mutate --clear-cache ............................ Clear the mutation cache  \n  --mutate --no-cache ............................... Clear the mutation cache  \n  --mutate --ignore-min-score-on-zero-mutations  Ignore the minimum score requirement when there are no mutations  \n  --mutate --covered-only  Only generate mutations for classes that are covered by tests  \n  --mutate --everything  Generate mutations for all classes, even if they are not covered by tests  \n  --mutate --profile . Output to standard output the top ten slowest mutations  \n  --mutate --retry  Run untested or uncovered mutations first and stop execution upon first error or failure  \n  --mutate --stop-on-uncovered  Stop mutation testing execution upon first untested mutation  \n  --mutate --stop-on-untested  Stop mutation testing execution upon first untested mutation  \n\n  PROFILING OPTIONS:\n  --profile .............. Output to standard output the top ten slowest tests  \n\n"
  },
  {
    "path": "tests/.pest/snapshots/Visual/Todo/todo.snap",
    "content": "\n   TODO  Tests\\Features\\BeforeEachProxiesToTestCallWithTodo - 4 todos\n  ↓ is marked as todo 1\n  ↓ is marked as todo 2\n  ↓ is marked as todo 3\n  ↓ shouldBeMarkedAsTodo\n\n   TODO  Tests\\Features\\DatasetsTests - 1 todo\n  ↓ forbids to define tests in Datasets dirs and Datasets.php files\n\n   TODO  Tests\\Features\\Describe - 5 todos\n  ↓ todo\n  ↓ todo on hook → should not fail\n  ↓ todo on hook → should run\n  ↓ todo on describe → should not fail\n  ↓ todo on describe → should run\n\n   TODO  Tests\\Features\\Todo - 29 todos\n  ↓ something todo later\n  ↓ something todo later chained\n  ↓ something todo later chained and with function body\n  ↓ it may have an associated assignee [@nunomaduro]\n  ↓ it may have an associated issue #1\n  ↓ it may have an associated PR #1\n  ↓ it may have an associated note\n  // a note\n  ↓ todo on describe → todo block → nested inside todo block → it should not execute\n  ↓ todo on describe → todo block → nested inside todo block → it should set the note\n  // hi\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on describe → todo block → it should not execute\n  ↓ todo on describe with matching name → describe block → it should not execute\n  ↓ todo on test after describe block\n  ↓ todo with note on test after describe block\n  // test note\n  ↓ todo on beforeEach → todo block → nested inside todo block → it should not execute\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on beforeEach → todo block → it should not execute\n  ↓ todo on test after describe block with beforeEach\n  ↓ todo with note on test after describe block with beforeEach\n  // test note\n\n   PASS  Tests\\CustomTestCase\\ChildTest\n  ✓ override method\n\n   PASS  Tests\\CustomTestCase\\ExecutedTest\n  ✓ that gets executed\n\n   PASS  Tests\\CustomTestCase\\ParentTest\n  ✓ override method\n\n  Tests:    39 todos, 3 passed (21 assertions)\n  Duration: x.xxs\n\n"
  },
  {
    "path": "tests/.pest/snapshots/Visual/Todo/todo_in_parallel.snap",
    "content": "\n   TODO  Tests\\Features\\BeforeEachProxiesToTestCallWithTodo - 4 todos\n  ↓ is marked as todo 1\n  ↓ is marked as todo 2\n  ↓ is marked as todo 3\n  ↓ shouldBeMarkedAsTodo\n\n   TODO  Tests\\Features\\DatasetsTests - 1 todo\n  ↓ forbids to define tests in Datasets dirs and Datasets.php files\n\n   TODO  Tests\\Features\\Describe - 5 todos\n  ↓ todo\n  ↓ todo on hook → should not fail\n  ↓ todo on hook → should run\n  ↓ todo on describe → should not fail\n  ↓ todo on describe → should run\n\n   TODO  Tests\\Features\\Todo - 29 todos\n  ↓ something todo later\n  ↓ something todo later chained\n  ↓ something todo later chained and with function body\n  ↓ it may have an associated assignee [@nunomaduro]\n  ↓ it may have an associated issue #1\n  ↓ it may have an associated PR #1\n  ↓ it may have an associated note\n  // a note\n  ↓ todo on describe → todo block → nested inside todo block → it should not execute\n  ↓ todo on describe → todo block → nested inside todo block → it should set the note\n  // hi\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on describe → todo block → it should not execute\n  ↓ todo on describe with matching name → describe block → it should not execute\n  ↓ todo on test after describe block\n  ↓ todo with note on test after describe block\n  // test note\n  ↓ todo on beforeEach → todo block → nested inside todo block → it should not execute\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on beforeEach → todo block → it should not execute\n  ↓ todo on test after describe block with beforeEach\n  ↓ todo with note on test after describe block with beforeEach\n  // test note\n\n   PASS  Tests\\CustomTestCase\\ChildTest\n  ✓ override method\n\n   PASS  Tests\\CustomTestCase\\ExecutedTest\n  ✓ that gets executed\n\n   PASS  Tests\\CustomTestCase\\ParentTest\n  ✓ override method\n\n  Tests:    39 todos, 3 passed (21 assertions)\n  Duration: x.xxs\n\n"
  },
  {
    "path": "tests/.pest/snapshots/Visual/Todo/todos.snap",
    "content": "\n   TODO  Tests\\Features\\BeforeEachProxiesToTestCallWithTodo - 4 todos\n  ↓ is marked as todo 1\n  ↓ is marked as todo 2\n  ↓ is marked as todo 3\n  ↓ shouldBeMarkedAsTodo\n\n   TODO  Tests\\Features\\DatasetsTests - 1 todo\n  ↓ forbids to define tests in Datasets dirs and Datasets.php files\n\n   TODO  Tests\\Features\\Describe - 5 todos\n  ↓ todo\n  ↓ todo on hook → should not fail\n  ↓ todo on hook → should run\n  ↓ todo on describe → should not fail\n  ↓ todo on describe → should run\n\n   TODO  Tests\\Features\\Todo - 29 todos\n  ↓ something todo later\n  ↓ something todo later chained\n  ↓ something todo later chained and with function body\n  ↓ it may have an associated assignee [@nunomaduro]\n  ↓ it may have an associated issue #1\n  ↓ it may have an associated PR #1\n  ↓ it may have an associated note\n  // a note\n  ↓ todo on describe → todo block → nested inside todo block → it should not execute\n  ↓ todo on describe → todo block → nested inside todo block → it should set the note\n  // hi\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on describe → todo block → it should not execute\n  ↓ todo on describe with matching name → describe block → it should not execute\n  ↓ todo on test after describe block\n  ↓ todo with note on test after describe block\n  // test note\n  ↓ todo on beforeEach → todo block → nested inside todo block → it should not execute\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on beforeEach → todo block → it should not execute\n  ↓ todo on test after describe block with beforeEach\n  ↓ todo with note on test after describe block with beforeEach\n  // test note\n\n   PASS  Tests\\CustomTestCase\\ChildTest\n  ✓ override method\n\n   PASS  Tests\\CustomTestCase\\ExecutedTest\n  ✓ that gets executed\n\n   PASS  Tests\\CustomTestCase\\ParentTest\n  ✓ override method\n\n  Tests:    39 todos, 3 passed (21 assertions)\n  Duration: x.xxs\n\n"
  },
  {
    "path": "tests/.pest/snapshots/Visual/Todo/todos_in_parallel.snap",
    "content": "\n   TODO  Tests\\Features\\BeforeEachProxiesToTestCallWithTodo - 4 todos\n  ↓ is marked as todo 1\n  ↓ is marked as todo 2\n  ↓ is marked as todo 3\n  ↓ shouldBeMarkedAsTodo\n\n   TODO  Tests\\Features\\DatasetsTests - 1 todo\n  ↓ forbids to define tests in Datasets dirs and Datasets.php files\n\n   TODO  Tests\\Features\\Describe - 5 todos\n  ↓ todo\n  ↓ todo on hook → should not fail\n  ↓ todo on hook → should run\n  ↓ todo on describe → should not fail\n  ↓ todo on describe → should run\n\n   TODO  Tests\\Features\\Todo - 29 todos\n  ↓ something todo later\n  ↓ something todo later chained\n  ↓ something todo later chained and with function body\n  ↓ it may have an associated assignee [@nunomaduro]\n  ↓ it may have an associated issue #1\n  ↓ it may have an associated PR #1\n  ↓ it may have an associated note\n  // a note\n  ↓ todo on describe → todo block → nested inside todo block → it should not execute\n  ↓ todo on describe → todo block → nested inside todo block → it should set the note\n  // hi\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on describe → todo block → it should not execute\n  ↓ todo on describe with matching name → describe block → it should not execute\n  ↓ todo on test after describe block\n  ↓ todo with note on test after describe block\n  // test note\n  ↓ todo on beforeEach → todo block → nested inside todo block → it should not execute\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on beforeEach → todo block → it should not execute\n  ↓ todo on test after describe block with beforeEach\n  ↓ todo with note on test after describe block with beforeEach\n  // test note\n\n   PASS  Tests\\CustomTestCase\\ChildTest\n  ✓ override method\n\n   PASS  Tests\\CustomTestCase\\ExecutedTest\n  ✓ that gets executed\n\n   PASS  Tests\\CustomTestCase\\ParentTest\n  ✓ override method\n\n  Tests:    39 todos, 3 passed (21 assertions)\n  Duration: x.xxs\n\n"
  },
  {
    "path": "tests/.pest/snapshots/Visual/Version/visual_snapshot_of_help_command_output.snap",
    "content": "\n  Pest Testing Framework 4.4.2.  \n\n"
  },
  {
    "path": "tests/.pest/snapshots-external/Features/Expect/toMatchSnapshot/_within_describe__→_pass_with_dataset___my_datas_set_value___with_data___my_datas_set_value__.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots-external/Features/Expect/toMatchSnapshot/_within_describe__→_pass_with_dataset_with_data_set_____my_datas_set_value___.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots-external/Features/Expect/toMatchSnapshot/_within_describe__→_pass_with_dataset_with_data_set____my_datas_set_value___.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots-external/Features/Expect/toMatchSnapshot/pass_with_dataset___my_datas_set_value___with_data___my_datas_set_value__.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots-external/Features/Expect/toMatchSnapshot/pass_with_dataset_with_data_set_____my_datas_set_value___.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.pest/snapshots-external/Features/Expect/toMatchSnapshot/pass_with_dataset_with_data_set____my_datas_set_value___.snap",
    "content": "    <div class=\"container\">\n        <div class=\"row\">\n            <div class=\"col-md-12\">\n                <h1>Snapshot</h1>\n            </div>\n        </div>\n    </div>"
  },
  {
    "path": "tests/.snapshots/Failure.php.inc",
    "content": "##teamcity[testSuiteStarted name='Tests/tests/Failure' locationHint='pest_qn://tests/.tests/Failure.php' flowId='1234']\n##teamcity[testCount count='8' flowId='1234']\n##teamcity[testStarted name='it can fail with comparison' locationHint='pest_qn://tests/.tests/Failure.php::it can fail with comparison' flowId='1234']\n##teamcity[testFailed name='it can fail with comparison' message='Failed asserting that true matches expected false.' details='at tests/.tests/Failure.php:6' type='comparisonFailure' actual='true' expected='false' flowId='1234']\n##teamcity[testFinished name='it can fail with comparison' duration='100000' flowId='1234']\n##teamcity[testStarted name='it can be ignored because of no assertions' locationHint='pest_qn://tests/.tests/Failure.php::it can be ignored because of no assertions' flowId='1234']\n##teamcity[testIgnored name='it can be ignored because of no assertions' message='This test did not perform any assertions' details='' flowId='1234']\n##teamcity[testFinished name='it can be ignored because of no assertions' duration='100000' flowId='1234']\n##teamcity[testStarted name='it can be ignored because it is skipped' locationHint='pest_qn://tests/.tests/Failure.php::it can be ignored because it is skipped' flowId='1234']\n##teamcity[testIgnored name='it can be ignored because it is skipped' message='This test was ignored.' details='' flowId='1234']\n##teamcity[testFinished name='it can be ignored because it is skipped' duration='100000' flowId='1234']\n##teamcity[testStarted name='it can fail' locationHint='pest_qn://tests/.tests/Failure.php::it can fail' flowId='1234']\n##teamcity[testFailed name='it can fail' message='oh noo' details='at tests/.tests/Failure.php:18' flowId='1234']\n##teamcity[testFinished name='it can fail' duration='100000' flowId='1234']\n##teamcity[testStarted name='it throws exception' locationHint='pest_qn://tests/.tests/Failure.php::it throws exception' flowId='1234']\n##teamcity[testFailed name='it throws exception' message='Exception: test error' details='at tests/.tests/Failure.php:22' flowId='1234']\n##teamcity[testFinished name='it throws exception' duration='100000' flowId='1234']\n##teamcity[testStarted name='it is not done yet' locationHint='pest_qn://tests/.tests/Failure.php::it is not done yet' flowId='1234']\n##teamcity[testFinished name='it is not done yet' duration='100000' flowId='1234']\n##teamcity[testStarted name='build this one.' locationHint='pest_qn://tests/.tests/Failure.php::build this one.' flowId='1234']\n##teamcity[testFinished name='build this one.' duration='100000' flowId='1234']\n##teamcity[testStarted name='it is passing' locationHint='pest_qn://tests/.tests/Failure.php::it is passing' flowId='1234']\n##teamcity[testFinished name='it is passing' duration='100000' flowId='1234']\n##teamcity[testSuiteFinished name='Tests/tests/Failure' flowId='1234']\n\n  \u001b[90mTests:\u001b[39m    \u001b[31;1m3 failed\u001b[39;22m\u001b[90m,\u001b[39m\u001b[39m \u001b[39m\u001b[33;1m1 risky\u001b[39;22m\u001b[90m,\u001b[39m\u001b[39m \u001b[39m\u001b[36;1m2 todos\u001b[39;22m\u001b[90m,\u001b[39m\u001b[39m \u001b[39m\u001b[33;1m1 skipped\u001b[39;22m\u001b[90m,\u001b[39m\u001b[39m \u001b[39m\u001b[32;1m1 passed\u001b[39;22m\u001b[90m (3 assertions)\u001b[39m\n  \u001b[90mDuration:\u001b[39m \u001b[39m1.00s\u001b[39m\n\n"
  },
  {
    "path": "tests/.snapshots/SuccessOnly.php.inc",
    "content": "##teamcity[testSuiteStarted name='Tests/tests/SuccessOnly' locationHint='pest_qn://tests/.tests/SuccessOnly.php' flowId='1234']\n##teamcity[testCount count='4' flowId='1234']\n##teamcity[testStarted name='it can pass with comparison' locationHint='pest_qn://tests/.tests/SuccessOnly.php::it can pass with comparison' flowId='1234']\n##teamcity[testFinished name='it can pass with comparison' duration='100000' flowId='1234']\n##teamcity[testStarted name='can also pass' locationHint='pest_qn://tests/.tests/SuccessOnly.php::can also pass' flowId='1234']\n##teamcity[testFinished name='can also pass' duration='100000' flowId='1234']\n##teamcity[testSuiteStarted name='can pass with dataset' locationHint='pest_qn://tests/.tests/SuccessOnly.php::can pass with dataset' flowId='1234']\n##teamcity[testStarted name='can pass with dataset with data set \"(true)\"' locationHint='pest_qn://tests/.tests/SuccessOnly.php::can pass with dataset with data set \"(true)\"' flowId='1234']\n##teamcity[testFinished name='can pass with dataset with data set \"(true)\"' duration='100000' flowId='1234']\n##teamcity[testSuiteFinished name='can pass with dataset' flowId='1234']\n##teamcity[testSuiteStarted name='`block` → can pass with dataset in describe block' locationHint='pest_qn://tests/.tests/SuccessOnly.php::`block` → can pass with dataset in describe block' flowId='1234']\n##teamcity[testStarted name='`block` → can pass with dataset in describe block with data set \"(1)\"' locationHint='pest_qn://tests/.tests/SuccessOnly.php::`block` → can pass with dataset in describe block with data set \"(1)\"' flowId='1234']\n##teamcity[testFinished name='`block` → can pass with dataset in describe block with data set \"(1)\"' duration='100000' flowId='1234']\n##teamcity[testSuiteFinished name='`block` → can pass with dataset in describe block' flowId='1234']\n##teamcity[testSuiteFinished name='Tests/tests/SuccessOnly' flowId='1234']\n\n  \u001b[90mTests:\u001b[39m    \u001b[32;1m4 passed\u001b[39;22m\u001b[90m (4 assertions)\u001b[39m\n  \u001b[90mDuration:\u001b[39m \u001b[39m1.00s\u001b[39m\n\n"
  },
  {
    "path": "tests/.snapshots/allows-to-run-a-directory.txt",
    "content": "   WARN  Tests\\Fixtures\\CollisionTest\n  - error\n  - success\n\n   PASS  Tests\\Fixtures\\DirectoryWithTests\\ExampleTest\n  ✓ it example 1\n\n   PASS  Tests\\Fixtures\\ExampleTest\n  ✓ it example 2\n\n   WARN  Tests\\Fixtures\\Inheritance\\Base\\ExampleTest\n  - example\n\n   PASS  Tests\\Fixtures\\Inheritance\\ExampleTest\n  ✓ example\n\n  Tests:    3 skipped, 3 passed (3 assertions)\n"
  },
  {
    "path": "tests/.snapshots/allows-to-run-a-single-test.txt",
    "content": "   PASS  Tests\\Fixtures\\DirectoryWithTests\\ExampleTest\n  ✓ it example 1\n\n  Tests:    1 passed (1 assertions)\n"
  },
  {
    "path": "tests/.snapshots/disable-decorating-printer.txt",
    "content": "\n   PASS  Tests\\Fixtures\\DirectoryWithTests\\ExampleTest\n  ✓ it example 1\n\n  Tests:    1 passed (1 assertions)\n"
  },
  {
    "path": "tests/.snapshots/success.txt",
    "content": "\n   PASS  Tests\\Arch\n  ✓ preset → php → ignoring ['Pest\\Expectation', 'debug_backtrace', 'var_export', …]\n  ✓ preset → strict → ignoring ['usleep']\n  ✓ preset → security → ignoring ['eval', 'str_shuffle', 'exec', …]\n  ✓ globals\n  ✓ contracts\n\n   PASS  Tests\\Environments\\Windows\n  ✓ global functions are loaded\n\n   WARN  Tests\\Features\\After\n  ✓ it can run after test\n  ✓ it can run after test twice\n  - it does not run when skipped\n  - something → it does not run when skipped\n  ✓ something → it can run after test\n  ✓ something 2 → it can run after test\n  ✓ high order test\n  - high order test with skip\n  ✓ post 'foo' → defer Closure Object () → expect Closure Object () → toBe 1\n\n   PASS  Tests\\Features\\AfterAll\n  ✓ deletes file after all\n\n   PASS  Tests\\Features\\AfterEach\n  ✓ it does not get executed before the test\n  ✓ it gets executed after the test\n  ✓ outer → inner → it does not get executed before the test\n  ✓ outer → inner → it should call all parent afterEach functions\n  ✓ matching describe block names → outer → middle → inner → it does not get executed before the test\n  ✓ matching describe block names → outer → middle → inner → it should call all parent afterEach functions\n  ✓ matching describe block names → outer → middle → it does not get executed before the test\n  ✓ matching describe block names → outer → middle → it should not call afterEach functions for sibling describe blocks with the same name\n  ✓ matching describe block names → outer → inner → it does not get executed before the test\n  ✓ matching describe block names → outer → inner → it should not call afterEach functions for descendent of sibling describe blocks with the same name\n\n   PASS  Tests\\Features\\Assignee\n  ✓ it may be associated with an assignee [@nunomaduro, @taylorotwell]\n  ✓ nested → it may be associated with an assignee [@nunomaduro, @jamesbrooks, @joedixon, @taylorotwell]\n  // an note between an the assignee\n\n   PASS  Tests\\Features\\BeforeAll\n  ✓ it gets executed before tests\n  ✓ it do not get executed before each test\n\n   PASS  Tests\\Features\\BeforeEach\n  ✓ it gets executed before each test\n  ✓ it gets executed before each test once again\n  ✓ outer → inner → it should call all parent beforeEach functions\n  ✓ with expectations → nested block → test\n  ✓ with expectations → test\n  ✓ matching describe block names → outer → middle → inner → it should call all parent beforeEach functions\n  ✓ matching describe block names → outer → middle → it should not call beforeEach functions for sibling describe blocks with the same name\n  ✓ matching describe block names → outer → inner → it should not call beforeEach functions for descendent of sibling describe blocks with the same name\n  ✓ matching name → it should call the before each\n  ✓ matching name → it should not call the before each on the describe block with the same name\n  ✓ called on all tests → beforeEach should be called\n  ✓ called on all tests → beforeEach should be called for all tests\n\n   PASS  Tests\\Features\\BeforeEachProxiesToTestCallWithExpectations\n  ✓ runs 1\n  ✓ runs 2\n  ✓ runs 3\n\n   WARN  Tests\\Features\\BeforeEachProxiesToTestCallWithSkip\n  - does not run 1\n  - does not run 2\n  - does not run 3\n\n   TODO  Tests\\Features\\BeforeEachProxiesToTestCallWithTodo - 4 todos\n  ↓ is marked as todo 1\n  ↓ is marked as todo 2\n  ↓ is marked as todo 3\n  ↓ shouldBeMarkedAsTodo\n\n   WARN  Tests\\Features\\Coverage\n  ✓ it has plugin\n  - it adds coverage if --coverage exist → Coverage is not available\n  ✓ it adds coverage if --min exist\n  ✓ it generates coverage based on file input\n\n   PASS  Tests\\Features\\Covers\\ClassCoverage\n  ✓ it uses the correct PHPUnit attribute for class\n\n   PASS  Tests\\Features\\Covers\\ExceptionHandling\n  ✓ it throws exception if no class nor method has been found\n\n   PASS  Tests\\Features\\Covers\\FunctionCoverage\n  ✓ it uses the correct PHPUnit attribute for function\n\n   PASS  Tests\\Features\\Covers\\GuessCoverage\n  ✓ it guesses if the given argument is a class or function\n\n   PASS  Tests\\Features\\Covers\\TraitCoverage\n  ✓ it uses the correct PHPUnit attribute for trait\n\n   PASS  Tests\\Features\\DatasetsTests - 1 todo\n  ✓ it throws exception if dataset does not exist\n  ✓ it throws exception if dataset already exist\n  ✓ it sets closures\n  ✓ it sets arrays\n  ✓ it gets bound to test case object with ('a')\n  ✓ it gets bound to test case object with ('b')\n  ✓ it truncates the description with ('FoooFoooFoooFoooFoooFoooFoooF…ooFooo')\n  ✓ lazy datasets with (1)\n  ✓ lazy datasets with (2)\n  ✓ lazy datasets did the job right\n  ✓ interpolated (1) lazy datasets\n  ✓ interpolated (2) lazy datasets\n  ✓ eager datasets with (1)\n  ✓ eager datasets with (2)\n  ✓ eager datasets did the job right\n  ✓ lazy registered datasets with (1)\n  ✓ lazy registered datasets with (2)\n  ✓ lazy registered datasets did the job right\n  ✓ eager registered datasets with (1)\n  ✓ eager registered datasets with (2)\n  ✓ eager registered datasets did the job right\n  ✓ eager wrapped registered datasets with (1)\n  ✓ eager wrapped registered datasets with (2)\n  ✓ eager registered wrapped datasets did the job right\n  ✓ named datasets with dataset \"one\"\n  ✓ named datasets with dataset \"two\"\n  ✓ interpolated \"one\" named datasets\n  ✓ interpolated \"two\" named datasets\n  ✓ named datasets did the job right\n  ✓ lazy named datasets with (Bar)\n  ✓ it creates unique test case names with ('Name 1', Pest\\Plugin, true) #1\n  ✓ it creates unique test case names with ('Name 1', Pest\\Plugin, true) #2\n  ✓ it creates unique test case names with ('Name 1', Pest\\Plugin, false)\n  ✓ it creates unique test case names with ('Name 2', Pest\\Plugin, false)\n  ✓ it creates unique test case names with ('Name 2', Pest\\Plugin, true)\n  ✓ it creates unique test case names with ('Name 1', Pest\\Plugin, true) #3\n  ✓ it creates unique test case names - count\n  ✓ lazy multiple datasets with (1) / (3)\n  ✓ lazy multiple datasets with (1) / (4)\n  ✓ lazy multiple datasets with (2) / (3)\n  ✓ lazy multiple datasets with (2) / (4)\n  ✓ lazy multiple datasets did the job right\n  ✓ eager multiple datasets with (1) / (3)\n  ✓ eager multiple datasets with (1) / (4)\n  ✓ eager multiple datasets with (2) / (3)\n  ✓ eager multiple datasets with (2) / (4)\n  ✓ eager multiple datasets did the job right\n  ✓ lazy registered multiple datasets with (1) / (1)\n  ✓ lazy registered multiple datasets with (1) / (2)\n  ✓ lazy registered multiple datasets with (2) / (1)\n  ✓ lazy registered multiple datasets with (2) / (2)\n  ✓ lazy registered multiple datasets did the job right\n  ✓ eager registered multiple datasets with (1) / (1)\n  ✓ eager registered multiple datasets with (1) / (2)\n  ✓ eager registered multiple datasets with (2) / (1)\n  ✓ eager registered multiple datasets with (2) / (2)\n  ✓ eager registered multiple datasets did the job right\n  ✓ eager wrapped registered multiple datasets with (1) / (1)\n  ✓ eager wrapped registered multiple datasets with (1) / (2)\n  ✓ eager wrapped registered multiple datasets with (2) / (1)\n  ✓ eager wrapped registered multiple datasets with (2) / (2)\n  ✓ eager wrapped registered multiple datasets did the job right\n  ✓ named multiple datasets with dataset \"one\" / dataset \"three\"\n  ✓ named multiple datasets with dataset \"one\" / dataset \"four\"\n  ✓ named multiple datasets with dataset \"two\" / dataset \"three\"\n  ✓ named multiple datasets with dataset \"two\" / dataset \"four\"\n  ✓ named multiple datasets did the job right\n  ✓ more than two datasets with (1) / (3) / (5)\n  ✓ more than two datasets with (1) / (3) / (6)\n  ✓ more than two datasets with (1) / (4) / (5)\n  ✓ more than two datasets with (1) / (4) / (6)\n  ✓ more than two datasets with (2) / (3) / (5)\n  ✓ more than two datasets with (2) / (3) / (6)\n  ✓ more than two datasets with (2) / (4) / (5)\n  ✓ more than two datasets with (2) / (4) / (6)\n  ✓ more than two datasets did the job right\n  ✓ eager registered wrapped datasets with Generator functions with (1)\n  ✓ eager registered wrapped datasets with Generator functions with (2)\n  ✓ eager registered wrapped datasets with Generator functions with (3)\n  ✓ eager registered wrapped datasets with Generator functions with (4)\n  ✓ eager registered wrapped datasets with Generator functions did the job right\n  ✓ eager registered wrapped datasets with Generator functions display description with dataset \"taylor\"\n  ✓ eager registered wrapped datasets with Generator functions display description with dataset \"james\"\n  ✓ it can resolve a dataset after the test case is available with (Closure Object ()) #1\n  ✓ it can resolve a dataset after the test case is available with (Closure Object ()) #2\n  ✓ it can resolve a dataset after the test case is available with multiple datasets with (Closure Object ()) / (Closure Object ()) #1\n  ✓ it can resolve a dataset after the test case is available with multiple datasets with (Closure Object ()) / (Closure Object ()) #2\n  ✓ it can resolve a dataset after the test case is available with multiple datasets with (Closure Object ()) / (Closure Object ()) #3\n  ✓ it can resolve a dataset after the test case is available with multiple datasets with (Closure Object ()) / (Closure Object ()) #4\n  ✓ it can resolve a dataset after the test case is available with shared yield sets with (Closure Object ()) #1\n  ✓ it can resolve a dataset after the test case is available with shared yield sets with (Closure Object ()) #2\n  ✓ it can resolve a dataset after the test case is available with shared array sets with (Closure Object ()) #1\n  ✓ it can resolve a dataset after the test case is available with shared array sets with (Closure Object ()) #2\n  ✓ it resolves a potential bound dataset logically with ('foo', Closure Object ())\n  ✓ it resolves a potential bound dataset logically even when the closure comes first with (Closure Object (), 'bar')\n  ✓ it will not resolve a closure if it is type hinted as a closure with (Closure Object ()) #1\n  ✓ it will not resolve a closure if it is type hinted as a closure with (Closure Object ()) #2\n  ✓ it will not resolve a closure if it is type hinted as a callable with (Closure Object ()) #1\n  ✓ it will not resolve a closure if it is type hinted as a callable with (Closure Object ()) #2\n  ✓ it can correctly resolve a bound dataset that returns an array with (Closure Object ())\n  ✓ it can correctly resolve a bound dataset that returns an array but wants to be spread with (Closure Object ())\n  ↓ forbids to define tests in Datasets dirs and Datasets.php files\n  ✓ it may be used with high order with dataset \"formal\"\n  ✓ it may be used with high order with dataset \"informal\"\n  ✓ it may be used with high order even when bound with dataset \"formal\"\n  ✓ it may be used with high order even when bound with dataset \"informal\"\n  ✓ with on nested describe → nested → before inner describe block with (1)\n  ✓ with on nested describe → nested → describe → it should include the with value from all parent describe blocks with (1) / (2)\n  ✓ with on nested describe → nested → describe → should include the with value from all parent describe blocks and the test with (1) / (2) / (3)\n  ✓ with on nested describe → nested → after inner describe block with (1)\n  ✓ matching describe block names → outer → before inner describe block with (1)\n  ✓ matching describe block names → outer → inner → it should include the with value from all parent describe blocks with (1) / (2)\n  ✓ matching describe block names → outer → inner → should include the with value from all parent describe blocks and the test with (1) / (2) / (3)\n  ✓ matching describe block names → outer → inner → it should not include the value from the other describe block with the same name with (1)\n  ✓ matching describe block names → outer → after inner describe block with (1)\n  ✓ after describe block with (5)\n  ✓ it may be used with high order after describe block with dataset \"formal\"\n  ✓ it may be used with high order after describe block with dataset \"informal\"\n  ✓ after describe block with named dataset with ('after')\n\n   PASS  Tests\\Features\\Depends\n  ✓ first\n  ✓ second\n  ✓ depends\n  ✓ depends with ...params\n  ✓ depends with defined arguments\n  ✓ depends run test only once\n  ✓ it asserts true is true\n  ✓ depends works with the correct test name\n  ✓ describe block → first in describe\n  ✓ describe block → second in describe\n  ✓ describe block → third in describe\n  ✓ describe block → nested describe → first in nested describe\n  ✓ describe block → nested describe → second in nested describe\n  ✓ describe block → nested describe → third in nested describe\n  ✓ depends on test after describe block\n\n   PASS  Tests\\Features\\DependsInheritance\n  ✓ it is a test\n  ✓ it uses correct parent class\n\n   DEPR  Tests\\Features\\Deprecated\n  ! deprecated → str_contains(): Passing null to parameter #1 ($haystack) of type string is deprecated // tests/Features/Deprecated.php:4\n  ! user deprecated → Since foo 1.0: This is a deprecation description // tests/Features/Deprecated.php:10\n\n   PASS  Tests\\Features\\Describe - 5 todos\n  ✓ before each\n  ✓ hooks → value\n  ✓ hooks in different orders → value\n  ↓ todo\n  ✓ previous describable before each does not get applied here\n  ↓ todo on hook → should not fail\n  ↓ todo on hook → should run\n  ↓ todo on describe → should not fail\n  ↓ todo on describe → should run\n  ✓ should run\n  ✓ with with (1)\n  ✓ with on hook → value with (2)\n  ✓ with on describe → value with (3)\n  ✓ depends on describe → foo\n  ✓ depends on describe → bar\n  ✓ depends on describe using with → foo with (3)\n  ✓ depends on describe using with → bar with (3)\n  ✓ with test after describe → it should run the before each\n\n   PASS  Tests\\Features\\DescriptionLess\n  ✓ get 'foo'\n  ✓ get 'foo' → get 'bar' → expect true → toBeTrue\n  ✓ get 'foo' → expect true → toBeTrue\n  ✓ a \"describe\" group of tests → get 'foo'\n  ✓ a \"describe\" group of tests → get 'foo' → get 'bar' → expect true → toBeTrue\n  ✓ a \"describe\" group of tests → get 'foo' → expect true → toBeTrue\n\n   PASS  Tests\\Features\\Done\n  ✓ it may have an associated assignee [@nunomaduro]\n  ✓ it may have an associated issue #1\n  ✓ it may have an associated PR #1\n  ✓ it may have an associated note\n  // a note\n\n   PASS  Tests\\Features\\Exceptions\n  ✓ it gives access the the underlying expectException\n  ✓ it catch exceptions\n  ✓ it catch exceptions and messages\n  ✓ it catch exceptions, messages and code\n  ✓ it can just define the message\n  ✓ it can just define the code\n  ✓ it not catch exceptions if given condition is false\n  ✓ it catch exceptions if given condition is true\n  ✓ it catch exceptions and messages if given condition is true\n  ✓ it catch exceptions, messages and code if given condition is true\n  ✓ it can just define the message if given condition is true\n  ✓ it can just define the code if given condition is true\n  ✓ it can just define the message if given condition is 1\n  ✓ it can just define the code if given condition is 1\n  ✓ it not catch exceptions if given condition is true\n  ✓ it catch exceptions if given condition is false\n  ✓ it catch exceptions and messages if given condition is false\n  ✓ it catch exceptions, messages and code if given condition is false\n  ✓ it can just define the message if given condition is false\n  ✓ it can just define the code if given condition is false\n  ✓ it can just define the message if given condition is 0\n  ✓ it can just define the code if given condition is 0\n\n   PASS  Tests\\Features\\Expect\\HigherOrder\\methods\n  ✓ it can access methods\n  ✓ it can access multiple methods\n  ✓ it works with not\n  ✓ it can accept arguments\n  ✓ it works with each\n  ✓ it works inside of each\n  ✓ it works with sequence\n  ✓ it can compose complex expectations\n  ✓ it can handle nested method calls\n  ✓ it works with higher order tests\n  ✓ it can use the scoped method to lock into the given level for expectations\n  ✓ it works consistently with the json expectation method\n\n   PASS  Tests\\Features\\Expect\\HigherOrder\\methodsAndProperties\n  ✓ it can access methods and properties\n  ✓ it can handle nested methods and properties\n  ✓ it works with higher order tests\n  ✓ it can start a new higher order expectation using the and syntax\n  ✓ it can start a new higher order expectation using the and syntax in higher order tests\n  ✓ it can start a new higher order expectation using the and syntax without nesting expectations\n\n   PASS  Tests\\Features\\Expect\\HigherOrder\\properties\n  ✓ it allows properties to be accessed from the value\n  ✓ it can access multiple properties from the value\n  ✓ it works with not\n  ✓ it works with each\n  ✓ it works inside of each\n  ✓ it works with sequence\n  ✓ it can compose complex expectations\n  ✓ it works with objects\n  ✓ it works with nested properties\n  ✓ it works with higher order tests\n\n   PASS  Tests\\Features\\Expect\\each\n  ✓ an exception is thrown if the the type is not iterable\n  ✓ it expects on each item\n  ✓ it chains expectations on each item\n  ✓ opposite expectations on each item\n  ✓ chained opposite and non-opposite expectations\n  ✓ it can add expectations via \"and\"\n  ✓ it accepts callables\n  ✓ it passes the key of the current item to callables\n\n   PASS  Tests\\Features\\Expect\\extend\n  ✓ it macros true is true\n  ✓ it macros false is not true\n  ✓ it macros true is true with argument\n  ✓ it macros false is not true with argument\n\n   PASS  Tests\\Features\\Expect\\json\n  ✓ it properly parses json string\n  ✓ fails with broken json string\n\n   PASS  Tests\\Features\\Expect\\matchExpectation\n  ✓ it pass\n  ✓ it failures\n  ✓ it runs with truthy\n  ✓ it runs with falsy\n  ✓ it runs with truthy closure condition\n  ✓ it runs with falsy closure condition\n  ✓ it can be passed non-callable values\n  ✓ it fails with unhandled match\n  ✓ it can be used in higher order tests\n\n   PASS  Tests\\Features\\Expect\\not\n  ✓ not property calls\n\n   PASS  Tests\\Features\\Expect\\pipes\n  ✓ pipe is applied and can stop pipeline\n  ✓ pipe is run and can let the pipeline keep going\n  ✓ pipe works with negated expectation\n  ✓ interceptor is applied\n  ✓ interceptor stops the pipeline\n  ✓ interceptor is called only when filter is met\n  ✓ interceptor can be filtered with a closure\n  ✓ interceptor can be filter the expected parameter as well\n  ✓ interceptor works with negated expectation\n  ✓ intercept can add new parameters to the expectation\n\n   PASS  Tests\\Features\\Expect\\ray\n  ✓ ray calls do not fail when ray is not installed\n\n   PASS  Tests\\Features\\Expect\\sequence\n  ✓ an exception is thrown if the the type is not iterable\n  ✓ an exception is thrown if there are no expectations\n  ✓ allows for sequences of checks to be run on iterable data\n  ✓ loops back to the start if it runs out of sequence items\n  ✓ fails if the number of iterable items is less than the number of expectations\n  ✓ it works with associative arrays\n  ✓ it can be passed non-callable values\n  ✓ it can be passed a mixture of value types\n  ✓ it works with traversables\n\n   PASS  Tests\\Features\\Expect\\toBe\n  ✓ strict comparisons\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeAlpha\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeAlphaNumeric\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeArray\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeBetween\n  ✓ passes with int\n  ✓ passes with float\n  ✓ passes with float and int\n  ✓ passes with DateTime\n  ✓ failure with int\n  ✓ failure with float\n  ✓ failure with float and int\n  ✓ failure with DateTime\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeBool\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeCallable\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeCamelCase\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeDigits\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeDirectory\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeEmpty\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeFalse\n  ✓ strict comparisons\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeFalsy\n  ✓ passes as falsy with (false)\n  ✓ passes as falsy with ('')\n  ✓ passes as falsy with (null)\n  ✓ passes as falsy with (0)\n  ✓ passes as falsy with ('0')\n  ✓ passes as not falsy with (true)\n  ✓ passes as not falsy with (1) #1\n  ✓ passes as not falsy with ('false')\n  ✓ passes as not falsy with (1) #2\n  ✓ passes as not falsy with (-1)\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeFile\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeFloat\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeGreaterThan\n  ✓ passes\n  ✓ passes with DateTime and DateTimeImmutable\n  ✓ passes with strings\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeGreaterThanOrEqual\n  ✓ passes\n  ✓ passes with DateTime and DateTimeImmutable\n  ✓ passes with strings\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeIn\n  ✓ passes\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeInfinite\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeInstanceOf\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeInt\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeIntBackedEnum\n  ✓ enum is backed by int\n  ✓ enum is not backed by int\n\n   PASS  Tests\\Features\\Expect\\toBeInvokable\n  ✓ class is invokable\n  ✓ opposite class is invokable\n  ✓ class is invokable via a parent class\n  ✓ class is invokable via a trait\n  ✓ failure when the class is not invokable\n  ✓ class is not invokable\n\n   PASS  Tests\\Features\\Expect\\toBeIterable\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeJson\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeKebabCase\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeLessThan\n  ✓ passes\n  ✓ passes with DateTime and DateTimeImmutable\n  ✓ passes with strings\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeLessThanOrEqual\n  ✓ passes\n  ✓ passes with DateTime and DateTimeImmutable\n  ✓ passes with strings\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeList\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeLowercase\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeNAN\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeNull\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeNumeric\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeObject\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeReadableDirectory\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeReadableFile\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeResource\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeScalar\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeSlug\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ failures with default message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeSnakeCase\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeString\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeStringBackedEnum\n  ✓ enum is backed by string\n  ✓ enum is not backed by string\n\n   PASS  Tests\\Features\\Expect\\toBeStudlyCase\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeTrue\n  ✓ strict comparisons\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeTruthy\n  ✓ passes as truthy with (true)\n  ✓ passes as truthy with (1) #1\n  ✓ passes as truthy with ('false')\n  ✓ passes as truthy with (1) #2\n  ✓ passes as truthy with (-1)\n  ✓ passes as not truthy with (false)\n  ✓ passes as not truthy with ('')\n  ✓ passes as not truthy with (null)\n  ✓ passes as not truthy with (0)\n  ✓ passes as not truthy with ('0')\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeUppercase\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeUrl\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ failures with default message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeUuid\n  ✓ failures with wrong type\n  ✓ pass\n  ✓ failures\n  ✓ failures with message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeWritableDirectory\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toBeWritableFile\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toContain\n  ✓ passes strings\n  ✓ passes strings with multiple needles\n  ✓ passes arrays\n  ✓ passes arrays with multiple needles\n  ✓ passes with array needles\n  ✓ failures\n  ✓ failures with multiple needles (all failing)\n  ✓ failures with multiple needles (some failing)\n  ✓ not failures\n  ✓ not failures with multiple needles (all failing)\n  ✓ not failures with multiple needles (some failing)\n\n   PASS  Tests\\Features\\Expect\\toContainEqual\n  ✓ passes arrays\n  ✓ passes arrays with multiple needles\n  ✓ failures\n  ✓ failures with multiple needles (all failing)\n  ✓ failures with multiple needles (some failing)\n  ✓ not failures\n  ✓ not failures with multiple needles (all failing)\n  ✓ not failures with multiple needles (some failing)\n\n   PASS  Tests\\Features\\Expect\\toContainOnlyInstancesOf\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toEndWith\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toEqual\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toEqualCanonicalizing\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toEqualWithDelta\n  ✓ pass\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toHaveAttribute\n  ✓ class has attribute\n  ✓ opposite class has attribute\n  ✓ class not has attribute\n\n   PASS  Tests\\Features\\Expect\\toHaveCamelCaseKeys\n  ✓ pass\n  ✓ failures\n  ✓ failures with message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toHaveConstructor\n  ✓ class has constructor\n  ✓ class has no constructor\n\n   PASS  Tests\\Features\\Expect\\toHaveCount\n  ✓ pass\n  ✓ failures with invalid type\n  ✓ failures\n  ✓ failures with message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toHaveDestructor\n  ✓ class has destructor\n  ✓ class has no destructor\n\n   PASS  Tests\\Features\\Expect\\toHaveKebabCaseKeys\n  ✓ pass\n  ✓ failures\n  ✓ failures with message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toHaveKey\n  ✓ pass\n  ✓ pass with nested key\n  ✓ pass with plain key with dots\n  ✓ pass with value check\n  ✓ pass with value check and nested key\n  ✓ pass with value check and plain key with dots\n  ✓ failures\n  ✓ failures with custom message\n  ✓ failures with custom message and Any matcher\n  ✓ failures with nested key\n  ✓ failures with nested key and custom message\n  ✓ failures with nested key and custom message with Any matcher\n  ✓ failures with plain key with dots\n  ✓ fails with wrong value\n  ✓ fails with wrong value and nested key\n  ✓ fails with wrong value and plain key with dots\n  ✓ not failures\n  ✓ not failures with nested key\n  ✓ not failures with plain key with dots\n  ✓ not failures with correct value\n  ✓ not failures with correct value and with nested key\n  ✓ not failures with correct value and with plain key with dots\n\n   PASS  Tests\\Features\\Expect\\toHaveKeys\n  ✓ pass\n  ✓ pass with multi-dimensional arrays\n  ✓ failures\n  ✓ failures with custom message\n  ✓ failures with multi-dimensional arrays\n  ✓ failures with multi-dimensional arrays and custom message\n  ✓ not failures\n  ✓ not failures with multi-dimensional arrays\n\n   PASS  Tests\\Features\\Expect\\toHaveLength\n  ✓ it passes with ('Fortaleza')\n  ✓ it passes with ('Sollefteå')\n  ✓ it passes with ('Ιεράπετρα')\n  ✓ it passes with (stdClass)\n  ✓ it passes with array\n  ✓ it passes with *not*\n  ✓ it properly fails with *not*\n  ✓ it fails\n  ✓ it fails with message\n\n   PASS  Tests\\Features\\Expect\\toHaveLineCountLessThan\n  ✓ it passes\n  ✓ it fails\n\n   PASS  Tests\\Features\\Expect\\toHaveMethod\n  ✓ class has method\n  ✓ opposite class has method\n  ✓ class has method via a parent class\n  ✓ class has method via a trait\n  ✓ failure when the class has no method\n  ✓ class has no method\n\n   PASS  Tests\\Features\\Expect\\toHaveMethods\n  ✓ class has method\n  ✓ opposite class has method\n  ✓ class has method via a parent class\n  ✓ class has method via a trait\n  ✓ failure when the class has no method\n  ✓ class has no method\n\n   PASS  Tests\\Features\\Expect\\toHaveMethodsDocumented\n  ✓ it passes\n  ✓ it fails 1\n  ✓ it fails 2\n\n   PASS  Tests\\Features\\Expect\\toHavePrefix\n  ✓ missing prefix\n  ✓ has prefix\n  ✓ opposite missing prefix\n  ✓ opposite has prefix\n\n   PASS  Tests\\Features\\Expect\\toHavePrivateMethodsBesides\n  ✓ pass\n  ✓ failures\n\n   PASS  Tests\\Features\\Expect\\toHaveProperties\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toHavePropertiesDocumented\n  ✓ it passes\n  ✓ it fails 1\n  ✓ it fails 2\n\n   PASS  Tests\\Features\\Expect\\toHaveProperty\n  ✓ pass\n  ✓ failures\n  ✓ failures with message\n  ✓ failures with message and Any matcher\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toHaveProtectedMethodsBesides\n  ✓ pass\n  ✓ failures\n\n   PASS  Tests\\Features\\Expect\\toHavePublicMethodsBesides\n  ✓ pass\n  ✓ failures\n\n   PASS  Tests\\Features\\Expect\\toHaveSameSize\n  ✓ failures with wrong type\n  ✓ pass\n  ✓ failures\n  ✓ failures with message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toHaveSnakeCaseKeys\n  ✓ pass\n  ✓ failures\n  ✓ failures with message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toHaveStudlyCaseKeys\n  ✓ pass\n  ✓ failures\n  ✓ failures with message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toHaveSuffix\n  ✓ missing suffix\n  ✓ has suffix\n  ✓ opposite missing suffix\n  ✓ opposite has suffix\n\n   PASS  Tests\\Features\\Expect\\toMatch\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toMatchArray\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toMatchConstraint\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toMatchObject\n  ✓ pass\n  ✓ pass with class\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toMatchSnapshot\n  ✓ pass\n  ✓ pass using pipes\n  ✓ pass with __toString\n  ✓ pass with toString\n  ✓ pass with dataset with ('my-datas-set-value')\n  ✓ within describe → pass with dataset with ('my-datas-set-value')\n  ✓ pass with toArray\n  ✓ pass with array\n  ✓ pass with toSnapshot\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n  ✓ multiple snapshot expectations\n  ✓ multiple snapshot expectations with datasets with (1)\n  ✓ multiple snapshot expectations with datasets with ('foo')\n  ✓ multiple snapshot expectations with datasets with ('bar')\n  ✓ multiple snapshot expectations with datasets with ('baz')\n  ✓ describable → multiple snapshot expectations with describe\n  ✓ multiple snapshot expectations with repeat @ repetition 1 of 10\n  ✓ multiple snapshot expectations with repeat @ repetition 2 of 10\n  ✓ multiple snapshot expectations with repeat @ repetition 3 of 10\n  ✓ multiple snapshot expectations with repeat @ repetition 4 of 10\n  ✓ multiple snapshot expectations with repeat @ repetition 5 of 10\n  ✓ multiple snapshot expectations with repeat @ repetition 6 of 10\n  ✓ multiple snapshot expectations with repeat @ repetition 7 of 10\n  ✓ multiple snapshot expectations with repeat @ repetition 8 of 10\n  ✓ multiple snapshot expectations with repeat @ repetition 9 of 10\n  ✓ multiple snapshot expectations with repeat @ repetition 10 of 10\n\n   PASS  Tests\\Features\\Expect\\toStartWith\n  ✓ pass\n  ✓ failures\n  ✓ failures with custom message\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\toThrow\n  ✓ passes\n  ✓ failures 1\n  ✓ failures 2\n  ✓ failures 3\n  ✓ failures 4\n  ✓ failures 5\n  ✓ failures 6\n  ✓ failures 7\n  ✓ failures 8\n  ✓ failures with custom message\n  ✓ not failures\n  ✓ closure missing parameter\n  ✓ closure missing type-hint\n  ✓ it can handle a non-defined exception\n  ✓ it can handle a class not found Error\n\n   PASS  Tests\\Features\\Expect\\toUseStrictEquality\n  ✓ missing strict equality\n  ✓ has strict equality\n  ✓ opposite missing strict equality\n  ✓ opposite has strict equality\n\n   PASS  Tests\\Features\\Expect\\toUseStrictTypes\n  ✓ pass\n  ✓ failures\n\n   PASS  Tests\\Features\\Expect\\toUseTrait\n  ✓ pass\n  ✓ failures\n  ✓ not failures\n\n   PASS  Tests\\Features\\Expect\\unless\n  ✓ it pass\n  ✓ it failures\n  ✓ it runs with truthy\n  ✓ it skips with falsy\n  ✓ it runs with truthy closure condition\n  ✓ it skips with falsy closure condition\n  ✓ it can be used in higher order tests\n\n   PASS  Tests\\Features\\Expect\\when\n  ✓ it pass\n  ✓ it failures\n  ✓ it runs with truthy\n  ✓ it skips with falsy\n  ✓ it runs with truthy closure condition\n  ✓ it skips with falsy closure condition\n  ✓ it can be used in higher order tests\n\n   PASS  Tests\\Features\\Fail\n  ✓ it may fail\n  ✓ it may fail with the given message\n\n   PASS  Tests\\Features\\Fails\n  ✓ it may fail\n  ✓ it may fail with the given message\n\n   PASS  Tests\\Features\\Fixture\n  ✓ it may return a file path\n  ✓ it may throw an exception if the file does not exist\n\n   WARN  Tests\\Features\\Helpers\n  ✓ it can set/get properties on $this\n  ! it gets null if property do not exist → Undefined property Tests\\Features\\Helpers::$wqdwqdqw\n  ✓ it allows to call underlying protected/private methods\n  ✓ it throws error if method do not exist\n  ✓ it can forward unexpected calls to any global function\n  ✓ it can use helpers from helpers file\n  ✓ it can use helpers from helpers directory\n\n   PASS  Tests\\Features\\HigherOrderTests\n  ✓ it proxies calls to object\n  ✓ it is capable doing multiple assertions\n  ✓ it resolves expect callables correctly\n  ✓ does not treat method names as callables\n  ✓ it can defer a method until after test setup\n  ✓ it can pass datasets into the expect callables with (1, 2, 3)\n  ✓ it can pass datasets into the defer callable with (1, 2, 3)\n  ✓ it can pass shared datasets into callables with (1)\n  ✓ it can pass shared datasets into callables with (2)\n\n   WARN  Tests\\Features\\Incompleted\n  … incompleted\n  … it is incompleted\n  … it is incompleted even with method calls like skip\n  … it is incompleted even with method calls like group\n  ✓ it is not incompleted because of expect\n  ✓ it is not incompleted because of assert\n  ✓ it is not incompleted because of test with assertions\n  … a \"describe\" group of tests → it is incompleted\n\n   PASS  Tests\\Features\\Issue\n  ✓ it may be associated with an issue #1, #2\n  ✓ nested → it may be associated with an issue #1, #4, #5, #6, #3\n  // an note between an the issue\n\n   PASS  Tests\\Features\\It\n  ✓ it is a test\n  ✓ it is a higher order message test\n  ✓ a \"describe\" group of tests → it is a test\n  ✓ a \"describe\" group of tests → it is a higher order message test\n\n   PASS  Tests\\Features\\Note\n  ✓ it may have a static note\n  // This is before each static note\n  // This is a note\n  // This is before each runtime note\n  ✓ it may have a runtime note\n  // This is before each static note\n  // This is before each runtime note\n  // This is a runtime note\n  ✓ it may have static note and runtime note\n  // This is before each static note\n  // This is a static note\n  // This is before each runtime note\n  // This is a runtime note\n  ✓ nested → it may have static note and runtime note\n  // This is before each static note\n  // This is describe static note\n  // This is before each describe static note\n  // This is a static note within describe\n  // This is before each runtime note\n  // This is before each describe runtime note\n  // This is a runtime note within describe\n  ✓ nested → describe nested within describe → it may have a static note and runtime note\n  // This is before each static note\n  // This is describe static note\n  // This is before each describe static note\n  // This is a nested describe static note\n  // This is before each nested describe static note\n  // This is a static note within a nested describe\n  // This is before each runtime note\n  // This is before each describe runtime note\n  // This is before each nested describe runtime note\n  // This is a runtime note within a nested describe\n  ✓ matching describe names → describe block → it may have a static note and runtime note\n  // This is before each static note\n  // This is before each matching describe static note\n  // This is a nested matching static note\n  // This is a static note within a matching describe\n  // This is before each runtime note\n  // This is before each matching describe runtime note\n  // This is before each matching describe runtime note\n  // This is a runtime note within a matching describe\n  ✓ matching describe names → describe block → it may have a static note and runtime note, that are different than the matching describe block\n  // This is before each static note\n  // This is before each matching describe static note\n  // This is a nested matching static note, and should not contain the matching describe notes\n  // This is before each matching describe static note, and should not contain the matching describe notes\n  // This is a static note within a matching describe, and should not contain the matching describe notes\n  // This is before each runtime note\n  // This is before each matching describe runtime note\n  // This is before each matching describe runtime note, and should not contain the matching describe notes\n  // This is a runtime note within a matching describe, and should not contain the matching describe notes\n  ✓ multiple notes\n  // This is before each static note\n  // This is before each runtime note\n  // This is a runtime note\n  // This is another runtime note\n\n   NOTI  Tests\\Features\\Notices\n  ! notice → This is a notice description // tests/Features/Notices.php:4\n  ! a \"describe\" group of tests → notice → This is a notice description // tests/Features/Notices.php:11\n\n   PASS  Tests\\Features\\Pr\n  ✓ it may be associated with an pr #1, #2\n  ✓ nested → it may be associated with an pr #1, #4, #5, #6, #3\n  // an note between an the pr\n\n   PASS  Tests\\Features\\References\n  ✓ it can reference a specific class\n  ✓ it can reference a specific class method\n\n   PASS  Tests\\Features\\Repeat\n  ✓ once\n  ✓ multiple times @ repetition 1 of 5\n  ✓ multiple times @ repetition 2 of 5\n  ✓ multiple times @ repetition 3 of 5\n  ✓ multiple times @ repetition 4 of 5\n  ✓ multiple times @ repetition 5 of 5\n  ✓ multiple times with single dataset dataset \"a\" @ repetition 1 of 6\n  ✓ multiple times with single dataset dataset \"b\" @ repetition 1 of 6\n  ✓ multiple times with single dataset dataset \"c\" @ repetition 1 of 6\n  ✓ multiple times with single dataset dataset \"a\" @ repetition 2 of 6\n  ✓ multiple times with single dataset dataset \"b\" @ repetition 2 of 6\n  ✓ multiple times with single dataset dataset \"c\" @ repetition 2 of 6\n  ✓ multiple times with single dataset dataset \"a\" @ repetition 3 of 6\n  ✓ multiple times with single dataset dataset \"b\" @ repetition 3 of 6\n  ✓ multiple times with single dataset dataset \"c\" @ repetition 3 of 6\n  ✓ multiple times with single dataset dataset \"a\" @ repetition 4 of 6\n  ✓ multiple times with single dataset dataset \"b\" @ repetition 4 of 6\n  ✓ multiple times with single dataset dataset \"c\" @ repetition 4 of 6\n  ✓ multiple times with single dataset dataset \"a\" @ repetition 5 of 6\n  ✓ multiple times with single dataset dataset \"b\" @ repetition 5 of 6\n  ✓ multiple times with single dataset dataset \"c\" @ repetition 5 of 6\n  ✓ multiple times with single dataset dataset \"a\" @ repetition 6 of 6\n  ✓ multiple times with single dataset dataset \"b\" @ repetition 6 of 6\n  ✓ multiple times with single dataset dataset \"c\" @ repetition 6 of 6\n  ✓ multiple times with multiple dataset dataset \"a\" / (4) @ repetition 1 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (5) @ repetition 1 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (6) @ repetition 1 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (4) @ repetition 1 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (5) @ repetition 1 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (6) @ repetition 1 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (4) @ repetition 1 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (5) @ repetition 1 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (6) @ repetition 1 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (4) @ repetition 2 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (5) @ repetition 2 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (6) @ repetition 2 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (4) @ repetition 2 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (5) @ repetition 2 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (6) @ repetition 2 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (4) @ repetition 2 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (5) @ repetition 2 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (6) @ repetition 2 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (4) @ repetition 3 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (5) @ repetition 3 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (6) @ repetition 3 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (4) @ repetition 3 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (5) @ repetition 3 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (6) @ repetition 3 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (4) @ repetition 3 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (5) @ repetition 3 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (6) @ repetition 3 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (4) @ repetition 4 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (5) @ repetition 4 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (6) @ repetition 4 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (4) @ repetition 4 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (5) @ repetition 4 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (6) @ repetition 4 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (4) @ repetition 4 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (5) @ repetition 4 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (6) @ repetition 4 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (4) @ repetition 5 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (5) @ repetition 5 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (6) @ repetition 5 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (4) @ repetition 5 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (5) @ repetition 5 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (6) @ repetition 5 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (4) @ repetition 5 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (5) @ repetition 5 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (6) @ repetition 5 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (4) @ repetition 6 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (5) @ repetition 6 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (6) @ repetition 6 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (4) @ repetition 6 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (5) @ repetition 6 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (6) @ repetition 6 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (4) @ repetition 6 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (5) @ repetition 6 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (6) @ repetition 6 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (4) @ repetition 7 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (5) @ repetition 7 of 7\n  ✓ multiple times with multiple dataset dataset \"a\" / (6) @ repetition 7 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (4) @ repetition 7 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (5) @ repetition 7 of 7\n  ✓ multiple times with multiple dataset dataset \"b\" / (6) @ repetition 7 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (4) @ repetition 7 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (5) @ repetition 7 of 7\n  ✓ multiple times with multiple dataset dataset \"c\" / (6) @ repetition 7 of 7\n  ✓ multiple times with iterator @ repetition 1 of 2\n  ✓ multiple times with iterator @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with single dataset ('a') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with single dataset ('b') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with single dataset ('c') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with single dataset ('a') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with single dataset ('b') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with single dataset ('c') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('a') / ('d') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('a') / ('e') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('a') / ('f') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('b') / ('d') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('b') / ('e') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('b') / ('f') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('c') / ('d') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('c') / ('e') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('c') / ('f') @ repetition 1 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('a') / ('d') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('a') / ('e') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('a') / ('f') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('b') / ('d') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('b') / ('e') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('b') / ('f') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('c') / ('d') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('c') / ('e') @ repetition 2 of 2\n  ✓ multiple times with repeat iterator with multiple dataset ('c') / ('f') @ repetition 2 of 2\n  ✓ describe blocks → multiple times @ repetition 1 of 3\n  ✓ describe blocks → multiple times @ repetition 2 of 3\n  ✓ describe blocks → multiple times @ repetition 3 of 3\n  ✓ describe blocks → describe with repeat → test with no repeat should repeat the number of times specified in the parent describe block @ repetition 1 of 3\n  ✓ describe blocks → describe with repeat → test with no repeat should repeat the number of times specified in the parent describe block @ repetition 2 of 3\n  ✓ describe blocks → describe with repeat → test with no repeat should repeat the number of times specified in the parent describe block @ repetition 3 of 3\n  ✓ describe blocks → describe with repeat → test with repeat should repeat the number of times specified in the test @ repetition 1 of 2\n  ✓ describe blocks → describe with repeat → test with repeat should repeat the number of times specified in the test @ repetition 2 of 2\n  ✓ describe blocks → describe with repeat → nested describe without repeat → test with no repeat should repeat the number of times specified in the parent's parent describe block @ repetition 1 of 3\n  ✓ describe blocks → describe with repeat → nested describe without repeat → test with no repeat should repeat the number of times specified in the parent's parent describe block @ repetition 2 of 3\n  ✓ describe blocks → describe with repeat → nested describe without repeat → test with no repeat should repeat the number of times specified in the parent's parent describe block @ repetition 3 of 3\n  ✓ describe blocks → describe with repeat → nested describe without repeat → test with repeat should repeat the number of times specified in the test @ repetition 1 of 2\n  ✓ describe blocks → describe with repeat → nested describe without repeat → test with repeat should repeat the number of times specified in the test @ repetition 2 of 2\n  ✓ describe blocks → describe with repeat → nested describe with repeat → test with no repeat should repeat the number of times specified in the parent describe block @ repetition 1 of 2\n  ✓ describe blocks → describe with repeat → nested describe with repeat → test with no repeat should repeat the number of times specified in the parent describe block @ repetition 2 of 2\n  ✓ describe blocks → describe with repeat → nested describe with repeat → test with repeat should repeat the number of times specified in the test @ repetition 1 of 2\n  ✓ describe blocks → describe with repeat → nested describe with repeat → test with repeat should repeat the number of times specified in the test @ repetition 2 of 2\n  ✓ matching describe blocks → describe block → it should repeat the number of times specified in the parent describe block @ repetition 1 of 3\n  ✓ matching describe blocks → describe block → it should repeat the number of times specified in the parent describe block @ repetition 2 of 3\n  ✓ matching describe blocks → describe block → it should repeat the number of times specified in the parent describe block @ repetition 3 of 3\n  ✓ matching describe blocks → describe block → should not repeat the number of times of the describe block with the same name\n\n   PASS  Tests\\Features\\ScopedDatasets\\Directory\\NestedDirectory1\\TestFileInNestedDirectoryWithDatasetsFile\n  ✓ uses dataset with (1)\n  ✓ uses dataset with (2)\n  ✓ uses dataset with (3)\n  ✓ uses dataset with (4)\n  ✓ uses dataset with (5)\n  ✓ uses dataset with ('ScopedDatasets/NestedDirector…ts.php')\n  ✓ the right dataset is taken\n\n   PASS  Tests\\Features\\ScopedDatasets\\Directory\\NestedDirectory2\\TestFileInNestedDirectory\n  ✓ uses dataset with (1)\n  ✓ uses dataset with (2)\n  ✓ uses dataset with (3)\n  ✓ uses dataset with (4)\n  ✓ uses dataset with (5)\n  ✓ uses dataset with ('ScopedDatasets/Datasets/Scoped.php')\n  ✓ the right dataset is taken\n\n   PASS  Tests\\Features\\ScopedDatasets\\Directory\\TestFileWithLocallyDefinedDataset\n  ✓ uses dataset with (1)\n  ✓ uses dataset with (2)\n  ✓ uses dataset with (3)\n  ✓ uses dataset with (4)\n  ✓ uses dataset with (5)\n  ✓ uses dataset with ('ScopedDatasets/ScopedDatasets.php')\n  ✓ the right dataset is taken\n\n   PASS  Tests\\Features\\ScopedDatasets\\Directory\\TestFileWithScopedDataset\n  ✓ uses dataset with (1)\n  ✓ uses dataset with (2)\n  ✓ uses dataset with (3)\n  ✓ uses dataset with (4)\n  ✓ uses dataset with (5)\n  ✓ uses dataset with ('ScopedDatasets/Datasets/Scoped.php')\n  ✓ the right dataset is taken\n\n   PASS  Tests\\Features\\ScopedDatasets\\TestFileOutOfScope\n  ✓ uses dataset with (1)\n  ✓ uses dataset with (2)\n  ✓ the right dataset is taken\n  ✓ it can see datasets defined in Pest.php file with ('A')\n  ✓ it can see datasets defined in Pest.php file with ('B')\n  ✓ Pest.php dataset is taken\n\n   PASS  Tests\\Features\\See\n  ✓ it can reference a specific class\n  ✓ it can reference a specific class method\n\n   WARN  Tests\\Features\\Skip\n  ✓ it do not skips\n  - it skips with truthy → 1\n  - it skips with truthy condition by default\n  - it skips with message → skipped because bar\n  - it skips with truthy closure condition\n  ✓ it do not skips with falsy closure condition\n  - it skips with condition and message → skipped because foo\n  - it skips when skip after assertion\n  - it can use something in the test case as a condition → This test was skipped\n  - it can user higher order callables and skip\n  - skip on describe → skipped tests → nested inside skipped block → it should not execute\n  - skip on describe → skipped tests → it should not execute\n  ✓ skip on describe → it should execute\n  - skip on beforeEach → skipped tests → nested inside skipped block → it should not execute\n  - skip on beforeEach → skipped tests → it should not execute\n  ✓ skip on beforeEach → it should execute\n  - matching describe with skip → describe block → it should not execute\n  ✓ matching describe with skip → describe block → it should execute a test in a describe block with the same name as a skipped describe block\n  ✓ matching describe with skip → it should execute\n  - matching describe with skip on beforeEach → describe block → it should not execute\n  ✓ matching describe with skip on beforeEach → describe block → it should execute a test in a describe block with the same name as a skipped describe block\n  ✓ matching describe with skip on beforeEach → it should execute\n  ✓ it does not skip after the describe block\n  - it can skip after the describe block\n\n   WARN  Tests\\Features\\SkipOnPhp\n  ✓ it can run on php version\n  ✓ it can run on specific php version\n  - it can skip on php versions depending on constraint → This test is skipped on PHP [>=7.4.0].\n\n   PASS  Tests\\Features\\Test\n  ✓ a test\n  ✓ higher order message test\n\n   PASS  Tests\\Features\\ThrowsNoExceptions\n  ✓ it allows access to the underlying expectNotToPerformAssertions method\n  ✓ it allows performing no expectations without being risky\n  ✓ a \"describe\" group of tests → it allows performing no expectations without being risky\n\n   PASS  Tests\\Features\\Ticket\n  ✓ it may be associated with an ticket #1, #2\n  ✓ nested → it may be associated with an ticket #1, #4, #5, #6, #3\n  // an note between an the ticket\n\n   PASS  Tests\\Features\\Todo - 29 todos\n  ↓ something todo later\n  ↓ something todo later chained\n  ↓ something todo later chained and with function body\n  ✓ it does something within a file with a todo\n  ↓ it may have an associated assignee [@nunomaduro]\n  ↓ it may have an associated issue #1\n  ↓ it may have an associated PR #1\n  ↓ it may have an associated note\n  // a note\n  ↓ todo on describe → todo block → nested inside todo block → it should not execute\n  ↓ todo on describe → todo block → nested inside todo block → it should set the note\n  // hi\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on describe → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on describe → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on describe → todo block → it should not execute\n  ✓ todo on describe → it should execute\n  ↓ todo on describe with matching name → describe block → it should not execute\n  ✓ todo on describe with matching name → describe block → it should execute a test in a describe block with the same name as a todo describe block\n  ✓ todo on describe with matching name → it should execute\n  ↓ todo on test after describe block\n  ↓ todo with note on test after describe block\n  // test note\n  ↓ todo on beforeEach → todo block → nested inside todo block → it should not execute\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test without a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note to a test with a todo\n  // describe note\n  ↓ todo on beforeEach → todo block → describe with note → it should apply the note as well as the note from the test\n  // describe note\n  // test note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test without a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes to a test with a todo\n  // describe note\n  // nested describe note\n  ↓ todo on beforeEach → todo block → describe with note → nested describe with note → it should apply all parent notes as well as the note from the test\n  // describe note\n  // nested describe note\n  // test note\n  ↓ todo on beforeEach → todo block → it should not execute\n  ✓ todo on beforeEach → it should execute\n  ↓ todo on test after describe block with beforeEach\n  ↓ todo with note on test after describe block with beforeEach\n  // test note\n\n   WARN  Tests\\Features\\Warnings\n  ! warning → Undefined property: P\\Tests\\Features\\Warnings::$fooqwdfwqdfqw\n  ! user warning → This is a warning description\n  ! a \"describe\" group of tests → user warning → This is a warning description\n\n   PASS  Tests\\Features\\Wip\n  ✓ it may have an associated assignee [@nunomaduro]\n  ✓ it may have an associated issue #1\n  ✓ it may have an associated PR #1\n  ✓ it may have an associated note\n  // a note\n\n   WARN  Tests\\Fixtures\\CollisionTest\n  - error\n  - success\n\n   PASS  Tests\\Fixtures\\DirectoryWithTests\\ExampleTest\n  ✓ it example 1\n\n   PASS  Tests\\Fixtures\\ExampleTest\n  ✓ it example 2\n\n   WARN  Tests\\Fixtures\\UnexpectedOutput\n  - output\n\n   PASS  Tests\\Helpers\\TestInHelpers\n  ✓ it executes tests in the Helpers directory\n\n   PASS  Tests\\Hooks\\AfterEachTest\n  ✓ nested → nested afterEach execution order\n  ✓ global afterEach execution order\n\n   PASS  Tests\\Hooks\\BeforeAllTest\n  ✓ it gets called before all tests 1 @ repetition 1 of 2\n  ✓ it gets called before all tests 1 @ repetition 2 of 2\n  ✓ it gets called before all tests 2\n\n   PASS  Tests\\Hooks\\BeforeEachTest\n  ✓ global beforeEach execution order\n\n   PASS  Tests\\PHPUnit\\CustomAffixes\\InvalidTestName\n  ✓ it runs file names like @#$%^&()-_=+.php\n\n   PASS  Tests\\PHPUnit\\CustomAffixes\\ATestWithSpaces\n  ✓ it runs file names like A Test With Spaces.php\n\n   PASS  Tests\\PHPUnit\\CustomAffixes\\AdditionalFileExtension\n  ✓ it runs file names like AdditionalFileExtension.spec.php\n\n   PASS  Tests\\PHPUnit\\CustomAffixes\\FolderWithAn\\ExampleTest\n  ✓ custom traits can be used\n  ✓ trait applied in this file\n\n   PASS  Tests\\PHPUnit\\CustomAffixes\\ManyExtensions\n  ✓ it runs file names like ManyExtensions.class.test.php\n\n   PASS  Tests\\PHPUnit\\CustomAffixes\\TestCaseWithQuotes\n  ✓ it runs file names like Test 'Case' With Quotes.php\n\n   PASS  Tests\\PHPUnit\\CustomAffixes\\kebabcasespec\n  ✓ it runs file names like kebab-case-spec.php\n\n   PASS  Tests\\PHPUnit\\CustomAffixes\\snakecasespec\n  ✓ it runs file names like snake_case_spec.php\n\n   PASS  Tests\\CustomTestCase\\ChildTest\n  ✓ override method\n\n   PASS  Tests\\CustomTestCase\\ExecutedTest\n  ✓ that gets executed\n\n   PASS  Tests\\CustomTestCase\\ParentTest\n  ✓ override method\n\n   PASS  Tests\\PHPUnit\\CustomTestCase\\UsesPerDirectory\n  ✓ closure was bound to CustomTestCase\n\n   PASS  Tests\\PHPUnit\\CustomTestCaseInSubFolders\\SubFolder\\SubFolder\\UsesPerSubDirectory\n  ✓ closure was bound to CustomTestCase\n\n   PASS  Tests\\PHPUnit\\CustomTestCaseInSubFolders\\SubFolder2\\UsesPerFile\n  ✓ custom traits can be used\n  ✓ trait applied in this file\n\n   PASS  Tests\\PHPUnit\\GlobPatternTests\\SubFolder\\InnerFolder\\UsesPerDirectoryAsPattern\n  ✓ closure was bound to CustomTestCase\n\n   PASS  Tests\\PHPUnit\\GlobPatternTests\\SubFolder2\\UsesPerFileAsPattern\n  ✓ closure was bound to CustomTestCase\n\n   PASS  Tests\\Playground\n  ✓ basic\n\n   PASS  Tests\\Plugins\\Coverage\n  ✓ compute comparable coverage with (0, 0)\n  ✓ compute comparable coverage with (0.5, 0.5)\n  ✓ compute comparable coverage with (1.0, 1.0)\n  ✓ compute comparable coverage with (32.51, 32.5)\n  ✓ compute comparable coverage with (32.12312321312312, 32.1)\n  ✓ compute comparable coverage with (32.53333333333333, 32.5)\n  ✓ compute comparable coverage with (32.57777771232132, 32.5)\n  ✓ compute comparable coverage with (100.0, 100.0)\n\n   PASS  Tests\\Plugins\\Traits\n  ✓ it allows global uses\n  ✓ it allows multiple global uses registered in the same path\n\n   PASS  Tests\\Unit\\Configuration\\In\n  ✓ it proxies to uses call\n\n   PASS  Tests\\Unit\\Configuration\\Theme\n  ✓ it creates a printer instance\n\n   PASS  Tests\\Unit\\Console\\Help\n  ✓ it outputs the help information when --help is used\n\n   PASS  Tests\\Unit\\DatasetsTests\n  ✓ it show only the names of named datasets in their description\n  ✓ it show the actual dataset of non-named datasets in their description\n  ✓ it show only the names of multiple named datasets in their description\n  ✓ it show the actual dataset of multiple non-named datasets in their description\n  ✓ it show the correct description for mixed named and not-named datasets\n  ✓ it shows the correct description for long texts with newlines\n  ✓ it shows the correct description for arrays with many elements\n  ✓ it shows the correct description of datasets with html\n\n   PASS  Tests\\Unit\\Expectations\\OppositeExpectation\n  ✓ it throw expectation failed exception with string argument\n  ✓ it throw expectation failed exception with array argument\n\n   PASS  Tests\\Unit\\Overrides\\ThrowableBuilder\n  ✓ collision editor can be added to the stack trace\n\n   PASS  Tests\\Unit\\Plugins\\Concerns\\HandleArguments\n  ✓ method hasArgument with ('--long-argument', true)\n  ✓ method hasArgument with ('-a', true)\n  ✓ method hasArgument with ('--with-equal-sign', true)\n  ✓ method hasArgument with ('someValue', true)\n  ✓ method hasArgument with ('--a', false)\n  ✓ method hasArgument with ('--undefined-argument', false)\n\n   PASS  Tests\\Unit\\Plugins\\Environment\n  ✓ environment is set to CI when --ci option is used\n  ✓ environment is set to Local when --ci option is not used\n\n   PASS  Tests\\Unit\\Plugins\\Retry\n  ✓ it orders by defects and stop on defects if when --retry is used\n\n   PASS  Tests\\Unit\\Preset\n  ✓ preset invalid name\n  ✓ preset → myFramework\n\n   PASS  Tests\\Unit\\Support\\Arr\n  ✓ last → it should return false for an empty arary\n  ✓ last → it should return the last element for an array with a single element\n  ✓ last → it should return the last element for an array without changing the internal pointer\n  ✓ last → it should return the last element for an associative array without changing the internal pointer\n  ✓ last → it should return the last element for an mixed key array without changing the internal pointer\n\n   PASS  Tests\\Unit\\Support\\Backtrace\n  ✓ it gets file name from called file\n\n   PASS  Tests\\Unit\\Support\\Container\n  ✓ it exists\n  ✓ it gets an instance\n  ✓ autowire\n  ✓ it creates an instance and resolves parameters\n  ✓ it creates an instance and resolves also sub parameters\n  ✓ it can resolve builtin value types\n  ✓ it cannot resolve a parameter without type\n\n   PASS  Tests\\Unit\\Support\\DatasetInfo\n  ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Datase…rs.php', true)\n  ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Datasets.php', false)\n  ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Featur…rs.php', true)\n  ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Featur…rs.php', false)\n  ✓ it can check if dataset is defined inside a Datasets directory with ('/var/www/project/tests/Featur…ts.php', false)\n  ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Datase…rs.php', false)\n  ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Datasets.php', true)\n  ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Featur…rs.php', false) #1\n  ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Featur…rs.php', false) #2\n  ✓ it can check if dataset is defined inside a Datasets.php file with ('/var/www/project/tests/Featur…ts.php', true)\n  ✓ it computes the dataset scope with ('/var/www/project/tests/Datase…rs.php', '/var/www/project/tests')\n  ✓ it computes the dataset scope with ('/var/www/project/tests/Datasets.php', '/var/www/project/tests')\n  ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…rs.php', '/var/www/project/tests/Features')\n  ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…rs.php', '/var/www/project/tests/Featur…rs.php') #1\n  ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…ts.php', '/var/www/project/tests/Features')\n  ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…rs.php', '/var/www/project/tests/Featur…ollers')\n  ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…rs.php', '/var/www/project/tests/Featur…rs.php') #2\n  ✓ it computes the dataset scope with ('/var/www/project/tests/Featur…ts.php', '/var/www/project/tests/Featur…ollers')\n\n   PASS  Tests\\Unit\\Support\\ExceptionTrace\n  ✓ it ensures the given closures reports the correct class name\n  ✓ it ensures the given closures reports the correct class name and suggests the [pest()] function\n\n   PASS  Tests\\Unit\\Support\\HigherOrderMessage\n  ✓ undefined method exceptions\n\n   PASS  Tests\\Unit\\Support\\Reflection\n  ✓ it gets file name from closure\n  ✓ it gets property values\n  ✓ it gets properties from classes\n  ✓ it gets methods from classes\n\n   PASS  Tests\\Unit\\Support\\Str\n  ✓ it evaluates the code with ('version()', '__pest_evaluable_version__')\n  ✓ it evaluates the code with ('version__ ', '__pest_evaluable_version_____')\n  ✓ it evaluates the code with ('version\\', '__pest_evaluable_version_')\n\n   PASS  Tests\\Unit\\TestName\n  ✓ it may start with P with ('P\\Tests\\BarTest', 'Tests\\BarTest')\n  ✓ it may start with P with ('P\\Packages\\Foo', 'Packages\\Foo')\n  ✓ it may start with P with ('P\\PPPackages\\Foo', 'PPPackages\\Foo')\n  ✓ it may start with P with ('PPPackages\\Foo', 'PPPackages\\Foo') #1\n  ✓ it may start with P with ('PPPackages\\Foo', 'PPPackages\\Foo') #2\n  ✓ test description\n  ✓ test_description\n  ✓ ふ+が+\n  ✓ ほげ\n  ✓ 卜竹弓一十山\n  ✓ アゴデヸ\n  ✓ !p8VrB\n  ✓ &xe6VeKWF#n4\n  ✓ %%HurHUnw7zM!\n  ✓ rundeliekend\n  ✓ g%%c!Jt9$fy#Kf\n  ✓ NRs*Gz2@hmB$W$BPD%%b2U%3P%z%apnwSX\n  ✓ ÀÄ¤{¼÷\n  ✓ ìèéàòç\n  ✓ زهراء المعادي\n  ✓ الجبيهه\n  ✓ الظهران\n  ✓ Каролин\n  ✓ অ্যান্টার্কটিকা\n  ✓ Frýdek-Místek\"\n  ✓ Allingåbro&\n  ✓ Κεντροαφρικανική Δημοκρατία\n  ✓ آذربایجان غربی\n  ✓ זימבבואה\n  ✓ Belišće\n  ✓ Գվատեմալա\n  ✓ パプアニューギニア\n  ✓ 富山県\n  ✓ Қарағанды\n  ✓ Қостанай\n  ✓ 안양시 동안구\n  ✓ Itālija\n  ✓ Honningsvåg\n  ✓ Águeda\n  ✓ Râșcani\n  ✓ Năsăud\n  ✓ Орехово-Зуево\n  ✓ Čereňany\n  ✓ Moravče\n  ✓ Šentjernej\n  ✓ Врање\n  ✓ Крушевац\n  ✓ Åkersberga\n  ✓ บอสเนียและเฮอร์เซโกวีนา\n  ✓ Birleşik Arap Emirlikleri\n  ✓ Німеччина\n  ✓ Nam Định\n  ✓ 呼和浩特\n  ✓ test /** with comment */ should do\n\n   PASS  Tests\\Unit\\TestSuite\n  ✓ it does not allow to add the same test description twice\n  ✓ it does not allow static closures\n  ✓ it alerts users about tests with arguments but no input\n  ✓ it can return an array of all test suite filenames\n\n   PASS  Tests\\Visual\\BeforeEachTestName\n  ✓ description\n  ✓ latest description\n\n   PASS  Tests\\Visual\\Collision\n  ✓ collision with ([''])\n\n   PASS  Tests\\Visual\\Help\n  ✓ visual snapshot of help command output\n\n   WARN  Tests\\Visual\\JUnit\n  ✓ junit output\n  - junit with parallel → Not working yet\n\n   PASS  Tests\\Visual\\Parallel\n  ✓ parallel\n  ✓ a parallel test can extend another test with same name\n\n   PASS  Tests\\Visual\\SingleTestOrDirectory\n  ✓ allows to run a single test\n  ✓ allows to run a directory\n  ✓ it disable decorating printer when colors is set to never\n\n   WARN  Tests\\Visual\\Success\n  - visual snapshot of test suite on success\n\n   WARN  Tests\\Visual\\TeamCity\n  - visual snapshot of team city with ('Failure.php')\n  - visual snapshot of team city with ('SuccessOnly.php')\n\n   WARN  Tests\\Visual\\Todo\n  - todos\n  - todos in parallel\n  - todo\n  - todo in parallel\n\n   WARN  Tests\\Visual\\Version\n  - visual snapshot of help command output\n\n   PASS  Testsexternal\\Features\\Expect\\toMatchSnapshot\n  ✓ pass with dataset with ('my-datas-set-value')\n  ✓ within describe → pass with dataset with ('my-datas-set-value')\n\n  Tests:    2 deprecated, 4 warnings, 5 incomplete, 2 notices, 39 todos, 35 skipped, 1188 passed (2813 assertions)"
  },
  {
    "path": "tests/.tests/Failure.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nit('can fail with comparison', function () {\n    expect(true)->toEqual(false);\n});\n\nit('can be ignored because of no assertions', function () {\n\n});\n\nit('can be ignored because it is skipped', function () {\n    expect(true)->toBeTrue();\n})->skip(\"this is why\");\n\nit('can fail', function () {\n    $this->fail(\"oh noo\");\n});\n\nit('throws exception', function () {\n    throw new Exception('test error');\n});\n\nit('is not done yet', function () {\n\n})->todo();\n\ntodo(\"build this one.\");\n\nit('is passing', function () {\n    expect(true)->toEqual(true);\n});\n\n"
  },
  {
    "path": "tests/.tests/SuccessOnly.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nit('can pass with comparison', function () {\n    expect(true)->toEqual(true);\n});\n\ntest('can also pass', function () {\n    expect(\"string\")->toBeString();\n});\n\ntest('can pass with dataset', function ($value) {\n    expect($value)->toEqual(true);\n})->with([true]);\n\ndescribe('block', function () {\n    test('can pass with dataset in describe block', function ($number) {\n        expect($number)->toBeInt();\n    })->with([1]);\n});\n"
  },
  {
    "path": "tests/Arch.php",
    "content": "<?php\n\nuse Pest\\Expectation;\n\narch()->preset()->php()->ignoring([\n    Expectation::class,\n    'debug_backtrace',\n    'var_export',\n    'xdebug_info',\n]);\n\narch()->preset()->strict()->ignoring([\n    'usleep',\n]);\n\narch()->preset()->security()->ignoring([\n    'eval',\n    'str_shuffle',\n    'exec',\n    'unserialize',\n    'extract',\n    'assert',\n]);\n\narch('globals')\n    ->expect(['dd', 'dump', 'ray', 'die', 'var_dump', 'sleep'])\n    ->not->toBeUsed()\n    ->ignoring(Expectation::class);\n\narch('contracts')\n    ->expect('Pest\\Contracts')\n    ->toOnlyUse([\n        'NunoMaduro\\Collision\\Contracts',\n        'Pest\\Factories\\TestCaseMethodFactory',\n        'Symfony\\Component\\Console',\n        'Pest\\Arch\\Contracts',\n        'Pest\\PendingCalls',\n    ])->toBeInterfaces();\n"
  },
  {
    "path": "tests/Autoload.php",
    "content": "<?php\n\nuse Pest\\Plugin;\n\ntrait PluginTrait\n{\n    public function assertPluginTraitGotRegistered(): void\n    {\n        $this->assertTrue(true);\n    }\n}\n\ntrait SecondPluginTrait\n{\n    public function assertSecondPluginTraitGotRegistered(): void\n    {\n        $this->assertTrue(true);\n    }\n}\n\nPlugin::uses(PluginTrait::class);\nPlugin::uses(SecondPluginTrait::class);\n\nfunction _assertThat()\n{\n    expect(true)->toBeTrue();\n}\n"
  },
  {
    "path": "tests/Datasets/Bound.php",
    "content": "<?php\n\ndataset('bound.closure', function () {\n    yield function () {\n        return 1;\n    };\n    yield function () {\n        return 2;\n    };\n});\n\ndataset('bound.array', [\n    function () {\n        return 1;\n    },\n    function () {\n        return 2;\n    },\n]);\n"
  },
  {
    "path": "tests/Datasets/Numbers.php",
    "content": "<?php\n\ndataset('numbers.closure', function () {\n    yield [1];\n    yield [2];\n});\n\ndataset('numbers.closure.wrapped', function () {\n    yield 1;\n    yield 2;\n});\n\ndataset('numbers.array', [[1], [2]]);\n\ndataset('numbers.array.wrapped', [1, 2]);\n\ndataset('numbers.generators.wrapped', function () {\n    yield from firstSetOfNumbers();\n    yield from secondSetOfNumbers();\n});\n\nfunction firstSetOfNumbers(): Generator\n{\n    yield 1;\n    yield 2;\n}\n\nfunction secondSetOfNumbers(): Generator\n{\n    yield 3;\n    yield 4;\n}\n"
  },
  {
    "path": "tests/Environments/Windows.php",
    "content": "<?php\n\ntest('global functions are loaded', function () {\n    expect(helper_returns_string())->toBeString();\n});\n"
  },
  {
    "path": "tests/Features/After.php",
    "content": "<?php\n\nbeforeEach(function () {\n    $this->count = 0;\n});\n\nafterEach(function () {\n    match ($this->name()) {\n        '__pest_evaluable_it_can_run_after_test' => expect($this->count)->toBe(1),\n        '__pest_evaluable_it_can_run_after_test_twice' => expect($this->count)->toBe(1),\n        '__pest_evaluable_it_does_not_run_when_skipped' => expect($this->count)->toBe(0),\n        '__pest_evaluable__something__→_it_does_not_run_when_skipped' => expect($this->count)->toBe(0),\n        '__pest_evaluable__something__→_it_can_run_after_test' => expect($this->count)->toBe(1),\n        '__pest_evaluable__something_2__→_it_can_run_after_test' => expect($this->count)->toBe(1),\n        '__pest_evaluable_high_order_test' => expect($this->count)->toBe(1),\n        '__pest_evaluable_high_order_test_with_skip' => expect($this->count)->toBe(0),\n        '__pest_evaluable_post__foo__→_defer_Closure_Object____→_expect_Closure_Object____→_toBe_1' => expect($this->count)->toBe(1),\n        default => $this->fail('Unexpected test name: '.$this->name()),\n    };\n\n    $this->count++;\n});\n\nit('can run after test', function () {\n    expect($this->count)->toBe(0);\n\n    $this->count++;\n})->after(function () {\n    expect($this->count)->toBe(2);\n\n    $this->count++;\n});\n\nit('can run after test twice', function () {\n    expect($this->count)->toBe(0);\n\n    $this->count++;\n})->after(function () {\n    expect($this->count)->toBe(2);\n\n    $this->count++;\n})->after(function () {\n    expect($this->count)->toBe(3);\n\n    $this->count++;\n});\n\nit('does not run when skipped', function () {\n    dd('This should not run 1');\n})->skip()->after(function () {\n    dd('This should not run 2');\n});\n\nafterEach(function () {\n    match ($this->name()) {\n        '__pest_evaluable_it_can_run_after_test' => expect($this->count)->toBe(3),\n        '__pest_evaluable_it_can_run_after_test_twice' => expect($this->count)->toBe(4),\n        '__pest_evaluable_it_does_not_run_when_skipped' => expect($this->count)->toBe(1),\n        '__pest_evaluable__something__→_it_does_not_run_when_skipped' => expect($this->count)->toBe(1),\n        '__pest_evaluable__something__→_it_can_run_after_test' => expect($this->count)->toBe(2),\n        '__pest_evaluable__something_2__→_it_can_run_after_test' => expect($this->count)->toBe(2),\n        '__pest_evaluable_high_order_test' => expect($this->count)->toBe(2),\n        '__pest_evaluable_high_order_test_with_skip' => expect($this->count)->toBe(1),\n        '__pest_evaluable_post__foo__→_defer_Closure_Object____→_expect_Closure_Object____→_toBe_1' => expect($this->count)->toBe(2),\n\n        default => $this->fail('Unexpected test name: '.$this->name()),\n\n    };\n\n    $this->count++;\n});\n\nafterEach(function () {\n    match ($this->name()) {\n        '__pest_evaluable_it_can_run_after_test' => expect($this->count)->toBe(4),\n        '__pest_evaluable_it_can_run_after_test_twice' => expect($this->count)->toBe(5),\n        '__pest_evaluable_it_does_not_run_when_skipped' => expect($this->count)->toBe(2),\n        '__pest_evaluable__something__→_it_does_not_run_when_skipped' => expect($this->count)->toBe(2),\n        '__pest_evaluable__something__→_it_can_run_after_test' => expect($this->count)->toBe(3),\n        '__pest_evaluable__something_2__→_it_can_run_after_test' => expect($this->count)->toBe(3),\n        '__pest_evaluable_high_order_test' => expect($this->count)->toBe(3),\n        '__pest_evaluable_high_order_test_with_skip' => expect($this->count)->toBe(2),\n        '__pest_evaluable_post__foo__→_defer_Closure_Object____→_expect_Closure_Object____→_toBe_1' => expect($this->count)->toBe(3),\n        default => $this->fail('Unexpected test name: '.$this->name()),\n    };\n\n    $this->count++;\n});\n\ndescribe('something', function () {\n    it('does not run when skipped', function () {\n        dd('This should not run 3');\n    })->skip()->after(function () {\n        dd('This should not run 4');\n    });\n\n    it('can run after test', function () {\n        expect($this->count)->toBe(0);\n\n        $this->count++;\n    })->after(function () {\n        expect($this->count)->toBe(5);\n\n        $this->count++;\n    })->after(function () {\n        expect($this->count)->toBe(6);\n\n        $this->count++;\n    });\n})->after(function () {\n    expect($this->count)->toBe(4);\n\n    $this->count++;\n});\n\ndescribe('something 2', function () {\n    it('can run after test', function () {\n        expect($this->count)->toBe(0);\n\n        $this->count++;\n    })->after(function () {\n        expect($this->count)->toBe(6);\n\n        $this->count++;\n    });\n})->after(function () {\n    expect($this->count)->toBe(4);\n\n    $this->count++;\n})->after(function () {\n    expect($this->count)->toBe(5);\n\n    $this->count++;\n});\n\ntest('high order test')\n    ->defer(fn () => $this->count++)\n    ->expect(fn () => $this->count)->toBe(1)\n    ->after(function () {\n        expect($this->count)->toBe(4);\n\n        $this->count++;\n    });\n\ntest('high order test with skip')\n    ->skip()\n    ->defer(fn () => $this->count++)\n    ->expect(fn () => $this->count)->toBe(1)\n    ->after(function () {\n        dd('This should not run 5');\n    });\n\npest()->use(Postable::class);\n\n/**\n * @return TestCase|TestCall|Gettable\n */\nfunction post(string $route)\n{\n    return test()->post($route);\n}\n\ntrait Postable\n{\n    /**\n     * @return TestCase|TestCall|Gettable\n     */\n    public function post(string $route)\n    {\n        expect($route)->not->toBeEmpty();\n\n        return $this;\n    }\n}\n\npost('foo')->defer(fn () => $this->count++)->expect(fn () => $this->count)->toBe(1);\n"
  },
  {
    "path": "tests/Features/AfterAll.php",
    "content": "<?php\n\n$file = __DIR__.DIRECTORY_SEPARATOR.'after-all-test';\n\nbeforeAll(function () use ($file) {\n    @unlink($file);\n});\n\nafterAll(function () use ($file) {\n    @unlink($file);\n});\n\ntest('deletes file after all', function () use ($file) {\n    file_put_contents($file, 'foo');\n    $this->assertFileExists($file);\n    register_shutdown_function(function () {\n        // $this->assertFileDoesNotExist($file);\n    });\n});\n"
  },
  {
    "path": "tests/Features/AfterEach.php",
    "content": "<?php\n\n$state = new stdClass;\n\nbeforeEach(function () use ($state) {\n    $this->state = $state;\n});\n\nafterEach(function () {\n    $this->state->bar = 1;\n});\n\nafterEach(function () {\n    unset($this->state->bar);\n});\n\nit('does not get executed before the test', function () {\n    expect($this->state)->not->toHaveProperty('bar');\n});\n\nit('gets executed after the test', function () {\n    expect($this->state)->toHaveProperty('bar');\n    expect($this->state->bar)->toBe(2);\n});\n\nafterEach(function () {\n    $this->state->bar = 2;\n});\n\ndescribe('outer', function () {\n    afterEach(function () {\n        $this->state->bar++;\n    });\n\n    describe('inner', function () {\n        afterEach(function () {\n            $this->state->bar++;\n        });\n\n        it('does not get executed before the test', function () {\n            expect($this->state)->toHaveProperty('bar');\n            expect($this->state->bar)->toBe(2);\n        });\n\n        it('should call all parent afterEach functions', function () {\n            expect($this->state)->toHaveProperty('bar');\n            expect($this->state->bar)->toBe(4);\n        });\n    });\n});\n\ndescribe('matching describe block names', function () {\n    afterEach(function () {\n        $this->state->foo = 1;\n    });\n\n    describe('outer', function () {\n        afterEach(function () {\n            $this->state->foo++;\n        });\n\n        describe('middle', function () {\n            afterEach(function () {\n                $this->state->foo++;\n            });\n\n            describe('inner', function () {\n                afterEach(function () {\n                    $this->state->foo++;\n                });\n\n                it('does not get executed before the test', function () {\n                    expect($this)->not->toHaveProperty('foo');\n                });\n\n                it('should call all parent afterEach functions', function () {\n                    expect($this->state->foo)->toBe(4);\n                });\n            });\n        });\n\n        describe('middle', function () {\n            it('does not get executed before the test', function () {\n                expect($this)->not->toHaveProperty('foo');\n            });\n\n            it('should not call afterEach functions for sibling describe blocks with the same name', function () {\n                expect($this)->not->toHaveProperty('foo');\n            });\n        });\n\n        describe('inner', function () {\n            it('does not get executed before the test', function () {\n                expect($this)->not->toHaveProperty('foo');\n            });\n\n            it('should not call afterEach functions for descendent of sibling describe blocks with the same name', function () {\n                expect($this)->not->toHaveProperty('foo');\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "tests/Features/Assignee.php",
    "content": "<?php\n\nbeforeEach(function () {\n    expect(true)->toBeTrue();\n})->assignee('nunomaduro');\n\nit('may be associated with an assignee', function () {\n    expect(true)->toBeTrue();\n})->assignee('taylorotwell');\n\ndescribe('nested', function () {\n    it('may be associated with an assignee', function () {\n        expect(true)->toBeTrue();\n    })->assignee('taylorotwell');\n})->assignee('nunomaduro')->note('an note between an the assignee')->assignee(['jamesbrooks', 'joedixon']);\n"
  },
  {
    "path": "tests/Features/BeforeAll.php",
    "content": "<?php\n\n$foo = new stdClass;\n$foo->bar = 0;\n\nbeforeAll(function () use ($foo) {\n    $foo->bar++;\n});\n\nit('gets executed before tests', function () use ($foo) {\n    expect($foo)->bar->toBe(1);\n\n    $foo->bar = 'changed';\n});\n\nit('do not get executed before each test', function () use ($foo) {\n    expect($foo)->bar->toBe('changed');\n});\n"
  },
  {
    "path": "tests/Features/BeforeEach.php",
    "content": "<?php\n\nbeforeEach(function () {\n    $this->bar = 2;\n});\n\nbeforeEach(function () {\n    $this->bar++;\n});\n\nbeforeEach(function () {\n    $this->bar = 0;\n});\n\nit('gets executed before each test', function () {\n    expect($this->bar)->toBe(1);\n\n    $this->bar = 'changed';\n});\n\nit('gets executed before each test once again', function () {\n    expect($this->bar)->toBe(1);\n});\n\nbeforeEach(function () {\n    $this->bar++;\n});\n\ndescribe('outer', function () {\n    beforeEach(function () {\n        $this->bar++;\n    });\n\n    describe('inner', function () {\n        beforeEach(function () {\n            $this->bar++;\n        });\n\n        it('should call all parent beforeEach functions', function () {\n            expect($this->bar)->toBe(3);\n        });\n    });\n});\n\ndescribe('with expectations', function () {\n    beforeEach()->expect(true)->toBeTrue();\n\n    describe('nested block', function () {\n        test('test', function () {});\n    });\n\n    test('test', function () {});\n});\n\ndescribe('matching describe block names', function () {\n    beforeEach(function () {\n        $this->foo = 1;\n    });\n\n    describe('outer', function () {\n        beforeEach(function () {\n            $this->foo++;\n        });\n\n        describe('middle', function () {\n            beforeEach(function () {\n                $this->foo++;\n            });\n\n            describe('inner', function () {\n                beforeEach(function () {\n                    $this->foo++;\n                });\n\n                it('should call all parent beforeEach functions', function () {\n                    expect($this->foo)->toBe(4);\n                });\n            });\n        });\n\n        describe('middle', function () {\n            it('should not call beforeEach functions for sibling describe blocks with the same name', function () {\n                expect($this->foo)->toBe(2);\n            });\n        });\n\n        describe('inner', function () {\n            it('should not call beforeEach functions for descendent of sibling describe blocks with the same name', function () {\n                expect($this->foo)->toBe(2);\n            });\n        });\n    });\n});\n\n$matchingNameCalls = 0;\ndescribe('matching name', function () use (&$matchingNameCalls) {\n    beforeEach(function () use (&$matchingNameCalls) {\n        $matchingNameCalls++;\n    });\n\n    it('should call the before each', function () use (&$matchingNameCalls) {\n        expect($matchingNameCalls)->toBe(1);\n    });\n});\n\ndescribe('matching name', function () use (&$matchingNameCalls) {\n    it('should not call the before each on the describe block with the same name', function () use (&$matchingNameCalls) {\n        expect($matchingNameCalls)->toBe(1);\n    });\n});\n\nbeforeEach(function () {\n    $this->baz = 1;\n});\n\ndescribe('called on all tests', function () {\n    beforeEach(function () {\n        $this->baz++;\n    });\n\n    test('beforeEach should be called', function () {\n        expect($this->baz)->toBe(2);\n    });\n\n    test('beforeEach should be called for all tests', function () {\n        expect($this->baz)->toBe(2);\n    });\n});\n"
  },
  {
    "path": "tests/Features/BeforeEachProxiesToTestCallWithExpectations.php",
    "content": "<?php\n\nbeforeEach()->expect(true)->toBeTrue();\n\ntest('runs 1', function () {\n    // This test did performs assertions...\n});\n\ntest('runs 2', function () {\n    // This test did performs assertions...\n});\n\ntest('runs 3', function () {\n    // This test did performs assertions...\n});\n"
  },
  {
    "path": "tests/Features/BeforeEachProxiesToTestCallWithSkip.php",
    "content": "<?php\n\nbeforeEach()->skip();\n\ntest('does not run 1', function () {\n    $this->fail('This test should not run');\n});\n\ntest('does not run 2', function () {\n    $this->fail('This test should not run');\n});\n\ntest('does not run 3', function () {\n    $this->fail('This test should not run');\n});\n"
  },
  {
    "path": "tests/Features/BeforeEachProxiesToTestCallWithTodo.php",
    "content": "<?php\n\nbeforeEach()->todo();\n\ntest('is marked as todo 1', function () {\n    $this->fail('This test should not run');\n});\n\ntest('is marked as todo 2', function () {\n    $this->fail('This test should not run');\n});\n\ntest('is marked as todo 3');\n\ntest()->shouldBeMarkedAsTodo();\n"
  },
  {
    "path": "tests/Features/Coverage.php",
    "content": "<?php\n\nuse Pest\\Plugins\\Coverage as CoveragePlugin;\nuse Pest\\Support\\Coverage;\nuse Symfony\\Component\\Console\\Output\\ConsoleOutput;\n\nit('has plugin')->assertTrue(class_exists(CoveragePlugin::class));\n\nit('adds coverage if --coverage exist', function () {\n    $plugin = new CoveragePlugin(new ConsoleOutput);\n\n    expect($plugin->coverage)->toBeFalse();\n    $arguments = $plugin->handleArguments([]);\n    expect($arguments)->toEqual([])\n        ->and($plugin->coverage)->toBeFalse();\n\n    $arguments = $plugin->handleArguments(['--coverage']);\n    expect($arguments)->toEqual(['--coverage-php', Coverage::getPath()])\n        ->and($plugin->coverage)->toBeTrue();\n})->skip(! Coverage::isAvailable() || ! function_exists('xdebug_info') || ! in_array('coverage', xdebug_info('mode'), true), 'Coverage is not available');\n\nit('adds coverage if --min exist', function () {\n    $plugin = new CoveragePlugin(new ConsoleOutput);\n    expect($plugin->coverageMin)->toEqual(0.0)\n        ->and($plugin->coverage)->toBeFalse();\n\n    $plugin->handleArguments([]);\n    expect($plugin->coverageMin)->toEqual(0.0);\n\n    $plugin->handleArguments(['--min=2']);\n    expect($plugin->coverageMin)->toEqual(2.0);\n\n    $plugin->handleArguments(['--min=2.4']);\n    expect($plugin->coverageMin)->toEqual(2.4);\n});\n\nit('generates coverage based on file input', function () {\n    expect(Coverage::getMissingCoverage(new class\n    {\n        public function lineCoverageData(): array\n        {\n            return [\n                1 => ['foo'],\n                2 => ['bar'],\n                4 => [],\n                5 => [],\n                6 => [],\n                7 => null,\n                100 => null,\n                101 => ['foo'],\n                102 => [],\n            ];\n        }\n    }))->toEqual([\n        '4..6', '102',\n    ]);\n});\n"
  },
  {
    "path": "tests/Features/Covers/ClassCoverage.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\Attributes\\CoversClass;\nuse Tests\\Fixtures\\Covers\\CoversClass1;\n\ncovers([CoversClass1::class]);\n\nit('uses the correct PHPUnit attribute for class', function () {\n    $attributes = (new ReflectionClass($this))->getAttributes();\n\n    expect($attributes[1]->getName())->toBe(CoversClass::class);\n    expect($attributes[1]->getArguments()[0])->toBe('Tests\\Fixtures\\Covers\\CoversClass1');\n});\n"
  },
  {
    "path": "tests/Features/Covers/ExceptionHandling.php",
    "content": "<?php\n\nuse Pest\\PendingCalls\\TestCall;\nuse Pest\\TestSuite;\n\nit('throws exception if no class nor method has been found', function () {\n    $testCall = new TestCall(TestSuite::getInstance(), 'filename', 'description', fn () => 'closure');\n\n    $testCall->covers('fakeName');\n})->throws(InvalidArgumentException::class, 'No class, trait or method named \"fakeName\" has been found.');\n"
  },
  {
    "path": "tests/Features/Covers/FunctionCoverage.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\Attributes\\CoversFunction;\n\nfunction testCoversFunction() {}\n\nit('uses the correct PHPUnit attribute for function', function () {\n    $attributes = (new ReflectionClass($this))->getAttributes();\n\n    expect($attributes[1]->getName())->toBe(CoversFunction::class);\n    expect($attributes[1]->getArguments()[0])->toBe('testCoversFunction');\n})->coversFunction('testCoversFunction');\n"
  },
  {
    "path": "tests/Features/Covers/GuessCoverage.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\Attributes\\CoversClass;\nuse PHPUnit\\Framework\\Attributes\\CoversFunction;\nuse Tests\\Fixtures\\Covers\\CoversClass3;\n\nfunction testCoversFunction2() {}\n\nit('guesses if the given argument is a class or function', function () {\n    $attributes = (new ReflectionClass($this))->getAttributes();\n\n    expect($attributes[1]->getName())->toBe(CoversClass::class);\n    expect($attributes[1]->getArguments()[0])->toBe(CoversClass3::class);\n\n    expect($attributes[2]->getName())->toBe(CoversFunction::class);\n    expect($attributes[2]->getArguments()[0])->toBe('testCoversFunction2');\n})->covers(CoversClass3::class, 'testCoversFunction2');\n"
  },
  {
    "path": "tests/Features/Covers/TraitCoverage.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\Attributes\\CoversTrait as PHPUnitCoversTrait;\nuse Tests\\Fixtures\\Covers\\CoversTrait;\n\nit('uses the correct PHPUnit attribute for trait', function () {\n    $attributes = (new ReflectionClass($this))->getAttributes();\n\n    expect($attributes[1]->getName())->toBe(PHPUnitCoversTrait::class);\n    expect($attributes[1]->getArguments()[0])->toBe('Tests\\Fixtures\\Covers\\CoversTrait');\n})->coversTrait(CoversTrait::class);\n"
  },
  {
    "path": "tests/Features/DatasetsTests.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\DatasetAlreadyExists;\nuse Pest\\Exceptions\\DatasetDoesNotExist;\nuse Pest\\Plugin;\nuse Pest\\Repositories\\DatasetsRepository;\n\nbeforeEach(function () {\n    $this->foo = 'bar';\n});\n\nit('throws exception if dataset does not exist', function () {\n    $this->expectException(DatasetDoesNotExist::class);\n    $this->expectExceptionMessage(\"A dataset with the name `first` does not exist. You can create it using `dataset('first', ['a', 'b']);`.\");\n\n    DatasetsRepository::resolve(['first'], __FILE__);\n});\n\nit('throws exception if dataset already exist', function () {\n    DatasetsRepository::set('second', [[]], __DIR__);\n    $this->expectException(DatasetAlreadyExists::class);\n    $this->expectExceptionMessage('A dataset with the name `second` already exists in scope ['.__DIR__.'].');\n    DatasetsRepository::set('second', [[]], __DIR__);\n});\n\nit('sets closures', function () {\n    DatasetsRepository::set('foo', function () {\n        yield [1];\n    }, __DIR__);\n\n    expect(DatasetsRepository::resolve(['foo'], __FILE__))->toBe(['(1)' => [1]]);\n});\n\nit('sets arrays', function () {\n    DatasetsRepository::set('bar', [[2]], __DIR__);\n\n    expect(DatasetsRepository::resolve(['bar'], __FILE__))->toBe(['(2)' => [2]]);\n});\n\nit('gets bound to test case object', function ($value) {\n    $this->assertTrue(true);\n})->with([['a'], ['b']]);\n\ntest('it truncates the description', function () {\n    expect(true)->toBe(true);\n    // it gets tested by the integration test\n})->with([str_repeat('Fooo', 10)]);\n\n$state = new stdClass;\n$state->text = '';\n\n$datasets = [[1], [2]];\n\ntest('lazy datasets', function ($text) use ($state, $datasets) {\n    $state->text .= $text;\n\n    expect(in_array([$text], $datasets))->toBe(true);\n})->with($datasets);\n\ntest('lazy datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('12');\n});\n\ntest('interpolated :dataset lazy datasets', function ($text) {\n    expect(true)->toBeTrue();\n})->with($datasets);\n\n$state->text = '';\n\ntest('eager datasets', function ($text) use ($state, $datasets) {\n    $state->text .= $text;\n    expect($datasets)->toContain([$text]);\n})->with(function () use ($datasets) {\n    return $datasets;\n});\n\ntest('eager datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('1212');\n});\n\ntest('lazy registered datasets', function ($text) use ($state, $datasets) {\n    $state->text .= $text;\n    expect($datasets)->toContain([$text]);\n})->with('numbers.array');\n\ntest('lazy registered datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('121212');\n});\n\ntest('eager registered datasets', function ($text) use ($state, $datasets) {\n    $state->text .= $text;\n    expect($datasets)->toContain([$text]);\n})->with('numbers.closure');\n\ntest('eager registered datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('12121212');\n});\n\ntest('eager wrapped registered datasets', function ($text) use ($state, $datasets) {\n    $state->text .= $text;\n    expect($datasets)->toContain([$text]);\n})->with('numbers.closure.wrapped');\n\ntest('eager registered wrapped datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('1212121212');\n});\n\ntest('named datasets', function ($text) use ($state, $datasets) {\n    $state->text .= $text;\n    expect($datasets)->toContain([$text]);\n})->with([\n    'one' => [1],\n    'two' => [2],\n]);\n\ntest('interpolated :dataset named datasets', function ($text) {\n    expect(true)->toBeTrue();\n})->with([\n    'one' => [1],\n    'two' => [2],\n]);\n\ntest('named datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('121212121212');\n});\n\nclass Bar\n{\n    public $name = 1;\n}\n\n$namedDatasets = [\n    new Bar,\n];\n\ntest('lazy named datasets', function ($text) {\n    expect(true)->toBeTrue();\n})->with($namedDatasets);\n\n$counter = 0;\n\nit('creates unique test case names', function (string $name, Plugin $plugin, bool $bool) use (&$counter) {\n    expect(true)->toBeTrue();\n    $counter++;\n})->with([\n    ['Name 1', new Plugin, true],\n    ['Name 1', new Plugin, true],\n    ['Name 1', new Plugin, false],\n    ['Name 2', new Plugin, false],\n    ['Name 2', new Plugin, true],\n    ['Name 1', new Plugin, true],\n]);\n\nit('creates unique test case names - count', function () use (&$counter) {\n    expect($counter)->toBe(6);\n});\n\n$datasets_a = [[1], [2]];\n$datasets_b = [[3], [4]];\n\ntest('lazy multiple datasets', function ($text_a, $text_b) use ($state, $datasets_a, $datasets_b) {\n    $state->text .= $text_a.$text_b;\n    expect($datasets_a)->toContain([$text_a]);\n    expect($datasets_b)->toContain([$text_b]);\n})->with($datasets_a, $datasets_b);\n\ntest('lazy multiple datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('12121212121213142324');\n});\n\n$state->text = '';\n\ntest('eager multiple datasets', function ($text_a, $text_b) use ($state, $datasets_a, $datasets_b) {\n    $state->text .= $text_a.$text_b;\n    expect($datasets_a)->toContain([$text_a]);\n    expect($datasets_b)->toContain([$text_b]);\n})->with(function () use ($datasets_a) {\n    return $datasets_a;\n})->with(function () use ($datasets_b) {\n    return $datasets_b;\n});\n\ntest('eager multiple datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('1212121212121314232413142324');\n});\n\ntest('lazy registered multiple datasets', function ($text_a, $text_b) use ($state, $datasets) {\n    $state->text .= $text_a.$text_b;\n    expect($datasets)->toContain([$text_a]);\n    expect($datasets)->toContain([$text_b]);\n})->with('numbers.array')->with('numbers.array');\n\ntest('lazy registered multiple datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('121212121212131423241314232411122122');\n});\n\ntest('eager registered multiple datasets', function ($text_a, $text_b) use ($state, $datasets) {\n    $state->text .= $text_a.$text_b;\n    expect($datasets)->toContain([$text_a]);\n    expect($datasets)->toContain([$text_b]);\n})->with('numbers.array')->with('numbers.closure');\n\ntest('eager registered multiple datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('12121212121213142324131423241112212211122122');\n});\n\ntest('eager wrapped registered multiple datasets', function ($text_a, $text_b) use ($state, $datasets) {\n    $state->text .= $text_a.$text_b;\n    expect($datasets)->toContain([$text_a]);\n    expect($datasets)->toContain([$text_b]);\n})->with('numbers.closure.wrapped')->with('numbers.closure');\n\ntest('eager wrapped registered multiple datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('1212121212121314232413142324111221221112212211122122');\n});\n\ntest('named multiple datasets', function ($text_a, $text_b) use ($state, $datasets_a, $datasets_b) {\n    $state->text .= $text_a.$text_b;\n    expect($datasets_a)->toContain([$text_a]);\n    expect($datasets_b)->toContain([$text_b]);\n})->with([\n    'one' => [1],\n    'two' => [2],\n])->with([\n    'three' => [3],\n    'four' => [4],\n]);\n\ntest('named multiple datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('121212121212131423241314232411122122111221221112212213142324');\n});\n\ntest('more than two datasets', function ($text_a, $text_b, $text_c) use ($state, $datasets_a, $datasets_b) {\n    $state->text .= $text_a.$text_b.$text_c;\n    expect($datasets_a)->toContain([$text_a]);\n    expect($datasets_b)->toContain([$text_b]);\n    expect([5, 6])->toContain($text_c);\n})->with($datasets_a, $datasets_b)->with([5, 6]);\n\ntest('more than two datasets did the job right', function () use ($state) {\n    expect($state->text)->toBe('121212121212131423241314232411122122111221221112212213142324135136145146235236245246');\n});\n\n$wrapped_generator_state = new stdClass;\n$wrapped_generator_state->text = '';\n$wrapped_generator_function_datasets = [1, 2, 3, 4];\n\ntest(\n    'eager registered wrapped datasets with Generator functions',\n    function (int $text) use (\n        $wrapped_generator_state,\n        $wrapped_generator_function_datasets\n    ) {\n        $wrapped_generator_state->text .= $text;\n        expect(in_array($text, $wrapped_generator_function_datasets))->toBe(true);\n    }\n)->with('numbers.generators.wrapped');\n\ntest('eager registered wrapped datasets with Generator functions did the job right', function () use ($wrapped_generator_state) {\n    expect($wrapped_generator_state->text)->toBe('1234');\n});\n\ntest('eager registered wrapped datasets with Generator functions display description', function ($wrapped_generator_state_with_description) {\n    expect($wrapped_generator_state_with_description)->not->toBeEmpty();\n})->with(function () {\n    yield 'taylor' => 'taylor@laravel.com';\n    yield 'james' => 'james@laravel.com';\n});\n\nit('can resolve a dataset after the test case is available', function ($result) {\n    expect($result)->toBe('bar');\n})->with([\n    function () {\n        return $this->foo;\n    },\n    [\n        function () {\n            return $this->foo;\n        },\n    ],\n]);\n\nit('can resolve a dataset after the test case is available with multiple datasets', function (string $result, string $result2) {\n    expect($result)->toBe('bar');\n})->with([\n    function () {\n        return $this->foo;\n    },\n    [\n        function () {\n            return $this->foo;\n        },\n    ],\n], [\n    function () {\n        return $this->foo;\n    },\n    [\n        function () {\n            return $this->foo;\n        },\n    ],\n]);\n\nit('can resolve a dataset after the test case is available with shared yield sets', function ($result) {\n    expect($result)->toBeInt()->toBeLessThan(3);\n})->with('bound.closure');\n\nit('can resolve a dataset after the test case is available with shared array sets', function ($result) {\n    expect($result)->toBeInt()->toBeLessThan(3);\n})->with('bound.array');\n\nit('resolves a potential bound dataset logically', function ($foo, $bar) {\n    expect($foo)->toBe('foo');\n    expect($bar())->toBe('bar');\n})->with([\n    [\n        'foo',\n        function () {\n            return 'bar';\n        },\n    ], // This should be passed as a closure because we've passed multiple arguments\n]);\n\nit('resolves a potential bound dataset logically even when the closure comes first', function ($foo, $bar) {\n    expect($foo())->toBe('foo');\n    expect($bar)->toBe('bar');\n})->with([\n    [\n        function () {\n            return 'foo';\n        }, 'bar',\n    ], // This should be passed as a closure because we've passed multiple arguments\n]);\n\nit('will not resolve a closure if it is type hinted as a closure', function (Closure $data) {\n    expect($data())->toBeString();\n})->with([\n    function () {\n        return 'foo';\n    },\n    function () {\n        return 'bar';\n    },\n]);\n\nit('will not resolve a closure if it is type hinted as a callable', function (callable $data) {\n    expect($data())->toBeString();\n})->with([\n    function () {\n        return 'foo';\n    },\n    function () {\n        return 'bar';\n    },\n]);\n\nit('can correctly resolve a bound dataset that returns an array', function (array $data) {\n    expect($data)->toBe(['foo', 'bar', 'baz']);\n})->with([\n    function () {\n        return ['foo', 'bar', 'baz'];\n    },\n]);\n\nit('can correctly resolve a bound dataset that returns an array but wants to be spread', function (string $foo, string $bar, string $baz) {\n    expect([$foo, $bar, $baz])->toBe(['foo', 'bar', 'baz']);\n})->with([\n    function () {\n        return ['foo', 'bar', 'baz'];\n    },\n]);\n\ntodo('forbids to define tests in Datasets dirs and Datasets.php files');\n\ndataset('greeting-string', [\n    'formal' => 'Evening',\n    'informal' => 'yo',\n]);\n\nit('may be used with high order')\n    ->with('greeting-string')\n    ->expect(fn (string $greeting) => $greeting)\n    ->throwsNoExceptions();\n\ndataset('greeting-bound', [\n    'formal' => fn () => 'Evening',\n    'informal' => fn () => 'yo',\n]);\n\nit('may be used with high order even when bound')\n    ->with('greeting-bound')\n    ->expect(fn (string $greeting) => $greeting)\n    ->throws(InvalidArgumentException::class);\n\ndescribe('with on nested describe', function () {\n    describe('nested', function () {\n        test('before inner describe block', function (...$args) {\n            expect($args)->toBe([1]);\n        });\n\n        describe('describe', function () {\n            it('should include the with value from all parent describe blocks', function (...$args) {\n                expect($args)->toBe([1, 2]);\n            });\n\n            test('should include the with value from all parent describe blocks and the test', function (...$args) {\n                expect($args)->toBe([1, 2, 3]);\n            })->with([3]);\n        })->with([2]);\n\n        test('after inner describe block', function (...$args) {\n            expect($args)->toBe([1]);\n        });\n    })->with([1]);\n});\n\ndescribe('matching describe block names', function () {\n    describe('outer', function () {\n        test('before inner describe block', function (...$args) {\n            expect($args)->toBe([1]);\n        });\n\n        describe('inner', function () {\n            it('should include the with value from all parent describe blocks', function (...$args) {\n                expect($args)->toBe([1, 2]);\n            });\n\n            test('should include the with value from all parent describe blocks and the test', function (...$args) {\n                expect($args)->toBe([1, 2, 3]);\n            })->with([3]);\n        })->with([2]);\n\n        describe('inner', function () {\n            it('should not include the value from the other describe block with the same name', function (...$args) {\n                expect($args)->toBe([1]);\n            });\n        });\n\n        test('after inner describe block', function (...$args) {\n            expect($args)->toBe([1]);\n        });\n    })->with([1]);\n});\n\ntest('after describe block', function (...$args) {\n    expect($args)->toBe([5]);\n})->with([5]);\n\nit('may be used with high order after describe block')\n    ->with('greeting-string')\n    ->expect(fn (string $greeting) => $greeting)\n    ->throwsNoExceptions();\n\ndataset('after-describe', ['after']);\n\ntest('after describe block with named dataset', function (...$args) {\n    expect($args)->toBe(['after']);\n})->with('after-describe');\n"
  },
  {
    "path": "tests/Features/Depends.php",
    "content": "<?php\n\n$runCounter = 0;\n\ntest('first', function () use (&$runCounter) {\n    expect(true)->toBeTrue();\n    $runCounter++;\n\n    return 'first';\n});\n\ntest('second', function () use (&$runCounter) {\n    expect(true)->toBeTrue();\n    $runCounter++;\n\n    return 'second';\n});\n\ntest('depends', function () {\n    expect(func_get_args())->toBe(['first', 'second']);\n})->depends('first', 'second');\n\ntest('depends with ...params', function (string ...$params) {\n    expect(func_get_args())->toBe($params);\n})->depends('first', 'second');\n\ntest('depends with defined arguments', function (string $first, string $second) {\n    expect($first)->toBe('first');\n    expect($second)->toBe('second');\n})->depends('first', 'second');\n\ntest('depends run test only once', function () use (&$runCounter) {\n    expect($runCounter)->toBe(2);\n})->depends('first', 'second');\n\n// Regression tests. See https://github.com/pestphp/pest/pull/216\nit('asserts true is true')->assertTrue(true);\ntest('depends works with the correct test name')->assertTrue(true)->depends('it asserts true is true');\n\ndescribe('describe block', function () {\n    $runCounter = 0;\n\n    test('first in describe', function () use (&$runCounter) {\n        $runCounter++;\n        expect(true)->toBeTrue();\n    });\n\n    test('second in describe', function () use (&$runCounter) {\n        expect($runCounter)->toBe(1);\n        $runCounter++;\n    })->depends('first in describe');\n\n    test('third in describe', function () use (&$runCounter) {\n        expect($runCounter)->toBe(2);\n    })->depends('second in describe');\n\n    describe('nested describe', function () {\n        $runCounter = 0;\n\n        test('first in nested describe', function () use (&$runCounter) {\n            $runCounter++;\n            expect(true)->toBeTrue();\n        });\n\n        test('second in nested describe', function () use (&$runCounter) {\n            expect($runCounter)->toBe(1);\n            $runCounter++;\n        })->depends('first in nested describe');\n\n        test('third in nested describe', function () use (&$runCounter) {\n            expect($runCounter)->toBe(2);\n        })->depends('second in nested describe');\n    });\n});\n\ntest('depends on test after describe block', function () use (&$runCounter) {\n    expect($runCounter)->toBe(2);\n})->depends('first', 'second');\n"
  },
  {
    "path": "tests/Features/DependsInheritance.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\TestCase;\n\nclass InheritanceTest extends TestCase\n{\n    public function foo()\n    {\n        return 'bar';\n    }\n}\n\npest()->extend(InheritanceTest::class);\n\nit('is a test', function () {\n    expect(true)->toBeTrue();\n});\n\nit('uses correct parent class', function () {\n    expect(get_parent_class($this))->toEqual(InheritanceTest::class);\n    expect($this->foo())->toEqual('bar');\n})->depends('it is a test');\n"
  },
  {
    "path": "tests/Features/Deprecated.php",
    "content": "<?php\n\ntest('deprecated', function () {\n    str_contains(null, null);\n\n    expect(true)->toBeTrue();\n});\n\ntest('user deprecated', function () {\n    trigger_error('Since foo 1.0: This is a deprecation description', \\E_USER_DEPRECATED);\n\n    expect(true)->toBeTrue();\n});\n"
  },
  {
    "path": "tests/Features/Describe.php",
    "content": "<?php\n\nbeforeEach(fn () => $this->count = 1);\n\ntest('before each', function () {\n    expect($this->count)->toBe(1);\n});\n\ndescribe('hooks', function () {\n    beforeEach(function () {\n        $this->count++;\n    });\n\n    test('value', function () {\n        expect($this->count)->toBe(2);\n        $this->count++;\n    });\n\n    afterEach(function () {\n        expect($this->count)->toBe(3);\n    });\n});\n\ndescribe('hooks in different orders', function () {\n    beforeEach(function () {\n        $this->count++;\n    });\n\n    test('value', function () {\n        expect($this->count)->toBe(3);\n        $this->count++;\n    });\n\n    afterEach(function () {\n        expect($this->count)->toBe(4);\n    });\n\n    beforeEach(function () {\n        $this->count++;\n    });\n});\n\ntest('todo')->todo()->shouldNotRun();\n\ntest('previous describable before each does not get applied here', function () {\n    expect($this->count)->toBe(1);\n});\n\ndescribe('todo on hook', function () {\n    beforeEach()->todo();\n\n    test('should not fail')->shouldNotRun();\n    test('should run')->expect(true)->toBeTrue();\n});\n\ndescribe('todo on describe', function () {\n    test('should not fail')->shouldNotRun();\n\n    test('should run')->expect(true)->toBeTrue();\n})->todo();\n\ntest('should run')->expect(true)->toBeTrue();\n\ntest('with', fn ($foo) => expect($foo)->toBe(1))->with([1]);\n\ndescribe('with on hook', function () {\n    beforeEach()->with([2]);\n\n    test('value', function ($foo) {\n        expect($foo)->toBe(2);\n    });\n});\n\ndescribe('with on describe', function () {\n    test('value', function ($foo) {\n        expect($foo)->toBe(3);\n    });\n})->with([3]);\n\ndescribe('depends on describe', function () {\n    test('foo', function () {\n        expect('foo')->toBe('foo');\n    });\n\n    test('bar', function () {\n        expect('bar')->toBe('bar');\n    })->depends('foo');\n});\n\ndescribe('depends on describe using with', function () {\n    test('foo', function ($foo) {\n        expect($foo)->toBe(3);\n    });\n\n    test('bar', function ($foo) {\n        expect($foo + $foo)->toBe(6);\n    })->depends('foo');\n})->with([3]);\n\ndescribe('with test after describe', function () {\n    beforeEach(function () {\n        $this->count++;\n    });\n\n    describe('foo', function () {});\n\n    it('should run the before each', function () {\n        expect($this->count)->toBe(2);\n    });\n});\n"
  },
  {
    "path": "tests/Features/DescriptionLess.php",
    "content": "<?php\n\nuse Pest\\PendingCalls\\TestCall;\nuse PHPUnit\\Framework\\TestCase;\n\npest()->use(Gettable::class);\n\n/**\n * @return TestCase|TestCall|Gettable\n */\nfunction get(string $route)\n{\n    return test()->get($route);\n}\n\ntrait Gettable\n{\n    /**\n     * @return TestCase|TestCall|Gettable\n     */\n    public function get(string $route)\n    {\n        expect($route)->not->toBeEmpty();\n\n        return $this;\n    }\n}\n\nget('foo'); // not incomplete because closure is created...\nget('foo')->get('bar')->expect(true)->toBeTrue();\nget('foo')->expect(true)->toBeTrue();\n\ndescribe('a \"describe\" group of tests', function () {\n    get('foo'); // not incomplete because closure is created...\n    get('foo')->get('bar')->expect(true)->toBeTrue();\n    get('foo')->expect(true)->toBeTrue();\n});\n"
  },
  {
    "path": "tests/Features/Done.php",
    "content": "<?php\n\nit('may have an associated assignee', function () {\n    expect(true)->toBeTrue();\n})->done(assignee: 'nunomaduro');\n\nit('may have an associated issue', function () {\n    expect(true)->toBeTrue();\n})->done(issue: 1);\n\nit('may have an associated PR', function () {\n    expect(true)->toBeTrue();\n})->done(pr: 1);\n\nit('may have an associated note', function () {\n    expect(true)->toBeTrue();\n})->done(note: 'a note');\n"
  },
  {
    "path": "tests/Features/Exceptions.php",
    "content": "<?php\n\nit('gives access the the underlying expectException', function () {\n    $this->expectException(InvalidArgumentException::class);\n\n    throw new InvalidArgumentException;\n});\n\nit('catch exceptions', function () {\n    throw new Exception('Something bad happened');\n})->throws(Exception::class);\n\nit('catch exceptions and messages', function () {\n    throw new Exception('Something bad happened');\n})->throws(Exception::class, 'Something bad happened');\n\nit('catch exceptions, messages and code', function () {\n    throw new Exception('Something bad happened', 1);\n})->throws(Exception::class, 'Something bad happened', 1);\n\nit('can just define the message', function () {\n    throw new Exception('Something bad happened');\n})->throws('Something bad happened');\n\nit('can just define the code', function () {\n    throw new Exception('Something bad happened', 1);\n})->throws(1);\n\nit('not catch exceptions if given condition is false', function () {\n    $this->assertTrue(true);\n})->throwsIf(false, Exception::class);\n\nit('catch exceptions if given condition is true', function () {\n    throw new Exception('Something bad happened');\n})->throwsIf(function () {\n    return true;\n}, Exception::class);\n\nit('catch exceptions and messages if given condition is true', function () {\n    throw new Exception('Something bad happened');\n})->throwsIf(true, Exception::class, 'Something bad happened');\n\nit('catch exceptions, messages and code if given condition is true', function () {\n    throw new Exception('Something bad happened', 1);\n})->throwsIf(true, Exception::class, 'Something bad happened', 1);\n\nit('can just define the message if given condition is true', function () {\n    throw new Exception('Something bad happened');\n})->throwsIf(true, 'Something bad happened');\n\nit('can just define the code if given condition is true', function () {\n    throw new Exception('Something bad happened', 1);\n})->throwsIf(true, 1);\n\nit('can just define the message if given condition is 1', function () {\n    throw new Exception('Something bad happened');\n})->throwsIf(1, 'Something bad happened');\n\nit('can just define the code if given condition is 1', function () {\n    throw new Exception('Something bad happened', 1);\n})->throwsIf(1, 1);\n\nit('not catch exceptions if given condition is true', function () {\n    $this->assertTrue(true);\n})->throwsUnless(true, Exception::class);\n\nit('catch exceptions if given condition is false', function () {\n    throw new Exception('Something bad happened');\n})->throwsUnless(function () {\n    return false;\n}, Exception::class);\n\nit('catch exceptions and messages if given condition is false', function () {\n    throw new Exception('Something bad happened');\n})->throwsUnless(false, Exception::class, 'Something bad happened');\n\nit('catch exceptions, messages and code if given condition is false', function () {\n    throw new Exception('Something bad happened', 1);\n})->throwsUnless(false, Exception::class, 'Something bad happened', 1);\n\nit('can just define the message if given condition is false', function () {\n    throw new Exception('Something bad happened');\n})->throwsUnless(false, 'Something bad happened');\n\nit('can just define the code if given condition is false', function () {\n    throw new Exception('Something bad happened', 1);\n})->throwsUnless(false, 1);\n\nit('can just define the message if given condition is 0', function () {\n    throw new Exception('Something bad happened');\n})->throwsUnless(0, 'Something bad happened');\n\nit('can just define the code if given condition is 0', function () {\n    throw new Exception('Something bad happened', 1);\n})->throwsUnless(0, 1);\n"
  },
  {
    "path": "tests/Features/Expect/HigherOrder/methods.php",
    "content": "<?php\n\nit('can access methods', function () {\n    expect(new HasMethods)\n        ->name()->toBeString()->toEqual('Has Methods');\n});\n\nit('can access multiple methods', function () {\n    expect(new HasMethods)\n        ->name()->toBeString()->toEqual('Has Methods')\n        ->quantity()->toBeInt()->toEqual(20);\n});\n\nit('works with not', function () {\n    expect(new HasMethods)\n        ->name()->not->toEqual('world')->toEqual('Has Methods')\n        ->quantity()->toEqual(20)->not()->toEqual('bar')->not->toBeNull;\n});\n\nit('can accept arguments', function () {\n    expect(new HasMethods)\n        ->multiply(5, 4)->toBeInt->toEqual(20);\n});\n\nit('works with each', function () {\n    expect(new HasMethods)\n        ->attributes()->toBeArray->each->not()->toBeNull\n        ->attributes()->each(function ($attribute) {\n            $attribute->not->toBeNull();\n        });\n});\n\nit('works inside of each', function () {\n    expect(new HasMethods)\n        ->books()->each(function ($book) {\n            $book->title->not->toBeNull->cost->toBeGreaterThan(19);\n        });\n});\n\nit('works with sequence', function () {\n    expect(new HasMethods)\n        ->books()->sequence(\n            function ($book) {\n                $book->title->toEqual('Foo')->cost->toEqual(20);\n            },\n            function ($book) {\n                $book->title->toEqual('Bar')->cost->toEqual(30);\n            },\n        );\n});\n\nit('can compose complex expectations', function () {\n    expect(new HasMethods)\n        ->toBeObject()\n        ->name()->toEqual('Has Methods')->not()->toEqual('bar')\n        ->quantity()->not->toEqual('world')->toEqual(20)->toBeInt\n        ->multiply(3, 4)->not->toBeString->toEqual(12)\n        ->attributes()->toBeArray()\n        ->books()->toBeArray->each->not->toBeEmpty\n        ->books()->sequence(\n            function ($book) {\n                $book->title->toEqual('Foo')->cost->toEqual(20);\n            },\n            function ($book) {\n                $book->title->toEqual('Bar')->cost->toEqual(30);\n            },\n        );\n});\n\nit('can handle nested method calls', function () {\n    expect(new HasMethods)\n        ->newInstance()->newInstance()->name()->toEqual('Has Methods')->toBeString()\n        ->newInstance()->name()->toEqual('Has Methods')->not->toBeInt\n        ->name()->toEqual('Has Methods')\n        ->books()->each->toBeArray();\n});\n\nit('works with higher order tests')\n    ->expect(new HasMethods)\n    ->newInstance()->newInstance()->name()->toEqual('Has Methods')->toBeString()\n    ->newInstance()->name()->toEqual('Has Methods')->not->toBeArray\n    ->name()->toEqual('Has Methods')\n    ->books()->each->toBeArray;\n\nit('can use the scoped method to lock into the given level for expectations', function () {\n    expect(new HasMethods)\n        ->attributes()->scoped(fn ($attributes) => $attributes\n        ->name->toBe('Has Methods')\n        ->quantity->toBe(20)\n        )\n        ->name()->toBeString()->toBe('Has Methods')\n        ->newInstance()->newInstance()->scoped(fn ($instance) => $instance\n        ->name()->toBe('Has Methods')\n        ->quantity()->toBe(20)\n        ->attributes()->scoped(fn ($attributes) => $attributes\n        ->name->toBe('Has Methods')\n        ->quantity->toBe(20)\n        )\n        );\n});\n\nit('works consistently with the json expectation method', function () {\n    expect(new HasMethods)\n        ->jsonString()->json()->id->toBe(1)\n        ->jsonString()->json()->name->toBe('Has Methods')->toBeString()\n        ->jsonString()->json()->quantity->toBe(20)->toBeInt();\n});\n\nclass HasMethods\n{\n    public function jsonString(): string\n    {\n        return '{ \"id\": 1, \"name\": \"Has Methods\", \"quantity\": 20 }';\n    }\n\n    public function name()\n    {\n        return 'Has Methods';\n    }\n\n    public function quantity()\n    {\n        return 20;\n    }\n\n    public function multiply($x, $y)\n    {\n        return $x * $y;\n    }\n\n    public function attributes()\n    {\n        return [\n            'name' => $this->name(),\n            'quantity' => $this->quantity(),\n        ];\n    }\n\n    public function books()\n    {\n        return [\n            [\n                'title' => 'Foo',\n                'cost' => 20,\n            ],\n            [\n                'title' => 'Bar',\n                'cost' => 30,\n            ],\n        ];\n    }\n\n    public function newInstance()\n    {\n        return new static;\n    }\n}\n"
  },
  {
    "path": "tests/Features/Expect/HigherOrder/methodsAndProperties.php",
    "content": "<?php\n\nit('can access methods and properties', function () {\n    expect(new HasMethodsAndProperties)\n        ->name->toEqual('Has Methods and Properties')->not()->toEqual('bar')\n        ->multiply(3, 4)->not->toBeString->toEqual(12)\n        ->posts->each(function ($post) {\n            $post->is_published->toBeTrue;\n        })->books()->toBeArray()\n        ->posts->toBeArray->each->not->toBeEmpty\n        ->books()->sequence(\n            function ($book) {\n                $book->title->toEqual('Foo')->cost->toEqual(20);\n            },\n            function ($book) {\n                $book->title->toEqual('Bar')->cost->toEqual(30);\n            },\n        );\n});\n\nit('can handle nested methods and properties', function () {\n    expect(new HasMethodsAndProperties)\n        ->meta->foo->bar->toBeString()->toEqual('baz')->not->toBeInt\n        ->newInstance()->meta->foo->toBeArray()\n        ->newInstance()->multiply(2, 2)->toEqual(4)->not->toEqual(5)\n        ->newInstance()->books()->toBeArray();\n});\n\nit('works with higher order tests')\n    ->expect(new HasMethodsAndProperties)\n    ->meta->foo->bar->toBeString()->toEqual('baz')->not->toBeInt\n    ->newInstance()->meta->foo->toBeArray\n    ->newInstance()->multiply(2, 2)->toEqual(4)->not->toEqual(5)\n    ->newInstance()->books()->toBeArray();\n\nit('can start a new higher order expectation using the and syntax', function () {\n    expect(new HasMethodsAndProperties)\n        ->toBeInstanceOf(HasMethodsAndProperties::class)\n        ->meta->toBeArray\n        ->and(['foo' => 'bar'])\n        ->toBeArray()\n        ->foo->toEqual('bar');\n\n    expect(static::getCount())->toEqual(4);\n});\n\nit('can start a new higher order expectation using the and syntax in higher order tests')\n    ->expect(new HasMethodsAndProperties)\n    ->toBeInstanceOf(HasMethodsAndProperties::class)\n    ->meta->toBeArray\n    ->and(['foo' => 'bar'])\n    ->toBeArray()\n    ->foo->toEqual('bar');\n\nit('can start a new higher order expectation using the and syntax without nesting expectations', function () {\n    expect(new HasMethodsAndProperties)\n        ->toBeInstanceOf(HasMethodsAndProperties::class)\n        ->meta\n        ->sequence(\n            function ($value, $key) {\n                $value->toBeArray()->and($key)->toBe('foo');\n            },\n        );\n});\n\nclass HasMethodsAndProperties\n{\n    public $name = 'Has Methods and Properties';\n\n    public $meta = ['foo' => ['bar' => 'baz']];\n\n    public $posts = [\n        [\n            'is_published' => true,\n            'title' => 'Foo',\n        ],\n        [\n            'is_published' => true,\n            'title' => 'Bar',\n        ],\n    ];\n\n    public function books()\n    {\n        return [\n            [\n                'title' => 'Foo',\n                'cost' => 20,\n            ],\n            [\n                'title' => 'Bar',\n                'cost' => 30,\n            ],\n        ];\n    }\n\n    public function multiply($x, $y)\n    {\n        return $x * $y;\n    }\n\n    public function newInstance()\n    {\n        return new static;\n    }\n}\n"
  },
  {
    "path": "tests/Features/Expect/HigherOrder/properties.php",
    "content": "<?php\n\nit('allows properties to be accessed from the value', function () {\n    expect(['foo' => 1])->foo->toBeInt()->toEqual(1);\n});\n\nit('can access multiple properties from the value', function () {\n    expect(['foo' => 'bar', 'hello' => 'world'])\n        ->foo->toBeString()->toEqual('bar')\n        ->hello->toBeString()->toEqual('world');\n});\n\nit('works with not', function () {\n    expect(['foo' => 'bar', 'hello' => 'world'])\n        ->foo->not->not->toEqual('bar')\n        ->foo->not->toEqual('world')->toEqual('bar')\n        ->hello->toEqual('world')->not()->toEqual('bar')->not->toBeNull;\n});\n\nit('works with each', function () {\n    expect(['numbers' => [1, 2, 3, 4], 'words' => ['hey', 'there']])\n        ->numbers->toEqual([1, 2, 3, 4])->each->toBeInt->toBeLessThan(5)\n        ->words->each(function ($word) {\n            $word->toBeString()->not->toBeInt();\n        });\n});\n\nit('works inside of each', function () {\n    expect(['books' => [['title' => 'Foo', 'cost' => 20], ['title' => 'Bar', 'cost' => 30]]])\n        ->books->each(function ($book) {\n            $book->title->not->toBeNull->cost->toBeGreaterThan(19);\n        });\n});\n\nit('works with sequence', function () {\n    expect(['books' => [['title' => 'Foo', 'cost' => 20], ['title' => 'Bar', 'cost' => 30]]])\n        ->books->sequence(\n            function ($book) {\n                $book->title->toEqual('Foo')->cost->toEqual(20);\n            },\n            function ($book) {\n                $book->title->toEqual('Bar')->cost->toEqual(30);\n            },\n        );\n});\n\nit('can compose complex expectations', function () {\n    expect(['foo' => 'bar', 'numbers' => [1, 2, 3, 4]])\n        ->toContain('bar')->toBeArray()\n        ->numbers->toEqual([1, 2, 3, 4])->not()->toEqual('bar')->each->toBeInt\n        ->foo->not->toEqual('world')->toEqual('bar')\n        ->numbers->toBeArray();\n});\n\nit('works with objects', function () {\n    expect(new HasProperties)\n        ->name->toEqual('foo')->not->toEqual('world')\n        ->posts->toHaveCount(2)->each(function ($post) {\n            $post->is_published->toBeTrue();\n        })\n        ->posts->sequence(\n            function ($post) {\n                $post->title->toEqual('Foo');\n            },\n            function ($post) {\n                $post->title->toEqual('Bar');\n            },\n        );\n});\n\nit('works with nested properties', function () {\n    expect(new HasProperties)\n        ->nested->foo->bar->toBeString()->toEqual('baz')\n        ->posts->toBeArray()->toHaveCount(2);\n});\n\nit('works with higher order tests')\n    ->expect(new HasProperties)\n    ->nested->foo->bar->toBeString()->toEqual('baz')\n    ->posts->toBeArray()->toHaveCount(2);\n\nclass HasProperties\n{\n    public $name = 'foo';\n\n    public $posts = [\n        [\n            'is_published' => true,\n            'title' => 'Foo',\n        ],\n        [\n            'is_published' => true,\n            'title' => 'Bar',\n        ],\n    ];\n\n    public $nested = [\n        'foo' => ['bar' => 'baz'],\n    ];\n}\n"
  },
  {
    "path": "tests/Features/Expect/each.php",
    "content": "<?php\n\nuse Pest\\Expectation;\n\ntest('an exception is thrown if the the type is not iterable', function () {\n    expect('Foobar')->each()->toEqual('Foobar');\n})->throws(BadMethodCallException::class, 'Expectation value is not iterable.');\n\nit('expects on each item', function () {\n    expect([1, 1, 1])\n        ->each()\n        ->toEqual(1);\n\n    expect(static::getCount())->toBe(3); // + 1 assertion\n\n    expect([1, 1, 1])\n        ->each\n        ->toEqual(1);\n\n    expect(static::getCount())->toBe(7);\n});\n\nit('chains expectations on each item', function () {\n    expect([1, 1, 1])\n        ->each()\n        ->toBeInt()\n        ->toEqual(1);\n\n    expect(static::getCount())->toBe(6); // + 1 assertion\n\n    expect([2, 2, 2])\n        ->each\n        ->toBeInt\n        ->toEqual(2);\n\n    expect(static::getCount())->toBe(13);\n});\n\ntest('opposite expectations on each item', function () {\n    expect([1, 2, 3])\n        ->each()\n        ->not()\n        ->toEqual(4);\n\n    expect(static::getCount())->toBe(3);\n\n    expect([1, 2, 3])\n        ->each()\n        ->not->toBeString;\n\n    expect(static::getCount())->toBe(7);\n});\n\ntest('chained opposite and non-opposite expectations', function () {\n    expect([1, 2, 3])\n        ->each()\n        ->not()\n        ->toEqual(4)\n        ->toBeInt();\n\n    expect(static::getCount())->toBe(6);\n});\n\nit('can add expectations via \"and\"', function () {\n    expect([1, 2, 3])\n        ->each()\n        ->toBeInt // + 3\n        ->and([4, 5, 6])\n        ->each\n        ->toBeLessThan(7) // + 3\n        ->not\n        ->toBeLessThan(3)\n        ->toBeGreaterThan(3) // + 3\n        ->and('Hello World')\n        ->toBeString // + 1\n        ->toEqual('Hello World'); // + 1\n\n    expect(static::getCount())->toBe(14);\n});\n\nit('accepts callables', function () {\n    expect([1, 2, 3])->each(function ($number) {\n        expect($number)->toBeInstanceOf(Expectation::class);\n        expect($number->value)->toBeInt();\n        $number->toBeInt->not->toBeString;\n    });\n\n    expect(static::getCount())->toBe(12);\n});\n\nit('passes the key of the current item to callables', function () {\n    expect([1, 2, 3])->each(function ($number, $key) {\n        expect($key)->toBeInt();\n    });\n\n    expect(static::getCount())->toBe(3);\n});\n"
  },
  {
    "path": "tests/Features/Expect/extend.php",
    "content": "<?php\n\nexpect()->extend('toBeAMacroExpectation', function () {\n    $this->toBeTrue();\n\n    return $this;\n});\n\nexpect()->extend('toBeAMacroExpectationWithArguments', function (bool $value) {\n    $this->toBe($value);\n\n    return $this;\n});\n\nit('macros true is true', function () {\n    expect(true)->toBeAMacroExpectation();\n});\n\nit('macros false is not true', function () {\n    expect(false)->not->toBeAMacroExpectation();\n});\n\nit('macros true is true with argument', function () {\n    expect(true)->toBeAMacroExpectationWithArguments(true);\n});\n\nit('macros false is not true with argument', function () {\n    expect(false)->not->toBeAMacroExpectationWithArguments(true);\n});\n"
  },
  {
    "path": "tests/Features/Expect/json.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('it properly parses json string', function () {\n    expect('{\"name\":\"Nuno\"}')\n        ->json()\n        ->name\n        ->toBe('Nuno');\n});\n\ntest('fails with broken json string', function () {\n    expect('{\":\"Nuno\"}')->json();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/matchExpectation.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    $this->matched = null;\n});\n\nit('pass', function () {\n    expect('baz')\n        ->match('foo', [\n            'bar' => function ($value) {\n                $this->matched = 'bar';\n\n                return $value->toEqual('bar');\n            },\n            'foo' => function ($value) {\n                $this->matched = 'baz';\n\n                return $value->toEqual('baz');\n            },\n        ]\n        )\n        ->toEqual($this->matched);\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('failures', function () {\n    expect(true)\n        ->match('foo', [\n            'bar' => function ($value) {\n                return $value->toBeTrue();\n            },\n            'foo' => function ($value) {\n                return $value->toBeFalse();\n            },\n        ]\n        );\n})->throws(ExpectationFailedException::class, 'true is false');\n\nit('runs with truthy', function () {\n    expect('foo')\n        ->match(1, [\n            'bar' => function ($value) {\n                $this->matched = 'bar';\n\n                return $value->toEqual('bar');\n            },\n            true => function ($value) {\n                $this->matched = 'foo';\n\n                return $value->toEqual('foo');\n            },\n        ]\n        )\n        ->toEqual($this->matched);\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('runs with falsy', function () {\n    expect('foo')\n        ->match(false, [\n            'bar' => function ($value) {\n                $this->matched = 'bar';\n\n                return $value->toEqual('bar');\n            },\n            false => function ($value) {\n                $this->matched = 'foo';\n\n                return $value->toEqual('foo');\n            },\n        ]\n        )\n        ->toEqual($this->matched);\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('runs with truthy closure condition', function () {\n    expect('foo')\n        ->match(\n            function () {\n                return '1';\n            }, [\n                'bar' => function ($value) {\n                    $this->matched = 'bar';\n\n                    return $value->toEqual('bar');\n                },\n                true => function ($value) {\n                    $this->matched = 'foo';\n\n                    return $value->toEqual('foo');\n                },\n            ]\n        )\n        ->toEqual($this->matched);\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('runs with falsy closure condition', function () {\n    expect('foo')\n        ->match(\n            function () {\n                return '0';\n            }, [\n                'bar' => function ($value) {\n                    $this->matched = 'bar';\n\n                    return $value->toEqual('bar');\n                },\n                false => function ($value) {\n                    $this->matched = 'foo';\n\n                    return $value->toEqual('foo');\n                },\n            ]\n        )\n        ->toEqual($this->matched);\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('can be passed non-callable values', function () {\n    expect('foo')\n        ->match('pest', [\n            'bar' => 'foo',\n            'pest' => 'baz',\n        ]\n        );\n})->throws(ExpectationFailedException::class, 'two strings are equal');\n\nit('fails with unhandled match', function () {\n    expect('foo')->match('bar', []);\n})->throws(ExpectationFailedException::class, 'Unhandled match value.');\n\nit('can be used in higher order tests')\n    ->expect(true)\n    ->match(\n        function () {\n            return true;\n        }, [\n            false => function ($value) {\n                return $value->toBeFalse();\n            },\n            true => function ($value) {\n                return $value->toBeTrue();\n            },\n        ]\n    );\n"
  },
  {
    "path": "tests/Features/Expect/not.php",
    "content": "<?php\n\ntest('not property calls', function () {\n    expect(true)\n        ->toBeTrue()\n        ->not()->toBeFalse()\n        ->not->toBeFalse\n        ->and(false)\n        ->toBeFalse();\n});\n"
  },
  {
    "path": "tests/Features/Expect/pipes.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nuse function PHPUnit\\Framework\\assertEquals;\nuse function PHPUnit\\Framework\\assertEqualsIgnoringCase;\nuse function PHPUnit\\Framework\\assertInstanceOf;\nuse function PHPUnit\\Framework\\assertSame;\n\nclass Number\n{\n    public function __construct(\n        public int $value\n    ) {\n        // ..\n    }\n}\n\nclass Char\n{\n    public function __construct(\n        public string $value\n    ) {\n        // ..\n    }\n}\n\nclass Symbol\n{\n    public function __construct(\n        public string $value\n    ) {\n        // ..\n    }\n}\n\nclass State\n{\n    public array $runCount = [];\n\n    public array $appliedCount = [];\n\n    public function __construct()\n    {\n        $this->reset();\n    }\n\n    public function reset(): void\n    {\n        $this->appliedCount = $this->runCount = [\n            'char' => 0,\n            'number' => 0,\n            'wildcard' => 0,\n            'symbol' => 0,\n        ];\n    }\n}\n\n$state = new State;\n\n/*\n * Overrides toBe to assert two Characters are the same\n */\nexpect()->pipe('toBe', function ($next, $expected) use ($state) {\n    $state->runCount['char']++;\n\n    if ($this->value instanceof Char) {\n        $state->appliedCount['char']++;\n\n        assertInstanceOf(Char::class, $expected);\n        assertEquals($this->value->value, $expected->value);\n\n        // returning nothing stops pipeline execution\n        return;\n    }\n\n    // calling $next(); let the pipeline to keep running\n    $next();\n});\n\n/*\n * Overrides toBe to assert two Number objects are the same\n */\nexpect()->intercept('toBe', Number::class, function ($expected) use ($state) {\n    $state->runCount['number']++;\n    $state->appliedCount['number']++;\n\n    assertInstanceOf(Number::class, $expected);\n    assertEquals($this->value->value, $expected->value);\n});\n\n/*\n * Overrides toBe to assert all integers are allowed if value is a wildcard (*)\n */\nexpect()->intercept('toBe', fn ($value, $expected) => $value === '*' && is_numeric($expected), function ($expected) use ($state) {\n    $state->runCount['wildcard']++;\n    $state->appliedCount['wildcard']++;\n});\n\n/*\n * Overrides toBe to assert to Symbols are the same\n */\nexpect()->pipe('toBe', function ($next, $expected) use ($state) {\n    $state->runCount['symbol']++;\n\n    if ($this->value instanceof Symbol) {\n        $state->appliedCount['symbol']++;\n        assertInstanceOf(Symbol::class, $expected);\n        assertEquals($this->value->value, $expected->value);\n\n        return;\n    }\n\n    $next();\n});\n\n/*\n * Overrides toBe to allow ignoring case when checking strings\n */\nexpect()->intercept('toBe', fn ($value) => is_string($value), function ($expected, $ignoreCase = false) {\n    if ($ignoreCase) {\n        assertEqualsIgnoringCase($expected, $this->value);\n    } else {\n        assertSame($expected, $this->value);\n    }\n});\n\ntest('pipe is applied and can stop pipeline', function () use ($state) {\n    $char = new Char('A');\n\n    $state->reset();\n\n    expect($char)->toBe(new Char('A'))\n        ->and($state)\n        ->runCount->toMatchArray([\n            'char' => 1,\n            'number' => 0,\n            'wildcard' => 0,\n            'symbol' => 0,\n        ])\n        ->appliedCount->toMatchArray([\n            'char' => 1,\n            'number' => 0,\n            'wildcard' => 0,\n            'symbol' => 0,\n        ]);\n});\n\ntest('pipe is run and can let the pipeline keep going', function () use ($state) {\n    $state->reset();\n\n    expect(3)->toBe(3)\n        ->and($state)\n        ->runCount->toMatchArray([\n            'char' => 1,\n            'number' => 0,\n            'wildcard' => 0,\n            'symbol' => 1,\n        ])\n        ->appliedCount->toMatchArray([\n            'char' => 0,\n            'number' => 0,\n            'wildcard' => 0,\n            'symbol' => 0,\n        ]);\n});\n\ntest('pipe works with negated expectation', function () use ($state) {\n    $char = new Char('A');\n\n    $state->reset();\n\n    expect($char)->not->toBe(new Char('B'))\n        ->and($state)\n        ->runCount->toMatchArray([\n            'char' => 1,\n            'number' => 0,\n            'wildcard' => 0,\n            'symbol' => 0,\n        ])\n        ->appliedCount->toMatchArray([\n            'char' => 1,\n            'number' => 0,\n            'wildcard' => 0,\n            'symbol' => 0,\n        ]);\n});\n\ntest('interceptor is applied', function () use ($state) {\n    $number = new Number(1);\n\n    $state->reset();\n\n    expect($number)->toBe(new Number(1))\n        ->and($state)\n        ->runCount->toHaveKey('number', 1)\n        ->appliedCount->toHaveKey('number', 1);\n});\n\ntest('interceptor stops the pipeline', function () use ($state) {\n    $number = new Number(1);\n\n    $state->reset();\n\n    expect($number)->toBe(new Number(1))\n        ->and($state)\n        ->runCount->toMatchArray([\n            'char' => 1,\n            'number' => 1,\n            'wildcard' => 0,\n            'symbol' => 0,\n        ])\n        ->appliedCount->toMatchArray([\n            'char' => 0,\n            'number' => 1,\n            'wildcard' => 0,\n            'symbol' => 0,\n        ]);\n});\n\ntest('interceptor is called only when filter is met', function () use ($state) {\n    $state->reset();\n\n    expect(1)->toBe(1)\n        ->and($state)\n        ->runCount->toHaveKey('number', 0)\n        ->appliedCount->toHaveKey('number', 0);\n});\n\ntest('interceptor can be filtered with a closure', function () use ($state) {\n    $state->reset();\n\n    expect('*')->toBe(1)\n        ->and($state)\n        ->runCount->toHaveKey('wildcard', 1)\n        ->appliedCount->toHaveKey('wildcard', 1);\n});\n\ntest('interceptor can be filter the expected parameter as well', function () use ($state) {\n    $state->reset();\n\n    expect('*')->toBe('*')\n        ->and($state)\n        ->runCount->toHaveKey('wildcard', 0)\n        ->appliedCount->toHaveKey('wildcard', 0);\n});\n\ntest('interceptor works with negated expectation', function () {\n    $char = new Number(1);\n\n    expect($char)->not->toBe(new Char('B'));\n});\n\ntest('intercept can add new parameters to the expectation', function () {\n    $ignoreCase = true;\n\n    expect('Foo')->toBe('foo', $ignoreCase);\n});\n"
  },
  {
    "path": "tests/Features/Expect/ray.php",
    "content": "<?php\n\ntest('ray calls do not fail when ray is not installed', function () {\n    expect(true)->ray()->toBe(true);\n});\n"
  },
  {
    "path": "tests/Features/Expect/sequence.php",
    "content": "<?php\n\ntest('an exception is thrown if the the type is not iterable', function () {\n    expect('Foobar')->each->sequence();\n})->throws(BadMethodCallException::class, 'Expectation value is not iterable.');\n\ntest('an exception is thrown if there are no expectations', function () {\n    expect(['Foobar'])->sequence();\n})->throws(InvalidArgumentException::class, 'No sequence expectations defined.');\n\ntest('allows for sequences of checks to be run on iterable data', function () {\n    expect([1, 2, 3])\n        ->sequence(\n            function ($expectation) {\n                $expectation->toBeInt()->toEqual(1);\n            },\n            function ($expectation) {\n                $expectation->toBeInt()->toEqual(2);\n            },\n            function ($expectation) {\n                $expectation->toBeInt()->toEqual(3);\n            },\n        );\n\n    expect(static::getCount())->toBe(6);\n});\n\ntest('loops back to the start if it runs out of sequence items', function () {\n    expect([1, 2, 3, 1, 2, 3, 1, 2])\n        ->sequence(\n            function ($expectation) {\n                $expectation->toBeInt()->toEqual(1);\n            },\n            function ($expectation) {\n                $expectation->toBeInt()->toEqual(2);\n            },\n            function ($expectation) {\n                $expectation->toBeInt()->toEqual(3);\n            },\n        );\n\n    expect(static::getCount())->toBe(16);\n});\n\ntest('fails if the number of iterable items is less than the number of expectations', function () {\n    expect([1, 2])\n        ->sequence(\n            function ($expectation) {\n                $expectation->toBeInt()->toEqual(1);\n            },\n            function ($expectation) {\n                $expectation->toBeInt()->toEqual(2);\n            },\n            function ($expectation) {\n                $expectation->toBeInt()->toEqual(3);\n            },\n        );\n})->throws(OutOfRangeException::class, 'Sequence expectations are more than the iterable items.');\n\ntest('it works with associative arrays', function () {\n    expect(['foo' => 'bar', 'baz' => 'boom'])\n        ->sequence(\n            function ($expectation, $key) {\n                $expectation->toEqual('bar');\n                $key->toEqual('foo');\n            },\n            function ($expectation, $key) {\n                $expectation->toEqual('boom');\n                $key->toEqual('baz');\n            },\n        );\n});\n\ntest('it can be passed non-callable values', function () {\n    expect(['foo', 'bar', 'baz'])->sequence('foo', 'bar', 'baz');\n\n    expect(static::getCount())->toBe(3);\n});\n\ntest('it can be passed a mixture of value types', function () {\n    expect(['foo', 'bar', 'baz'])->sequence(\n        'foo',\n        function ($expectation) {\n            $expectation->toEqual('bar')->toBeString();\n        },\n        'baz'\n    );\n\n    expect(static::getCount())->toBe(4);\n});\n\ntest('it works with traversables', function () {\n    $generator = (function () {\n        yield 'one' => (fn () => yield from [1, 2, 3])();\n        yield 'two' => (fn () => yield from [4, 5, 6])();\n        yield 'three' => (fn () => yield from [7, 8, 9])();\n    })();\n\n    expect($generator)->sequence(\n        fn ($value, $key) => $key->toBe('one')\n            ->and($value)\n            ->toBeInstanceOf(Generator::class)\n            ->sequence(1, 2, 3),\n        fn ($value, $key) => $key->toBe('two')\n            ->and($value)\n            ->toBeInstanceOf(Generator::class)\n            ->sequence(4, 5, 6),\n        fn ($value, $key) => $key->toBe('three')\n            ->and($value)\n            ->toBeInstanceOf(Generator::class)\n            ->sequence(7, 8, 9),\n    );\n});\n"
  },
  {
    "path": "tests/Features/Expect/toBe.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nexpect(true)->toBeTrue()->and(false)->toBeFalse();\n\ntest('strict comparisons', function () {\n    $nuno = new stdClass;\n    $dries = new stdClass;\n\n    expect($nuno)->toBe($nuno)->not->toBe($dries);\n});\n\ntest('failures', function () {\n    expect(1)->toBe(2);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(1)->toBe(2, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(1)->not->toBe(1);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeAlpha.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('abc')->toBeAlpha();\n    expect('123')->not->toBeAlpha();\n});\n\ntest('failures', function () {\n    expect('123')->toBeAlpha();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('123')->toBeAlpha('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('abc')->not->toBeAlpha();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeAlphaNumeric.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('abc123')->toBeAlphaNumeric();\n    expect('-')->not->toBeAlphaNumeric();\n});\n\ntest('failures', function () {\n    expect('-')->toBeAlphaNumeric();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('-')->toBeAlphaNumeric('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('abc123')->not->toBeAlphaNumeric();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeArray.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect([1, 2, 3])->toBeArray();\n    expect('1, 2, 3')->not->toBeArray();\n});\n\ntest('failures', function () {\n    expect(null)->toBeArray();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(null)->toBeArray('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(['a', 'b', 'c'])->not->toBeArray();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeBetween.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes with int', function () {\n    expect(2)->toBeBetween(1, 3);\n});\n\ntest('passes with float', function () {\n    expect(1.5)->toBeBetween(1.25, 1.75);\n});\n\ntest('passes with float and int', function () {\n    expect(1.5)->toBeBetween(1, 2);\n});\n\ntest('passes with DateTime', function () {\n    expect(new DateTime('2023-09-22'))->toBeBetween(new DateTime('2023-09-21'), new DateTime('2023-09-23'));\n});\n\ntest('failure with int', function () {\n    expect(4)->toBeBetween(1, 3);\n})->throws(ExpectationFailedException::class);\n\ntest('failure with float', function () {\n    expect(2)->toBeBetween(1.5, 1.75);\n})->throws(ExpectationFailedException::class);\n\ntest('failure with float and int', function () {\n    expect(2.1)->toBeBetween(1, 2);\n})->throws(ExpectationFailedException::class);\n\ntest('failure with DateTime', function () {\n    expect(new DateTime('2023-09-20'))->toBeBetween(new DateTime('2023-09-21'), new DateTime('2023-09-23'));\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(4)->toBeBetween(1, 3, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(2)->not->toBeBetween(1, 3);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeBool.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(true)->toBeBool();\n    expect(0)->not->toBeBool();\n});\n\ntest('failures', function () {\n    expect(null)->toBeBool();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(null)->toBeBool('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(false)->not->toBeBool();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeCallable.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(function () {})->toBeCallable();\n    expect(null)->not->toBeCallable();\n});\n\ntest('failures', function () {\n    $hello = 5;\n\n    expect($hello)->toBeCallable();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    $hello = 5;\n\n    expect($hello)->toBeCallable('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(function () {\n        return 42;\n    })->not->toBeCallable();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeCamelCase.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('abc')->toBeCamelCase();\n    expect('abcDef')->toBeCamelCase();\n    expect('abc-def')->not->toBeCamelCase();\n    expect('abc-def')->not->toBeCamelCase();\n    expect('AbcDef')->not->toBeCamelCase();\n});\n\ntest('failures', function () {\n    expect('Abc')->toBeCamelCase();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('Abc')->toBeCamelCase('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('abcDef')->not->toBeCamelCase();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeDigits.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('123')->toBeDigits();\n    expect('123.14')->not->toBeDigits();\n});\n\ntest('failures', function () {\n    expect('123.14')->toBeDigits();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('123.14')->toBeDigits('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('445')->not->toBeDigits();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeDirectory.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    $temp = sys_get_temp_dir();\n\n    expect($temp)->toBeDirectory();\n});\n\ntest('failures', function () {\n    expect('/random/path/whatever')->toBeDirectory();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('/random/path/whatever')->toBeDirectory('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('.')->not->toBeDirectory();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeEmpty.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect([])->toBeEmpty();\n    expect(null)->toBeEmpty();\n});\n\ntest('failures', function () {\n    expect([1, 2])->toBeEmpty();\n    expect(' ')->toBeEmpty();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect([1, 2])->toBeEmpty('oh no!');\n    expect(' ')->toBeEmpty('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect([])->not->toBeEmpty();\n    expect(null)->not->toBeEmpty();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeFalse.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('strict comparisons', function () {\n    expect(false)->toBeFalse();\n});\n\ntest('failures', function () {\n    expect('')->toBeFalse();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('')->toBeFalse('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(false)->not->toBe(false);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeFalsy.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes as falsy', function ($value) {\n    expect($value)->toBeFalsy();\n})->with([false, '', null, 0, '0']);\n\ntest('passes as not falsy', function ($value) {\n    expect($value)->not->toBeFalsy();\n})->with([true, [1], 'false', 1, -1]);\n\ntest('failures', function () {\n    expect(1)->toBeFalsy();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(1)->toBeFalsy('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(null)->not->toBeFalsy();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeFile.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    touch($this->tempFile = sys_get_temp_dir().'/fake.file');\n});\n\nafterEach(function () {\n    unlink($this->tempFile);\n});\n\ntest('pass', function () {\n    expect($this->tempFile)->toBeFile();\n});\n\ntest('failures', function () {\n    expect('/random/path/whatever.file')->toBeFile();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('/random/path/whatever.file')->toBeFile('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect($this->tempFile)->not->toBeFile();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeFloat.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(1.0)->toBeFloat();\n    expect(1)->not->toBeFloat();\n});\n\ntest('failures', function () {\n    expect(42)->toBeFloat();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(42)->toBeFloat('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(log(3))->not->toBeFloat();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeGreaterThan.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes', function () {\n    expect(42)->toBeGreaterThan(41);\n    expect(4)->toBeGreaterThan(3.9);\n});\n\ntest('passes with DateTime and DateTimeImmutable', function () {\n    $now = new DateTime;\n    $past = (new DateTimeImmutable)->modify('-1 day');\n\n    expect($now)->toBeGreaterThan($past);\n\n    expect($past)->not->toBeGreaterThan($now);\n});\n\ntest('passes with strings', function () {\n    expect('b')->toBeGreaterThan('a');\n    expect('a')->not->toBeGreaterThan('a');\n});\n\ntest('failures', function () {\n    expect(4)->toBeGreaterThan(4);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(4)->toBeGreaterThan(4, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(5)->not->toBeGreaterThan(4);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeGreaterThanOrEqual.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes', function () {\n    expect(42)->toBeGreaterThanOrEqual(41);\n    expect(4)->toBeGreaterThanOrEqual(4);\n});\n\ntest('passes with DateTime and DateTimeImmutable', function () {\n    $now = new DateTime;\n    $past = (new DateTimeImmutable)->modify('-1 day');\n\n    expect($now)->toBeGreaterThanOrEqual($now);\n\n    expect($now)->toBeGreaterThanOrEqual($past);\n\n    expect($past)->not->toBeGreaterThanOrEqual($now);\n});\n\ntest('passes with strings', function () {\n    expect('b')->toBeGreaterThanOrEqual('a');\n    expect('a')->toBeGreaterThanOrEqual('a');\n});\n\ntest('failures', function () {\n    expect(4)->toBeGreaterThanOrEqual(4.1);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(4)->toBeGreaterThanOrEqual(4.1, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(5)->not->toBeGreaterThanOrEqual(5);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeIn.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes', function () {\n    expect('a')->toBeIn(['a', 'b', 'c']);\n    expect('d')->not->toBeIn(['a', 'b', 'c']);\n});\n\ntest('failures', function () {\n    expect('d')->toBeIn(['a', 'b', 'c']);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('d')->toBeIn(['a', 'b', 'c'], 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('a')->not->toBeIn(['a', 'b', 'c']);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeInfinite.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(log(0))->toBeInfinite();\n    expect(log(1))->not->toBeInfinite();\n});\n\ntest('failures', function () {\n    expect(asin(2))->toBeInfinite();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(asin(2))->toBeInfinite('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(INF)->not->toBeInfinite();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeInstanceOf.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(new Exception)->toBeInstanceOf(Exception::class);\n    expect(new Exception)->not->toBeInstanceOf(RuntimeException::class);\n});\n\ntest('failures', function () {\n    expect(new Exception)->toBeInstanceOf(RuntimeException::class);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(new Exception)->toBeInstanceOf(RuntimeException::class, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(new Exception)->not->toBeInstanceOf(Exception::class);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeInt.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(42)->toBeInt();\n    expect(42.0)->not->toBeInt();\n});\n\ntest('failures', function () {\n    expect(42.0)->toBeInt();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(42.0)->toBeInt('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(6 * 7)->not->toBeInt();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeIntBackedEnum.php",
    "content": "<?php\n\ntest('enum is backed by int')\n    ->expect('Tests\\Fixtures\\Arch\\ToBeIntBackedEnum\\HasIntBacking')\n    ->toBeIntBackedEnum();\n\ntest('enum is not backed by int')\n    ->expect('Tests\\Fixtures\\Arch\\ToBeIntBackedEnum\\HasStringBacking')\n    ->not->toBeIntBackedEnum();\n"
  },
  {
    "path": "tests/Features/Expect/toBeInvokable.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\n\ntest('class is invokable')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToBeInvokable\\\\IsInvokable\\\\InvokableClass')\n    ->toBeInvokable();\n\ntest('opposite class is invokable')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToBeInvokable\\\\IsInvokable\\\\InvokableClass')\n    ->not->toBeInvokable();\n\ntest('class is invokable via a parent class')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToBeInvokable\\\\IsInvokable\\\\InvokableClassViaParent')\n    ->toBeInvokable();\n\ntest('class is invokable via a trait')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToBeInvokable\\\\IsInvokable\\\\InvokableClassViaTrait')\n    ->toBeInvokable();\n\ntest('failure when the class is not invokable')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToBeInvokable\\\\IsNotInvokable\\\\IsNotInvokableClass')\n    ->toBeInvokable();\n\ntest('class is not invokable')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToBeInvokable\\\\IsNotInvokable\\\\IsNotInvokableClass')\n    ->not->toBeInvokable();\n"
  },
  {
    "path": "tests/Features/Expect/toBeIterable.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect([])->toBeIterable();\n    expect(null)->not->toBeIterable();\n});\n\ntest('failures', function () {\n    expect(42)->toBeIterable();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(42)->toBeIterable('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    function gen(): iterable\n    {\n        yield 1;\n        yield 2;\n        yield 3;\n    }\n\n    expect(gen())->not->toBeIterable();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeJson.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('{\"hello\":\"world\"}')->toBeJson();\n    expect('foo')->not->toBeJson();\n    expect('{\"hello\"')->not->toBeJson();\n});\n\ntest('failures', function () {\n    expect(':\"world\"}')->toBeJson();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(':\"world\"}')->toBeJson('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('{\"hello\":\"world\"}')->not->toBeJson();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeKebabCase.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('abc')->toBeKebabCase();\n    expect('abc-def')->toBeKebabCase();\n    expect('abc_def')->not->toBeKebabCase();\n    expect('abcDef')->not->toBeKebabCase();\n    expect('AbcDef')->not->toBeKebabCase();\n});\n\ntest('failures', function () {\n    expect('Abc')->toBeKebabCase();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('Abc')->toBeKebabCase('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('abc-def')->not->toBeKebabCase();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeLessThan.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes', function () {\n    expect(41)->toBeLessThan(42);\n    expect(4)->toBeLessThan(5);\n});\n\ntest('passes with DateTime and DateTimeImmutable', function () {\n    $now = new DateTime;\n    $past = (new DateTimeImmutable)->modify('-1 day');\n\n    expect($past)->toBeLessThan($now);\n\n    expect($now)->not->toBeLessThan($now);\n});\n\ntest('passes with strings', function () {\n    expect('a')->toBeLessThan('b');\n    expect('a')->not->toBeLessThan('a');\n});\n\ntest('failures', function () {\n    expect(4)->toBeLessThan(4);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(4)->toBeLessThan(4, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(5)->not->toBeLessThan(6);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeLessThanOrEqual.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes', function () {\n    expect(41)->toBeLessThanOrEqual(42);\n    expect(4)->toBeLessThanOrEqual(4);\n});\n\ntest('passes with DateTime and DateTimeImmutable', function () {\n    $now = new DateTime;\n    $past = (new DateTimeImmutable)->modify('-1 day');\n\n    expect($now)->toBeLessThanOrEqual($now);\n\n    expect($past)->toBeLessThanOrEqual($now);\n\n    expect($now)->not->toBeLessThanOrEqual($past);\n});\n\ntest('passes with strings', function () {\n    expect('a')->toBeLessThanOrEqual('b');\n    expect('a')->toBeLessThanOrEqual('a');\n});\n\ntest('failures', function () {\n    expect(4)->toBeLessThanOrEqual(3.9);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(4)->toBeLessThanOrEqual(3.9, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(5)->not->toBeLessThanOrEqual(5);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeList.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect([1, 2, 3])->toBeList();\n    expect(['a' => 1, 'b' => 2, 'c' => 3])->not->toBeList();\n    expect('1, 2, 3')->not->toBeList();\n});\n\ntest('failures', function () {\n    expect(null)->toBeList();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(null)->toBeList('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(['a', 'b', 'c'])->not->toBeList();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeLowercase.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('lowercase')->toBeLowercase();\n    expect('UPPERCASE')->not->toBeLowercase();\n});\n\ntest('failures', function () {\n    expect('UPPERCASE')->toBeLowercase();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('UPPERCASE')->toBeLowercase('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('lowercase')->not->toBeLowercase();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeNAN.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(asin(2))->toBeNan();\n    expect(log(0))->not->toBeNan();\n});\n\ntest('failures', function () {\n    expect(1)->toBeNan();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(1)->toBeNan('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(acos(1.5))->not->toBeNan();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeNull.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(null)->toBeNull();\n    expect('')->not->toBeNull();\n});\n\ntest('failures', function () {\n    expect('hello')->toBeNull();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('hello')->toBeNull('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(null)->not->toBeNull();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeNumeric.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(42)->toBeNumeric();\n    expect('A')->not->toBeNumeric();\n});\n\ntest('failures', function () {\n    expect(null)->toBeNumeric();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(null)->toBeNumeric('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(6 * 7)->not->toBeNumeric();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeObject.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect((object) ['a' => 1])->toBeObject();\n    expect(['a' => 1])->not->toBeObject();\n});\n\ntest('failures', function () {\n    expect(null)->toBeObject();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(null)->toBeObject('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect((object) 'ciao')->not->toBeObject();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeReadableDirectory.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(sys_get_temp_dir())->toBeReadableDirectory();\n});\n\ntest('failures', function () {\n    expect('/random/path/whatever')->toBeReadableDirectory();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('/random/path/whatever')->toBeReadableDirectory('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(sys_get_temp_dir())->not->toBeReadableDirectory();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeReadableFile.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    touch($this->tempFile = sys_get_temp_dir().'/fake.file');\n});\n\nafterEach(function () {\n    unlink($this->tempFile);\n});\n\ntest('pass', function () {\n    expect($this->tempFile)->toBeReadableFile();\n});\n\ntest('failures', function () {\n    expect('/random/path/whatever.file')->toBeReadableFile();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('/random/path/whatever.file')->toBeReadableFile('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect($this->tempFile)->not->toBeReadableFile();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeResource.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\n$resource = tmpfile();\n\nafterAll(function () use ($resource) {\n    fclose($resource);\n});\n\ntest('pass', function () use ($resource) {\n    expect($resource)->toBeResource();\n    expect(null)->not->toBeResource();\n});\n\ntest('failures', function () {\n    expect(null)->toBeResource();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(null)->toBeResource('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () use ($resource) {\n    expect($resource)->not->toBeResource();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeScalar.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(1.1)->toBeScalar();\n});\n\ntest('failures', function () {\n    expect(null)->toBeScalar();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(null)->toBeScalar('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(42)->not->toBeScalar();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeSlug.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('This is a Test String!')->toBeSlug()\n        ->and('Another Test String')->toBeSlug();\n});\n\ntest('failures', function () {\n    expect('')->toBeSlug();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('')->toBeSlug('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('failures with default message', function () {\n    expect('')->toBeSlug();\n})->throws(ExpectationFailedException::class, 'Failed asserting that  can be converted to a slug.');\n\ntest('not failures', function () {\n    expect('This is a Test String!')->not->toBeSlug();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeSnakeCase.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('abc')->toBeSnakeCase();\n    expect('abc_def')->toBeSnakeCase();\n    expect('abc-def')->not->toBeSnakeCase();\n    expect('abcDef')->not->toBeSnakeCase();\n    expect('AbcDef')->not->toBeSnakeCase();\n});\n\ntest('failures', function () {\n    expect('Abc')->toBeSnakeCase();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('Abc')->toBeSnakeCase('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('abc_def')->not->toBeSnakeCase();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeString.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('1.1')->toBeString();\n    expect(1.1)->not->toBeString();\n});\n\ntest('failures', function () {\n    expect(null)->toBeString();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(null)->toBeString('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('42')->not->toBeString();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeStringBackedEnum.php",
    "content": "<?php\n\ntest('enum is backed by string')\n    ->expect('Tests\\Fixtures\\Arch\\ToBeStringBackedEnum\\HasStringBacking')\n    ->toBeStringBackedEnum();\n\ntest('enum is not backed by string')\n    ->expect('Tests\\Fixtures\\Arch\\ToBeStringBackedEnum\\HasIntBacking')\n    ->not->toBeStringBackedEnum();\n"
  },
  {
    "path": "tests/Features/Expect/toBeStudlyCase.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('Abc')->toBeStudlyCase();\n    expect('AbcDef')->toBeStudlyCase();\n    expect('abc-def')->not->toBeStudlyCase();\n    expect('abc-def')->not->toBeStudlyCase();\n    expect('abc')->not->toBeStudlyCase();\n});\n\ntest('failures', function () {\n    expect('abc')->toBeStudlyCase();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('abc')->toBeStudlyCase('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('AbcDef')->not->toBeStudlyCase();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeTrue.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('strict comparisons', function () {\n    expect(true)->toBeTrue();\n});\n\ntest('failures', function () {\n    expect('')->toBeTrue();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('')->toBeTrue('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(false)->not->toBe(false);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeTruthy.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes as truthy', function ($value) {\n    expect($value)->toBeTruthy();\n})->with([true, [1], 'false', 1, -1]);\n\ntest('passes as not truthy', function ($value) {\n    expect($value)->not->toBeTruthy();\n})->with([false, '', null, 0, '0']);\n\ntest('failures', function () {\n    expect(null)->toBeTruthy();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(null)->toBeTruthy('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(1)->not->toBeTruthy();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeUppercase.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('UPPERCASE')->toBeUppercase();\n    expect('lowercase')->not->toBeUppercase();\n});\n\ntest('failures', function () {\n    expect('lowercase')->toBeUppercase();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('lowercase')->toBeUppercase('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('UPPERCASE')->not->toBeUppercase();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeUrl.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('https://pestphp.com')->toBeUrl()\n        ->and('pestphp.com')->not->toBeUrl();\n});\n\ntest('failures', function () {\n    expect('pestphp.com')->toBeUrl();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('pestphp.com')->toBeUrl('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('failures with default message', function () {\n    expect('pestphp.com')->toBeUrl();\n})->throws(ExpectationFailedException::class, 'Failed asserting that pestphp.com is a url.');\n\ntest('not failures', function () {\n    expect('https://pestphp.com')->not->toBeUrl();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeUuid.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\InvalidExpectationValue;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('failures with wrong type', function () {\n    expect([])->toBeUuid();\n})->throws(InvalidExpectationValue::class, 'Invalid expectation value type. Expected [string].');\n\ntest('pass', function () {\n    expect('3cafb226-4326-11ee-a516-846993788c86')->toBeUuid(); // version 1\n    expect('0000415c-4326-21ee-a700-846993788c86')->toBeUuid(); // version 2\n    expect('3f703955-aaba-3e70-a3cb-baff6aa3b28f')->toBeUuid(); // version 3\n    expect('ca0a8228-cdf6-41db-b34b-c2f31485796c')->toBeUuid(); // version 4\n    expect('a35477ae-bfb1-5f2e-b5a4-4711594d855f')->toBeUuid(); // version 5\n    expect('1ee43263-cf5a-6fd8-8f47-846993788c86')->toBeUuid(); // version 6\n    expect('018a2bef-09f2-728c-becb-c3f569d91486')->toBeUuid(); // version 7\n    expect('00112233-4455-8677-8899-aabbccddeeff')->toBeUuid(); // version 8\n});\n\ntest('failures', function () {\n    expect('foo')->toBeUuid();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with message', function () {\n    expect('bar')->toBeUuid('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('foo')->not->toBeUuid();\n});\n"
  },
  {
    "path": "tests/Features/Expect/toBeWritableDirectory.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(sys_get_temp_dir())->toBeWritableDirectory();\n});\n\ntest('failures', function () {\n    expect('/random/path/whatever')->toBeWritableDirectory();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('/random/path/whatever')->toBeWritableDirectory('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(sys_get_temp_dir())->not->toBeWritableDirectory();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toBeWritableFile.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    touch($this->tempFile = sys_get_temp_dir().'/fake.file');\n});\n\nafterEach(function () {\n    unlink($this->tempFile);\n});\n\ntest('pass', function () {\n    expect($this->tempFile)->toBeWritableFile();\n});\n\ntest('failures', function () {\n    expect('/random/path/whatever.file')->toBeWritableFile();\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('/random/path/whatever.file')->toBeWritableFile('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect($this->tempFile)->not->toBeWritableFile();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toContain.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes strings', function () {\n    expect('Nuno')->toContain('Nu');\n});\n\ntest('passes strings with multiple needles', function () {\n    expect('Nuno')->toContain('Nu', 'no');\n});\n\ntest('passes arrays', function () {\n    expect([1, 2, 42])->toContain(42);\n});\n\ntest('passes arrays with multiple needles', function () {\n    expect([1, 2, 42])->toContain(42, 2);\n});\n\ntest('passes with array needles', function () {\n    expect([[1, 2, 3], 2, 42])->toContain(42, [1, 2, 3]);\n});\n\ntest('failures', function () {\n    expect([1, 2, 42])->toContain(3);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with multiple needles (all failing)', function () {\n    expect([1, 2, 42])->toContain(3, 4);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with multiple needles (some failing)', function () {\n    expect([1, 2, 42])->toContain(1, 3, 4);\n})->throws(ExpectationFailedException::class);\n\ntest('not failures', function () {\n    expect([1, 2, 42])->not->toContain(42);\n})->throws(ExpectationFailedException::class);\n\ntest('not failures with multiple needles (all failing)', function () {\n    expect([1, 2, 42])->not->toContain(42, 2);\n})->throws(ExpectationFailedException::class);\n\ntest('not failures with multiple needles (some failing)', function () {\n    expect([1, 2, 42])->not->toContain(42, 1);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toContainEqual.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('passes arrays', function () {\n    expect([1, 2, 42])->toContainEqual('42');\n});\n\ntest('passes arrays with multiple needles', function () {\n    expect([1, 2, 42])->toContainEqual('42', '2');\n});\n\ntest('failures', function () {\n    expect([1, 2, 42])->toContainEqual('3');\n})->throws(ExpectationFailedException::class);\n\ntest('failures with multiple needles (all failing)', function () {\n    expect([1, 2, 42])->toContainEqual('3', '4');\n})->throws(ExpectationFailedException::class);\n\ntest('failures with multiple needles (some failing)', function () {\n    expect([1, 2, 42])->toContainEqual('1', '3', '4');\n})->throws(ExpectationFailedException::class);\n\ntest('not failures', function () {\n    expect([1, 2, 42])->not->toContainEqual('42');\n})->throws(ExpectationFailedException::class);\n\ntest('not failures with multiple needles (all failing)', function () {\n    expect([1, 2, 42])->not->toContainEqual('42', '2');\n})->throws(ExpectationFailedException::class);\n\ntest('not failures with multiple needles (some failing)', function () {\n    expect([1, 2, 42])->not->toContainEqual('42', '1');\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toContainOnlyInstancesOf.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    $this->times = [new DateTimeImmutable, new DateTimeImmutable];\n});\n\ntest('pass', function () {\n    expect($this->times)->toContainOnlyInstancesOf(DateTimeImmutable::class);\n    expect($this->times)->not->toContainOnlyInstancesOf(DateTime::class);\n});\n\ntest('failures', function () {\n    expect($this->times)->toContainOnlyInstancesOf(DateTime::class);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect($this->times)->toContainOnlyInstancesOf(DateTime::class, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect($this->times)->not->toContainOnlyInstancesOf(DateTimeImmutable::class);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toEndWith.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('username')->toEndWith('name');\n});\n\ntest('failures', function () {\n    expect('username')->toEndWith('password');\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('username')->toEndWith('password', 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('username')->not->toEndWith('name');\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toEqual.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('00123')->toEqual(123);\n});\n\ntest('failures', function () {\n    expect(['a', 'b', 'c'])->toEqual(['a', 'b']);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(['a', 'b', 'c'])->toEqual(['a', 'b'], 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('042')->not->toEqual(42);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toEqualCanonicalizing.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect([1, 2, 3])->toEqualCanonicalizing([3, 1, 2]);\n    expect(['g', 'a', 'z'])->not->toEqualCanonicalizing(['a', 'z']);\n});\n\ntest('failures', function () {\n    expect([3, 2, 1])->toEqualCanonicalizing([1, 2]);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect([3, 2, 1])->toEqualCanonicalizing([1, 2], 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(['a', 'b', 'c'])->not->toEqualCanonicalizing(['b', 'a', 'c']);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toEqualWithDelta.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(1.0)->toEqualWithDelta(1.3, .4);\n});\n\ntest('failures with custom message', function () {\n    expect(1.0)->toEqualWithDelta(1.5, .1, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(1.0)->not->toEqualWithDelta(1.6, .7);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveAttribute.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\n\ntest('class has attribute')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHaveAttribute\\\\HaveAttribute')\n    ->toHaveAttribute('Tests\\\\Fixtures\\\\Arch\\\\ToHaveAttribute\\\\Attributes\\\\AsAttribute');\n\ntest('opposite class has attribute')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHaveAttribute\\\\HaveAttribute')\n    ->not\n    ->toHaveAttribute('Tests\\\\Fixtures\\\\Arch\\\\ToHaveAttribute\\\\Attributes\\\\AsAttribute');\n\ntest('class not has attribute')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHaveAttribute\\\\NotHaveAttribute')\n    ->not\n    ->toHaveAttribute('Tests\\\\Fixtures\\\\Arch\\\\ToHaveAttribute\\\\Attributes\\\\AsAttribute');\n"
  },
  {
    "path": "tests/Features/Expect/toHaveCamelCaseKeys.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\InvalidExpectationValue;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\n$array = [\n    'camel' => true,\n    'camelCase' => [\n        'camel' => true,\n        'camelCase' => [\n            'camel' => true,\n            'camelCase' => true,\n        ],\n        'list' => [\n            'abc',\n            'def',\n            'ghi',\n        ],\n    ],\n];\n\ntest('pass', function () use ($array) {\n    expect($array)->toHaveCamelCaseKeys();\n});\n\ntest('failures', function () {\n    expect('not-an-array')->toHaveCamelCaseKeys();\n})->throws(InvalidExpectationValue::class);\n\ntest('failures with message', function () use ($array) {\n    expect($array)->not->toHaveCamelCaseKeys('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () use ($array) {\n    expect($array)->not->toHaveCamelCaseKeys();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveConstructor.php",
    "content": "<?php\n\ntest('class has constructor')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveConstructor\\HasConstructor\\HasConstructor')\n    ->toHaveConstructor();\n\ntest('class has no constructor')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveConstructor\\HasNoConstructor\\HasNoConstructor')\n    ->not->toHaveConstructor();\n"
  },
  {
    "path": "tests/Features/Expect/toHaveCount.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\InvalidExpectationValue;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect([1, 2, 3])->toHaveCount(3);\n});\n\ntest('failures with invalid type', function () {\n    expect('foo')->toHaveCount(3);\n})->throws(InvalidExpectationValue::class, 'Invalid expectation value type. Expected [countable|iterable]');\n\ntest('failures', function () {\n    expect([1, 2, 3])->toHaveCount(4);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with message', function () {\n    expect([1, 2, 3])->toHaveCount(4, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect([1, 2, 3])->not->toHaveCount(3);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveDestructor.php",
    "content": "<?php\n\ntest('class has destructor')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveDestructor\\HasDestructor\\HasDestructor')\n    ->toHaveDestructor();\n\ntest('class has no destructor')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveDestructor\\HasNoDestructor\\HasNoDestructor')\n    ->not->toHaveDestructor();\n"
  },
  {
    "path": "tests/Features/Expect/toHaveFileSystemPermissions.php",
    "content": "<?php\n\n// ...\n"
  },
  {
    "path": "tests/Features/Expect/toHaveKebabCaseKeys.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\InvalidExpectationValue;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\n$array = [\n    'kebab' => true,\n    'kebab-case' => [\n        'kebab' => true,\n        'kebab-case' => [\n            'kebab' => true,\n            'kebab-case' => true,\n        ],\n        'list' => [\n            'abc',\n            'def',\n            'ghi',\n        ],\n    ],\n];\n\ntest('pass', function () use ($array) {\n    expect($array)->toHaveKebabCaseKeys();\n});\n\ntest('failures', function () {\n    expect('not-an-array')->toHaveKebabCaseKeys();\n})->throws(InvalidExpectationValue::class);\n\ntest('failures with message', function () use ($array) {\n    expect($array)->not->toHaveKebabCaseKeys('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () use ($array) {\n    expect($array)->not->toHaveKebabCaseKeys();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveKey.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\n$test_array = [\n    'a' => 1,\n    'b',\n    'c' => 'world',\n    'd' => [\n        'e' => 'hello',\n    ],\n    'key.with.dots' => false,\n];\n\ntest('pass')->expect($test_array)->toHaveKey('c');\ntest('pass with nested key')->expect($test_array)->toHaveKey('d.e');\ntest('pass with plain key with dots')->expect($test_array)->toHaveKey('key.with.dots');\n\ntest('pass with value check')->expect($test_array)->toHaveKey('c', 'world');\ntest('pass with value check and nested key')->expect($test_array)->toHaveKey('d.e', 'hello');\ntest('pass with value check and plain key with dots')->expect($test_array)->toHaveKey('key.with.dots', false);\n\ntest('failures', function () use ($test_array) {\n    expect($test_array)->toHaveKey('foo');\n})->throws(ExpectationFailedException::class, \"Failed asserting that an array has the key 'foo'\");\n\ntest('failures with custom message', function () use ($test_array) {\n    expect($test_array)->toHaveKey('foo', message: 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('failures with custom message and Any matcher', function () use ($test_array) {\n    expect($test_array)->toHaveKey('foo', expect()->any(), 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('failures with nested key', function () use ($test_array) {\n    expect($test_array)->toHaveKey('d.bar');\n})->throws(ExpectationFailedException::class, \"Failed asserting that an array has the key 'd.bar'\");\n\ntest('failures with nested key and custom message', function () use ($test_array) {\n    expect($test_array)->toHaveKey('d.bar', message: 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('failures with nested key and custom message with Any matcher', function () use ($test_array) {\n    expect($test_array)->toHaveKey('d.bar', expect()->any(), 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('failures with plain key with dots', function () use ($test_array) {\n    expect($test_array)->toHaveKey('missing.key.with.dots');\n})->throws(ExpectationFailedException::class, \"Failed asserting that an array has the key 'missing.key.with.dots'\");\n\ntest('fails with wrong value', function () use ($test_array) {\n    expect($test_array)->toHaveKey('c', 'bar');\n})->throws(ExpectationFailedException::class);\n\ntest('fails with wrong value and nested key', function () use ($test_array) {\n    expect($test_array)->toHaveKey('d.e', 'foo');\n})->throws(ExpectationFailedException::class);\n\ntest('fails with wrong value and plain key with dots', function () use ($test_array) {\n    expect($test_array)->toHaveKey('key.with.dots', true);\n})->throws(ExpectationFailedException::class);\n\ntest('not failures', function () use ($test_array) {\n    expect($test_array)->not->toHaveKey('c');\n})->throws(ExpectationFailedException::class, \"Expecting […] not to have key 'c'\");\n\ntest('not failures with nested key', function () use ($test_array) {\n    expect($test_array)->not->toHaveKey('d.e');\n})->throws(ExpectationFailedException::class, \"Expecting […] not to have key 'd.e'\");\n\ntest('not failures with plain key with dots', function () use ($test_array) {\n    expect($test_array)->not->toHaveKey('key.with.dots');\n})->throws(ExpectationFailedException::class, \"Expecting […] not to have key 'key.with.dots'\");\n\ntest('not failures with correct value', function () use ($test_array) {\n    expect($test_array)->not->toHaveKey('c', 'world');\n})->throws(ExpectationFailedException::class);\n\ntest('not failures with correct value and  with nested key', function () use ($test_array) {\n    expect($test_array)->not->toHaveKey('d.e', 'hello');\n})->throws(ExpectationFailedException::class);\n\ntest('not failures with correct value and  with plain key with dots', function () use ($test_array) {\n    expect($test_array)->not->toHaveKey('key.with.dots', false);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveKeys.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => 'baz']])->toHaveKeys(['a', 'c', 'foo.bar']);\n});\n\ntest('pass with multi-dimensional arrays', function () {\n    expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => ['bir' => 'biz']]])->toHaveKeys(['a', 'c', 'foo' => ['bar' => ['bir']]]);\n});\n\ntest('failures', function () {\n    expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => 'baz']])->toHaveKeys(['a', 'd', 'foo.bar', 'hello.world']);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => 'baz']])->toHaveKeys(['a', 'd', 'foo.bar', 'hello.world'], 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('failures with multi-dimensional arrays', function () {\n    expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => ['bir' => 'biz']]])->toHaveKeys(['a', 'd', 'foo' => ['bar' => 'bir'], 'hello.world']);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with multi-dimensional arrays and custom message', function () {\n    expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => ['bir' => 'biz']]])->toHaveKeys(['a', 'd', 'foo' => ['bar' => 'bir'], 'hello.world'], 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => 'baz']])->not->toHaveKeys(['foo.bar', 'c', 'z']);\n})->throws(ExpectationFailedException::class);\n\ntest('not failures with multi-dimensional arrays', function () {\n    expect(['a' => 1, 'b', 'c' => 'world', 'foo' => ['bar' => ['bir' => 'biz']]])->not->toHaveKeys(['foo' => ['bar' => 'bir'], 'c', 'z']);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveLength.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nit('passes', function ($value) {\n    expect($value)->toHaveLength(9);\n})->with([\n    'Fortaleza',\n    'Sollefteå',\n    'Ιεράπετρα',\n    (object) [1, 2, 3, 4, 5, 6, 7, 8, 9],\n]);\n\nit('passes with array', function () {\n    expect([1, 2, 3])->toHaveLength(3);\n});\n\nit('passes with *not*', function () {\n    expect('')->not->toHaveLength(1);\n});\n\nit('properly fails with *not*', function () {\n    expect('pest')->not->toHaveLength(4, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\nit('fails', function () {\n    expect([1, 1.5, true, null])->toHaveLength(1);\n})->throws(ExpectationFailedException::class);\n\nit('fails with message', function () {\n    expect([1, 1.5, true, null])->toHaveLength(1, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n"
  },
  {
    "path": "tests/Features/Expect/toHaveLineCountLessThan.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\nuse Pest\\Expectation;\n\nit('passes', function () {\n    expect(Expectation::class)->toHaveLineCountLessThan(2000);\n});\n\nit('fails', function () {\n    expect(Expectation::class)->toHaveLineCountLessThan(10);\n})->throws(ArchExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveMethod.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\n\ntest('class has method')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod\\HasMethod')\n    ->toHaveMethod('foo');\n\ntest('opposite class has method')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod\\HasMethod')\n    ->not->toHaveMethod('foo');\n\ntest('class has method via a parent class')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod\\HasMethodViaParent')\n    ->toHaveMethod('foo');\n\ntest('class has method via a trait')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod\\HasMethodViaTrait')\n    ->toHaveMethod('foo');\n\ntest('failure when the class has no method')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasNoMethod\\HasNoMethodClass')\n    ->toHaveMethod('foo');\n\ntest('class has no method')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasNoMethod\\HasNoMethodClass')\n    ->not->toHaveMethod('foo');\n"
  },
  {
    "path": "tests/Features/Expect/toHaveMethods.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\n\ntest('class has method')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod\\HasMethod')\n    ->toHaveMethods(['foo']);\n\ntest('opposite class has method')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod\\HasMethod')\n    ->not->toHaveMethods(['foo']);\n\ntest('class has method via a parent class')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod\\HasMethodViaParent')\n    ->toHaveMethods(['foo']);\n\ntest('class has method via a trait')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod\\HasMethodViaTrait')\n    ->toHaveMethods(['foo']);\n\ntest('failure when the class has no method')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasNoMethod\\HasNoMethodClass')\n    ->toHaveMethods(['foo']);\n\ntest('class has no method')\n    ->expect('Tests\\Fixtures\\Arch\\ToHaveMethod\\HasNoMethod\\HasNoMethodClass')\n    ->not->toHaveMethods(['foo']);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveMethodsDocumented.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\nuse Pest\\Configuration;\nuse Pest\\Expectation;\nuse Tests\\Fixtures\\Inheritance\\ExampleTest;\n\nit('passes', function () {\n    expect(Expectation::class)->toHaveMethodsDocumented()\n        ->and(ExampleTest::class)->not->toHaveMethodsDocumented();\n});\n\nit('fails 1', function () {\n    expect(ExampleTest::class)->toHaveMethodsDocumented();\n})->throws(ArchExpectationFailedException::class);\n\nit('fails 2', function () {\n    expect(Configuration::class)->not->toHaveMethodsDocumented();\n})->throws(ArchExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHavePrefix.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\n\ntest('missing prefix')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHavePrefix\\\\HasNoPrefix')\n    ->toHavePrefix('Prefix');\n\ntest('has prefix')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHavePrefix\\\\HasPrefix')\n    ->toHavePrefix('Prefix');\n\ntest('opposite missing prefix')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHavePrefix\\\\HasPrefix')\n    ->not->toHavePrefix('Prefix');\n\ntest('opposite has prefix')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHavePrefix\\\\HasNoPrefix')\n    ->not->toHavePrefix('Prefix');\n"
  },
  {
    "path": "tests/Features/Expect/toHavePrivateMethodsBesides.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\nuse Tests\\Fixtures\\Arch\\ToHavePublicMethodsBesides\\UserController;\n\ntest('pass', function () {\n    expect(UserController::class)->not->toHavePrivateMethodsBesides(['privateMethod']);\n});\n\ntest('failures', function () {\n    expect(UserController::class)->not->toHavePrivateMethods();\n})->throws(ArchExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveProperties.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    $object = new stdClass;\n    $object->name = 'John';\n    $object->age = 21;\n\n    expect($object)\n        ->toHaveProperties(['name', 'age'])\n        ->toHaveProperties([\n            'name' => 'John',\n            'age' => 21,\n        ]);\n});\n\ntest('failures', function () {\n    $object = new stdClass;\n    $object->name = 'John';\n\n    expect($object)\n        ->toHaveProperties(['name', 'age'])\n        ->toHaveProperties([\n            'name' => 'John',\n            'age' => 21,\n        ]);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    $object = new stdClass;\n    $object->name = 'John';\n\n    expect($object)\n        ->toHaveProperties(['name', 'age'], 'oh no!')\n        ->toHaveProperties([\n            'name' => 'John',\n            'age' => 21,\n        ], 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    $object = new stdClass;\n    $object->name = 'John';\n    $object->age = 21;\n\n    expect($object)->not->toHaveProperties(['name', 'age'])\n        ->not->toHaveProperties([\n            'name' => 'John',\n            'age' => 21,\n        ]);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHavePropertiesDocumented.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\nuse Pest\\Expectation;\nuse Pest\\Factories\\TestCaseFactory;\nuse Tests\\Fixtures\\Inheritance\\ExampleTest;\n\nit('passes', function () {\n    expect(Expectation::class)->toHavePropertiesDocumented()\n        ->and(ExampleTest::class)->not->toHavePropertiesDocumented();\n});\n\nit('fails 1', function () {\n    expect(ExampleTest::class)->toHavePropertiesDocumented();\n})->throws(ArchExpectationFailedException::class);\n\nit('fails 2', function () {\n    expect(TestCaseFactory::class)->not->toHavePropertiesDocumented();\n})->throws(ArchExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveProperty.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\n$obj = new stdClass;\n$obj->foo = 'bar';\n$obj->fooNull = null;\n\ntest('pass', function () use ($obj) {\n    expect($obj)->toHaveProperty('foo');\n    expect($obj)->toHaveProperty('foo', 'bar');\n    expect($obj)->toHaveProperty('fooNull');\n    expect($obj)->toHaveProperty('fooNull', null);\n});\n\ntest('failures', function () use ($obj) {\n    expect($obj)->toHaveProperty('bar');\n})->throws(ExpectationFailedException::class);\n\ntest('failures with message', function () use ($obj) {\n    expect($obj)->toHaveProperty(name: 'bar', message: 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('failures with message and Any matcher', function () use ($obj) {\n    expect($obj)->toHaveProperty('bar', expect()->any(), 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () use ($obj) {\n    expect($obj)->not->toHaveProperty('foo');\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveProtectedMethodsBesides.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\nuse Tests\\Fixtures\\Arch\\ToHavePublicMethodsBesides\\UserController;\n\ntest('pass', function () {\n    expect(UserController::class)->not->toHaveProtectedMethodsBesides(['protectedMethod']);\n});\n\ntest('failures', function () {\n    expect(UserController::class)->not->toHaveProtectedMethods();\n})->throws(ArchExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHavePublicMethodsBesides.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\nuse Tests\\Fixtures\\Arch\\ToHavePublicMethodsBesides\\UserController;\n\ntest('pass', function () {\n    expect(UserController::class)->not->toHavePublicMethodsBesides(['publicMethod']);\n});\n\ntest('failures', function () {\n    expect(UserController::class)->not->toHavePublicMethods();\n})->throws(ArchExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveSameSize.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\InvalidExpectationValue;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('failures with wrong type', function () {\n    expect('foo')->toHaveSameSize([1]);\n})->throws(InvalidExpectationValue::class, 'Invalid expectation value type. Expected [countable|iterable].');\n\ntest('pass', function () {\n    expect([1, 2, 3])->toHaveSameSize([4, 5, 6]);\n});\n\ntest('failures', function () {\n    expect([1, 2, 3])->toHaveSameSize([1]);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with message', function () {\n    expect([1, 2, 3])->toHaveSameSize([1], 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect([1, 2, 3])->not->toHaveSameSize([1]);\n});\n"
  },
  {
    "path": "tests/Features/Expect/toHaveSnakeCaseKeys.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\InvalidExpectationValue;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\n$array = [\n    'snake' => true,\n    'snake_case' => [\n        'snake' => true,\n        'snake_case' => [\n            'snake' => true,\n            'snake_case' => true,\n        ],\n        'list' => [\n            'abc',\n            'def',\n            'ghi',\n        ],\n    ],\n];\n\ntest('pass', function () use ($array) {\n    expect($array)->toHaveSnakeCaseKeys();\n});\n\ntest('failures', function () {\n    expect('not-an-array')->toHaveSnakeCaseKeys();\n})->throws(InvalidExpectationValue::class);\n\ntest('failures with message', function () use ($array) {\n    expect($array)->not->toHaveSnakeCaseKeys('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () use ($array) {\n    expect($array)->not->toHaveSnakeCaseKeys();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveStudlyCaseKeys.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\InvalidExpectationValue;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\n$array = [\n    'Studly' => true,\n    'StudlyCase' => [\n        'Studly' => true,\n        'StudlyCase' => [\n            'Studly' => true,\n            'StudlyCase' => true,\n        ],\n        'List' => [\n            'abc',\n            'def',\n            'ghi',\n        ],\n    ],\n];\n\ntest('pass', function () use ($array) {\n    expect($array)->toHaveStudlyCaseKeys();\n});\n\ntest('failures', function () {\n    expect('not-an-array')->toHaveStudlyCaseKeys();\n})->throws(InvalidExpectationValue::class);\n\ntest('failures with message', function () use ($array) {\n    expect($array)->not->toHaveStudlyCaseKeys('oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () use ($array) {\n    expect($array)->not->toHaveStudlyCaseKeys();\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toHaveSuffix.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\n\ntest('missing suffix')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHaveSuffix\\\\HasNoSuffix')\n    ->toHaveSuffix('Suffix');\n\ntest('has suffix')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHaveSuffix\\\\HasSuffix')\n    ->toHaveSuffix('Suffix');\n\ntest('opposite missing suffix')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHaveSuffix\\\\HasSuffix')\n    ->not->toHaveSuffix('Suffix');\n\ntest('opposite has suffix')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToHaveSuffix\\\\HasNoSuffix')\n    ->not->toHaveSuffix('Suffix');\n"
  },
  {
    "path": "tests/Features/Expect/toMatch.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('Hello World')->toMatch('/^hello wo.*$/i');\n});\n\ntest('failures', function () {\n    expect('Hello World')->toMatch('/^hello$/i');\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('Hello World')->toMatch('/^hello$/i', 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('Hello World')->not->toMatch('/^hello wo.*$/i');\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toMatchArray.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    $this->user = [\n        'id' => 1,\n        'name' => 'Nuno',\n        'email' => 'enunomaduro@gmail.com',\n    ];\n});\n\ntest('pass', function () {\n    expect($this->user)->toMatchArray([\n        'name' => 'Nuno',\n        'email' => 'enunomaduro@gmail.com',\n    ]);\n});\n\ntest('failures', function () {\n    expect($this->user)->toMatchArray([\n        'name' => 'Not the same name',\n        'email' => 'enunomaduro@gmail.com',\n    ]);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect($this->user)->toMatchArray([\n        'name' => 'Not the same name',\n        'email' => 'enunomaduro@gmail.com',\n    ], 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect($this->user)->not->toMatchArray([\n        'id' => 1,\n    ]);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toMatchConstraint.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\Constraint\\IsTrue;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect(true)->toMatchConstraint(new IsTrue);\n});\n\ntest('failures', function () {\n    expect(false)->toMatchConstraint(new IsTrue);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(false)->toMatchConstraint(new IsTrue, 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(true)->not->toMatchConstraint(new IsTrue);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toMatchObject.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    $this->user = (object) [\n        'id' => 1,\n        'name' => 'Nuno',\n        'email' => 'enunomaduro@gmail.com',\n    ];\n});\n\ntest('pass', function () {\n    expect($this->user)->toMatchObject([\n        'name' => 'Nuno',\n        'email' => 'enunomaduro@gmail.com',\n    ]);\n});\n\ntest('pass with class', function () {\n    expect(new class\n    {\n        public $name = 'Nuno';\n\n        public $email = 'enunomaduro@gmail.com';\n    })->toMatchObject([\n        'name' => 'Nuno',\n        'email' => 'enunomaduro@gmail.com',\n    ]);\n});\n\ntest('failures', function () {\n    expect($this->user)->toMatchObject([\n        'name' => 'Not the same name',\n        'email' => 'enunomaduro@gmail.com',\n    ]);\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect($this->user)->toMatchObject([\n        'name' => 'Not the same name',\n        'email' => 'enunomaduro@gmail.com',\n    ], 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect($this->user)->not->toMatchObject([\n        'id' => 1,\n    ]);\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toMatchSnapshot.php",
    "content": "<?php\n\nuse Pest\\TestSuite;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    $this->snapshotable = <<<'HTML'\n        <div class=\"container\">\n            <div class=\"row\">\n                <div class=\"col-md-12\">\n                    <h1>Snapshot</h1>\n                </div>\n            </div>\n        </div>\n    HTML;\n});\n\ntest('pass', function () {\n    TestSuite::getInstance()->snapshots->save($this->snapshotable);\n\n    expect($this->snapshotable)->toMatchSnapshot();\n});\n\nexpect()->pipe('toMatchSnapshot', function (Closure $next) {\n    if (is_string($this->value)) {\n        $this->value = preg_replace(\n            '/name=\"_token\" value=\".*\"/',\n            'name=\"_token\" value=\"1\"',\n            $this->value\n        );\n    }\n\n    return $next();\n});\n\ntest('pass using pipes', function () {\n    expect('<input type=\"hidden\" name=\"_token\" value=\"'.random_int(1, 999).'\" />')\n        ->toMatchSnapshot();\n});\n\ntest('pass with `__toString`', function () {\n    TestSuite::getInstance()->snapshots->save($this->snapshotable);\n\n    $object = new class($this->snapshotable)\n    {\n        public function __construct(protected string $snapshotable) {}\n\n        public function __toString()\n        {\n            return $this->snapshotable;\n        }\n    };\n\n    expect($object)->toMatchSnapshot();\n});\n\ntest('pass with `toString`', function () {\n    TestSuite::getInstance()->snapshots->save($this->snapshotable);\n\n    $object = new class($this->snapshotable)\n    {\n        public function __construct(protected string $snapshotable) {}\n\n        public function toString()\n        {\n            return $this->snapshotable;\n        }\n    };\n\n    expect($object)->toMatchSnapshot();\n});\n\ntest('pass with dataset', function ($data) {\n    TestSuite::getInstance()->snapshots->save($this->snapshotable);\n    [$filename] = TestSuite::getInstance()->snapshots->get();\n\n    expect($filename)->toStartWith('tests/.pest/snapshots/')\n        ->toEndWith('pass_with_dataset_with_data_set____my_datas_set_value___.snap')\n        ->and($this->snapshotable)->toMatchSnapshot();\n})->with(['my-datas-set-value']);\n\ndescribe('within describe', function () {\n    test('pass with dataset', function ($data) {\n        TestSuite::getInstance()->snapshots->save($this->snapshotable);\n        [$filename] = TestSuite::getInstance()->snapshots->get();\n\n        expect($filename)->toStartWith('tests/.pest/snapshots/')\n            ->toEndWith('pass_with_dataset_with_data_set____my_datas_set_value___.snap')\n            ->and($this->snapshotable)->toMatchSnapshot();\n    });\n})->with(['my-datas-set-value']);\n\ntest('pass with `toArray`', function () {\n    TestSuite::getInstance()->snapshots->save(json_encode(['key' => $this->snapshotable], JSON_PRETTY_PRINT));\n\n    $object = new class($this->snapshotable)\n    {\n        public function __construct(protected string $snapshotable) {}\n\n        public function toArray()\n        {\n            return [\n                'key' => $this->snapshotable,\n            ];\n        }\n    };\n\n    expect($object)->toMatchSnapshot();\n});\n\ntest('pass with array', function () {\n    TestSuite::getInstance()->snapshots->save(json_encode(['key' => $this->snapshotable], JSON_PRETTY_PRINT));\n\n    expect([\n        'key' => $this->snapshotable,\n    ])->toMatchSnapshot();\n});\n\ntest('pass with `toSnapshot`', function () {\n    TestSuite::getInstance()->snapshots->save(json_encode(['key' => $this->snapshotable], JSON_PRETTY_PRINT));\n\n    $object = new class($this->snapshotable)\n    {\n        public function __construct(protected string $snapshotable) {}\n\n        public function toSnapshot()\n        {\n            return json_encode([\n                'key' => $this->snapshotable,\n            ], JSON_PRETTY_PRINT);\n        }\n    };\n\n    expect($object)->toMatchSnapshot();\n});\n\ntest('failures', function () {\n    TestSuite::getInstance()->snapshots->save($this->snapshotable);\n\n    expect('contain that does not match snapshot')->toMatchSnapshot();\n})->throws(ExpectationFailedException::class, 'Failed asserting that two strings are identical.');\n\ntest('failures with custom message', function () {\n    TestSuite::getInstance()->snapshots->save($this->snapshotable);\n\n    expect('contain that does not match snapshot')->toMatchSnapshot('oh no');\n})->throws(ExpectationFailedException::class, 'oh no');\n\ntest('not failures', function () {\n    TestSuite::getInstance()->snapshots->save($this->snapshotable);\n\n    expect($this->snapshotable)->not->toMatchSnapshot();\n})->throws(ExpectationFailedException::class);\n\ntest('multiple snapshot expectations', function () {\n    expect('foo bar 1')->toMatchSnapshot();\n\n    expect('foo bar 2')->toMatchSnapshot();\n});\n\ntest('multiple snapshot expectations with datasets', function () {\n    expect('foo bar 1')->toMatchSnapshot();\n\n    expect('foo bar 2')->toMatchSnapshot();\n})->with([1, 'foo', 'bar', 'baz']);\n\ndescribe('describable', function () {\n    test('multiple snapshot expectations with describe', function () {\n        expect('foo bar 1')->toMatchSnapshot();\n\n        expect('foo bar 2')->toMatchSnapshot();\n    });\n});\n\ntest('multiple snapshot expectations with repeat', function () {\n    expect('foo bar 1')->toMatchSnapshot();\n\n    expect('foo bar 2')->toMatchSnapshot();\n})->repeat(10);\n"
  },
  {
    "path": "tests/Features/Expect/toStartWith.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\ntest('pass', function () {\n    expect('username')->toStartWith('user');\n});\n\ntest('failures', function () {\n    expect('username')->toStartWith('password');\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect('username')->toStartWith('password', 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect('username')->not->toStartWith('user');\n})->throws(ExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toThrow.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nclass CustomException extends Exception {}\n\ntest('passes', function () {\n    expect(function () {\n        throw new RuntimeException;\n    })->toThrow(RuntimeException::class);\n    expect(function () {\n        throw new RuntimeException;\n    })->toThrow(Exception::class);\n    expect(function () {\n        throw new RuntimeException;\n    })->toThrow(function (RuntimeException $e) {});\n    expect(function () {\n        throw new RuntimeException('actual message');\n    })->toThrow(function (Exception $e) {\n        expect($e->getMessage())->toBe('actual message');\n    });\n    expect(function () {})->not->toThrow(Exception::class);\n    expect(function () {\n        throw new RuntimeException('actual message');\n    })->toThrow('actual message');\n    expect(function () {\n        throw new Exception;\n    })->not->toThrow(RuntimeException::class);\n    expect(function () {\n        throw new RuntimeException('actual message');\n    })->toThrow(RuntimeException::class, 'actual message');\n    expect(function () {\n        throw new RuntimeException('actual message');\n    })->toThrow(function (RuntimeException $e) {}, 'actual message');\n    expect(function () {\n        throw new CustomException('foo');\n    })->toThrow(new CustomException('foo'));\n});\n\ntest('failures 1', function () {\n    expect(function () {})->toThrow(RuntimeException::class);\n})->throws(ExpectationFailedException::class, 'Exception \"'.RuntimeException::class.'\" not thrown.');\n\ntest('failures 2', function () {\n    expect(function () {})->toThrow(function (RuntimeException $e) {});\n})->throws(ExpectationFailedException::class, 'Exception \"'.RuntimeException::class.'\" not thrown.');\n\ntest('failures 3', function () {\n    expect(function () {\n        throw new Exception;\n    })->toThrow(function (RuntimeException $e) {\n        //\n    });\n})->throws(ExpectationFailedException::class, 'Failed asserting that an instance of class Exception is an instance of class RuntimeException.');\n\ntest('failures 4', function () {\n    expect(function () {\n        throw new Exception('actual message');\n    })\n        ->toThrow(function (Exception $e) {\n            expect($e->getMessage())->toBe('expected message');\n        });\n})->throws(ExpectationFailedException::class, 'Failed asserting that two strings are identical');\n\ntest('failures 5', function () {\n    expect(function () {\n        throw new Exception('actual message');\n    })->toThrow('expected message');\n})->throws(ExpectationFailedException::class, 'Failed asserting that \\'actual message\\' [ASCII](length: 14) contains \"expected message\" [ASCII](length: 16).');\n\ntest('failures 6', function () {\n    expect(function () {})->toThrow('actual message');\n})->throws(ExpectationFailedException::class, 'Exception with message \"actual message\" not thrown');\n\ntest('failures 7', function () {\n    expect(function () {\n        throw new RuntimeException('actual message');\n    })->toThrow(RuntimeException::class, 'expected message');\n})->throws(ExpectationFailedException::class);\n\ntest('failures 8', function () {\n    expect(function () {\n        throw new CustomException('actual message');\n    })->toThrow(new CustomException('expected message'));\n})->throws(ExpectationFailedException::class);\n\ntest('failures with custom message', function () {\n    expect(function () {\n        throw new RuntimeException('actual message');\n    })->toThrow(RuntimeException::class, 'expected message', 'oh no!');\n})->throws(ExpectationFailedException::class, 'oh no!');\n\ntest('not failures', function () {\n    expect(function () {\n        throw new RuntimeException;\n    })->not->toThrow(RuntimeException::class);\n})->throws(ExpectationFailedException::class);\n\ntest('closure missing parameter', function () {\n    expect(function () {})->toThrow(function () {});\n})->throws(InvalidArgumentException::class, 'The given closure must have a single parameter type-hinted as the class string.');\n\ntest('closure missing type-hint', function () {\n    expect(function () {})->toThrow(function ($e) {});\n})->throws(InvalidArgumentException::class, 'The given closure\\'s parameter must be type-hinted as the class string.');\n\nit('can handle a non-defined exception', function () {\n    expect(function () {\n        throw new NonExistingException;\n    })->toThrow(NonExistingException::class);\n})->throws(Error::class, 'Class \"NonExistingException\" not found');\n\nit('can handle a class not found Error', function () {\n    expect(function () {\n        throw new NonExistingException;\n    })->toThrow('Class \"NonExistingException\" not found');\n\n    expect(function () {\n        throw new NonExistingException;\n    })->toThrow(Error::class, 'Class \"NonExistingException\" not found');\n});\n"
  },
  {
    "path": "tests/Features/Expect/toUseStrictEquality.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\n\ntest('missing strict equality')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToUseStrictEquality\\\\NotStrictEquality')\n    ->toUseStrictEquality();\n\ntest('has strict equality')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToUseStrictEquality\\\\StrictEquality')\n    ->toUseStrictEquality();\n\ntest('opposite missing strict equality')\n    ->throws(ArchExpectationFailedException::class)\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToUseStrictEquality\\\\StrictEquality')\n    ->not->toUseStrictEquality();\n\ntest('opposite has strict equality')\n    ->expect('Tests\\\\Fixtures\\\\Arch\\\\ToUseStrictEquality\\\\NotStrictEquality')\n    ->not->toUseStrictEquality();\n"
  },
  {
    "path": "tests/Features/Expect/toUseStrictTypes.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\nuse Tests\\Fixtures\\Arch\\ToUseStrictTypes\\HasNoStrictType;\nuse Tests\\Fixtures\\Arch\\ToUseStrictTypes\\HasStrictType;\nuse Tests\\Fixtures\\Arch\\ToUseStrictTypes\\HasStrictTypeWithCommentsAbove;\n\ntest('pass', function () {\n    expect(HasStrictType::class)->toUseStrictTypes()\n        ->and(HasStrictTypeWithCommentsAbove::class)->toUseStrictTypes();\n});\n\ntest('failures', function () {\n    expect(HasNoStrictType::class)->toUseStrictTypes();\n})->throws(ArchExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/toUseTrait.php",
    "content": "<?php\n\nuse Pest\\Arch\\Exceptions\\ArchExpectationFailedException;\n\ntest('pass', function () {\n    expect('Pest\\Expectations\\HigherOrderExpectation')->toUseTrait('Pest\\Concerns\\Retrievable')\n        ->and('Pest\\Expectations\\EachExpectation')->not->toUseTrait('Pest\\Concerns\\Retrievable');\n});\n\ntest('failures', function () {\n    expect('Pest\\Expectations\\EachExpectation')->toUseTrait('Pest\\Concerns\\Foo');\n})->throws(ArchExpectationFailedException::class);\n\ntest('not failures', function () {\n    expect('Pest\\Expectations\\HigherOrderExpectation')->not->toUseTrait('Pest\\Concerns\\Retrievable');\n})->throws(ArchExpectationFailedException::class);\n"
  },
  {
    "path": "tests/Features/Expect/unless.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    $this->unlessObject = new stdClass;\n    $this->unlessObject->trueValue = true;\n    $this->unlessObject->foo = 'foo';\n});\n\nit('pass', function () {\n    expect('foo')\n        ->unless(\n            true,\n            function ($value) {\n                return $value->toEqual('bar');\n            }\n        )\n        ->toEqual('foo');\n\n    expect(static::getCount())->toBe(1);\n});\n\nit('failures', function () {\n    expect('foo')\n        ->unless(\n            false,\n            function ($value) {\n                return $value->toBeTrue();\n            }\n        )\n        ->toEqual('foo');\n})->throws(ExpectationFailedException::class, 'is true');\n\nit('runs with truthy', function () {\n    expect($this->unlessObject)\n        ->unless(\n            0,\n            function ($value) {\n                return $value->trueValue->toBeTrue();\n            }\n        )\n        ->foo->toEqual('foo');\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('skips with falsy', function () {\n    expect($this->unlessObject)\n        ->unless(\n            1,\n            function ($value) {\n                return $value->trueValue->toBeFalse(); // fails\n            }\n        )\n        ->unless(\n            true,\n            function ($value) {\n                return $value->trueValue->toBeFalse(); // fails\n            }\n        )\n        ->foo->toEqual('foo');\n\n    expect(static::getCount())->toBe(1);\n});\n\nit('runs with truthy closure condition', function () {\n    expect($this->unlessObject)\n        ->unless(\n            function () {\n                return '0';\n            },\n            function ($value) {\n                return $value->trueValue->toBeTrue();\n            }\n        )\n        ->foo->toEqual('foo');\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('skips with falsy closure condition', function () {\n    expect($this->unlessObject)\n        ->unless(\n            function () {\n                return '1';\n            },\n            function ($value) {\n                return $value->trueValue->toBeFalse(); // fails\n            }\n        )\n        ->foo->toEqual('foo');\n\n    expect(static::getCount())->toBe(1);\n});\n\nit('can be used in higher order tests')\n    ->expect(true)\n    ->unless(\n        function () {\n            return false;\n        },\n        function ($value) {\n            return $value->toBeFalse();\n        }\n    )\n    ->throws(ExpectationFailedException::class, 'true is false');\n"
  },
  {
    "path": "tests/Features/Expect/when.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nbeforeEach(function () {\n    $this->whenObject = new stdClass;\n    $this->whenObject->trueValue = true;\n    $this->whenObject->foo = 'foo';\n});\n\nit('pass', function () {\n    expect('foo')\n        ->when(\n            true,\n            function ($value) {\n                return $value->toEqual('foo');\n            }\n        )\n        ->toEqual('foo');\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('failures', function () {\n    expect('foo')\n        ->when(\n            true,\n            function ($value) {\n                return $value->toBeTrue();\n            }\n        )\n        ->toEqual('foo');\n})->throws(ExpectationFailedException::class, 'is true');\n\nit('runs with truthy', function () {\n    expect($this->whenObject)\n        ->when(\n            1,\n            function ($value) {\n                return $value->trueValue->toBeTrue();\n            }\n        )\n        ->foo->toEqual('foo');\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('skips with falsy', function () {\n    expect($this->whenObject)\n        ->when(\n            0,\n            function ($value) {\n                return $value->trueValue->toBeFalse(); // fails\n            }\n        )\n        ->when(\n            false,\n            function ($value) {\n                return $value->trueValue->toBeFalse(); // fails\n            }\n        )\n        ->foo->toEqual('foo');\n\n    expect(static::getCount())->toBe(1);\n});\n\nit('runs with truthy closure condition', function () {\n    expect($this->whenObject)\n        ->when(\n            function () {\n                return '1';\n            },\n            function ($value) {\n                return $value->trueValue->toBeTrue();\n            }\n        )\n        ->foo->toEqual('foo');\n\n    expect(static::getCount())->toBe(2);\n});\n\nit('skips with falsy closure condition', function () {\n    expect($this->whenObject)\n        ->when(\n            function () {\n                return '0';\n            },\n            function ($value) {\n                return $value->trueValue->toBeFalse(); // fails\n            }\n        )\n        ->foo->toEqual('foo');\n\n    expect(static::getCount())->toBe(1);\n});\n\nit('can be used in higher order tests')\n    ->expect(false)\n    ->when(\n        function () {\n            return true;\n        },\n        function ($value) {\n            return $value->toBeTrue();\n        }\n    )\n    ->throws(ExpectationFailedException::class, 'false is true');\n"
  },
  {
    "path": "tests/Features/Fail.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\AssertionFailedError;\n\nit('may fail', function () {\n    $this->fail();\n})->throws(AssertionFailedError::class);\n\nit('may fail with the given message', function () {\n    $this->fail('this is a failure');\n})->throws(AssertionFailedError::class, 'this is a failure');\n"
  },
  {
    "path": "tests/Features/Fails.php",
    "content": "<?php\n\nit('may fail', function () {\n    $this->fail();\n})->fails();\n\nit('may fail with the given message', function () {\n    $this->fail('this is a failure');\n})->fails('this is a failure');\n"
  },
  {
    "path": "tests/Features/Fixture.php",
    "content": "<?php\n\nit('may return a file path', function () {\n    $file = fixture('phpunit-in-isolation.xml');\n\n    expect($file)->toBeString()\n        ->toBeFile();\n});\n\nit('may throw an exception if the file does not exist', function () {\n    fixture('file-that-does-not-exist.php');\n})->throws(InvalidArgumentException::class);\n"
  },
  {
    "path": "tests/Features/Helpers.php",
    "content": "<?php\n\nfunction addUser()\n{\n    test()->user = 'nuno';\n}\n\nit('can set/get properties on $this', function () {\n    addUser();\n    expect($this->user)->toBe('nuno');\n});\n\nit('gets null if property do not exist', function () {\n    expect(test()->wqdwqdqw)->toBe(null);\n});\n\nclass User\n{\n    public function getName()\n    {\n        return 'nuno';\n    }\n}\n\nfunction mockUser()\n{\n    $mock = test()->createMock(User::class);\n\n    $mock->method('getName')\n        ->willReturn('maduro');\n\n    return $mock;\n}\n\nit('allows to call underlying protected/private methods', function () {\n    $user = mockUser();\n    expect($user->getName())->toBe('maduro');\n});\n\nit('throws error if method do not exist', function () {\n    test()->foo();\n})->throws(ReflectionException::class, 'Call to undefined method PHPUnit\\Framework\\TestCase::foo()');\n\nit('can forward unexpected calls to any global function')->_assertThat();\n\nit('can use helpers from helpers file')->myAssertTrue(true);\n\nit('can use helpers from helpers directory')->myDirectoryAssertTrue(true);\n"
  },
  {
    "path": "tests/Features/HigherOrderTests.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\TestCase;\n\nbeforeEach()->assertTrue(true);\n\nit('proxies calls to object')->assertTrue(true);\n\nit('is capable doing multiple assertions')\n    ->assertTrue(true)\n    ->assertFalse(false);\n\nit('resolves expect callables correctly')\n    ->expect(function () {\n        return 'foo';\n    })\n    ->toBeString()\n    ->toBe('foo')\n    ->and('bar')\n    ->toBeString()\n    ->toBe('bar');\n\ntest('does not treat method names as callables')\n    ->expect('it')->toBeString();\n\nit('can defer a method until after test setup')\n    ->expect('foo')->toBeString()\n    ->defer(function () {\n        expect($this)->toBeInstanceOf(TestCase::class);\n    })\n    ->toBe('foo')\n    ->and('hello world')->toBeString();\n\nit('can pass datasets into the expect callables')\n    ->with([[1, 2, 3]])\n    ->expect(function (...$numbers) {\n        return $numbers;\n    })->toBe([1, 2, 3])\n    ->and(function (...$numbers) {\n        return $numbers;\n    })->toBe([1, 2, 3]);\n\nit('can pass datasets into the defer callable')\n    ->with([[1, 2, 3]])\n    ->defer(function (...$numbers) {\n        expect($numbers)->toBe([1, 2, 3]);\n    });\n\nit('can pass shared datasets into callables')\n    ->with('numbers.closure.wrapped')\n    ->expect(function ($value) {\n        return $value;\n    })\n    ->and(function ($value) {\n        return $value;\n    })\n    ->defer(function ($value) {\n        expect($value)->toBeInt();\n    })\n    ->toBeInt();\n\nafterEach()->assertTrue(true);\n"
  },
  {
    "path": "tests/Features/Incompleted.php",
    "content": "<?php\n\ntest('incompleted');\n\nit('is incompleted');\n\nit('is incompleted even with method calls like skip')->skip(false);\n\nit('is incompleted even with method calls like group')->group('wtv');\n\nit('is not incompleted because of expect')->expect(true)->toBeTrue();\n\nit('is not incompleted because of assert')->assertTrue(true);\n\nit('is not incompleted because of test with assertions', function () {\n    expect(true)->toBeTrue();\n});\n\ndescribe('a \"describe\" group of tests', function () {\n    it('is incompleted');\n});\n"
  },
  {
    "path": "tests/Features/Issue.php",
    "content": "<?php\n\nbeforeEach(function () {\n    expect(true)->toBeTrue();\n})->issue(1);\n\nit('may be associated with an issue', function () {\n    expect(true)->toBeTrue();\n})->issue(2);\n\ndescribe('nested', function () {\n    it('may be associated with an issue', function () {\n        expect(true)->toBeTrue();\n    })->issue('#3');\n})->issue(4)->note('an note between an the issue')->issue([5, 6]);\n"
  },
  {
    "path": "tests/Features/It.php",
    "content": "<?php\n\nit('is a test', function () {\n    expect(['key' => 'foo'])->toHaveKey('key')->key->toBeString();\n});\n\nit('is a higher order message test')->expect(true)->toBeTrue();\n\ndescribe('a \"describe\" group of tests', function () {\n    it('is a test', function () {\n        expect(['key' => 'foo'])->toHaveKey('key')->key->toBeString();\n    });\n\n    it('is a higher order message test')->expect(true)->toBeTrue();\n});\n"
  },
  {
    "path": "tests/Features/Note.php",
    "content": "<?php\n\nbeforeEach(function () {\n    $this->note('This is before each runtime note');\n})->note('This is before each static note');\n\nit('may have a static note', function () {\n    expect(true)->toBeTrue();\n})->note('This is a note');\n\nit('may have a runtime note', function () {\n    expect(true)->toBeTrue(true);\n\n    $this->note('This is a runtime note');\n});\n\nit('may have static note and runtime note', function () {\n    expect(true)->toBeTrue(true);\n\n    $this->note('This is a runtime note');\n})->note('This is a static note');\n\ndescribe('nested', function () {\n    beforeEach(function () {\n        $this->note('This is before each describe runtime note');\n    })->note('This is before each describe static note');\n\n    it('may have static note and runtime note', function () {\n        expect(true)->toBeTrue(true);\n\n        $this->note('This is a runtime note within describe');\n    })->note('This is a static note within describe');\n\n    describe('describe nested within describe', function () {\n        beforeEach(function () {\n            $this->note('This is before each nested describe runtime note');\n        })->note('This is before each nested describe static note');\n\n        it('may have a static note and runtime note', function () {\n            expect(true)->toBeTrue(true);\n\n            $this->note('This is a runtime note within a nested describe');\n        })->note('This is a static note within a nested describe');\n    })->note('This is a nested describe static note');\n})->note('This is describe static note');\n\ndescribe('matching describe names', function () {\n    beforeEach(function () {\n        $this->note('This is before each matching describe runtime note');\n    })->note('This is before each matching describe static note');\n\n    describe('describe block', function () {\n        beforeEach(function () {\n            $this->note('This is before each matching describe runtime note');\n        })->note('This is before each matching describe static note');\n\n        it('may have a static note and runtime note', function () {\n            expect(true)->toBeTrue(true);\n\n            $this->note('This is a runtime note within a matching describe');\n        })->note('This is a static note within a matching describe');\n    })->note('This is a nested matching static note');\n\n    describe('describe block', function () {\n        beforeEach(function () {\n            $this->note('This is before each matching describe runtime note, and should not contain the matching describe notes');\n        })->note('This is before each matching describe static note, and should not contain the matching describe notes');\n\n        it('may have a static note and runtime note, that are different than the matching describe block', function () {\n            expect(true)->toBeTrue(true);\n\n            $this->note('This is a runtime note within a matching describe, and should not contain the matching describe notes');\n        })->note('This is a static note within a matching describe, and should not contain the matching describe notes');\n    })->note('This is a nested matching static note, and should not contain the matching describe notes');\n});\n\ntest('multiple notes', function () {\n    expect(true)->toBeTrue(true);\n\n    $this->note([\n        'This is a runtime note',\n        'This is another runtime note',\n    ]);\n});\n"
  },
  {
    "path": "tests/Features/Notices.php",
    "content": "<?php\n\ntest('notice', function () {\n    trigger_error('This is a notice description', E_USER_NOTICE);\n\n    expect(true)->toBeTrue();\n});\n\ndescribe('a \"describe\" group of tests', function () {\n    test('notice', function () {\n        trigger_error('This is a notice description', E_USER_NOTICE);\n\n        expect(true)->toBeTrue();\n    });\n});\n"
  },
  {
    "path": "tests/Features/Pr.php",
    "content": "<?php\n\nbeforeEach(function () {\n    expect(true)->toBeTrue();\n})->pr(1);\n\nit('may be associated with an pr', function () {\n    expect(true)->toBeTrue();\n})->pr(2);\n\ndescribe('nested', function () {\n    it('may be associated with an pr', function () {\n        expect(true)->toBeTrue();\n    })->pr('#3');\n})->pr(4)->note('an note between an the pr')->pr(['#5', 6]);\n"
  },
  {
    "path": "tests/Features/References.php",
    "content": "<?php\n\nuse Pest\\Panic;\n\nit('can reference a specific class', function () {\n    expect(Panic::class)->toBeString();\n})->references(Panic::class);\n\nit('can reference a specific class method', function () {\n    expect(Panic::with(...))->toBeCallable();\n})->references([Panic::class, 'with']);\n"
  },
  {
    "path": "tests/Features/Repeat.php",
    "content": "<?php\n\ntest('once', function () {\n    expect(true)->toBeTrue();\n})->repeat(times: 1);\n\ntest('multiple times', function () {\n    expect(true)->toBeTrue();\n})->repeat(times: 5);\n\ntest('multiple times with single dataset', function (int $number) {\n    expect([1, 2, 3])->toContain($number);\n})->repeat(times: 6)->with(['a' => 1, 'b' => 2, 'c' => 3]);\n\ntest('multiple times with multiple dataset', function (int $numberA, int $numberB) {\n    expect([1, 2, 3])->toContain($numberA)\n        ->and([4, 5, 6])->toContain($numberB);\n})->repeat(times: 7)->with(['a' => 1, 'b' => 2, 'c' => 3], [4, 5, 6]);\n\ntest('multiple times with iterator', function (int $iteration) {\n    expect($iteration)\n        ->toBeNumeric()\n        ->toBeGreaterThan(0);\n})->repeat(times: 2);\n\ntest('multiple times with repeat iterator with single dataset', function (string $letter, int $iteration) {\n    expect($letter)\n        ->toBeString()\n        ->toBeIn(['a', 'b', 'c'])\n        ->and($iteration)\n        ->toBeNumeric()\n        ->toBeGreaterThan(0);\n})->repeat(times: 2)->with(['a', 'b', 'c']);\n\ntest('multiple times with repeat iterator with multiple dataset', function (string $letterA, string $letterB, int $iteration) {\n    expect($letterA)\n        ->toBeString()\n        ->toBeIn(['a', 'b', 'c'])\n        ->and($letterB)\n        ->toBeString()\n        ->toBeIn(['d', 'e', 'f'])\n        ->and($iteration)\n        ->toBeNumeric()\n        ->toBeGreaterThan(0);\n})->repeat(times: 2)->with(['a', 'b', 'c'], ['d', 'e', 'f']);\n\ndescribe('describe blocks', function () {\n    test('multiple times', function () {\n        expect(true)->toBeTrue();\n    })->repeat(times: 3);\n\n    describe('describe with repeat', function () {\n        test('test with no repeat should repeat the number of times specified in the parent describe block', function () {\n            expect(true)->toBeTrue();\n        });\n\n        test('test with repeat should repeat the number of times specified in the test', function () {\n            expect(true)->toBeTrue();\n        })->repeat(times: 2);\n\n        describe('nested describe without repeat', function () {\n            test(\"test with no repeat should repeat the number of times specified in the parent's parent describe block\", function () {\n                expect(true)->toBeTrue();\n            });\n\n            test('test with repeat should repeat the number of times specified in the test', function () {\n                expect(true)->toBeTrue();\n            })->repeat(times: 2);\n        });\n\n        describe('nested describe with repeat', function () {\n            test('test with no repeat should repeat the number of times specified in the parent describe block', function () {\n                expect(true)->toBeTrue();\n            });\n\n            test('test with repeat should repeat the number of times specified in the test', function () {\n                expect(true)->toBeTrue();\n            })->repeat(times: 2);\n        })->repeat(times: 2);\n    })->repeat(times: 3);\n});\n\ndescribe('matching describe blocks', function () {\n    describe('describe block', function () {\n        it('should repeat the number of times specified in the parent describe block', function () {\n            expect(true)->toBeTrue();\n        });\n    })->repeat(times: 3);\n\n    describe('describe block', function () {\n        test('should not repeat the number of times of the describe block with the same name', function () {\n            expect(true)->toBeTrue();\n        });\n    });\n});\n"
  },
  {
    "path": "tests/Features/ScopedDatasets/Directory/Datasets/Scoped.php",
    "content": "<?php\n\ndataset('numbers.array', [\n    1, 2, 3, 4, 5, 'ScopedDatasets/Datasets/Scoped.php',\n]);\n"
  },
  {
    "path": "tests/Features/ScopedDatasets/Directory/NestedDirectory1/Datasets.php",
    "content": "<?php\n\ndataset('numbers.array', [\n    1, 2, 3, 4, 5, 'ScopedDatasets/NestedDirectory1/Datasets.php',\n]);\n"
  },
  {
    "path": "tests/Features/ScopedDatasets/Directory/NestedDirectory1/TestFileInNestedDirectoryWithDatasetsFile.php",
    "content": "<?php\n\n$state = new stdClass;\n$state->text = '';\ntest('uses dataset', function ($value) use ($state) {\n    $state->text .= $value;\n    expect(true)->toBe(true);\n})->with('numbers.array');\n\ntest('the right dataset is taken', function () use ($state) {\n    expect($state->text)->toBe('12345ScopedDatasets/NestedDirectory1/Datasets.php');\n});\n"
  },
  {
    "path": "tests/Features/ScopedDatasets/Directory/NestedDirectory2/TestFileInNestedDirectory.php",
    "content": "<?php\n\n$state = new stdClass;\n$state->text = '';\ntest('uses dataset', function ($value) use ($state) {\n    $state->text .= $value;\n    expect(true)->toBe(true);\n})->with('numbers.array');\n\ntest('the right dataset is taken', function () use ($state) {\n    expect($state->text)->toBe('12345ScopedDatasets/Datasets/Scoped.php');\n});\n"
  },
  {
    "path": "tests/Features/ScopedDatasets/Directory/TestFileWithLocallyDefinedDataset.php",
    "content": "<?php\n\ndataset('numbers.array', [\n    1, 2, 3, 4, 5, 'ScopedDatasets/ScopedDatasets.php',\n]);\n\n$state = new stdClass;\n$state->text = '';\ntest('uses dataset', function ($value) use ($state) {\n    $state->text .= $value;\n    expect(true)->toBe(true);\n})->with('numbers.array');\n\ntest('the right dataset is taken', function () use ($state) {\n    expect($state->text)->toBe('12345ScopedDatasets/ScopedDatasets.php');\n});\n"
  },
  {
    "path": "tests/Features/ScopedDatasets/Directory/TestFileWithScopedDataset.php",
    "content": "<?php\n\n$state = new stdClass;\n$state->text = '';\ntest('uses dataset', function ($value) use ($state) {\n    $state->text .= $value;\n    expect(true)->toBe(true);\n})->with('numbers.array');\n\ntest('the right dataset is taken', function () use ($state) {\n    expect($state->text)->toBe('12345ScopedDatasets/Datasets/Scoped.php');\n});\n"
  },
  {
    "path": "tests/Features/ScopedDatasets/TestFileOutOfScope.php",
    "content": "<?php\n\n$state = new stdClass;\n$state->text = '';\ntest('uses dataset', function ($value) use ($state) {\n    $state->text .= $value;\n    expect(true)->toBe(true);\n})->with('numbers.array');\n\ntest('the right dataset is taken', function () use ($state) {\n    expect($state->text)->toBe('12');\n});\n\nit('can see datasets defined in Pest.php file', function (string $value) use ($state) {\n    $state->text .= $value;\n    expect(true)->toBe(true);\n})->with('dataset_in_pest_file');\n\ntest('Pest.php dataset is taken', function () use ($state) {\n    expect($state->text)->toBe('12AB');\n});\n"
  },
  {
    "path": "tests/Features/See.php",
    "content": "<?php\n\nuse Pest\\Panic;\n\nit('can reference a specific class', function () {\n    expect(Panic::class)->toBeString();\n})->see(Panic::class);\n\nit('can reference a specific class method', function () {\n    expect(Panic::with(...))->toBeCallable();\n})->see([Panic::class, 'with']);\n"
  },
  {
    "path": "tests/Features/Skip.php",
    "content": "<?php\n\nbeforeEach(function () {\n    $this->shouldSkip = true;\n});\n\nit('do not skips')\n    ->skip(false)\n    ->assertTrue(true);\n\nit('skips with truthy')\n    ->skip(1)\n    ->assertTrue(false);\n\nit('skips with truthy condition by default')\n    ->skip()\n    ->assertTrue(false);\n\nit('skips with message')\n    ->skip('skipped because bar')\n    ->assertTrue(false);\n\nit('skips with truthy closure condition')\n    ->skip(function () {\n        return '1';\n    })\n    ->assertTrue(false);\n\nit('do not skips with falsy closure condition')\n    ->skip(function () {\n        return false;\n    })\n    ->assertTrue(true);\n\nit('skips with condition and message')\n    ->skip(true, 'skipped because foo')\n    ->assertTrue(false);\n\nit('skips when skip after assertion')\n    ->assertTrue(true)\n    ->skip();\n\nit('can use something in the test case as a condition')\n    ->skip(function () {\n        return $this->shouldSkip;\n    }, 'This test was skipped')\n    ->assertTrue(false);\n\nit('can user higher order callables and skip')\n    ->skip(function () {\n        return $this->shouldSkip;\n    })\n    ->expect(function () {\n        return $this->shouldSkip;\n    })\n    ->toBeFalse();\n\ndescribe('skip on describe', function () {\n    beforeEach(function () {\n        $this->ran = false;\n    });\n\n    afterEach(function () {\n        match ($this->name()) {\n            '__pest_evaluable__skip_on_describe__→__skipped_tests__→__nested_inside_skipped_block__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__skip_on_describe__→__skipped_tests__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__skip_on_describe__→_it_should_execute' => expect($this->ran)->toBe(true),\n            default => $this->fail('Unexpected test name: '.$this->name()),\n        };\n    });\n\n    describe('skipped tests', function () {\n        describe('nested inside skipped block', function () {\n            it('should not execute', function () {\n                $this->ran = true;\n                $this->fail();\n            });\n        });\n\n        it('should not execute', function () {\n            $this->ran = true;\n            $this->fail();\n        });\n    })->skip();\n\n    it('should execute', function () {\n        $this->ran = true;\n        expect($this->ran)->toBe(true);\n    });\n});\n\ndescribe('skip on beforeEach', function () {\n    beforeEach(function () {\n        $this->ran = false;\n    });\n\n    afterEach(function () {\n        match ($this->name()) {\n            '__pest_evaluable__skip_on_beforeEach__→__skipped_tests__→__nested_inside_skipped_block__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__skip_on_beforeEach__→__skipped_tests__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__skip_on_beforeEach__→_it_should_execute' => expect($this->ran)->toBe(true),\n            default => $this->fail('Unexpected test name: '.$this->name()),\n        };\n    });\n\n    describe('skipped tests', function () {\n        beforeEach()->skip();\n\n        describe('nested inside skipped block', function () {\n            it('should not execute', function () {\n                $this->ran = true;\n                $this->fail();\n            });\n        });\n\n        it('should not execute', function () {\n            $this->ran = true;\n            $this->fail();\n        });\n    });\n\n    it('should execute', function () {\n        $this->ran = true;\n        expect($this->ran)->toBe(true);\n    });\n});\n\ndescribe('matching describe with skip', function () {\n    beforeEach(function () {\n        $this->ran = false;\n    });\n\n    afterEach(function () {\n        match ($this->name()) {\n            '__pest_evaluable__matching_describe_with_skip__→__describe_block__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__matching_describe_with_skip__→__describe_block__→_it_should_execute_a_test_in_a_describe_block_with_the_same_name_as_a_skipped_describe_block' => expect($this->ran)->toBe(true),\n            '__pest_evaluable__matching_describe_with_skip__→_it_should_execute' => expect($this->ran)->toBe(true),\n            default => $this->fail('Unexpected test name: '.$this->name()),\n        };\n    });\n\n    describe('describe block', function () {\n        it('should not execute', function () {\n            $this->ran = true;\n            $this->fail();\n        });\n    })->skip();\n\n    describe('describe block', function () {\n        it('should execute a test in a describe block with the same name as a skipped describe block', function () {\n            $this->ran = true;\n        });\n    });\n\n    it('should execute', function () {\n        $this->ran = true;\n        expect($this->ran)->toBe(true);\n    });\n});\n\ndescribe('matching describe with skip on beforeEach', function () {\n    beforeEach(function () {\n        $this->ran = false;\n    });\n\n    afterEach(function () {\n        match ($this->name()) {\n            '__pest_evaluable__matching_describe_with_skip_on_beforeEach__→__describe_block__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__matching_describe_with_skip_on_beforeEach__→__describe_block__→_it_should_execute_a_test_in_a_describe_block_with_the_same_name_as_a_skipped_describe_block' => expect($this->ran)->toBe(true),\n            '__pest_evaluable__matching_describe_with_skip_on_beforeEach__→_it_should_execute' => expect($this->ran)->toBe(true),\n            default => $this->fail('Unexpected test name: '.$this->name()),\n        };\n    });\n\n    describe('describe block', function () {\n        beforeEach()->skip();\n\n        it('should not execute', function () {\n            $this->ran = true;\n            $this->fail();\n        });\n    });\n\n    describe('describe block', function () {\n        it('should execute a test in a describe block with the same name as a skipped describe block', function () {\n            $this->ran = true;\n        });\n    });\n\n    it('should execute', function () {\n        $this->ran = true;\n        expect($this->ran)->toBe(true);\n    });\n});\n\nit('does not skip after the describe block', function () {\n    expect(true)->toBeTrue();\n});\n\nit('can skip after the describe block', function () {\n    expect(true)->toBeTrue();\n})->skip();\n"
  },
  {
    "path": "tests/Features/SkipOnPhp.php",
    "content": "<?php\n\nit('can run on php version')\n    ->skipOnPhp('<=7.4.0')\n    ->assertTrue(true);\n\nit('can run on specific php version')\n    ->skipOnPhp('7.4.0')\n    ->assertTrue(true);\n\nit('can skip on php versions depending on constraint')\n    ->skipOnPhp('>=7.4.0')\n    ->assertTrue(false);\n"
  },
  {
    "path": "tests/Features/Test.php",
    "content": "<?php\n\ntest('a test', function () {\n    $this->assertArrayHasKey('key', ['key' => 'foo']);\n});\n\ntest('higher order message test')->expect(true)->toBeTrue();\n"
  },
  {
    "path": "tests/Features/TestCycle.php",
    "content": "<?php\n\nuse function PHPUnit\\Framework\\assertFalse;\n\n$foo = new stdClass;\n$foo->beforeAll = false;\n$foo->beforeEach = false;\n$foo->afterEach = false;\n$foo->afterAll = false;\n\nbeforeAll(function () use ($foo) {\n    $foo->beforeAll = true;\n});\nbeforeEach(function () use ($foo) {\n    $foo->beforeEach = true;\n});\nafterEach(function () use ($foo) {\n    $foo->afterEach = true;\n});\nafterAll(function () use ($foo) {\n    $foo->afterAll = true;\n});\n\nregister_shutdown_function(function () use ($foo) {\n    assertFalse($foo->beforeAll);\n    assertFalse($foo->beforeEach);\n    assertFalse($foo->afterEach);\n    assertFalse($foo->afterAll);\n});\n"
  },
  {
    "path": "tests/Features/ThrowsNoExceptions.php",
    "content": "<?php\n\nit('allows access to the underlying expectNotToPerformAssertions method', function () {\n    $this->expectNotToPerformAssertions();\n\n    $result = 1 + 1;\n});\n\nit('allows performing no expectations without being risky', function () {\n    $result = 1 + 1;\n})->throwsNoExceptions();\n\ndescribe('a \"describe\" group of tests', function () {\n    it('allows performing no expectations without being risky', function () {\n        $result = 1 + 1;\n    });\n})->throwsNoExceptions();\n"
  },
  {
    "path": "tests/Features/Ticket.php",
    "content": "<?php\n\nbeforeEach(function () {\n    expect(true)->toBeTrue();\n})->ticket(1);\n\nit('may be associated with an ticket', function () {\n    expect(true)->toBeTrue();\n})->ticket(2);\n\ndescribe('nested', function () {\n    it('may be associated with an ticket', function () {\n        expect(true)->toBeTrue();\n    })->ticket(3);\n})->ticket(4)->note('an note between an the ticket')->ticket([5, 6]);\n"
  },
  {
    "path": "tests/Features/Todo.php",
    "content": "<?php\n\ntodo('something todo later');\n\ntest('something todo later chained')->todo();\n\ntest('something todo later chained and with function body', function () {\n    expect(true)->toBeFalse();\n})->todo();\n\nit('does something within a file with a todo', function () {\n    expect(true)->toBeTrue();\n});\n\nit('may have an associated assignee', function () {\n    expect(true)->toBeTrue();\n})->todo(assignee: 'nunomaduro');\n\nit('may have an associated issue', function () {\n    expect(true)->toBeTrue();\n})->todo(issue: 1);\n\nit('may have an associated PR', function () {\n    expect(true)->toBeTrue();\n})->todo(pr: 1);\n\nit('may have an associated note', function () {\n    expect(true)->toBeTrue();\n})->todo(note: 'a note');\n\ndescribe('todo on describe', function () {\n    beforeEach(function () {\n        $this->ran = false;\n    });\n\n    afterEach(function () {\n        match ($this->name()) {\n            '__pest_evaluable__todo_on_describe__→__todo_block__→__nested_inside_todo_block__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe__→__todo_block__→__nested_inside_todo_block__→_it_should_set_the_note' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe__→__todo_block__→__describe_with_note__→_it_should_apply_the_note_to_a_test_without_a_todo' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe__→__todo_block__→__describe_with_note__→_it_should_apply_the_note_to_a_test_with_a_todo' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe__→__todo_block__→__describe_with_note__→_it_should_apply_the_note_as_well_as_the_note_from_the_test' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe__→__todo_block__→__describe_with_note__→__nested_describe_with_note__→_it_should_apply_all_parent_notes_to_a_test_without_a_todo' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe__→__todo_block__→__describe_with_note__→__nested_describe_with_note__→_it_should_apply_all_parent_notes_to_a_test_with_a_todo' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe__→__todo_block__→__describe_with_note__→__nested_describe_with_note__→_it_should_apply_all_parent_notes_as_well_as_the_note_from_the_test' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe__→__todo_block__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe__→_it_should_execute' => expect($this->ran)->toBe(true),\n            default => $this->fail('Unexpected test name: '.$this->name()),\n        };\n    });\n\n    describe('todo block', function () {\n        describe('nested inside todo block', function () {\n            it('should not execute', function () {\n                $this->ran = true;\n                $this->fail();\n            });\n\n            it('should set the note', function () {\n                $this->ran = true;\n                $this->fail();\n            })->todo(note: 'hi');\n        });\n\n        describe('describe with note', function () {\n            it('should apply the note to a test without a todo', function () {\n                $this->ran = true;\n                $this->fail();\n            });\n\n            it('should apply the note to a test with a todo', function () {\n                $this->ran = true;\n                $this->fail();\n            })->todo();\n\n            it('should apply the note as well as the note from the test', function () {\n                $this->ran = true;\n                $this->fail();\n            })->todo(note: 'test note');\n\n            describe('nested describe with note', function () {\n                it('should apply all parent notes to a test without a todo', function () {\n                    $this->ran = true;\n                    $this->fail();\n                });\n\n                it('should apply all parent notes to a test with a todo', function () {\n                    $this->ran = true;\n                    $this->fail();\n                })->todo();\n\n                it('should apply all parent notes as well as the note from the test', function () {\n                    $this->ran = true;\n                    $this->fail();\n                })->todo(note: 'test note');\n            })->todo(note: 'nested describe note');\n        })->todo(note: 'describe note');\n\n        it('should not execute', function () {\n            $this->ran = true;\n            $this->fail();\n        });\n    })->todo();\n\n    it('should execute', function () {\n        $this->ran = true;\n        expect($this->ran)->toBe(true);\n    });\n});\n\ndescribe('todo on describe with matching name', function () {\n    beforeEach(function () {\n        $this->ran = false;\n    });\n\n    afterEach(function () {\n        match ($this->name()) {\n            '__pest_evaluable__todo_on_describe_with_matching_name__→__describe_block__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_describe_with_matching_name__→__describe_block__→_it_should_execute_a_test_in_a_describe_block_with_the_same_name_as_a_todo_describe_block' => expect($this->ran)->toBe(true),\n            '__pest_evaluable__todo_on_describe_with_matching_name__→_it_should_execute' => expect($this->ran)->toBe(true),\n\n            default => $this->fail('Unexpected test name: '.$this->name()),\n        };\n    });\n\n    describe('describe block', function () {\n        it('should not execute', function () {\n            $this->ran = true;\n            $this->fail();\n        });\n    })->todo();\n\n    describe('describe block', function () {\n        it('should execute a test in a describe block with the same name as a todo describe block', function () {\n            $this->ran = true;\n        });\n    });\n\n    it('should execute', function () {\n        $this->ran = true;\n        expect($this->ran)->toBe(true);\n    });\n});\n\ntest('todo on test after describe block', function () {\n    $this->fail();\n})->todo();\n\ntest('todo with note on test after describe block', function () {\n    $this->fail();\n})->todo(note: 'test note');\n\ndescribe('todo on beforeEach', function () {\n    beforeEach(function () {\n        $this->ran = false;\n    });\n\n    afterEach(function () {\n        match ($this->name()) {\n            '__pest_evaluable__todo_on_beforeEach__→__todo_block__→__nested_inside_todo_block__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_beforeEach__→__todo_block__→_it_should_not_execute' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_beforeEach__→__todo_block__→__describe_with_note__→_it_should_apply_the_note_to_a_test_without_a_todo' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_beforeEach__→__todo_block__→__describe_with_note__→_it_should_apply_the_note_to_a_test_with_a_todo' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_beforeEach__→__todo_block__→__describe_with_note__→_it_should_apply_the_note_as_well_as_the_note_from_the_test' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_beforeEach__→__todo_block__→__describe_with_note__→__nested_describe_with_note__→_it_should_apply_all_parent_notes_to_a_test_without_a_todo' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_beforeEach__→__todo_block__→__describe_with_note__→__nested_describe_with_note__→_it_should_apply_all_parent_notes_to_a_test_with_a_todo' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_beforeEach__→__todo_block__→__describe_with_note__→__nested_describe_with_note__→_it_should_apply_all_parent_notes_as_well_as_the_note_from_the_test' => expect($this->ran)->toBe(false),\n            '__pest_evaluable__todo_on_beforeEach__→_it_should_execute' => expect($this->ran)->toBe(true),\n            default => $this->fail('Unexpected test name: '.$this->name()),\n        };\n    });\n\n    describe('todo block', function () {\n        beforeEach()->todo();\n\n        describe('nested inside todo block', function () {\n            it('should not execute', function () {\n                $this->ran = true;\n                $this->fail();\n            });\n        });\n\n        describe('describe with note', function () {\n            it('should apply the note to a test without a todo', function () {\n                $this->ran = true;\n                $this->fail();\n            });\n\n            it('should apply the note to a test with a todo', function () {\n                $this->ran = true;\n                $this->fail();\n            })->todo();\n\n            it('should apply the note as well as the note from the test', function () {\n                $this->ran = true;\n                $this->fail();\n            })->todo(note: 'test note');\n\n            describe('nested describe with note', function () {\n                it('should apply all parent notes to a test without a todo', function () {\n                    $this->ran = true;\n                    $this->fail();\n                });\n\n                it('should apply all parent notes to a test with a todo', function () {\n                    $this->ran = true;\n                    $this->fail();\n                })->todo();\n\n                it('should apply all parent notes as well as the note from the test', function () {\n                    $this->ran = true;\n                    $this->fail();\n                })->todo(note: 'test note');\n            })->todo(note: 'nested describe note');\n        })->todo(note: 'describe note');\n\n        it('should not execute', function () {\n            $this->ran = true;\n            $this->fail();\n        });\n    });\n\n    it('should execute', function () {\n        $this->ran = true;\n        expect($this->ran)->toBe(true);\n    });\n});\n\ntest('todo on test after describe block with beforeEach', function () {\n    $this->fail();\n})->todo();\n\ntest('todo with note on test after describe block with beforeEach', function () {\n    $this->fail();\n})->todo(note: 'test note');\n"
  },
  {
    "path": "tests/Features/Warnings.php",
    "content": "<?php\n\ntest('warning', function () {\n    $this->fooqwdfwqdfqw;\n\n    expect(true)->toBeTrue();\n});\n\ntest('user warning', function () {\n    trigger_error('This is a warning description', E_USER_WARNING);\n\n    expect(true)->toBeTrue();\n});\n\ndescribe('a \"describe\" group of tests', function () {\n    test('user warning', function () {\n        trigger_error('This is a warning description', E_USER_WARNING);\n\n        expect(true)->toBeTrue();\n    });\n});\n"
  },
  {
    "path": "tests/Features/Wip.php",
    "content": "<?php\n\nit('may have an associated assignee', function () {\n    expect(true)->toBeTrue();\n})->wip(assignee: 'nunomaduro');\n\nit('may have an associated issue', function () {\n    expect(true)->toBeTrue();\n})->wip(issue: 1);\n\nit('may have an associated PR', function () {\n    expect(true)->toBeTrue();\n})->wip(pr: 1);\n\nit('may have an associated note', function () {\n    expect(true)->toBeTrue();\n})->wip(note: 'a note');\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeIntBackedEnum/HasIntBacking/HasIntBackingEnum.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeIntBackedEnum\\HasIntBacking;\n\nenum HasIntBackingEnum: int\n{\n    case IntBacked = 1;\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeIntBackedEnum/HasStringBacking/HasStringBackingEnum.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeIntBackedEnum\\HasStringBacking;\n\nenum HasStringBackingEnum: string\n{\n    case StringBacked = 'Testing';\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeInvokable/IsInvokable/InvokableClass.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeInvokable\\IsInvokable;\n\nclass InvokableClass\n{\n    public function __invoke(): void {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeInvokable/IsInvokable/InvokableClassViaParent.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeInvokable\\IsInvokable;\n\nclass InvokableClassViaParent extends ParentInvokableClass\n{\n    //\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeInvokable/IsInvokable/InvokableClassViaTrait.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeInvokable\\IsInvokable;\n\nclass InvokableClassViaTrait\n{\n    use InvokableTrait;\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeInvokable/IsInvokable/InvokableTrait.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeInvokable\\IsInvokable;\n\ntrait InvokableTrait\n{\n    public function __invoke(): void\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeInvokable/IsInvokable/ParentInvokableClass.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeInvokable\\IsInvokable;\n\nclass ParentInvokableClass\n{\n    public function __invoke(): void {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeInvokable/IsNotInvokable/IsNotInvokableClass.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeInvokable\\IsNotInvokable;\n\nclass IsNotInvokableClass\n{\n    public function handle(): void {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeStringBackedEnum/HasIntBacking/HasIntBackingEnum.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeStringBackedEnum\\HasIntBacking;\n\nenum HasIntBackingEnum: int\n{\n    case IntBacked = 1;\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToBeStringBackedEnum/HasStringBacking/HasStringBackingEnum.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToBeStringBackedEnum\\HasStringBacking;\n\nenum HasStringBackingEnum: string\n{\n    case StringBacked = 'Testing';\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveAttribute/Attributes/AsAttribute.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveAttribute\\Attributes;\n\nuse Attribute;\n\n#[Attribute()]\nclass AsAttribute {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveAttribute/HaveAttribute/HaveAttributeClass.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveAttribute\\HaveAttribute;\n\nuse Tests\\Fixtures\\Arch\\ToHaveAttribute\\Attributes\\AsAttribute;\n\n#[AsAttribute]\nclass HaveAttributeClass {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveAttribute/NotHaveAttribute/NotHaveAttributeClass.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveAttribute\\NotHaveAttribute;\n\nclass NotHaveAttributeClass {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveConstructor/HasConstructor/HasConstructor.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveConstructor\\HasConstructor;\n\nclass HasConstructor\n{\n    public function __construct() {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveConstructor/HasNoConstructor/HasNoConstructor.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveConstructor\\HasNoConstructor;\n\nclass HasNoConstructor {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveDestructor/HasDestructor/HasDestructor.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveDestructor\\HasDestructor;\n\nclass HasDestructor\n{\n    public function __destruct() {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveDestructor/HasNoDestructor/HasNoDestructor.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveDestructor\\HasNoDestructor;\n\nclass HasNoDestructor {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveMethod/HasMethod/HasMethod.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod;\n\nclass HasMethod\n{\n    public function foo(): void {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveMethod/HasMethod/HasMethodTrait.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod;\n\ntrait HasMethodTrait\n{\n    public function foo(): void {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveMethod/HasMethod/HasMethodViaParent.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod;\n\nclass HasMethodViaParent extends ParentHasMethodClass\n{\n    //\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveMethod/HasMethod/HasMethodViaTrait.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod;\n\nclass HasMethodViaTrait\n{\n    use HasMethodTrait;\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveMethod/HasMethod/ParentHasMethodClass.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveMethod\\HasMethod;\n\nclass ParentHasMethodClass\n{\n    public function foo(): void {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveMethod/HasNoMethod/HasNoMethodClass.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveMethod\\HasNoMethod;\n\nclass HasNoMethodClass\n{\n    public function bar(): void {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHavePrefix/HasNoPrefix/ClassWithout.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHavePrefix\\HasNoPrefix;\n\nclass ClassWithout {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHavePrefix/HasPrefix/PrefixClassWith.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHavePrefix\\HasPrefix;\n\nclass PrefixClassWith {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHavePublicMethodsBesides/UserController.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHavePublicMethodsBesides;\n\nclass UserController\n{\n    public function publicMethod(): string\n    {\n        return '';\n    }\n\n    protected function protectedMethod(): string\n    {\n        return '';\n    }\n\n    private function privateMethod(): string\n    {\n        return '';\n    }\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveSuffix/HasNoSuffix/ClassWithout.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveSuffix\\HasNoSuffix;\n\nclass ClassWithout {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToHaveSuffix/HasSuffix/ClassWithSuffix.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToHaveSuffix\\HasSuffix;\n\nclass ClassWithSuffix {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToUseStrictEquality/NotStrictEquality.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToUseStrictEquality;\n\nclass NotStrictEquality\n{\n    public function test(): void\n    {\n        $a = 1;\n        $b = '1';\n\n        if ($a == $b) {\n            echo 'Equal';\n        }\n\n        if ($a != $b) {\n            echo 'Equal';\n        }\n    }\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToUseStrictEquality/StrictEquality.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToUseStrictEquality;\n\nclass StrictEquality\n{\n    public function test(): void\n    {\n        $a = 1;\n        $b = '1';\n\n        if ($a === $b) {\n            echo 'Equal';\n        }\n\n        if ($a !== $b) {\n            echo 'Equal';\n        }\n    }\n}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToUseStrictTypes/HasNoStrictType.php",
    "content": "<?php\n\nnamespace Tests\\Fixtures\\Arch\\ToUseStrictTypes;\n\nclass HasNoStrictType {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToUseStrictTypes/HasStrictType.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToUseStrictTypes;\n\nclass HasStrictType {}\n"
  },
  {
    "path": "tests/Fixtures/Arch/ToUseStrictTypes/HasStrictTypeWithCommentsAbove.php",
    "content": "<?php\n\n/** @noinspection PhpUnused */\n\n// some other comment\n\ndeclare(strict_types=1);\n\nnamespace Tests\\Fixtures\\Arch\\ToUseStrictTypes;\n\nclass HasStrictTypeWithCommentsAbove {}\n"
  },
  {
    "path": "tests/Fixtures/CollisionTest.php",
    "content": "<?php\n\ntest('error', function () {\n    throw new Exception('error');\n})->skip(! isset($_SERVER['COLLISION_TEST']));\n\ntest('success', function () {\n    expect(true)->toBeTrue();\n})->skip(! isset($_SERVER['COLLISION_TEST']));\n"
  },
  {
    "path": "tests/Fixtures/Covers/CoversClass1.php",
    "content": "<?php\n\nnamespace Tests\\Fixtures\\Covers;\n\nclass CoversClass1\n{\n    public function foo() {}\n}\n"
  },
  {
    "path": "tests/Fixtures/Covers/CoversClass2.php",
    "content": "<?php\n\nnamespace Tests\\Fixtures\\Covers;\n\nclass CoversClass2 {}\n"
  },
  {
    "path": "tests/Fixtures/Covers/CoversClass3.php",
    "content": "<?php\n\nnamespace Tests\\Fixtures\\Covers;\n\nclass CoversClass3 {}\n"
  },
  {
    "path": "tests/Fixtures/Covers/CoversTrait.php",
    "content": "<?php\n\nnamespace Tests\\Fixtures\\Covers;\n\ntrait CoversTrait {}\n"
  },
  {
    "path": "tests/Fixtures/DirectoryWithTests/ExampleTest.php",
    "content": "<?php\n\nit('example 1')->assertTrue(true);\n"
  },
  {
    "path": "tests/Fixtures/ExampleTest.php",
    "content": "<?php\n\nit('example 2')->assertTrue(true);\n"
  },
  {
    "path": "tests/Fixtures/Inheritance/Base/ExampleTest.php",
    "content": "<?php\n\nnamespace Tests\\Fixtures\\Inheritance\\Base;\n\nuse PHPUnit\\Framework\\TestCase;\n\nclass ExampleTest extends TestCase\n{\n    public function test_example()\n    {\n        $this->markTestSkipped();\n    }\n}\n"
  },
  {
    "path": "tests/Fixtures/Inheritance/ExampleTest.php",
    "content": "<?php\n\nnamespace Tests\\Fixtures\\Inheritance;\n\nclass ExampleTest extends Base\\ExampleTest\n{\n    protected $foo;\n\n    public function test_example()\n    {\n        $this->assertTrue(true);\n    }\n}\n"
  },
  {
    "path": "tests/Fixtures/UnexpectedOutput.php",
    "content": "<?php\n\ntest('output', function () {\n    echo 'this is unexpected output';\n\n    expect(true)->toBeTrue();\n})->skip(! isset($_SERVER['COLLISION_TEST']));\n"
  },
  {
    "path": "tests/Fixtures/phpunit-in-isolation.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"./vendor/phpunit/phpunit/phpunit.xsd\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n         processIsolation=\"true\"\n>\n</phpunit>\n"
  },
  {
    "path": "tests/Fixtures/phpunit-not-in-isolation.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:noNamespaceSchemaLocation=\"./vendor/phpunit/phpunit/phpunit.xsd\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n         processIsolation=\"false\"\n>\n</phpunit>\n"
  },
  {
    "path": "tests/Helpers/Helper.php",
    "content": "<?php\n\nfunction myDirectoryAssertTrue($value)\n{\n    test()->assertTrue($value);\n}\n"
  },
  {
    "path": "tests/Helpers/TestInHelpers.php",
    "content": "<?php\n\nit('executes tests in the Helpers directory', function () {\n    expect(true)->toBeTrue();\n});\n"
  },
  {
    "path": "tests/Helpers.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\TestCase;\n\n/**\n * @return TestCase\n */\nfunction myAssertTrue($value)\n{\n    test()->assertTrue($value);\n\n    return test();\n}\n"
  },
  {
    "path": "tests/Hooks/AfterEachTest.php",
    "content": "<?php\n\nbeforeEach(function () {\n    $this->ith = 0;\n});\n\npest()->afterEach(function () {\n    expect($this)\n        ->toHaveProperty('ith')\n        ->and($this->ith)\n        ->toBe(3);\n\n    $this->ith++;\n});\n\npest()->afterEach(function () {\n    expect($this)\n        ->toHaveProperty('ith')\n        ->and($this->ith)\n        ->toBe(4);\n\n    $this->ith++;\n});\n\nafterEach(function () {\n    expect($this)\n        ->toHaveProperty('ith')\n        ->and($this->ith)\n        ->toBe(5);\n\n    $this->ith++;\n});\n\ndescribe('nested', function () {\n    afterEach(function () {\n        expect($this)\n            ->toHaveProperty('ith')\n            ->and($this->ith)\n            ->toBe(6);\n\n        $this->ith++;\n    });\n\n    test('nested afterEach execution order', function () {\n        expect($this)\n            ->toHaveProperty('ith')\n            ->and($this->ith)\n            ->toBe(0);\n\n        $this->ith++;\n    });\n\n    afterEach(function () {\n        expect($this)\n            ->toHaveProperty('ith')\n            ->and($this->ith)\n            ->toBe(7);\n\n        $this->ith++;\n    });\n});\n\nafterEach(function () {\n    expect($this)\n        ->toHaveProperty('ith')\n        ->and($this->ith)\n        ->toBeBetween(6, 8);\n\n    $this->ith++;\n});\n\ntest('global afterEach execution order', function () {\n    expect($this)\n        ->toHaveProperty('ith')\n        ->and($this->ith)\n        ->toBe(0);\n\n    $this->ith++;\n});\n"
  },
  {
    "path": "tests/Hooks/BeforeAllTest.php",
    "content": "<?php\n\npest()->beforeAll(function () {\n    expect($_SERVER['globalHook']->calls->beforeAll)\n        ->toBe(0);\n\n    $_SERVER['globalHook']->calls->beforeAll++;\n});\n\nit('gets called before all tests 1', function () {\n    expect($_SERVER['globalHook']->calls->beforeAll)->toBe(1);\n})->repeat(2);\n\nit('gets called before all tests 2', function () {\n    expect($_SERVER['globalHook']->calls->beforeAll)->toBe(1);\n});\n"
  },
  {
    "path": "tests/Hooks/BeforeEachTest.php",
    "content": "<?php\n\npest()->beforeEach(function () {\n    expect($this)\n        ->toHaveProperty('baz')\n        ->and($this->baz)\n        ->toBe(1);\n\n    $this->baz = 2;\n});\n\nbeforeEach(function () {\n    expect($this)\n        ->toHaveProperty('baz')\n        ->and($this->baz)\n        ->toBe(2);\n\n    $this->baz = 3;\n});\n\ntest('global beforeEach execution order', function () {\n    expect($this)\n        ->toHaveProperty('baz')\n        ->and($this->baz)\n        ->toBe(3);\n});\n"
  },
  {
    "path": "tests/PHPUnit/CustomAffixes/@#$%^&()-_=+.php",
    "content": "<?php\n\n/*\n * NOTE: To preserve cross-platform testing compatibility we cannot use ! * and\n * other Windows reserved characters in this test's filename.\n *\n * See https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions\n */\n\nit(sprintf('runs file names like `%s`', basename(__FILE__)))->assertTrue(true);\n"
  },
  {
    "path": "tests/PHPUnit/CustomAffixes/A Test With Spaces.php",
    "content": "<?php\n\nit(sprintf('runs file names like `%s`', basename(__FILE__)))->assertTrue(true);\n"
  },
  {
    "path": "tests/PHPUnit/CustomAffixes/AdditionalFileExtension.spec.php",
    "content": "<?php\n\nit(sprintf('runs file names like `%s`', basename(__FILE__)))->assertTrue(true);\n"
  },
  {
    "path": "tests/PHPUnit/CustomAffixes/FolderWithAn@/ExampleTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\nuse PHPUnit\\Framework\\TestCase;\n\nclass MyCustomClassTest extends TestCase\n{\n    public function assertTrueIsTrue()\n    {\n        $this->assertTrue(true);\n    }\n}\n\npest()->extend(MyCustomClassTest::class);\n\ntest('custom traits can be used', function () {\n    $this->assertTrueIsTrue();\n});\n\ntest('trait applied in this file')->assertTrueIsTrue();\n"
  },
  {
    "path": "tests/PHPUnit/CustomAffixes/ManyExtensions.class.test.php",
    "content": "<?php\n\nit(sprintf('runs file names like `%s`', basename(__FILE__)))->assertTrue(true);\n"
  },
  {
    "path": "tests/PHPUnit/CustomAffixes/Test 'Case' With Quotes.php",
    "content": "<?php\n\nit(sprintf('runs file names like `%s`', basename(__FILE__)))->assertTrue(true);\n"
  },
  {
    "path": "tests/PHPUnit/CustomAffixes/kebab-case-spec.php",
    "content": "<?php\n\nit(sprintf('runs file names like `%s`', basename(__FILE__)))->assertTrue(true);\n"
  },
  {
    "path": "tests/PHPUnit/CustomAffixes/snake_case_spec.php",
    "content": "<?php\n\nit(sprintf('runs file names like `%s`', basename(__FILE__)))->assertTrue(true);\n"
  },
  {
    "path": "tests/PHPUnit/CustomTestCase/ChildTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\CustomTestCase;\n\nclass ChildTest extends ParentTest\n{\n    private function getEntity(): bool\n    {\n        return true;\n    }\n}\n"
  },
  {
    "path": "tests/PHPUnit/CustomTestCase/CustomTestCase.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\CustomTestCase;\n\nuse PHPUnit\\Framework\\TestCase;\n\nuse function PHPUnit\\Framework\\assertTrue;\n\nabstract class CustomTestCase extends TestCase\n{\n    public function assertCustomTrue()\n    {\n        assertTrue(true);\n    }\n}\n"
  },
  {
    "path": "tests/PHPUnit/CustomTestCase/ExecutedTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\CustomTestCase;\n\nuse PHPUnit\\Framework\\TestCase;\n\nuse function PHPUnit\\Framework\\assertTrue;\n\nclass ExecutedTest extends TestCase\n{\n    public static $executed = false;\n\n    #[Test]\n    public function test_that_gets_executed(): void\n    {\n        self::$executed = true;\n\n        assertTrue(true);\n    }\n}\n\n// register_shutdown_function(fn () => assertTrue(ExecutedTest::$executed));\n"
  },
  {
    "path": "tests/PHPUnit/CustomTestCase/ParentTest.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\CustomTestCase;\n\nuse PHPUnit\\Framework\\Attributes\\Test;\nuse PHPUnit\\Framework\\TestCase;\n\nuse function PHPUnit\\Framework\\assertTrue;\n\nclass ParentTest extends TestCase\n{\n    private function getEntity(): bool\n    {\n        return false;\n    }\n\n    #[Test]\n    public function test_override_method(): void\n    {\n        assertTrue($this->getEntity() || true);\n    }\n}\n"
  },
  {
    "path": "tests/PHPUnit/CustomTestCase/UsesPerDirectory.php",
    "content": "<?php\n\nuse Tests\\CustomTestCase\\CustomTestCase;\n\npest()->use(CustomTestCase::class)->in(__DIR__);\n\ntest('closure was bound to CustomTestCase', function () {\n    $this->assertCustomTrue();\n});\n"
  },
  {
    "path": "tests/PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder/CustomTestCaseInSubFolder.php",
    "content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Tests\\CustomTestCaseInSubFolders\\SubFolder\\SubFolder;\n\nuse PHPUnit\\Framework\\TestCase;\n\nclass CustomTestCaseInSubFolder extends TestCase\n{\n    public function assertCustomInSubFolderTrue()\n    {\n        $this->assertTrue(true);\n    }\n}\n"
  },
  {
    "path": "tests/PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder/UsesPerSubDirectory.php",
    "content": "<?php\n\ntest('closure was bound to CustomTestCase', function () {\n    $this->assertCustomInSubFolderTrue();\n});\n"
  },
  {
    "path": "tests/PHPUnit/CustomTestCaseInSubFolders/SubFolder2/UsesPerFile.php",
    "content": "<?php\n\nuse PHPUnit\\Framework\\TestCase;\n\ntrait MyCustomTrait\n{\n    public function assertFalseIsFalse()\n    {\n        assertFalse(false);\n    }\n}\n\nabstract class MyCustomClass extends TestCase\n{\n    public function assertTrueIsTrue()\n    {\n        $this->assertTrue(true);\n    }\n}\n\npest()->extend(MyCustomClass::class)->use(MyCustomTrait::class);\n\ntest('custom traits can be used', function () {\n    $this->assertTrueIsTrue();\n});\n\ntest('trait applied in this file')->assertTrueIsTrue();\n"
  },
  {
    "path": "tests/PHPUnit/GlobPatternTests/SubFolder/InnerFolder/UsesPerDirectoryAsPattern.php",
    "content": "<?php\n\ntest('closure was bound to CustomTestCase', function () {\n    $this->assertCustomTrue();\n});\n"
  },
  {
    "path": "tests/PHPUnit/GlobPatternTests/SubFolder2/UsesPerFileAsPattern.php",
    "content": "<?php\n\ntest('closure was bound to CustomTestCase', function () {\n    $this->assertCustomTrue();\n});\n"
  },
  {
    "path": "tests/PHPUnit/IgnorableTest.php",
    "content": "<?php\n"
  },
  {
    "path": "tests/Pest.php",
    "content": "<?php\n\nuse Tests\\CustomTestCase\\CustomTestCase;\nuse Tests\\CustomTestCaseInSubFolders\\SubFolder\\SubFolder\\CustomTestCaseInSubFolder;\n\nerror_reporting(E_ALL);\n\n$GLOBALS['__PEST_INTERNAL_TEST_SUITE'] = true;\n\npest()->project()->github('pestphp/pest');\n\npest()->in('PHPUnit/CustomTestCaseInSubFolders/SubFolder/SubFolder')->use(CustomTestCaseInSubFolder::class);\n\n// test case for all the directories inside PHPUnit/GlobPatternTests/SubFolder/\npest()->in('PHPUnit/GlobPatternTests/SubFolder/*')->extend(CustomTestCase::class);\n\n// test case for all the files that end with AsPattern.php inside PHPUnit/GlobPatternTests/SubFolder2/\npest()->in('PHPUnit/GlobPatternTests/SubFolder2/*AsPattern.php')->use(CustomTestCase::class);\n\npest()->in('Visual')->group('integration');\n\n// NOTE: global test value container to be mutated and checked across files, as needed\n$_SERVER['globalHook'] = (object) ['calls' => (object) ['beforeAll' => 0, 'afterAll' => 0]];\n\npest()\n    ->in('Hooks')\n    ->beforeEach(function () {\n        $this->baz = 0;\n    })\n    ->beforeAll(function () {\n        $_SERVER['globalHook']->beforeAll = 0;\n    })\n    ->afterEach(function () {\n        if (! isset($this->ith)) {\n            return;\n        }\n\n        assert($this->ith === 1, 'Expected $this->ith to be 1, but got '.$this->ith);\n        $this->ith++;\n    })\n    ->afterAll(function () {\n        $_SERVER['globalHook']->afterAll = 0;\n        $_SERVER['globalHook']->calls->afterAll++;\n    });\n\npest()->in('Hooks')\n    ->beforeEach(function () {\n        expect($this)\n            ->toHaveProperty('baz')\n            ->and($this->baz)\n            ->toBe(0);\n\n        $this->baz = 1;\n    })\n    ->beforeAll(function () {\n        expect($_SERVER['globalHook'])\n            ->toHaveProperty('beforeAll')\n            ->and($_SERVER['globalHook']->beforeAll)\n            ->toBe(0);\n\n        $_SERVER['globalHook']->beforeAll = 1;\n    })\n    ->afterEach(function () {\n        if (! isset($this->ith)) {\n            return;\n        }\n\n        assert($this->ith === 2, 'Expected $this->ith to be 1, but got '.$this->ith);\n        $this->ith++;\n    })\n    ->afterAll(function () {\n        expect($_SERVER['globalHook'])\n            ->toHaveProperty('afterAll')\n            ->and($_SERVER['globalHook']->afterAll)\n            ->toBe(0);\n\n        $_SERVER['globalHook']->afterAll = 1;\n    });\n\nfunction helper_returns_string()\n{\n    return 'string';\n}\n\ndataset('dataset_in_pest_file', ['A', 'B']);\n\nfunction removeAnsiEscapeSequences(string $input): ?string\n{\n    return preg_replace('#\\\\x1b[[][^A-Za-z]*[A-Za-z]#', '', $input);\n}\n"
  },
  {
    "path": "tests/Playground.php",
    "content": "<?php\n\ntest('basic', function () {\n    expect(true)->toBeTrue();\n});\n"
  },
  {
    "path": "tests/Plugins/Coverage.php",
    "content": "<?php\n\nuse Pest\\Plugins\\Coverage;\nuse Symfony\\Component\\Console\\Output\\NullOutput;\n\ntest('compute comparable coverage', function (float $givenValue, float $expectedValue) {\n    $output = new NullOutput;\n\n    $plugin = new Coverage($output);\n\n    $comparableCoverage = (fn () => $this->computeComparableCoverage($givenValue))->call($plugin);\n\n    expect($comparableCoverage)->toBe($expectedValue);\n})->with([\n    [0, 0],\n    [0.5, 0.5],\n    [1.0, 1.0],\n    [32.51, 32.5],\n    [32.12312321312312, 32.1],\n    [32.53333333333333, 32.5],\n    [32.57777771232132, 32.5],\n    [100.0, 100.0],\n]);\n"
  },
  {
    "path": "tests/Plugins/Traits.php",
    "content": "<?php\n\nit('allows global uses')->assertPluginTraitGotRegistered();\n\nit('allows multiple global uses registered in the same path')->assertSecondPluginTraitGotRegistered();\n"
  },
  {
    "path": "tests/Unit/Configuration/In.php",
    "content": "<?php\n\nuse Pest\\PendingCalls\\UsesCall;\n\nit('proxies to uses call', function () {\n    $in = pest()->in();\n\n    expect($in)->toBeInstanceOf(UsesCall::class);\n});\n"
  },
  {
    "path": "tests/Unit/Configuration/Theme.php",
    "content": "<?php\n\nuse Pest\\Configuration\\Printer;\n\nit('creates a printer instance', function () {\n    $theme = pest()->printer();\n\n    expect($theme)->toBeInstanceOf(Printer::class);\n});\n"
  },
  {
    "path": "tests/Unit/Console/Help.php",
    "content": "<?php\n\nuse Pest\\Console\\Help;\nuse Symfony\\Component\\Console\\Output\\BufferedOutput;\n\nit('outputs the help information when --help is used', function () {\n    $output = new BufferedOutput;\n    $plugin = new Help($output);\n\n    $plugin();\n    expect($output->fetch())->toContain('Pest Options:');\n});\n"
  },
  {
    "path": "tests/Unit/DatasetsTests.php",
    "content": "<?php\n\nuse Pest\\Repositories\\DatasetsRepository;\n\nit('show only the names of named datasets in their description', function () {\n    $descriptions = array_keys(DatasetsRepository::resolve([\n        [\n            'one' => [1],\n            'two' => [[2]],\n        ],\n    ], __FILE__));\n\n    expect($descriptions[0])->toBe('dataset \"one\"')\n        ->and($descriptions[1])->toBe('dataset \"two\"');\n});\n\nit('show the actual dataset of non-named datasets in their description', function () {\n    $descriptions = array_keys(DatasetsRepository::resolve([\n        [\n            [1],\n            [[2]],\n        ],\n    ], __FILE__));\n\n    expect($descriptions[0])->toBe('(1)');\n    expect($descriptions[1])->toBe('([2])');\n});\n\nit('show only the names of multiple named datasets in their description', function () {\n    $descriptions = array_keys(DatasetsRepository::resolve([\n        [\n            'one' => [1],\n            'two' => [[2]],\n        ],\n        [\n            'three' => [3],\n            'four' => [[4]],\n        ],\n    ], __FILE__));\n\n    expect($descriptions[0])->toBe('dataset \"one\" / dataset \"three\"');\n    expect($descriptions[1])->toBe('dataset \"one\" / dataset \"four\"');\n    expect($descriptions[2])->toBe('dataset \"two\" / dataset \"three\"');\n    expect($descriptions[3])->toBe('dataset \"two\" / dataset \"four\"');\n});\n\nit('show the actual dataset of multiple non-named datasets in their description', function () {\n    $descriptions = array_keys(DatasetsRepository::resolve([\n        [\n            [1],\n            [[2]],\n        ],\n        [\n            [3],\n            [[4]],\n        ],\n    ], __FILE__));\n\n    expect($descriptions[0])->toBe('(1) / (3)');\n    expect($descriptions[1])->toBe('(1) / ([4])');\n    expect($descriptions[2])->toBe('([2]) / (3)');\n    expect($descriptions[3])->toBe('([2]) / ([4])');\n});\n\nit('show the correct description for mixed named and not-named datasets', function () {\n    $descriptions = array_keys(DatasetsRepository::resolve([\n        [\n            'one' => [1],\n            [[2]],\n        ],\n        [\n            [3],\n            'four' => [[4]],\n        ],\n    ], __FILE__));\n\n    expect($descriptions[0])->toBe('dataset \"one\" / (3)');\n    expect($descriptions[1])->toBe('dataset \"one\" / dataset \"four\"');\n    expect($descriptions[2])->toBe('([2]) / (3)');\n    expect($descriptions[3])->toBe('([2]) / dataset \"four\"');\n});\n\nit('shows the correct description for long texts with newlines', function () {\n    $descriptions = array_keys(DatasetsRepository::resolve([\n        [\n            ['some very \\nlong text with \\n     newlines'],\n        ],\n    ], __FILE__));\n\n    expect($descriptions[0])->toBe('(\\'some very long text with …wlines\\')');\n});\n\nit('shows the correct description for arrays with many elements', function () {\n    $descriptions = array_keys(DatasetsRepository::resolve([\n        [\n            [[1, 2, 3, 4, 5]],\n        ],\n    ], __FILE__));\n\n    expect($descriptions[0])->toBe('([1, 2, 3, …])');\n});\n\nit('shows the correct description of datasets with html', function () {\n    $descriptions = array_keys(DatasetsRepository::resolve([\n        [\n            '<div class=\"flex items-center\"></div>',\n        ],\n    ], __FILE__));\n\n    expect($descriptions[0])->toBe('(\\'<div class=\"flex items-center\"></div>\\')');\n});\n"
  },
  {
    "path": "tests/Unit/Expectations/OppositeExpectation.php",
    "content": "<?php\n\nuse Pest\\Expectations\\OppositeExpectation;\nuse PHPUnit\\Framework\\ExpectationFailedException;\n\nit('throw expectation failed exception with string argument', function (): void {\n    $expectation = new OppositeExpectation(expect('foo'));\n\n    $expectation->throwExpectationFailedException('toBe', 'bar');\n})->throws(ExpectationFailedException::class, \"Expecting 'foo' not to be 'bar'.\");\n\nit('throw expectation failed exception with array argument', function (): void {\n    $expectation = new OppositeExpectation(expect('foo'));\n\n    $expectation->throwExpectationFailedException('toBe', ['bar']);\n})->throws(ExpectationFailedException::class, \"Expecting 'foo' not to be 'bar'.\");\n"
  },
  {
    "path": "tests/Unit/Overrides/ThrowableBuilder.php",
    "content": "<?php\n\nuse NunoMaduro\\Collision\\Contracts\\RenderableOnCollisionEditor;\nuse PHPUnit\\Event\\Code\\ThrowableBuilder;\nuse Whoops\\Exception\\Frame;\n\ntest('collision editor can be added to the stack trace', function () {\n    $exception = new class extends Exception implements RenderableOnCollisionEditor\n    {\n        public function __construct()\n        {\n            parent::__construct('test exception');\n        }\n\n        public function toCollisionEditor(): Frame\n        {\n            return new Frame([\n                'file' => __DIR__.'/../../Pest.php',\n                'line' => 5,\n            ]);\n        }\n    };\n\n    expect(str_replace(DIRECTORY_SEPARATOR, '/', ThrowableBuilder::from($exception)->stackTrace()))\n        ->toContain('tests/Unit/Overrides/../../Pest.php:5')\n        ->and(str_replace(DIRECTORY_SEPARATOR, '/', ThrowableBuilder::from(new Exception('test'))->stackTrace()))\n        ->toContain('tests/Unit/Overrides/ThrowableBuilder.php:26');\n});\n"
  },
  {
    "path": "tests/Unit/Plugins/Concerns/HandleArguments.php",
    "content": "<?php\n\nuse Pest\\Plugins\\Concerns\\HandleArguments;\n\ntest('method hasArgument', function (string $argument, bool $expectedResult) {\n    $obj = new class\n    {\n        use HandleArguments;\n    };\n\n    $arguments = [\n        '--long-argument',\n        'someValue',\n        '-a',\n        '--with-equal-sign=1337',\n    ];\n\n    expect($obj->hasArgument($argument, $arguments))->toBe($expectedResult);\n})->with([\n    ['--long-argument', true],\n    ['-a', true],\n    ['--with-equal-sign', true],\n    ['someValue', true],\n    ['--a', false],\n    ['--undefined-argument', false],\n]);\n"
  },
  {
    "path": "tests/Unit/Plugins/Environment.php",
    "content": "<?php\n\nuse Pest\\Plugins\\Environment;\n\ntest('environment is set to CI when --ci option is used', function () {\n    $previousName = Environment::name();\n\n    $plugin = new Environment;\n\n    $plugin->handleArguments(['foo', '--ci', 'bar']);\n\n    expect(Environment::name())->toBe(Environment::CI);\n\n    Environment::name($previousName);\n});\n\ntest('environment is set to Local when --ci option is not used', function () {\n    $plugin = new Environment;\n\n    $plugin->handleArguments(['foo', 'bar', 'baz']);\n\n    expect(Environment::name())->toBe(Environment::LOCAL);\n});\n"
  },
  {
    "path": "tests/Unit/Plugins/Retry.php",
    "content": "<?php\n\nuse Pest\\Plugins\\Retry;\n\nit('orders by defects and stop on defects if when --retry is used ', function () {\n    $retry = new Retry;\n\n    $arguments = $retry->handleArguments(['--retry']);\n\n    expect($arguments)->toBe([\n        '--order-by=defects',\n        '--stop-on-failure',\n    ]);\n});\n"
  },
  {
    "path": "tests/Unit/Preset.php",
    "content": "<?php\n\npest()->presets()->custom('myFramework', function (array $userNamespaces) {\n    return [\n        expect($userNamespaces)->toBe(['Pest']),\n    ];\n});\n\ntest('preset invalid name', function () {\n    $this->preset()->myAnotherFramework();\n})->throws(InvalidArgumentException::class, 'The preset [myAnotherFramework] does not exist. The available presets are [php, laravel, strict, security, relaxed, myFramework].');\n\narch()->preset()->myFramework();\n"
  },
  {
    "path": "tests/Unit/Support/Arr.php",
    "content": "<?php\n\nuse Pest\\Support\\Arr;\n\ndescribe('last', function () {\n    it('should return false for an empty arary', function () {\n        expect(Arr::last([]))->toBeFalse();\n    });\n\n    it('should return the last element for an array with a single element', function () {\n        expect(Arr::last([1]))->toBe(1);\n    });\n\n    it('should return the last element for an array without changing the internal pointer', function () {\n        $array = [1, 2, 3];\n\n        expect(Arr::last($array))->toBe(3);\n        expect(current($array))->toBe(1);\n\n        next($array);\n        expect(current($array))->toBe(2);\n        expect(Arr::last($array))->toBe(3);\n        expect(current($array))->toBe(2);\n    });\n\n    it('should return the last element for an associative array without changing the internal pointer', function () {\n        $array = ['first' => 1, 'second' => 2, 'third' => 3];\n\n        expect(Arr::last($array))->toBe(3);\n        expect(current($array))->toBe(1);\n\n        next($array);\n        expect(current($array))->toBe(2);\n        expect(Arr::last($array))->toBe(3);\n        expect(current($array))->toBe(2);\n    });\n\n    it('should return the last element for an mixed key array without changing the internal pointer', function () {\n        $array = ['first' => 1, 2, 'third' => 3];\n\n        expect(Arr::last($array))->toBe(3);\n        expect(current($array))->toBe(1);\n\n        next($array);\n        expect(current($array))->toBe(2);\n        expect(Arr::last($array))->toBe(3);\n        expect(current($array))->toBe(2);\n    });\n});\n"
  },
  {
    "path": "tests/Unit/Support/Backtrace.php",
    "content": "<?php\n\nuse Pest\\Support\\Backtrace;\n\nit('gets file name from called file', function () {\n    $a = function () {\n        return Backtrace::file();\n    };\n\n    expect($a())->toBe(__FILE__);\n});\n"
  },
  {
    "path": "tests/Unit/Support/Container.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\ShouldNotHappen;\nuse Pest\\Support\\Container;\nuse Pest\\TestSuite;\n\npest()->group('container');\n\nbeforeEach(function () {\n    $this->container = new Container;\n});\n\nit('exists')\n    ->assertTrue(class_exists(Container::class));\n\nit('gets an instance', function () {\n    $this->container->add(Container::class, $this->container);\n    expect($this->container->get(Container::class))->toBe($this->container);\n});\n\ntest('autowire', function () {\n    expect($this->container->get(Container::class))->toBeInstanceOf(Container::class);\n});\n\nit('creates an instance and resolves parameters', function () {\n    $this->container->add(Container::class, $this->container);\n    $instance = $this->container->get(ClassWithDependency::class);\n\n    expect($instance)->toBeInstanceOf(ClassWithDependency::class);\n});\n\nit('creates an instance and resolves also sub parameters', function () {\n    $this->container->add(Container::class, $this->container);\n    $instance = $this->container->get(ClassWithSubDependency::class);\n\n    expect($instance)->toBeInstanceOf(ClassWithSubDependency::class);\n});\n\nit('can resolve builtin value types', function () {\n    $this->container->add('rootPath', getcwd());\n    $this->container->add('testPath', 'tests');\n\n    $instance = $this->container->get(TestSuite::class);\n    expect($instance)->toBeInstanceOf(TestSuite::class);\n});\n\nit('cannot resolve a parameter without type', function () {\n    $this->container->get(ClassWithoutTypeParameter::class);\n})->throws(ShouldNotHappen::class);\n\nclass ClassWithDependency\n{\n    public function __construct(Container $container) {}\n}\n\nclass ClassWithSubDependency\n{\n    public function __construct(ClassWithDependency $param) {}\n}\n\nclass ClassWithoutTypeParameter\n{\n    public function __construct($param) {}\n}\n"
  },
  {
    "path": "tests/Unit/Support/DatasetInfo.php",
    "content": "<?php\n\nuse Pest\\Support\\DatasetInfo;\n\nit('can check if dataset is defined inside a Datasets directory', function (string $file, bool $inside) {\n    expect(DatasetInfo::isInsideADatasetsDirectory($file))->toBe($inside);\n})->with([\n    ['file' => '/var/www/project/tests/Datasets/Numbers.php', 'inside' => true],\n    ['file' => '/var/www/project/tests/Datasets.php', 'inside' => false],\n    ['file' => '/var/www/project/tests/Features/Datasets/Numbers.php', 'inside' => true],\n    ['file' => '/var/www/project/tests/Features/Numbers.php', 'inside' => false],\n    ['file' => '/var/www/project/tests/Features/Datasets.php', 'inside' => false],\n]);\n\nit('can check if dataset is defined inside a Datasets.php file', function (string $file, bool $inside) {\n    expect(DatasetInfo::isADatasetsFile($file))->toBe($inside);\n})->with([\n    ['file' => '/var/www/project/tests/Datasets/Numbers.php', 'inside' => false],\n    ['file' => '/var/www/project/tests/Datasets.php', 'inside' => true],\n    ['file' => '/var/www/project/tests/Features/Datasets/Numbers.php', 'inside' => false],\n    ['file' => '/var/www/project/tests/Features/Numbers.php', 'inside' => false],\n    ['file' => '/var/www/project/tests/Features/Datasets.php', 'inside' => true],\n]);\n\nit('computes the dataset scope', function (string $file, string $scope) {\n    expect(DatasetInfo::scope($file))->toBe($scope);\n})->with([\n    ['file' => '/var/www/project/tests/Datasets/Numbers.php', 'scope' => '/var/www/project/tests'],\n    ['file' => '/var/www/project/tests/Datasets.php', 'scope' => '/var/www/project/tests'],\n    ['file' => '/var/www/project/tests/Features/Datasets/Numbers.php', 'scope' => '/var/www/project/tests/Features'],\n    ['file' => '/var/www/project/tests/Features/Numbers.php', 'scope' => '/var/www/project/tests/Features/Numbers.php'],\n    ['file' => '/var/www/project/tests/Features/Datasets.php', 'scope' => '/var/www/project/tests/Features'],\n    ['file' => '/var/www/project/tests/Features/Controllers/Datasets/Numbers.php', 'scope' => '/var/www/project/tests/Features/Controllers'],\n    ['file' => '/var/www/project/tests/Features/Controllers/Numbers.php', 'scope' => '/var/www/project/tests/Features/Controllers/Numbers.php'],\n    ['file' => '/var/www/project/tests/Features/Controllers/Datasets.php', 'scope' => '/var/www/project/tests/Features/Controllers'],\n]);\n"
  },
  {
    "path": "tests/Unit/Support/ExceptionTrace.php",
    "content": "<?php\n\nuse Pest\\Support\\ExceptionTrace;\n\nit('ensures the given closures reports the correct class name', function () {\n    $closure = function () {\n        throw new Exception('Call to undefined method P\\Tests\\IntentionallyNotExisting::testBasic().');\n    };\n\n    ExceptionTrace::ensure($closure);\n})->throws(\n    Exception::class,\n    'Call to undefined method Tests\\IntentionallyNotExisting::testBasic().',\n);\n\nit('ensures the given closures reports the correct class name and suggests the [pest()] function', function () {\n    $this->get();\n})->throws(\n    Error::class,\n    'Call to undefined method Tests\\Unit\\Support\\ExceptionTrace::get(). Did you forget to use the [pest()->extend()] function? Read more at: https://pestphp.com/docs/configuring-tests',\n);\n"
  },
  {
    "path": "tests/Unit/Support/HigherOrderMessage.php",
    "content": "<?php\n\nuse Pest\\Support\\HigherOrderMessage;\n\ntest('undefined method exceptions', function () {\n    $message = new HigherOrderMessage(\n        __FILE__,\n        1,\n        'foqwdqwd',\n        []\n    );\n\n    expect(fn () => $message->call($this))->toThrow(function (ReflectionException $exception) {\n        expect($exception)\n            ->getMessage()->toBe('Call to undefined method PHPUnit\\Framework\\TestCase::foqwdqwd()')\n            ->getLine()->toBe(1)\n            ->getFile()->toBe(__FILE__);\n    });\n});\n"
  },
  {
    "path": "tests/Unit/Support/Reflection.php",
    "content": "<?php\n\nuse Pest\\Support\\Reflection;\n\nit('gets file name from closure', function () {\n    $fileName = Reflection::getFileNameFromClosure(function () {});\n\n    expect($fileName)->toBe(__FILE__);\n});\n\nit('gets property values', function () {\n    $class = new class\n    {\n        private $foo = 'bar';\n    };\n\n    $value = Reflection::getPropertyValue($class, 'foo');\n\n    expect($value)->toBe('bar');\n});\n\nclass Asd\n{\n    protected $foo = 'bar';\n\n    public function getFoo()\n    {\n        return $this->foo;\n    }\n}\n\ntrait Zxc\n{\n    protected $baz = 'qux';\n\n    public function getBaz()\n    {\n        return $this->baz;\n    }\n}\n\nclass Qwe extends Asd\n{\n    use Zxc;\n\n    protected $bar = 'baz';\n\n    public function getBar()\n    {\n        return $this->bar;\n    }\n}\n\nit('gets properties from classes', function () {\n    $reflectionClass = new ReflectionClass(Qwe::class);\n\n    $properties = Reflection::getPropertiesFromReflectionClass($reflectionClass);\n\n    $properties = array_map(fn ($property) => $property->getName(), $properties);\n\n    expect($properties)->toBe([\n        'bar',\n    ]);\n});\n\nit('gets methods from classes', function () {\n    $reflectionClass = new ReflectionClass(Qwe::class);\n\n    $methods = Reflection::getMethodsFromReflectionClass($reflectionClass);\n\n    $methods = array_map(fn ($method) => $method->getName(), $methods);\n\n    expect($methods)->toBe([\n        'getBar',\n    ]);\n});\n"
  },
  {
    "path": "tests/Unit/Support/Str.php",
    "content": "<?php\n\nuse Pest\\Support\\Str;\n\nit('evaluates the code', function ($evaluatable, $expected) {\n    $code = Str::evaluable($evaluatable);\n\n    expect($code)->toBe($expected);\n})->with([\n    ['version()', '__pest_evaluable_version__'],\n    ['version__ ', '__pest_evaluable_version_____'],\n    ['version\\\\', '__pest_evaluable_version_'],\n]);\n"
  },
  {
    "path": "tests/Unit/TestName.php",
    "content": "<?php\n\nit('may start with P', function (string $real, string $toBePrinted) {\n    $printed = preg_replace('/P\\\\\\/', '', $real, 1);\n\n    expect($printed)->toBe($toBePrinted);\n})->with([\n    ['P\\Tests\\BarTest', 'Tests\\BarTest'],\n    ['P\\Packages\\Foo', 'Packages\\Foo'],\n    ['P\\PPPackages\\Foo', 'PPPackages\\Foo'],\n    ['PPPackages\\Foo', 'PPPackages\\Foo'],\n    ['PPPackages\\Foo', 'PPPackages\\Foo'],\n]);\n\n$names = [\n    'test description' => '__pest_evaluable_test_description',\n    'test_description' => '__pest_evaluable_test__description',\n    'ふ+が+' => '__pest_evaluable_ふ_が_',\n    'ほげ' => '__pest_evaluable_ほげ',\n    '卜竹弓一十山' => '__pest_evaluable_卜竹弓一十山',\n    'アゴデヸ' => '__pest_evaluable_アゴデヸ',\n    '!p8VrB' => '__pest_evaluable__p8VrB',\n    '&amp;xe6VeKWF#n4' => '__pest_evaluable__amp_xe6VeKWF_n4',\n    '%%HurHUnw7zM!' => '__pest_evaluable___HurHUnw7zM_',\n    'rundeliekend' => '__pest_evaluable_rundeliekend',\n    'g%%c!Jt9$fy#Kf' => '__pest_evaluable_g__c_Jt9_fy_Kf',\n    'NRs*Gz2@hmB$W$BPD%%b2U%3P%z%apnwSX' => '__pest_evaluable_NRs_Gz2_hmB_W_BPD__b2U_3P_z_apnwSX',\n    'ÀÄ¤{¼÷' => '__pest_evaluable_ÀÄ¤_¼÷',\n    'ìèéàòç' => '__pest_evaluable_ìèéàòç',\n    'زهراء المعادي' => '__pest_evaluable_زهراء_المعادي',\n    'الجبيهه' => '__pest_evaluable_الجبيهه',\n    'الظهران' => '__pest_evaluable_الظهران',\n    'Каролин' => '__pest_evaluable_Каролин',\n    'অ্যান্টার্কটিকা' => '__pest_evaluable_অ্যান্টার্কটিকা',\n    'Frýdek-Místek\"' => '__pest_evaluable_Frýdek_Místek_',\n    'Allingåbro&amp;' => '__pest_evaluable_Allingåbro_amp_',\n    'Κεντροαφρικανική Δημοκρατία' => '__pest_evaluable_Κεντροαφρικανική_Δημοκρατία',\n    'آذربایجان غربی' => '__pest_evaluable_آذربایجان_غربی',\n    'זימבבואה' => '__pest_evaluable_זימבבואה',\n    'Belišće' => '__pest_evaluable_Belišće',\n    'Գվատեմալա' => '__pest_evaluable_Գվատեմալա',\n    'パプアニューギニア' => '__pest_evaluable_パプアニューギニア',\n    '富山県' => '__pest_evaluable_富山県',\n    'Қарағанды' => '__pest_evaluable_Қарағанды',\n    'Қостанай' => '__pest_evaluable_Қостанай',\n    '안양시 동안구' => '__pest_evaluable_안양시_동안구',\n    'Itālija' => '__pest_evaluable_Itālija',\n    'Honningsvåg' => '__pest_evaluable_Honningsvåg',\n    'Águeda' => '__pest_evaluable_Águeda',\n    'Râșcani' => '__pest_evaluable_Râșcani',\n    'Năsăud' => '__pest_evaluable_Năsăud',\n    'Орехово-Зуево' => '__pest_evaluable_Орехово_Зуево',\n    'Čereňany' => '__pest_evaluable_Čereňany',\n    'Moravče' => '__pest_evaluable_Moravče',\n    'Šentjernej' => '__pest_evaluable_Šentjernej',\n    'Врање' => '__pest_evaluable_Врање',\n    'Крушевац' => '__pest_evaluable_Крушевац',\n    'Åkersberga' => '__pest_evaluable_Åkersberga',\n    'บอสเนียและเฮอร์เซโกวีนา' => '__pest_evaluable_บอสเนียและเฮอร์เซโกวีนา',\n    'Birleşik Arap Emirlikleri' => '__pest_evaluable_Birleşik_Arap_Emirlikleri',\n    'Німеччина' => '__pest_evaluable_Німеччина',\n    'Nam Định' => '__pest_evaluable_Nam_Định',\n    '呼和浩特' => '__pest_evaluable_呼和浩特',\n    'test /** with comment */ should do' => '__pest_evaluable_test_____with_comment____should_do',\n];\n\nforeach ($names as $name => $methodName) {\n    test($name)\n        ->expect(fn () => static::getLatestPrintableTestCaseMethodName())\n        ->toBe($name)\n        ->and(fn () => $this->name())\n        ->toBe($methodName);\n}\n"
  },
  {
    "path": "tests/Unit/TestSuite.php",
    "content": "<?php\n\nuse Pest\\Exceptions\\DatasetMissing;\nuse Pest\\Exceptions\\TestAlreadyExist;\nuse Pest\\Exceptions\\TestClosureMustNotBeStatic;\nuse Pest\\Factories\\TestCaseMethodFactory;\nuse Pest\\TestSuite;\n\nit('does not allow to add the same test description twice', function () {\n    $testSuite = new TestSuite(getcwd(), 'tests');\n    $method = new TestCaseMethodFactory('foo', null);\n    $method->description = 'bar';\n\n    $testSuite->tests->set($method);\n    $testSuite->tests->set($method);\n})->throws(\n    TestAlreadyExist::class,\n    sprintf('A test with the description `%s` already exists in the filename `%s`.', 'bar', 'foo'),\n);\n\nit('does not allow static closures', function () {\n    $testSuite = new TestSuite(getcwd(), 'tests');\n\n    $method = new TestCaseMethodFactory('foo', static function () {});\n    $method->description = 'bar';\n\n    $testSuite->tests->set($method);\n})->throws(\n    TestClosureMustNotBeStatic::class,\n    'Test closure must not be static. Please remove the [static] keyword from the [bar] method in [foo].',\n);\n\nit('alerts users about tests with arguments but no input', function () {\n    $testSuite = new TestSuite(getcwd(), 'tests');\n\n    $method = new TestCaseMethodFactory('foo', function (int $arg) {});\n\n    $method->description = 'bar';\n\n    $testSuite->tests->set($method);\n})->throws(\n    DatasetMissing::class,\n    sprintf('A test with the description [%s] has [%d] argument(s) ([%s]) and no dataset(s) provided in [%s]', 'bar', 1, 'int $arg', 'foo'),\n);\n\nit('can return an array of all test suite filenames', function () {\n    $testSuite = new TestSuite(getcwd(), 'tests');\n\n    $method = new TestCaseMethodFactory('a', null);\n    $method->description = 'b';\n    $testSuite->tests->set($method);\n\n    $method = new TestCaseMethodFactory('c', null);\n    $method->description = 'd';\n    $testSuite->tests->set($method);\n\n    expect($testSuite->tests->getFilenames())->toEqual([\n        'a',\n        'c',\n    ]);\n});\n"
  },
  {
    "path": "tests/Visual/BeforeEachTestName.php",
    "content": "<?php\n\nbeforeEach(function () {\n    $this->description = $this->__description;\n    $this->latestDescription = self::$__latestDescription;\n});\n\ntest('description', function () {\n    expect($this->description)->toBe('description');\n});\n\ntest('latest description', function () {\n    expect($this->latestDescription)->toBe('latest description');\n});\n"
  },
  {
    "path": "tests/Visual/Collision.php",
    "content": "<?php\n\nuse Symfony\\Component\\Process\\Process;\n\ntest('collision', function (array $arguments) {\n    $output = function () use ($arguments) {\n        $process = (new Process(\n            array_merge(['php', 'bin/pest', 'tests/Fixtures/CollisionTest.php'], $arguments),\n            null,\n            ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true', 'COLLISION_TEST' => true]\n        ));\n\n        $process->run();\n\n        return removeAnsiEscapeSequences($process->getOutput());\n    };\n\n    $outputContent = explode(\"\\n\", $output());\n    array_pop($outputContent);\n    array_pop($outputContent);\n    array_pop($outputContent);\n\n    if (in_array('--parallel', $arguments)) {\n        array_pop($outputContent);\n        array_pop($outputContent);\n    }\n\n    expect(implode(\"\\n\", $outputContent))->toMatchSnapshot();\n})->with([\n    [['']],\n    // [['--parallel']],\n])->skipOnWindows();\n"
  },
  {
    "path": "tests/Visual/Help.php",
    "content": "<?php\n\nuse Symfony\\Component\\Process\\Process;\n\ntest('visual snapshot of help command output', function () {\n    $output = function () {\n        $process = (new Process(['php', 'bin/pest', '--help'], null, ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true']));\n\n        $process->run();\n\n        return removeAnsiEscapeSequences($process->getOutput());\n    };\n\n    expect($output())->toMatchSnapshot();\n})->skipOnWindows();\n"
  },
  {
    "path": "tests/Visual/JUnit.php",
    "content": "<?php\n\nuse Symfony\\Component\\Process\\Process;\n\n$run = function () {\n    $junitLogFile = tempnam(sys_get_temp_dir(), 'junit');\n\n    $process = new Process(\n        array_merge(['php', 'bin/pest', '--log-junit', $junitLogFile], func_get_args()),\n        dirname(__DIR__, 2),\n        ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true'],\n    );\n\n    $process->run();\n\n    $rawXmlContent = file_get_contents($junitLogFile);\n    unlink($junitLogFile);\n\n    // convert xml to array\n    try {\n        $xml = new SimpleXMLElement(preg_replace(\"/(<\\/?)(\\w+):([^>]*>)/\", '$1$2$3', $rawXmlContent));\n\n        return json_decode(json_encode((array) $xml), true);\n    } catch (Exception $exception) {\n        throw new XmlParseException($exception->getMessage(), $exception->getCode(), $exception->getPrevious());\n    }\n};\n\n$normalizedPath = function (string $path) {\n    return str_replace('/', DIRECTORY_SEPARATOR, $path);\n};\n\ntest('junit output', function () use ($normalizedPath, $run) {\n    $result = $run('tests/.tests/SuccessOnly.php');\n\n    expect($result['testsuite']['@attributes'])\n        ->name->toBe('Tests\\tests\\SuccessOnly')\n        ->file->toBe($normalizedPath('tests/.tests/SuccessOnly.php'))\n        ->tests->toBe('4')\n        ->assertions->toBe('4')\n        ->errors->toBe('0')\n        ->failures->toBe('0')\n        ->skipped->toBe('0');\n\n    expect($result['testsuite']['testcase'])\n        ->toHaveCount(2);\n\n    expect($result['testsuite']['testcase'][0]['@attributes'])\n        ->name->toBe('it can pass with comparison')\n        ->file->toBe($normalizedPath('tests/.tests/SuccessOnly.php::it can pass with comparison'))\n        ->class->toBe('Tests\\tests\\SuccessOnly')\n        ->classname->toBe('Tests.tests.SuccessOnly')\n        ->assertions->toBe('1')\n        ->time->toStartWith('0.0');\n});\n\ntest('junit with parallel', function () use ($normalizedPath, $run) {\n    $result = $run('tests/.tests/SuccessOnly.php', '--parallel', '--processes=1', '--filter', 'can pass with comparison');\n\n    expect($result['testsuite']['@attributes'])\n        ->name->toBe('Tests\\tests\\SuccessOnly')\n        ->file->toBe($normalizedPath('tests/.tests/SuccessOnly.php'))\n        ->tests->toBe('2')\n        ->assertions->toBe('2')\n        ->errors->toBe('0')\n        ->failures->toBe('0')\n        ->skipped->toBe('0');\n\n    expect($result['testsuite']['testcase'])\n        ->toHaveCount(2);\n\n    expect($result['testsuite']['testcase'][0]['@attributes'])\n        ->name->toBe('it can pass with comparison')\n        ->file->toBe($normalizedPath('tests/.tests/SuccessOnly.php::it can pass with comparison'))\n        ->class->toBe('Tests\\tests\\SuccessOnly')\n        ->classname->toBe('Tests.tests.SuccessOnly')\n        ->assertions->toBe('1')\n        ->time->toStartWith('0.0');\n})->skip('Not working yet');\n"
  },
  {
    "path": "tests/Visual/Parallel.php",
    "content": "<?php\n\nuse Symfony\\Component\\Process\\Process;\n\n$run = function () {\n    $process = new Process(\n        array_merge(['php', 'bin/pest', '--parallel', '--processes=3'], func_get_args()),\n        dirname(__DIR__, 2),\n        ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true'],\n    );\n\n    $process->run();\n\n    return removeAnsiEscapeSequences($process->getOutput());\n};\n\ntest('parallel', function () use ($run) {\n    expect($run('--exclude-group=integration'))\n        ->toContain('Tests:    2 deprecated, 4 warnings, 5 incomplete, 2 notices, 39 todos, 26 skipped, 1177 passed (2789 assertions)')\n        ->toContain('Parallel: 3 processes');\n})->skipOnWindows();\n\ntest('a parallel test can extend another test with same name', function () use ($run) {\n    expect($run('tests/Fixtures/Inheritance'))->toContain('Tests:    1 skipped, 2 passed (2 assertions)');\n});\n"
  },
  {
    "path": "tests/Visual/SingleTestOrDirectory.php",
    "content": "<?php\n\nuse Symfony\\Component\\Process\\Process;\n\n$run = function (string $target, $decorated = false) {\n    $process = new Process(['php', 'bin/pest', $target, '--colors=always'], dirname(__DIR__, 2),\n        ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true'],\n    );\n\n    $process->run();\n\n    return $decorated ? $process->getOutput() : removeAnsiEscapeSequences($process->getOutput());\n};\n\n$snapshot = function ($name) {\n    $testsPath = dirname(__DIR__);\n\n    return file_get_contents(implode(DIRECTORY_SEPARATOR, [\n        $testsPath,\n        '.snapshots',\n        \"$name.txt\",\n    ]));\n};\n\ntest('allows to run a single test', function () use ($run, $snapshot) {\n    expect($run('tests/Fixtures/DirectoryWithTests/ExampleTest.php'))->toContain($snapshot('allows-to-run-a-single-test'));\n})->skipOnWindows();\n\ntest('allows to run a directory', function () use ($run, $snapshot) {\n    expect($run('tests/Fixtures'))->toContain($snapshot('allows-to-run-a-directory'));\n})->skipOnWindows();\n\nit('disable decorating printer when colors is set to never', function () use ($snapshot) {\n    $process = new Process([\n        'php',\n        './bin/pest',\n        '--colors=never',\n        'tests/Fixtures/DirectoryWithTests/ExampleTest.php',\n    ], dirname(__DIR__, 2), ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true']);\n    $process->run();\n    $output = $process->getOutput();\n    expect($output)->toContain($snapshot('disable-decorating-printer'));\n})->skipOnWindows();\n"
  },
  {
    "path": "tests/Visual/Success.php",
    "content": "<?php\n\nuse Symfony\\Component\\Process\\Process;\n\ntest('visual snapshot of test suite on success', function () {\n    $testsPath = dirname(__DIR__);\n    $snapshot = implode(DIRECTORY_SEPARATOR, [\n        $testsPath,\n        '.snapshots',\n        'success.txt',\n    ]);\n\n    $output = function () use ($testsPath) {\n        $process = (new Process(\n            ['php', 'bin/pest'],\n            dirname($testsPath),\n            ['EXCLUDE' => 'integration', '--exclude-group' => 'integration', 'REBUILD_SNAPSHOTS' => false, 'PARATEST' => 0, 'COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true'],\n        ));\n\n        $process->run();\n\n        return preg_replace([\n            '#\\\\x1b[[][^A-Za-z]*[A-Za-z]#',\n            '/(Tests\\\\\\PHPUnit\\\\\\CustomAffixes\\\\\\InvalidTestName)([A-Za-z0-9]*)/',\n        ], [\n            '',\n            '$1',\n        ], $process->getOutput());\n    };\n\n    if (getenv('REBUILD_SNAPSHOTS')) {\n        $outputContent = explode(\"\\n\", $output());\n        array_pop($outputContent);\n        array_pop($outputContent);\n        array_pop($outputContent);\n\n        file_put_contents($snapshot, implode(\"\\n\", $outputContent));\n    } elseif (! getenv('EXCLUDE')) {\n        $output = explode(\"\\n\", $output());\n        array_pop($output);\n        array_pop($output);\n\n        expect(implode(\"\\n\", $output))->toContain(file_get_contents($snapshot));\n    }\n})->skip(! getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE'))\n    ->skipOnWindows();\n"
  },
  {
    "path": "tests/Visual/TeamCity.php",
    "content": "<?php\n\nuse Symfony\\Component\\Process\\Process;\n\nfunction normalize_windows_os_output(string $text): string\n{\n    $text = str_replace('\\r', '', $text);\n\n    return str_replace('\\\\', '/', $text);\n}\n\ntest('visual snapshot of team city', function (string $testFile) {\n    $testsPath = dirname(__DIR__).\"/.tests/$testFile\";\n\n    $snapshot = implode(DIRECTORY_SEPARATOR, [\n        dirname(__DIR__),\n        '.snapshots',\n        \"$testFile.inc\",\n    ]);\n\n    $output = function () use ($testsPath) {\n        $process = (new Process(\n            ['php', 'bin/pest', '--teamcity', $testsPath],\n            dirname(__DIR__, levels: 2),\n            [\n                'EXCLUDE' => 'integration',\n                'REBUILD_SNAPSHOTS' => false,\n                'PARATEST' => 0,\n                'COLLISION_IGNORE_DURATION' => 'true',\n                'FLOW_ID' => '1234',\n            ],\n        ));\n\n        $process->run();\n\n        return $process->getOutput();\n    };\n\n    if (getenv('REBUILD_SNAPSHOTS')) {\n        file_put_contents($snapshot, normalize_windows_os_output($output()));\n    } elseif (! getenv('EXCLUDE')) {\n        expect(normalize_windows_os_output($output()))->toEqual(file_get_contents($snapshot));\n    }\n})->with([\n    'Failure.php',\n    'SuccessOnly.php',\n])->skip(! getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE'));\n"
  },
  {
    "path": "tests/Visual/Todo.php",
    "content": "<?php\n\nuse Symfony\\Component\\Process\\Process;\n\n$run = function (string $target, bool $parallel) {\n    $process = new Process(['php', 'bin/pest', $target, $parallel ? '--parallel' : ''], dirname(__DIR__, 2),\n        ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true'],\n    );\n\n    $process->run();\n\n    expect($process->getExitCode())->toBe(0);\n\n    $output = $process->getOutput();\n\n    return preg_replace('/Duration: \\d+\\.\\d+s/', 'Duration: x.xxs', removeAnsiEscapeSequences($output));\n};\n\ntest('todos', function () use ($run) {\n    expect($run('--todos', false))->toMatchSnapshot();\n})->skipOnWindows()->skip(! getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE'));\n\ntest('todos in parallel', function () use ($run) {\n    expect($run('--todos', true))->toMatchSnapshot();\n})->skipOnWindows()->skip(! getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE'));\n\ntest('todo', function () use ($run) {\n    expect($run('--todo', false))->toMatchSnapshot();\n})->skipOnWindows()->skip(! getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE'));\n\ntest('todo in parallel', function () use ($run) {\n    expect($run('--todo', true))->toMatchSnapshot();\n})->skipOnWindows()->skip(! getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE'));\n"
  },
  {
    "path": "tests/Visual/Version.php",
    "content": "<?php\n\nuse Symfony\\Component\\Process\\Process;\n\ntest('visual snapshot of help command output', function () {\n    $output = function () {\n        $process = (new Process(['php', 'bin/pest', '--version'], null, ['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true']));\n\n        $process->run();\n\n        return removeAnsiEscapeSequences($process->getOutput());\n    };\n\n    expect($output())->toMatchSnapshot();\n})->skipOnWindows()->skip(! getenv('REBUILD_SNAPSHOTS') && getenv('EXCLUDE'));\n"
  },
  {
    "path": "tests-external/Features/Expect/toMatchSnapshot.php",
    "content": "<?php\n\nuse Pest\\TestSuite;\n\nbeforeEach(function () {\n    $this->snapshotable = <<<'HTML'\n        <div class=\"container\">\n            <div class=\"row\">\n                <div class=\"col-md-12\">\n                    <h1>Snapshot</h1>\n                </div>\n            </div>\n        </div>\n    HTML;\n});\n\ntest('pass with dataset', function ($data) {\n    TestSuite::getInstance()->snapshots->save($this->snapshotable);\n    [$filename] = TestSuite::getInstance()->snapshots->get();\n\n    expect($filename)->toStartWith('tests/.pest/snapshots-external/')\n        ->toEndWith('pass_with_dataset_with_data_set____my_datas_set_value___.snap')\n        ->and($this->snapshotable)->toMatchSnapshot();\n})->with(['my-datas-set-value']);\n\ndescribe('within describe', function () {\n    test('pass with dataset', function ($data) {\n        TestSuite::getInstance()->snapshots->save($this->snapshotable);\n        [$filename] = TestSuite::getInstance()->snapshots->get();\n\n        expect($filename)->toStartWith('tests/.pest/snapshots-external/')\n            ->toEndWith('pass_with_dataset_with_data_set____my_datas_set_value___.snap')\n            ->and($this->snapshotable)->toMatchSnapshot();\n    });\n})->with(['my-datas-set-value']);\n"
  }
]