diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml new file mode 100644 index 0000000..0a22667 --- /dev/null +++ b/.github/workflows/php.yml @@ -0,0 +1,49 @@ +name: Unit Tests + +on: + push: + branches: [ "3.0" ] + pull_request: + branches: [ "3.0" ] + +jobs: + test: + runs-on: ${{ matrix.operating-system }} + strategy: + matrix: + operating-system: ['ubuntu-latest'] + php-versions: [ '8.1' ] + phpunit-versions: ['latest'] + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-versions }} + + - name: Validate composer.json and composer.lock + run: composer validate --strict + + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v2 + with: + path: vendor + key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-php- + + - name: Install dependencies + run: composer install --prefer-dist --no-progress + + - name: Run test suite + run: composer unit + + - name: Run lint Tests + run: composer lint + + - name: Run CodeStyle Check + run: composer codestyle + diff --git a/.gitignore b/.gitignore index 4aa7207..e4ef782 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ -tests/result/* +tests/result vendor -.idea \ No newline at end of file +.idea +/.php-cs-fixer.cache +/.phpunit.result.cache +/.phplint-cache diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2c1b9d6..0000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: php - -cache: - directories: - - vendor - - $HOME/.composer/cache - -php: - - 7 - - 7.1 - -before_script: - - composer install --dev - -script: - - composer -v exec phpunit -- tests --bootstrap tests/bootstrap.php --exclude-group example --stderr -v --debug diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..277b18e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,136 @@ +## [2.0.1](https://github.com/Codeception/robo-paracept/releases/tag/2.0.1) Bugfix Release - TimeReporter and FailedTestsReporter + +* Fix bug where leading character was being removed from tests in the reporter instead of leading directory separator + +## [2.0.0](https://github.com/Codeception/robo-paracept/releases/tag/2.0.0) Major Release + +robo-paracept 2.0 is now released + +- support for PHP 7.4 , 8.0, 8.1 +- refactorings + +Thanks to [@DavertMik](https://github.com/DavertMik) and [@TavoNiievez](https://github.com/TavoNiievez) for their contributions. + +## [1.3.1](https://github.com/Codeception/robo-paracept/releases/tag/1.3.1) Preloading Codeception configuration + +* Loading default Codeception config to detect the main directory path +* Show warning if Codeception config was not loaded + +## [1.3.0](https://github.com/Codeception/robo-paracept/releases/tag/1.3.0) Split group improvements + +* Load PHPUnit bridge of Codeception before splitting tests +* All `Split*` to return result objects (readme updated) +* Warn if root directory for Codeception is not set when splitting by groups +* Improved matching groups by using GroupManager + +See [#96](https://github.com/Codeception/robo-paracept/pull/96) + +## [1.2.4](https://github.com/Codeception/robo-paracept/releases/tag/1.2.4) Bugfix Release HTMLMerger + +If one of the html reports wasn't created by a parallel job the merger will not longer throw an exception. +The Merger will show a warning that an expected html report wasn't found. + +## What's Changed +* Update CHANGELOG.md by [@Arhell](https://github.com/Arhell) in https://github.com/Codeception/robo-paracept/pull/90 +* Bugfix/91 fixing html merger by [@vansari](https://github.com/vansari) in https://github.com/Codeception/robo-paracept/pull/92 + +**Full Changelog**: https://github.com/Codeception/robo-paracept/compare/1.2.3...1.2.4 + +## [1.2.3](https://github.com/Codeception/robo-paracept/releases/tag/1.2.3) Bugfix Release XmlMerger + +Fix the issue that an exception is thrown if a xml report does not exists. + +## [1.2.2](https://github.com/Codeception/robo-paracept/releases/tag/1.2.2) Bugfix HTML Merger + +Fix [#31](https://github.com/Codeception/robo-paracept/issues/31) + +## [1.2.1](https://github.com/Codeception/robo-paracept/releases/tag/1.2.1) Bugfix + +Pull Request: [#82](https://github.com/Codeception/robo-paracept/pull/82) + +Calculation number of tests in groups in class TestsSplitterTask did not work as expected. +If you have a high number of Tests it was possible that the last group received a huge number of tests while all others had a stable small number of tests. + +- Fixing calculation number of tests in Groups +- Using PHP Built In round() instead of floor() + +## [1.2.0](https://github.com/Codeception/robo-paracept/releases/tag/1.2.0) + +- Bugfix for extension FailedTestsReporter and new FailedTestsMergerTask [#75](https://github.com/Codeception/robo-paracept/pull/75) + - generated Files will not be overwriten anymore + - each generated File has now a uniqid-suffix (PHP Function uniqid('', true)) + - merge generated report files from FailedTestsReporter into single file + - posibility to merge also another files into a single file + +- Bugfix src/Splitter/TestsSplitter.php::testsFrom [#78](https://github.com/Codeception/robo-paracept/pull/78) [@ccsuperstar](https://github.com/ccsuperstar) + - revert string type hint and allow array or string again + +## [1.1.1](https://github.com/Codeception/robo-paracept/releases/tag/1.1.1) Bugfix + +* Fixed return type declaraton [#68](https://github.com/Codeception/robo-paracept/pull/68) + +## [1.1.0](https://github.com/Codeception/robo-paracept/releases/tag/1.1.0) Robo-Paracept 1.1 + +* SplitFailedTests task added to split by groups failed tests only [#65](https://github.com/Codeception/robo-paracept/pull/65) +* Fixed return type in taskSplitTestFilesByGroups [#62](https://github.com/Codeception/robo-paracept/pull/62) + +## [1.0.0](https://github.com/Codeception/robo-paracept/releases/tag/1.0.0) Robo-Paracept 1.0 + +Big day for Robo-Paracept. The first stable version is released! ✈️ + +### Changes + +* **Support for modern PHP 7.3, 7.4, 8.0** +* Added support for the latest [Robo task runner](https://robo.li) +* Added **Filters** to select tests before splitting them +* Added **SplitByTime** task to use time statistics of previous runs to balance groups of tests. Thanks to [@ivan1986](https://github.com/ivan1986) + +## [0.4.2](https://github.com/Codeception/robo-paracept/releases/tag/0.4.2) Resolve dependencies when splitting tests + +[#46](https://github.com/Codeception/robo-paracept/pull/46) + +## [0.4.1](https://github.com/Codeception/robo-paracept/releases/tag/0.4.1) Release with new PHPUnit support + +* PHPUnit 6.x support in split [#45](https://github.com/Codeception/robo-paracept/pull/45) +* follow symlinks while scanning for tests [#44](https://github.com/Codeception/robo-paracept/pull/44) + +## [0.4.0](https://github.com/Codeception/robo-paracept/releases/tag/0.4.0) Minor improvements + +* [#37](https://github.com/Codeception/robo-paracept/pull/37) Added `excluePath` option to `SplitTestsByGroups` task. By [@thejanasatan](https://github.com/thejanasatan) +* [#36](https://github.com/Codeception/robo-paracept/pull/36) Added mergeRewrite to merge reports by [@maxgorovenko](https://github.com/maxgorovenko) +* [#30](https://github.com/Codeception/robo-paracept/pull/30) Fixed execute test name from data provider by [@ivan1986](https://github.com/ivan1986) + +Also PHPUnit 6 compatibility can be achieved by including Codeception's autoloader: + +```php +require 'vendor/codeception/codeception/autoload.php' +``` + +See [#35 (comment)](https://github.com/Codeception/robo-paracept/issues/35#issuecomment-311605115) + +## [0.3.1](https://github.com/Codeception/robo-paracept/releases/tag/0.3.1) 0.3.1: Merge pull request #27 from dhiva/master + +Improved HTML report merge [#27](https://github.com/Codeception/robo-paracept/pull/27) + +## [0.3.0](https://github.com/Codeception/robo-paracept/releases/tag/0.3.0) Robo 1.0 compatibility + +* Robo 1.0 compatibility (Merged [#19](https://github.com/Codeception/robo-paracept/issues/19) , Fixed [#16](https://github.com/Codeception/robo-paracept/issues/16) [#17](https://github.com/Codeception/robo-paracept/pull/17)) +* Support for `.feature` files in `SplitGroups`. Merged [#23](https://github.com/Codeception/robo-paracept/pull/23) + +## [0.2.0](https://github.com/Codeception/robo-paracept/releases/tag/0.2.0) Support for Robo 0.7-1.0 + +Fixed using with Robo >= 0.7 + +* [#12](https://github.com/Codeception/robo-paracept/pull/12) +* [#15](https://github.com/Codeception/robo-paracept/pull/15) +* Fixed [#14](https://github.com/Codeception/robo-paracept/issues/14) + +## [0.1.1](https://github.com/Codeception/robo-paracept/releases/tag/0.1.1) Codeception v2.2 and Robo 0.7 compat + +Reference + +https://codeception.com/docs/12-ParallelExecution#Robo + +## [0.1.0](https://github.com/Codeception/robo-paracept/releases/tag/0.1.0) + +To be compatible with codeception 2.2.2 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6efb163 --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +.DEFAULT_GOAL := help + +mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) +current_dir := $(dir $(mkfile_path)) + +help: + @echo "Use this makefile to execute your tests in correct php version" + @echo "\tr.php-7.4\t\trun Tests with PHP 7.4" + @echo "\tr.php-8.0\t\trun Tests with PHP 8.0" + @echo "\tr.php-8.1\t\trun Tests with PHP 8.1" + @echo "\tr.php-8.2\t\trun Tests with PHP 8.2" + +r.php-7.4: + docker build -t robo:php-7.4 --target PHP74 --build-arg PHP_VERSION=7.4 docker + docker run --rm -v $(current_dir):/app -w /app robo:php-7.4 composer install + docker run --rm -v $(current_dir):/app -w /app robo:php-7.4 composer test + +r.php-8.0: + docker build -t robo:php-8.0 --target PHP8 --build-arg PHP_VERSION=8.0 docker + docker run --rm -v $(current_dir):/app -w /app robo:php-8.0 composer install + docker run --rm -v $(current_dir):/app -w /app robo:php-8.0 composer test + +r.php-8.1: + docker build -t robo:php-8.1 --target PHP8 --build-arg PHP_VERSION=8.1 docker + docker run --rm -v $(current_dir):/app -w /app robo:php-8.1 composer install + docker run --rm -v $(current_dir):/app -w /app robo:php-8.1 composer test + +r.php-8.2: + docker build -t robo:php-8.2 --target PHP8 --build-arg PHP_VERSION=8.2 docker + docker run --rm -v $(current_dir):/app -w /app robo:php-8.2 composer install + docker run --rm -v $(current_dir):/app -w /app robo:php-8.2 composer test \ No newline at end of file diff --git a/README.md b/README.md index e05cf8c..900ee5b 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,138 @@ robo-paracept ============= -[![Build Status](https://travis-ci.org/Codeception/robo-paracept.svg?branch=master)](https://travis-ci.org/Codeception/robo-paracept) +[![PHP Composer](https://github.com/Codeception/robo-paracept/actions/workflows/php.yml/badge.svg)](https://github.com/Codeception/robo-paracept/actions/workflows/php.yml) [![Latest Stable Version](https://poser.pugx.org/codeception/robo-paracept/version)](https://packagist.org/packages/codeception/robo-paracept) [![Total Downloads](https://poser.pugx.org/codeception/robo-paracept/downloads)](https://packagist.org/packages/codeception/robo-paracept) [![License](https://poser.pugx.org/codeception/robo-paracept/license)](https://packagist.org/packages/codeception/robo-paracept) -Robo tasks for Codeception tests parallel execution. Requires [Robo Task Runner](http://robo.li) +Robo tasks for Codeception tests parallel execution. Requires [Robo Task Runner](https://robo.li) ## Install via Composer ``` -"codeception/robo-paracept":"~0.4" +composer require codeception/robo-paracept --dev ``` Include into your RoboFile ```php -``` - -### PHPUnit 6 compatiblity - -Add ` 'vendor/codeception/codeception/autoload.php'` to enabled PHPUnit 6 class names: - -```php -require_once 'vendor/codeception/codeception/autoload.php'; ``` ## Idea Parallel execution of Codeception tests can be implemented in different ways. Depending on a project the actual needs can be different. -Thus, we are going to prepare a set of predefined tasks that can be combined and reconfigured to fit needs. +So we prepared a set of predefined Robo tasks that can be combined and reconfigured to fit your needs. ## Tasks ### SplitTestsByGroups -Loads tests from a folder and distributes them between groups. +Load tests from a folder and distributes them between groups. ```php -$this->taskSplitTestsByGroups(5) +$result = $this->taskSplitTestsByGroups(5) ->testsFrom('tests/acceptance') ->projectRoot('.') ->groupsTo('tests/_data/group_') ->run(); + +// task returns a result which contains information about processed data: +// optionally check result data +if ($result->wasSuccessful()) { + $groups = $result['groups']; + $tests = $result['tests']; + $filenames = $result['files']; +} ``` -this command uses `Codeception\Test\Loader` to load tests and organize them between group. If you want just split test file and not actual tests (and not load tests into memory) you can use: +> This command **loads Codeception into memory**, loads and parses tests to organize them between group. If you want just split test file and not actual tests (and not load tests into memory) use `taskSplitTestFilesByGroups`: + +### SplitTestFilesByGroups + +To split tests by suites (files) without loading them into memory use `taskSplitTestFilesByGroups` method: ```php -$this->taskSplitTestFilesByGroups(5) +$result = $this->taskSplitTestFilesByGroups(5) ->testsFrom('tests') ->groupsTo('tests/_data/paratest_') ->run(); + +// optionally check result data +if ($result->wasSuccessful()) { + $filenames = $result['files']; +} +``` + +### SplitTestsByTime + +Enable extension for collect execution time of you use taskSplitTestsByTime + +``` +extensions: + enabled: + - Codeception\Task\Extension\TimeReporter +``` + +Load tests from a folder and distributes them between groups by execution time. + +```php +$result = $this->taskSplitTestsByTime(5) + ->testsFrom('tests/acceptance') + ->projectRoot('.') + ->groupsTo('tests/_data/group_') + ->run(); + +// optionally check result data +if ($result->wasSuccessful()) { + $filenames = $result['files']; +} +``` + +this command need run all tests with `Codeception\Task\TimeReporter` for collect execution time. If you want just split tests between group (and not execute its) you can use SplitTestsByGroups. **Please be aware**: This task will not consider any 'depends' annotation! + +### SplitFailedTests + +Enable extension for collect failed tests if you use taskSplitFailedTests +The extension saves the report files into \Codeception\Configuration::outputDir() + +``` +extensions: + enabled: + - Codeception\Task\Extension\FailedTestsReporter +``` + +Merge the created report files from the FailedTestsReporter into single file +```php +$this->taskMergeFailedTestsReports() + ->fromPathWithPattern(\Codeception\Configuration::outputDir(), '/failedTests_\w+\.txt$/') + ->into(\Codeception\Configuration::outputDir() . 'failedTests.txt') // absolute path with Filename + ->run(); +``` + +Load the failed Tests from a reportfile into the groups: +```php +$result = $this + ->taskSplitFailedTests(5) + ->setReportPath(\Codeception\Configuration::outputDir() . 'failedTests.txt') // absoulute Path to Reportfile + ->groupsTo(\Codeception\Configuration::outputDir() . 'group_') + ->run(); + +// optionally check result data +if ($result->wasSuccessful()) { + $filenames = $result['files']; +} ``` ### MergeXmlReports @@ -90,3 +159,89 @@ $this->taskMergeHtmlReports() ->into('tests/result/merged.html') ->run(); ``` + + +## Filters + +You can use a custom filter to select the necessary tests. + +Two filters already included: DefaultFilter, GroupFilter + +* **DefaultFilter** is enabled by default, takes all tests. +* **GroupFilter** _(Can only be used by taskSplitTestsByGroups)_, allows you to filter the loaded tests by the given groups. You have the possibility to declare groups which you want to include or exclude. If you declare foo and bar as included, only tests with this both group annotations will be matched. The same thing is happend when you add excluded groups. If you combine the included and excluded group the only tests which have exactly the correct group annotations for the included items and none of the excluded items. + +You can add as many filters as you want. The FIFO (First In - First Out) principle applies. The next filter will only get the result of the filter before. + +### Usage + +For example, you want all tests which have in the doc comment the groups 'foo' AND 'bar' but not 'baz' then you can do it like this: + +```php +$filter = new GroupFilter(); +$filter + ->groupIncluded('foo') + ->groupIncluded('bar') + ->groupExcluded('baz'); + +$this->taskSplitTestsByGroups(5) + ->testsFrom('tests') + ->groupsTo('tests/_data/paratest_') + ->addFilter($filter) + ->run(); +``` + +Now create your own filter class: +```php +=5.4.0", - "psr/log": "^1", - "symfony/console": "^2.8|^3|^4", - "symfony/event-dispatcher": "^2.5|^3|^4", - "symfony/finder": "^2.5|^3|^4" + "consolidation/output-formatters": "^4.1.1", + "php": ">=7.1.3", + "psr/log": "^1|^2|^3", + "symfony/console": "^4.4.8|^5|^6", + "symfony/event-dispatcher": "^4.4.8|^5|^6", + "symfony/finder": "^4.4.8|^5|^6" }, "require-dev": { - "g1a/composer-test-scenarios": "^3", - "php-coveralls/php-coveralls": "^1", - "phpunit/phpunit": "^6", - "squizlabs/php_codesniffer": "^2.7" + "composer-runtime-api": "^2.0", + "phpunit/phpunit": "^7.5.20 || ^8 || ^9", + "squizlabs/php_codesniffer": "^3", + "yoast/phpunit-polyfills": "^0.2.0" }, "type": "library", "extra": { - "scenarios": { - "symfony4": { - "require": { - "symfony/console": "^4.0" - }, - "config": { - "platform": { - "php": "7.1.3" - } - } - }, - "symfony2": { - "require": { - "symfony/console": "^2.8" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36" - }, - "remove": [ - "php-coveralls/php-coveralls" - ], - "config": { - "platform": { - "php": "5.4.8" - } - }, - "scenario-options": { - "create-lockfile": "false" - } - }, - "phpunit4": { - "require-dev": { - "phpunit/phpunit": "^4.8.36" - }, - "remove": [ - "php-coveralls/php-coveralls" - ], - "config": { - "platform": { - "php": "5.4.8" - } - } - } - }, "branch-alias": { - "dev-master": "2.x-dev" + "dev-main": "4.x-dev" } }, "autoload": { @@ -100,42 +137,48 @@ } ], "description": "Initialize Symfony Console commands from annotated command class methods.", - "time": "2018-12-29T04:43:17+00:00" + "support": { + "issues": "https://github.com/consolidation/annotated-command/issues", + "source": "https://github.com/consolidation/annotated-command/tree/4.6.1" + }, + "time": "2022-11-09T18:31:17+00:00" }, { "name": "consolidation/config", - "version": "1.1.1", + "version": "2.1.2", "source": { "type": "git", "url": "https://github.com/consolidation/config.git", - "reference": "925231dfff32f05b787e1fddb265e789b939cf4c" + "reference": "597f8d7fbeef801736250ec10c3e190569b1b0ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/config/zipball/925231dfff32f05b787e1fddb265e789b939cf4c", - "reference": "925231dfff32f05b787e1fddb265e789b939cf4c", + "url": "https://api.github.com/repos/consolidation/config/zipball/597f8d7fbeef801736250ec10c3e190569b1b0ae", + "reference": "597f8d7fbeef801736250ec10c3e190569b1b0ae", "shasum": "" }, "require": { - "dflydev/dot-access-data": "^1.1.0", - "grasmash/expander": "^1", - "php": ">=5.4.0" + "dflydev/dot-access-data": "^1.1.0 || ^2 || ^3", + "grasmash/expander": "^2.0.1 || ^3", + "php": ">=7.1.3", + "symfony/event-dispatcher": "^4 || ^5 || ^6" }, "require-dev": { - "g1a/composer-test-scenarios": "^1", - "phpunit/phpunit": "^5", - "satooshi/php-coveralls": "^1.0", - "squizlabs/php_codesniffer": "2.*", - "symfony/console": "^2.5|^3|^4", - "symfony/yaml": "^2.8.11|^3|^4" + "ext-json": "*", + "phpunit/phpunit": ">=7.5.20", + "squizlabs/php_codesniffer": "^3", + "symfony/console": "^4 || ^5 || ^6", + "symfony/yaml": "^4 || ^5 || ^6", + "yoast/phpunit-polyfills": "^1" }, "suggest": { + "symfony/event-dispatcher": "Required to inject configuration into Command options", "symfony/yaml": "Required to use Consolidation\\Config\\Loader\\YamlConfigLoader" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-main": "2.x-dev" } }, "autoload": { @@ -154,78 +197,40 @@ } ], "description": "Provide configuration services for a commandline tool.", - "time": "2018-10-24T17:55:35+00:00" + "support": { + "issues": "https://github.com/consolidation/config/issues", + "source": "https://github.com/consolidation/config/tree/2.1.2" + }, + "time": "2022-10-06T17:48:03+00:00" }, { "name": "consolidation/log", - "version": "1.1.1", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/consolidation/log.git", - "reference": "b2e887325ee90abc96b0a8b7b474cd9e7c896e3a" + "reference": "caaad9d70dae54eb49002666f000e3c607066878" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/log/zipball/b2e887325ee90abc96b0a8b7b474cd9e7c896e3a", - "reference": "b2e887325ee90abc96b0a8b7b474cd9e7c896e3a", + "url": "https://api.github.com/repos/consolidation/log/zipball/caaad9d70dae54eb49002666f000e3c607066878", + "reference": "caaad9d70dae54eb49002666f000e3c607066878", "shasum": "" }, "require": { - "php": ">=5.4.5", - "psr/log": "^1.0", - "symfony/console": "^2.8|^3|^4" + "php": ">=8.0.0", + "psr/log": "^3", + "symfony/console": "^5 || ^6" }, "require-dev": { - "g1a/composer-test-scenarios": "^3", - "php-coveralls/php-coveralls": "^1", - "phpunit/phpunit": "^6", - "squizlabs/php_codesniffer": "^2" + "phpunit/phpunit": ">=7.5.20", + "squizlabs/php_codesniffer": "^3", + "yoast/phpunit-polyfills": "^0.2.0" }, "type": "library", "extra": { - "scenarios": { - "symfony4": { - "require": { - "symfony/console": "^4.0" - }, - "config": { - "platform": { - "php": "7.1.3" - } - } - }, - "symfony2": { - "require": { - "symfony/console": "^2.8" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36" - }, - "remove": [ - "php-coveralls/php-coveralls" - ], - "config": { - "platform": { - "php": "5.4.8" - } - } - }, - "phpunit4": { - "require-dev": { - "phpunit/phpunit": "^4.8.36" - }, - "remove": [ - "php-coveralls/php-coveralls" - ], - "config": { - "platform": { - "php": "5.4.8" - } - } - } - }, "branch-alias": { - "dev-master": "1.x-dev" + "dev-main": "2.x-dev" } }, "autoload": { @@ -244,36 +249,39 @@ } ], "description": "Improved Psr-3 / Psr\\Log logger based on Symfony Console components.", - "time": "2019-01-01T17:30:51+00:00" + "support": { + "issues": "https://github.com/consolidation/log/issues", + "source": "https://github.com/consolidation/log/tree/3.0.0" + }, + "time": "2022-04-05T16:53:32+00:00" }, { "name": "consolidation/output-formatters", - "version": "3.4.0", + "version": "4.2.3", "source": { "type": "git", "url": "https://github.com/consolidation/output-formatters.git", - "reference": "a942680232094c4a5b21c0b7e54c20cce623ae19" + "reference": "cbb50cc86775f14972003f797b61e232788bee1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/a942680232094c4a5b21c0b7e54c20cce623ae19", - "reference": "a942680232094c4a5b21c0b7e54c20cce623ae19", + "url": "https://api.github.com/repos/consolidation/output-formatters/zipball/cbb50cc86775f14972003f797b61e232788bee1f", + "reference": "cbb50cc86775f14972003f797b61e232788bee1f", "shasum": "" }, "require": { - "dflydev/dot-access-data": "^1.1.0", - "php": ">=5.4.0", - "symfony/console": "^2.8|^3|^4", - "symfony/finder": "^2.5|^3|^4" + "dflydev/dot-access-data": "^1.1.0 || ^2 || ^3", + "php": ">=7.1.3", + "symfony/console": "^4|^5|^6", + "symfony/finder": "^4|^5|^6" }, "require-dev": { - "g1a/composer-test-scenarios": "^2", - "phpunit/phpunit": "^5.7.27", - "satooshi/php-coveralls": "^2", - "squizlabs/php_codesniffer": "^2.7", - "symfony/console": "3.2.3", - "symfony/var-dumper": "^2.8|^3|^4", - "victorjonsson/markdowndocs": "^1.3" + "php-coveralls/php-coveralls": "^2.4.2", + "phpunit/phpunit": ">=7", + "squizlabs/php_codesniffer": "^3", + "symfony/var-dumper": "^4|^5|^6", + "symfony/yaml": "^4|^5|^6", + "yoast/phpunit-polyfills": "^0.2.0" }, "suggest": { "symfony/var-dumper": "For using the var_dump formatter" @@ -281,7 +289,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.x-dev" + "dev-main": "4.x-dev" } }, "autoload": { @@ -300,98 +308,63 @@ } ], "description": "Format text by applying transformations provided by plug-in formatters.", - "time": "2018-10-19T22:35:38+00:00" + "support": { + "issues": "https://github.com/consolidation/output-formatters/issues", + "source": "https://github.com/consolidation/output-formatters/tree/4.2.3" + }, + "time": "2022-10-17T04:01:40+00:00" }, { "name": "consolidation/robo", - "version": "1.4.3", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/consolidation/Robo.git", - "reference": "d0b6f516ec940add7abed4f1432d30cca5f8ae0c" + "url": "https://github.com/consolidation/robo.git", + "reference": "86b4c35770a9e734112571b3b73e13bd03ac710e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/Robo/zipball/d0b6f516ec940add7abed4f1432d30cca5f8ae0c", - "reference": "d0b6f516ec940add7abed4f1432d30cca5f8ae0c", + "url": "https://api.github.com/repos/consolidation/robo/zipball/86b4c35770a9e734112571b3b73e13bd03ac710e", + "reference": "86b4c35770a9e734112571b3b73e13bd03ac710e", "shasum": "" }, "require": { - "consolidation/annotated-command": "^2.10.2", - "consolidation/config": "^1.0.10", - "consolidation/log": "~1", - "consolidation/output-formatters": "^3.1.13", - "consolidation/self-update": "^1", - "grasmash/yaml-expander": "^1.3", - "league/container": "^2.2", - "php": ">=5.5.0", - "symfony/console": "^2.8|^3|^4", - "symfony/event-dispatcher": "^2.5|^3|^4", - "symfony/filesystem": "^2.5|^3|^4", - "symfony/finder": "^2.5|^3|^4", - "symfony/process": "^2.5|^3|^4" + "consolidation/annotated-command": "^4.3", + "consolidation/config": "^2.0.1", + "consolidation/log": "^2.0.2 || ^3", + "consolidation/output-formatters": "^4.1.2", + "consolidation/self-update": "^2.0", + "league/container": "^3.3.1 || ^4.0", + "php": ">=8.0", + "phpowermove/docblock": "^4.0", + "symfony/console": "^6", + "symfony/event-dispatcher": "^6", + "symfony/filesystem": "^6", + "symfony/finder": "^6", + "symfony/process": "^6", + "symfony/yaml": "^6" }, - "replace": { - "codegyre/robo": "< 1.0" + "conflict": { + "codegyre/robo": "*" }, "require-dev": { - "codeception/aspect-mock": "^1|^2.1.1", - "codeception/base": "^2.3.7", - "codeception/verify": "^0.3.2", - "g1a/composer-test-scenarios": "^3", - "goaop/framework": "~2.1.2", - "goaop/parser-reflection": "^1.1.0", "natxet/cssmin": "3.0.4", - "nikic/php-parser": "^3.1.5", - "patchwork/jsqueeze": "~2", - "pear/archive_tar": "^1.4.2", - "php-coveralls/php-coveralls": "^1", - "phpunit/php-code-coverage": "~2|~4", - "squizlabs/php_codesniffer": "^2.8" + "patchwork/jsqueeze": "^2", + "pear/archive_tar": "^1.4.4", + "phpunit/phpunit": "^7.5.20 || ^8", + "squizlabs/php_codesniffer": "^3.6", + "yoast/phpunit-polyfills": "^0.2.0" }, "suggest": { - "henrikbjorn/lurker": "For monitoring filesystem changes in taskWatch", - "natxet/CssMin": "For minifying CSS files in taskMinify", + "natxet/cssmin": "For minifying CSS files in taskMinify", "patchwork/jsqueeze": "For minifying JS files in taskMinify", - "pear/archive_tar": "Allows tar archives to be created and extracted in taskPack and taskExtract, respectively." + "pear/archive_tar": "Allows tar archives to be created and extracted in taskPack and taskExtract, respectively.", + "totten/lurkerlite": "For monitoring filesystem changes in taskWatch" }, "bin": [ "robo" ], "type": "library", - "extra": { - "scenarios": { - "symfony4": { - "require": { - "symfony/console": "^4" - }, - "config": { - "platform": { - "php": "7.1.3" - } - } - }, - "symfony2": { - "require": { - "symfony/console": "^2.8" - }, - "remove": [ - "goaop/framework" - ], - "config": { - "platform": { - "php": "5.5.9" - } - }, - "scenario-options": { - "create-lockfile": "false" - } - } - }, - "branch-alias": { - "dev-master": "2.x-dev" - } - }, "autoload": { "psr-4": { "Robo\\": "src" @@ -408,26 +381,31 @@ } ], "description": "Modern task runner", - "time": "2019-01-02T21:33:28+00:00" + "support": { + "issues": "https://github.com/consolidation/robo/issues", + "source": "https://github.com/consolidation/robo/tree/4.0.1" + }, + "time": "2022-09-20T16:53:20+00:00" }, { "name": "consolidation/self-update", - "version": "1.1.5", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/consolidation/self-update.git", - "reference": "a1c273b14ce334789825a09d06d4c87c0a02ad54" + "reference": "8a64bdd8daf5faa8e85f56534dd99caf928164b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/self-update/zipball/a1c273b14ce334789825a09d06d4c87c0a02ad54", - "reference": "a1c273b14ce334789825a09d06d4c87c0a02ad54", + "url": "https://api.github.com/repos/consolidation/self-update/zipball/8a64bdd8daf5faa8e85f56534dd99caf928164b3", + "reference": "8a64bdd8daf5faa8e85f56534dd99caf928164b3", "shasum": "" }, "require": { + "composer/semver": "^3.2", "php": ">=5.5.0", - "symfony/console": "^2.8|^3|^4", - "symfony/filesystem": "^2.5|^3|^4" + "symfony/console": "^2.8 || ^3 || ^4 || ^5 || ^6", + "symfony/filesystem": "^2.5 || ^3 || ^4 || ^5 || ^6" }, "bin": [ "scripts/release" @@ -435,7 +413,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-main": "2.x-dev" } }, "autoload": { @@ -448,75 +426,55 @@ "MIT" ], "authors": [ - { - "name": "Greg Anderson", - "email": "greg.1.anderson@greenknowe.org" - }, { "name": "Alexander Menk", "email": "menk@mestrona.net" + }, + { + "name": "Greg Anderson", + "email": "greg.1.anderson@greenknowe.org" } ], "description": "Provides a self:update command for Symfony Console applications.", - "time": "2018-10-28T01:52:03+00:00" - }, - { - "name": "container-interop/container-interop", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/container-interop/container-interop.git", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", - "shasum": "" - }, - "require": { - "psr/container": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Interop\\Container\\": "src/Interop/Container/" - } + "support": { + "issues": "https://github.com/consolidation/self-update/issues", + "source": "https://github.com/consolidation/self-update/tree/2.0.5" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", - "homepage": "https://github.com/container-interop/container-interop", - "time": "2017-02-14T19:40:03+00:00" + "time": "2022-02-09T22:44:24+00:00" }, { "name": "dflydev/dot-access-data", - "version": "v1.1.0", + "version": "v3.0.2", "source": { "type": "git", "url": "https://github.com/dflydev/dflydev-dot-access-data.git", - "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a" + "reference": "f41715465d65213d644d3141a6a93081be5d3549" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/3fbd874921ab2c041e899d044585a2ab9795df8a", - "reference": "3fbd874921ab2c041e899d044585a2ab9795df8a", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/f41715465d65213d644d3141a6a93081be5d3549", + "reference": "f41715465d65213d644d3141a6a93081be5d3549", "shasum": "" }, "require": { - "php": ">=5.3.2" + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "3.x-dev" } }, "autoload": { - "psr-0": { - "Dflydev\\DotAccessData": "src" + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -538,6 +496,11 @@ "name": "Carlos Frutos", "email": "carlos@kiwing.it", "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" } ], "description": "Given a deep data structure, access data by dot notation.", @@ -548,31 +511,36 @@ "dot", "notation" ], - "time": "2017-01-20T21:14:22+00:00" + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.2" + }, + "time": "2022-10-27T11:44:00+00:00" }, { "name": "grasmash/expander", - "version": "1.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/grasmash/expander.git", - "reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f" + "reference": "bb1c1a2430957945cf08c5a62f5d72a6aa6a2c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/grasmash/expander/zipball/95d6037344a4be1dd5f8e0b0b2571a28c397578f", - "reference": "95d6037344a4be1dd5f8e0b0b2571a28c397578f", + "url": "https://api.github.com/repos/grasmash/expander/zipball/bb1c1a2430957945cf08c5a62f5d72a6aa6a2c82", + "reference": "bb1c1a2430957945cf08c5a62f5d72a6aa6a2c82", "shasum": "" }, "require": { - "dflydev/dot-access-data": "^1.1.0", - "php": ">=5.4" + "dflydev/dot-access-data": "^3.0.0", + "php": ">=8.0", + "psr/log": "^2 | ^3" }, "require-dev": { "greg-1-anderson/composer-test-scenarios": "^1", - "phpunit/phpunit": "^4|^5.5.4", - "satooshi/php-coveralls": "^1.0.2|dev-master", - "squizlabs/php_codesniffer": "^2.7" + "php-coveralls/php-coveralls": "^2.5", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.3" }, "type": "library", "extra": { @@ -595,87 +563,51 @@ } ], "description": "Expands internal property references in PHP arrays file.", - "time": "2017-12-21T22:14:55+00:00" - }, - { - "name": "grasmash/yaml-expander", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/grasmash/yaml-expander.git", - "reference": "3f0f6001ae707a24f4d9733958d77d92bf9693b1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/grasmash/yaml-expander/zipball/3f0f6001ae707a24f4d9733958d77d92bf9693b1", - "reference": "3f0f6001ae707a24f4d9733958d77d92bf9693b1", - "shasum": "" + "support": { + "issues": "https://github.com/grasmash/expander/issues", + "source": "https://github.com/grasmash/expander/tree/3.0.0" }, - "require": { - "dflydev/dot-access-data": "^1.1.0", - "php": ">=5.4", - "symfony/yaml": "^2.8.11|^3|^4" - }, - "require-dev": { - "greg-1-anderson/composer-test-scenarios": "^1", - "phpunit/phpunit": "^4.8|^5.5.4", - "satooshi/php-coveralls": "^1.0.2|dev-master", - "squizlabs/php_codesniffer": "^2.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Grasmash\\YamlExpander\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matthew Grasmick" - } - ], - "description": "Expands internal property references in a yaml file.", - "time": "2017-12-16T16:06:03+00:00" + "time": "2022-05-10T13:14:49+00:00" }, { "name": "league/container", - "version": "2.4.1", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/thephpleague/container.git", - "reference": "43f35abd03a12977a60ffd7095efd6a7808488c0" + "reference": "375d13cb828649599ef5d48a339c4af7a26cd0ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/container/zipball/43f35abd03a12977a60ffd7095efd6a7808488c0", - "reference": "43f35abd03a12977a60ffd7095efd6a7808488c0", + "url": "https://api.github.com/repos/thephpleague/container/zipball/375d13cb828649599ef5d48a339c4af7a26cd0ab", + "reference": "375d13cb828649599ef5d48a339c4af7a26cd0ab", "shasum": "" }, "require": { - "container-interop/container-interop": "^1.2", - "php": "^5.4.0 || ^7.0" + "php": "^7.2 || ^8.0", + "psr/container": "^1.1 || ^2.0" }, "provide": { - "container-interop/container-interop-implementation": "^1.2", "psr/container-implementation": "^1.0" }, "replace": { "orno/di": "~2.0" }, "require-dev": { - "phpunit/phpunit": "4.*" + "nette/php-generator": "^3.4", + "nikic/php-parser": "^4.10", + "phpstan/phpstan": "^0.12.47", + "phpunit/phpunit": "^8.5.17", + "roave/security-advisories": "dev-latest", + "scrutinizer/ocular": "^1.8", + "squizlabs/php_codesniffer": "^3.6" }, "type": "library", "extra": { "branch-alias": { + "dev-master": "4.x-dev", + "dev-4.x": "4.x-dev", + "dev-3.x": "3.x-dev", "dev-2.x": "2.x-dev", "dev-1.x": "1.x-dev" } @@ -692,8 +624,7 @@ "authors": [ { "name": "Phil Bennett", - "email": "philipobenito@gmail.com", - "homepage": "http://www.philipobenito.com", + "email": "mail@philbennett.co.uk", "role": "Developer" } ], @@ -708,34 +639,40 @@ "provider", "service" ], - "time": "2017-05-10T09:20:27+00:00" + "support": { + "issues": "https://github.com/thephpleague/container/issues", + "source": "https://github.com/thephpleague/container/tree/4.2.0" + }, + "funding": [ + { + "url": "https://github.com/philipobenito", + "type": "github" + } + ], + "time": "2021-11-16T10:29:06+00:00" }, { - "name": "psr/container", - "version": "1.0.0", + "name": "phootwork/collection", + "version": "v3.2.1", "source": { "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + "url": "https://github.com/phootwork/collection.git", + "reference": "46dde20420fba17766c89200bc3ff91d3e58eafa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", - "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "url": "https://api.github.com/repos/phootwork/collection/zipball/46dde20420fba17766c89200bc3ff91d3e58eafa", + "reference": "46dde20420fba17766c89200bc3ff91d3e58eafa", "shasum": "" }, "require": { - "php": ">=5.3.0" + "phootwork/lang": "^3.0", + "php": ">=8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { - "Psr\\Container\\": "src/" + "phootwork\\collection\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -744,47 +681,54 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Thomas Gossmann", + "homepage": "http://gos.si" } ], - "description": "Common Container Interface (PHP FIG PSR-11)", - "homepage": "https://github.com/php-fig/container", + "description": "The phootwork library fills gaps in the php language and provides better solutions than the existing ones php offers.", + "homepage": "https://phootwork.github.io/collection/", "keywords": [ - "PSR-11", - "container", - "container-interface", - "container-interop", - "psr" - ], - "time": "2017-02-14T16:28:37+00:00" + "Array object", + "Text object", + "collection", + "collections", + "json", + "list", + "map", + "queue", + "set", + "stack", + "xml" + ], + "support": { + "issues": "https://github.com/phootwork/phootwork/issues", + "source": "https://github.com/phootwork/collection/tree/v3.2.1" + }, + "time": "2022-08-27T12:51:24+00:00" }, { - "name": "psr/log", - "version": "1.1.0", + "name": "phootwork/lang", + "version": "v3.2.1", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" + "url": "https://github.com/phootwork/lang.git", + "reference": "f6687cb0e5453ceb7b4a2c4f9fa81273758eedd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "url": "https://api.github.com/repos/phootwork/lang/zipball/f6687cb0e5453ceb7b4a2c4f9fa81273758eedd0", + "reference": "f6687cb0e5453ceb7b4a2c4f9fa81273758eedd0", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0", + "symfony/polyfill-mbstring": "^1.12", + "symfony/polyfill-php81": "^1.22" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "phootwork\\lang\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -793,69 +737,53 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Thomas Gossmann", + "homepage": "http://gos.si" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Missing PHP language constructs", + "homepage": "https://phootwork.github.io/lang/", "keywords": [ - "log", - "psr", - "psr-3" + "array", + "comparator", + "comparison", + "string" ], - "time": "2018-11-20T15:27:04+00:00" + "support": { + "issues": "https://github.com/phootwork/phootwork/issues", + "source": "https://github.com/phootwork/lang/tree/v3.2.1" + }, + "time": "2022-08-27T12:51:24+00:00" }, { - "name": "symfony/console", - "version": "v3.4.21", + "name": "phpowermove/docblock", + "version": "v4.0", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "a700b874d3692bc8342199adfb6d3b99f62cc61a" + "url": "https://github.com/phpowermove/docblock.git", + "reference": "a73f6e17b7d4e1b92ca5378c248c952c9fae7826" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a700b874d3692bc8342199adfb6d3b99f62cc61a", - "reference": "a700b874d3692bc8342199adfb6d3b99f62cc61a", + "url": "https://api.github.com/repos/phpowermove/docblock/zipball/a73f6e17b7d4e1b92ca5378c248c952c9fae7826", + "reference": "a73f6e17b7d4e1b92ca5378c248c952c9fae7826", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/dependency-injection": "<3.4", - "symfony/process": "<3.3" + "phootwork/collection": "^3.0", + "phootwork/lang": "^3.0", + "php": ">=8.0" }, "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.3|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.3|~4.0" - }, - "suggest": { - "psr/log-implementation": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "phootwork/php-cs-fixer-config": "^0.4", + "phpunit/phpunit": "^9.0", + "psalm/phar": "^4.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "phpowermove\\docblock\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -863,55 +791,49 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Thomas Gossmann", + "homepage": "http://gos.si" } ], - "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2019-01-04T04:42:43+00:00" + "description": "PHP Docblock parser and generator. An API to read and write Docblocks.", + "keywords": [ + "docblock", + "generator", + "parser" + ], + "support": { + "issues": "https://github.com/phpowermove/docblock/issues", + "source": "https://github.com/phpowermove/docblock/tree/v4.0" + }, + "time": "2021-09-22T16:57:06+00:00" }, { - "name": "symfony/debug", - "version": "v3.4.21", + "name": "psr/container", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "26d7f23b9bd0b93bee5583e4d6ca5cb1ab31b186" + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/26d7f23b9bd0b93bee5583e4d6ca5cb1ab31b186", - "reference": "26d7f23b9bd0b93bee5583e4d6ca5cb1ab31b186", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" - }, - "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" + "php": ">=7.4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Psr\\Container\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -919,62 +841,52 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } ], - "description": "Symfony Debug Component", - "homepage": "https://symfony.com", - "time": "2019-01-01T13:45:19+00:00" + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" }, { - "name": "symfony/event-dispatcher", - "version": "v3.4.21", + "name": "psr/event-dispatcher", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d1cdd46c53c264a2bd42505bd0e8ce21423bd0e2" + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d1cdd46c53c264a2bd42505bd0e8ce21423bd0e2", - "reference": "d1cdd46c53c264a2bd42505bd0e8ce21423bd0e2", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/dependency-injection": "<3.3" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" - }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "php": ">=7.2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\EventDispatcher\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Psr\\EventDispatcher\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -982,45 +894,122 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Symfony EventDispatcher Component", - "homepage": "https://symfony.com", - "time": "2019-01-01T18:08:36+00:00" + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" }, { - "name": "symfony/filesystem", - "version": "v3.4.21", + "name": "psr/log", + "version": "3.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "c24ce3d18ccc9bb9d7e1d6ce9330fcc6061cafde" + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/c24ce3d18ccc9bb9d7e1d6ce9330fcc6061cafde", - "reference": "c24ce3d18ccc9bb9d7e1d6ce9330fcc6061cafde", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "3.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Filesystem\\": "" + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "symfony/console", + "version": "v6.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "a1282bd0c096e0bdb8800b104177e2ce404d8815" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/a1282bd0c096e0bdb8800b104177e2ce404d8815", + "reference": "a1282bd0c096e0bdb8800b104177e2ce404d8815", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -1040,39 +1029,63 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Filesystem Component", + "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", - "time": "2019-01-01T13:45:19+00:00" + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.1.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-10-26T21:42:49+00:00" }, { - "name": "symfony/finder", - "version": "v3.4.21", + "name": "symfony/deprecation-contracts", + "version": "v3.1.1", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "3f2a2ab6315dd7682d4c16dcae1e7b95c8b8555e" + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/3f2a2ab6315dd7682d4c16dcae1e7b95c8b8555e", - "reference": "3f2a2ab6315dd7682d4c16dcae1e7b95c8b8555e", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", + "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "function.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1081,50 +1094,81 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", - "time": "2019-01-01T13:45:19+00:00" + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-02-25T11:15:52+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.10.0", + "name": "symfony/event-dispatcher", + "version": "v6.1.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", - "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a0449a7ad7daa0f7c0acd508259f80544ab5a347", + "reference": "a0449a7ad7daa0f7c0acd508259f80544ab5a347", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2|^3" + }, + "conflict": { + "symfony/dependency-injection": "<5.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^5.4|^6.0" }, "suggest": { - "ext-ctype": "For best performance" + "symfony/dependency-injection": "", + "symfony/http-kernel": "" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.9-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" + "Symfony\\Component\\EventDispatcher\\": "" }, - "files": [ - "bootstrap.php" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1133,57 +1177,70 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Gert de Pagter", - "email": "backendtea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v6.1.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2018-08-06T14:22:27+00:00" + "time": "2022-05-05T16:51:07+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.10.0", + "name": "symfony/event-dispatcher-contracts", + "version": "v3.1.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "02ff5eea2f453731cfbc6bc215e456b781480448" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", - "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/02ff5eea2f453731cfbc6bc215e456b781480448", + "reference": "02ff5eea2f453731cfbc6bc215e456b781480448", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=8.1", + "psr/event-dispatcher": "^1" }, "suggest": { - "ext-mbstring": "For best performance" + "symfony/event-dispatcher-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.9-dev" + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] + "Symfony\\Contracts\\EventDispatcher\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1199,43 +1256,58 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Generic abstractions related to dispatching event", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2018-09-21T13:07:52+00:00" + "time": "2022-02-25T11:15:52+00:00" }, { - "name": "symfony/process", - "version": "v3.4.21", + "name": "symfony/filesystem", + "version": "v6.1.5", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "0d41dd7d95ed179aed6a13393b0f4f97bfa2d25c" + "url": "https://github.com/symfony/filesystem.git", + "reference": "4d216a2beef096edf040a070117c39ca2abce307" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0d41dd7d95ed179aed6a13393b0f4f97bfa2d25c", - "reference": "0d41dd7d95ed179aed6a13393b0f4f97bfa2d25c", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4d216a2beef096edf040a070117c39ca2abce307", + "reference": "4d216a2beef096edf040a070117c39ca2abce307", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Component\\Process\\": "" + "Symfony\\Component\\Filesystem\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -1255,46 +1327,51 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Process Component", + "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", - "time": "2019-01-02T21:24:08+00:00" + "support": { + "source": "https://github.com/symfony/filesystem/tree/v6.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-09-21T20:29:40+00:00" }, { - "name": "symfony/yaml", - "version": "v3.4.21", + "name": "symfony/finder", + "version": "v6.1.3", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "554a59a1ccbaac238a89b19c8e551a556fd0e2ea" + "url": "https://github.com/symfony/finder.git", + "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/554a59a1ccbaac238a89b19c8e551a556fd0e2ea", - "reference": "554a59a1ccbaac238a89b19c8e551a556fd0e2ea", + "url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709", + "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" - }, - "conflict": { - "symfony/console": "<3.4" + "php": ">=8.1" }, "require-dev": { - "symfony/console": "~3.4|~4.0" - }, - "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "symfony/filesystem": "^6.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Component\\Yaml\\": "" + "Symfony\\Component\\Finder\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -1314,46 +1391,66 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Yaml Component", + "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", - "time": "2019-01-01T13:45:19+00:00" - } - ], - "packages-dev": [ + "support": { + "source": "https://github.com/symfony/finder/tree/v6.1.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-07-29T07:42:06+00:00" + }, { - "name": "behat/gherkin", - "version": "v4.6.0", + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/Behat/Gherkin.git", - "reference": "ab0a02ea14893860bca00f225f5621d351a3ad07" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Behat/Gherkin/zipball/ab0a02ea14893860bca00f225f5621d351a3ad07", - "reference": "ab0a02ea14893860bca00f225f5621d351a3ad07", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", "shasum": "" }, "require": { - "php": ">=5.3.1" + "php": ">=7.1" }, - "require-dev": { - "phpunit/phpunit": "~4.5|~5", - "symfony/phpunit-bridge": "~2.7|~3|~4", - "symfony/yaml": "~2.3|~3|~4" + "provide": { + "ext-ctype": "*" }, "suggest": { - "symfony/yaml": "If you want to parse features, represented in YAML files" + "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.4-dev" + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "psr-0": { - "Behat\\Gherkin": "src/" + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -1362,91 +1459,77 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Gherkin DSL parser for PHP 5.3", - "homepage": "http://behat.org/", + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", "keywords": [ - "BDD", - "Behat", - "Cucumber", - "DSL", - "gherkin", - "parser" + "compatibility", + "ctype", + "polyfill", + "portable" ], - "time": "2019-01-16T14:22:17+00:00" - }, - { - "name": "codeception/base", - "version": "2.5.2", - "source": { - "type": "git", - "url": "https://github.com/Codeception/base.git", - "reference": "4f89de32929fef53ca6d83b159fe329b6d484c1c" + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Codeception/base/zipball/4f89de32929fef53ca6d83b159fe329b6d484c1c", - "reference": "4f89de32929fef53ca6d83b159fe329b6d484c1c", - "shasum": "" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" }, - "require": { - "behat/gherkin": "^4.4.0", - "codeception/phpunit-wrapper": "^6.0.9|^7.0.6", - "codeception/stub": "^2.0", - "ext-curl": "*", - "ext-json": "*", - "ext-mbstring": "*", - "facebook/webdriver": ">=1.1.3 <2.0", - "guzzlehttp/guzzle": ">=4.1.4 <7.0", - "guzzlehttp/psr7": "~1.0", - "php": ">=5.6.0 <8.0", - "symfony/browser-kit": ">=2.7 <5.0", - "symfony/console": ">=2.7 <5.0", - "symfony/css-selector": ">=2.7 <5.0", - "symfony/dom-crawler": ">=2.7 <5.0", - "symfony/event-dispatcher": ">=2.7 <5.0", - "symfony/finder": ">=2.7 <5.0", - "symfony/yaml": ">=2.7 <5.0" + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" }, - "require-dev": { - "codeception/specify": "~0.3", - "facebook/graph-sdk": "~5.3", - "flow/jsonpath": "~0.2", - "monolog/monolog": "~1.8", - "pda/pheanstalk": "~3.0", - "php-amqplib/php-amqplib": "~2.4", - "predis/predis": "^1.0", - "squizlabs/php_codesniffer": "~2.0", - "symfony/process": ">=2.7 <5.0", - "vlucas/phpdotenv": "^2.4.0" + "require": { + "php": ">=7.1" }, "suggest": { - "aws/aws-sdk-php": "For using AWS Auth in REST module and Queue module", - "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests", - "codeception/specify": "BDD-style code blocks", - "codeception/verify": "BDD-style assertions", - "flow/jsonpath": "For using JSONPath in REST module", - "league/factory-muffin": "For DataFactory module", - "league/factory-muffin-faker": "For Faker support in DataFactory module", - "phpseclib/phpseclib": "for SFTP option in FTP Module", - "stecman/symfony-console-completion": "For BASH autocompletion", - "symfony/phpunit-bridge": "For phpunit-bridge support" + "ext-intl": "For best performance" }, - "bin": [ - "codecept" - ], "type": "library", "extra": { - "branch-alias": [] + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Codeception\\": "src/Codeception", - "Codeception\\Extension\\": "ext" + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -1455,91 +1538,83 @@ ], "authors": [ { - "name": "Michael Bodnarchuk", - "email": "davert@mail.ua", - "homepage": "http://codegyre.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "BDD-style testing framework", - "homepage": "http://codeception.com/", + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", "keywords": [ - "BDD", - "TDD", - "acceptance testing", - "functional testing", - "unit testing" + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" ], - "time": "2019-01-02T10:28:51+00:00" + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "codeception/codeception", - "version": "2.5.2", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/Codeception/Codeception.git", - "reference": "4f89de32929fef53ca6d83b159fe329b6d484c1c" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/4f89de32929fef53ca6d83b159fe329b6d484c1c", - "reference": "4f89de32929fef53ca6d83b159fe329b6d484c1c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", "shasum": "" }, "require": { - "behat/gherkin": "^4.4.0", - "codeception/phpunit-wrapper": "^6.0.9|^7.0.6", - "codeception/stub": "^2.0", - "ext-curl": "*", - "ext-json": "*", - "ext-mbstring": "*", - "facebook/webdriver": ">=1.1.3 <2.0", - "guzzlehttp/guzzle": ">=4.1.4 <7.0", - "guzzlehttp/psr7": "~1.0", - "php": ">=5.6.0 <8.0", - "symfony/browser-kit": ">=2.7 <5.0", - "symfony/console": ">=2.7 <5.0", - "symfony/css-selector": ">=2.7 <5.0", - "symfony/dom-crawler": ">=2.7 <5.0", - "symfony/event-dispatcher": ">=2.7 <5.0", - "symfony/finder": ">=2.7 <5.0", - "symfony/yaml": ">=2.7 <5.0" - }, - "require-dev": { - "codeception/specify": "~0.3", - "facebook/graph-sdk": "~5.3", - "flow/jsonpath": "~0.2", - "monolog/monolog": "~1.8", - "pda/pheanstalk": "~3.0", - "php-amqplib/php-amqplib": "~2.4", - "predis/predis": "^1.0", - "squizlabs/php_codesniffer": "~2.0", - "symfony/process": ">=2.7 <5.0", - "vlucas/phpdotenv": "^2.4.0" + "php": ">=7.1" }, "suggest": { - "aws/aws-sdk-php": "For using AWS Auth in REST module and Queue module", - "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests", - "codeception/specify": "BDD-style code blocks", - "codeception/verify": "BDD-style assertions", - "flow/jsonpath": "For using JSONPath in REST module", - "league/factory-muffin": "For DataFactory module", - "league/factory-muffin-faker": "For Faker support in DataFactory module", - "phpseclib/phpseclib": "for SFTP option in FTP Module", - "stecman/symfony-console-completion": "For BASH autocompletion", - "symfony/phpunit-bridge": "For phpunit-bridge support" + "ext-intl": "For best performance" }, - "bin": [ - "codecept" - ], "type": "library", "extra": { - "branch-alias": [] + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Codeception\\": "src/Codeception", - "Codeception\\Extension\\": "ext" - } + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1547,53 +1622,82 @@ ], "authors": [ { - "name": "Michael Bodnarchuk", - "email": "davert@mail.ua", - "homepage": "http://codegyre.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "BDD-style testing framework", - "homepage": "http://codeception.com/", + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", "keywords": [ - "BDD", - "TDD", - "acceptance testing", - "functional testing", - "unit testing" + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2019-01-02T10:28:51+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "codeception/phpunit-wrapper", - "version": "6.5.1", + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/Codeception/phpunit-wrapper.git", - "reference": "d78f9eb9c4300a5924cc27dee03e8c1a96fcf5f3" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/phpunit-wrapper/zipball/d78f9eb9c4300a5924cc27dee03e8c1a96fcf5f3", - "reference": "d78f9eb9c4300a5924cc27dee03e8c1a96fcf5f3", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", "shasum": "" }, "require": { - "phpunit/php-code-coverage": ">=4.0.4 <6.0", - "phpunit/phpunit": ">=6.5.13 <7.0", - "sebastian/comparator": ">=1.2.4 <3.0", - "sebastian/diff": ">=1.4 <4.0" + "php": ">=7.1" }, - "replace": { - "codeception/phpunit-wrapper": "*" + "provide": { + "ext-mbstring": "*" }, - "require-dev": { - "codeception/specify": "*", - "vlucas/phpdotenv": "^2.4" + "suggest": { + "ext-mbstring": "For best performance" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Codeception\\PHPUnit\\": "src\\" + "Symfony\\Polyfill\\Mbstring\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -1602,77 +1706,308 @@ ], "authors": [ { - "name": "Davert", - "email": "davert.php@resend.cc" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "description": "PHPUnit classes used by Codeception", - "time": "2019-01-13T10:34:55+00:00" + "time": "2022-11-03T14:55:06+00:00" }, { - "name": "codeception/stub", - "version": "2.0.4", + "name": "symfony/polyfill-php81", + "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/Codeception/Stub.git", - "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Stub/zipball/f50bc271f392a2836ff80690ce0c058efe1ae03e", - "reference": "f50bc271f392a2836ff80690ce0c058efe1ae03e", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", "shasum": "" }, "require": { - "phpunit/phpunit": ">=4.8 <8.0" + "php": ">=7.1" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Codeception\\": "src/" + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/process", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/a6506e99cfad7059b1ab5cab395854a0a0c21292", + "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", - "time": "2018-07-26T11:55:37+00:00" + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v6.1.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-06-27T17:24:16+00:00" }, { - "name": "doctrine/instantiator", - "version": "1.0.5", + "name": "symfony/service-contracts", + "version": "v3.1.1", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239", + "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": ">=8.1", + "psr/container": "^2.0" }, - "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-30T19:18:58+00:00" + }, + { + "name": "symfony/string", + "version": "v6.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "823f143370880efcbdfa2dbca946b3358c4707e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/823f143370880efcbdfa2dbca946b3358c4707e5", + "reference": "823f143370880efcbdfa2dbca946b3358c4707e5", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1680,119 +2015,321 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", "keywords": [ - "constructor", - "instantiate" + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" ], - "time": "2015-06-14T21:17:01+00:00" + "support": { + "source": "https://github.com/symfony/string/tree/v6.1.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-10-10T09:34:31+00:00" }, { - "name": "facebook/webdriver", - "version": "1.6.0", + "name": "symfony/yaml", + "version": "v6.1.6", "source": { "type": "git", - "url": "https://github.com/facebook/php-webdriver.git", - "reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e" + "url": "https://github.com/symfony/yaml.git", + "reference": "66c6b0cf52b00f74614a2cf7ae7db08ea1095931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/bd8c740097eb9f2fc3735250fc1912bc811a954e", - "reference": "bd8c740097eb9f2fc3735250fc1912bc811a954e", + "url": "https://api.github.com/repos/symfony/yaml/zipball/66c6b0cf52b00f74614a2cf7ae7db08ea1095931", + "reference": "66c6b0cf52b00f74614a2cf7ae7db08ea1095931", "shasum": "" }, "require": { - "ext-curl": "*", - "ext-json": "*", - "ext-mbstring": "*", - "ext-zip": "*", - "php": "^5.6 || ~7.0", - "symfony/process": "^2.8 || ^3.1 || ^4.0" + "php": ">=8.1", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v6.1.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-10-07T08:04:03+00:00" + } + ], + "packages-dev": [ + { + "name": "behat/gherkin", + "version": "v4.9.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/0bc8d1e30e96183e4f36db9dc79caead300beff4", + "reference": "0bc8d1e30e96183e4f36db9dc79caead300beff4", + "shasum": "" + }, + "require": { + "php": "~7.2|~8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.0", - "jakub-onderka/php-parallel-lint": "^0.9.2", - "php-coveralls/php-coveralls": "^2.0", - "php-mock/php-mock-phpunit": "^1.1", - "phpunit/phpunit": "^5.7", - "sebastian/environment": "^1.3.4 || ^2.0 || ^3.0", - "squizlabs/php_codesniffer": "^2.6", - "symfony/var-dumper": "^3.3 || ^4.0" + "cucumber/cucumber": "dev-gherkin-22.0.0", + "phpunit/phpunit": "~8|~9", + "symfony/yaml": "~3|~4|~5" }, "suggest": { - "ext-SimpleXML": "For Firefox profile creation" + "symfony/yaml": "If you want to parse features, represented in YAML files" }, "type": "library", "extra": { "branch-alias": { - "dev-community": "1.5-dev" + "dev-master": "4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Gherkin": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" } + ], + "description": "Gherkin DSL parser for PHP", + "homepage": "http://behat.org/", + "keywords": [ + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", + "parser" + ], + "support": { + "issues": "https://github.com/Behat/Gherkin/issues", + "source": "https://github.com/Behat/Gherkin/tree/v4.9.0" + }, + "time": "2021-10-12T13:05:09+00:00" + }, + { + "name": "codeception/codeception", + "version": "5.0.4", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Codeception.git", + "reference": "e3a69881696935c4209a7a45958a3bdd17def56a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/e3a69881696935c4209a7a45958a3bdd17def56a", + "reference": "e3a69881696935c4209a7a45958a3bdd17def56a", + "shasum": "" + }, + "require": { + "behat/gherkin": "^4.6.2", + "codeception/lib-asserts": "2.0.*@dev", + "codeception/stub": "^3.7 | ^4.0", + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "php": "^8.0", + "phpunit/php-code-coverage": "^9.2", + "phpunit/php-text-template": "^2.0", + "phpunit/php-timer": "^5.0.3", + "phpunit/phpunit": "^9.5", + "psy/psysh": "^0.11.2", + "sebastian/comparator": "^4.0.5", + "sebastian/diff": "^4.0.3", + "symfony/console": ">=4.4.24 <7.0", + "symfony/css-selector": ">=4.4.24 <7.0", + "symfony/event-dispatcher": ">=4.4.24 <7.0", + "symfony/finder": ">=4.4.24 <7.0", + "symfony/var-dumper": ">=4.4.24 < 7.0", + "symfony/yaml": ">=4.4.24 <7.0" + }, + "conflict": { + "codeception/lib-innerbrowser": "<3.1", + "codeception/module-filesystem": "<3.0", + "codeception/module-phpbrowser": "<2.5" + }, + "replace": { + "codeception/phpunit-wrapper": "*" + }, + "require-dev": { + "codeception/lib-innerbrowser": "*@dev", + "codeception/lib-web": "^1.0", + "codeception/module-asserts": "*@dev", + "codeception/module-cli": "*@dev", + "codeception/module-db": "*@dev", + "codeception/module-filesystem": "*@dev", + "codeception/module-phpbrowser": "*@dev", + "codeception/util-universalframework": "*@dev", + "ext-simplexml": "*", + "symfony/dotenv": ">=4.4.24 <7.0", + "symfony/process": ">=4.4.24 <7.0", + "vlucas/phpdotenv": "^5.1" + }, + "suggest": { + "codeception/specify": "BDD-style code blocks", + "codeception/verify": "BDD-style assertions", + "ext-simplexml": "For loading params from XML files", + "stecman/symfony-console-completion": "For BASH autocompletion", + "symfony/dotenv": "For loading params from .env files", + "symfony/phpunit-bridge": "For phpunit-bridge support", + "vlucas/phpdotenv": "For loading params from .env files" }, + "bin": [ + "codecept" + ], + "type": "library", "autoload": { + "files": [ + "functions.php" + ], "psr-4": { - "Facebook\\WebDriver\\": "lib/" - } + "Codeception\\": "src/Codeception", + "Codeception\\Extension\\": "ext" + }, + "classmap": [ + "src/PHPUnit/TestCase.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "Apache-2.0" + "MIT" + ], + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert.ua@gmail.com", + "homepage": "https://codeception.com" + } ], - "description": "A PHP client for Selenium WebDriver", - "homepage": "https://github.com/facebook/php-webdriver", + "description": "BDD-style testing framework", + "homepage": "https://codeception.com/", "keywords": [ - "facebook", - "php", - "selenium", - "webdriver" + "BDD", + "TDD", + "acceptance testing", + "functional testing", + "unit testing" + ], + "support": { + "issues": "https://github.com/Codeception/Codeception/issues", + "source": "https://github.com/Codeception/Codeception/tree/5.0.4" + }, + "funding": [ + { + "url": "https://opencollective.com/codeception", + "type": "open_collective" + } ], - "time": "2018-05-16T17:37:13+00:00" + "time": "2022-10-30T19:15:56+00:00" }, { - "name": "guzzlehttp/guzzle", - "version": "6.3.3", + "name": "codeception/lib-asserts", + "version": "2.0.1", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + "url": "https://github.com/Codeception/lib-asserts.git", + "reference": "78c55044611437988b54e1daecf13f247a742bf8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "url": "https://api.github.com/repos/Codeception/lib-asserts/zipball/78c55044611437988b54e1daecf13f247a742bf8", + "reference": "78c55044611437988b54e1daecf13f247a742bf8", "shasum": "" }, "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" + "codeception/phpunit-wrapper": "^7.7.1 | ^8.0.3 | ^9.0", + "ext-dom": "*", + "php": "^7.4 | ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.3-dev" - } - }, "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1800,113 +2337,99 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Michael Bodnarchuk", + "email": "davert@mail.ua", + "homepage": "http://codegyre.com" + }, + { + "name": "Gintautas Miselis" + }, + { + "name": "Gustavo Nieves", + "homepage": "https://medium.com/@ganieves" } ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", + "description": "Assertion methods used by Codeception core and Asserts module", + "homepage": "https://codeception.com/", "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" + "codeception" ], - "time": "2018-04-22T15:46:56+00:00" + "support": { + "issues": "https://github.com/Codeception/lib-asserts/issues", + "source": "https://github.com/Codeception/lib-asserts/tree/2.0.1" + }, + "time": "2022-09-27T06:17:39+00:00" }, { - "name": "guzzlehttp/promises", - "version": "v1.3.1", + "name": "codeception/stub", + "version": "4.0.2", "source": { "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + "url": "https://github.com/Codeception/Stub.git", + "reference": "18a148dacd293fc7b044042f5aa63a82b08bff5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "url": "https://api.github.com/repos/Codeception/Stub/zipball/18a148dacd293fc7b044042f5aa63a82b08bff5d", + "reference": "18a148dacd293fc7b044042f5aa63a82b08bff5d", "shasum": "" }, "require": { - "php": ">=5.5.0" + "php": "^7.4 | ^8.0", + "phpunit/phpunit": "^8.4 | ^9.0 | ^10.0 | 10.0.x-dev" }, "require-dev": { - "phpunit/phpunit": "^4.0" + "consolidation/robo": "^3.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, "autoload": { "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + "Codeception\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" + "description": "Flexible Stub wrapper for PHPUnit's Mock Builder", + "support": { + "issues": "https://github.com/Codeception/Stub/issues", + "source": "https://github.com/Codeception/Stub/tree/4.0.2" + }, + "time": "2022-01-31T19:25:15+00:00" }, { - "name": "guzzlehttp/psr7", - "version": "1.5.2", + "name": "doctrine/instantiator", + "version": "1.4.1", "source": { "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "9f83dded91781a01c63574e387eaa769be769115" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", - "reference": "9f83dded91781a01c63574e387eaa769be769115", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc", + "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc", "shasum": "" }, "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0", - "ralouphie/getallheaders": "^2.0.5" - }, - "provide": { - "psr/http-message-implementation": "1.0" + "php": "^7.1 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + "doctrine/coding-standard": "^9", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.22" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5-dev" - } - }, "autoload": { "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1914,58 +2437,71 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" } ], - "description": "PSR-7 message implementation that also provides common utility methods", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ - "http", - "message", - "psr-7", - "request", - "response", - "stream", - "uri", - "url" + "constructor", + "instantiate" + ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } ], - "time": "2018-12-04T20:46:45+00:00" + "time": "2022-03-03T08:28:38+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.7.0", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e" + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", - "reference": "3b8a3a99ba1f6a3952ac2747d989303cbd6b7a3e", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" }, "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^4.1" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, "files": [ "src/DeepCopy/deep_copy.php" - ] + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1979,200 +2515,158 @@ "object", "object graph" ], - "time": "2017-10-19T19:58:43+00:00" - }, - { - "name": "phar-io/manifest", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/phar-io/manifest.git", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/2df402786ab5368a0169091f61a7c1e0eb6852d0", - "reference": "2df402786ab5368a0169091f61a7c1e0eb6852d0", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-phar": "*", - "phar-io/version": "^1.0.1", - "php": "^5.6 || ^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, + "funding": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" } ], - "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", - "time": "2017-03-05T18:14:27+00:00" + "time": "2022-03-03T13:19:32+00:00" }, { - "name": "phar-io/version", - "version": "1.0.1", + "name": "n98/junit-xml", + "version": "1.1.0", "source": { "type": "git", - "url": "https://github.com/phar-io/version.git", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df" + "url": "https://github.com/cmuench/junit-xml.git", + "reference": "0017dd92ac8cb619f02e32f4cffd768cfe327c73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/a70c0ced4be299a63d32fa96d9281d03e94041df", - "reference": "a70c0ced4be299a63d32fa96d9281d03e94041df", + "url": "https://api.github.com/repos/cmuench/junit-xml/zipball/0017dd92ac8cb619f02e32f4cffd768cfe327c73", + "reference": "0017dd92ac8cb619f02e32f4cffd768cfe327c73", "shasum": "" }, - "require": { - "php": "^5.6 || ^7.0" + "require-dev": { + "phpunit/phpunit": "^9.5.0" }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "N98\\JUnitXml\\": "src/N98/JUnitXml" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" - }, - { - "name": "Sebastian Heuer", - "email": "sebastian@phpeople.de", - "role": "Developer" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "Developer" + "name": "Christian Münch", + "email": "c.muench@netz98.de" } ], - "description": "Library for handling version information and constraints", - "time": "2017-03-05T17:38:23+00:00" + "description": "JUnit XML Document generation library", + "support": { + "issues": "https://github.com/cmuench/junit-xml/issues", + "source": "https://github.com/cmuench/junit-xml/tree/1.1.0" + }, + "time": "2020-12-25T09:08:58+00:00" }, { - "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "name": "nikic/php-parser", + "version": "v4.15.2", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc", + "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc", "shasum": "" }, "require": { - "php": ">=5.5" + "ext-tokenizer": "*", + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "4.9-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "PhpParser\\": "lib/PhpParser" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "name": "Nikita Popov" } ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", + "description": "A PHP parser written in PHP", "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" + "parser", + "php" ], - "time": "2017-09-11T18:02:19+00:00" + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2" + }, + "time": "2022-11-12T15:38:23+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "4.3.0", + "name": "overtrue/phplint", + "version": "5.3.0", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08" + "url": "https://github.com/overtrue/phplint.git", + "reference": "42ddcab45454e0cf3f1522340fc22f3875c4c74f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08", - "reference": "94fd0001232e47129dd3504189fa1c7225010d08", + "url": "https://api.github.com/repos/overtrue/phplint/zipball/42ddcab45454e0cf3f1522340fc22f3875c4c74f", + "reference": "42ddcab45454e0cf3f1522340fc22f3875c4c74f", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", - "webmozart/assert": "^1.0" + "ext-json": "*", + "n98/junit-xml": "1.1.0", + "php": "^8.1", + "symfony/console": "^5.0 || ^6.0", + "symfony/finder": "^6.0", + "symfony/process": "^6.0", + "symfony/yaml": "^6.0" }, "require-dev": { - "doctrine/instantiator": "~1.0.5", - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^6.4" + "bamarni/composer-bin-plugin": "^1.4", + "brainmaestro/composer-git-hooks": "^2.8.5", + "friendsofphp/php-cs-fixer": "^3.4.0", + "jakub-onderka/php-console-highlighter": "^0.4", + "jetbrains/phpstorm-stubs": "^2021.3 || ^2022.0" }, + "bin": [ + "bin/phplint" + ], "type": "library", "extra": { - "branch-alias": { - "dev-master": "4.x-dev" + "hooks": { + "pre-commit": [ + "composer fix-style" + ] } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "Overtrue\\PHPLint\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2181,159 +2675,180 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "overtrue", + "email": "anzhengchao@gmail.com" + } + ], + "description": "`phplint` is a tool that can speed up linting of php files by running several lint processes at once.", + "keywords": [ + "check", + "lint", + "phplint", + "syntax" + ], + "support": { + "issues": "https://github.com/overtrue/phplint/issues", + "source": "https://github.com/overtrue/phplint/tree/5.3.0" + }, + "funding": [ + { + "url": "https://github.com/overtrue", + "type": "github" } ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2017-11-30T07:14:17+00:00" + "time": "2022-07-12T07:42:45+00:00" }, { - "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "name": "phar-io/manifest", + "version": "2.0.3", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" - }, - "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "time": "2017-07-14T14:27:02+00:00" + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" }, { - "name": "phpspec/prophecy", - "version": "1.8.0", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" - }, - "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + "php": "^7.2 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.8.x-dev" - } - }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", - "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" - ], - "time": "2018-08-05T17:53:17+00:00" + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "5.3.2", + "version": "9.2.18", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c89677919c5dd6d3b3852f230a663118762218ac" + "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c89677919c5dd6d3b3852f230a663118762218ac", - "reference": "c89677919c5dd6d3b3852f230a663118762218ac", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/12fddc491826940cf9b7e88ad9664cf51f0f6d0a", + "reference": "12fddc491826940cf9b7e88ad9664cf51f0f6d0a", "shasum": "" }, "require": { "ext-dom": "*", + "ext-libxml": "*", "ext-xmlwriter": "*", - "php": "^7.0", - "phpunit/php-file-iterator": "^1.4.2", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^2.0.1", - "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.0", - "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "nikic/php-parser": "^4.14", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-xdebug": "^2.5.5" + "ext-pcov": "*", + "ext-xdebug": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.3.x-dev" + "dev-master": "9.2-dev" } }, "autoload": { @@ -2359,29 +2874,42 @@ "testing", "xunit" ], - "time": "2018-04-06T15:36:58+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.18" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-10-27T13:35:33+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.5", + "version": "3.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", - "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2396,7 +2924,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -2406,26 +2934,48 @@ "filesystem", "iterator" ], - "time": "2017-11-27T13:52:08+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "phpunit/php-invoker", + "version": "3.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -2442,37 +2992,47 @@ "role": "lead" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ - "template" + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2015-06-21T13:50:34+00:00" + "time": "2020-09-28T05:58:55+00:00" }, { - "name": "phpunit/php-timer", - "version": "1.0.9", + "name": "phpunit/php-text-template", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", - "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2487,42 +3047,51 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ - "timer" + "template" ], - "time": "2017-02-26T11:10:40+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "2.0.2", + "name": "phpunit/php-timer", + "version": "5.0.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "791198a2c6254db10131eecfe8c06670700904db" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/791198a2c6254db10131eecfe8c06670700904db", - "reference": "791198a2c6254db10131eecfe8c06670700904db", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.2.4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2537,65 +3106,73 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "tokenizer" + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-11-27T05:48:46+00:00" + "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/phpunit", - "version": "6.5.13", + "version": "9.5.26", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "0973426fb012359b2f18d3bd1e90ef1172839693" + "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0973426fb012359b2f18d3bd1e90ef1172839693", - "reference": "0973426fb012359b2f18d3bd1e90ef1172839693", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/851867efcbb6a1b992ec515c71cdcf20d895e9d2", + "reference": "851867efcbb6a1b992ec515c71cdcf20d895e9d2", "shasum": "" }, "require": { + "doctrine/instantiator": "^1.3.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.6.1", - "phar-io/manifest": "^1.0.1", - "phar-io/version": "^1.0", - "php": "^7.0", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^5.3", - "phpunit/php-file-iterator": "^1.4.3", - "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^1.0.9", - "phpunit/phpunit-mock-objects": "^5.0.9", - "sebastian/comparator": "^2.1", - "sebastian/diff": "^2.0", - "sebastian/environment": "^3.1", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", - "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^1.0", - "sebastian/version": "^2.0.1" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2", - "phpunit/dbunit": "<3.0" - }, - "require-dev": { - "ext-pdo": "*" + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" }, "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "^1.1" + "ext-soap": "*", + "ext-xdebug": "*" }, "bin": [ "phpunit" @@ -2603,10 +3180,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.5.x-dev" + "dev-master": "9.5-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -2629,181 +3209,776 @@ "testing", "xunit" ], - "time": "2018-09-08T15:10:43+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.26" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2022-10-28T06:00:21+00:00" }, { - "name": "phpunit/phpunit-mock-objects", - "version": "5.0.10", + "name": "psy/psysh", + "version": "v0.11.9", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f" + "url": "https://github.com/bobthecow/psysh.git", + "reference": "1acec99d6684a54ff92f8b548a4e41b566963778" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/cd1cf05c553ecfec36b170070573e540b67d3f1f", - "reference": "cd1cf05c553ecfec36b170070573e540b67d3f1f", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1acec99d6684a54ff92f8b548a4e41b566963778", + "reference": "1acec99d6684a54ff92f8b548a4e41b566963778", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.5", - "php": "^7.0", - "phpunit/php-text-template": "^1.2.1", - "sebastian/exporter": "^3.1" + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^4.0 || ^3.1", + "php": "^8.0 || ^7.0.8", + "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" }, "conflict": { - "phpunit/phpunit": "<6.0" + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" }, "require-dev": { - "phpunit/phpunit": "^6.5.11" + "bamarni/composer-bin-plugin": "^1.2" }, "suggest": { - "ext-soap": "*" + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." }, + "bin": [ + "bin/psysh" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0.x-dev" + "dev-main": "0.11.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" } ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", "keywords": [ - "mock", - "xunit" + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.11.9" + }, + "time": "2022-11-06T15:29:46+00:00" + }, + { + "name": "roave/security-advisories", + "version": "dev-latest", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "5317244268eb40e418f1cf8afa6d1d9df4e1f4a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/5317244268eb40e418f1cf8afa6d1d9df4e1f4a3", + "reference": "5317244268eb40e418f1cf8afa6d1d9df4e1f4a3", + "shasum": "" + }, + "conflict": { + "3f/pygmentize": "<1.2", + "admidio/admidio": "<4.1.9", + "adodb/adodb-php": "<=5.20.20|>=5.21,<=5.21.3", + "aheinze/cockpit": "<=2.2.1", + "akaunting/akaunting": "<2.1.13", + "alextselegidis/easyappointments": "<=1.4.3", + "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amazing/media2click": ">=1,<1.3.3", + "amphp/artax": "<1.0.6|>=2,<2.0.6", + "amphp/http": "<1.0.1", + "amphp/http-client": ">=4,<4.4", + "anchorcms/anchor-cms": "<=0.12.7", + "andreapollastri/cipi": "<=3.1.15", + "apereo/phpcas": "<1.6", + "api-platform/core": ">=2.2,<2.2.10|>=2.3,<2.3.6", + "appwrite/server-ce": "<0.11.1|>=0.12,<0.12.2", + "area17/twill": "<1.2.5|>=2,<2.5.3", + "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", + "awesome-support/awesome-support": "<=6.0.7", + "aws/aws-sdk-php": ">=3,<3.2.1", + "badaso/core": "<2.6.1", + "bagisto/bagisto": "<0.1.5", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", + "barryvdh/laravel-translation-manager": "<0.6.2", + "baserproject/basercms": "<4.5.4", + "billz/raspap-webgui": "<=2.6.6", + "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "bmarshall511/wordpress_zero_spam": "<5.2.13", + "bolt/bolt": "<3.7.2", + "bolt/core": "<=4.2", + "bottelet/flarepoint": "<2.2.1", + "brightlocal/phpwhois": "<=4.2.5", + "brotkrueml/codehighlight": "<2.7", + "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", + "brotkrueml/typo3-matomo-integration": "<1.3.2", + "buddypress/buddypress": "<7.2.1", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "bytefury/crater": "<6.0.2", + "cachethq/cachet": "<2.5.1", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.6", + "cardgate/magento2": "<2.0.33", + "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cartalyst/sentry": "<=2.1.6", + "catfan/medoo": "<1.7.5", + "centreon/centreon": "<22.10-beta.1", + "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "codeception/codeception": "<3.1.3|>=4,<4.1.22", + "codeigniter/framework": "<=3.0.6", + "codeigniter4/framework": "<4.2.7", + "codeigniter4/shield": "= 1.0.0-beta", + "codiad/codiad": "<=2.8.4", + "composer/composer": "<1.10.26|>=2-alpha.1,<2.2.12|>=2.3,<2.3.5", + "concrete5/concrete5": "<9", + "concrete5/core": "<8.5.8|>=9,<9.1", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/contao": ">=4,<4.4.56|>=4.5,<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3", + "contao/core": ">=2,<3.5.39", + "contao/core-bundle": "<4.9.18|>=4.10,<4.11.7|>=4.13,<4.13.3|= 4.10.0", + "contao/listing-bundle": ">=4,<4.4.8", + "contao/managed-edition": "<=1.5", + "craftcms/cms": "<3.7.55.2|>= 4.0.0-RC1, < 4.2.1", + "croogo/croogo": "<3.0.7", + "cuyz/valinor": "<0.12", + "czproject/git-php": "<4.0.3", + "darylldoyle/safe-svg": "<1.9.10", + "datadog/dd-trace": ">=0.30,<0.30.2", + "david-garcia/phpwhois": "<=4.3.1", + "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1", + "directmailteam/direct-mail": "<5.2.4", + "doctrine/annotations": ">=1,<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": ">=2,<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<=0.7.1", + "doctrine/mongodb-odm": ">=1,<1.0.2", + "doctrine/mongodb-odm-bundle": ">=2,<3.0.1", + "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", + "dolibarr/dolibarr": "<16|= 12.0.5|>= 3.3.beta1, < 13.0.2", + "dompdf/dompdf": "<2.0.1", + "drupal/core": ">=7,<7.91|>=8,<9.3.19|>=9.4,<9.4.3", + "drupal/drupal": ">=7,<7.80|>=8,<8.9.16|>=9,<9.1.12|>=9.2,<9.2.4", + "dweeves/magmi": "<=0.7.24", + "ecodev/newsletter": "<=4", + "ectouch/ectouch": "<=2.7.2", + "elefant/cms": "<1.3.13", + "elgg/elgg": "<3.3.24|>=4,<4.0.5", + "endroid/qr-code-bundle": "<3.4.2", + "enshrined/svg-sanitize": "<0.15", + "erusev/parsedown": "<1.7.2", + "ether/logs": "<3.0.4", + "exceedone/exment": "<4.4.3|>=5,<5.0.3", + "exceedone/laravel-admin": "= 3.0.0|<2.2.3", + "ezsystems/demobundle": ">=5.4,<5.4.6.1", + "ezsystems/ez-support-tools": ">=2.2,<2.2.3", + "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", + "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", + "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.26", + "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", + "ezsystems/ezplatform-graphql": ">=1-rc.1,<1.0.13|>=2-beta.1,<2.3.12", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.26", + "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", + "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", + "ezsystems/ezplatform-user": ">=1,<1.0.1", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.30", + "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1", + "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1|>=2.5,<2.5.15", + "ezyang/htmlpurifier": "<4.1.1", + "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", + "facturascripts/facturascripts": "<=2022.8", + "feehi/cms": "<=2.1.1", + "feehi/feehicms": "<=2.0.1.1", + "fenom/fenom": "<=2.12.1", + "filegator/filegator": "<7.8", + "firebase/php-jwt": "<2", + "flarum/core": ">=1,<=1.0.1", + "flarum/sticky": ">=0.1-beta.14,<=0.1-beta.15", + "flarum/tags": "<=0.1-beta.13", + "fluidtypo3/vhs": "<5.1.1", + "fof/byobu": ">=0.3-beta.2,<1.1.7", + "fof/upload": "<1.2.3", + "fooman/tcpdf": "<6.2.22", + "forkcms/forkcms": "<5.11.1", + "fossar/tcpdf-parser": "<6.2.22", + "francoisjacquet/rosariosis": "<10.1", + "friendsofsymfony/oauth2-php": "<1.3", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1.2,<1.3.5", + "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", + "froala/wysiwyg-editor": "<3.2.7", + "froxlor/froxlor": "<0.10.39", + "fuel/core": "<1.8.1", + "gaoming13/wechat-php-sdk": "<=1.10.2", + "genix/cms": "<=1.1.11", + "getgrav/grav": "<1.7.34", + "getkirby/cms": "= 3.8.0|<3.5.8.2|>=3.6,<3.6.6.2|>=3.7,<3.7.5.1", + "getkirby/panel": "<2.5.14", + "getkirby/starterkit": "<=3.7.0.2", + "gilacms/gila": "<=1.11.4", + "globalpayments/php-sdk": "<2", + "google/protobuf": "<3.15", + "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", + "gree/jose": "<=2.2", + "gregwar/rst": "<1.0.3", + "grumpydictator/firefly-iii": "<5.6.5", + "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", + "guzzlehttp/psr7": "<1.8.4|>=2,<2.1.1", + "helloxz/imgurl": "= 2.31|<=2.31", + "hillelcoren/invoice-ninja": "<5.3.35", + "hjue/justwriting": "<=1", + "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "hyn/multi-tenant": ">=5.6,<5.7.2", + "ibexa/admin-ui": ">=4.2,<4.2.3", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3", + "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", + "ibexa/post-install": "<=1.0.4", + "icecoder/icecoder": "<=8.1", + "idno/known": "<=1.3.1", + "illuminate/auth": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.10", + "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<=4.1.99999|>=4.2,<=4.2.99999|>=5,<=5.0.99999|>=5.1,<=5.1.99999|>=5.2,<=5.2.99999|>=5.3,<=5.3.99999|>=5.4,<=5.4.99999|>=5.5,<=5.5.49|>=5.6,<=5.6.99999|>=5.7,<=5.7.99999|>=5.8,<=5.8.99999|>=6,<6.18.31|>=7,<7.22.4", + "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", + "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "impresscms/impresscms": "<=1.4.3", + "in2code/femanager": "<5.5.2|>=6,<6.3.3|>=7,<7.0.1", + "in2code/lux": "<17.6.1|>=18,<24.0.2", + "intelliants/subrion": "<=4.2.1", + "islandora/islandora": ">=2,<2.4.1", + "ivankristianto/phpwhois": "<=4.3", + "jackalope/jackalope-doctrine-dbal": "<1.7.4", + "james-heinrich/getid3": "<1.9.21", + "joomla/archive": "<1.1.12|>=2,<2.0.1", + "joomla/filesystem": "<1.6.2|>=2,<2.0.1", + "joomla/filter": "<1.4.4|>=2,<2.0.1", + "joomla/input": ">=2,<2.0.2", + "joomla/session": "<1.3.1", + "joyqi/hyper-down": "<=2.4.27", + "jsdecena/laracom": "<2.0.9", + "jsmitty12/phpwhois": "<5.1", + "kazist/phpwhois": "<=4.2.6", + "kevinpapst/kimai2": "<1.16.7", + "kitodo/presentation": "<3.1.2", + "klaviyo/magento2-extension": ">=1,<3", + "krayin/laravel-crm": "<1.2.2", + "kreait/firebase-php": ">=3.2,<3.8.1", + "la-haute-societe/tcpdf": "<6.2.22", + "laminas/laminas-diactoros": "<2.11.1", + "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", + "laminas/laminas-http": "<2.14.2", + "laravel/fortify": "<1.11.1", + "laravel/framework": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", + "latte/latte": "<2.10.8", + "lavalite/cms": "<=5.8", + "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", + "league/commonmark": "<0.18.3", + "league/flysystem": "<1.1.4|>=2,<2.1.1", + "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", + "librenms/librenms": "<=22.8", + "limesurvey/limesurvey": "<3.27.19", + "livehelperchat/livehelperchat": "<=3.91", + "livewire/livewire": ">2.2.4,<2.2.6", + "lms/routes": "<2.1.1", + "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", + "luyadev/yii-helpers": "<1.2.1", + "magento/community-edition": ">=2,<2.2.10|>=2.3,<2.3.3", + "magento/magento1ce": "<1.9.4.3", + "magento/magento1ee": ">=1,<1.14.4.3", + "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", + "marcwillmann/turn": "<0.3.3", + "matyhtf/framework": "<3.0.6", + "mautic/core": "<4.3|= 2.13.1", + "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", + "melisplatform/melis-asset-manager": "<5.0.1", + "melisplatform/melis-cms": "<5.0.1", + "melisplatform/melis-front": "<5.0.1", + "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", + "microweber/microweber": "<=1.3.1", + "miniorange/miniorange-saml": "<1.4.3", + "mittwald/typo3_forum": "<1.2.1", + "modx/revolution": "<= 2.8.3-pl|<2.8", + "mojo42/jirafeau": "<4.4", + "monolog/monolog": ">=1.8,<1.12", + "moodle/moodle": "<4.0.1", + "mustache/mustache": ">=2,<2.14.1", + "namshi/jose": "<2.2", + "neoan3-apps/template": "<1.1.1", + "neorazorx/facturascripts": "<2022.4", + "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.9.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", + "neos/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", + "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", + "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", + "nilsteampassnet/teampass": "<=2.1.27.36", + "notrinos/notrinos-erp": "<=0.7", + "noumo/easyii": "<=0.9", + "nukeviet/nukeviet": "<4.5.2", + "nystudio107/craft-seomatic": "<3.4.12", + "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/backend": "<1.1.2", + "october/cms": "= 1.1.1|= 1.0.471|= 1.0.469|>=1.0.319,<1.0.469", + "october/october": ">=1.0.319,<1.0.466|>=2.1,<2.1.12", + "october/rain": "<1.0.472|>=1.1,<1.1.2", + "october/system": "<1.0.476|>=1.1,<1.1.12|>=2,<2.2.34|>=3,<3.0.66", + "onelogin/php-saml": "<2.10.4", + "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", + "open-web-analytics/open-web-analytics": "<1.7.4", + "opencart/opencart": "<=3.0.3.7", + "openid/php-openid": "<2.3", + "openmage/magento-lts": "<19.4.15|>=20,<20.0.13", + "orchid/platform": ">=9,<9.4.4", + "oro/commerce": ">=4.1,<5.0.6", + "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", + "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<4.2.8", + "packbackbooks/lti-1-3-php-library": "<5", + "padraic/humbug_get_contents": "<1.1.2", + "pagarme/pagarme-php": ">=0,<3", + "pagekit/pagekit": "<=1.0.18", + "paragonie/random_compat": "<2", + "passbolt/passbolt_api": "<2.11", + "paypal/merchant-sdk-php": "<3.12", + "pear/archive_tar": "<1.4.14", + "pear/crypt_gpg": "<1.6.7", + "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", + "personnummer/personnummer": "<3.0.2", + "phanan/koel": "<5.1.4", + "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", + "phpmailer/phpmailer": "<6.5", + "phpmussel/phpmussel": ">=1,<1.6", + "phpmyadmin/phpmyadmin": "<5.1.3", + "phpmyfaq/phpmyfaq": "<=3.1.7", + "phpoffice/phpexcel": "<1.8", + "phpoffice/phpspreadsheet": "<1.16", + "phpseclib/phpseclib": "<2.0.31|>=3,<3.0.7", + "phpservermon/phpservermon": "<=3.5.2", + "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5,<5.6.3", + "phpwhois/phpwhois": "<=4.2.5", + "phpxmlrpc/extras": "<0.6.1", + "pimcore/data-hub": "<1.2.4", + "pimcore/pimcore": "<10.5.9", + "pocketmine/bedrock-protocol": "<8.0.2", + "pocketmine/pocketmine-mp": "<4.7.2|>= 4.0.0-BETA5, < 4.4.2", + "pressbooks/pressbooks": "<5.18", + "prestashop/autoupgrade": ">=4,<4.10.1", + "prestashop/blockwishlist": ">=2,<2.1.1", + "prestashop/contactform": ">=1.0.1,<4.3", + "prestashop/gamification": "<2.3.2", + "prestashop/prestashop": ">=1.6.0.10,<1.7.8.7", + "prestashop/productcomments": "<5.0.2", + "prestashop/ps_emailsubscription": "<2.6.1", + "prestashop/ps_facetedsearch": "<3.4.1", + "prestashop/ps_linklist": "<3.1", + "privatebin/privatebin": "<1.4", + "processwire/processwire": "<=3.0.200", + "propel/propel": ">=2-alpha.1,<=2-alpha.7", + "propel/propel1": ">=1,<=1.7.1", + "pterodactyl/panel": "<1.7", + "ptrofimov/beanstalk_console": "<1.7.14", + "pusher/pusher-php-server": "<2.2.1", + "pwweb/laravel-core": "<=0.3.6-beta", + "rainlab/debugbar-plugin": "<3.1", + "rankmath/seo-by-rank-math": "<=1.0.95", + "react/http": ">=0.7,<1.7", + "remdex/livehelperchat": "<3.99", + "rmccue/requests": ">=1.6,<1.8", + "robrichards/xmlseclibs": "<3.0.4", + "rudloff/alltube": "<3.0.3", + "s-cart/core": "<6.9", + "s-cart/s-cart": "<6.9", + "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", + "sabre/dav": ">=1.6,<1.6.99|>=1.7,<1.7.11|>=1.8,<1.8.9", + "scheb/two-factor-bundle": ">=0,<3.26|>=4,<4.11", + "sensiolabs/connect": "<4.2.3", + "serluck/phpwhois": "<=4.2.6", + "shopware/core": "<=6.4.9", + "shopware/platform": "<=6.4.9", + "shopware/production": "<=6.3.5.2", + "shopware/shopware": "<=5.7.14", + "shopware/storefront": "<=6.4.8.1", + "shopxo/shopxo": "<2.2.6", + "showdoc/showdoc": "<2.10.4", + "silverstripe/admin": ">=1,<1.8.1", + "silverstripe/assets": ">=1,<1.10.1", + "silverstripe/cms": "<4.3.6|>=4.4,<4.4.4", + "silverstripe/comments": ">=1.3,<1.9.99|>=2,<2.9.99|>=3,<3.1.1", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": "<4.10.9", + "silverstripe/graphql": "<3.5.2|>=4-alpha.1,<4-alpha.2|= 4.0.0-alpha1", + "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", + "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", + "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4", + "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", + "silverstripe/subsites": ">=2,<2.1.1", + "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", + "silverstripe/userforms": "<3", + "simple-updates/phpwhois": "<=1", + "simplesamlphp/saml2": "<1.10.6|>=2,<2.3.8|>=3,<3.1.4", + "simplesamlphp/simplesamlphp": "<1.18.6", + "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplito/elliptic-php": "<1.0.6", + "slim/slim": "<2.6", + "smarty/smarty": "<3.1.47|>=4,<4.2.1", + "snipe/snipe-it": "<6.0.11|>= 6.0.0-RC-1, <= 6.0.0-RC-5", + "socalnick/scn-social-auth": "<1.15.2", + "socialiteproviders/steam": "<1.1", + "spipu/html2pdf": "<5.2.4", + "spoonity/tcpdf": "<6.2.22", + "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "ssddanbrown/bookstack": "<22.2.3", + "statamic/cms": "<3.2.39|>=3.3,<3.3.2", + "stormpath/sdk": ">=0,<9.9.99", + "studio-42/elfinder": "<2.1.59", + "subrion/cms": "<=4.2.1", + "sulu/sulu": "= 2.4.0-RC1|<1.6.44|>=2,<2.2.18|>=2.3,<2.3.8", + "swiftmailer/swiftmailer": ">=4,<5.4.5", + "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/grid-bundle": "<1.10.1", + "sylius/paypal-plugin": ">=1,<1.2.4|>=1.3,<1.3.1", + "sylius/resource-bundle": "<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", + "sylius/sylius": "<1.9.10|>=1.10,<1.10.11|>=1.11,<1.11.2", + "symbiote/silverstripe-multivaluefield": ">=3,<3.0.99", + "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-versionedfiles": "<=2.0.3", + "symfont/process": ">=0,<4", + "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", + "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3|= 6.0.3|= 5.4.3|= 5.3.14", + "symfony/http-foundation": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7", + "symfony/http-kernel": ">=2,<2.8.52|>=3,<3.4.35|>=4,<4.2.12|>=4.3,<4.4.13|>=5,<5.1.5|>=5.2,<5.3.12", + "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", + "symfony/mime": ">=4.3,<4.3.8", + "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/polyfill": ">=1,<1.10", + "symfony/polyfill-php55": ">=1,<1.10", + "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/routing": ">=2,<2.0.19", + "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", + "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11|>=5.3,<5.3.12", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", + "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.3.2", + "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", + "symfony/symfony": ">=2,<3.4.49|>=4,<4.4.35|>=5,<5.3.12|>=5.3.14,<=5.3.14|>=5.4.3,<=5.4.3|>=6.0.3,<=6.0.3", + "symfony/translation": ">=2,<2.0.17", + "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", + "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", + "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "t3/dce": ">=2.2,<2.6.2", + "t3g/svg-sanitizer": "<1.0.3", + "tastyigniter/tastyigniter": "<3.3", + "tecnickcom/tcpdf": "<6.2.22", + "terminal42/contao-tablelookupwizard": "<3.3.5", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1-beta.1,<2.1.3", + "theonedemon/phpwhois": "<=4.2.5", + "thinkcmf/thinkcmf": "<=5.1.7", + "thorsten/phpmyfaq": "<3.1.8", + "tinymce/tinymce": "<5.10", + "titon/framework": ">=0,<9.9.99", + "tobiasbg/tablepress": "<= 2.0-RC1", + "topthink/framework": "<=6.0.13", + "topthink/think": "<=6.0.9", + "topthink/thinkphp": "<=3.2.3", + "tribalsystems/zenario": "<9.2.55826", + "truckersmp/phpwhois": "<=4.3.1", + "twig/twig": "<1.44.7|>=2,<2.15.3|>=3,<3.4.3", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.29|>=10,<10.4.32|>=11,<11.5.16", + "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/cms-core": ">=6.2,<=6.2.56|>=7,<7.6.58|>=8,<8.7.48|>=9,<9.5.37|>=10,<10.4.32|>=11,<11.5.16", + "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/html-sanitizer": ">=1,<1.0.7|>=2,<2.0.16", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", + "ua-parser/uap-php": "<3.8", + "unisharp/laravel-filemanager": "<=2.5.1", + "userfrosting/userfrosting": ">=0.3.1,<4.6.3", + "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "vanilla/safecurl": "<0.9.2", + "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", + "vrana/adminer": "<4.8.1", + "wallabag/tcpdf": "<6.2.22", + "wanglelecc/laracms": "<=1.0.3", + "web-auth/webauthn-framework": ">=3.3,<3.3.4", + "webcoast/deferred-image-processing": "<1.0.2", + "wikimedia/parsoid": "<0.12.2", + "willdurand/js-translation-bundle": "<2.1.1", + "wintercms/winter": "<1.0.475|>=1.1,<1.1.10|>=1.2,<1.2.1", + "woocommerce/woocommerce": "<6.6", + "wp-cli/wp-cli": "<2.5", + "wp-graphql/wp-graphql": "<0.3.5", + "wpanel/wpanel4-cms": "<=4.3.1", + "wwbn/avideo": "<=11.6", + "yeswiki/yeswiki": "<4.1", + "yetiforce/yetiforce-crm": "<=6.4", + "yidashi/yii2cmf": "<=2", + "yii2mod/yii2-cms": "<1.9.2", + "yiisoft/yii": ">=1.1.14,<1.1.15", + "yiisoft/yii2": "<2.0.38", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<2.0.43", + "yiisoft/yii2-elasticsearch": "<2.0.5", + "yiisoft/yii2-gii": "<2.0.4", + "yiisoft/yii2-jui": "<2.0.4", + "yiisoft/yii2-redis": "<2.0.8", + "yoast-seo-for-typo3/yoast_seo": "<7.2.3", + "yourls/yourls": "<=1.8.2", + "zendesk/zendesk_api_client_php": "<2.2.11", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", + "zendframework/zend-diactoros": "<1.8.4", + "zendframework/zend-feed": "<2.10.3", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": "<2.8.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": ">=2,<2.4.11|>=2.5,<2.7.2", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": "<=3", + "zendframework/zendframework1": "<1.12.20", + "zendframework/zendopenid": ">=2,<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zetacomponents/mail": "<1.8.2", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2", + "zoujingli/thinkadmin": "<6.0.22" + }, + "default-branch": true, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + }, + { + "name": "Ilya Tribusean", + "email": "slash3b@gmail.com", + "role": "maintainer" + } + ], + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "support": { + "issues": "https://github.com/Roave/SecurityAdvisories/issues", + "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", + "type": "tidelift" + } ], - "time": "2018-08-09T05:50:03+00:00" + "time": "2022-11-11T00:18:57+00:00" }, { - "name": "psr/http-message", + "name": "sebastian/cli-parser", "version": "1.0.1", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", + "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.0-dev" } }, "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } + "classmap": [ + "src/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2016-08-06T14:39:51+00:00" + "time": "2020-09-28T06:08:49+00:00" }, { - "name": "ralouphie/getallheaders", - "version": "2.0.5", + "name": "sebastian/code-unit", + "version": "1.0.8", "source": { "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", - "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", "shasum": "" }, "require": { - "php": ">=5.3" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "~3.7.0", - "satooshi/php-coveralls": ">=1.0" + "phpunit/phpunit": "^9.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { - "files": [ - "src/getallheaders.php" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "A polyfill for getallheaders.", - "time": "2016-02-11T07:05:27+00:00" + "time": "2020-10-26T13:08:54+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", - "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2823,34 +3998,44 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04T06:30:41+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" }, { "name": "sebastian/comparator", - "version": "2.1.3", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", - "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/diff": "^2.0 || ^3.0", - "sebastian/exporter": "^3.1" + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2863,6 +4048,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -2874,10 +4063,6 @@ { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", @@ -2887,27 +4072,38 @@ "compare", "equality" ], - "time": "2018-02-01T13:46:46+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" }, { - "name": "sebastian/diff", - "version": "2.0.1", + "name": "sebastian/complexity", + "version": "2.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", - "reference": "347c1d8b49c5c3ee30c7040ea6fc446790e6bddd", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", + "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", "shasum": "" }, "require": { - "php": "^7.0" + "nikic/php-parser": "^4.7", + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { @@ -2926,45 +4122,118 @@ ], "authors": [ { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T15:52:27+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "diff" + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } ], - "time": "2017-08-03T08:09:46+00:00" + "time": "2020-10-26T13:10:38+00:00" }, { "name": "sebastian/environment", - "version": "3.1.0", + "version": "5.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5" + "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/cd0871b3975fb7fc44d11314fd1ee20925fce4f5", - "reference": "cd0871b3975fb7fc44d11314fd1ee20925fce4f5", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.1" + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -2989,34 +4258,44 @@ "environment", "hhvm" ], - "time": "2017-07-01T08:51:00+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-04-03T09:37:03+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.0", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", + "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/recursion-context": "^3.0" + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3029,6 +4308,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -3037,46 +4320,55 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T06:03:37+00:00" }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "5.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^9.3" }, "suggest": { "ext-uopz": "*" @@ -3084,7 +4376,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -3107,34 +4399,101 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-02-14T08:28:10+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.6", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-11-28T06:42:11+00:00" }, { "name": "sebastian/object-enumerator", - "version": "3.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", - "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", "shasum": "" }, "require": { - "php": "^7.0", - "sebastian/object-reflector": "^1.1.1", - "sebastian/recursion-context": "^3.0" + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3154,32 +4513,42 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-08-03T12:35:26+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" }, { "name": "sebastian/object-reflector", - "version": "1.1.1", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "773f97c67f28de00d397be301821b06708fca0be" + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", - "reference": "773f97c67f28de00d397be301821b06708fca0be", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -3199,32 +4568,42 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", - "time": "2017-03-29T09:07:27+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" }, { "name": "sebastian/recursion-context", - "version": "3.0.0", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", - "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", + "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", "shasum": "" }, "require": { - "php": "^7.0" + "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -3237,14 +4616,14 @@ "BSD-3-Clause" ], "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, { "name": "Adam Harvey", "email": "aharvey@php.net" @@ -3252,29 +4631,42 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-03T06:23:57+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:17:30+00:00" }, { "name": "sebastian/resource-operations", - "version": "1.0.0", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", + "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -3294,29 +4686,42 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28T20:34:47+00:00" + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:45:17+00:00" }, { - "name": "sebastian/version", - "version": "2.0.1", + "name": "sebastian/type", + "version": "3.2.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.2-dev" } }, "autoload": { @@ -3335,90 +4740,147 @@ "role": "lead" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03T07:35:21+00:00" + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-12T14:47:03+00:00" }, { - "name": "symfony/browser-kit", - "version": "v3.4.21", + "name": "sebastian/version", + "version": "3.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/browser-kit.git", - "reference": "6d98fb221a263c66b1311203fe4eed154035f508" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/6d98fb221a263c66b1311203fe4eed154035f508", - "reference": "6d98fb221a263c66b1311203fe4eed154035f508", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/dom-crawler": "~2.8|~3.0|~4.0" - }, - "require-dev": { - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0" - }, - "suggest": { - "symfony/process": "" + "php": ">=7.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Component\\BrowserKit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "url": "https://github.com/sebastianbergmann", + "type": "github" } ], - "description": "Symfony BrowserKit Component", - "homepage": "https://symfony.com", - "time": "2019-01-01T13:45:19+00:00" + "time": "2020-09-28T06:39:44+00:00" }, { - "name": "symfony/css-selector", - "version": "v3.4.21", + "name": "squizlabs/php_codesniffer", + "version": "3.7.1", "source": { "type": "git", - "url": "https://github.com/symfony/css-selector.git", - "reference": "12f86295c46c36af9896cf21db6b6b8a1465315d" + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/12f86295c46c36af9896cf21db6b6b8a1465315d", - "reference": "12f86295c46c36af9896cf21db6b6b8a1465315d", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", + "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2022-06-18T07:21:10+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "0dd5e36b80e1de97f8f74ed7023ac2b837a36443" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/0dd5e36b80e1de97f8f74ed7023ac2b837a36443", + "reference": "0dd5e36b80e1de97f8f74ed7023ac2b837a36443", + "shasum": "" + }, + "require": { + "php": ">=8.1" }, + "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\CssSelector\\": "" @@ -3432,57 +4894,84 @@ "MIT" ], "authors": [ - { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony CssSelector Component", + "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", - "time": "2019-01-02T09:30:52+00:00" + "support": { + "source": "https://github.com/symfony/css-selector/tree/v6.1.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-06-27T17:24:16+00:00" }, { - "name": "symfony/dom-crawler", - "version": "v3.4.21", + "name": "symfony/var-dumper", + "version": "v6.1.6", "source": { "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "311f666d85d1075b0a294ba1f3de4ae9307d8180" + "url": "https://github.com/symfony/var-dumper.git", + "reference": "0f0adde127f24548e23cbde83bcaeadc491c551f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/311f666d85d1075b0a294ba1f3de4ae9307d8180", - "reference": "311f666d85d1075b0a294ba1f3de4ae9307d8180", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0f0adde127f24548e23cbde83bcaeadc491c551f", + "reference": "0f0adde127f24548e23cbde83bcaeadc491c551f", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8", + "php": ">=8.1", "symfony/polyfill-mbstring": "~1.0" }, + "conflict": { + "phpunit/phpunit": "<5.4.3", + "symfony/console": "<5.4" + }, "require-dev": { - "symfony/css-selector": "~2.8|~3.0|~4.0" + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/uid": "^5.4|^6.0", + "twig/twig": "^2.13|^3.0.4" }, "suggest": { - "symfony/css-selector": "" + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script" }, + "bin": [ + "Resources/bin/var-dump-server" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.4-dev" - } - }, "autoload": { + "files": [ + "Resources/functions/dump.php" + ], "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" + "Symfony\\Component\\VarDumper\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -3494,37 +4983,58 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony DomCrawler Component", + "description": "Provides mechanisms for walking through any arbitrary PHP variable", "homepage": "https://symfony.com", - "time": "2019-01-01T13:45:19+00:00" + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.1.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-10-07T08:04:03+00:00" }, { "name": "theseer/tokenizer", - "version": "1.1.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b" + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/cb2f008f3f05af2893a87208fe6a6c4985483f8b", - "reference": "cb2f008f3f05af2893a87208fe6a6c4985483f8b", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { "ext-dom": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": "^7.0" + "php": "^7.2 || ^8.0" }, "type": "library", "autoload": { @@ -3544,65 +5054,35 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2017-04-07T12:08:54+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0", - "symfony/polyfill-ctype": "^1.8" - }, - "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ + "funding": [ { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" + "url": "https://github.com/theseer", + "type": "github" } ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "time": "2018-12-25T11:19:39+00:00" + "time": "2021-07-28T10:34:58+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "roave/security-advisories": 20 + }, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [] + "platform": { + "php": "^8.1", + "ext-dom": "*", + "ext-libxml": "*", + "ext-json": "*" + }, + "platform-dev": [], + "platform-overrides": { + "php": "8.1.12" + }, + "plugin-api-version": "2.3.0" } diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..073ad7b --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,13 @@ +ARG PHP_VERSION=7.4 +FROM php:${PHP_VERSION}-cli as base +COPY --from=composer /usr/bin/composer /usr/bin/composer + +RUN apt update \ + && apt upgrade -y \ + && apt install -y apt-utils libxml2-dev libzip-dev + +FROM base as PHP74 +RUN docker-php-ext-install dom json xml zip + +FROM base as PHP8 +RUN docker-php-ext-install dom xml zip \ No newline at end of file diff --git a/src/Exception/KeyNotFoundException.php b/src/Exception/KeyNotFoundException.php new file mode 100644 index 0000000..2c59765 --- /dev/null +++ b/src/Exception/KeyNotFoundException.php @@ -0,0 +1,11 @@ + 'afterFail', + Events::RESULT_PRINT_AFTER => 'endRun', + ]; + + /** + * Event after each failed test - collect the failed test + */ + public function afterFail(FailEvent $event): void + { + $this->failedTests[] = $this->getTestName($event); + } + + /** + * Event after all Tests - write failed tests to report file + */ + public function endRun(): void + { + if (empty($this->failedTests)) { + return; + } + + $file = $this->getLogDir() . $this->getUniqReportFile(); + if (is_file($file)) { + unlink($file); // remove old reportFile + } + + file_put_contents($file, implode(PHP_EOL, $this->failedTests)); + } + + public function getTestName(TestEvent $e): string + { + $name = Descriptor::getTestFullName($e->getTest()); + + // If a leading DIRECTORY_SEPARATOR was found, remove it + return ltrim(str_replace($this->getRootDir(), '', $name), DIRECTORY_SEPARATOR); + } + + public function getUniqReportFile(): string + { + return self::REPORT_NAME . '_' . uniqid('', true) . '.txt'; + } +} diff --git a/src/Extension/TimeReporter.php b/src/Extension/TimeReporter.php new file mode 100644 index 0000000..4268648 --- /dev/null +++ b/src/Extension/TimeReporter.php @@ -0,0 +1,52 @@ + 'endRun', + Events::TEST_END => 'after', + ]; + + private array $timeList = []; + + /** + * Event handler after each test - collect stat + */ + public function after(TestEvent $e): void + { + $name = $this->getTestName($e); + + if (empty($this->timeList[$name])) { + $this->timeList[$name] = 0; + } + $this->timeList[$name] += $e->getTime(); + } + + /** + * Event handler after all tests - save stat + */ + public function endRun(): void + { + $file = $this->getLogDir() . 'timeReport.json'; + $data = is_file($file) ? json_decode(file_get_contents($file), true) : []; + $data = array_replace($data, $this->timeList); + file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT)); + } + + public function getTestName(TestEvent $e): string + { + $name = Descriptor::getTestFullName($e->getTest()); + + // If a leading DIRECTORY_SEPARATOR was found, remove it + return ltrim(str_replace($this->getRootDir(), '', $name), DIRECTORY_SEPARATOR); + } +} diff --git a/src/Filter/DefaultFilter.php b/src/Filter/DefaultFilter.php new file mode 100644 index 0000000..11cb690 --- /dev/null +++ b/src/Filter/DefaultFilter.php @@ -0,0 +1,29 @@ +tests = $tests; + } + + /** + * @inheritDoc + */ + public function filter(): array + { + return $this->tests; + } +} diff --git a/src/Filter/Filter.php b/src/Filter/Filter.php new file mode 100644 index 0000000..60bda4d --- /dev/null +++ b/src/Filter/Filter.php @@ -0,0 +1,22 @@ +resetIncludedGroups(); + $this->resetExcludedGroups(); + } + + public function resetIncludedGroups(): void + { + $this->includedGroups = []; + } + + public function resetExcludedGroups(): void + { + $this->excludedGroups = []; + } + + /** + * @return SelfDescribing[] + */ + public function getTests(): array + { + return $this->tests; + } + + /** + * Adds a group name to the excluded array + */ + public function groupExcluded(string $group): self + { + if (in_array($group, $this->getIncludedGroups(), true)) { + throw new InvalidArgumentException( + sprintf( + 'You can mark group "%s" only as included OR excluded.', + $group + ) + ); + } + + if (!in_array($group, $this->getExcludedGroups(), true)) { + $this->excludedGroups[] = $group; + } + + return $this; + } + + /** + * Adds a group name to the included array + */ + public function groupIncluded(string $group): self + { + if (in_array($group, $this->getExcludedGroups(), true)) { + throw new InvalidArgumentException( + sprintf( + 'You can mark group "%s" only as included OR excluded.', + $group + ) + ); + } + + if (!in_array($group, $this->getIncludedGroups(), true)) { + $this->includedGroups[] = $group; + } + + return $this; + } + + public function getExcludedGroups(): array + { + return $this->excludedGroups; + } + + /** + * @return string[] + */ + public function getIncludedGroups(): array + { + return $this->includedGroups; + } + + /** + * @param SelfDescribing[] $tests + */ + public function setTests(array $tests): void + { + $this->tests = $tests; + } + + /** + * Filter the tests by the given included and excluded @group annotations + * + * @return \PHPUnit\Framework\SelfDescribing[] + */ + public function filter(): array + { + $groupManager = new GroupManager([]); + + $testsByGroups = []; + foreach ($this->getTests() as $test) { + if (!($test instanceof SelfDescribing)) { + throw new InvalidArgumentException( + 'Tests must be an instance of ' . SelfDescribing::class + ); + } + + $groups = $groupManager->groupsForTest($test); + + if (!$groups && $test instanceof \PHPUnit\Framework\DataProviderTestSuite) { + /** @var \PHPUnit\Framework\DataProviderTestSuite $dataProviderTestSuite */ + $dataProviderTestSuite = $test; + // By definition (a) all tests of dataprovider test suite are the same test + // case definition, and (b) there is at least one test case + $firstDataProviderTest = $dataProviderTestSuite->tests()[0]; + $groups = $groupManager->groupsForTest($firstDataProviderTest); + } + + if ( + !empty($this->getExcludedGroups()) + && [] === array_diff($this->getExcludedGroups(), $groups) + ) { + continue; + } + + if ( + !empty($this->getIncludedGroups()) + && [] !== array_diff($this->getIncludedGroups(), $groups) + ) { + continue; + } + + $testsByGroups[] = $test; + } + + return $testsByGroups; + } +} diff --git a/src/MergeReports.php b/src/MergeReports.php deleted file mode 100644 index 4c20e84..0000000 --- a/src/MergeReports.php +++ /dev/null @@ -1,326 +0,0 @@ -task(MergeXmlReportsTask::class, $src); - } - - protected function taskMergeHTMLReports($src = []) - { - return $this->task(MergeHTMLReportsTask::class, $src); - } -} - -interface MergeReportsTaskInterface -{ - public function from($fileName); - - public function into($fileName); -} - -class MergeXmlReportsTask extends BaseTask implements TaskInterface, MergeReportsTaskInterface -{ - protected $src = []; - protected $dst; - protected $summarizeTime = true; - - protected $mergeRewrite = false; - /** @var \DOMElement[][] */ - protected $suites = []; - - public function __construct($src = []) - { - $this->src = $src; - } - - public function sumTime() - { - $this->summarizeTime = true; - } - - public function maxTime() - { - $this->summarizeTime = false; - } - - public function mergeRewrite() - { - $this->mergeRewrite = true; - return $this; - } - - public function from($fileName) - { - if (is_array($fileName)) { - $this->src = array_merge($fileName, $this->src); - } else { - $this->src[] = $fileName; - } - return $this; - } - - public function into($fileName) - { - $this->dst = $fileName; - return $this; - } - - public function run() - { - if (!$this->dst) { - throw new TaskException($this, "No destination file is set. Use `->into()` method to set result xml"); - } - $this->printTaskInfo("Merging JUnit XML reports into {$this->dst}"); - $dstXml = new \DOMDocument(); - $dstXml->appendChild($dstXml->createElement('testsuites')); - - $this->suites = []; - foreach ($this->src as $src) { - $this->printTaskInfo("Processing $src"); - - $srcXml = new \DOMDocument(); - if (!file_exists($src)) { - throw new TaskException($this, "XML file $src does not exist"); - } - $loaded = $srcXml->load($src); - if (!$loaded) { - $this->printTaskInfo("File $src can't be loaded as XML"); - continue; - } - $suiteNodes = (new \DOMXPath($srcXml))->query('//testsuites/testsuite'); - foreach ($suiteNodes as $suiteNode) { - $suiteNode = $dstXml->importNode($suiteNode, true); - /** @var $suiteNode \DOMElement **/ - $this->loadSuites($suiteNode); - } - } - - $this->mergeSuites($dstXml); - - $dstXml->save($this->dst); - $this->printTaskInfo("File {$this->dst} saved. ".count($this->suites).' suites added'); - } - - protected function loadSuites(\DOMElement $current) - { - /** @var \DOMNode $node */ - foreach ($current->childNodes as $node) { - if ($node instanceof \DOMElement) { - if ($this->mergeRewrite) { - $this->suites[$current->getAttribute('name')][$node->getAttribute('class') . '::' . $node->getAttribute('name')] = $node->cloneNode(true); - } else { - $this->suites[$current->getAttribute('name')][] = $node->cloneNode(true); - } - } - } - } - - protected function mergeSuites(\DOMDocument $dstXml) - { - foreach ($this->suites as $suiteName => $tests) { - $resultNode = $dstXml->createElement("testsuite"); - $resultNode->setAttribute('name', $suiteName); - $data = [ - 'tests' => count($tests), - 'assertions' => 0, - 'failures' => 0, - 'errors' => 0, - 'time' => 0, - ]; - foreach ($tests as $test) { - $resultNode->appendChild($test); - - $data['assertions'] += (int)$test->getAttribute('assertions'); - $data['time'] = $this->summarizeTime - ? ((float) $test->getAttribute('time') + $data['time']) - : max($test->getAttribute('time'), $data['time']); - - $data['failures'] += $test->getElementsByTagName('failure')->length; - $data['errors'] += $test->getElementsByTagName('error')->length; - } - foreach ($data as $key => $value) { - $resultNode->setAttribute($key, $value); - } - $dstXml->firstChild->appendChild($resultNode); - } - } -} - -/** - * Generate common HTML report - * Class MergeHTMLReportsTask - * @author Kerimov Asif - */ -class MergeHTMLReportsTask extends BaseTask implements TaskInterface, MergeReportsTaskInterface -{ - protected $src = []; - protected $dst; - protected $countSuccess = 0; - protected $countFailed = 0; - protected $countSkipped = 0; - protected $countIncomplete = 0; - protected $previousLibXmlUseErrors; - - public function __construct($src = []) - { - $this->src = $src; - } - - public function from($fileName) - { - if (is_array($fileName)) { - $this->src = array_merge($fileName, $this->src); - } else { - $this->src[] = $fileName; - } - return $this; - } - - public function into($fileName) - { - $this->dst = $fileName; - return $this; - } - - public function run() - { - //save initial statament and switch on use_internal_errors mode - $this->previousLibXmlUseErrors = libxml_use_internal_errors(true); - - if (!$this->dst) { - libxml_use_internal_errors($this->previousLibXmlUseErrors); - throw new TaskException($this, "No destination file is set. Use `->into()` method to set result HTML"); - } - - $this->printTaskInfo("Merging HTML reports into {$this->dst}"); - - //read first source file as main - $dstHTML = new \DOMDocument(); - $dstHTML->loadHTMLFile($this->src[0],LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); - - //main node for all table rows - $table = (new \DOMXPath($dstHTML))->query("//table")->item(0); - - //prepare reference nodes for envs - $refnodes = (new \DOMXPath($dstHTML))->query("//div[@class='layout']/table/tr[not(@class)]"); - - for($k=1;$ksrc);$k++){ - $srcHTML = new \DOMDocument(); - $src = $this->src[$k]; - $srcHTML->loadHTMLFile($src,LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); - $suiteNodes = (new \DOMXPath($srcHTML))->query("//div[@class='layout']/table/tr"); - $j=0; - foreach($suiteNodes as $suiteNode){ - if($suiteNode->getAttribute('class') == ''){ - //move to next reference node - $j++; - if($j > $refnodes->length-1) break; - continue; - } - //insert nodes before current reference node - $suiteNode = $dstHTML->importNode($suiteNode, true); - $table->insertBefore($suiteNode, $refnodes->item($j)); - } - } - - /** - * The next 5 functions correct our almost finished final report - */ - $this->countSummary($dstHTML); - $this->moveSummaryTable($dstHTML,$table); - $this->updateSummaryTable($dstHTML); - $this->updateToolbarTable($dstHTML); - $this->updateButtons($dstHTML); - - //save final report - file_put_contents($this->dst,$dstHTML->saveHTML()); - - //return to initial statement - libxml_use_internal_errors($this->previousLibXmlUseErrors); - } - - /** - * This function counts all types of tests' scenarios and writes in class members - * @param $dstFile \DOMDocument - destination file - */ - private function countSummary($dstFile){ - $tests = (new \DOMXPath($dstFile))->query("//table/tr[contains(@class,'scenarioRow')]"); - foreach($tests as $test){ - $class = str_replace('scenarioRow ', '', $test->getAttribute('class')); - switch($class){ - case 'scenarioSuccess': - $this->countSuccess += 0.5; - break; - case 'scenarioFailed': - $this->countFailed += 0.5; - break; - case 'scenarioSkipped': - $this->countSkipped += 0.5; - break; - case 'scenarioIncomplete': - $this->countIncomplete += 0.5; - break; - } - } - } - - /** - * This function updates values in Summary block for each type of scenarios - * @param $dstFile \DOMDocument - destination file - */ - private function updateSummaryTable($dstFile){ - $dstFile = new \DOMXPath($dstFile); - $pathFor = function ($type) { return "//div[@id='stepContainerSummary']//td[@class='$type']";}; - $dstFile->query($pathFor('scenarioSuccessValue'))->item(0)->nodeValue = $this->countSuccess; - $dstFile->query($pathFor('scenarioFailedValue'))->item(0)->nodeValue = $this->countFailed; - $dstFile->query($pathFor('scenarioSkippedValue'))->item(0)->nodeValue = $this->countSkipped; - $dstFile->query($pathFor('scenarioIncompleteValue'))->item(0)->nodeValue = $this->countIncomplete; - } - - /** - * This function moves Summary block in the bottom of result report - * @param $dstFile \DOMDocument - destination file - * @param $node \DOMNode - parent node of Summary table - */ - private function moveSummaryTable($dstFile,$node){ - $summaryTable = (new \DOMXPath($dstFile))->query("//div[@id='stepContainerSummary']") - ->item(0)->parentNode->parentNode; - $node->appendChild($dstFile->importNode($summaryTable,true)); - } - - /** - * This function updates values in Toolbar block for each type of scenarios (blue block on the left side of the report) - * @param $dstFile \DOMDocument - destination file - */ - private function updateToolbarTable($dstFile){ - $dstFile = new \DOMXPath($dstFile); - $pathFor = function ($type) {return "//ul[@id='toolbar-filter']//a[@title='$type']";}; - $dstFile->query($pathFor('Successful'))->item(0)->nodeValue = '✔ '.$this->countSuccess; - $dstFile->query($pathFor('Failed'))->item(0)->nodeValue = '✗ '.$this->countFailed; - $dstFile->query($pathFor('Skipped'))->item(0)->nodeValue = 'S '.$this->countSkipped; - $dstFile->query($pathFor('Incomplete'))->item(0)->nodeValue= 'I '.$this->countIncomplete; - } - - /** - * This function updates "+" and "-" button for viewing test steps in final report - * @param $dstFile \DOMDocument - destination file - */ - private function updateButtons($dstFile){ - $nodes = (new \DOMXPath($dstFile))->query("//div[@class='layout']/table/tr[contains(@class, 'scenarioRow')]"); - for($i=2;$i<$nodes->length;$i+=2){ - $n = $i/2 + 1; - $p = $nodes->item($i)->childNodes->item(1)->childNodes->item(1); - $table = $nodes->item($i+1)->childNodes->item(1)->childNodes->item(1); - $p->setAttribute('onclick',"showHide('$n', this)"); - $table->setAttribute('id',"stepContainer".$n); - } - } - -} diff --git a/src/Merger/AbstractMerger.php b/src/Merger/AbstractMerger.php new file mode 100644 index 0000000..d774524 --- /dev/null +++ b/src/Merger/AbstractMerger.php @@ -0,0 +1,29 @@ +src = $src; + } + + /** + * @inheritDoc + */ + abstract public function from($fileName): self; + + abstract public function into(string $fileName): self; + + /** + * @inheritDoc + */ + abstract public function run(); +} diff --git a/src/Merger/FailedTestsMergerTask.php b/src/Merger/FailedTestsMergerTask.php new file mode 100644 index 0000000..d8bdcd3 --- /dev/null +++ b/src/Merger/FailedTestsMergerTask.php @@ -0,0 +1,124 @@ +taskMergeFailedTestsReports() + * ->from(__DIR__ . 'tests/_data/Acme/failedTests_123.txt') + * ->from(__DIR__ . 'tests/_data/failedTests_foo.txt') + * ->from([__DIR__ . 'tests/_data/Acme/failedTests_bar.txt', __DIR__ . 'tests/_data/Acme/failedTests_baz.txt',]) + * ->fromPathWithPattern(__DIR__ . 'tests/_data/failed_1/', '/failedTests_\w+\.txt$/') + * ->fromPathWithPattern(__DIR__ . 'tests/_data/failed_2/', '/failedTests_\w+\.txt$/') + * ->into(__DIR__ . '/failedTests.txt') // absolute path with Filename + * ->run(); + * ``` + * + * @see \Tests\Codeception\Task\Merger\FailedTestsMergerTaskTest + */ +class FailedTestsMergerTask extends AbstractMerger +{ + /** + * @var string + */ + public const DEFAULT_PATTERN = '/^failedTests_\w+\.\w+\.txt$/'; + + public array $pathPatterns = []; + + private string $dest = ''; + + /** @var string[] */ + protected array $src = []; + + /** + * @param string[]|string $fileName + * @return FailedTestsMergerTask|void + */ + public function from($fileName): self + { + if (!(is_array($fileName) || is_string($fileName) || !empty($fileName))) { + throw new InvalidArgumentException( + 'The argument must be an array or string and could not be empty.' + ); + } + + $this->src = array_merge($this->src, (is_string($fileName) ? [$fileName] : $fileName)); + + return $this; + } + + /** + * Search all report files in path with default pattern or the given pattern + * + * @param string $path - The path where the report files exists + * @param string|null $pattern - The regex pattern for the files (optional) + * @return $this + */ + public function fromPathWithPattern(string $path, ?string $pattern = null): self + { + $this->pathPatterns[$path] = $pattern ?? self::DEFAULT_PATTERN; + + return $this; + } + + public function into(string $fileName): self + { + $this->dest = $fileName; + + return $this; + } + + public function run(): void + { + $content = []; + $files = array_merge($this->src, $this->searchFilesByPattern()); + foreach ($files as $file) { + if (!is_file($file)) { + continue; + } + + $tmpContent = file_get_contents($file); + if (!$tmpContent) { + throw new RuntimeException( + 'Could not read content of reportfile: ' . $file + ); + } + + $content[] = $tmpContent; + } + + if (!empty($content)) { + file_put_contents($this->dest, implode(PHP_EOL, $content)); + } + } + + /** + * Search the files by the given path and pattern + */ + private function searchFilesByPattern(): array + { + $results = []; + foreach ($this->pathPatterns as $path => $pattern) { + $files = Finder::create() + ->files() + ->in($path) + ->name($pattern ?? self::DEFAULT_PATTERN); + foreach ($files->getIterator() as $splFileInfo) { + $results[] = $splFileInfo->getPathname(); + } + } + + return $results; + } +} diff --git a/src/Merger/HtmlReportMerger.php b/src/Merger/HtmlReportMerger.php new file mode 100644 index 0000000..a2c0066 --- /dev/null +++ b/src/Merger/HtmlReportMerger.php @@ -0,0 +1,416 @@ +maxTime = true; + } + + /** + * HtmlReportMerger constructor. + * + * @param string[] $src - array of source reports + */ + public function __construct(array $src = []) + { + $this->src = $src; + } + + /** + * @param string[]|string $fileName - a single report file or array of report files + * @return $this|HtmlReportMerger + */ + public function from($fileName): self + { + if (is_array($fileName)) { + $this->src = array_merge($fileName, $this->src); + } else { + $this->src[] = $fileName; + } + + return $this; + } + + /** + * @return $this|HtmlReportMerger + */ + public function into(string $fileName): self + { + $this->dst = $fileName; + return $this; + } + + public function run(): void + { + //save initial statament and switch on use_internal_errors mode + $this->previousLibXmlUseErrors = libxml_use_internal_errors(true); + + if ($this->dst === '' || $this->dst === '0') { + libxml_use_internal_errors($this->previousLibXmlUseErrors); + throw new TaskException($this, "No destination file is set. Use `->into()` method to set result HTML"); + } + + $this->printTaskInfo("Remove not existing HTML reports..."); + foreach ($this->src as $index => $item) { + if (!file_exists($item)) { + unset($this->src[$index]); + $this->printTaskWarning( + "HTML report {$item} did not exist and was removed from merge list" + ); + } + } + + // Resetting keys + $this->src = array_values($this->src); + + $this->printTaskInfo("Merging HTML reports into {$this->dst}"); + + //read first source file as main + $dstHTML = new DOMDocument(); + $dstHTML->loadHTMLFile($this->src[0], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + $this->countExecutionTime($dstHTML); + //main node for all table rows + $nodeList = (new DOMXPath($dstHTML))->query("//table"); + if (!$nodeList) { + throw XPathExpressionException::malformedXPath("//table"); + } + + $index = 0; + $table = $nodeList->item($index); + if (!$table instanceof DOMNode) { + throw new KeyNotFoundException('Could not find table item at pos: ' . $index); + } + + //prepare reference nodes for envs + $xpathExprRefNodes = "//div[@class='layout']/table/tr[not(@class)]"; + $refnodes = (new DOMXPath($dstHTML))->query($xpathExprRefNodes); + if (!$refnodes) { + throw XPathExpressionException::malformedXPath($xpathExprRefNodes); + } + + for ($k = 1, $kMax = count($this->src); $k < $kMax; ++$k) { + $src = $this->src[$k]; + if (!file_exists($src) || !is_readable($src)) { + $this->printTaskWarning('File did not exists or is not readable: ' . $src); + continue; + } + + $srcHTML = new DOMDocument(); + $srcHTML->loadHTMLFile($src, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + $this->countExecutionTime($srcHTML); + $xpathExprSuiteNodes = "//div[@class='layout']/table/tr"; + $suiteNodes = (new DOMXPath($srcHTML))->query($xpathExprSuiteNodes); + if (!$suiteNodes) { + throw XPathExpressionException::malformedXPath($xpathExprSuiteNodes); + } + + $j = 0; + foreach ($suiteNodes as $suiteNode) { + if ($suiteNode->getAttribute('class') == '') { + //move to next reference node + ++$j; + if ($j > $refnodes->length - 1) { + break; + } + + continue; + } + + //insert nodes before current reference node + $suiteNode = $dstHTML->importNode($suiteNode, true); + $table->insertBefore($suiteNode, $refnodes->item($j)); + } + } + + /** + * The next 6 functions correct our almost finished final report + */ + $this->countSummary($dstHTML); + $this->moveSummaryTable($dstHTML, $table); + $this->updateSummaryTable($dstHTML); + $this->updateToolbarTable($dstHTML); + $this->updateButtons($dstHTML); + $this->updateHeaderLine($dstHTML); + + //save final report + file_put_contents($this->dst, $dstHTML->saveHTML()); + + //return to initial statement + libxml_use_internal_errors($this->previousLibXmlUseErrors); + } + + /** + * This function sums all execution time of each report + * @param DOMDocument $dstFile + * @throws XPathExpressionException + */ + private function countExecutionTime(DOMDocument $dstFile): void + { + $xpathHeadline = "//h1[text() = 'Codeception Results ']"; + $nodeList = (new DOMXPath($dstFile)) + ->query($xpathHeadline); + if (!$nodeList) { + throw XPathExpressionException::malformedXPath($xpathHeadline); + } + $hoursMinutesSeconds = '(([0-1]?\d|2[0-3])(?::([0-5]?\d))?(?::([0-5]?\d))\.\d+)'; + $seconds = '\d+\.\d+s'; + $pregResult = preg_match( + "#^Codeception Results .* \((?$hoursMinutesSeconds|$seconds)\)$#", + $nodeList[0]->nodeValue, + $matches + ); + + if (false === $pregResult) { + throw new RuntimeException('Regexpression is malformed'); + } + + if (0 === $pregResult) { + return; + } + + if (str_contains($matches['timesum'], 's')) { + $matches['timesum'] = str_replace('s', '', $matches['timesum']); + } + if (!$this->maxTime) { + if (str_contains($matches['timesum'], ':')) { + $this->executionTimeSum = $this->sumTime(strval($this->executionTimeSum), (string)$matches['timesum']); + } else { + $this->executionTimeSum += (float)$matches['timesum']; + } + } else { + $this->executionTime[] = (string)$matches['timesum']; + } + } + + /** + * @param DOMDocument $dstFile + * @throws XPathExpressionException + */ + private function updateHeaderLine(DOMDocument $dstFile): void + { + $xpathHeadline = "//h1[text() = 'Codeception Results ']"; + $nodeList = (new DOMXPath($dstFile)) + ->query($xpathHeadline); + if (!$nodeList) { + throw XPathExpressionException::malformedXPath($xpathHeadline); + } + + /** @var DOMNode $executionTimeNode */ + $executionTimeNode = $nodeList[0]->childNodes[1]->childNodes[1]; + /** @var DOMAttr $statusAttr */ + $statusNode = $nodeList[0]->childNodes[1]->childNodes[0]; + $statusAttr = $statusNode->attributes[0]; + if (0 !== $this->countFailed) { + $statusNode->nodeValue = 'FAILED'; + $statusAttr->value = 'color: red'; + } + if (!$this->maxTime) { + $executionTime = (string)$this->executionTimeSum; + } else { + usort($this->executionTime, function ($a, $b) { + return strcmp($a, $b); + }); + $executionTime = max($this->executionTime); + } + $executionTimeNode->nodeValue = sprintf( + (preg_match('#([0-1]?\d|2[0-3])(?::([0-5]?\d))?(?::([0-5]?\d))\.\d+#', $executionTime)) + ? ' (%s)' + : ' (%ss)', + $executionTime + ); + } + + /** + * This function counts all types of tests' scenarios and writes in class members + * + * @param DOMDocument $dstFile - destination file + * @throws XPathExpressionException + */ + private function countSummary(DOMDocument $dstFile): void + { + $xpathExprTests = "//table/tr[contains(@class,'scenarioRow')]"; + /** @var DOMNodeList $tests */ + $tests = (new DOMXPath($dstFile))->query($xpathExprTests); + if (!$tests) { + throw XPathExpressionException::malformedXPath($xpathExprTests); + } + + foreach ($tests as $test) { + $class = str_replace('scenarioRow ', '', $test->getAttribute('class')); + switch ($class) { + case 'scenarioSuccess': + $this->countSuccess += 0.5; + break; + case 'scenarioFailed': + $this->countFailed += 0.5; + break; + case 'scenarioSkipped': + $this->countSkipped += 0.5; + break; + case 'scenarioIncomplete': + $this->countIncomplete += 0.5; + break; + } + } + } + + /** + * This function updates values in Summary block for each type of scenarios + * + * @param DOMDocument $dstFile - destination file + */ + private function updateSummaryTable(DOMDocument $dstFile): void + { + $dstFile = new DOMXPath($dstFile); + $pathFor = fn($type): string => sprintf("//div[@id='stepContainerSummary']//td[@class='%s']", $type); + $dstFile->query($pathFor('scenarioSuccessValue'))->item(0)->nodeValue = (string)$this->countSuccess; + $dstFile->query($pathFor('scenarioFailedValue'))->item(0)->nodeValue = (string)$this->countFailed; + $dstFile->query($pathFor('scenarioSkippedValue'))->item(0)->nodeValue = (string)$this->countSkipped; + $dstFile->query($pathFor('scenarioIncompleteValue'))->item(0)->nodeValue = (string)$this->countIncomplete; + } + + /** + * This function moves Summary block in the bottom of result report + * + * @param $dstFile DOMDocument - destination file + * @param $node DOMNode - parent node of Summary table + */ + private function moveSummaryTable(DOMDocument $dstFile, DOMNode $node): void + { + $summaryTable = (new DOMXPath($dstFile))->query("//div[@id='stepContainerSummary']") + ->item(0)->parentNode->parentNode; + $node->appendChild($dstFile->importNode($summaryTable, true)); + } + + /** + * This function updates values in Toolbar block for each type of scenarios + * (blue block on the left side of the report) + * + * @param DOMDocument $dstFile - destination file + */ + private function updateToolbarTable(DOMDocument $dstFile): void + { + $dstFile = new DOMXPath($dstFile); + $pathFor = static fn(string $type): string => sprintf("//ul[@id='toolbar-filter']//a[@title='%s']", $type); + $dstFile->query($pathFor('Successful'))->item(0)->nodeValue = '✔ ' . $this->countSuccess; + $dstFile->query($pathFor('Failed'))->item(0)->nodeValue = '✗ ' . $this->countFailed; + $dstFile->query($pathFor('Skipped'))->item(0)->nodeValue = 'S ' . $this->countSkipped; + $dstFile->query($pathFor('Incomplete'))->item(0)->nodeValue = 'I ' . $this->countIncomplete; + } + + /** + * This function updates "+" and "-" button for viewing test steps in final report + * + * @param $dstFile DOMDocument - destination file + * @throws XPathExpressionException + */ + private function updateButtons(DOMDocument $dstFile): void + { + $xpathExprNodes = "//div[@class='layout']/table/tr[contains(@class, 'scenarioRow')]"; + $nodes = (new DOMXPath($dstFile))->query($xpathExprNodes); + if (!$nodes) { + throw XPathExpressionException::malformedXPath($xpathExprNodes); + } + + for ($i = 2; $i < $nodes->length; $i += 2) { + $n = $i / 2 + 1; + $p = $nodes->item($i)->childNodes->item(1)->childNodes->item(1); + $table = $nodes->item($i + 1)->childNodes->item(1)->childNodes->item(1); + $p->setAttribute('onclick', "showHide('{$n}', this)"); + $table->setAttribute('id', "stepContainer" . $n); + } + } + + private function sumTime(string $time1, string $time2): string + { + $times = [$time1, $time2]; + $seconds = 0; + $milliseconds = 0; + $isHour = false; + foreach ($times as $time) { + if ($time !== '0') { + $output = explode(':', $time); + if (count($output) > 2) { + $isHour = true; + [$hour, $minute, $second] = $output; + $seconds += $hour * 3600; + } else { + [$minute, $second] = $output; + } + $seconds += $minute * 60; + [$second, $millisecond] = explode('.', $second); + $seconds += $second; + $milliseconds += $millisecond; + } + } + if ($isHour) { + $hours = floor($seconds / 3600); + $seconds -= $hours * 3600; + } + $minutes = floor($seconds / 60); + $seconds -= $minutes * 60; + + return $isHour + ? sprintf('%02d:%02d:%02d.%02d', $hours, $minutes, $seconds, $milliseconds) + : sprintf('%02d:%02d.%02d', $minutes, $seconds, $milliseconds); + } +} diff --git a/src/Merger/ReportMerger.php b/src/Merger/ReportMerger.php new file mode 100644 index 0000000..b45da16 --- /dev/null +++ b/src/Merger/ReportMerger.php @@ -0,0 +1,23 @@ +task(XmlReportMergerTask::class, $src); + } + + protected function taskMergeHTMLReports($src = []) + { + return $this->task(HtmlReportMerger::class, $src); + } + + protected function taskMergeFailedTestsReports($src = []) + { + return $this->task(FailedTestsMergerTask::class, $src); + } +} diff --git a/src/Merger/ReportMergerTaskInterface.php b/src/Merger/ReportMergerTaskInterface.php new file mode 100644 index 0000000..5378811 --- /dev/null +++ b/src/Merger/ReportMergerTaskInterface.php @@ -0,0 +1,16 @@ +summarizeTime = true; + } + + public function maxTime(): void + { + $this->summarizeTime = false; + } + + public function maxSuiteTime(): void + { + $this->summarizeTime = false; + $this->maxSuiteTime = true; + } + + public function mergeRewrite(): self + { + $this->mergeRewrite = true; + + return $this; + } + + /** + * @param array|string $fileName + */ + public function from($fileName): self + { + if (is_array($fileName)) { + $this->src = array_merge($fileName, $this->src); + } else { + $this->src[] = $fileName; + } + + return $this; + } + + public function into(string $fileName): self + { + $this->dst = $fileName; + + return $this; + } + + public function run(): void + { + if ($this->dst === '' || $this->dst === '0') { + throw new TaskException( + $this, + "No destination file is set. Use `->into()` method to set result xml" + ); + } + + $this->printTaskInfo(sprintf('Merging JUnit XML reports into %s', $this->dst)); + $dstXml = new DOMDocument(); + $dstXml->appendChild($dstXml->createElement('testsuites')); + + $this->suites = []; + foreach ($this->src as $src) { + $this->printTaskInfo("Processing {$src}"); + + $srcXml = new DOMDocument(); + if (!file_exists($src) || !is_readable($src)) { + $this->printTaskWarning('File did not exists or is not readable: ' . $src); + continue; + } + + $loaded = $srcXml->load($src); + if (!$loaded) { + $this->printTaskInfo("File {$src} can't be loaded as XML"); + continue; + } + + $suiteNodes = (new DOMXPath($srcXml))->query('//testsuites/testsuite'); + foreach ($suiteNodes as $suiteNode) { + /** @var $suiteNode DOMElement **/ + $suiteNode = $dstXml->importNode($suiteNode, true); + $this->loadSuites($suiteNode); + } + } + + $this->mergeSuites($dstXml); + + $dstXml->save($this->dst); + $this->printTaskInfo( + "File {$this->dst} saved. " . count($this->suites) . ' suites added' + ); + } + + protected function loadSuites(DOMElement $current): void + { + $this->suiteDuration[$current->getAttribute('name')][] = (float) $current->getAttribute('time'); + /** @var DOMNode $node */ + foreach ($current->childNodes as $node) { + if ($node instanceof DOMElement) { + if ($this->mergeRewrite) { + $this->suites[$current->getAttribute('name')][$node->getAttribute('class') . + '::' . $node->getAttribute('name')] = $node->cloneNode(true); + } else { + $this->suites[$current->getAttribute('name')][] = $node->cloneNode(true); + } + } + } + } + + protected function mergeSuites(DOMDocument $dstXml): void + { + foreach ($this->suites as $suiteName => $tests) { + $resultNode = $dstXml->createElement("testsuite"); + $resultNode->setAttribute('name', $suiteName); + $data = [ + 'tests' => count($tests), + 'assertions' => 0, + 'failures' => 0, + 'errors' => 0, + 'time' => 0, + ]; + + foreach ($tests as $test) { + $resultNode->appendChild($test); + + $data['assertions'] += (int)$test->getAttribute('assertions'); + if ($this->summarizeTime) { + $data['time'] = ((float)$test->getAttribute('time') + $data['time']); + } else { + if ($this->maxSuiteTime) { + $data['time'] = max($this->suiteDuration[$suiteName]); + } else { + $data['time'] = max($test->getAttribute('time'), $data['time']); + } + } + + $data['failures'] += $test->getElementsByTagName('failure')->length; + $data['errors'] += $test->getElementsByTagName('error')->length; + } + + foreach ($data as $key => $value) { + $resultNode->setAttribute($key, (string)$value); + } + + $dstXml->firstChild->appendChild($resultNode); + } + } +} diff --git a/src/SplitTestsByGroups.php b/src/SplitTestsByGroups.php deleted file mode 100644 index 76848a0..0000000 --- a/src/SplitTestsByGroups.php +++ /dev/null @@ -1,325 +0,0 @@ -task(SplitTestsByGroupsTask::class, $numGroups); - } - - /** - * @param $numGroups - * - * @return SplitTestFilesByGroupsTask - */ - protected function taskSplitTestFilesByGroups($numGroups) - { - return $this->task(SplitTestFilesByGroupsTask::class, $numGroups); - } -} - -abstract class TestsSplitter extends BaseTask -{ - protected $numGroups; - protected $projectRoot = '.'; - protected $testsFrom = 'tests'; - protected $saveTo = 'tests/_data/paracept_'; - protected $excludePath = 'vendor'; - - public function __construct($groups) - { - $this->numGroups = $groups; - } - - public function projectRoot($path) - { - $this->projectRoot = $path; - - return $this; - } - - public function testsFrom($path) - { - $this->testsFrom = $path; - - return $this; - } - - public function groupsTo($pattern) - { - $this->saveTo = $pattern; - - return $this; - } - - public function excludePath($path) - { - $this->excludePath = $path; - - return $this; - } - - /** - * @param $item - * @param array $items - * @param array $resolved - * @param array $unresolved - * - * @return array - */ - protected function resolveDependencies($item, array $items, array $resolved, array $unresolved) { - $unresolved[] = $item; - foreach ($items[$item] as $dep) { - if (!in_array($dep, $resolved)) { - if (!in_array($dep, $unresolved)) { - $unresolved[] = $dep; - list($resolved, $unresolved) = $this->resolveDependencies($dep, $items, $resolved, $unresolved); - } else { - throw new \RuntimeException("Circular dependency: $item -> $dep"); - } - } - } - // Add $item to $resolved if it's not already there - if (!in_array($item, $resolved)) { - $resolved[] = $item; - } - // Remove all occurrences of $item in $unresolved - while (($index = array_search($item, $unresolved)) !== false) { - unset($unresolved[$index]); - } - - return [$resolved, $unresolved]; - } - - /** - * Make sure that tests are in array are always with full path and name. - * - * @param array $testsListWithDependencies - * - * @return array - */ - protected function resolveDependenciesToFullNames(array $testsListWithDependencies){ - // make sure that dependencies are in array as full names - foreach ($testsListWithDependencies as $testName => $test) { - foreach ($test as $i => $dependency) { - - // sometimes it is written as class::method. - // for that reason we do trim in first case and replace from :: to one in second case - - - // just test name, that means that class name is the same, just different method name - if (strrpos($dependency, ':') === false) { - $testsListWithDependencies[$testName][$i] = trim(substr($testName,0,strrpos($testName, ':')), ':') . ':' . $dependency; - continue; - } - $dependency = str_replace('::', ':', $dependency); - // className:testName, that means we need to find proper test. - list($targetTestFileName, $targetTestMethodName) = explode(':', $dependency); - - // look for proper test in list of all tests. Test could be in different directory so we need to compare - // strings and if matched we just assign found test name - foreach (array_keys($testsListWithDependencies) as $arrayKey) { - if (strpos($arrayKey, $targetTestFileName . '.php:' . $targetTestMethodName) !== false) { - $testsListWithDependencies[$testName][$i] = $arrayKey; - continue 2; - } - } - throw new \RuntimeException('Dependency target test '.$dependency.' not found. Please make sure test exists and you are using full test name'); - } - } - return $testsListWithDependencies; - } -} - -/** - * Loads all tests into groups and saves them to groupfile according to pattern. - * - * ``` php - * taskSplitTestsByGroups(5) - * ->testsFrom('tests') - * ->groupsTo('tests/_log/paratest_') - * ->run(); - * ?> - * ``` - */ -class SplitTestsByGroupsTask extends TestsSplitter implements TaskInterface -{ - public function run() - { - if (!class_exists('\Codeception\Test\Loader')) { - throw new TaskException($this, 'This task requires Codeception to be loaded. Please require autoload.php of Codeception'); - } - $testLoader = new TestLoader(['path' => $this->testsFrom]); - $testLoader->loadTests($this->testsFrom); - $tests = $testLoader->getTests(); - - $this->printTaskInfo('Processing ' . count($tests) . ' tests'); - - $testsHaveAtLeastOneDependency = false; - - // test preloading (and fetching dependencies) requires dummy DI service. - $di = new \Codeception\Lib\Di(); - // gather test dependencies and deal with dataproviders - $testsListWithDependencies = []; - foreach ($tests as $test) { - if ($test instanceof DataProvider || $test instanceof DataProviderTestSuite) { - $test = current($test->tests()); - } - - // load dependencies for cest type. Unit tests dependencies are loaded automatically - if ($test instanceof \Codeception\Test\Cest) { - $test->getMetadata()->setServices(['di'=>$di]); - $test->preload(); - } - - if (method_exists($test, 'getMetadata')) { - $testsListWithDependencies[TestDescriptor::getTestFullName($test)] = $test->getMetadata() - ->getDependencies(); - if ($testsHaveAtLeastOneDependency === false and count($test->getMetadata()->getDependencies()) != 0) { - $testsHaveAtLeastOneDependency = true; - } - - // little hack to get dependencies from phpunit test cases that are private. - } elseif ($test instanceof \PHPUnit\Framework\TestCase) { - $ref = new \ReflectionObject($test); - do { - try{ - $property = $ref->getProperty('dependencies'); - $property->setAccessible(true); - $testsListWithDependencies[TestDescriptor::getTestFullName($test)] = $property->getValue($test); - - if ($testsHaveAtLeastOneDependency === false and count($property->getValue($test)) != 0) { - $testsHaveAtLeastOneDependency = true; - } - - } catch (\ReflectionException $e) { - // go up on level on inheritance chain. - } - } while($ref = $ref->getParentClass()); - - } else { - $testsListWithDependencies[TestDescriptor::getTestFullName($test)] = []; - } - } - - if ($testsHaveAtLeastOneDependency) { - $this->printTaskInfo('Resolving test dependencies'); - - // make sure that dependencies are in array as full names - try { - $testsListWithDependencies = $this->resolveDependenciesToFullNames($testsListWithDependencies); - } catch (\Exception $e) { - $this->printTaskError($e->getMessage()); - return false; - } - - // resolved and ordered list of dependencies - $orderedListOfTests = []; - // helper array - $unresolved = []; - - // Resolve dependencies for each test - foreach (array_keys($testsListWithDependencies) as $test) { - try { - list ($orderedListOfTests, $unresolved) = $this->resolveDependencies($test, $testsListWithDependencies, $orderedListOfTests, $unresolved); - } catch (\Exception $e) { - $this->printTaskError($e->getMessage()); - return false; - } - } - - // if we don't have any dependencies just use keys from original list. - } else { - $orderedListOfTests = array_keys($testsListWithDependencies); - } - - // for even split, calculate number of tests in each group - $numberOfElementsInGroup = floor(count($orderedListOfTests) / $this->numGroups); - - $i = 1; - $groups = []; - - // split tests into files. - foreach ($orderedListOfTests as $test) { - // move to the next group ONLY if number of tests is equal or greater desired number of tests in group - // AND current test has no dependencies AKA: we are in different branch than previous test - if (!empty($groups[$i]) AND count($groups[$i]) >= $numberOfElementsInGroup AND $i <= ($this->numGroups-1) AND empty($testsListWithDependencies[$test])) { - $i++; - } - - $groups[$i][] = $test; - } - - // saving group files - foreach ($groups as $i => $tests) { - $filename = $this->saveTo . $i; - $this->printTaskInfo("Writing $filename"); - file_put_contents($filename, implode("\n", $tests)); - } - } -} - -/** - * Finds all test files and splits them by group. - * Unlike `SplitTestsByGroupsTask` does not load them into memory and not requires Codeception to be loaded. - * - * ``` php - * taskSplitTestFilesByGroups(5) - * ->testsFrom('tests/unit/Acme') - * ->codeceptionRoot('projects/tested') - * ->groupsTo('tests/_log/paratest_') - * ->run(); - * ?> - * ``` - */ -class SplitTestFilesByGroupsTask extends TestsSplitter implements TaskInterface -{ - public function run() - { - $files = Finder::create() - ->followLinks() - ->name('*Cept.php') - ->name('*Cest.php') - ->name('*Test.php') - ->name('*.feature') - ->path($this->testsFrom) - ->in($this->projectRoot ? $this->projectRoot : getcwd()) - ->exclude($this->excludePath); - - $i = 0; - $groups = []; - - $this->printTaskInfo('Processing ' . count($files) . ' files'); - // splitting tests by groups - /** @var SplFileInfo $file */ - foreach ($files as $file) { - $groups[($i % $this->numGroups) + 1][] = $file->getRelativePathname(); - $i++; - } - - // saving group files - foreach ($groups as $i => $tests) { - $filename = $this->saveTo . $i; - $this->printTaskInfo("Writing $filename"); - file_put_contents($filename, implode("\n", $tests)); - } - } -} diff --git a/src/Splitter/FailedTestSplitterTask.php b/src/Splitter/FailedTestSplitterTask.php new file mode 100644 index 0000000..e1fe000 --- /dev/null +++ b/src/Splitter/FailedTestSplitterTask.php @@ -0,0 +1,66 @@ +reportPath; + } + + /** + * @inheritDoc + */ + public function run(): Result + { + $this->claimCodeceptionLoaded(); + $reportPath = $this->getReportPath(); + + if (!@file_exists($reportPath) || !is_file($reportPath)) { + throw new RuntimeException( + 'The report file did not exists or is not a regular file.' + ); + } + + $filenames = $this->splitToGroupFiles( + $this->filter( + explode( + PHP_EOL, + file_get_contents($reportPath) + ) + ) + ); + + $numFiles = count($filenames); + + return Result::success($this, "Split all tests into $numFiles group files", [ + 'files' => $filenames, + ]); + } + + public function setReportPath(string $reportFilePath): self + { + if (empty($reportFilePath)) { + throw new InvalidArgumentException('The reportPath could not be empty!'); + } + + $this->reportPath = $reportFilePath; + + return $this; + } +} diff --git a/src/Splitter/SplitTestsByTimeTask.php b/src/Splitter/SplitTestsByTimeTask.php new file mode 100644 index 0000000..f7b19af --- /dev/null +++ b/src/Splitter/SplitTestsByTimeTask.php @@ -0,0 +1,141 @@ +statFile = $path; + + return $this; + } + + public function run(): Result + { + $this->claimCodeceptionLoaded(); + + if (!is_file($this->statFile)) { + throw new TaskException($this, 'Can not find stat file - run tests with TimeReporter extension'); + } + + $testLoader = new Loader(['path' => $this->testsFrom]); + $testLoader->loadTests($this->testsFrom); + + $tests = $testLoader->getTests(); + $data = $this->readStatFileContent(); + + $testsWithTime = []; + $groups = []; + + $this->printTaskInfo('Processing ' . count($tests) . ' tests'); + foreach ($tests as $test) { + if ($test instanceof DataProviderTestSuite) { + $test = current($test->tests()); + } + + $testName = Descriptor::getTestFullName($test); + if (1 !== preg_match('#^/#', $testName)) { + $testName = '/' . $testName; + } + + $testName = substr(str_replace($this->getProjectDir(), '', $testName), 1); + $testsWithTime[$testName] = $data[$testName] ?? 0; + } + + arsort($testsWithTime); + + for ($i = 0; $i < $this->numGroups; ++$i) { + $groups[$i] = [ + 'tests' => [], + 'sum' => 0, + ]; + } + + foreach ($testsWithTime as $test => $time) { + $i = $this->getMinGroup($groups); + $groups[$i]['tests'][] = $test; + $groups[$i]['sum'] += $time; + } + + $filenames = []; + // saving group files + foreach ($groups as $i => ['tests' => $tests, 'sum' => $sum]) { + $filename = $this->saveTo . ($i + 1); + $this->printTaskInfo( + sprintf( + 'Writing %s: %d tests with %01.2f seconds', + $filename, + count($tests), + number_format($sum, 2) + ) + ); + file_put_contents($filename, implode("\n", $tests)); + $filenames[] = $filename; + } + + $numFiles = count($filenames); + + return Result::success($this, "Split all tests into $numFiles group files", [ + 'files' => $filenames, + ]); + } + + /** + * Find group num with min execute time + */ + protected function getMinGroup(array $groups): int + { + $min = 0; + $minSum = $groups[0]['sum']; + foreach ($groups as $i => $data) { + if ($data['sum'] < $minSum) { + $min = $i; + $minSum = $data['sum']; + } + } + + return $min; + } + + private function readStatFileContent(): array + { + if (false === ($data = file_get_contents($this->statFile))) { + throw new RuntimeException('Could not read content of stat file.'); + } + + try { + $data = json_decode($data, true, 512, JSON_THROW_ON_ERROR); + } catch (JsonException $exception) { + throw new RuntimeException( + "Could not decode content of stat file.", + 0, + $exception + ); + } + + return $data; + } + + public function getProjectDir(): string + { + return Configuration::projectDir(); + } +} diff --git a/src/Splitter/TestFileSplitterTask.php b/src/Splitter/TestFileSplitterTask.php new file mode 100644 index 0000000..c0b318b --- /dev/null +++ b/src/Splitter/TestFileSplitterTask.php @@ -0,0 +1,84 @@ +taskSplitTestFilesByGroups(5) + * ->testsFrom('tests/unit/Acme') + * ->codeceptionRoot('projects/tested') + * ->groupsTo('tests/_log/paratest_') + * ->run(); + * ``` + * + * @see \Tests\Codeception\Task\Splitter\TestFileSplitterTaskTest + */ +class TestFileSplitterTask extends TestsSplitter +{ + /** + * @var string[] + */ + private array $pattern = ['*Cept.php', '*Cest.php', '*Test.php', '*.feature']; + + public function run(): Result + { + $files = Finder::create() + ->followLinks() + ->name($this->getPattern()) + ->path($this->testsFrom) + ->in($this->projectRoot ?: getcwd()) + ->exclude($this->excludePath); + + + + $filenames = $this->splitToGroupFiles( + array_map( + static fn(SplFileInfo $fileInfo): string => $fileInfo->getRelativePathname(), + $this->filter(iterator_to_array($files->getIterator())) + ) + ); + + $numFiles = count($filenames); + + return Result::success($this, "Split all tests into $numFiles group files", [ + 'files' => $filenames, + ]); + } + + /** + * @param string[] $pattern + */ + public function setPattern(array $pattern): self + { + $this->pattern = $pattern; + + return $this; + } + + public function addPattern(string $pattern): self + { + $this->pattern[] = $pattern; + + return $this; + } + + /** + * @return string[] + */ + public function getPattern(): array + { + return $this->pattern; + } +} diff --git a/src/Splitter/TestsSplitter.php b/src/Splitter/TestsSplitter.php new file mode 100644 index 0000000..1029afc --- /dev/null +++ b/src/Splitter/TestsSplitter.php @@ -0,0 +1,257 @@ +numGroups = $groups; + $this->filter[] = new DefaultFilter(); + } + + public function addFilter(Filter $filter): TestsSplitter + { + if (!in_array($filter, $this->filter, true)) { + $this->filter[] = $filter; + } + + return $this; + } + + public function getProjectRoot(): string + { + return realpath($this->projectRoot); + } + + public function projectRoot(string $path): TestsSplitter + { + $this->projectRoot = $path; + + return $this; + } + + /** + * @param string[]|string $path - a single path or array of paths + * @return $this|TestsSplitter + */ + public function testsFrom($path): TestsSplitter + { + $this->testsFrom = $path; + + return $this; + } + + public function groupsTo(string $pattern): TestsSplitter + { + $this->saveTo = $pattern; + + return $this; + } + + public function excludePath(string $path): TestsSplitter + { + $this->excludePath = $path; + + return $this; + } + + /** + * @param mixed $item + */ + protected function resolveDependencies( + $item, + array $items, + array $resolved, + array $unresolved + ): array { + $unresolved[] = $item; + foreach ($items[$item] as $dep) { + if (!in_array($dep, $resolved, true)) { + if (!in_array($dep, $unresolved, true)) { + $unresolved[] = $dep; + [$resolved, $unresolved] = + $this->resolveDependencies($dep, $items, $resolved, $unresolved); + } else { + throw new RuntimeException(sprintf('Circular dependency: %s -> %s', $item, $dep)); + } + } + } + + // Add $item to $resolved if it's not already there + if (!in_array($item, $resolved, true)) { + $resolved[] = $item; + } + + // Remove all occurrences of $item in $unresolved + while (($index = array_search($item, $unresolved, true)) !== false) { + unset($unresolved[$index]); + } + + return [$resolved, $unresolved]; + } + + /** + * Make sure that tests are in array are always with full path and name. + */ + protected function resolveDependenciesToFullNames(array $testsListWithDependencies): array + { + // make sure that dependencies are in array as full names + foreach ($testsListWithDependencies as $testName => $test) { + foreach ($test as $i => $dependency) { + if (is_a($dependency, '\PHPUnit\Framework\ExecutionOrderDependency')) { + // getTarget gives the classname::method + $dependency = $dependency->getTarget(); + [$class, $method] = explode('::', $dependency); + $ref = new ReflectionClass($class); + $dependency = $ref->getFileName() . ':' . $method; + } + + // sometimes it is written as class::method. + // for that reason we do trim in first case and replace from :: to one in second case + // just test name, that means that class name is the same, just different method name + if (strrpos($dependency, ':') === false) { + $testsListWithDependencies[$testName][$i] = trim( + substr($testName, 0, strrpos($testName, ':')), + ':' + ) . ':' . $dependency; + continue; + } + + $dependency = str_replace('::', ':', $dependency); + // className:testName, that means we need to find proper test. + [$targetTestFileName, $targetTestMethodName] = explode(':', $dependency); + if (false === strrpos($targetTestFileName, '.php')) { + $targetTestFileName .= '.php'; + } + + // look for proper test in list of all tests. Test could be in different directory + // so we need to compare strings and if matched we just assign found test name + foreach (array_keys($testsListWithDependencies) as $arrayKey) { + if ( + str_contains( + $arrayKey, + $targetTestFileName . ':' . $targetTestMethodName + ) + ) { + $testsListWithDependencies[$testName][$i] = $arrayKey; + continue 2; + } + } + + throw new RuntimeException( + 'Dependency target test ' . $dependency . ' not found.' + . 'Please make sure test exists and you are using full test name' + ); + } + } + + return $testsListWithDependencies; + } + + /** + * Filter tests by the given filters, FIFO principal + */ + protected function filter(array $tests): array + { + foreach ($this->filter as $filter) { + $filter->setTests($tests); + $tests = $filter->filter(); + } + + return $tests; + } + + /** + * Claims that the Codeception is loaded for Tasks which need it + * + * @throws TaskException + */ + protected function claimCodeceptionLoaded(): void + { + if (!$this->doCodeceptLoaderExists()) { + throw new TaskException( + $this, + 'This task requires Codeception to be loaded. Please require autoload.php of Codeception' + ); + } + + try { + // load Codeception config to set base directory + \Codeception\Configuration::config(); + } catch (\Exception $e) { + $this->output()->writeln('Codeception config was not loaded, please load it manually'); + } + } + + protected function doCodeceptLoaderExists(): bool + { + return class_exists(\Codeception\Test\Loader::class); + } + + /** + * Splitting array of files to the group files + * + * @param string[] $files - the relative path of the Testfile with or without test function + * @example $this->splitToGroupFiles(['tests/FooCest.php', 'tests/BarTest.php:testBarReturn']); + */ + protected function splitToGroupFiles(array $files): array + { + $i = 0; + $groups = []; + + if (!Configuration::projectDir()) { + $this->output()->writeln("Codeception config was not loaded, paths to tests may not be set correctly."); + $this->output()->writeln("Execute \Codeception\Configuration::config() before this task"); + } + + + $this->printTaskInfo('Processing ' . count($files) . ' files'); + + // splitting tests by groups + /** @var string $file */ + foreach ($files as $file) { + $groups[($i % $this->numGroups) + 1][] = $file; + ++$i; + } + + $filenames = []; + // saving group files + foreach ($groups as $i => $tests) { + $filename = $this->saveTo . $i; + $this->printTaskInfo("Writing {$filename}"); + file_put_contents($filename, implode("\n", $tests)); + $filenames[] = $filename; + } + return $filenames; + } +} diff --git a/src/Splitter/TestsSplitterTask.php b/src/Splitter/TestsSplitterTask.php new file mode 100644 index 0000000..23b27ea --- /dev/null +++ b/src/Splitter/TestsSplitterTask.php @@ -0,0 +1,180 @@ +taskSplitTestsByGroups(5) + * ->testsFrom('tests') + * ->groupsTo('tests/_log/paratest_') + * ->addFilter(new Filter1()) + * ->addFilter(new Filter2()) + * ->run(); + * ``` + * + * @see \Tests\Codeception\Task\Splitter\TestsSplitterTaskTest + */ +class TestsSplitterTask extends TestsSplitter +{ + /** + * @throws \Robo\Exception\TaskException + */ + public function run(): Result + { + $this->claimCodeceptionLoaded(); + $tests = $this->filter($this->loadTests()); + $numTests = count($tests); + $this->printTaskInfo("Processing $numTests tests"); + + $testsHaveAtLeastOneDependency = false; + + // test preloading (and fetching dependencies) requires dummy DI service. + $di = new Di(); + // gather test dependencies and deal with dataproviders + $testsListWithDependencies = []; + foreach ($tests as $test) { + if ($test instanceof DataProviderTestSuite) { + $test = current($test->tests()); + } + + if ($test instanceof Cest) { + $test->getMetadata()->setServices(['di' => $di]); + $test->preload(); + } + + if (method_exists($test, 'getMetadata')) { + $dependencies = $test->getMetadata()->getDependencies(); + if (count($dependencies) !== 0) { + $testsHaveAtLeastOneDependency = true; + $testsListWithDependencies[TestDescriptor::getTestFullName($test)] = $dependencies; + } else { + $testsListWithDependencies[TestDescriptor::getTestFullName($test)] = []; + } + // little hack to get dependencies from phpunit test cases that are private. + } elseif ($test instanceof TestCase) { + $ref = new ReflectionObject($test); + do { + try { + $property = $ref->getProperty('dependencies'); + $property->setAccessible(true); + $dependencies = $property->getValue($test); + if (count($dependencies) !== 0) { + $testsHaveAtLeastOneDependency = true; + $testsListWithDependencies[TestDescriptor::getTestFullName($test)] = $dependencies; + } else { + $testsListWithDependencies[TestDescriptor::getTestFullName($test)] = []; + } + } catch (ReflectionException $exception) { + // go up on level on inheritance chain. + } + } while ($ref = $ref->getParentClass()); + } else { + $testsListWithDependencies[TestDescriptor::getTestFullName($test)] = []; + } + } + + if ($testsHaveAtLeastOneDependency) { + $this->printTaskInfo('Resolving test dependencies'); + // make sure that dependencies are in array as full names + try { + $testsListWithDependencies = $this->resolveDependenciesToFullNames( + $testsListWithDependencies + ); + } catch (Exception $e) { + $this->printTaskError($e->getMessage()); + return Result::error($this, $e->getMessage(), ['exception' => $e]); + } + + // resolved and ordered list of dependencies + $orderedListOfTests = []; + // helper array + $unresolved = []; + + // Resolve dependencies for each test + foreach (array_keys($testsListWithDependencies) as $test) { + try { + [$orderedListOfTests, $unresolved] = $this->resolveDependencies( + $test, + $testsListWithDependencies, + $orderedListOfTests, + $unresolved + ); + } catch (Exception $e) { + $this->printTaskError($e->getMessage()); + return Result::error($this, $e->getMessage(), ['exception' => $e]); + } + } + + // if we don't have any dependencies just use keys from original list. + } else { + $orderedListOfTests = array_keys($testsListWithDependencies); + } + + // for even split, calculate number of tests in each group + $numberOfElementsInGroup = round(count($orderedListOfTests) / $this->numGroups); + $i = 1; + $groups = []; + + // split tests into files. + foreach ($orderedListOfTests as $test) { + // move to the next group ONLY if number of tests is equal or greater desired number of tests in group + // AND current test has no dependencies AKA: we are in different branch than previous test + if ( + !empty($groups[$i]) + && empty($testsListWithDependencies[$test]) + && $i <= ($this->numGroups - 1) + && count($groups[$i]) >= $numberOfElementsInGroup + ) { + ++$i; + } + + $groups[$i][] = $test; + } + + $filenames = []; + // saving group files + foreach ($groups as $i => $groupTests) { + $filename = $this->saveTo . $i; + $this->printTaskInfo("Writing $filename"); + file_put_contents($filename, implode("\n", $groupTests)); + $filenames[] = $filename; + } + $numFiles = count($filenames); + + return Result::success($this, "Split $numTests into $numFiles group files", [ + 'groups' => $groups, + 'tests' => $tests, + 'files' => $filenames, + ]); + } + + protected function getTestLoader(): TestLoader + { + return new TestLoader(['path' => $this->testsFrom]); + } + + protected function loadTests(): array + { + $testLoader = $this->getTestLoader(); + $testLoader->loadTests($this->testsFrom); + + return $testLoader->getTests(); + } +} diff --git a/src/Splitter/TestsSplitterTrait.php b/src/Splitter/TestsSplitterTrait.php new file mode 100644 index 0000000..184466f --- /dev/null +++ b/src/Splitter/TestsSplitterTrait.php @@ -0,0 +1,42 @@ +task(TestsSplitterTask::class, $numGroups); + } + + /** + * @return TestFileSplitterTask|CollectionBuilder + */ + protected function taskSplitTestFilesByGroups(int $numGroups) + { + return $this->task(TestFileSplitterTask::class, $numGroups); + } + + /** + * @return TestFileSplitterTask|CollectionBuilder + */ + protected function taskSplitTestsByTime(int $numGroups) + { + return $this->task(SplitTestsByTimeTask::class, $numGroups); + } + + /** + * @return TestFileSplitterTask|CollectionBuilder + */ + protected function taskSplitFailedTests(int $numGroups) + { + return $this->task(FailedTestSplitterTask::class, $numGroups); + } +} diff --git a/tests/Extension/FailedTestsReporterTest.php b/tests/Extension/FailedTestsReporterTest.php new file mode 100644 index 0000000..8daab49 --- /dev/null +++ b/tests/Extension/FailedTestsReporterTest.php @@ -0,0 +1,106 @@ + 'tests/acceptance/bar/baz.php:testA',], + ['testName' => 'tests/acceptance/bar/baz.php:testB',], + ['testName' => 'tests/acceptance/bar/baz.php:testC',], + ['testName' => 'tests/acceptance/bar/baz.php:testD',], + ['testName' => 'tests/acceptance/bar/baz.php:testE',], + ['testName' => 'tests/acceptance/bar/baz.php:testF',], + ['testName' => 'tests/acceptance/bar/baz.php:testG',], + ['testName' => 'tests/acceptance/bar/baz.php:testH',], + ]; + + /** + * @covers ::endRun + */ + public function testEndRun(): void + { + $reporter = $this->getMockBuilder(FailedTestsReporter::class) + ->disableOriginalConstructor() + ->onlyMethods(['getTestName', 'getLogDir']) + ->getMock(); + + $reporter->method('getLogDir')->willReturn(TEST_PATH . '/result/'); + + // prepare Mocks for Test + $testEvents = []; + foreach ($this->failedTests as $test) { + $eventMock = $this->getMockBuilder(FailEvent::class) + ->disableOriginalConstructor() + ->getMock(); + + $testEvents[] = [ + 'mock' => $eventMock, + 'testName' => $test['testName'] + ]; + } + + // get test name by the TestEventMock + $reporter + ->method('getTestName') + ->withConsecutive( + ...array_map( + static function (FailEvent $event): array { + return [$event]; + }, + array_column($testEvents, 'mock') + ) + ) + ->willReturnOnConsecutiveCalls(...array_column($testEvents, 'testName')); + + foreach ($testEvents as $event) { + $reporter->afterFail($event['mock']); + } + + $reporter->endRun(); + $files = Finder::create() + ->followLinks() + ->files() + ->in(TEST_PATH) + ->path('result') + ->name('/^failedTests_\w+\.\w+\.txt$/'); + + $iterator = $files->getIterator(); + $this->assertCount(1, $iterator); + $iterator->rewind(); + /** @var SplFileInfo $file */ + $file = $iterator->current(); + $this->assertTrue($file->isFile()); + $content = explode(PHP_EOL, file_get_contents($file->getPathname())); + $this->assertCount(8, $content); + } + + protected function tearDown(): void + { + parent::tearDown(); // TODO: Change the autogenerated stub + $files = Finder::create() + ->followLinks() + ->files() + ->in(TEST_PATH) + ->path('result') + ->name('/^failedTests_\w+\.\w+\.txt$/'); + + foreach ($files->getIterator() as $file) { + unlink($file->getPathname()); + } + } +} diff --git a/tests/Extension/TimeReporterTest.php b/tests/Extension/TimeReporterTest.php new file mode 100644 index 0000000..7a30f73 --- /dev/null +++ b/tests/Extension/TimeReporterTest.php @@ -0,0 +1,106 @@ + 'tests/acceptance/bar/baz.php:testA', 'time' => 10.0,], + ['testName' => 'tests/acceptance/bar/baz.php:testA', 'time' => 50.0,], // rerun + ['testName' => 'tests/acceptance/bar/baz.php:testB', 'time' => 100.0,], + ['testName' => 'tests/acceptance/bar/baz.php:testC', 'time' => 50.0,], + ['testName' => 'tests/acceptance/bar/baz.php:testD', 'time' => 33.0,], + ['testName' => 'tests/acceptance/bar/baz.php:testD', 'time' => 50.0,], // rerun + ['testName' => 'tests/acceptance/bar/baz.php:testE', 'time' => 66.0,], + ['testName' => 'tests/acceptance/bar/baz.php:testF', 'time' => 90.0,], + ['testName' => 'tests/acceptance/bar/baz.php:testG', 'time' => 100.0,], + ['testName' => 'tests/acceptance/bar/baz.php:testG', 'time' => 13.0,], //rerun + ['testName' => 'tests/acceptance/bar/baz.php:testH', 'time' => 50.0,], + ]; + + $expected = [ + 'tests/acceptance/bar/baz.php:testA' => 60, + 'tests/acceptance/bar/baz.php:testB' => 100, + 'tests/acceptance/bar/baz.php:testC' => 50, + 'tests/acceptance/bar/baz.php:testD' => 83, + 'tests/acceptance/bar/baz.php:testE' => 66, + 'tests/acceptance/bar/baz.php:testF' => 90, + 'tests/acceptance/bar/baz.php:testG' => 113, + 'tests/acceptance/bar/baz.php:testH' => 50, + ]; + + $reporter = $this->getMockBuilder(TimeReporter::class) + ->disableOriginalConstructor() + ->onlyMethods(['getTestName', 'getLogDir']) + ->getMock(); + $reporter->method('getLogDir')->willReturn(TEST_PATH . '/result/'); + + // prepare Mocks for Test + $testEvents = []; + foreach ($eventTests as $test) { + $eventMock = $this->getMockBuilder(TestEvent::class) + ->disableOriginalConstructor() + ->onlyMethods(['getTime']) + ->getMock(); + + $eventMock->method('getTime')->willReturn($test['time']); + $testEvents[] = [ + 'mock' => $eventMock, + 'testName' => $test['testName'] + ]; + } + + // get test name by the TestEventMock + $reporter + ->method('getTestName') + ->withConsecutive( + ...array_map( + static function (TestEvent $event): array { + return [$event]; + }, + array_column($testEvents, 'mock') + ) + ) + ->willReturnOnConsecutiveCalls(...array_column($testEvents, 'testName')); + + // fill timeList with the mocked Events + foreach ($testEvents as $testEvent) { + $reporter->after($testEvent['mock']); + } + + $reporter->endRun(); + $reportFile = TEST_PATH . '/result/timeReport.json'; + $this->assertFileExists($reportFile); + + $lines = json_decode(file_get_contents($reportFile), true); + $this->assertCount(count($expected), $lines); + foreach ($expected as $test => $time) { + $this->assertContains($test, array_keys($lines), $test . ' does not exists in file.'); + $this->assertSame($time, $lines[$test], 'Calculated time does not match the expected.'); + } + } + + protected function tearDown(): void + { + parent::tearDown(); // TODO: Change the autogenerated stub + unlink(TEST_PATH . '/result/timeReport.json'); + } +} diff --git a/tests/Filter/GroupFilterTest.php b/tests/Filter/GroupFilterTest.php new file mode 100644 index 0000000..7ee7e10 --- /dev/null +++ b/tests/Filter/GroupFilterTest.php @@ -0,0 +1,174 @@ +groupExcluded($group); + } + + $this->assertSame($expected, $task->getExcludedGroups()); + } + + /** + * @covers ::getIncludedGroups + * @covers ::groupIncluded + */ + public function testGetIncludedGroups(): void + { + $groupsToAdd = [ + 'foo', + 'bar', + 'baz', + 'foo', + 'Foo', + 'baZ', + ]; + + $expected = [ + 'foo', + 'bar', + 'baz', + 'Foo', + 'baZ', + ]; + + $task = new GroupFilter(); + foreach ($groupsToAdd as $group) { + $task->groupIncluded($group); + } + + $this->assertSame($expected, $task->getIncludedGroups()); + } + + /** + * @covers ::groupIncluded + * @covers ::groupExcluded + */ + public function testDoNotAddGroupToIncludedAndExcluded(): void + { + $task = new GroupFilter(); + $task->groupIncluded('foo'); + $this->expectException(InvalidArgumentException::class); + $this->expectErrorMessageMatches( + '/^You can mark group "\w+" only as included OR excluded.$/' + ); + $task->groupExcluded('foo'); + } + + /** + * @covers ::groupIncluded + * @covers ::groupExcluded + */ + public function testDoNotAddGroupToExcludedAndIncluded(): void + { + $task = (new GroupFilter())->groupExcluded('bar'); + $this->expectException(InvalidArgumentException::class); + $this->expectErrorMessageMatches( + '/^You can mark group "\w+" only as included OR excluded.$/' + ); + $task->groupIncluded('bar'); + } + + /** + * @covers ::filter + */ + public function testFilterWithCestFiles(): void + { + $loader = new TestLoader(['path' => TEST_PATH . '/fixtures/Cests']); + $loader->loadTests(TEST_PATH . '/fixtures/Cests'); + + $tests = $loader->getTests(); + $this->assertCount(3, $tests); + // Filter with no groups should return all tests + $filter = new GroupFilter(); + $filter->setTests($tests); + + $filtered = $filter->filter(); + $this->assertCount(3, $filtered); + // Filter with group foo should return 2 Tests + $filter->groupIncluded('foo'); + $filtered = $filter->filter(); + $this->assertCount(2, $filtered); + // Filter with group foo from before and new excluded group no should return 1 test + $filter->groupExcluded('no'); + $filtered = $filter->filter(); + $this->assertCount(1, $filtered); + $filter->reset(); + $filtered = $filter->filter(); + $this->assertCount(3, $filtered); + foreach ($filtered as $test) { + $this->assertInstanceOf(SelfDescribing::class, $test); + } + } + + public function testFilterWithUnitTests(): void + { + $loader = new TestLoader(['path' => TEST_PATH . '/fixtures/Unit']); + $loader->loadTests(TEST_PATH . '/fixtures/Unit'); + + $tests = $loader->getTests(); + $this->assertCount(4, $tests); + // Filter with no groups should return all tests + $filter = new GroupFilter(); + $filter->setTests($tests); + + $filtered = $filter->filter(); + $this->assertCount(4, $filtered); + // Filter with group foo should return 2 Tests + $filter->groupIncluded('foo'); + $filtered = $filter->filter(); + $this->assertCount(3, $filtered); + // Filter with group foo from before and new excluded group no should return 1 test + $filter->groupExcluded('no'); + $filtered = $filter->filter(); + $this->assertCount(1, $filtered); + $filter->reset(); + $filtered = $filter->filter(); + $this->assertCount(4, $filtered); + foreach ($filtered as $test) { + $this->assertInstanceOf(SelfDescribing::class, $test); + } + } +} diff --git a/tests/MergeJUnitReportsTest.php b/tests/MergeJUnitReportsTest.php deleted file mode 100644 index 8094f69..0000000 --- a/tests/MergeJUnitReportsTest.php +++ /dev/null @@ -1,48 +0,0 @@ -setLogger(new \Consolidation\Log\Logger(new \Symfony\Component\Console\Output\NullOutput())); - $task->from('tests/fixtures/result1.xml') - ->from('tests/fixtures/result2.xml') - ->into('tests/result/merged.xml') - ->run(); - - $this->assertFileExists('tests/result/merged.xml'); - $xml = file_get_contents('tests/result/merged.xml'); - $this->assertContains('assertContains('assertContains('assertContains('setLogger(new \Consolidation\Log\Logger(new \Symfony\Component\Console\Output\NullOutput())); - $task->from('tests/fixtures/result1.xml') - ->from('tests/fixtures/result2.xml') - ->into('tests/result/merged.xml') - ->mergeRewrite() - ->run(); - - $task->mergeRewrite()->run(); - $this->assertFileExists('tests/result/merged.xml'); - $xml = file_get_contents('tests/result/merged.xml'); - $this->assertContains('assertContains('assertContains('assertContains(' '/foo_\w+\.txt/', + 'bar' => '/bar_\w+\.txt/', + 'baz' => '/baz_\w+\.txt/', + ]; + + private static array $testContent = [ + 'tests/acceptance/%s/baz.php:testA', + 'tests/acceptance/%s/baz.php:testB', + 'tests/acceptance/%s/baz.php:testC', + 'tests/acceptance/%s/baz.php:testD', + 'tests/acceptance/%s/baz.php:testE', + 'tests/acceptance/%s/baz.php:testF', + 'tests/acceptance/%s/baz.php:testG', + 'tests/acceptance/%s/baz.php:testH', + ]; + + private static array $testFiles = []; + + /** + * Prepare the test files and directories + */ + public static function setUpBeforeClass(): void + { + parent::setUpBeforeClass(); + $tmpDir = sys_get_temp_dir(); + foreach (array_keys(self::$tmpDirsPattern) as $dir) { + $tempDir = $tmpDir . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR; + if (!is_dir($tempDir)) { + mkdir($tempDir); + } + + $i = 1; + while ($i <= self::TEST_FILES_PER_DIR) { + $tempFile = $tempDir . $dir . '_unit' . $i++ . '.txt'; + file_put_contents( + $tempFile, + implode( + PHP_EOL, + array_map( + static fn(string $filename): string => sprintf($filename, $dir), + self::$testContent + ) + ) + ); + self::$testFiles[] = $tempFile; + } + } + } + + /** + * @covers ::run + */ + public function testRunSingleFile(): void + { + $tmpDir = sys_get_temp_dir() . '/foz/'; + $testFile = $tmpDir . 'foz_123456.txt'; + + if (!is_dir($tmpDir)) { + mkdir($tmpDir); + } + + $this->putContents($testFile); + $task = new FailedTestsMergerTask(); + $task->setLogger(new Logger(new NullOutput())); + $task + ->from($testFile) + ->into(self::EXPECTED_TEST_MERGED_FILE) + ->run(); + + $this->assertFileExists(self::EXPECTED_TEST_MERGED_FILE); + $content = explode(PHP_EOL, file_get_contents(self::EXPECTED_TEST_MERGED_FILE)); + $this->assertCount( + count(self::$testContent), + $content + ); + } + + public function testRunWithPathAndFilePatterns(): void + { + $task = new FailedTestsMergerTask(); + $task->setLogger(new Logger(new NullOutput())); + + foreach (self::$tmpDirsPattern as $path => $pattern) { + $task->fromPathWithPattern( + sys_get_temp_dir() . DIRECTORY_SEPARATOR . $path, + $pattern + ); + } + + $task + ->into(self::EXPECTED_TEST_MERGED_FILE) + ->run(); + + $this->assertFileExists(self::EXPECTED_TEST_MERGED_FILE); + $this->assertCount( + (count(self::$testContent) * count(self::$testFiles)), + explode(PHP_EOL, file_get_contents(self::EXPECTED_TEST_MERGED_FILE)) + ); + } + + public function testRunWithFileAndArrayAndPathWithPatterns(): void + { + $tmpDir = sys_get_temp_dir() . '/foz/'; + $testFile = $tmpDir . 'foz_123456.txt'; + + if (!is_dir($tmpDir)) { + mkdir($tmpDir); + } + + $this->putContents($testFile); + + $fileData = []; + $i = 0; + while ($i < self::TEST_FILES_PER_DIR) { + $testFile = $tmpDir . 'foz_' . (123456 + ++$i) . '.txt'; + $this->putContents($testFile); + $fileData[] = $testFile; + } + + $task = new FailedTestsMergerTask(); + $task->setLogger(new Logger(new NullOutput())); + $task->from($testFile); + $task->from($fileData); + foreach (self::$tmpDirsPattern as $path => $pattern) { + $task->fromPathWithPattern( + sys_get_temp_dir() . DIRECTORY_SEPARATOR . $path, + $pattern + ); + } + + $task + ->into(self::EXPECTED_TEST_MERGED_FILE) + ->run(); + + $this->assertFileExists(self::EXPECTED_TEST_MERGED_FILE); + $this->assertCount( + ( + count(self::$testContent) * ( + count(self::$testFiles) + + count($fileData) + + count([$testFile]) + ) + ), + explode(PHP_EOL, file_get_contents(self::EXPECTED_TEST_MERGED_FILE)) + ); + } + + protected function tearDown(): void + { + parent::tearDown(); // TODO: Change the autogenerated stub + unlink(self::EXPECTED_TEST_MERGED_FILE); + } + + public static function tearDownAfterClass(): void + { + parent::tearDownAfterClass(); // TODO: Change the autogenerated stub + foreach (self::$testFiles as $file) { + unlink($file); + } + } + + protected function putContents(string $testFile): void + { + file_put_contents( + $testFile, + implode( + PHP_EOL, + array_map( + static fn(string $filename): string => sprintf($filename, 'foz'), + self::$testContent + ) + ) + ); + } +} diff --git a/tests/Merger/HtmlReportMergerTest.php b/tests/Merger/HtmlReportMergerTest.php new file mode 100644 index 0000000..f5be1f5 --- /dev/null +++ b/tests/Merger/HtmlReportMergerTest.php @@ -0,0 +1,217 @@ +setLogger(new Logger(new NullOutput())); + + $resultReport = TEST_PATH . '/result/report.html'; + $task + ->from( + [ + $reportPath . 'report_0.html', // this file did not exists and it should not fail + $reportPath . 'report_1.html', + $reportPath . 'report_2.html', + $reportPath . 'report_3.html', + ] + ) + ->into($resultReport) + ->run(); + + $this->assertFileExists($resultReport); + + //read first source file as main + $dstHTML = new DOMDocument(); + $dstHTML->loadHTMLFile($resultReport, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + /** @var DOMNodeList $values */ + $values = (new DOMXPath($dstHTML)) + ->query("//*[contains(@class,'scenarioSuccessValue')]"); + + $this->assertCount(1, $values); + $this->assertSame($expectedSuccess, (int)$values[0]->nodeValue); + + $values = (new DOMXPath($dstHTML)) + ->query("//h1[text() = 'Codeception Results ']"); + preg_match( + '#^Codeception Results .* \((?\d+\.\d+)s\)$#', + $values[0]->nodeValue, + $matches + ); + + $this->assertSame($expectedTimeInSeconds, (float)$matches['timesum']); + } + + /** + * @covers ::run + */ + public function testRunWithCodeception5Reports(): void + { + $expectedTimeInSeconds = '03:34.98'; + $expectedSuccess= 3; + + $reportPath = TEST_PATH . '/fixtures/reports/html/'; + $task = new HtmlReportMerger(); + $task->setLogger(new Logger(new NullOutput())); + + $resultReport = TEST_PATH . '/result/report_codeception5.html'; + $task + ->from( + [ + $reportPath . 'report_0_codeception5.html', // this file did not exists and it should not fail + $reportPath . 'report_1_codeception5.html', + $reportPath . 'report_2_codeception5.html', + $reportPath . 'report_3_codeception5.html', + ] + ) + ->into($resultReport) + ->run(); + + $this->assertFileExists($resultReport); + + //read first source file as main + $dstHTML = new DOMDocument(); + $dstHTML->loadHTMLFile($resultReport, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + /** @var DOMNodeList $values */ + $values = (new DOMXPath($dstHTML)) + ->query("//*[contains(@class,'scenarioSuccessValue')]"); + + $this->assertCount(1, $values); + $this->assertSame($expectedSuccess, (int)$values[0]->nodeValue); + + $values = (new DOMXPath($dstHTML)) + ->query("//h1[text() = 'Codeception Results ']"); + preg_match( + '#^Codeception Results .* \((?(([0-1]?\d|2[0-3])(?::([0-5]?\d))?(?::([0-5]?\d))\.\d+))\)$#', + $values[0]->nodeValue, + $matches + ); + + $this->assertSame($expectedTimeInSeconds, (string)$matches['timesum']); + } + + /** + * @covers ::run + */ + public function testRunMaxTimeReports(): void + { + $expectedTime = '129.25'; + $expectedSuccess= 3; + + $reportPath = TEST_PATH . '/fixtures/reports/html/'; + $task = new HtmlReportMerger(); + $task->setLogger(new Logger(new NullOutput())); + + $resultReport = TEST_PATH . '/result/report_max_time.html'; + $task->maxTime(); + $task + ->from( + [ + $reportPath . 'report_0.html', // this file did not exists and it should not fail + $reportPath . 'report_1.html', + $reportPath . 'report_2.html', + $reportPath . 'report_3.html', + ] + ) + ->into($resultReport) + ->run(); + + $this->assertFileExists($resultReport); + + //read first source file as main + $dstHTML = new DOMDocument(); + $dstHTML->loadHTMLFile($resultReport, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + /** @var DOMNodeList $values */ + $values = (new DOMXPath($dstHTML)) + ->query("//*[contains(@class,'scenarioSuccessValue')]"); + + $this->assertCount(1, $values); + $this->assertSame($expectedSuccess, (int)$values[0]->nodeValue); + + $values = (new DOMXPath($dstHTML)) + ->query("//h1[text() = 'Codeception Results ']"); + preg_match( + '#^Codeception Results .* \((?\d+\.\d+)s\)$#', + $values[0]->nodeValue, + $matches + ); + $executionTime[] = (string)$matches['timesum']; + usort($executionTime, function ($a, $b) { + return strcmp($a, $b); + }); + $this->assertSame($expectedTime, max($executionTime)); + } + + /** + * @covers ::run + */ + public function testRunMaxTimeWithCodeception5Reports(): void + { + $expectedTime = '02:09.25'; + $expectedSuccess= 3; + + $reportPath = TEST_PATH . '/fixtures/reports/html/'; + $task = new HtmlReportMerger(); + $task->setLogger(new Logger(new NullOutput())); + + $resultReport = TEST_PATH . '/result/report_codeception5_max_time.html'; + $task->maxTime(); + $task + ->from( + [ + $reportPath . 'report_0_codeception5.html', // this file did not exists and it should not fail + $reportPath . 'report_1_codeception5.html', + $reportPath . 'report_2_codeception5.html', + $reportPath . 'report_3_codeception5.html', + ] + ) + ->into($resultReport) + ->run(); + + $this->assertFileExists($resultReport); + + //read first source file as main + $dstHTML = new DOMDocument(); + $dstHTML->loadHTMLFile($resultReport, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + /** @var DOMNodeList $values */ + $values = (new DOMXPath($dstHTML)) + ->query("//*[contains(@class,'scenarioSuccessValue')]"); + + $this->assertCount(1, $values); + $this->assertSame($expectedSuccess, (int)$values[0]->nodeValue); + + $values = (new DOMXPath($dstHTML)) + ->query("//h1[text() = 'Codeception Results ']"); + preg_match( + '#^Codeception Results .* \((?(([0-1]?\d|2[0-3])(?::([0-5]?\d))?(?::([0-5]?\d))\.\d+))\)$#', + $values[0]->nodeValue, + $matches + ); + $executionTime[] = (string)$matches['timesum']; + usort($executionTime, function ($a, $b) { + return strcmp($a, $b); + }); + $this->assertSame($expectedTime, max($executionTime)); + } +} diff --git a/tests/Merger/XmlReportMergerTaskTest.php b/tests/Merger/XmlReportMergerTaskTest.php new file mode 100644 index 0000000..22416bc --- /dev/null +++ b/tests/Merger/XmlReportMergerTaskTest.php @@ -0,0 +1,94 @@ +setLogger(new Logger(new NullOutput())); + $task->from(TEST_PATH . '/fixtures/result1.xml') + ->from(TEST_PATH . '/fixtures/result2.xml') + // This report did not exists and we should not throw an exception + ->from(TEST_PATH . '/fixtures/result3.xml') + ->into(TEST_PATH . '/result/merged.xml') + ->run(); + + $this->assertFileExists(TEST_PATH . '/result/merged.xml'); + $xml = file_get_contents(TEST_PATH . '/result/merged.xml'); + $this->assertStringContainsString( + '', + $xml + ); + $this->assertStringContainsString( + '', + $xml + ); + $this->assertStringContainsString( + 'assertStringContainsString( + 'setLogger(new Logger(new NullOutput())); + $task->maxSuiteTime(); + $task->from(TEST_PATH . '/fixtures/result1.xml') + ->from(TEST_PATH . '/fixtures/result2.xml') + ->into(TEST_PATH . '/result/merged.xml') + ->run(); + + $this->assertFileExists(TEST_PATH . '/result/merged.xml'); + $xml = file_get_contents(TEST_PATH . '/result/merged.xml'); + $this->assertStringContainsString( + '', + $xml + ); + $this->assertStringContainsString( + '', + $xml + ); + } + + public function testMergeRewriteReports(): void + { + $task = new XmlReportMergerTask(); + $task->setLogger(new Logger(new NullOutput())); + $task->from(TEST_PATH . '/fixtures/result1.xml') + ->from(TEST_PATH . '/fixtures/result2.xml') + ->into(TEST_PATH . '/result/merged.xml') + ->run(); + $this->assertFileExists(TEST_PATH . '/result/merged.xml'); + + $task->mergeRewrite()->run(); + $this->assertFileExists(TEST_PATH . '/result/merged.xml'); + $xml = file_get_contents(TEST_PATH . '/result/merged.xml'); + $this->assertStringContainsString('assertStringContainsString('assertStringContainsString('assertStringContainsString('setLogger(new \Consolidation\Log\Logger(new \Symfony\Component\Console\Output\NullOutput())); - $task->testsFrom('vendor/codeception/base/tests/unit/Codeception/Command') - ->groupsTo('tests/result/group_') - ->run(); - - for ($i = 1; $i <= 10; $i++) { - $this->assertFileExists("tests/result/group_$i"); - } - $this->assertFileNotExists("tests/result/group_11"); - } - - public function testSplitFilesByGroups() - { - $task = new Codeception\Task\SplitTestsByGroupsTask(5); - $task->setLogger(new \Consolidation\Log\Logger(new \Symfony\Component\Console\Output\NullOutput())); - $task->testsFrom('vendor/codeception/base/tests/unit/Codeception/Command') - ->projectRoot('vendor/codeception/base/') - ->groupsTo('tests/result/group_') - ->run(); - - for ($i = 1; $i <= 5; $i++) { - $this->assertFileExists("tests/result/group_$i"); - } - } - - /** - * Test Circular dependency protection - * - * @throws \Robo\Exception\TaskException - */ - public function testCircularDependencyDetectionAndHandling(){ - $task = new Codeception\Task\SplitTestsByGroupsTask(5); - $output = new \Symfony\Component\Console\Output\BufferedOutput(); - $task->setLogger(new \Consolidation\Log\Logger($output)); - $task->testsFrom('tests/fixtures/DependencyResolutionExampleTests2') - ->projectRoot('vendor/codeception/base/') - ->groupsTo('tests/result/group_') - ->run(); - - $d = $output->fetch(); - - self::assertContains('Circular dependency:', $d); - - // make sure that no files were generated. - $this->assertEmpty(glob("tests/result/group_*")); - } - - /** - * Test dependency resolving - * - * @throws \Robo\Exception\TaskException - */ - public function testDependencyResolving(){ - - $task = new Codeception\Task\SplitTestsByGroupsTask(2); - $output = new \Symfony\Component\Console\Output\BufferedOutput(); - $task->setLogger(new \Consolidation\Log\Logger($output)); - - $task->testsFrom('tests/fixtures/DependencyResolutionExampleTests') - ->projectRoot('vendor/codeception/base/') - ->groupsTo('tests/result/group_') - ->run(); - for ($i = 1; $i <= 2; $i++) { - $this->assertFileExists("tests/result/group_$i"); - } - - // because path might be different on every system we need only last part of the path. - $firstFile = file_get_contents("tests/result/group_1"); - $lines = []; - foreach(explode("\n", $firstFile) as $line) { - $lines[] = substr($line, -22); - } - // correct order of test execution is preserved - self::assertSame(['Example1Test.php:testB', 'Example1Test.php:testA', 'Example1Test.php:testC'], $lines); - - // check second file. - $secondFile = file_get_contents("tests/result/group_2"); - $lines = []; - foreach(explode("\n", $secondFile) as $line) { - $lines[] = substr($line, -22); - } - // correct order of test execution is preserved - self::assertSame(['Example2Test.php:testE', 'Example2Test.php:testD', 'Example3Test.php:testF', 'Example3Test.php:testG'], $lines); - } - - public function setUp() - { - @mkdir('tests/result'); - - // remove all files even from bad runs. - foreach(glob('tests/result/group_*') as $file) { - $file = new SplFileInfo($file); - if (is_file($file)) { - @unlink($file); - } - } - } - - - -} diff --git a/tests/Splitter/FailedTestSplitterTaskTest.php b/tests/Splitter/FailedTestSplitterTaskTest.php new file mode 100644 index 0000000..9d5f0fe --- /dev/null +++ b/tests/Splitter/FailedTestSplitterTaskTest.php @@ -0,0 +1,85 @@ +setLogger(new Logger(new NullOutput())); + $task->setReportPath('tests/_output/failedTests.txt') + ->groupsTo(TEST_PATH . '/result/group_'); + + $this->expectException(RuntimeException::class); + $task->run(); + } + + /** + * @covers ::run + */ + public function testRun(): void + { + $expected = 4; + $task = new FailedTestSplitterTask($expected); + $task->setLogger(new Logger(new NullOutput())); + + $groupTo = TEST_PATH . '/result/group_'; + $task + ->setReportPath(TEST_PATH . '/fixtures/failedTests.txt') + ->groupsTo($groupTo) + ->run(); + + $countedFiles = 0; + for ($i = 1; $i <= $expected; ++$i) { + $this->assertFileExists($groupTo . $i); + $countedFiles += count( + explode( + PHP_EOL, + file_get_contents($groupTo . $i) + ) + ); + } + + $this->assertSame( + 8, + $countedFiles, + "Expected 8 tests but got {$countedFiles} tests." + ); + $this->assertFileDoesNotExist($groupTo . ($expected + 1)); + } + + /** + * @covers ::setReportPath + */ + public function testSetReportPathWillThrowExceptionWithEmptyPath(): void + { + $task = new FailedTestSplitterTask(5); + $task->setLogger(new Logger(new NullOutput())); + $this->expectException(InvalidArgumentException::class); + $task->setReportPath(''); + } + + protected function tearDown(): void + { + parent::tearDown(); // TODO: Change the autogenerated stub + $finder = Finder::create() + ->files() + ->name('group_*'); + + foreach ($finder->in(TEST_PATH . '/result') as $file) { + unlink($file->getPathname()); + } + } +} diff --git a/tests/Splitter/SplitTestsByTimeTaskTest.php b/tests/Splitter/SplitTestsByTimeTaskTest.php new file mode 100644 index 0000000..5148a9c --- /dev/null +++ b/tests/Splitter/SplitTestsByTimeTaskTest.php @@ -0,0 +1,107 @@ + [ // 150 sec. + 20 sec. = 170 sec. + 'tests/fixtures/DependencyResolutionExampleTests/DirA/Example1Test.php:testA', + 'tests/fixtures/DependencyResolutionExampleTests2/DirA/Example1Test.php:testB', + ], + 'group_2' => [ // 130 sec. + 20 sec. + 10 sec. = 160 sec. + 'tests/fixtures/DependencyResolutionExampleTests/DirA/Example1Test.php:testB', + 'tests/fixtures/Cests/DirB/ExampleACest.php:testExampleGoFrom', + 'tests/fixtures/DependencyResolutionExampleTests/DirA/Example1Test.php:testC', + ], + 'group_3' => [ // 120.10 sec. + 29.98 sec. + 0.5 sec. + 1.5 sec. + 0.3 sec. = 152.38 sec. + 'tests/fixtures/Cests/DirC/ExampleACest.php:testExampleStayHere', + 'tests/fixtures/Cests/DirA/ExampleACest.php:testExampleGoTo', + 'tests/fixtures/Unit/ExampleBTest.php:testB', + 'tests/fixtures/Unit/ExampleBTest.php:testA', + 'tests/fixtures/Unit/ExampleATest.php:testB', + ], + 'group_4' => [ // 34 sec. + 35 sec. + 33 sec. + 30 sec. + 20 sec. + 0.3 sec. = 152.3 sec. + 'tests/fixtures/DependencyResolutionExampleTests/DirA/Example2Test.php:testD', + 'tests/fixtures/DependencyResolutionExampleTests/DirA/Example2Test.php:testE', + 'tests/fixtures/DependencyResolutionExampleTests/DirB/Example3Test.php:testF', + 'tests/fixtures/DependencyResolutionExampleTests/DirB/Example3Test.php:testG', + 'tests/fixtures/DependencyResolutionExampleTests2/DirA/Example1Test.php:testA', + 'tests/fixtures/Unit/ExampleATest.php:testA', + ], + ]; + + $expectedFiles = 4; + + $task = $this->getMockBuilder(SplitTestsByTimeTask::class) + ->setConstructorArgs([4]) + ->onlyMethods(['getProjectDir']) + ->getMock(); + + $task->method('getProjectDir')->willReturn(dirname(TEST_PATH)); + $groupTo = TEST_PATH . '/result/group_'; + $task->setLogger(new Logger(new NullOutput())); + $task->statFile(TEST_PATH . '/fixtures/timeReport.json') + ->projectRoot(TEST_PATH . '/../') + ->testsFrom(TEST_PATH . '/fixtures/') + ->groupsTo($groupTo) + ->run(); + + + for ($i = 1; $i <= $expectedFiles; ++$i) { + $filename = $groupTo . $i; + $this->assertFileExists($filename); + $lines = explode(PHP_EOL, file_get_contents($filename)); + $this->assertCount(count($expectedGroupContent['group_' . $i]), $lines); + foreach ($expectedGroupContent['group_' . $i] as $expectedSubpath) { + $matches = preg_grep('~' . preg_quote($expectedSubpath, '~') . '$~', $lines); + $this->assertCount( + 1, + $matches, + sprintf( + 'Did not found expected subpath %s in lines of file %s.', + $expectedSubpath, + $filename + ) + ); + } + } + + $this->assertFileDoesNotExist($groupTo . ($expectedFiles + 1)); + } + + protected function tearDown(): void + { + parent::tearDown(); // TODO: Change the autogenerated stub + $finder = Finder::create() + ->files() + ->name('group_*'); + + foreach ($finder->in(TEST_PATH . '/result') as $file) { + unlink($file->getPathname()); + } + } +} diff --git a/tests/Splitter/TestFileSplitterTaskTest.php b/tests/Splitter/TestFileSplitterTaskTest.php new file mode 100644 index 0000000..6eb2988 --- /dev/null +++ b/tests/Splitter/TestFileSplitterTaskTest.php @@ -0,0 +1,111 @@ + 1, + 'from' => 'tests/fixtures/DependencyResolutionExampleTests/', + 'to' => TEST_PATH . '/result/group_', + 'expected' => 1, + ], + [ + 'groups' => 2, + 'from' => 'tests/fixtures/DependencyResolutionExampleTests/', + 'to' => TEST_PATH . '/result/group_', + 'expected' => 2, + ], + [ + 'groups' => 3, + 'from' => 'tests/fixtures/DependencyResolutionExampleTests/', + 'to' => TEST_PATH . '/result/group_', + 'expected' => 3, + ], + [ + 'groups' => 4, + 'from' => 'tests/fixtures/DependencyResolutionExampleTests/', + 'to' => TEST_PATH . '/result/group_', + 'expected' => 3, + ], + [ + 'groups' => 4, + 'from' => 'tests/fixtures/DependencyResolutionExampleTests', + 'to' => TEST_PATH . '/result/group_', + 'expected' => 4, + ], + ]; + } + + /** + * @covers ::run + * @dataProvider providerTestFilesCanBeSplit + */ + public function testFilesCanBeSplitted( + int $groups, + string $from, + string $groupTo, + int $expected + ): void { + $task = new TestFileSplitterTask($groups); + $task->setLogger(new Logger(new NullOutput())); + $task->testsFrom($from) + ->groupsTo($groupTo) + ->run(); + + for ($i = 1; $i <= $expected; ++$i) { + $this->assertFileExists($groupTo . $i); + } + + $this->assertFileDoesNotExist($groupTo . ($expected + 1)); + } + + /** + * @covers ::run + */ + public function testPatternNotFound(): void + { + $task = new TestFileSplitterTask(2); + $task->setLogger(new Logger(new NullOutput())); + $task + ->setPattern(['*Cest.php']) + ->testsFrom('tests/fixtures/DependencyResolutionExampleTests/') + ->groupsTo(TEST_PATH . '/result/group_') + ->run(); + + $this->assertFileDoesNotExist(TEST_PATH . '/result/group_1'); + $this->assertFileDoesNotExist(TEST_PATH . '/result/group_2'); + } + + protected function tearDown(): void + { + parent::tearDown(); // TODO: Change the autogenerated stub + $finder = Finder::create() + ->files() + ->name('group_*'); + + foreach ($finder->in(TEST_PATH . '/result') as $file) { + unlink($file->getPathname()); + } + } +} diff --git a/tests/Splitter/TestsSplitterTaskTest.php b/tests/Splitter/TestsSplitterTaskTest.php new file mode 100644 index 0000000..dc5fab2 --- /dev/null +++ b/tests/Splitter/TestsSplitterTaskTest.php @@ -0,0 +1,154 @@ +getMockBuilder(TestsSplitterTask::class) + ->disableOriginalConstructor() + ->onlyMethods(['doCodeceptLoaderExists']) + ->getMock(); + + $service + ->method('doCodeceptLoaderExists') + ->willReturn(false); + + $this->expectException(TaskException::class); + $this->expectErrorMessage( + 'This task requires Codeception to be loaded. Please require autoload.php of Codeception' + ); + $service->run(); + } + + public function providerTestLoadTestsWithDifferentPatterns(): array + { + return [ + 'Cests' => [ + 'type' => 'cest', + 'groups' => 2, + 'from' => TEST_PATH . '/fixtures/Cests/', + 'expectedFiles' => 2, + ], + 'Dependencies' => [ + 'type' => 'depends', + 'groups' => 2, + 'from' => TEST_PATH . '/fixtures/DependencyResolutionExampleTests/', + 'expectedFiles' => 2, + ], + 'Unit Tests' => [ + 'type' => 'unit', + 'groups' => 2, + 'from' => TEST_PATH . '/fixtures/Unit/', + 'expectedFiles' => 2, + ], + 'Circular Dep' => [ + 'type' => 'circ_depends', + 'groups' => 1, + 'from' => TEST_PATH . '/fixtures/DependencyResolutionExampleTests2/', + 'expectedFiles' => 0, // Circular dependency + ], + ]; + } + + /** + * @covers ::run + * @dataProvider providerTestLoadTestsWithDifferentPatterns + */ + public function testLoadTests( + string $type, + int $groups, + string $from, + int $expectedFiles + ): void { + $task = new TestsSplitterTask($groups); + $task->setLogger(new Logger(new NullOutput())); + $task->testsFrom($from); + + $groupTo = TEST_PATH . '/result/group_'; + $task->groupsTo($groupTo); + $result = $task->run(); + + $this->assertNotEmpty($result); + + if ($expectedFiles > 0) { + $this->assertTrue($result->wasSuccessful()); + $this->assertEquals($expectedFiles, count($result['files'])); + } + + $files = Finder::create() + ->files() + ->in(TEST_PATH . '/result/') + ->name('group_*'); + + $this->assertCount($expectedFiles, $files->getIterator()); + + for ($i = 1; $i <= $expectedFiles; ++$i) { + $this->assertFileExists($groupTo . $i); + } + + // check that the dependencies are ordered correct + if ('depends' === $type) { + for ($i = 1; $i <= $expectedFiles; ++$i) { + $content = explode(PHP_EOL, file_get_contents($groupTo . $i)); + $check = array_flip( + array_map( + static fn(string $fullPath): string => explode(':', $fullPath)[1], + $content + ) + ); + if (preg_grep('#Example1Test\.php#', $content)) { + $this->assertGreaterThan( + $check['testB'], + $check['testA'], + 'The index of testA must be greater than testB to ensure the correct order.' + ); + $this->assertGreaterThan( + $check['testA'], + $check['testC'], + 'The index of testC must be greater than testA to ensure the correct order.' + ); + } + + if (preg_grep('#Example2Test\.php#', $content)) { + $this->assertGreaterThan( + $check['testE'], + $check['testD'], + 'The index of testD must be greater than testE to ensure the correct order.' + ); + } + } + } + } + + protected function tearDown(): void + { + parent::tearDown(); // TODO: Change the autogenerated stub + $finder = Finder::create() + ->files() + ->name('group_*'); + + foreach ($finder->in(TEST_PATH . '/result') as $file) { + unlink($file->getPathname()); + } + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 018e3ad..9965e7f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,9 +1,29 @@ add('logger', new \Consolidation\Log\Logger(new \Symfony\Component\Console\Output\NullOutput)); + +declare(strict_types=1); + +namespace Tests\Codeception\Task; + +require_once dirname(__DIR__) . '/vendor/autoload.php'; +require_once dirname(__DIR__) . '/vendor/codeception/codeception/autoload.php'; + +use Robo\Robo; +use RuntimeException; +use function dirname; +use function is_dir; +use function mkdir; +use function sprintf; + +const TEST_PATH = __DIR__; + +if ( + !is_dir($concurrentDirectory = TEST_PATH . '/result/') + && !mkdir($concurrentDirectory) + && !is_dir($concurrentDirectory) +) { + throw new RuntimeException( + sprintf('Directory "%s" was not created', $concurrentDirectory) + ); +} + +Robo::createContainer(); diff --git a/tests/fixtures/Cests/DirA/ExampleACest.php b/tests/fixtures/Cests/DirA/ExampleACest.php new file mode 100644 index 0000000..1e389a5 --- /dev/null +++ b/tests/fixtures/Cests/DirA/ExampleACest.php @@ -0,0 +1,17 @@ +markTestSkipped('Just a test ... test'); } @@ -14,7 +20,8 @@ public function testA() { * @depends testA * @group example */ - public function testB(){ + public function testB() + { $this->markTestSkipped('Just a test ... test'); } } diff --git a/tests/fixtures/Unit/ExampleATest.php b/tests/fixtures/Unit/ExampleATest.php new file mode 100644 index 0000000..46405d8 --- /dev/null +++ b/tests/fixtures/Unit/ExampleATest.php @@ -0,0 +1,31 @@ +assertTrue(false); + } + + /** + * @group foo + * @group bar + * @group no + * @group example + */ + public function testB(): void + { + $this->assertTrue(false); + } +} diff --git a/tests/fixtures/Unit/ExampleBTest.php b/tests/fixtures/Unit/ExampleBTest.php new file mode 100644 index 0000000..fbaa875 --- /dev/null +++ b/tests/fixtures/Unit/ExampleBTest.php @@ -0,0 +1,31 @@ +assertTrue(false); + } + + /** + * @group foo + * @group baz + * @group no + * @group example + */ + public function testB(): void + { + $this->assertTrue(false); + } +} diff --git a/tests/fixtures/failedTests.txt b/tests/fixtures/failedTests.txt new file mode 100644 index 0000000..e53018c --- /dev/null +++ b/tests/fixtures/failedTests.txt @@ -0,0 +1,8 @@ +tests/acceptance/bar/baz.php:testA +tests/acceptance/bar/baz.php:testB +tests/acceptance/bar/baz.php:testC +tests/acceptance/bar/baz.php:testD +tests/acceptance/bar/baz.php:testE +tests/acceptance/bar/baz.php:testF +tests/acceptance/bar/baz.php:testG +tests/acceptance/bar/baz.php:testH \ No newline at end of file diff --git a/tests/fixtures/reports/html/expected_report.html b/tests/fixtures/reports/html/expected_report.html new file mode 100644 index 0000000..0c496f3 --- /dev/null +++ b/tests/fixtures/reports/html/expected_report.html @@ -0,0 +1,528 @@ + + + Test results + + + + + + + + + + +
+

Codeception Results OK (234.98s)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Acceptance (cloud-stage) Tests

+
+

+ + ExpleogroupCest » Student apply expleogroup and + choose interest 103.29s

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ I acting as "Vincenzo" +

+ +

+ I set locale "fr"

+ +

+ I visit "Page\Applications\ApplicationFormPage","","appsource=expleogroup" +

+ +

+ Page\Applications\ApplicationFormPage: start + application {"title":"La première étape de votre candidature","button":"Commencer"} +

+ +

+ Page\Applications\ApplicationFormPage: fill + personal details {"title":"Votre profil","birthdate":"Votre date de naissance","address":"Votre adresse","gender":"Votre genre"},{"gender":"Masculin","address":"7 cité paradis PARIS"} +

+ +

+ Page\Applications\ApplicationFormPage: fill + education {"title":"Vos études","education":"","diploma":"Quel est votre niveau de diplôme le plus élevé ?","frenchLevel":"","englishLevel":"Quel est votre niveau d’anglais ?"},{"diploma":"Bac+2","englishLevel":"Intermédiaire (B1-B2)"} +

+ +

+ Page\Applications\ApplicationFormPage: fill + learning resources {"title":"La formation en ligne et vous","followedCourses":"Avez-vous déjà suivi des cours en ligne ?","followedCoursesSubject":"Sur quels sujets et sur quels sites ?","resources":"Pour cette formation, vous aurez accès à :"},{"followedCourses":"Oui","followedCoursesSubject":"Coursera","resources":["Un endroit calme","Un ordinateur","Un micro"]} +

+ +

+ Page\Applications\ApplicationFormPage: fill + motivation {"title":"Votre nouvelle carrière","professionalProject":"Détaillez votre projet professionnel (à court, moyen et long-terme)","cv":"Ajoutez votre CV","linkedin":"","foundEmployer":"","desiredStartDate":"","nextButton":"Envoyer la candidature"},{"cv":"cv.pdf"} +

+ +

+ Page\Applications\ApplicationFormPage: see + application end {"title":"Merci de votre intérêt pour nos formations !","button":"RETOUR À L’ACCUEIL"} +

+ +
+
+

Api (cloud-stage) Tests

+
+

+ + AnalyticsCest » Get analytics with paths code + 2.44s

+
+ + + + + + + + + + + + + +

+ I acting as "Business\Users\BotAdmin" +

+ +

+ I get analytics "PATHS",[],"0-1000" +

+ +

+ I see analytics "PATHS" +

+ +
+ + +
+

Bdd (cloud-stage) Tests

+
+

+ + Course » Member can follow a course and pass a + quiz 129.25s

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    As a member +
    I want to follow a + course and pass a quiz
    In order to make + progress on the platform

+ Given i am "member"

+ +

+ When i choose a course

+ +

+ And i follow a course

+ +

+ And i pass a quiz

+ +

+ Then i see that i have followed the course

+ +

+ And i see that i have passed the quiz

+ +
+ + +
+

Summary

+
+ + + + + + + + + + + + + + + + + +
Successful scenarios:3
Failed scenarios:0
Skipped scenarios:0
Incomplete scenarios:0
+
+
+
+ + diff --git a/tests/fixtures/reports/html/expected_report_codeception5.html b/tests/fixtures/reports/html/expected_report_codeception5.html new file mode 100644 index 0000000..0c496f3 --- /dev/null +++ b/tests/fixtures/reports/html/expected_report_codeception5.html @@ -0,0 +1,528 @@ + + + Test results + + + + + + + + + + +
+

Codeception Results OK (234.98s)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Acceptance (cloud-stage) Tests

+
+

+ + ExpleogroupCest » Student apply expleogroup and + choose interest 103.29s

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ I acting as "Vincenzo" +

+ +

+ I set locale "fr"

+ +

+ I visit "Page\Applications\ApplicationFormPage","","appsource=expleogroup" +

+ +

+ Page\Applications\ApplicationFormPage: start + application {"title":"La première étape de votre candidature","button":"Commencer"} +

+ +

+ Page\Applications\ApplicationFormPage: fill + personal details {"title":"Votre profil","birthdate":"Votre date de naissance","address":"Votre adresse","gender":"Votre genre"},{"gender":"Masculin","address":"7 cité paradis PARIS"} +

+ +

+ Page\Applications\ApplicationFormPage: fill + education {"title":"Vos études","education":"","diploma":"Quel est votre niveau de diplôme le plus élevé ?","frenchLevel":"","englishLevel":"Quel est votre niveau d’anglais ?"},{"diploma":"Bac+2","englishLevel":"Intermédiaire (B1-B2)"} +

+ +

+ Page\Applications\ApplicationFormPage: fill + learning resources {"title":"La formation en ligne et vous","followedCourses":"Avez-vous déjà suivi des cours en ligne ?","followedCoursesSubject":"Sur quels sujets et sur quels sites ?","resources":"Pour cette formation, vous aurez accès à :"},{"followedCourses":"Oui","followedCoursesSubject":"Coursera","resources":["Un endroit calme","Un ordinateur","Un micro"]} +

+ +

+ Page\Applications\ApplicationFormPage: fill + motivation {"title":"Votre nouvelle carrière","professionalProject":"Détaillez votre projet professionnel (à court, moyen et long-terme)","cv":"Ajoutez votre CV","linkedin":"","foundEmployer":"","desiredStartDate":"","nextButton":"Envoyer la candidature"},{"cv":"cv.pdf"} +

+ +

+ Page\Applications\ApplicationFormPage: see + application end {"title":"Merci de votre intérêt pour nos formations !","button":"RETOUR À L’ACCUEIL"} +

+ +
+
+

Api (cloud-stage) Tests

+
+

+ + AnalyticsCest » Get analytics with paths code + 2.44s

+
+ + + + + + + + + + + + + +

+ I acting as "Business\Users\BotAdmin" +

+ +

+ I get analytics "PATHS",[],"0-1000" +

+ +

+ I see analytics "PATHS" +

+ +
+ + +
+

Bdd (cloud-stage) Tests

+
+

+ + Course » Member can follow a course and pass a + quiz 129.25s

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    As a member +
    I want to follow a + course and pass a quiz
    In order to make + progress on the platform

+ Given i am "member"

+ +

+ When i choose a course

+ +

+ And i follow a course

+ +

+ And i pass a quiz

+ +

+ Then i see that i have followed the course

+ +

+ And i see that i have passed the quiz

+ +
+ + +
+

Summary

+
+ + + + + + + + + + + + + + + + + +
Successful scenarios:3
Failed scenarios:0
Skipped scenarios:0
Incomplete scenarios:0
+
+
+
+ + diff --git a/tests/fixtures/reports/html/report_1.html b/tests/fixtures/reports/html/report_1.html new file mode 100644 index 0000000..d91f6fd --- /dev/null +++ b/tests/fixtures/reports/html/report_1.html @@ -0,0 +1,317 @@ + + + Test results + + + + + + + + + + +
+

Codeception Results OK (103.29s)

+ + + + + + + + + + + + + + + +
+

Acceptance (cloud-stage) Tests

+
+

+ + ExpleogroupCest » Student apply expleogroup and choose interest 103.29s

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ I acting as "Vincenzo"

+ +

+ I set locale "fr"

+ +

+ I visit "Page\Applications\ApplicationFormPage","","appsource=expleogroup"

+ +

+ Page\Applications\ApplicationFormPage: start application {"title":"La première étape de votre candidature","button":"Commencer"}

+ +

+ Page\Applications\ApplicationFormPage: fill personal details {"title":"Votre profil","birthdate":"Votre date de naissance","address":"Votre adresse","gender":"Votre genre"},{"gender":"Masculin","address":"7 cité paradis PARIS"}

+ +

+ Page\Applications\ApplicationFormPage: fill education {"title":"Vos études","education":"","diploma":"Quel est votre niveau de diplôme le plus élevé ?","frenchLevel":"","englishLevel":"Quel est votre niveau d’anglais ?"},{"diploma":"Bac+2","englishLevel":"Intermédiaire (B1-B2)"}

+ +

+ Page\Applications\ApplicationFormPage: fill learning resources {"title":"La formation en ligne et vous","followedCourses":"Avez-vous déjà suivi des cours en ligne ?","followedCoursesSubject":"Sur quels sujets et sur quels sites ?","resources":"Pour cette formation, vous aurez accès à :"},{"followedCourses":"Oui","followedCoursesSubject":"Coursera","resources":["Un endroit calme","Un ordinateur","Un micro"]}

+ +

+ Page\Applications\ApplicationFormPage: fill motivation {"title":"Votre nouvelle carrière","professionalProject":"Détaillez votre projet professionnel (à court, moyen et long-terme)","cv":"Ajoutez votre CV","linkedin":"","foundEmployer":"","desiredStartDate":"","nextButton":"Envoyer la candidature"},{"cv":"cv.pdf"}

+ +

+ Page\Applications\ApplicationFormPage: see application end {"title":"Merci de votre intérêt pour nos formations !","button":"RETOUR À L’ACCUEIL"}

+ +
+
+

Summary

+
+ + + + + + + + + + + + + + + + + +
Successful scenarios:1
Failed scenarios:0
Skipped scenarios:0
Incomplete scenarios:0
+
+
+
+ + diff --git a/tests/fixtures/reports/html/report_1_codeception5.html b/tests/fixtures/reports/html/report_1_codeception5.html new file mode 100644 index 0000000..3073123 --- /dev/null +++ b/tests/fixtures/reports/html/report_1_codeception5.html @@ -0,0 +1,317 @@ + + + Test results + + + + + + + + + + +
+

Codeception Results OK (01:23.29)

+ + + + + + + + + + + + + + + +
+

Acceptance (cloud-stage) Tests

+
+

+ + ExpleogroupCest » Student apply expleogroup and choose interest 103.29s

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ I acting as "Vincenzo"

+ +

+ I set locale "fr"

+ +

+ I visit "Page\Applications\ApplicationFormPage","","appsource=expleogroup"

+ +

+ Page\Applications\ApplicationFormPage: start application {"title":"La première étape de votre candidature","button":"Commencer"}

+ +

+ Page\Applications\ApplicationFormPage: fill personal details {"title":"Votre profil","birthdate":"Votre date de naissance","address":"Votre adresse","gender":"Votre genre"},{"gender":"Masculin","address":"7 cité paradis PARIS"}

+ +

+ Page\Applications\ApplicationFormPage: fill education {"title":"Vos études","education":"","diploma":"Quel est votre niveau de diplôme le plus élevé ?","frenchLevel":"","englishLevel":"Quel est votre niveau d’anglais ?"},{"diploma":"Bac+2","englishLevel":"Intermédiaire (B1-B2)"}

+ +

+ Page\Applications\ApplicationFormPage: fill learning resources {"title":"La formation en ligne et vous","followedCourses":"Avez-vous déjà suivi des cours en ligne ?","followedCoursesSubject":"Sur quels sujets et sur quels sites ?","resources":"Pour cette formation, vous aurez accès à :"},{"followedCourses":"Oui","followedCoursesSubject":"Coursera","resources":["Un endroit calme","Un ordinateur","Un micro"]}

+ +

+ Page\Applications\ApplicationFormPage: fill motivation {"title":"Votre nouvelle carrière","professionalProject":"Détaillez votre projet professionnel (à court, moyen et long-terme)","cv":"Ajoutez votre CV","linkedin":"","foundEmployer":"","desiredStartDate":"","nextButton":"Envoyer la candidature"},{"cv":"cv.pdf"}

+ +

+ Page\Applications\ApplicationFormPage: see application end {"title":"Merci de votre intérêt pour nos formations !","button":"RETOUR À L’ACCUEIL"}

+ +
+
+

Summary

+
+ + + + + + + + + + + + + + + + + +
Successful scenarios:1
Failed scenarios:0
Skipped scenarios:0
Incomplete scenarios:0
+
+
+
+ + diff --git a/tests/fixtures/reports/html/report_2.html b/tests/fixtures/reports/html/report_2.html new file mode 100644 index 0000000..5e9d9dd --- /dev/null +++ b/tests/fixtures/reports/html/report_2.html @@ -0,0 +1,292 @@ + + + Test results + + + + + + + + + + +
+

Codeception Results OK (2.44s)

+ + + + + + + + + + + + + + + + + + + + +
+

Api (cloud-stage) Tests

+
+

+ + AnalyticsCest » Get analytics with paths code 2.44s

+
+ + + + + + + + + + + + + +

+ I acting as "Business\Users\BotAdmin"

+ +

+ I get analytics "PATHS",[],"0-1000"

+ +

+ I see analytics "PATHS"

+ +
+ + +
+

Summary

+
+ + + + + + + + + + + + + + + + + +
Successful scenarios:1
Failed scenarios:0
Skipped scenarios:0
Incomplete scenarios:0
+
+
+
+ + diff --git a/tests/fixtures/reports/html/report_2_codeception5.html b/tests/fixtures/reports/html/report_2_codeception5.html new file mode 100644 index 0000000..8bb50e2 --- /dev/null +++ b/tests/fixtures/reports/html/report_2_codeception5.html @@ -0,0 +1,292 @@ + + + Test results + + + + + + + + + + +
+

Codeception Results OK (00:02.44)

+ + + + + + + + + + + + + + + + + + + + +
+

Api (cloud-stage) Tests

+
+

+ + AnalyticsCest » Get analytics with paths code 2.44s

+
+ + + + + + + + + + + + + +

+ I acting as "Business\Users\BotAdmin"

+ +

+ I get analytics "PATHS",[],"0-1000"

+ +

+ I see analytics "PATHS"

+ +
+ + +
+

Summary

+
+ + + + + + + + + + + + + + + + + +
Successful scenarios:1
Failed scenarios:0
Skipped scenarios:0
Incomplete scenarios:0
+
+
+
+ + diff --git a/tests/fixtures/reports/html/report_3.html b/tests/fixtures/reports/html/report_3.html new file mode 100644 index 0000000..db1be8e --- /dev/null +++ b/tests/fixtures/reports/html/report_3.html @@ -0,0 +1,319 @@ + + + Test results + + + + + + + + + + +
+

Codeception Results OK (129.25s)

+ + + + + + + + + + + + + + + + + + + + + +
+

Bdd (cloud-stage) Tests

+
+

+ + Course » Member can follow a course and pass a quiz 129.25s

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    As a member
    I want to follow a course and pass a quiz
    In order to make progress on the platform

+ Given i am "member"

+ +

+ When i choose a course

+ +

+ And i follow a course

+ +

+ And i pass a quiz

+ +

+ Then i see that i have followed the course

+ +

+ And i see that i have passed the quiz

+ +
+ + +
+

Summary

+
+ + + + + + + + + + + + + + + + + +
Successful scenarios:1
Failed scenarios:0
Skipped scenarios:0
Incomplete scenarios:0
+
+
+
+ + diff --git a/tests/fixtures/reports/html/report_3_codeception5.html b/tests/fixtures/reports/html/report_3_codeception5.html new file mode 100644 index 0000000..bffa76b --- /dev/null +++ b/tests/fixtures/reports/html/report_3_codeception5.html @@ -0,0 +1,319 @@ + + + Test results + + + + + + + + + + +
+

Codeception Results OK (02:09.25)

+ + + + + + + + + + + + + + + + + + + + + +
+

Bdd (cloud-stage) Tests

+
+

+ + Course » Member can follow a course and pass a quiz 129.25s

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    As a member
    I want to follow a course and pass a quiz
    In order to make progress on the platform

+ Given i am "member"

+ +

+ When i choose a course

+ +

+ And i follow a course

+ +

+ And i pass a quiz

+ +

+ Then i see that i have followed the course

+ +

+ And i see that i have passed the quiz

+ +
+ + +
+

Summary

+
+ + + + + + + + + + + + + + + + + +
Successful scenarios:1
Failed scenarios:0
Skipped scenarios:0
Incomplete scenarios:0
+
+
+
+ + diff --git a/tests/fixtures/result1.xml b/tests/fixtures/result1.xml index 57fa115..688446c 100644 --- a/tests/fixtures/result1.xml +++ b/tests/fixtures/result1.xml @@ -1,58 +1,58 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + diff --git a/tests/fixtures/result2.xml b/tests/fixtures/result2.xml index 374a865..349229f 100644 --- a/tests/fixtures/result2.xml +++ b/tests/fixtures/result2.xml @@ -1,31 +1,31 @@ - - + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/fixtures/timeReport.json b/tests/fixtures/timeReport.json new file mode 100644 index 0000000..aba889b --- /dev/null +++ b/tests/fixtures/timeReport.json @@ -0,0 +1,18 @@ +{ + "tests/fixtures/Cests/DirA/ExampleACest.php:testExampleGoTo": 29.98, + "tests/fixtures/Cests/DirB/ExampleACest.php:testExampleGoFrom": 20, + "tests/fixtures/Cests/DirC/ExampleACest.php:testExampleStayHere": 120.10, + "tests/fixtures/DependencyResolutionExampleTests/DirA/Example1Test.php:testA": 150, + "tests/fixtures/DependencyResolutionExampleTests/DirA/Example1Test.php:testB": 130, + "tests/fixtures/DependencyResolutionExampleTests/DirA/Example1Test.php:testC": 10, + "tests/fixtures/DependencyResolutionExampleTests/DirA/Example2Test.php:testD": 34, + "tests/fixtures/DependencyResolutionExampleTests/DirA/Example2Test.php:testE": 35, + "tests/fixtures/DependencyResolutionExampleTests/DirB/Example3Test.php:testF": 33, + "tests/fixtures/DependencyResolutionExampleTests/DirB/Example3Test.php:testG": 30, + "tests/fixtures/DependencyResolutionExampleTests2/DirA/Example1Test.php:testA": 20, + "tests/fixtures/DependencyResolutionExampleTests2/DirA/Example1Test.php:testB": 20, + "tests/fixtures/Unit/ExampleATest.php:testA": 0.3, + "tests/fixtures/Unit/ExampleATest.php:testB": 0.3, + "tests/fixtures/Unit/ExampleBTest.php:testA": 0.5, + "tests/fixtures/Unit/ExampleBTest.php:testB": 1.5 +} \ No newline at end of file