diff --git a/composer.lock b/composer.lock index d87cede..d52e349 100644 --- a/composer.lock +++ b/composer.lock @@ -2195,6 +2195,145 @@ ], "packages-dev": [ { + "name": "behat/behat", + "version": "v3.0.15", + "source": { + "type": "git", + "url": "https://github.com/Behat/Behat.git", + "reference": "b35ae3d45332d80c532af69cc36f780a9397a996" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Behat/zipball/b35ae3d45332d80c532af69cc36f780a9397a996", + "reference": "b35ae3d45332d80c532af69cc36f780a9397a996", + "shasum": "" + }, + "require": { + "behat/gherkin": "~4.3", + "behat/transliterator": "~1.0", + "ext-mbstring": "*", + "php": ">=5.3.3", + "symfony/class-loader": "~2.1", + "symfony/config": "~2.3", + "symfony/console": "~2.1", + "symfony/dependency-injection": "~2.1", + "symfony/event-dispatcher": "~2.1", + "symfony/translation": "~2.3", + "symfony/yaml": "~2.1" + }, + "require-dev": { + "phpspec/prophecy-phpunit": "~1.0", + "phpunit/phpunit": "~4.0", + "symfony/process": "~2.1" + }, + "suggest": { + "behat/mink-extension": "for integration with Mink testing framework", + "behat/symfony2-extension": "for integration with Symfony2 web framework", + "behat/yii-extension": "for integration with Yii web framework" + }, + "bin": [ + "bin/behat" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Behat": "src/", + "Behat\\Testwork": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Scenario-oriented BDD framework for PHP 5.3", + "homepage": "http://behat.org/", + "keywords": [ + "Agile", + "BDD", + "ScenarioBDD", + "Scrum", + "StoryBDD", + "User story", + "business", + "development", + "documentation", + "examples", + "symfony", + "testing" + ], + "time": "2015-02-22 14:10:33" + }, + { + "name": "behat/gherkin", + "version": "v4.4.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "6b3f8cf3560dc4909c4cddd4f1af3e1f6e9d80af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/6b3f8cf3560dc4909c4cddd4f1af3e1f6e9d80af", + "reference": "6b3f8cf3560dc4909c4cddd4f1af3e1f6e9d80af", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "~4.0", + "symfony/yaml": "~2.1" + }, + "suggest": { + "symfony/yaml": "If you want to parse features, represented in YAML files" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.4-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 5.3", + "homepage": "http://behat.org/", + "keywords": [ + "BDD", + "Behat", + "Cucumber", + "DSL", + "gherkin", + "parser" + ], + "time": "2015-09-29 13:41:19" + }, + { "name": "behat/mink", "version": "v1.6.1", "source": { @@ -2305,6 +2444,65 @@ "time": "2014-09-26 11:35:19" }, { + "name": "behat/mink-extension", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/MinkExtension.git", + "reference": "06e2b99d92e175719d7e841d5be16b7df1a233c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/06e2b99d92e175719d7e841d5be16b7df1a233c5", + "reference": "06e2b99d92e175719d7e841d5be16b7df1a233c5", + "shasum": "" + }, + "require": { + "behat/behat": "~3.0,>=3.0.5", + "behat/mink": "~1.5", + "php": ">=5.3.2", + "symfony/config": "~2.2" + }, + "require-dev": { + "behat/mink-goutte-driver": "~1.1", + "phpspec/phpspec": "~2.0" + }, + "type": "behat-extension", + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\MinkExtension": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christophe Coevoet", + "email": "stof@notk.org" + }, + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com" + } + ], + "description": "Mink extension for Behat", + "homepage": "http://extensions.behat.org/mink", + "keywords": [ + "browser", + "gui", + "test", + "web" + ], + "time": "2015-09-29 17:42:41" + }, + { "name": "behat/mink-goutte-driver", "version": "dev-master", "source": { @@ -2357,6 +2555,46 @@ "time": "2015-06-27 00:15:11" }, { + "name": "behat/transliterator", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Transliterator.git", + "reference": "868e05be3a9f25ba6424c2dd4849567f50715003" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Transliterator/zipball/868e05be3a9f25ba6424c2dd4849567f50715003", + "reference": "868e05be3a9f25ba6424c2dd4849567f50715003", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-0": { + "Behat\\Transliterator": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Artistic-1.0" + ], + "description": "String transliterator", + "keywords": [ + "i18n", + "slug", + "transliterator" + ], + "time": "2015-09-28 16:26:35" + }, + { "name": "doctrine/instantiator", "version": "1.0.5", "source": { @@ -2460,6 +2698,140 @@ "time": "2015-08-29 16:16:56" }, { + "name": "jcalderonzumba/gastonjs", + "version": "dev-guzzle6", + "source": { + "type": "git", + "url": "https://github.com/dawehner/gastonjs.git", + "reference": "31c4bdb076d5d839dd5005810e12533091c603db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dawehner/gastonjs/zipball/31c4bdb076d5d839dd5005810e12533091c603db", + "reference": "31c4bdb076d5d839dd5005810e12533091c603db", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "~6.0", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "~4.6", + "silex/silex": "~1.2", + "symfony/phpunit-bridge": "~2.7", + "symfony/process": "~2.1" + }, + "type": "phantomjs-api", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zumba\\GastonJS\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Zumba\\GastonJS\\Tests\\": "tests/unit" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Juan Francisco Calderón Zumba", + "email": "juanfcz@gmail.com", + "homepage": "http://github.com/jcalderonzumba" + } + ], + "description": "PhantomJS API based server for webpage automation", + "homepage": "https://github.com/jcalderonzumba/gastonjs", + "keywords": [ + "api", + "automation", + "browser", + "headless", + "phantomjs" + ], + "support": { + "source": "https://github.com/dawehner/gastonjs/tree/guzzle6" + }, + "time": "2015-10-04 12:41:08" + }, + { + "name": "jcalderonzumba/mink-phantomjs-driver", + "version": "dev-guzzle6", + "source": { + "type": "git", + "url": "https://github.com/dawehner/MinkPhantomJSDriver.git", + "reference": "ee72b461f0d9c4277f3da0bfe596b22542294e97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dawehner/MinkPhantomJSDriver/zipball/ee72b461f0d9c4277f3da0bfe596b22542294e97", + "reference": "ee72b461f0d9c4277f3da0bfe596b22542294e97", + "shasum": "" + }, + "require": { + "behat/mink": "~1.6", + "behat/mink-extension": "~2.0", + "guzzlehttp/guzzle": "~6.0", + "jcalderonzumba/gastonjs": "dev-guzzle6", + "php": ">=5.4", + "twig/twig": "~1.8" + }, + "require-dev": { + "phpunit/phpunit": "~4.6", + "silex/silex": "~1.2", + "symfony/css-selector": "~2.1", + "symfony/phpunit-bridge": "~2.7", + "symfony/process": "~2.3" + }, + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "0.4.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zumba\\Mink\\Driver\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "Behat\\Mink\\Tests\\Driver\\": "tests/integration" + } + }, + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Juan Francisco Calderón Zumba", + "email": "juanfcz@gmail.com", + "homepage": "http://github.com/jcalderonzumba" + } + ], + "description": "PhantomJS driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "ajax", + "browser", + "headless", + "javascript", + "phantomjs", + "testing" + ], + "support": { + "source": "https://github.com/dawehner/MinkPhantomJSDriver/tree/guzzle6" + }, + "time": "2015-10-04 13:57:04" + }, + { "name": "mikey179/vfsStream", "version": "v1.5.0", "source": { @@ -3409,6 +3781,56 @@ "time": "2015-09-06 08:36:38" }, { + "name": "symfony/config", + "version": "v2.7.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "9698fdf0a750d6887d5e7729d5cf099765b20e61" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/9698fdf0a750d6887d5e7729d5cf099765b20e61", + "reference": "9698fdf0a750d6887d5e7729d5cf099765b20e61", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/filesystem": "~2.3" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + } + }, + "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": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2015-09-21 15:02:29" + }, + { "name": "symfony/css-selector", "version": "v2.7.4", "source": { @@ -3513,6 +3935,55 @@ "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", "time": "2015-08-26 10:48:03" + }, + { + "name": "symfony/filesystem", + "version": "v2.7.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "a17f8a17c20e8614c15b8e116e2f4bcde102cfab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/a17f8a17c20e8614c15b8e116e2f4bcde102cfab", + "reference": "a17f8a17c20e8614c15b8e116e2f4bcde102cfab", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + } + }, + "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": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2015-09-09 17:42:36" } ], "aliases": [], @@ -3547,7 +4018,8 @@ "behat/mink-goutte-driver": 20, "mikey179/vfsstream": 0, "phpunit/phpunit": 0, - "symfony/css-selector": 0 + "symfony/css-selector": 0, + "jcalderonzumba/mink-phantomjs-driver": 20 }, "prefer-stable": true, "prefer-lowest": false, diff --git a/core/composer.json b/core/composer.json index 78ef4f7..fe45482 100644 --- a/core/composer.json +++ b/core/composer.json @@ -35,8 +35,19 @@ "behat/mink-goutte-driver": "dev-master#cc5ce119b5a8e06662f634b35967aff0b0c7dfdd", "mikey179/vfsStream": "~1.2", "phpunit/phpunit": "4.8.*", - "symfony/css-selector": "2.7.*" + "symfony/css-selector": "2.7.*", + "jcalderonzumba/mink-phantomjs-driver": "dev-guzzle6" }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/dawehner/MinkPhantomJSDriver.git" + }, + { + "type": "vcs", + "url": "https://github.com/dawehner/gastonjs.git" + } + ], "replace": { "drupal/action": "self.version", "drupal/aggregator": "self.version", diff --git a/core/modules/simpletest/src/BrowserTestBase.php b/core/modules/simpletest/src/BrowserTestBase.php index e5712c1..ccd3368 100644 --- a/core/modules/simpletest/src/BrowserTestBase.php +++ b/core/modules/simpletest/src/BrowserTestBase.php @@ -25,6 +25,7 @@ use Drupal\Core\Test\TestRunnerKernel; use Drupal\user\UserInterface; use Symfony\Component\HttpFoundation\Request; +use Zumba\Mink\Driver\PhantomJSDriver; /** * Provides a test case for functional Drupal tests. @@ -188,15 +189,34 @@ protected $mink; /** + * The base URL. + * + * @var string + */ + protected $baseUrl; + + /** * Initializes Mink sessions. */ protected function initMink() { - $driver = new GoutteDriver(); + $path = '/tmp/browsertestbase-templatecache'; + if (!file_exists($path)) { + mkdir($path); + } + $driver = new PhantomJSDriver(getenv("DRIVER_URL"), $path); $session = new Session($driver); $this->mink = new Mink(); $this->mink->registerSession('goutte', $session); $this->mink->setDefaultSessionName('goutte'); $this->registerSessions(); + + // Fire up the first request to the front page in order to be able to set + // a cookie later. + // @fixme This is done to circumvent: + // WebDriver\Exception\UnableToSetCookie: {"errorMessage":"Unable to set Cookie: no URL has been loaded yet","request":{"headers":{"Accept":"application/json;charset=UTF-8","Content-Length":"164","Content-Type":"application/json;charset=UTF-8","Host":"127.0.0.1:8910"},"httpVersion":"1.1","method":"POST","post":"{\"cookie\":{\"name\":\"SIMPLETEST_USER_AGENT\",\"value\":\"simpletest472558;1441488302;55eb5dae78eeb7.36607058;IxhRvB7dhbDAMurfBshqgUwEOpAPPKybnJMv0JgaG8Q\",\"secure\":false}}","url":"/cookie","urlParsed":{"anchor":"","query":"","file":"cookie","directory":"/","path":"/cookie","relative":"/cookie","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/cookie","queryKey":{},"chunks":["cookie"]},"urlOriginal":"/session/91aef6b0-5414-11e5-9028-67c7fcbbdc3b/cookie"}} + $session = $this->getSession(); + $session->visit($this->baseUrl); + return $session; } @@ -237,6 +257,8 @@ protected function setUp() { $path = isset($parsed_url['path']) ? rtrim(rtrim($parsed_url['path']), '/') : ''; $port = isset($parsed_url['port']) ? $parsed_url['port'] : 80; + $this->baseUrl = $base_url; + // If the passed URL schema is 'https' then setup the $_SERVER variables // properly so that testing will run under HTTPS. if ($parsed_url['scheme'] === 'https') { diff --git a/core/phpunit.xml.dist b/core/phpunit.xml.dist index 31169cd..b2d6fe7 100644 --- a/core/phpunit.xml.dist +++ b/core/phpunit.xml.dist @@ -10,6 +10,8 @@ + + diff --git a/vendor/behat/behat/.scrutinizer.yml b/vendor/behat/behat/.scrutinizer.yml new file mode 100644 index 0000000..a957ea4 --- /dev/null +++ b/vendor/behat/behat/.scrutinizer.yml @@ -0,0 +1,21 @@ +checks: + php: + code_rating: true + duplication: true + +tools: + external_code_coverage: false + php_code_coverage: false + php_code_sniffer: + config: { standard: 'PSR1' } + php_changetracking: true + php_cpd: true + php_cs_fixer: + config: { level: 'psr1' } + php_mess_detector: true + php_pdepend: true + php_analyzer: true + sensiolabs_security_checker: true + +filter: + paths: [ 'src/*' ] diff --git a/vendor/behat/behat/.travis.yml b/vendor/behat/behat/.travis.yml new file mode 100644 index 0000000..26792bb --- /dev/null +++ b/vendor/behat/behat/.travis.yml @@ -0,0 +1,36 @@ +language: php + +php: [5.3, 5.4, 5.5, 5.6, 5.3.3, hhvm] + +sudo: false + +cache: + directories: + - $HOME/.composer/cache + +branches: + except: + - /^bugfix\/.*$/ + - /^feature\/.*$/ + - /^optimization\/.*$/ + +matrix: + include: + - php: 5.5 + env: SYMFONY_VERSION='2.3.*' + - php: 5.5 + env: SYMFONY_VERSION='2.5.*' + - php: 5.3.3 + env: DEPENDENCIES='low' + +before_script: + - composer selfupdate + - if [ "$SYMFONY_VERSION" != "" ]; then composer require --no-update symfony/symfony=$SYMFONY_VERSION; fi; + - if [ "$DEPENDENCIES" != "low" ]; then composer update; fi; + - if [ "$DEPENDENCIES" = "low" ]; then composer update --prefer-lowest; fi; + - export PATH=./bin:$PATH + - echo " php_version_tags.php + +script: + - phpunit + - behat -fprogress --strict --tags '~@php-version,'`php php_version_tags.php` diff --git a/vendor/behat/behat/CHANGES.md b/vendor/behat/behat/CHANGES.md new file mode 100644 index 0000000..c59255b --- /dev/null +++ b/vendor/behat/behat/CHANGES.md @@ -0,0 +1,793 @@ +3.0.15 / 2015-02-22 +=================== + + * Fix broken null-transformations (Issue #669) + * Improve exception messages (thanks @dantleech) + +3.0.14 / 2014-09-23 +=================== + + * Improve generated context class + +3.0.13 / 2014-08-28 +=================== + + * Add support for typehinted parameters + * Allow any whitespace characters at the end of context class + * Fix scenario with decimal number following string in Turnip pattern + * Fix scenario with empty string in step with Turnip pattern + * Fix scenario where step has slashes in Turnip pattern + +3.0.12 / 2014-07-17 +=================== + + * Fix remaining issues with the definition arguments parsing + * Introduce `Testwork\Argument` component + +3.0.11 / 2014-07-09 +=================== + + * Fix argument resolution for functions with default values (thanks @alesblaznik) + * Fix step colouring of internationalised definitions + * Refactor `ContextFactory` and `RepositorySearchEngine` arguments resolution into the new + Testwork component - `ArgumentResolver` + +3.0.10 / 2014-06-29 +=================== + + * Fix argument resolution when named arguments used and method has defaults (thanks @WouterJ) + * Fix support for decimal numbers in turnip placeholders + +3.0.9 / 2014-06-20 +================== + + * Fix definition translations reading bug with multi-suite configurations (thanks @WouterJ for reporting) + * Fix pretty printer bug with failing background and 2 scenarios (thanks @andytson for reporting) + * Fix memory footprint calculation (thanks @dready for reporting) + +3.0.8 / 2014-06-06 +================== + + * Profile level Gherkin filters are now overridable by CLI filter options + * Rerun cache path is now configurable + * Fix turnip-based step definitions starting from token + * Fix token-based transformations interfering with regex-based ones + * Rerun cache dump have been optimised + +3.0.7 / 2014-05-27 +================== + + * Properly generate keywords in snippets for non-english and `And`, `But` steps (thanks @kibao) + * Fix regex check bug with transformations that return objects (thanks @vaidasm) + * Return ability to use custom formatters by specifiying their class names + +3.0.6 / 2014-05-06 +================== + + * Fix a small extension registration shortcut issue introduced in previous release (thanks @FrenkyNet) + +3.0.5 / 2014-05-06 +================== + + * Fix a suite initialization bug when suite contexts have arguments + * Fix wrong handling of an empty `behat.yml` + * Explicitly fail when provided context argument is not supported by constructor + * Fix extension registration shortcut for 3rd-part plugins + +3.0.4 / 2014-04-29 +================== + + * Make sure that `Before*Tested` is always executed before `Before*` hooks + * Introduce additional `After*Setup` and `Before*Teardown` events + * Improved the error reporting for invalid regexes in step definitions (thanks @stof) + +3.0.3 / 2014-04-27 +================== + + * Support definition transformations without capture groups + * Override gherkin filters in custom profiles instead of merging them + * Refactored the handling of colors to set them earlier + ([#513](https://github.com/Behat/Behat/pull/513) thanks to @stof) + +3.0.2 / 2014-04-26 +================== + + * Fix warning on empty scenarios + +3.0.1 / 2014-04-26 +================== + + * Make sure that `AfterStep` hook is running even if step is failed + ([504](https://github.com/Behat/Behat/issues/504)) + * Optimised the way service wrappers are registered (thanks @stof) + +3.0.0 / 2014-04-20 +================== + + * Brand new highly extendable and clear architecture + * Support for multiple suites per profile + * Support for multiple contexts per suite + * Support for multiple feature paths per suite + * Support for filtered suites + * Support for unique context constructor parameters + * Hooks are first class citizens and thus have their own error and output buffering + * Turnip syntax in definitions + * Reworked formatters with improved error and output buffering + * Rerun does not require precache run + * New gherkin role filter + * Improved error handling with 3 levels of error reporting (-v, -vv, -vvv) + * Dropped subcontexts + * Dropped chained steps + * Dropped closured definitions + +3.0.0rc3 / 2014-03-16 +======================= + + * Multiline step description support ([082da36b7db2525700287616babe982e485330d1](https://github.com/Behat/Behat/commit/082da36b7db2525700287616babe982e485330d1)) + * Added ability to choose all 3 verbosity levels and moved stack traces to the 2nd one ([d550f72d6aa49f0f87a6ce0e50721356a5d04c45](https://github.com/Behat/Behat/commit/d550f72d6aa49f0f87a6ce0e50721356a5d04c45)) + * Renamed Subject to Specification ([#447](https://github.com/Behat/Behat/pull/447)) + * Refactored ContextSnippetGenerator ([#445](https://github.com/Behat/Behat/pull/445)) + * Refactored context arguments handling ([#446](https://github.com/Behat/Behat/pull/446)) + * Refactored testers to use composition over inheritance and added setUp/tearDown phase to them ([#457](https://github.com/Behat/Behat/pull/457)) + * Refactored output formatters to be chain of event listeners + * Refactored hooks to use [scopes](https://github.com/Behat/Behat/tree/3.0/src/Behat/Behat/Hook/Scope) instead of events + * Fixed the GroupedSubjectIterator when dealing with an empty iterator ([2c1312780d610f01116ac42fb958c0c09a64c041](https://github.com/Behat/Behat/commit/2c1312780d610f01116ac42fb958c0c09a64c041)) + * Forced the paths.base to use a real path all the time ([b4477d7cf3f9550874c609d4edc5a4f55390672c](https://github.com/Behat/Behat/commit/b4477d7cf3f9550874c609d4edc5a4f55390672c)) + +3.0.0rc2 / 2014-01-10 +======================= + + * Fixed progress formatter hooks support + * Reintroduced suite hooks (with an additional functionality of name filtering) + * Behat tells about steps that it couldn't generate snippets for + * Memory consumption optimizations + * Fixed contexts inheritance + * New formatter translations + + * Added constructor arguments and class resolving extension points to context creation routine + * Simplified and cleaned `Context` package of the Behat + * Minor public API changes across the board (simplification) + * Optimized subject finding routine and cleaned extension points (`SubjectLocator`) + * Both `ExampleTested` and `ScenarioTested` now use same method name - `getScenario()` + * Added exception accessors to `StepTestResult` + * Renamed `ExerciseTester` to `Exercise` + * Added `HookableEvent` to Testwork, which extends `LifecycleEvent` + * Made `priority` attribute of a tag optional + * Changed all occurrences of `classname` to `class` across public API + * Renamed `GherkinSuite` to `GenericSuite` and moved it into the Testwork + * Added `initialize` call to extension lifecycle and Extension interface + * Renamed some extensions config keys to be more intuitive + +3.0.0rc1 / 2014-01-01 +======================= + + * New layered and highly extendable architecture + * Standard output buffering of definitions and hooks + * Hooks as first class citizens + * New pretty and progress formatters + * Huge speed and memory footprint improvements + * Moved 40% of non-Behat related codebase into a shared foundation called Testwork + +3.0.0beta8 / 2013-10-01 +======================= + + * Add `*SnippetsFriendlyInterface`(s) that are now required to generate snippets + * Add support for turnip-style definitions + * Use turnip-style definitions by default from `--init` + * Rename `SuitesLoader` to `SuitesRegistry` to clarify purpose + * Extract snippet generators into extendable component + * Extract context generators into extendable component + +3.0.0beta7 / 2013-09-29 +======================= + + * Multivalue options are now array options (format, output, name and tags) + * Added back junit formatter (should support all junit formats from 4 to 7) + * Added back html formatter + * Small optimizations and refactorings + * Proper handling of hook failures + +3.0.0beta6 / 2013-09-25 +======================= + + * Skip step execution and `AfterStep` hook if its `BeforeStep` hook failed + * Fix failure-initiated skips of hooks in Scenario and Example testers + * Refactor Suite routines + * Cleanup Context Pools + * Enhance `--definitions` option with suites output and regex search + * Add `toString()` methods to `DefinitionInterface` and `TransformationInterface` + * Add `SnippetlessContextInterface` to `Snippet` namespace - to prevent snippet generation for + custom contexts + +3.0.0beta5 / 2013-09-15 +======================= + + * Switch to Gherkin 3.0 parser + * Complete rewrite of pretty formatter (much better outline handling) + * Automatically add `use` for `PendingException` to contexts during `--append-snippets` + * Lots of optimizations + +3.0.0beta4 / 2013-08-17 +======================= + + * Cleanup suite configuration sub-system + * New ability to turn off specific suites through `behat.yml` + * Support for danish language + +3.0.0beta3 / 2013-08-13 +======================= + + * Refactor extension sub-system. Update `ExtensionInterface` + * Avoid trying to create folders for non-fs suites + +3.0.0beta2 / 2013-08-13 +======================= + + * Remove support for Symfony 2.0 components + +3.0.0beta1 / 2013-08-13 +======================= + + * New suite-centric architecture + * New context pools sub-system with multi-context support + * New dynamic event-driven testing core + * Refactored console processors sub-system + * Refactored formatters management sub-system + * 8 new process extension points and 36 generic execution extension points + * Gherkin caching is enabled by default + * Rerun is enabled by default (use `--rerun` to rerun failed scenarios) + * New Gherkin Role filter + * Subcontexts removed in favor of context pools + * Chained steps extracted into [separate extension](https://github.com/Behat/ChainedStepsExtension) + * Closured step definitions removed + +2.5.0 / 2013-08-11 +================== + + * First Behat LTS release + * Update Junit formatter to reflect latest junit format (thanks @alistairstead) + * Fix some container options + +2.4.6 / 2013-06-06 +================== + + * New --stop-on-failure option + * Support JSON in environment variables + * Update Gherkin + * Support Symfony 2.3 + * Out-of-the-box support for PHPUnit assertions pretty output + +2.4.5 / 2013-01-27 +================== + + * Added wrapping of lines in progress formatter + * Added `--append-to` option to be able to add snippets to custom class + * Both `ScenarioEvent` and `OutlineExampleEvent` now extend same `BaseScenarioEvent` class + * Highly improved ability to create simple custom extensions + * Always hide stack traces for `PendingException` + * Ensured compatibility with all major symfony versions + * Fixed configs import directive and loading precedence + * Fixed path to vendor dir (solves problem of custom vendor dirs) + +2.4.4 / 2012-09-12 +================== + + * Fixed `RuntimeException` namespacing error + * Added `FormatterManager::disableFormatter(s)` method + * Updated Gherkin parser and fixed couple of helper bugs + +2.4.3 / 2012-07-28 +================== + + * Fixed broken `output_path` setting ([issue #169](https://github.com/Behat/Behat/issues/169)) + * Added shellbang to phar executable ([issue #167](https://github.com/Behat/Behat/issues/167)) + * Added feature title to progress exceptions ([issue #166](https://github.com/Behat/Behat/issues/166)) + * Tuned failed formatter to print only failed examples in outline ([issue #154](https://github.com/Behat/Behat/issues/154)) + * Small bugfixes + +2.4.2 / 2012-06-26 +================== + + * Fixed broken autoloading with Composer installation + +2.4.1 / 2012-06-26 +================== + + * Force custom context class usage if user changed it from `FeatureContext` + * Clarified `Context class not found` exception + * Use CWD for CLI options, basepath (config path) for everything else + * Pass `behat.extension.classes` container param to extensions during their load + * Tuned `event_subscriber` priorities + * Use `require_once` instead of `require` in closured loaders + * Fixed transformers bug with falsy transformations (that return **falsy** values) + * Fixed custom formatters definition bug + * Fixed formatter manager exception bug + * Fixed czech translation + * Fixed CS to be PSR2 compliant + +2.4.0 / 2012-05-15 +================== + + * New extension system based on Symfony2 DIC component + * Refactored paths reading system (now relative paths are fully supported) + * Support latest Composer changes + * Removed static constraint for transformations + * Updated to latest Gherkin with immutable AST + * Fixed couple of definition snippet generator bugs + * Option for HTML formatter to provide step definition links + * Added fallback locale (in case if provided lang is unsupported yet) + * Print step snippets in HTML formatter only if they're enabled + * Escape placeholder brackets in HTML formatter + * Use different names for examples in JUnit formatter + * Major core cleanup + +2.3.5 / 2012-03-30 +================== + + * Fixed formatter language configuration and locale guesser + +2.3.4 / 2012-03-28 +================== + + * Added `StepEvent::getLogicalParent()`. Fixed issue #115 + +2.3.3 / 2012-03-09 +================== + + * Implemented Gherkin caching support ([--cache](https://github.com/Behat/Behat/commit/753c4f6e392a873a640543306191d92e6dc91099)) + * Line ranges filtering support (`behat features/some.feature:12-19`. Thanks @headrevision) + * `behat.yml.dist` configs support out of the box + * Minor bug fixes + * Updated Gherkin + +2.3.2 / 2012-01-29 +================== + + * Fixed bug in `ErrorException`, that caused wrong exceptions on warnings and notices + +2.3.1 / 2012-01-26 +================== + + * Updated error handler to avoid suppressed exceptions + * Autoload bootstrap scripts in their name order + * Updated Gherkin dependency to v2.0.1 + +2.3.0 / 2012-01-19 +================== + + * Switch to the Behat\Gherkin 2.0 usage + * Migration to the single-file translation + * Support for callables inside steps chains + * Support for `*.yml` and `*.php` as definition translations + * Added opposite options to option switchers (`--[no-]colors`, `--[no-]multiline`, etc.) + * Redesigned `--story-syntax` + * Refactored Runner + * Performance improvements + * Bugfixes + +2.2.7 / 2012-01-13 +================== + + * Added ability to search translated definitions with `--definitions` + * Fixed custom formatters use bug + +2.2.6 / 2012-01-09 +================== + + * Fixed pretty and html formatters printing of undefined steps in outlines + +2.2.5 / 2012-01-07 +================== + + * `BEHAT_PARAMS` env variable support (083092e) + * HTML formatter print styles optimization (@davedevelopment) + +2.2.4 / 2012-01-04 +================== + + * Prevent method name duplication with definition snippets + +2.2.3 / 2012-01-04 +================== + + * Fixed couple of `--append-snippets` bugs + +2.2.2 / 2011-12-21 +================== + + * Fixed Composer deps + +2.2.1 / 2011-12-21 +================== + + * Fixed Composer package bin + +2.2.0 / 2011-12-14 +================== + + * Multiple formats and outputs support + * New `snippets` formatter + * New `failed` formatter + * Updated output of `-d` option + * Search abilities added to `-d` option + * New `--dry-run` option + * New `--append-snippets` option + * Rerun functionality refactored to use `failed` formatter internally + * Overall code refactoring and cleaning + * Polish translation added (Joseph Bielawski) + * Spanish translation updated (Andrés Botero) + * Locale autodetect + +2.1.3 / 2011-11-04 +================== + + * Substep translations support + * Correctly print undefined substeps in pretty printer + * @Transform callback now gets all provided matches + * Always set proper encoding (UTF8) + +2.1.2 / 2011-10-12 +================== + + * Fixed filtered feature hooks + * Fixed JUnit formatter time output in some locales + +2.1.1 / 2011-10-09 +================== + + * Fixed multiline titles printing bug + * Fixed outline parameter inside step argument printing bug + +2.1.0 / 2011-09-12 +================== + + * Totally revamped HTML formatter template + * Added transliteration support to definition snippets (for most langs) + * Written missed features and fixed some bugs + * Stabilization fixes for 3 major OS: MacOS/Ubuntu/Windows + +2.0.5 / 2011-08-07 +================== + + * Cleaned ContextDispatcher extension points + * Cleaned context-parameters passing behavior + +2.0.4 / 2011-08-02 +================== + + * Subcontexts aliasing and retrieving + * Multiple steps chaining + * `--snippets-paths` option to show steps alongside the snippets + * getContextParameters() method in SuiteEvent and FeatureEvent + * Updated to Symfony2 stable components + * Spanish translation + * Dutch translation + +2.0.3 / 2011-07-20 +================== + + * Fixed JUnit formatter CDATA output + +2.0.2 / 2011-07-17 +================== + + * Added extra checks to context instance mapper + * Fixed i18n support in definitions printer + * Refactored Gherkin tags inheritance + +2.0.1 / 2011-07-12 +================== + + * Exception prefix added to statuses. Now you should throw `PendingException` instead of just + `Pending` + +2.0.0 / 2011-07-12 +================== + + * Brand new Context-oriented architecture + * Refactored --definitions (--steps) to print more useful info + * Rafactored --story-syntax (--usage) to print more useful info + * Refactored Command to use separate processors + * Added --no-paths option + * Added --no-snippets option + * Added --expand option to expand outlines + * phar package + * Faster autoloader + * Steps chaining added + * Added BEHAT_ERROR_REPORTING constant to change error_repoting level + * Fixed some Gherkin bugs + * Fixed lots of bugs in Behat itself + +1.1.9 / 2011-06-17 +================== + + * Updated to the latest Symfony components + +1.1.8 / 2011-06-09 +================== + + * Fixed empty match printing in Pretty and HTML formatters + * Updated to latest Symfony components + +1.1.7 / 2011-06-03 +================== + + * Fixed steps colorization bug in outline + * Additional checks in config import routine + +1.1.6 / 2011-05-27 +================== + + * Updated Symfony vendors + * Refactored console formatters + +1.1.5 / 2011-05-17 +================== + + * Fixed CWD path finding + * Fixed HTML formatter (thanks @glenjamin) + +1.1.4 / 2011-05-03 +================== + + * Fixed `--out` option usage critical bug + * Added ability to specify `output_path` from config file + +1.1.3 / 2011-04-28 +================== + + * JUnit formatter fix + * Formatters basePath fix. Now formatters uses CWD as path trimmer + * Relative paths locator bug fix + * Show table argument header in HTML formatter + +1.1.2 / 2011-04-27 +================== + + * Fixed custom features path locator bug(issue #020) + +1.1.1 / 2011-04-21 +================== + + * Fixed paths finding routines + * Totally refactored BehatCommand + * Added rerun functionality (`--rerun`) + * Ability to remove previously specified paths in `behat.yml` + * Bugfixes and little tweaks + +1.1.0 / 2011-04-04 +================== + + * New configuration system with profiles and imports support + * New event system + * Environment parameters support + * Named regex arguments support + * Japanese translation for formatters + * JUnit formatter bugfixes + * HTML and Pretty formatters multiple arguments print bugfix + * Step snippets (proposals) bugfixes + * Updated vendor libraries + +1.0.0 / 2011-03-08 +================== + + * Changed XSD + * Updated vendors + +1.0.0RC6 / 2011-03-03 +===================== + + * Cleaned command options + * Added --init option + * Multiple paths support in behat.yml + * Application options refactoring + +1.0.0RC5 / 2011-02-25 +===================== + + * Windows support + * Bundled features hooks optimizations + +1.0.0RC4 / 2011-02-23 +===================== + + * Pretty formatter tag printing fix + * Custom formatter specification fix in `behat.yml` + * Symfony components updated + * Extension configuration manager (Symfony\Component\Config component) + * Cleaning of `behat.yml` configurator (thanks to Symfony\Component\Config) + * Additional formatter parameters support in `behat.yml` + +1.0.0RC3 / 2011-02-18 +===================== + + * Event dispatcher binding optimizations + * Command API optimizations for easier overloading + * Formatter path trimming bugfix + * BehatExtension config merging support + +1.0.0RC2 / 2011-02-15 +===================== + + * Step printing option bugfix + +1.0.0RC1 / 2011-02-15 +===================== + + * Gherkin DSL parser is standalone project + * Own Behat namespace for both Behat & Gherkin + * Fully rewritten formatters (much cleaner & beautifull API) + * Big refactoring of whole Behat code (clean code DRYing) + * Config file is now handled by standart-driven DIC extension (cleaner `behat.yml`) + * API documentation retouched + * New `--strict` option + * New `--no-multiline` option + * Feature examples in your language with `--usage` + * Available definitions listing with `--steps` + * Definition i18n + * Command refactoring (much cleaner API & actions) + * Event system refactoring + * 42 new languages with new Gherkin DSL parser + +0.3.6 / 2010-12-07 +================== + + * [Behat,Gherkin] Fixed French support includes (fr) + +0.3.6 / 2010-12-06 +================== + + * [Behat] Updated Symfony2 Components to latest PR4 + * [Gherkin] Added French support (fr) + * [Gherkin] Added German support (de) + * [Behat] Small bugfixes + +0.3.5 / 2010-11-19 +================== + + * [Behat] Refactored EnvironmentBuilder to allow Environment service definition overload + +0.3.4 / 2010-11-18 +================== + + * [Behat] Introduced environment builder + * [Gherkin,Behat] id locale support + +0.3.3 / 2010-11-07 +================== + + * [Gherkin] Added ability to create Table & PyString nodes with hands (in your step to step calls for example) + * [Gherkin] Added getRowsHash() method to TableNode, so now you can "rotate" given tables + * [Gherkin] You now can add comments before language specification in your feature files + +0.3.2 / 2010-11-06 +================== + + * [Gherkin] Added ability to specify extended langs (en-US) + * [Behat,Gherkin] Added pt-BR translation + +0.3.1 / 2010-11-02 +================== + + * [Behat] JUnit formatter + * [Behat] Pretty & HTML formatter background hooks fix + * [Behat] Other small fixes + +0.3.0 / 2010-11-02 +================== + + * [Behat] Refactored tags filter + * [Behat] Added name filter + * [Behat] Refactored hooks + * [Behat] Added tagged/named hooks + * [Behat] Customizable HTML formatter with w3c valid default markup + * [Behat] Ability to specify out path for formatters + * [Behat] Bunch of new options + * [Behat] DIC optimisations + +0.2.5 / 2010-10-22 +================== + + * [Behat] Format manager introduced + * [Behat] Formatters refactoring + * [Behat] Optmized container parameters to support EverzetBehatBundle + * [Behat] --no-color => --no-colors + +0.2.4 / 2010-10-19 +================== + + * [Behat] Autoguess of colors support + * [Behat] Formatter setup bugfix (properl casing) + +0.2.3 / 2010-10-19 +================== + + * [Behat] Filters optimisations + * [Behat] Changed Core Loaders with topic-specific (`StepDefinition\Loader\PHPLoader`, + `Features\Loader\GherkinLoader`) + * [Behat] Simplified TestCommand in prepare of Symfony2 BehatBundle + * [Behat] Configuration file/path setting update (you can now create `behat.yml` inside `./config/behat.yml` & Behat + will load it + * [Behat] Updated Redundant & Ambiguous exceptions behavior + +0.2.2 / 2010-10-10 +================== + + * [Behat] Configuration file/path setting update + +0.2.1 / 2010-10-10 +================== + + * [PEAR] Fix path to phpbin on installation + +0.2.0 / 2010-10-08 +================== + + * [Behat] Brand new stateless testers, based on Visitor pattern + * [Behat] Refactored event listeners & event names + * [Behat] Refactored formatters to confirm with new stateless testers (statuses now sent as event parameters) + * [Behat] Refactored ConsoleFormatter (and removed base formatter) + * [Behat] Removed custom I18n classes & refactored Translator routines in flavor of Symfony\Component\Translation + * [Behat] Added missed translation strings into XLIFF files + * [Behat] Optimised multiline arguments (Node instances are sent to definitions instead of their plain representations) + * [Behat] Support for Scenario Outline tokens replace in multiline arguments (tables & pystrings) + * [Behat] Step arguments transformations (including table transformations) + * [Behat] Colorize inline step arguments + * [Behat] Optimized exit statuses of CLI + * [Behat] Added ability to turn-off colors + * [Behat] Added ability to translate formatters output with `--i18n` option + * [Behat] Bunch of new core feature tests + * [Gherkin] Parser now uses Symfony Dependency Injection to + * [Gherkin] Refactored parser to be like AST (Nodes that supports Visitor pattern) + * [Gherkin] Comments support + * [Gherkin] Fixed PHPUnit warnings + * [Behat,Gherkin] PEAR release script to support http://pear.everzet.com release model + * [Behat,Gherkin] DIC naming refactoring + * [Behat,Gherkin] Autoloader refactoring + * [Behat,Gherkin] Removed Zend & Goutte depencies + +0.1.5 / 2010-09-25 +================== + + * Added ability to call other steps inside step definition + * Added profiles + * Refactored container creation routine + * Single quotes support in step definitions + * Added tests for hooks, profiles, inline steps + +0.1.4 / 2010-09-16 +================== + + * Refactored code + * Removed logic from object constructors + * Added Loader & Filter interfaces + +0.1.3 / 2010-09-14 +================== + + * Ability to specify arrays of paths/files for loaders + * Event hooks and support for `support/hooks.php` + * Formatters listens events with smallest priority + * Don't try to load steps if `steps` folder doesn't exists + * Bugfixes/refactoring + +0.1.2 / 2010-09-10 +================== + + * Added ability to read from `behat.yml` and `behat.xml` + * Moved tags filter to separate object + * Refactored injection controller + * Optimized event names in event dispatcher + * Other small fixes/refactorings + +0.1.1 / 2010-09-09 +================== + + * Added `--tags` option + * Changed environment (world) routines + * Added lots of core tests (writed in Behat itself) + +0.1.0 / 2010-09-08 +================== + + * Initial release diff --git a/vendor/behat/behat/CONTRIBUTING.md b/vendor/behat/behat/CONTRIBUTING.md new file mode 100644 index 0000000..7d8b2d2 --- /dev/null +++ b/vendor/behat/behat/CONTRIBUTING.md @@ -0,0 +1,46 @@ +Contributing +------------ + +Behat is an open source, community-driven project. If you'd like to contribute, +feel free to do this, but remember to follow this few simple rules: + +- Make your feature addition or bug fix, +- __Always__ as base for your changes use `master` branch (all new development + happens here), +- Add `*.features` for those changes (please look into `features/` folder for + some examples). This is important so we don't break it in a future version + unintentionally, +- Commit your code, but do not mess with `BehatApplication` version, or + `CHANGES.md` one, +- __Remember__: when you create Pull Request, always select `master` branch as + target, otherwise it will be closed (this is selected by default). + +Backwards compatibility +----------------------- + +Starting from `v3.0.0`, Behat is following [Semantic Versioning v2.0.0](http://semver.org/spec/v2.0.0.html). +This means that we take backwards compatibility of public API very seriously. So unless you want your PR to start a +new major version of Behat (`v4.0.0` for example), you need to make sure that either you do not change existing +interfaces and their usage across the system or that you at least introduce backwards compatibility layer together with +your change. Not following these rules will cause a rejection of your PR. Exception could be an extremely rare case +where BC break is introduced as a measure to fix a serious issue. + +You can read detailed guidance on what BC means in [Symfony2 BC guide](http://symfony.com/doc/current/contributing/code/bc.html). + +Contributing to Formatter Translations +-------------------------------------- + +Almost any output message (except exceptions and custom output) printed by Behat +formatters could be translated into your language with `--lang` option. In order +to fix/add translation, edit the appropriate section of the `i18n.php` file. + +Running tests +------------- + +Make sure that you don't break anything with your changes by running the test +suite with your locale set to english: + +```bash +$> LANG=C bin/behat +``` + diff --git a/vendor/behat/behat/LICENSE b/vendor/behat/behat/LICENSE new file mode 100644 index 0000000..10e33a9 --- /dev/null +++ b/vendor/behat/behat/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011-2014 Konstantin Kudryashov + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/behat/behat/README.md b/vendor/behat/behat/README.md new file mode 100644 index 0000000..bb7377b --- /dev/null +++ b/vendor/behat/behat/README.md @@ -0,0 +1,74 @@ +![Behat](https://dl.dropboxusercontent.com/u/282797/behat/behat.png) + +Behat is a BDD framework for PHP to help you test business expectations. + +[![Gitter chat](https://badges.gitter.im/Behat/Behat.svg)](https://gitter.im/Behat/Behat) +[![License](https://poser.pugx.org/behat/behat/license.svg)](https://packagist.org/packages/behat/behat) +[![Build Status](https://travis-ci.org/Behat/Behat.svg?branch=master)](https://travis-ci.org/Behat/Behat) +[![HHVM Status](http://hhvm.h4cc.de/badge/behat/behat.svg?branch=master)](http://hhvm.h4cc.de/package/behat/behat) +[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/Behat/Behat/badges/quality-score.png?s=ad84e95fc2405712f88a96d89b4f31dfe5c80fae)](https://scrutinizer-ci.com/g/Behat/Behat/) +[![Total Downloads](https://poser.pugx.org/behat/behat/downloads.svg)](https://packagist.org/packages/behat/behat) + +Installing Behat +---------------- + +The easiest way to install Behat is by using [Composer](https://getcomposer.org): + +```bash +$> curl -sS https://getcomposer.org/installer | php +$> php composer.phar require behat/behat='~3.0.6' +``` + +After that you'll be able to run Behat via: + +```bash +$> vendor/bin/behat +``` + +Installing Development Version +------------------------------ + +Clone the repository and install dependencies via [Composer](https://getcomposer.org): + +```bash +$> curl -sS https://getcomposer.org/installer | php +$> php composer.phar install +``` + +After that you will be able to run development version of Behat via: + +```bash +$> bin/behat +``` + +Contributing +------------ + +Before contributing to Behat, please take a look at the [CONTRIBUTING.md](CONTRIBUTING.md) document. + +Versioning +---------- + +Starting from `v3.0.0`, Behat is following [Semantic Versioning v2.0.0](http://semver.org/spec/v2.0.0.html). +This basically means that if all you do is implement interfaces (like [this one](https://github.com/Behat/Behat/blob/master/src/Behat/Behat/Context/ContextClass/ClassResolver.php#L15-L22)) +and use service constants (like [this one](https://github.com/Behat/Behat/blob/master/src/Behat/Behat/Context/ServiceContainer/ContextExtension.php#L45)), +you would not have any backwards compatibility issues with Behat up until `v4.0.0` (or later major) +is released. Exception could be an extremely rare case where BC break is introduced as a measure +to fix a serious issue. + +You can read detailed guidance on what BC means in [Symfony2 BC guide](http://symfony.com/doc/current/contributing/code/bc.html). + +Useful Links +------------ + +- The main website is at [http://behat.org](http://behat.org) +- The documentation is at [http://behat.readthedocs.org](http://docs.behat.org/en/latest/) +- Official Google Group is at [http://groups.google.com/group/behat](http://groups.google.com/group/behat) +- IRC channel on [#freenode](http://freenode.net/) is `#behat` +- [Note on Patches/Pull Requests](CONTRIBUTING.md) + +Contributors +------------ + +- Konstantin Kudryashov [everzet](http://github.com/everzet) [lead developer] +- Other [awesome developers](https://github.com/Behat/Behat/graphs/contributors) diff --git a/vendor/behat/behat/bin/behat b/vendor/behat/behat/bin/behat new file mode 100755 index 0000000..db21469 --- /dev/null +++ b/vendor/behat/behat/bin/behat @@ -0,0 +1,31 @@ +#!/usr/bin/env php + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +define('BEHAT_BIN_PATH', __FILE__); + +function includeIfExists($file) +{ + if (file_exists($file)) { + return include $file; + } +} + +if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) { + fwrite(STDERR, + 'You must set up the project dependencies, run the following commands:'.PHP_EOL. + 'curl -s http://getcomposer.org/installer | php'.PHP_EOL. + 'php composer.phar install'.PHP_EOL + ); + exit(1); +} + +$factory = new \Behat\Behat\ApplicationFactory(); +$factory->createApplication()->run(); diff --git a/vendor/behat/behat/bin/behat.bat b/vendor/behat/behat/bin/behat.bat new file mode 100755 index 0000000..1034418 --- /dev/null +++ b/vendor/behat/behat/bin/behat.bat @@ -0,0 +1,17 @@ +@echo off +REM Behat +REM +REM This file is part of the Behat. +REM (c) Konstantin Kudryashov +REM +REM For the full copyright and license information, please view the LICENSE +REM file that was distributed with this source code. +REM + +if "%PHPBIN%" == "" set PHPBIN=@php_bin@ +if not exist "%PHPBIN%" if "%PHP_PEAR_PHP_BIN%" neq "" goto USE_PEAR_PATH +GOTO RUN +:USE_PEAR_PATH +set PHPBIN=%PHP_PEAR_PHP_BIN% +:RUN +"%PHPBIN%" "@bin_dir@\behat" %* \ No newline at end of file diff --git a/vendor/behat/behat/box.json b/vendor/behat/behat/box.json new file mode 100644 index 0000000..63118b8 --- /dev/null +++ b/vendor/behat/behat/box.json @@ -0,0 +1,19 @@ +{ + "chmod": "0755", + "directories": ["src"], + "files": [ + "LICENSE", + "i18n.php" + ], + "finder": [ + { + "name": ["*.php", "*.xsd", "LICENSE"], + "exclude": ["Tests", "tests", "sebastian", "phpunit", "phpspec", "process", "filesystem"], + "in": "vendor" + } + ], + "compactors": "Herrera\\Box\\Compactor\\Php", + "main": "bin/behat", + "output": "behat.phar", + "stub": true +} diff --git a/vendor/behat/behat/composer.json b/vendor/behat/behat/composer.json new file mode 100644 index 0000000..a4c5b28 --- /dev/null +++ b/vendor/behat/behat/composer.json @@ -0,0 +1,56 @@ +{ + "name": "behat/behat", + "description": "Scenario-oriented BDD framework for PHP 5.3", + "keywords": ["BDD", "ScenarioBDD", "StoryBDD", "Examples", "Scrum", "Agile", "User story", "Symfony", "business", "development", "testing", "documentation"], + "homepage": "http://behat.org/", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + + "require": { + "php": ">=5.3.3", + "ext-mbstring": "*", + "behat/gherkin": "~4.3", + "behat/transliterator": "~1.0", + "symfony/console": "~2.1", + "symfony/config": "~2.3", + "symfony/dependency-injection": "~2.1", + "symfony/event-dispatcher": "~2.1", + "symfony/translation": "~2.3", + "symfony/yaml": "~2.1", + "symfony/class-loader": "~2.1" + }, + + "require-dev": { + "symfony/process": "~2.1", + "phpspec/prophecy-phpunit": "~1.0", + "phpunit/phpunit": "~4.0" + }, + + "suggest": { + "behat/symfony2-extension": "for integration with Symfony2 web framework", + "behat/yii-extension": "for integration with Yii web framework", + "behat/mink-extension": "for integration with Mink testing framework" + }, + + "autoload": { + "psr-0": { + "Behat\\Behat": "src/", + "Behat\\Testwork": "src/" + } + }, + + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + + "bin": ["bin/behat"] +} diff --git a/vendor/behat/behat/features/append_snippets.feature b/vendor/behat/behat/features/append_snippets.feature new file mode 100644 index 0000000..0c39f3c --- /dev/null +++ b/vendor/behat/behat/features/append_snippets.feature @@ -0,0 +1,827 @@ +Feature: Append snippets option + In order to use definition snippets fully + As a context developer + I need to be able to autoappend snippets to context + + Background: + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + parameters = $parameters; + } + + /** + * @Given /^I have (\d+) apples?$/ + */ + public function iHaveApples($count) { + $this->apples = intval($count); + } + + /** + * @When /^I ate (\d+) apples?$/ + */ + public function iAteApples($count) { + $this->apples -= intval($count); + } + + /** + * @When /^I found (\d+) apples?$/ + */ + public function iFoundApples($count) { + $this->apples += intval($count); + } + + /** + * @Then /^I should have (\d+) apples$/ + */ + public function iShouldHaveApples($count) { + \PHPUnit_Framework_Assert::assertEquals(intval($count), $this->apples); + } + + /** + * @Then /^context parameter "([^"]*)" should be equal to "([^"]*)"$/ + */ + public function contextParameterShouldBeEqualTo($key, $val) { + \PHPUnit_Framework_Assert::assertEquals($val, $this->parameters[$key]); + } + + /** + * @Given /^context parameter "([^"]*)" should be array with (\d+) elements$/ + */ + public function contextParameterShouldBeArrayWithElements($key, $count) { + \PHPUnit_Framework_Assert::assertInternalType('array', $this->parameters[$key]); + \PHPUnit_Framework_Assert::assertEquals(2, count($this->parameters[$key])); + } + + private function doSomethingUndefinedWith() {} + } + """ + And a file named "features/apples.feature" with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 3 apples + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + And do something undefined with $ + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + And do something undefined with \1 + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + | 2 | 2 | 3 | + + Scenario: Multilines + Given pystring: + ''' + some pystring + ''' + And pystring 5: + ''' + other pystring + ''' + And table: + | col1 | col2 | + | val1 | val2 | + """ + + Scenario: Append snippets to main context + When I run "behat -f progress --append-snippets" + Then "features/bootstrap/FeatureContext.php" file should contain: + """ + parameters = $parameters; + } + + /** + * @Given /^I have (\d+) apples?$/ + */ + public function iHaveApples($count) { + $this->apples = intval($count); + } + + /** + * @When /^I ate (\d+) apples?$/ + */ + public function iAteApples($count) { + $this->apples -= intval($count); + } + + /** + * @When /^I found (\d+) apples?$/ + */ + public function iFoundApples($count) { + $this->apples += intval($count); + } + + /** + * @Then /^I should have (\d+) apples$/ + */ + public function iShouldHaveApples($count) { + \PHPUnit_Framework_Assert::assertEquals(intval($count), $this->apples); + } + + /** + * @Then /^context parameter "([^"]*)" should be equal to "([^"]*)"$/ + */ + public function contextParameterShouldBeEqualTo($key, $val) { + \PHPUnit_Framework_Assert::assertEquals($val, $this->parameters[$key]); + } + + /** + * @Given /^context parameter "([^"]*)" should be array with (\d+) elements$/ + */ + public function contextParameterShouldBeArrayWithElements($key, $count) { + \PHPUnit_Framework_Assert::assertInternalType('array', $this->parameters[$key]); + \PHPUnit_Framework_Assert::assertEquals(2, count($this->parameters[$key])); + } + + private function doSomethingUndefinedWith() {} + + /** + * @Then /^do something undefined with \$$/ + */ + public function doSomethingUndefinedWith2() + { + throw new PendingException(); + } + + /** + * @Then /^do something undefined with \\(\d+)$/ + */ + public function doSomethingUndefinedWith3($arg1) + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^pystring (\d+):$/ + */ + public function pystring2($arg1, PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + } + """ + + Scenario: Append snippets to main context with auto use PendingException + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + parameters = $parameters; + } + + /** + * @Given /^I have (\d+) apples?$/ + */ + public function iHaveApples($count) { + $this->apples = intval($count); + } + + /** + * @When /^I ate (\d+) apples?$/ + */ + public function iAteApples($count) { + $this->apples -= intval($count); + } + + /** + * @When /^I found (\d+) apples?$/ + */ + public function iFoundApples($count) { + $this->apples += intval($count); + } + + /** + * @Then /^I should have (\d+) apples$/ + */ + public function iShouldHaveApples($count) { + \PHPUnit_Framework_Assert::assertEquals(intval($count), $this->apples); + } + + /** + * @Then /^context parameter "([^"]*)" should be equal to "([^"]*)"$/ + */ + public function contextParameterShouldBeEqualTo($key, $val) { + \PHPUnit_Framework_Assert::assertEquals($val, $this->parameters[$key]); + } + + /** + * @Given /^context parameter "([^"]*)" should be array with (\d+) elements$/ + */ + public function contextParameterShouldBeArrayWithElements($key, $count) { + \PHPUnit_Framework_Assert::assertInternalType('array', $this->parameters[$key]); + \PHPUnit_Framework_Assert::assertEquals(2, count($this->parameters[$key])); + } + + private function doSomethingUndefinedWith() {} + } + """ + When I run "behat -f progress --append-snippets" + Then "features/bootstrap/FeatureContext.php" file should contain: + """ + parameters = $parameters; + } + + /** + * @Given /^I have (\d+) apples?$/ + */ + public function iHaveApples($count) { + $this->apples = intval($count); + } + + /** + * @When /^I ate (\d+) apples?$/ + */ + public function iAteApples($count) { + $this->apples -= intval($count); + } + + /** + * @When /^I found (\d+) apples?$/ + */ + public function iFoundApples($count) { + $this->apples += intval($count); + } + + /** + * @Then /^I should have (\d+) apples$/ + */ + public function iShouldHaveApples($count) { + \PHPUnit_Framework_Assert::assertEquals(intval($count), $this->apples); + } + + /** + * @Then /^context parameter "([^"]*)" should be equal to "([^"]*)"$/ + */ + public function contextParameterShouldBeEqualTo($key, $val) { + \PHPUnit_Framework_Assert::assertEquals($val, $this->parameters[$key]); + } + + /** + * @Given /^context parameter "([^"]*)" should be array with (\d+) elements$/ + */ + public function contextParameterShouldBeArrayWithElements($key, $count) { + \PHPUnit_Framework_Assert::assertInternalType('array', $this->parameters[$key]); + \PHPUnit_Framework_Assert::assertEquals(2, count($this->parameters[$key])); + } + + private function doSomethingUndefinedWith() {} + + /** + * @Then /^do something undefined with \$$/ + */ + public function doSomethingUndefinedWith2() + { + throw new PendingException(); + } + + /** + * @Then /^do something undefined with \\(\d+)$/ + */ + public function doSomethingUndefinedWith3($arg1) + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^pystring (\d+):$/ + */ + public function pystring2($arg1, PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + } + """ + + Scenario: Append snippets to two contexts + Given a file named "features/bootstrap/FirstContext.php" with: + """ + strings[1] = "hello,\n w\n o\nr\nl\n d"; + $this->tables[1] = array( + array('item1' => 'super', 'item2' => 'mega', 'item3' => 'extra'), + array('item1' => 'hyper', 'item2' => 'mini', 'item3' => 'XXL'), + ); + } + + /** + * @Given /^a pystring:$/ + */ + public function aPystring(PyStringNode $string) { + $this->input = $string; + } + + /** + * @Given /^a table:$/ + */ + public function aTable(TableNode $table) { + $this->input = $table; + } + + /** + * @Then /^it must be equals to string (\d+)$/ + */ + public function itMustBeEqualsToString($number) { + \PHPUnit_Framework_Assert::assertEquals($this->strings[intval($number)], (string) $this->input); + } + + /** + * @Then /^it must be equals to table (\d+)$/ + */ + public function itMustBeEqualsToTable($number) { + \PHPUnit_Framework_Assert::assertEquals($this->tables[intval($number)], $this->input->getHash()); + } + + /** + * @Given /^I have number2 = (?P\d+) and number1 = (?P\d+)$/ + */ + public function iHaveNumberAndNumber($number1, $number2) { + \PHPUnit_Framework_Assert::assertEquals(13, intval($number1)); + \PHPUnit_Framework_Assert::assertEquals(243, intval($number2)); + } + } + """ + + Scenario: PyStrings + Given a file named "features/pystring.feature" with: + """ + Feature: PyStrings + Scenario: + Given a pystring: + ''' + hello, + w + o + r + l + d + ''' + Then it must be equals to string 1 + """ + When I run "behat --no-colors -f progress features/pystring.feature" + Then it should pass with: + """ + .. + + 1 scenario (1 passed) + 2 steps (2 passed) + """ + + Scenario: PyString tokens + Given a file named "features/pystring_tokens.feature" with: + """ + Feature: PyStrings + Scenario Outline: + Given a pystring: + ''' + + w + o + r + + d + ''' + Then it must be equals to string 1 + + Examples: + | word1 | word2 | + | hello, | l | + """ + When I run "behat --no-colors -f progress features/pystring_tokens.feature" + Then it should pass with: + """ + .. + + 1 scenario (1 passed) + 2 steps (2 passed) + """ + + Scenario: Table tokens + Given a file named "features/table_tokens.feature" with: + """ + Feature: Tables + Scenario Outline: + Given a table: + | item1 | item2 | item3 | + | | | extra | + | hyper | mini | | + Then it must be equals to table 1 + + Examples: + | word1 | word2 | word3 | + | super | XXL | mega | + """ + When I run "behat --no-colors -f progress features/table_tokens.feature" + Then it should pass with: + """ + .. + + 1 scenario (1 passed) + 2 steps (2 passed) + """ + + Scenario: Table + Given a file named "features/table.feature" with: + """ + Feature: Tables + Scenario: + Given a table: + | item1 | item2 | item3 | + | super | mega | extra | + | hyper | mini | XXL | + Then it must be equals to table 1 + """ + When I run "behat --no-colors -f progress features/table.feature" + Then it should pass with: + """ + .. + + 1 scenario (1 passed) + 2 steps (2 passed) + """ + + Scenario: Named arguments + Given a file named "features/named_args.feature" with: + """ + Feature: Named arguments + In order to maintain i18n for steps + As a step developer + I need to be able to declare regex with named parameters + + Scenario: + Given I have number2 = 243 and number1 = 13 + """ + When I run "behat --no-colors -f progress features/named_args.feature " + Then it should pass with: + """ + . + + 1 scenario (1 passed) + 1 step (1 passed) + """ diff --git a/vendor/behat/behat/features/bootstrap/FeatureContext.php b/vendor/behat/behat/features/bootstrap/FeatureContext.php new file mode 100644 index 0000000..6d301be --- /dev/null +++ b/vendor/behat/behat/features/bootstrap/FeatureContext.php @@ -0,0 +1,308 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Behat\Behat\Context\Context; +use Behat\Gherkin\Node\PyStringNode; +use Symfony\Component\Process\PhpExecutableFinder; +use Symfony\Component\Process\Process; + +/** + * Behat test suite context. + * + * @author Konstantin Kudryashov + */ +class FeatureContext implements Context +{ + /** + * @var string + */ + private $phpBin; + /** + * @var Process + */ + private $process; + /** + * @var string + */ + private $workingDir; + + /** + * Cleans test folders in the temporary directory. + * + * @BeforeSuite + * @AfterSuite + */ + public static function cleanTestFolders() + { + if (is_dir($dir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'behat')) { + self::clearDirectory($dir); + } + } + + /** + * Prepares test folders in the temporary directory. + * + * @BeforeScenario + */ + public function prepareTestFolders() + { + $dir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'behat' . DIRECTORY_SEPARATOR . + md5(microtime() * rand(0, 10000)); + + mkdir($dir . '/features/bootstrap/i18n', 0777, true); + + $phpFinder = new PhpExecutableFinder(); + if (false === $php = $phpFinder->find()) { + throw new \RuntimeException('Unable to find the PHP executable.'); + } + $this->workingDir = $dir; + $this->phpBin = $php; + $this->process = new Process(null); + } + + /** + * Creates a file with specified name and context in current workdir. + * + * @Given /^(?:there is )?a file named "([^"]*)" with:$/ + * + * @param string $filename name of the file (relative path) + * @param PyStringNode $content PyString string instance + */ + public function aFileNamedWith($filename, PyStringNode $content) + { + $content = strtr((string) $content, array("'''" => '"""')); + $this->createFile($this->workingDir . '/' . $filename, $content); + } + + /** + * Moves user to the specified path. + * + * @Given /^I am in the "([^"]*)" path$/ + * + * @param string $path + */ + public function iAmInThePath($path) + { + $this->moveToNewPath($path); + } + + /** + * Checks whether a file at provided path exists. + * + * @Given /^file "([^"]*)" should exist$/ + * + * @param string $path + */ + public function fileShouldExist($path) + { + PHPUnit_Framework_Assert::assertFileExists($this->workingDir . DIRECTORY_SEPARATOR . $path); + } + + /** + * Sets specified ENV variable + * + * @When /^"BEHAT_PARAMS" environment variable is set to:$/ + * + * @param PyStringNode $value + */ + public function iSetEnvironmentVariable(PyStringNode $value) + { + $this->process->setEnv(array('BEHAT_PARAMS' => (string) $value)); + } + + /** + * Runs behat command with provided parameters + * + * @When /^I run "behat(?: ((?:\"|[^"])*))?"$/ + * + * @param string $argumentsString + */ + public function iRunBehat($argumentsString = '') + { + $argumentsString = strtr($argumentsString, array('\'' => '"')); + + $this->process->setWorkingDirectory($this->workingDir); + $this->process->setCommandLine( + sprintf( + '%s %s %s %s', + $this->phpBin, + escapeshellarg(BEHAT_BIN_PATH), + $argumentsString, + strtr('--format-settings=\'{"timer": false}\'', array('\'' => '"', '"' => '\"')) + ) + ); + + // Don't reset the LANG variable on HHVM, because it breaks HHVM itself + if (!defined('HHVM_VERSION')) { + $env = $this->process->getEnv(); + $env['LANG'] = 'en'; // Ensures that the default language is en, whatever the OS locale is. + $this->process->setEnv($env); + } + + $this->process->start(); + $this->process->wait(); + } + + /** + * Checks whether previously ran command passes|fails with provided output. + * + * @Then /^it should (fail|pass) with:$/ + * + * @param string $success "fail" or "pass" + * @param PyStringNode $text PyString text instance + */ + public function itShouldPassWith($success, PyStringNode $text) + { + $this->itShouldFail($success); + $this->theOutputShouldContain($text); + } + + /** + * Checks whether specified file exists and contains specified string. + * + * @Then /^"([^"]*)" file should contain:$/ + * + * @param string $path file path + * @param PyStringNode $text file content + */ + public function fileShouldContain($path, PyStringNode $text) + { + $path = $this->workingDir . '/' . $path; + PHPUnit_Framework_Assert::assertFileExists($path); + + $fileContent = trim(file_get_contents($path)); + // Normalize the line endings in the output + if ("\n" !== PHP_EOL) { + $fileContent = str_replace(PHP_EOL, "\n", $fileContent); + } + + PHPUnit_Framework_Assert::assertEquals($this->getExpectedOutput($text), $fileContent); + } + + /** + * Checks whether last command output contains provided string. + * + * @Then the output should contain: + * + * @param PyStringNode $text PyString text instance + */ + public function theOutputShouldContain(PyStringNode $text) + { + PHPUnit_Framework_Assert::assertContains($this->getExpectedOutput($text), $this->getOutput()); + } + + private function getExpectedOutput(PyStringNode $expectedText) + { + $text = strtr($expectedText, array('\'\'\'' => '"""', '%%TMP_DIR%%' => sys_get_temp_dir() . DIRECTORY_SEPARATOR)); + + // windows path fix + if ('/' !== DIRECTORY_SEPARATOR) { + $text = preg_replace_callback( + '/ features\/[^\n ]+/', function ($matches) { + return str_replace('/', DIRECTORY_SEPARATOR, $matches[0]); + }, $text + ); + $text = preg_replace_callback( + '/\features\/[^\<]+/', function ($matches) { + return str_replace('/', DIRECTORY_SEPARATOR, $matches[0]); + }, $text + ); + $text = preg_replace_callback( + '/\+[fd] [^ ]+/', function ($matches) { + return str_replace('/', DIRECTORY_SEPARATOR, $matches[0]); + }, $text + ); + } + + return $text; + } + + /** + * Checks whether previously ran command failed|passed. + * + * @Then /^it should (fail|pass)$/ + * + * @param string $success "fail" or "pass" + */ + public function itShouldFail($success) + { + if ('fail' === $success) { + if (0 === $this->getExitCode()) { + echo 'Actual output:' . PHP_EOL . PHP_EOL . $this->getOutput(); + } + + PHPUnit_Framework_Assert::assertNotEquals(0, $this->getExitCode()); + } else { + if (0 !== $this->getExitCode()) { + echo 'Actual output:' . PHP_EOL . PHP_EOL . $this->getOutput(); + } + + PHPUnit_Framework_Assert::assertEquals(0, $this->getExitCode()); + } + } + + private function getExitCode() + { + return $this->process->getExitCode(); + } + + private function getOutput() + { + $output = $this->process->getErrorOutput() . $this->process->getOutput(); + + // Normalize the line endings in the output + if ("\n" !== PHP_EOL) { + $output = str_replace(PHP_EOL, "\n", $output); + } + + // Replace wrong warning message of HHVM + $output = str_replace('Notice: Undefined index: ', 'Notice: Undefined offset: ', $output); + + return trim(preg_replace("/ +$/m", '', $output)); + } + + private function createFile($filename, $content) + { + $path = dirname($filename); + if (!is_dir($path)) { + mkdir($path, 0777, true); + } + + file_put_contents($filename, $content); + } + + private function moveToNewPath($path) + { + $newWorkingDir = $this->workingDir .'/' . $path; + if (!file_exists($newWorkingDir)) { + mkdir($newWorkingDir, 0777, true); + } + + $this->workingDir = $newWorkingDir; + } + + private static function clearDirectory($path) + { + $files = scandir($path); + array_shift($files); + array_shift($files); + + foreach ($files as $file) { + $file = $path . DIRECTORY_SEPARATOR . $file; + if (is_dir($file)) { + self::clearDirectory($file); + } else { + unlink($file); + } + } + + rmdir($path); + } +} diff --git a/vendor/behat/behat/features/config.feature b/vendor/behat/behat/features/config.feature new file mode 100644 index 0000000..31f7502 --- /dev/null +++ b/vendor/behat/behat/features/config.feature @@ -0,0 +1,37 @@ +Feature: Config + In order to configure behat for my needs + As a feature automator + I need to be able to use behat configuration file + + Scenario: Empty configuration file + Given a file named "behat.yml" with: + """ + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + parameters = $parameters; + } + + public function setExtensionParameters(array $parameters) { + $this->extension = $parameters; + } + + /** @When this scenario executes */ + public function thisScenarioExecutes() {} + + /** @Then the context parameters should be overwritten */ + public function theContextParametersOverwrite() { + \PHPUnit_Framework_Assert::assertEquals(array('param2' => 'val2'), $this->parameters); + } + + /** @Then the extension config should be merged */ + public function theExtensionConfigMerge() { + \PHPUnit_Framework_Assert::assertEquals(array('param1' => 'val2', 'param2' => 'val1'), $this->extension); + } + } + """ + And a file named "custom_extension.php" with: + """ + parameters = $parameters; + } + + public function supportsContext(Context $context) + { + return true; + } + + public function initializeContext(Context $context) + { + $context->setExtensionParameters($this->parameters); + } + } + + class CustomExtension implements Extension + { + public function getConfigKey() + { + return 'custom'; + } + + public function configure(ArrayNodeDefinition $builder) + { + $builder->useAttributeAsKey('name')->prototype('variable'); + } + + public function initialize(ExtensionManager $extensionManager) {} + + public function load(ContainerBuilder $container, array $config) + { + $definition = $container->register('custom_initializer', 'CustomInitializer'); + $definition->setArguments(array($config)); + $definition->addTag('context.initializer', array('priority' => 100)); + } + + public function process(ContainerBuilder $container) {} + } + + return new CustomExtension; + """ + And a file named "features/configs.feature" with: + """ + Feature: + Scenario: + When this scenario executes + Then the context parameters should be overwritten + And the extension config should be merged + """ + + Scenario: Config should successfully inherit parent one for default profiles + When I run "behat -f progress --append-snippets" + Then it should pass + + Scenario: Config should successfully inherit parent one for custom profiles + When I run "behat -f progress --append-snippets --profile custom_profile" + Then it should pass diff --git a/vendor/behat/behat/features/config_reference.feature b/vendor/behat/behat/features/config_reference.feature new file mode 100644 index 0000000..0302652 --- /dev/null +++ b/vendor/behat/behat/features/config_reference.feature @@ -0,0 +1,73 @@ +Feature: Config reference + In order to know the available configuration + As a Behat user + I need to be able to dump the configuration reference + + Scenario: Reference of defaults extension + When I run "behat --no-colors --config-reference -v" + Then it should pass + And the output should contain: + """ + suites: + """ + And the output should contain: + """ + exceptions: + """ + + Scenario: Custom extension + Given a file named "behat.yml" with: + """ + default: + extensions: + custom_extension.php: ~ + """ + And a file named "custom_extension.php" with: + """ + children() + ->scalarNode('child')->info('A child node')->end() + ->booleanNode('test')->defaultTrue()->end() + ->end(); + } + + public function initialize(Behat\Testwork\ServiceContainer\ExtensionManager $extensionManager) {} + + public function load(ContainerBuilder $container, array $config) {} + + public function process(ContainerBuilder $container) {} + } + + return new CustomExtension; + """ + When I run "behat --no-colors --config-reference" + Then it should pass + And the output should contain: + """ + custom_extension: + + # A child node + child: ~ + test: true + """ + And the output should contain: + """ + # A child node + """ + And the output should contain: + """ + test: true + """ diff --git a/vendor/behat/behat/features/context.feature b/vendor/behat/behat/features/context.feature new file mode 100644 index 0000000..40b1487 --- /dev/null +++ b/vendor/behat/behat/features/context.feature @@ -0,0 +1,380 @@ +Feature: Context consistency + In order to maintain stable behavior tests + As a feature writer + I need a separate context for every scenario/outline + + Background: + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + parameters = array('parameter1' => $parameter1, 'parameter2' => $parameter2); + } + + /** + * @Given /^I have (\d+) apples?$/ + */ + public function iHaveApples($count) { + $this->apples = intval($count); + } + + /** + * @When /^I ate (\d+) apples?$/ + */ + public function iAteApples($count) { + $this->apples -= intval($count); + } + + /** + * @When /^I found (\d+) apples?$/ + */ + public function iFoundApples($count) { + $this->apples += intval($count); + } + + /** + * @Then /^I should have (\d+) apples$/ + */ + public function iShouldHaveApples($count) { + PHPUnit_Framework_Assert::assertEquals(intval($count), $this->apples); + } + + /** + * @Then /^context parameter "([^"]*)" should be equal to "([^"]*)"$/ + */ + public function contextParameterShouldBeEqualTo($key, $val) { + PHPUnit_Framework_Assert::assertEquals($val, $this->parameters[$key]); + } + + /** + * @Given /^context parameter "([^"]*)" should be array with (\d+) elements$/ + */ + public function contextParameterShouldBeArrayWithElements($key, $count) { + PHPUnit_Framework_Assert::assertInternalType('array', $this->parameters[$key]); + PHPUnit_Framework_Assert::assertEquals(2, count($this->parameters[$key])); + } + } + + class FeatureContext extends CoreContext implements CustomSnippetAcceptingContext + { + public static function getAcceptedSnippetType() { return 'regex'; } + } + """ + And a file named "features/bootstrap/CustomContext.php" with: + """ + apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 5 | 8 | + | 2 | 2 | 3 | + """ + When I run "behat --no-colors -f progress features/apples.feature" + Then it should pass with: + """ + .................. + + 5 scenarios (5 passed) + 18 steps (18 passed) + """ + + Scenario: False "apples story" + Given a file named "features/apples.feature" with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 5 apples + + Scenario: Found more apples + When I found 10 apples + Then I should have 10 apples + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 3 | + | 0 | 5 | 8 | + | 2 | 2 | 4 | + """ + When I run "behat --no-colors -f progress features/apples.feature" + Then it should fail with: + """ + ..F..F...F.......F + + --- Failed steps: + + Then I should have 5 apples # features/apples.feature:11 + Failed asserting that 2 matches expected 5. + + Then I should have 10 apples # features/apples.feature:15 + Failed asserting that 13 matches expected 10. + + Then I should have 3 apples # features/apples.feature:20 + Failed asserting that 1 matches expected 3. + + Then I should have 4 apples # features/apples.feature:20 + Failed asserting that 3 matches expected 4. + + 5 scenarios (1 passed, 4 failed) + 18 steps (14 passed, 4 failed) + """ + + Scenario: Context parameters + Given a file named "behat.yml" with: + """ + default: + suites: + default: + contexts: + - FeatureContext: + parameter1: val_one + parameter2: + everzet: behat_admin + avalanche123: behat_admin + """ + And a file named "features/params.feature" with: + """ + Feature: Context parameters + In order to run a browser + As feature runner + I need to be able to configure behat context + + Scenario: I'm little hungry + Then context parameter "parameter1" should be equal to "val_one" + And context parameter "parameter2" should be array with 2 elements + """ + When I run "behat --no-colors -f progress features/params.feature" + Then it should pass with: + """ + .. + + 1 scenario (1 passed) + 2 steps (2 passed) + """ + + Scenario: Context parameters including optional + Given a file named "behat.yml" with: + """ + default: + suites: + default: + contexts: + - FeatureContext: + parameter1: val_one + """ + And a file named "features/params.feature" with: + """ + Feature: Context parameters + In order to run a browser + As feature runner + I need to be able to configure behat context + + Scenario: I'm little hungry + Then context parameter "parameter1" should be equal to "val_one" + Then context parameter "parameter2" should be equal to "val2_default" + """ + When I run "behat --no-colors -f progress features/params.feature" + Then it should pass with: + """ + .. + + 1 scenario (1 passed) + 2 steps (2 passed) + """ + + Scenario: Existing custom context class + Given a file named "behat.yml" with: + """ + default: + suites: + default: + contexts: [ CustomContext ] + """ + And a file named "features/params.feature" with: + """ + Feature: Context parameters + In order to run a browser + As feature runner + I need to be able to configure behat context + + Scenario: I'm little hungry + Then context parameter "parameter1" should be equal to "val_one" + And context parameter "parameter2" should be array with 2 elements + """ + When I run "behat --no-colors -f progress features/params.feature" + Then it should pass with: + """ + UU + + 1 scenario (1 undefined) + 2 steps (2 undefined) + + --- CustomContext has missing steps. Define them with these snippets: + + /** + * @Then /^context parameter "([^"]*)" should be equal to "([^"]*)"$/ + */ + public function contextParameterShouldBeEqualTo($arg1, $arg2) + { + throw new PendingException(); + } + + /** + * @Then /^context parameter "([^"]*)" should be array with (\d+) elements$/ + */ + public function contextParameterShouldBeArrayWithElements($arg1, $arg2) + { + throw new PendingException(); + } + """ + + Scenario: Single context class instead of an array provided as `contexts` option + Given a file named "behat.yml" with: + """ + default: + suites: + default: + contexts: UnexistentContext + """ + And a file named "features/params.feature" with: + """ + Feature: Context parameters + In order to run a browser + As feature runner + I need to be able to configure behat context + + Scenario: I'm little hungry + Then context parameter "parameter1" should be equal to "val_one" + And context parameter "parameter2" should be array with 2 elements + """ + When I run "behat --no-colors -f progress features/params.feature" + Then it should fail with: + """ + [Behat\Testwork\Suite\Exception\SuiteConfigurationException] + `contexts` setting of the "default" suite is expected to be an array, string given. + + + + behat [-s|--suite="..."] [-f|--format="..."] [-o|--out="..."] [--format-settings="..."] [--init] [--lang="..."] [--name="..."] [--tags="..."] [--role="..."] [--story-syntax] [-d|--definitions="..."] [--append-snippets] [--no-snippets] [--strict] [--rerun] [--stop-on-failure] [--dry-run] [paths] + """ + + Scenario: Unexisting custom context class + Given a file named "behat.yml" with: + """ + default: + suites: + default: + contexts: [ UnexistentContext ] + """ + And a file named "features/params.feature" with: + """ + Feature: Context parameters + In order to run a browser + As feature runner + I need to be able to configure behat context + + Scenario: I'm little hungry + Then context parameter "parameter1" should be equal to "val_one" + And context parameter "parameter2" should be array with 2 elements + """ + When I run "behat --no-colors -f progress features/params.feature" + Then it should fail with: + """ + [Behat\Behat\Context\Exception\ContextNotFoundException] + `UnexistentContext` context class not found and can not be used. + + + + behat [-s|--suite="..."] [-f|--format="..."] [-o|--out="..."] [--format-settings="..."] [--init] [--lang="..."] [--name="..."] [--tags="..."] [--role="..."] [--story-syntax] [-d|--definitions="..."] [--append-snippets] [--no-snippets] [--strict] [--rerun] [--stop-on-failure] [--dry-run] [paths] + """ + + Scenario: Unexisting context argument + Given a file named "behat.yml" with: + """ + default: + suites: + default: + contexts: + - FeatureContext: + unexistingParam: 'value' + """ + And a file named "features/params.feature" with: + """ + Feature: Context parameters + In order to run a browser + As feature runner + I need to be able to configure behat context + + Scenario: I'm little hungry + Then context parameter "parameter1" should be equal to "val_one" + And context parameter "parameter2" should be array with 2 elements + """ + When I run "behat --no-colors -f progress features/params.feature" + Then it should fail with: + """ + [Behat\Testwork\Argument\Exception\UnknownParameterValueException] + `CoreContext::__construct()` does not expect argument `$unexistingParam`. + + + + behat [-s|--suite="..."] [-f|--format="..."] [-o|--out="..."] [--format-settings="..."] [--init] [--lang="..."] [--name="..."] [--tags="..."] [--role="..."] [--story-syntax] [-d|--definitions="..."] [--append-snippets] [--no-snippets] [--strict] [--rerun] [--stop-on-failure] [--dry-run] [paths] + """ diff --git a/vendor/behat/behat/features/definitions_override.feature b/vendor/behat/behat/features/definitions_override.feature new file mode 100644 index 0000000..464a63c --- /dev/null +++ b/vendor/behat/behat/features/definitions_override.feature @@ -0,0 +1,78 @@ +Feature: Step Definitions Override + In order to fine-tune definitions defined in parent classes + As a step definitions developer + I need to be able to override definition methods + + Scenario: Overriden method without own annotation will inherit parent pattern + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + .*)")? should(? not)? be:$/ + */ + public function checkEquality($path = null, $isNegative = null, PyStringNode $json = null) + { + PHPUnit_Framework_Assert::assertNull($path); + PHPUnit_Framework_Assert::assertNull($isNegative); + PHPUnit_Framework_Assert::assertNotNull($json); + } + + /** + * @Then /^the other (?:JSON|json)(?: response)?(?: at "(?.*)")? should(? not)? be:$/ + */ + public function checkEquality2($json = null, $path = null, $isNegative = null) + { + PHPUnit_Framework_Assert::assertNull($path); + PHPUnit_Framework_Assert::assertNull($isNegative); + PHPUnit_Framework_Assert::assertNotNull($json); + } + } + """ + And a file named "features/step_patterns.feature" with: + """ + Feature: Step Pattern + Scenario: + Then the JSON should be: + ''' + Test + ''' + And the other JSON should be: + ''' + Test + ''' + """ + When I run "behat -f progress --no-colors" + Then it should pass with: + """ + .. + + 1 scenario (1 passed) + 2 steps (2 passed) + """ + + Scenario: Definition parameter with decimal number following string + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + username = $username; + $this->age = $age; + } + + public function getUsername() { return $this->username; } + public function getAge() { return $this->age; } + } + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + getHash(); + $username = $hash[0]['username']; + $age = $hash[0]['age']; + + return new User($username, $age); + } + + /** @Transform /^\d+$/ */ + public function castToNumber($number) { + return intval($number); + } + + /** @Transform :user */ + public function castToUser($username) { + return new User($username); + } + + /** + * @Transform /^(yes|no)$/ + */ + public function castEinenOrKeinenToBoolean($expected) { + return 'yes' === $expected; + } + + /** + * @Given /I am (".*" user)/ + * @Given I am user: + * @Given I am :user + */ + public function iAmUser(User $user) { + $this->user = $user; + } + + /** + * @Then /Username must be "([^"]+)"/ + */ + public function usernameMustBe($username) { + PHPUnit_Framework_Assert::assertEquals($username, $this->user->getUsername()); + } + + /** + * @Then /Age must be (\d+)/ + */ + public function ageMustBe($age) { + PHPUnit_Framework_Assert::assertEquals($age, $this->user->getAge()); + PHPUnit_Framework_Assert::assertInternalType('int', $age); + } + + /** + * @Then /^the boolean (no) should be transformed to false$/ + */ + public function theBooleanShouldBeTransformed($boolean) { + PHPUnit_Framework_Assert::assertSame(false, $boolean); + } + } + """ + + Scenario: Simple Arguments Transformations + Given a file named "features/step_arguments.feature" with: + """ + Feature: Step Arguments + Scenario: + Given I am "everzet" user + Then Username must be "everzet" + And Age must be 20 + And the boolean no should be transformed to false + + Scenario: + Given I am "antono - 29" user + Then Username must be "antono" + And Age must be 29 + """ + When I run "behat -f progress --no-colors" + Then it should pass with: + """ + ....... + + 2 scenarios (2 passed) + 7 steps (7 passed) + """ + + Scenario: Table Arguments Transformations + Given a file named "features/table_arguments.feature" with: + """ + Feature: Step Arguments + Scenario: + Given I am user: + | username | age | + | ever.zet | 22 | + Then Username must be "ever.zet" + And Age must be 22 + + Scenario: + Given I am user: + | username | age | + | vasiljev | 30 | + Then Username must be "vasiljev" + And Age must be 30 + """ + When I run "behat -f progress --no-colors" + Then it should pass with: + """ + ...... + + 2 scenarios (2 passed) + 6 steps (6 passed) + """ + + Scenario: Named Arguments Transformations + Given a file named "features/step_arguments.feature" with: + """ + Feature: Step Arguments + Scenario: + Given I am "everzet" + Then Username must be "everzet" + + Scenario: + Given I am "antono" + Then Username must be "antono" + """ + When I run "behat -f progress --no-colors" + Then it should pass with: + """ + .... + + 2 scenarios (2 passed) + 4 steps (4 passed) + """ + + Scenario: Transforming different types + Given a file named "features/to_null.feature" with: + """ + Feature: I should be able to transform values into different types for testing + + Scenario Outline: Converting different types + Given I have the value "" + Then it should be of type "" + + Examples: + | value | type | + | "soeuhtou" | string | + | 34 | integer | + | null | NULL | + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + value); + } + + /** + * @Transform /^".*"$/ + */ + public function transformString($string) + { + return strval($string); + } + + /** + * @Transform /^\d+$/ + */ + public function transformInt($int) + { + return intval($int); + } + + /** + * @Transform /^null/ + */ + public function transformNull($null) + { + return null; + } + + /** + * @Given I have the value ":value" + */ + public function iHaveTheValue($value) + { + $this->value = $value; + } + + /** + * @Then it should be of type :type + */ + public function itShouldBeOfType($type) + { + if (gettype($this->value) != $type) { + throw new Exception("Expected " . $type . ", got " . gettype($this->value) . " (value: " . $this->value . ")"); + } + } + } + """ + When I run "behat -f progress --no-colors" + Then it should pass with: + """ + ...... + + 3 scenarios (3 passed) + 6 steps (6 passed) + """ diff --git a/vendor/behat/behat/features/definitions_translations.feature b/vendor/behat/behat/features/definitions_translations.feature new file mode 100644 index 0000000..df41e94 --- /dev/null +++ b/vendor/behat/behat/features/definitions_translations.feature @@ -0,0 +1,361 @@ +Feature: Definitions translations + In order to be able to use predefined steps in native language + As a step definitions developer + I need to be able to write definition translations + + Scenario: In place XLIFF translations + Given a file named "features/calc_ru.feature" with: + """ + # language: ru + Функция: Базовая калькуляция + + Сценарий: + Допустим Я набрал число 10 на калькуляторе + И Я набрал число 4 на калькуляторе + И Я нажал "+" + То Я должен увидеть на экране 14 + И пользователь "everzet" должен иметь имя "everzet" + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + numbers[] = intval($number); + } + + /** + * @Given /^I have clicked "+"$/ + */ + public function iHaveClickedPlus() { + $this->result = array_sum($this->numbers); + } + + /** + * @Then /^I should see (\d+) on the screen$/ + */ + public function iShouldSeeOnTheScreen($result) { + PHPUnit_Framework_Assert::assertEquals(intval($result), $this->result); + } + + /** @Transform /"([^"]+)" user/ */ + public static function createUserFromUsername($username) { + return (Object) array('name' => $username); + } + + /** + * @Then /^the ("[^"]+" user) name should be "([^"]*)"$/ + */ + public function theUserUsername($user, $username) { + PHPUnit_Framework_Assert::assertEquals($username, $user->name); + } + + public static function getTranslationResources() { + return array(__DIR__ . DIRECTORY_SEPARATOR . 'i18n' . DIRECTORY_SEPARATOR . 'ru.xliff'); + } + } + """ + And a file named "features/bootstrap/i18n/ru.xliff" with: + """ + + +
+ + + /^I have entered (\d+) into calculator$/ + /^Я набрал число (\d+) на калькуляторе$/ + + + /^I have clicked "+"$/ + /^Я нажал "([^"]*)"$/ + + + /^I should see (\d+) on the screen$/ + /^Я должен увидеть на экране (\d+)$/ + + + /"([^"]+)" user/ + /пользователь "([^"]+)"/ + + + /^the ("[^"]+" user) name should be "([^"]*)"$/ + /^(пользователь "[^"]+") должен иметь имя "([^"]*)"$/ + + + + + """ + When I run "behat --no-colors -f progress features/calc_ru.feature" + Then it should pass with: + """ + ..... + + 1 scenario (1 passed) + 5 steps (5 passed) + """ + + Scenario: In place YAML translations + Given a file named "features/calc_ru.feature" with: + """ + # language: ru + Функция: Базовая калькуляция + + Сценарий: + Допустим Я набрал число 10 на калькуляторе + И Я набрал число 4 на калькуляторе + И Я нажал "+" + То Я должен увидеть на экране 14 + И пользователь "everzet" должен иметь имя "everzet" + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + numbers[] = intval($number); + } + + /** + * @Given /^I have clicked "+"$/ + */ + public function iHaveClickedPlus() { + $this->result = array_sum($this->numbers); + } + + /** + * @Then /^I should see (\d+) on the screen$/ + */ + public function iShouldSeeOnTheScreen($result) { + PHPUnit_Framework_Assert::assertEquals(intval($result), $this->result); + } + + /** @Transform /"([^"]+)" user/ */ + public static function createUserFromUsername($username) { + return (Object) array('name' => $username); + } + + /** + * @Then /^the ("[^"]+" user) name should be "([^"]*)"$/ + */ + public function theUserUsername($user, $username) { + PHPUnit_Framework_Assert::assertEquals($username, $user->name); + } + + public static function getTranslationResources() { + return array(__DIR__ . DIRECTORY_SEPARATOR . 'i18n' . DIRECTORY_SEPARATOR . 'ru.yml'); + } + } + """ + And a file named "features/bootstrap/i18n/ru.yml" with: + """ + '/^I have entered (\d+) into calculator$/': '/^Я набрал число (\d+) на калькуляторе$/' + '/^I have clicked "+"$/': '/^Я нажал "([^"]*)"$/' + '/^I should see (\d+) on the screen$/': '/^Я должен увидеть на экране (\d+)$/' + '/"([^"]+)" user/': '/пользователь "([^"]+)"/' + '/^the ("[^"]+" user) name should be "([^"]*)"$/': '/^(пользователь "[^"]+") должен иметь имя "([^"]*)"$/' + """ + When I run "behat --no-colors -f progress features/calc_ru.feature" + Then it should pass with: + """ + ..... + + 1 scenario (1 passed) + 5 steps (5 passed) + """ + + Scenario: In place PHP translations + Given a file named "features/calc_ru.feature" with: + """ + # language: ru + Функция: Базовая калькуляция + + Сценарий: + Допустим Я набрал число 10 на калькуляторе + И Я набрал число 4 на калькуляторе + И Я нажал "+" + То Я должен увидеть на экране 14 + И пользователь "everzet" должен иметь имя "everzet" + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + numbers[] = intval($number); + } + + /** + * @Given /^I have clicked "+"$/ + */ + public function iHaveClickedPlus() { + $this->result = array_sum($this->numbers); + } + + /** + * @Then /^I should see (\d+) on the screen$/ + */ + public function iShouldSeeOnTheScreen($result) { + PHPUnit_Framework_Assert::assertEquals(intval($result), $this->result); + } + + /** @Transform /"([^"]+)" user/ */ + public static function createUserFromUsername($username) { + return (Object) array('name' => $username); + } + + /** + * @Then /^the ("[^"]+" user) name should be "([^"]*)"$/ + */ + public function theUserUsername($user, $username) { + PHPUnit_Framework_Assert::assertEquals($username, $user->name); + } + + public static function getTranslationResources() { + return array(__DIR__ . DIRECTORY_SEPARATOR . 'i18n' . DIRECTORY_SEPARATOR . 'ru.php'); + } + } + """ + And a file named "features/bootstrap/i18n/ru.php" with: + """ + '/^Я набрал число (\d+) на калькуляторе$/', + '/^I have clicked "+"$/' => '/^Я нажал "([^"]*)"$/', + '/^I should see (\d+) on the screen$/' => '/^Я должен увидеть на экране (\d+)$/', + '/"([^"]+)" user/' => '/пользователь "([^"]+)"/', + '/^the ("[^"]+" user) name should be "([^"]*)"$/' => '/^(пользователь "[^"]+") должен иметь имя "([^"]*)"$/', + ); + """ + When I run "behat --no-colors -f progress features/calc_ru.feature" + Then it should pass with: + """ + ..... + + 1 scenario (1 passed) + 5 steps (5 passed) + """ + + Scenario: Translations with 2 suites + Given a file named "behat.yml" with: + """ + default: + suites: + frontend: ~ + backend: ~ + """ + Given a file named "features/calc_ru.feature" with: + """ + # language: ru + Функция: Базовая калькуляция + + Сценарий: + Допустим Я набрал число 10 на калькуляторе + И Я набрал число 4 на калькуляторе + И Я нажал "+" + То Я должен увидеть на экране 14 + И пользователь "everzet" должен иметь имя "everzet" + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + numbers[] = intval($number); + } + + /** + * @Given /^I have clicked "+"$/ + */ + public function iHaveClickedPlus() { + $this->result = array_sum($this->numbers); + } + + /** + * @Then /^I should see (\d+) on the screen$/ + */ + public function iShouldSeeOnTheScreen($result) { + PHPUnit_Framework_Assert::assertEquals(intval($result), $this->result); + } + + /** @Transform /"([^"]+)" user/ */ + public static function createUserFromUsername($username) { + return (Object) array('name' => $username); + } + + /** + * @Then /^the ("[^"]+" user) name should be "([^"]*)"$/ + */ + public function theUserUsername($user, $username) { + PHPUnit_Framework_Assert::assertEquals($username, $user->name); + } + + public static function getTranslationResources() { + return array(__DIR__ . DIRECTORY_SEPARATOR . 'i18n' . DIRECTORY_SEPARATOR . 'ru.php'); + } + } + """ + And a file named "features/bootstrap/i18n/ru.php" with: + """ + '/^Я набрал число (\d+) на калькуляторе$/', + '/^I have clicked "+"$/' => '/^Я нажал "([^"]*)"$/', + '/^I should see (\d+) on the screen$/' => '/^Я должен увидеть на экране (\d+)$/', + '/"([^"]+)" user/' => '/пользователь "([^"]+)"/', + '/^the ("[^"]+" user) name should be "([^"]*)"$/' => '/^(пользователь "[^"]+") должен иметь имя "([^"]*)"$/', + ); + """ + When I run "behat --no-colors -f progress features/calc_ru.feature" + Then it should pass with: + """ + .......... + + 2 scenarios (2 passed) + 10 steps (10 passed) + """ diff --git a/vendor/behat/behat/features/dry_run.feature b/vendor/behat/behat/features/dry_run.feature new file mode 100644 index 0000000..961786c --- /dev/null +++ b/vendor/behat/behat/features/dry_run.feature @@ -0,0 +1,219 @@ +Feature: Dry run + In order to print formatters output without executing steps + As a feature developer + I need to have a --dry-run option + + Background: + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + | 2 | 2 | 3 | + """ + + Scenario: Just run feature + When I run "behat --no-colors --format-settings='{\"paths\": false}' features/apples.feature" + Then it should pass with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + │ STEP: I have 3 apples + + ┌─ @BeforeScenario # FeatureContext::beforeScenario() + │ + │ HOOK: before scenario + │ + Scenario: I'm little hungry + When I ate 1 apple + │ STEP: I ate 1 apples + Then I should have 3 apples + │ STEP: I should have 3 apples + + ┌─ @BeforeScenario # FeatureContext::beforeScenario() + │ + │ HOOK: before scenario + │ + Scenario: Found more apples + Given I have 3 apples + │ STEP: I have 3 apples + When I found 5 apples + │ STEP: I found 5 apples + Then I should have 8 apples + │ STEP: I should have 8 apples + + ┌─ @BeforeScenario # FeatureContext::beforeScenario() + │ + │ HOOK: before scenario + │ + Scenario: Found more apples + Given I have 3 apples + │ STEP: I have 3 apples + When I found 2 apples + │ STEP: I found 2 apples + Then I should have 5 apples + │ STEP: I should have 5 apples + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + ┌─ @BeforeScenario # FeatureContext::beforeScenario() + │ + │ HOOK: before scenario + │ + | 3 | 1 | 1 | + │ STEP: I have 3 apples + │ STEP: I ate 3 apples + │ STEP: I found 1 apples + │ STEP: I should have 1 apples + ┌─ @BeforeScenario # FeatureContext::beforeScenario() + │ + │ HOOK: before scenario + │ + | 0 | 4 | 8 | + │ STEP: I have 3 apples + │ STEP: I ate 0 apples + │ STEP: I found 4 apples + │ STEP: I should have 8 apples + ┌─ @BeforeScenario # FeatureContext::beforeScenario() + │ + │ HOOK: before scenario + │ + | 2 | 2 | 3 | + │ STEP: I have 3 apples + │ STEP: I ate 2 apples + │ STEP: I found 2 apples + │ STEP: I should have 3 apples + + 6 scenarios (6 passed) + 21 steps (21 passed) + """ + + Scenario: Run feature with --dry-run + When I run "behat --no-colors --dry-run features/apples.feature" + Then it should pass with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: # features/apples.feature:6 + Given I have 3 apples # FeatureContext::iHaveApples() + + Scenario: I'm little hungry # features/apples.feature:9 + When I ate 1 apple # FeatureContext::iAteApples() + Then I should have 3 apples # FeatureContext::iShouldHaveApples() + + Scenario: Found more apples # features/apples.feature:13 + When I found 5 apples # FeatureContext::iFoundApples() + Then I should have 8 apples # FeatureContext::iShouldHaveApples() + + Scenario: Found more apples # features/apples.feature:17 + When I found 2 apples # FeatureContext::iFoundApples() + Then I should have 5 apples # FeatureContext::iShouldHaveApples() + + Scenario Outline: Other situations # features/apples.feature:21 + When I ate apples # FeatureContext::iAteApples() + And I found apples # FeatureContext::iFoundApples() + Then I should have apples # FeatureContext::iShouldHaveApples() + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + | 2 | 2 | 3 | + + --- Skipped scenarios: + + features/apples.feature:9 + features/apples.feature:13 + features/apples.feature:17 + features/apples.feature:28 + features/apples.feature:29 + features/apples.feature:30 + + 6 scenarios (6 skipped) + 21 steps (21 skipped) + """ diff --git a/vendor/behat/behat/features/empty_feature.feature b/vendor/behat/behat/features/empty_feature.feature new file mode 100644 index 0000000..42e7854 --- /dev/null +++ b/vendor/behat/behat/features/empty_feature.feature @@ -0,0 +1,28 @@ +Feature: Empty feature + In order to follow BDD practice without a hassle + As a BDD practitioner + I need to be able to leave scenario titles without steps for time being + + Scenario: Empty scenario + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + array = array(); + } + + /** + * @When /^I access array index (\d+)$/ + */ + public function iAccessArrayIndex($arg1) + { + $index = intval($arg1); + $this->result = $this->array[$index]; + } + + /** + * @Then /^I should get NULL$/ + */ + public function iShouldGetNull() + { + PHPUnit_Framework_Assert::assertNull($this->result); + } + + /** + * @When /^I push "([^"]*)" to that array$/ + */ + public function iPushToThatArray($arg1) + { + array_push($this->array, $arg1); + } + + /** + * @Then /^I should get "([^"]*)"$/ + */ + public function iShouldGet($arg1) + { + PHPUnit_Framework_Assert::assertEquals($arg1, $this->result); + } + + } + """ + And a file named "features/e_notice_in_scenario.feature" with: + """ + Feature: E_NOTICE in scenario + In order to test the BEHAT_ERROR_REPORTING constant + As a contributor of behat + I need to have a FeatureContext that throws E_NOTICE within steps. + + Background: + Given I have an empty array + + Scenario: Access undefined index + When I access array index 0 + Then I should get NULL + + Scenario: Access defined index + When I push "foo" to that array + And I access array index 0 + Then I should get "foo" + + """ + + Scenario: With default error reporting + When I run "behat -f progress --no-colors" + Then it should fail + And the output should contain: + """ + --- Failed steps: + + When I access array index 0 # features/e_notice_in_scenario.feature:10 + Notice: Undefined offset: 0 in features/bootstrap/FeatureContext.php line 24 + + 2 scenarios (1 passed, 1 failed) + 7 steps (5 passed, 1 failed, 1 skipped) + """ + + Scenario: With error reporting ignoring E_NOTICE + Given a file named "behat.yml" with: + """ + default: + calls: + error_reporting: 32759 + """ + When I run "behat -f progress --no-colors" + Then it should pass diff --git a/vendor/behat/behat/features/extensions.feature b/vendor/behat/behat/features/extensions.feature new file mode 100644 index 0000000..247c87c --- /dev/null +++ b/vendor/behat/behat/features/extensions.feature @@ -0,0 +1,124 @@ +Feature: Extensions + In order to provide additional functionality for Behat + As a developer + I need to be able to write simple extensions + + Background: + Given a file named "behat.yml" with: + """ + default: + extensions: + custom_extension.php: + param1: val1 + param2: val2 + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + extension = $parameters; + } + + /** @When this scenario executes */ + public function thisScenarioExecutes() {} + + /** @Then the extension should be loaded */ + public function theExtensionLoaded() { + PHPUnit_Framework_Assert::assertEquals(array('param1' => 'val1', 'param2' => 'val2'), $this->extension); + } + } + """ + And a file named "custom_extension.php" with: + """ + parameters = $parameters; + } + + public function supportsContext(Behat\Behat\Context\Context $context) + { + return true; + } + + public function initializeContext(Behat\Behat\Context\Context $context) + { + $context->setExtensionParameters($this->parameters); + } + } + + class CustomExtension implements Behat\Testwork\ServiceContainer\Extension { + public function getConfigKey() + { + return 'custom_extension'; + } + + public function configure(ArrayNodeDefinition $builder) + { + $builder->useAttributeAsKey('name')->prototype('variable'); + } + + public function initialize(Behat\Testwork\ServiceContainer\ExtensionManager $extensionManager) {} + + public function load(ContainerBuilder $container, array $config) + { + $definition = $container->register('custom_initializer', 'CustomInitializer', array($config)); + $definition->setArguments(array($config)); + $definition->addTag('context.initializer', array('priority' => 100)); + } + + public function process(ContainerBuilder $container) {} + } + + return new CustomExtension; + """ + And a file named "features/extensions.feature" with: + """ + Feature: + Scenario: + When this scenario executes + Then the extension should be loaded + """ + + Scenario: Extension should be successfully loaded + When I run "behat -f progress --append-snippets" + Then it should pass + + Scenario: Instantiating inexistent extension file + Given a file named "behat.yml" with: + """ + default: + extensions: + inexistent_extension: ~ + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + parameters = $parameters; + } + + /** + * @Given /^I have (\d+) apples?$/ + */ + public function iHaveApples($count) { + $this->apples = intval($count); + } + + /** + * @When /^I ate (\d+) apples?$/ + */ + public function iAteApples($count) { + $this->apples -= intval($count); + } + + /** + * @When /^I found (\d+) apples?$/ + */ + public function iFoundApples($count) { + $this->apples += intval($count); + } + + /** + * @Then /^I should have (\d+) apples$/ + */ + public function iShouldHaveApples($count) { + PHPUnit_Framework_Assert::assertEquals(intval($count), $this->apples); + } + + /** + * @Then /^context parameter "([^"]*)" should be equal to "([^"]*)"$/ + */ + public function contextParameterShouldBeEqualTo($key, $val) { + PHPUnit_Framework_Assert::assertEquals($val, $this->parameters[$key]); + } + + /** + * @Given /^context parameter "([^"]*)" should be array with (\d+) elements$/ + */ + public function contextParameterShouldBeArrayWithElements($key, $count) { + PHPUnit_Framework_Assert::assertInternalType('array', $this->parameters[$key]); + PHPUnit_Framework_Assert::assertEquals(2, count($this->parameters[$key])); + } + } + """ + And a file named "features/apples.feature" with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 3 apples + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + And do something undefined + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + | 2 | 2 | 3 | + + Scenario: Multilines + Given pystring: + ''' + some pystring + ''' + And table: + | col1 | col2 | + | val1 | val2 | + """ + + Scenario: --no-colors option + When I run "behat --no-colors" + Then it should fail with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: # features/apples.feature:6 + Given I have 3 apples # FeatureContext::iHaveApples() + + Scenario: I'm little hungry # features/apples.feature:9 + When I ate 1 apple # FeatureContext::iAteApples() + Then I should have 3 apples # FeatureContext::iShouldHaveApples() + Failed asserting that 2 matches expected 3. + + Scenario: Found more apples # features/apples.feature:13 + When I found 5 apples # FeatureContext::iFoundApples() + Then I should have 8 apples # FeatureContext::iShouldHaveApples() + + Scenario: Found more apples # features/apples.feature:17 + When I found 2 apples # FeatureContext::iFoundApples() + Then I should have 5 apples # FeatureContext::iShouldHaveApples() + And do something undefined + + Scenario Outline: Other situations # features/apples.feature:22 + When I ate apples # FeatureContext::iAteApples() + And I found apples # FeatureContext::iFoundApples() + Then I should have apples # FeatureContext::iShouldHaveApples() + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + Failed asserting that 7 matches expected 8. + | 2 | 2 | 3 | + + Scenario: Multilines # features/apples.feature:33 + Given pystring: + ''' + some pystring + ''' + And table: + | col1 | col2 | + | val1 | val2 | + + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^do something undefined$/ + */ + public function doSomethingUndefined() + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + """ + + Scenario: --no-paths option + When I run "behat --no-colors --format-settings='{\"paths\": false}'" + Then it should fail with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 3 apples + Failed asserting that 2 matches expected 3. + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + And do something undefined + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + Failed asserting that 7 matches expected 8. + | 2 | 2 | 3 | + + Scenario: Multilines + Given pystring: + ''' + some pystring + ''' + And table: + | col1 | col2 | + | val1 | val2 | + + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^do something undefined$/ + */ + public function doSomethingUndefined() + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + """ + + Scenario: --no-snippets option + When I run "behat --no-colors --no-snippets" + Then it should fail with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: # features/apples.feature:6 + Given I have 3 apples # FeatureContext::iHaveApples() + + Scenario: I'm little hungry # features/apples.feature:9 + When I ate 1 apple # FeatureContext::iAteApples() + Then I should have 3 apples # FeatureContext::iShouldHaveApples() + Failed asserting that 2 matches expected 3. + + Scenario: Found more apples # features/apples.feature:13 + When I found 5 apples # FeatureContext::iFoundApples() + Then I should have 8 apples # FeatureContext::iShouldHaveApples() + + Scenario: Found more apples # features/apples.feature:17 + When I found 2 apples # FeatureContext::iFoundApples() + Then I should have 5 apples # FeatureContext::iShouldHaveApples() + And do something undefined + + Scenario Outline: Other situations # features/apples.feature:22 + When I ate apples # FeatureContext::iAteApples() + And I found apples # FeatureContext::iFoundApples() + Then I should have apples # FeatureContext::iShouldHaveApples() + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + Failed asserting that 7 matches expected 8. + | 2 | 2 | 3 | + + Scenario: Multilines # features/apples.feature:33 + Given pystring: + ''' + some pystring + ''' + And table: + | col1 | col2 | + | val1 | val2 | + + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + """ + + Scenario: --expand option + When I run "behat --no-colors --format-settings='{\"expand\": true}'" + Then it should fail with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: # features/apples.feature:6 + Given I have 3 apples # FeatureContext::iHaveApples() + + Scenario: I'm little hungry # features/apples.feature:9 + When I ate 1 apple # FeatureContext::iAteApples() + Then I should have 3 apples # FeatureContext::iShouldHaveApples() + Failed asserting that 2 matches expected 3. + + Scenario: Found more apples # features/apples.feature:13 + When I found 5 apples # FeatureContext::iFoundApples() + Then I should have 8 apples # FeatureContext::iShouldHaveApples() + + Scenario: Found more apples # features/apples.feature:17 + When I found 2 apples # FeatureContext::iFoundApples() + Then I should have 5 apples # FeatureContext::iShouldHaveApples() + And do something undefined + + Scenario Outline: Other situations # features/apples.feature:22 + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | # features/apples.feature:29 + When I ate 3 apples # FeatureContext::iAteApples() + And I found 1 apples # FeatureContext::iFoundApples() + Then I should have 1 apples # FeatureContext::iShouldHaveApples() + | 0 | 4 | 8 | # features/apples.feature:30 + When I ate 0 apples # FeatureContext::iAteApples() + And I found 4 apples # FeatureContext::iFoundApples() + Then I should have 8 apples # FeatureContext::iShouldHaveApples() + Failed asserting that 7 matches expected 8. + | 2 | 2 | 3 | # features/apples.feature:31 + When I ate 2 apples # FeatureContext::iAteApples() + And I found 2 apples # FeatureContext::iFoundApples() + Then I should have 3 apples # FeatureContext::iShouldHaveApples() + + Scenario: Multilines # features/apples.feature:33 + Given pystring: + ''' + some pystring + ''' + And table: + | col1 | col2 | + | val1 | val2 | + + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^do something undefined$/ + */ + public function doSomethingUndefined() + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + """ + + Scenario: --no-multiline option + When I run "behat --no-colors --format-settings='{\"multiline\": false}'" + Then it should fail with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: # features/apples.feature:6 + Given I have 3 apples # FeatureContext::iHaveApples() + + Scenario: I'm little hungry # features/apples.feature:9 + When I ate 1 apple # FeatureContext::iAteApples() + Then I should have 3 apples # FeatureContext::iShouldHaveApples() + Failed asserting that 2 matches expected 3. + + Scenario: Found more apples # features/apples.feature:13 + When I found 5 apples # FeatureContext::iFoundApples() + Then I should have 8 apples # FeatureContext::iShouldHaveApples() + + Scenario: Found more apples # features/apples.feature:17 + When I found 2 apples # FeatureContext::iFoundApples() + Then I should have 5 apples # FeatureContext::iShouldHaveApples() + And do something undefined + + Scenario Outline: Other situations # features/apples.feature:22 + When I ate apples # FeatureContext::iAteApples() + And I found apples # FeatureContext::iFoundApples() + Then I should have apples # FeatureContext::iShouldHaveApples() + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + Failed asserting that 7 matches expected 8. + | 2 | 2 | 3 | + + Scenario: Multilines # features/apples.feature:33 + Given pystring: + ... + And table: + ... + + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^do something undefined$/ + */ + public function doSomethingUndefined() + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + """ diff --git a/vendor/behat/behat/features/hooks.feature b/vendor/behat/behat/features/hooks.feature new file mode 100644 index 0000000..557969e --- /dev/null +++ b/vendor/behat/behat/features/hooks.feature @@ -0,0 +1,516 @@ +Feature: hooks + In order to hook into Behat testing process + As a tester + I need to be able to write hooks + + Background: + Given a file named "behat.yml" with: + """ + default: + suites: + default: + parameters: + before_feature: BEFORE EVERY FEATURE + after_feature: AFTER EVERY FEATURE + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + getSuite()->getSetting('parameters'); + echo "= do something ".$params['before_feature']; + } + + /** + * @AfterFeature + */ + static public function doSomethingAfterFeature($event) { + $params = $event->getSuite()->getSetting('parameters'); + echo "= do something ".$params['after_feature']; + } + + /** + * @BeforeFeature @someFeature + */ + static public function doSomethingBeforeSomeFeature($event) { + echo "= do something before SOME feature"; + } + + /** + * @AfterFeature @someFeature + */ + static public function doSomethingAfterSomeFeature($event) { + echo "= do something after SOME feature"; + } + + /** + * @BeforeScenario + */ + public function beforeScenario($event) { + $this->number = 50; + } + + /** + * @BeforeScenario 130 + */ + public function beforeScenario130($event) { + $this->number = 130; + } + + /** + * @BeforeScenario @thirty + */ + public function beforeScenarioThirty($event) { + $this->number = 30; + } + + /** + * @BeforeScenario @exception + */ + public function beforeScenarioException($event) { + throw new \Exception('Exception'); + } + + /** + * @BeforeStep I must have 100 + */ + public function beforeStep100($event) { + $this->number = 100; + } + + /** + * @Given /^I have entered (\d+)$/ + */ + public function iHaveEntered($number) { + $this->number = intval($number); + } + + /** + * @Then /^I must have (\d+)$/ + */ + public function iMustHave($number) { + \PHPUnit_Framework_Assert::assertEquals(intval($number), $this->number); + } + } + """ + + Scenario: + Given a file named "features/test.feature" with: + """ + Feature: + Scenario: + Then I must have 50 + Scenario: + Given I have entered 12 + Then I must have 12 + + @thirty + Scenario: + Given I must have 30 + When I have entered 23 + Then I must have 23 + @100 @thirty + Scenario: + Given I must have 30 + When I have entered 1 + Then I must have 100 + + Scenario: 130 + Given I must have 130 + """ + When I run "behat --no-colors -f pretty" + Then it should pass with: + """ + ┌─ @BeforeFeature # FeatureContext::doSomethingBeforeFeature() + │ + │ = do something BEFORE EVERY FEATURE + │ + Feature: + + Scenario: # features/test.feature:2 + Then I must have 50 # FeatureContext::iMustHave() + + Scenario: # features/test.feature:4 + Given I have entered 12 # FeatureContext::iHaveEntered() + Then I must have 12 # FeatureContext::iMustHave() + + @thirty + Scenario: # features/test.feature:9 + Given I must have 30 # FeatureContext::iMustHave() + When I have entered 23 # FeatureContext::iHaveEntered() + Then I must have 23 # FeatureContext::iMustHave() + + @100 @thirty + Scenario: # features/test.feature:14 + Given I must have 30 # FeatureContext::iMustHave() + When I have entered 1 # FeatureContext::iHaveEntered() + Then I must have 100 # FeatureContext::iMustHave() + + Scenario: 130 # features/test.feature:19 + Given I must have 130 # FeatureContext::iMustHave() + + │ + │ = do something AFTER EVERY FEATURE + │ + └─ @AfterFeature # FeatureContext::doSomethingAfterFeature() + + 5 scenarios (5 passed) + 10 steps (10 passed) + """ + + Scenario: Filter features + Given a file named "features/1-one.feature" with: + """ + Feature: + Scenario: + Then I must have 50 + + Scenario: + Given I have entered 12 + Then I must have 12 + + Scenario: 130 + Given I must have 130 + """ + Given a file named "features/2-two.feature" with: + """ + @someFeature + Feature: + Scenario: 130 + Given I must have 130 + """ + When I run "behat --no-colors -f pretty" + Then it should pass with: + """ + ┌─ @BeforeFeature # FeatureContext::doSomethingBeforeFeature() + │ + │ = do something BEFORE EVERY FEATURE + │ + Feature: + + Scenario: # features/1-one.feature:2 + Then I must have 50 # FeatureContext::iMustHave() + + Scenario: # features/1-one.feature:5 + Given I have entered 12 # FeatureContext::iHaveEntered() + Then I must have 12 # FeatureContext::iMustHave() + + Scenario: 130 # features/1-one.feature:9 + Given I must have 130 # FeatureContext::iMustHave() + + │ + │ = do something AFTER EVERY FEATURE + │ + └─ @AfterFeature # FeatureContext::doSomethingAfterFeature() + + ┌─ @BeforeFeature # FeatureContext::doSomethingBeforeFeature() + │ + │ = do something BEFORE EVERY FEATURE + │ + ┌─ @BeforeFeature @someFeature # FeatureContext::doSomethingBeforeSomeFeature() + │ + │ = do something before SOME feature + │ + @someFeature + Feature: + + Scenario: 130 # features/2-two.feature:3 + Given I must have 130 # FeatureContext::iMustHave() + + │ + │ = do something AFTER EVERY FEATURE + │ + └─ @AfterFeature # FeatureContext::doSomethingAfterFeature() + + │ + │ = do something after SOME feature + │ + └─ @AfterFeature @someFeature # FeatureContext::doSomethingAfterSomeFeature() + + 4 scenarios (4 passed) + 5 steps (5 passed) + """ + + Scenario: Background step hooks + Given a file named "features/background.feature" with: + """ + Feature: + Background: + Given I must have 50 + + Scenario: + Given I have entered 12 + Then I must have 12 + """ + When I run "behat --no-colors -f pretty" + Then it should pass with: + """ + ┌─ @BeforeFeature # FeatureContext::doSomethingBeforeFeature() + │ + │ = do something BEFORE EVERY FEATURE + │ + Feature: + + Background: # features/background.feature:2 + Given I must have 50 # FeatureContext::iMustHave() + + Scenario: # features/background.feature:5 + Given I have entered 12 # FeatureContext::iHaveEntered() + Then I must have 12 # FeatureContext::iMustHave() + + │ + │ = do something AFTER EVERY FEATURE + │ + └─ @AfterFeature # FeatureContext::doSomethingAfterFeature() + + 1 scenario (1 passed) + 3 steps (3 passed) + """ + + Scenario: Background exceptions + Given a file named "features/background.feature" with: + """ + Feature: + + @exception + Scenario: + Then I must have 50 + Scenario: + Given I have entered 12 + Then I must have 12 + + @exception + Scenario: + Given I must have 30 + When I have entered 23 + Then I must have 23 + + Scenario: 130 + Given I must have 130 + """ + When I run "behat --no-colors -f pretty" + Then it should fail with: + """ + ┌─ @BeforeFeature # FeatureContext::doSomethingBeforeFeature() + │ + │ = do something BEFORE EVERY FEATURE + │ + Feature: + + ┌─ @BeforeScenario @exception # FeatureContext::beforeScenarioException() + │ + ╳ Exception (Exception) + │ + @exception + Scenario: # features/background.feature:4 + Then I must have 50 # FeatureContext::iMustHave() + + Scenario: # features/background.feature:6 + Given I have entered 12 # FeatureContext::iHaveEntered() + Then I must have 12 # FeatureContext::iMustHave() + + ┌─ @BeforeScenario @exception # FeatureContext::beforeScenarioException() + │ + ╳ Exception (Exception) + │ + @exception + Scenario: # features/background.feature:11 + Given I must have 30 # FeatureContext::iMustHave() + When I have entered 23 # FeatureContext::iHaveEntered() + Then I must have 23 # FeatureContext::iMustHave() + + Scenario: 130 # features/background.feature:16 + Given I must have 130 # FeatureContext::iMustHave() + + │ + │ = do something AFTER EVERY FEATURE + │ + └─ @AfterFeature # FeatureContext::doSomethingAfterFeature() + + --- Skipped scenarios: + + features/background.feature:4 + features/background.feature:11 + + 4 scenarios (2 passed, 2 skipped) + 7 steps (3 passed, 4 skipped) + """ + + Scenario: Step state doesn't affect after hooks + Given a file named "features/test.feature" with: + """ + Feature: + + Scenario: + Given passing step + + Scenario: + Given failing step + + Scenario: + Given passing step with failing hook + + @failing-before-hook + Scenario: + Given passing step + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + value = intval($number); + } + + /** + * @Then /Я должен иметь (\d+)/ + */ + public function iShouldHave($number) { + PHPUnit_Framework_Assert::assertEquals(intval($number), $this->value); + } + + /** + * @When /Я добавлю (\d+)/ + */ + public function iAdd($number) { + $this->value += intval($number); + } + + /** + * @When /^Что-то еще не сделано$/ + */ + public function somethingNotDone() { + throw new PendingException(); + } + } + """ + And a file named "features/World.feature" with: + """ + # language: ru + Функционал: Постоянство мира + Чтобы поддерживать стабильными тесты + Как разработчик функционала + Я хочу чтобы Мир сбрасывался между сценариями + + Предыстория: + Если Я ввел 10 + + Сценарий: Неопределен + То Я должен иметь 10 + И Добавить "нормальное" число + То Я должен иметь 10 + + Сценарий: В ожидании + То Я должен иметь 10 + И Что-то еще не сделано + То Я должен иметь 10 + + Сценарий: Провален + Если Я добавлю 4 + То Я должен иметь 13 + + Структура сценария: Пройдено и Провалено + Допустим Я должен иметь 10 + Если Я добавлю <значение> + То Я должен иметь <результат> + + Примеры: + | значение | результат | + | 5 | 16 | + | 10 | 20 | + | 23 | 32 | + """ + + Scenario: Pretty + When I run "behat --no-colors -f pretty --lang=ru" + Then it should fail with: + """ + Функционал: Постоянство мира + Чтобы поддерживать стабильными тесты + Как разработчик функционала + Я хочу чтобы Мир сбрасывался между сценариями + + Предыстория: # features/World.feature:7 + Если Я ввел 10 # FeatureContext::iHaveEntered() + + Сценарий: Неопределен # features/World.feature:10 + То Я должен иметь 10 # FeatureContext::iShouldHave() + И Добавить "нормальное" число + То Я должен иметь 10 # FeatureContext::iShouldHave() + + Сценарий: В ожидании # features/World.feature:15 + То Я должен иметь 10 # FeatureContext::iShouldHave() + И Что-то еще не сделано # FeatureContext::somethingNotDone() + TODO: write pending definition + То Я должен иметь 10 # FeatureContext::iShouldHave() + + Сценарий: Провален # features/World.feature:20 + Если Я добавлю 4 # FeatureContext::iAdd() + То Я должен иметь 13 # FeatureContext::iShouldHave() + Failed asserting that 14 matches expected 13. + + Структура сценария: Пройдено и Провалено # features/World.feature:24 + Допустим Я должен иметь 10 # FeatureContext::iShouldHave() + Если Я добавлю <значение> # FeatureContext::iAdd() + То Я должен иметь <результат> # FeatureContext::iShouldHave() + + Примеры: + | значение | результат | + | 5 | 16 | + Failed asserting that 15 matches expected 16. + | 10 | 20 | + | 23 | 32 | + Failed asserting that 33 matches expected 32. + + --- Проваленные сценарии: + + features/World.feature:20 + features/World.feature:31 + features/World.feature:33 + + 6 сценариев (1 пройден, 3 провалено, 1 не определен, 1 в ожидании) + 23 шага (16 пройдено, 3 провалено, 1 не определен, 1 в ожидании, 2 пропущено) + + --- FeatureContext не содержит необходимых определений. Вы можете добавить их используя шаблоны: + + /** + * @Then /^Добавить "([^"]*)" число$/ + */ + public function dobavitChislo($arg1) + { + throw new PendingException(); + } + """ + + Scenario: Progress + When I run "behat --no-colors -f progress --lang=ru" + Then it should fail with: + """ + ..U-..P-..F...F.......F + + --- Проваленные шаги: + + То Я должен иметь 13 # features/World.feature:22 + Failed asserting that 14 matches expected 13. + + То Я должен иметь 16 # features/World.feature:27 + Failed asserting that 15 matches expected 16. + + То Я должен иметь 32 # features/World.feature:27 + Failed asserting that 33 matches expected 32. + + --- Шаги в ожидании: + + И Что-то еще не сделано # FeatureContext::somethingNotDone() + TODO: write pending definition + + 6 сценариев (1 пройден, 3 провалено, 1 не определен, 1 в ожидании) + 23 шага (16 пройдено, 3 провалено, 1 не определен, 1 в ожидании, 2 пропущено) + + --- FeatureContext не содержит необходимых определений. Вы можете добавить их используя шаблоны: + + /** + * @Then /^Добавить "([^"]*)" число$/ + */ + public function dobavitChislo($arg1) + { + throw new PendingException(); + } + """ + + Scenario: Progress with unexisting locale + When I run "behat --no-colors -f progress --lang=xx" + Then it should fail with: + """ + ..U-..P-..F...F.......F + + --- Failed steps: + + То Я должен иметь 13 # features/World.feature:22 + Failed asserting that 14 matches expected 13. + + То Я должен иметь 16 # features/World.feature:27 + Failed asserting that 15 matches expected 16. + + То Я должен иметь 32 # features/World.feature:27 + Failed asserting that 33 matches expected 32. + + --- Pending steps: + + И Что-то еще не сделано # FeatureContext::somethingNotDone() + TODO: write pending definition + + 6 scenarios (1 passed, 3 failed, 1 undefined, 1 pending) + 23 steps (16 passed, 3 failed, 1 undefined, 1 pending, 2 skipped) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^Добавить "([^"]*)" число$/ + */ + public function dobavitChislo($arg1) + { + throw new PendingException(); + } + """ + + Scenario: Progress with unexisting locale + When I run "behat --no-colors -f progress --lang=xx" + Then it should fail with: + """ + ..U-..P-..F...F.......F + + --- Failed steps: + + То Я должен иметь 13 # features/World.feature:22 + Failed asserting that 14 matches expected 13. + + То Я должен иметь 16 # features/World.feature:27 + Failed asserting that 15 matches expected 16. + + То Я должен иметь 32 # features/World.feature:27 + Failed asserting that 33 matches expected 32. + + --- Pending steps: + + И Что-то еще не сделано # FeatureContext::somethingNotDone() + TODO: write pending definition + + 6 scenarios (1 passed, 3 failed, 1 undefined, 1 pending) + 23 steps (16 passed, 3 failed, 1 undefined, 1 pending, 2 skipped) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^Добавить "([^"]*)" число$/ + */ + public function dobavitChislo($arg1) + { + throw new PendingException(); + } + """ diff --git a/vendor/behat/behat/features/init.feature b/vendor/behat/behat/features/init.feature new file mode 100644 index 0000000..2023780 --- /dev/null +++ b/vendor/behat/behat/features/init.feature @@ -0,0 +1,82 @@ +Feature: Init + In order to be able to start fast + As a feature developer + I need to be able to init Behat path structure fast + + Scenario: Simple init + Given I am in the "init_test" path + When I run "behat --no-colors --init" + Then it should pass with: + """ + +d features - place your *.feature files here + +d features/bootstrap - place your context classes here + +f features/bootstrap/FeatureContext.php - place your definitions, transformations and hooks here + """ + And file "features/bootstrap/FeatureContext.php" should exist + + Scenario: Custom paths + Given I am in the "init_test2" path + And a file named "behat.yml" with: + """ + default: + autoload: %paths.base%/supp + suites: + default: + paths: [ %paths.base%/scenarios ] + contexts: [ CustomContext ] + """ + When I run "behat --no-colors --init" + Then it should pass with: + """ + +d scenarios - place your *.feature files here + +d supp - place your context classes here + +f supp/CustomContext.php - place your definitions, transformations and hooks here + """ + And file "supp/CustomContext.php" should exist + + Scenario: Multiple suites + Given I am in the "init_test3" path + And a file named "behat.yml" with: + """ + default: + autoload: %paths.base%/contexts + suites: + suite1: + paths: [ %paths.base%/scenarios1 ] + contexts: [ Custom1Context ] + suite2: + paths: [ %paths.base%/scenarios2 ] + contexts: [ Custom2Context ] + """ + When I run "behat --no-colors --init" + Then it should pass with: + """ + +d scenarios1 - place your *.feature files here + +d contexts - place your context classes here + +f contexts/Custom1Context.php - place your definitions, transformations and hooks here + +d scenarios2 - place your *.feature files here + +f contexts/Custom2Context.php - place your definitions, transformations and hooks here + """ + And file "contexts/Custom1Context.php" should exist + And file "contexts/Custom2Context.php" should exist + + Scenario: Contexts with arguments + Given I am in the "init_test2" path + And a file named "behat.yml" with: + """ + default: + autoload: %paths.base%/supp + suites: + default: + paths: [ %paths.base%/scenarios ] + contexts: + - CustomContext: [ 'a', 'b' ] + """ + When I run "behat --no-colors --init" + Then it should pass with: + """ + +d scenarios - place your *.feature files here + +d supp - place your context classes here + +f supp/CustomContext.php - place your definitions, transformations and hooks here + """ + And file "supp/CustomContext.php" should exist diff --git a/vendor/behat/behat/features/locale_configuration.feature b/vendor/behat/behat/features/locale_configuration.feature new file mode 100644 index 0000000..ad02924 --- /dev/null +++ b/vendor/behat/behat/features/locale_configuration.feature @@ -0,0 +1,48 @@ +Feature: Locale configuration + In order to display feature in custom language + As a feature writer + I need to be able to the locale inside the configuration file + + Background: + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + parameters = $parameters; + } + + /** + * @Given /^I have (\d+) apples?$/ + */ + public function iHaveApples($count) { + $this->apples = intval($count); + } + + /** + * @When /^I ate (\d+) apples?$/ + */ + public function iAteApples($count) { + $this->apples -= intval($count); + } + + /** + * @When /^I found (\d+) apples?$/ + */ + public function iFoundApples($count) { + $this->apples += intval($count); + } + + /** + * @Then /^I should have (\d+) apples$/ + */ + public function iShouldHaveApples($count) { + PHPUnit_Framework_Assert::assertEquals(intval($count), $this->apples); + } + + /** + * @Then /^context parameter "([^"]*)" should be equal to "([^"]*)"$/ + */ + public function contextParameterShouldBeEqualTo($key, $val) { + PHPUnit_Framework_Assert::assertEquals($val, $this->parameters[$key]); + } + + /** + * @Given /^context parameter "([^"]*)" should be array with (\d+) elements$/ + */ + public function contextParameterShouldBeArrayWithElements($key, $count) { + PHPUnit_Framework_Assert::assertInternalType('array', $this->parameters[$key]); + PHPUnit_Framework_Assert::assertEquals(2, count($this->parameters[$key])); + } + } + """ + And a file named "features/apples.feature" with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 3 apples + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + And do something undefined + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + | 2 | 2 | 3 | + + Scenario: Multilines + Given pystring: + ''' + some pystring + ''' + And table: + | col1 | col2 | + | val1 | val2 | + """ + + Scenario: 2 formats, default output + When I run "behat --no-colors -f pretty -f progress --format-settings='{\"multiline\": false}'" + Then it should fail with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: # features/apples.feature:6 + Given I have 3 apples # FeatureContext::iHaveApples() + . + Scenario: I'm little hungry # features/apples.feature:9 + When I ate 1 apple # FeatureContext::iAteApples() + . Then I should have 3 apples # FeatureContext::iShouldHaveApples() + Failed asserting that 2 matches expected 3. + F + Scenario: Found more apples # features/apples.feature:13 + . When I found 5 apples # FeatureContext::iFoundApples() + . Then I should have 8 apples # FeatureContext::iShouldHaveApples() + . + Scenario: Found more apples # features/apples.feature:17 + . When I found 2 apples # FeatureContext::iFoundApples() + . Then I should have 5 apples # FeatureContext::iShouldHaveApples() + . And do something undefined + U + .... Scenario Outline: Other situations # features/apples.feature:22 + When I ate apples # FeatureContext::iAteApples() + And I found apples # FeatureContext::iFoundApples() + Then I should have apples # FeatureContext::iShouldHaveApples() + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + ...F | 0 | 4 | 8 | + Failed asserting that 7 matches expected 8. + .... | 2 | 2 | 3 | + + Scenario: Multilines # features/apples.feature:33 + . Given pystring: + ... + U And table: + ... + U + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + + --- Failed steps: + + Then I should have 3 apples # features/apples.feature:11 + Failed asserting that 2 matches expected 3. + + Then I should have 8 apples # features/apples.feature:25 + Failed asserting that 7 matches expected 8. + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^do something undefined$/ + */ + public function doSomethingUndefined() + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + """ + + Scenario: 2 formats, same output + When I run "behat --no-colors -f pretty -f progress --out=std --format-settings='{\"multiline\": false}'" + Then it should fail with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: # features/apples.feature:6 + Given I have 3 apples # FeatureContext::iHaveApples() + . + Scenario: I'm little hungry # features/apples.feature:9 + When I ate 1 apple # FeatureContext::iAteApples() + . Then I should have 3 apples # FeatureContext::iShouldHaveApples() + Failed asserting that 2 matches expected 3. + F + Scenario: Found more apples # features/apples.feature:13 + . When I found 5 apples # FeatureContext::iFoundApples() + . Then I should have 8 apples # FeatureContext::iShouldHaveApples() + . + Scenario: Found more apples # features/apples.feature:17 + . When I found 2 apples # FeatureContext::iFoundApples() + . Then I should have 5 apples # FeatureContext::iShouldHaveApples() + . And do something undefined + U + .... Scenario Outline: Other situations # features/apples.feature:22 + When I ate apples # FeatureContext::iAteApples() + And I found apples # FeatureContext::iFoundApples() + Then I should have apples # FeatureContext::iShouldHaveApples() + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + ...F | 0 | 4 | 8 | + Failed asserting that 7 matches expected 8. + .... | 2 | 2 | 3 | + + Scenario: Multilines # features/apples.feature:33 + . Given pystring: + ... + U And table: + ... + U + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + + --- Failed steps: + + Then I should have 3 apples # features/apples.feature:11 + Failed asserting that 2 matches expected 3. + + Then I should have 8 apples # features/apples.feature:25 + Failed asserting that 7 matches expected 8. + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^do something undefined$/ + */ + public function doSomethingUndefined() + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + """ + + Scenario: 2 formats, write first to file + When I run "behat --no-colors -f pretty -o apples.pretty -f progress -o std --format-settings='{\"multiline\": false, \"paths\": false}'" + Then it should fail with: + """ + ..F......U.......F.....UU + + --- Failed steps: + + Then I should have 3 apples # features/apples.feature:11 + Failed asserting that 2 matches expected 3. + + Then I should have 8 apples # features/apples.feature:25 + Failed asserting that 7 matches expected 8. + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^do something undefined$/ + */ + public function doSomethingUndefined() + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + """ + And "apples.pretty" file should contain: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 3 apples + Failed asserting that 2 matches expected 3. + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + And do something undefined + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + Failed asserting that 7 matches expected 8. + | 2 | 2 | 3 | + + Scenario: Multilines + Given pystring: + ... + And table: + ... + + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + """ + + Scenario: 2 formats, write second to file + When I run "behat --no-colors -f pretty -o std --format=progress --out=apples.progress --format-settings='{\"multiline\": false, \"paths\": false}'" + Then it should fail with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 3 apples + Failed asserting that 2 matches expected 3. + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + And do something undefined + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + Failed asserting that 7 matches expected 8. + | 2 | 2 | 3 | + + Scenario: Multilines + Given pystring: + ... + And table: + ... + + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^do something undefined$/ + */ + public function doSomethingUndefined() + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + """ + And "apples.progress" file should contain: + """ + ..F......U.......F.....UU + + --- Failed steps: + + Then I should have 3 apples # features/apples.feature:11 + Failed asserting that 2 matches expected 3. + + Then I should have 8 apples # features/apples.feature:25 + Failed asserting that 7 matches expected 8. + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + """ + + Scenario: 2 formats, write both to files + When I run "behat --no-colors -f pretty -o app.pretty -f progress -o app.progress --format-settings='{\"multiline\": false, \"paths\": false}'" + Then it should fail with: + """ + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^do something undefined$/ + */ + public function doSomethingUndefined() + { + throw new PendingException(); + } + + /** + * @Given /^pystring:$/ + */ + public function pystring(PyStringNode $string) + { + throw new PendingException(); + } + + /** + * @Given /^table:$/ + */ + public function table(TableNode $table) + { + throw new PendingException(); + } + """ + And "app.pretty" file should contain: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 3 apples + Failed asserting that 2 matches expected 3. + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + And do something undefined + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + Failed asserting that 7 matches expected 8. + | 2 | 2 | 3 | + + Scenario: Multilines + Given pystring: + ... + And table: + ... + + --- Failed scenarios: + + features/apples.feature:9 + features/apples.feature:30 + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + """ + And "app.progress" file should contain: + """ + ..F......U.......F.....UU + + --- Failed steps: + + Then I should have 3 apples # features/apples.feature:11 + Failed asserting that 2 matches expected 3. + + Then I should have 8 apples # features/apples.feature:25 + Failed asserting that 7 matches expected 8. + + 7 scenarios (3 passed, 2 failed, 2 undefined) + 25 steps (20 passed, 2 failed, 3 undefined) + """ diff --git a/vendor/behat/behat/features/name_filters.feature b/vendor/behat/behat/features/name_filters.feature new file mode 100644 index 0000000..5195375 --- /dev/null +++ b/vendor/behat/behat/features/name_filters.feature @@ -0,0 +1,118 @@ +Feature: Name filters + In order to run only needed features + As a Behat user + I need to Behat support features & scenario/outline names filtering + + Background: + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + result = 0; + $this->numbers = array(); + } + + /** + * @Given /^I have entered (\d+)$/ + */ + public function iHaveEntered($number) { + $this->numbers[] = intval($number); + } + + /** + * @When /^I add$/ + */ + public function iAdd() { + foreach ($this->numbers as $number) { + $this->result += $number; + } + $this->numbers = array(); + } + + /** + * @When /^I sub$/ + */ + public function iSub() { + $this->result = array_shift($this->numbers); + foreach ($this->numbers as $number) { + $this->result -= $number; + } + $this->numbers = array(); + } + + /** + * @When /^I multiply$/ + */ + public function iMultiply() { + $this->result = array_shift($this->numbers); + foreach ($this->numbers as $number) { + $this->result *= $number; + } + $this->numbers = array(); + } + + /** + * @When /^I div$/ + */ + public function iDiv() { + $this->result = array_shift($this->numbers); + foreach ($this->numbers as $number) { + $this->result /= $number; + } + $this->numbers = array(); + } + + /** + * @Then /^The result should be (\d+)$/ + */ + public function theResultShouldBe($result) { + PHPUnit_Framework_Assert::assertEquals(intval($result), $this->result); + } + } + """ + + Scenario: Basic scenario outline + Given a file named "features/math.feature" with: + """ + Feature: Math + Background: + Given I have basic calculator + + Scenario Outline: + Given I have entered + And I have entered + When I add + Then The result should be + + Examples: + | number1 | number2 | result | + | 10 | 12 | 22 | + | 5 | 3 | 8 | + | 5 | 5 | 10 | + """ + When I run "behat --no-colors -f progress features/math.feature" + Then it should pass with: + """ + ............... + + 3 scenarios (3 passed) + 15 steps (15 passed) + """ + + Scenario: Multiple scenario outlines + Given a file named "features/math.feature" with: + """ + Feature: Math + Background: + Given I have basic calculator + + Scenario Outline: + Given I have entered + And I have entered + When I multiply + Then The result should be + + Examples: + | number1 | number2 | result | + | 10 | 12 | 120 | + | 5 | 3 | 15 | + + Scenario: + Given I have entered 10 + And I have entered 3 + When I sub + Then The result should be 7 + + Scenario Outline: + Given I have entered + And I have entered + When I div + Then The result should be + + Examples: + | number1 | number2 | result | + | 10 | 2 | 5 | + | 50 | 5 | 10 | + """ + When I run "behat --no-colors -f progress features/math.feature" + Then it should pass with: + """ + ......................... + + 5 scenarios (5 passed) + 25 steps (25 passed) + """ + + Scenario: Multiple scenario outlines with failing steps + Given a file named "features/math.feature" with: + """ + Feature: Math + Background: + Given I have basic calculator + + Scenario Outline: + Given I have entered + And I have entered + When I multiply + Then The result should be + + Examples: + | number1 | number2 | result | + | 10 | 12 | 120 | + | 5 | 4 | 15 | + + Scenario: + Given I have entered 10 + And I have entered 4 + When I sub + Then The result should be 7 + + Scenario Outline: + Given I have entered + And I have entered + When I div + Then The result should be + + Examples: + | number1 | number2 | result | + | 10 | 2 | 5 | + | 50 | 10 | 2 | + | 50 | 10 | 4 | + """ + When I run "behat --no-colors -f progress features/math.feature" + Then it should fail with: + """ + .........F....F.........F....F + + --- Failed steps: + + Then The result should be 15 # features/math.feature:9 + Failed asserting that 20 matches expected 15. + + Then The result should be 7 # features/math.feature:20 + Failed asserting that 6 matches expected 7. + + Then The result should be 2 # features/math.feature:26 + Failed asserting that 5 matches expected 2. + + Then The result should be 4 # features/math.feature:26 + Failed asserting that 5 matches expected 4. + + 6 scenarios (2 passed, 4 failed) + 30 steps (26 passed, 4 failed) + """ diff --git a/vendor/behat/behat/features/parameters.feature b/vendor/behat/behat/features/parameters.feature new file mode 100644 index 0000000..601054c --- /dev/null +++ b/vendor/behat/behat/features/parameters.feature @@ -0,0 +1,161 @@ +Feature: Parameters + In order to support different setups + As a tester + I need to be able to configure Behat through environment variable + + Background: + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + result = 0; + $this->numbers = array(); + } + + /** + * @Given /I have entered (\d+)/ + */ + public function iHaveEntered($number) { + $this->numbers[] = intval($number); + } + + /** + * @When /I add/ + */ + public function iAdd() { + $this->result = array_sum($this->numbers); + $this->numbers = array(); + } + + /** + * @When /I sub/ + */ + public function iSub() { + $this->result = array_shift($this->numbers); + $this->result -= array_sum($this->numbers); + $this->numbers = array(); + } + + /** + * @Then /The result should be (\d+)/ + */ + public function theResultShouldBe($result) { + PHPUnit_Framework_Assert::assertEquals($result, $this->result); + } + } + """ + And a file named "features/math.feature" with: + """ + Feature: Math + Background: + Given I have basic calculator + + Scenario Outline: + Given I have entered + And I have entered + When I add + Then The result should be + + Examples: + | number1 | number2 | result | + | 10 | 12 | 22 | + | 5 | 3 | 8 | + | 5 | 5 | 10 | + """ + And a file named "behat.yml" with: + """ + default: + formatters: + progress: ~ + """ + + Scenario: + When I run "behat --no-colors" + Then it should pass with: + """ + ............... + + 3 scenarios (3 passed) + 15 steps (15 passed) + """ + + Scenario: + Given "BEHAT_PARAMS" environment variable is set to: + """ + {"formatters": {"pretty": {"paths": false, "timer": false}}} + """ + And a file named "behat.yml" with: + """ + default: + formatters: ~ + """ + When I run "behat --no-colors -c unexistent" + Then it should pass with: + """ + Feature: Math + + Background: + Given I have basic calculator + + Scenario Outline: + Given I have entered + And I have entered + When I add + Then The result should be + + Examples: + | number1 | number2 | result | + | 10 | 12 | 22 | + | 5 | 3 | 8 | + | 5 | 5 | 10 | + + 3 scenarios (3 passed) + 15 steps (15 passed) + """ + + Scenario: + Given "BEHAT_PARAMS" environment variable is set to: + """ + {"formatters": {"pretty": {"timer": false}}} + """ + And a file named "behat.yml" with: + """ + default: + formatters: ~ + """ + When I run "behat --no-colors -c unexistent" + Then it should pass with: + """ + Feature: Math + + Background: # features/math.feature:2 + Given I have basic calculator # FeatureContext::iHaveBasicCalculator() + + Scenario Outline: # features/math.feature:5 + Given I have entered # FeatureContext::iHaveEntered() + And I have entered # FeatureContext::iHaveEntered() + When I add # FeatureContext::iAdd() + Then The result should be # FeatureContext::theResultShouldBe() + + Examples: + | number1 | number2 | result | + | 10 | 12 | 22 | + | 5 | 3 | 8 | + | 5 | 5 | 10 | + + 3 scenarios (3 passed) + 15 steps (15 passed) + """ diff --git a/vendor/behat/behat/features/pretty_format.feature b/vendor/behat/behat/features/pretty_format.feature new file mode 100644 index 0000000..d1a9d90 --- /dev/null +++ b/vendor/behat/behat/features/pretty_format.feature @@ -0,0 +1,484 @@ +Feature: Pretty Formatter + In order to debug features + As a feature writer + I need to have pretty formatter + + Scenario: Complex + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + value = $num; + } + + /** + * @Then /I must have (\d+)/ + */ + public function iMustHave($num) { + PHPUnit_Framework_Assert::assertEquals($num, $this->value); + } + + /** + * @When /I add (\d+)/ + */ + public function iAdd($num) { + $this->value += $num; + } + + /** + * @When /^Something not done yet$/ + */ + public function somethingNotDoneYet() { + throw new PendingException(); + } + } + """ + And a file named "features/World.feature" with: + """ + Feature: World consistency + In order to maintain stable behaviors + As a features developer + I want, that "World" flushes between scenarios + + Background: + Given I have entered 10 + + Scenario: Undefined + Then I must have 10 + And Something new + Then I must have 10 + + Scenario: Pending + Then I must have 10 + And Something not done yet + Then I must have 10 + + Scenario: Failed + When I add 4 + Then I must have 13 + + Scenario Outline: Passed & Failed + Given I must have 10 + When I add + Then I must have + + Examples: + | value | result | + | 5 | 16 | + | 10 | 20 | + | 23 | 32 | + """ + When I run "behat --no-colors -f pretty" + Then it should fail with: + """ + Feature: World consistency + In order to maintain stable behaviors + As a features developer + I want, that "World" flushes between scenarios + + Background: # features/World.feature:6 + Given I have entered 10 # FeatureContext::iHaveEntered() + + Scenario: Undefined # features/World.feature:9 + Then I must have 10 # FeatureContext::iMustHave() + And Something new + Then I must have 10 # FeatureContext::iMustHave() + + Scenario: Pending # features/World.feature:14 + Then I must have 10 # FeatureContext::iMustHave() + And Something not done yet # FeatureContext::somethingNotDoneYet() + TODO: write pending definition + Then I must have 10 # FeatureContext::iMustHave() + + Scenario: Failed # features/World.feature:19 + When I add 4 # FeatureContext::iAdd() + Then I must have 13 # FeatureContext::iMustHave() + Failed asserting that 14 matches expected '13'. + + Scenario Outline: Passed & Failed # features/World.feature:23 + Given I must have 10 # FeatureContext::iMustHave() + When I add # FeatureContext::iAdd() + Then I must have # FeatureContext::iMustHave() + + Examples: + | value | result | + | 5 | 16 | + Failed asserting that 15 matches expected '16'. + | 10 | 20 | + | 23 | 32 | + Failed asserting that 33 matches expected '32'. + + --- Failed scenarios: + + features/World.feature:19 + features/World.feature:30 + features/World.feature:32 + + 6 scenarios (1 passed, 3 failed, 1 undefined, 1 pending) + 23 steps (16 passed, 3 failed, 1 undefined, 1 pending, 2 skipped) + + --- FeatureContext has missing steps. Define them with these snippets: + + /** + * @Then /^Something new$/ + */ + public function somethingNew() + { + throw new PendingException(); + } + """ + + Scenario: Multiline titles + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + value = $num; + } + + /** + * @Then /I must have (\d+)/ + */ + public function iMustHave($num) { + PHPUnit_Framework_Assert::assertEquals($num, $this->value); + } + + /** + * @When /I (add|subtract) the value (\d+)/ + */ + public function iAddOrSubtract($op, $num) { + if ($op == 'add') + $this->value += $num; + elseif ($op == 'subtract') + $this->value -= $num; + } + } + """ + And a file named "features/World.feature" with: + """ + Feature: World consistency + In order to maintain stable behaviors + As a features developer + I want, that "World" flushes between scenarios + + Background: + Given I have entered 10 + + Scenario: Adding some interesting + value + Then I must have 10 + And I add the value 6 + Then I must have 16 + + Scenario: Subtracting + some + value + Then I must have 10 + And I subtract the value 6 + Then I must have 4 + """ + When I run "behat --no-colors -f pretty" + Then it should pass with: + """ + Feature: World consistency + In order to maintain stable behaviors + As a features developer + I want, that "World" flushes between scenarios + + Background: # features/World.feature:6 + Given I have entered 10 # FeatureContext::iHaveEntered() + + Scenario: Adding some interesting # features/World.feature:9 + value + Then I must have 10 # FeatureContext::iMustHave() + And I add the value 6 # FeatureContext::iAddOrSubtract() + Then I must have 16 # FeatureContext::iMustHave() + + Scenario: Subtracting # features/World.feature:15 + some + value + Then I must have 10 # FeatureContext::iMustHave() + And I subtract the value 6 # FeatureContext::iAddOrSubtract() + Then I must have 4 # FeatureContext::iMustHave() + + 2 scenarios (2 passed) + 8 steps (8 passed) + """ + + Scenario: Don't print undefined exceptions in outline + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + value); + } + + /** + * @When /I add "([^"]+)"/ + */ + public function iAdd($num) { + $this->value += intval(preg_replace('/[^\d]+/', '', $num)); + } + } + """ + And a file named "features/ls.feature" with: + """ + Feature: ls + In order to see the directory structure + As a UNIX user + I need to be able to list the current directory's contents + + Background: + Given I have a file named "foo" + + Scenario: List 2 files in a directory + Given I have a file named "bar" + When I run "ls" + Then I should see "bar" in output + And I should see "foo" in output + + Scenario: List 1 file and 1 dir + Given I have a directory named "dir" + When I run "ls" + Then I should see "dir" in output + And I should see "foo" in output + + Scenario Outline: + Given I have a named "" + When I run "ls" + Then I should see "" in output + And I should see "foo" in output + + Examples: + | object | name | + | file | bar | + | directory | dir | + """ + When I run "behat --no-colors features/ls.feature --no-snippets" + Then it should pass with: + """ + Feature: ls + In order to see the directory structure + As a UNIX user + I need to be able to list the current directory's contents + + Background: # features/ls.feature:6 + Given I have a file named "foo" + + Scenario: List 2 files in a directory # features/ls.feature:9 + Given I have a file named "bar" + When I run "ls" + Then I should see "bar" in output + And I should see "foo" in output + + Scenario: List 1 file and 1 dir # features/ls.feature:15 + Given I have a directory named "dir" + When I run "ls" + Then I should see "dir" in output + And I should see "foo" in output + + Scenario Outline: # features/ls.feature:21 + Given I have a named "" + When I run "ls" + Then I should see "" in output + And I should see "foo" in output + + Examples: + | object | name | + | file | bar | + | directory | dir | + + 4 scenarios (4 undefined) + 20 steps (20 undefined) + """ + + Scenario: Multiline titles + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + + Then I must have + + Examples: + | value | result | + | 5 | 16 | + | 10 | 20 | + | 23 | 32 | + """ + When I run "behat --no-colors -f pretty --no-snippets" + Then it should pass with: + """ + Feature: World consistency + In order to maintain stable behaviors + As a features developer + I want, that "World" flushes between scenarios + + Background: Some background # features/World.feature:6 + title + with + multiple lines + Given I have entered 10 + + Scenario: Undefined # features/World.feature:13 + scenario or + whatever + Then I must have 10 + And Something new + Then I must have 10 + + Scenario Outline: Passed & Failed # features/World.feature:20 + steps and other interesting stuff + he-he-he + Given I must have 10 + When I add + Then I must have + + Examples: + | value | result | + | 5 | 16 | + | 10 | 20 | + | 23 | 32 | + + 4 scenarios (4 undefined) + 16 steps (16 undefined) + """ + + Scenario: Background with failing step and 2 scenarios + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + result = 0; + $this->numbers = array(); + } + + /** + * @Given /I have entered (\d+)/ + */ + public function iHaveEntered($number) { + $this->numbers[] = intval($number); + } + + /** + * @When /I add/ + */ + public function iAdd() { + $this->result = array_sum($this->numbers); + $this->numbers = array(); + } + + /** + * @When /I sub/ + */ + public function iSub() { + $this->result = array_shift($this->numbers); + $this->result -= array_sum($this->numbers); + $this->numbers = array(); + } + + /** + * @Then /The result should be (\d+)/ + */ + public function theResultShouldBe($result) { + PHPUnit_Framework_Assert::assertEquals($result, $this->result); + } + } + """ + And a file named "features/math.feature" with: + """ + Feature: Math + Background: + Given I have basic calculator + + Scenario Outline: + Given I have entered + And I have entered + When I add + Then The result should be + + Examples: + | number1 | number2 | result | + | 10 | 12 | 22 | + | 5 | 3 | 8 | + | 5 | 5 | 10 | + """ + And a file named "pretty.yml" with: + """ + pretty: + formatters: + progress: false + pretty: ~ + """ + And a file named "behat.yml" with: + """ + default: + formatters: + pretty: false + progress: ~ + + pretty_without_paths: + formatters: + progress: false + pretty: + paths: false + + imports: + - pretty.yml + """ + + Scenario: + Given I run "behat --no-colors features/math.feature" + Then it should pass with: + """ + ............... + + 3 scenarios (3 passed) + 15 steps (15 passed) + """ + + Scenario: + Given I run "behat --no-colors --profile pretty_without_paths" + Then it should pass with: + """ + Feature: Math + + Background: + Given I have basic calculator + + Scenario Outline: + Given I have entered + And I have entered + When I add + Then The result should be + + Examples: + | number1 | number2 | result | + | 10 | 12 | 22 | + | 5 | 3 | 8 | + | 5 | 5 | 10 | + + 3 scenarios (3 passed) + 15 steps (15 passed) + """ + + Scenario: + Given I run "behat --no-colors --profile pretty" + Then it should pass with: + """ + Feature: Math + + Background: # features/math.feature:2 + Given I have basic calculator # FeatureContext::iHaveBasicCalculator() + + Scenario Outline: # features/math.feature:5 + Given I have entered # FeatureContext::iHaveEntered() + And I have entered # FeatureContext::iHaveEntered() + When I add # FeatureContext::iAdd() + Then The result should be # FeatureContext::theResultShouldBe() + + Examples: + | number1 | number2 | result | + | 10 | 12 | 22 | + | 5 | 3 | 8 | + | 5 | 5 | 10 | + + 3 scenarios (3 passed) + 15 steps (15 passed) + """ diff --git a/vendor/behat/behat/features/rerun.feature b/vendor/behat/behat/features/rerun.feature new file mode 100644 index 0000000..a6a92e4 --- /dev/null +++ b/vendor/behat/behat/features/rerun.feature @@ -0,0 +1,185 @@ +Feature: Rerun + In order to test only failed scenarios + As a feature developer + I need to have an ability to rerun failed previously scenarios + + Background: + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + parameters = $parameters; + } + + /** + * @Given /^I have (\d+) apples?$/ + */ + public function iHaveApples($count) { + $this->apples = intval($count); + } + + /** + * @When /^I ate (\d+) apples?$/ + */ + public function iAteApples($count) { + $this->apples -= intval($count); + } + + /** + * @When /^I found (\d+) apples?$/ + */ + public function iFoundApples($count) { + $this->apples += intval($count); + } + + /** + * @Then /^I should have (\d+) apples$/ + */ + public function iShouldHaveApples($count) { + PHPUnit_Framework_Assert::assertEquals(intval($count), $this->apples); + } + + /** + * @Then /^context parameter "([^"]*)" should be equal to "([^"]*)"$/ + */ + public function contextParameterShouldBeEqualTo($key, $val) { + PHPUnit_Framework_Assert::assertEquals($val, $this->parameters[$key]); + } + + /** + * @Given /^context parameter "([^"]*)" should be array with (\d+) elements$/ + */ + public function contextParameterShouldBeArrayWithElements($key, $count) { + PHPUnit_Framework_Assert::assertInternalType('array', $this->parameters[$key]); + PHPUnit_Framework_Assert::assertEquals(2, count($this->parameters[$key])); + } + } + """ + And a file named "features/apples.feature" with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 3 apples + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 8 | + | 2 | 2 | 3 | + """ + + Scenario: Run one feature with 2 failed and 3 passing scenarios + When I run "behat --no-colors -f progress features/apples.feature" + Then it should fail with: + """ + ..F.............F.... + + --- Failed steps: + + Then I should have 3 apples # features/apples.feature:11 + Failed asserting that 2 matches expected 3. + + Then I should have 8 apples # features/apples.feature:24 + Failed asserting that 7 matches expected 8. + + 6 scenarios (4 passed, 2 failed) + 21 steps (19 passed, 2 failed) + """ + + Scenario: Rerun only failed scenarios + Given I run "behat --no-colors -f progress features/apples.feature" + When I run "behat --no-colors -f progress features/apples.feature --rerun" + Then it should fail with: + """ + ..F...F + + --- Failed steps: + + Then I should have 3 apples # features/apples.feature:11 + Failed asserting that 2 matches expected 3. + + Then I should have 8 apples # features/apples.feature:24 + Failed asserting that 7 matches expected 8. + + 2 scenarios (2 failed) + 7 steps (5 passed, 2 failed) + """ + + Scenario: Fixing scenario removes it from the rerun log + Given I run "behat --no-colors -f progress features/apples.feature" + And there is a file named "features/apples.feature" with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 3 apples + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 7 | + | 2 | 2 | 3 | + """ + When I run "behat --no-colors -f progress features/apples.feature" + And I run "behat --no-colors -f progress features/apples.feature --rerun" + Then it should fail with: + """ + ..F + + --- Failed steps: + + Then I should have 3 apples # features/apples.feature:11 + Failed asserting that 2 matches expected 3. + + 1 scenario (1 failed) + 3 steps (2 passed, 1 failed) + """ diff --git a/vendor/behat/behat/features/result_types.feature b/vendor/behat/behat/features/result_types.feature new file mode 100644 index 0000000..ac22013 --- /dev/null +++ b/vendor/behat/behat/features/result_types.feature @@ -0,0 +1,493 @@ +Feature: Different result types + In order to differentiate feature statuses + As a feature writer + I need to be able to see different types of test results + + Scenario: Undefined steps + Given a file named "features/coffee.feature" with: + """ + Feature: Undefined coffee machine actions + In order to make clients happy + As a coffee machine factory + We need to be able to tell customers + about what coffee type is supported + + Background: + Given I have magically created 10$ + + Scenario: Buy incredible coffee + When I have chose "coffee with turkey" in coffee machine + Then I should have "turkey with coffee sauce" + + Scenario: Buy incredible tea + When I have chose "pizza tea" in coffee machine + Then I should have "pizza tea" + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + money += $money; + } + + /** + * @Then /^I should see (\d+)\$ on the screen$/ + */ + public function iShouldSee($money) { + PHPUnit_Framework_Assert::assertEquals($money, $this->money); + } + } + """ + When I run "behat --no-colors -f progress features/coffee.feature" + Then it should fail with: + """ + .F..F- + + --- Failed steps: + + Then I should see 12$ on the screen # features/coffee.feature:10 + Failed asserting that 10 matches expected '12'. + + Then I should see 31$ on the screen # features/coffee.feature:14 + Failed asserting that 30 matches expected '31'. + + 2 scenarios (2 failed) + 6 steps (3 passed, 2 failed, 1 skipped) + """ + + Scenario: Skipped steps + Given a file named "features/coffee.feature" with: + """ + Feature: Skipped coffee machine actions + In order to tell clients about failures faster + As a coffee machine + I need to be able to skip unneeded steps + + Background: + Given human bought coffee + + Scenario: I have no water + Given I have no water + And I have electricity + When I boil water + Then the coffee should be almost done + + Scenario: I have no electricity + Given I have water + And I have no electricity + When I boil water + Then the coffee should be almost done + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + money); + } + } + """ + When I run "behat --no-colors -f progress features/coffee.feature" + Then it should fail with: + """ + .F---..F-- + + --- Failed steps: + + Given I have no water # features/coffee.feature:10 + NO water in coffee machine!!! (Exception) + + And I have no electricity # features/coffee.feature:17 + NO electricity in coffee machine!!! (Exception) + + 2 scenarios (2 failed) + 10 steps (3 passed, 2 failed, 5 skipped) + """ + + Scenario: Ambiguous steps + Given a file named "features/coffee.feature" with: + """ + Feature: Ambiguous orders in coffee menu + In order to be able to chose concrete coffee type + As a coffee buyer + I need to be able to know about ambiguous decisions + + Scenario: Ambiguous coffee type + Given human have chosen "Latte" + Then I should make him "Latte" + """ + And a file named "features/bootstrap/FeatureContext.php" with: + """ + + And there is agent + When I erase agent 's memory + Then there should be agent + But there should not be agent + + [Examples|Scenarios]: + | agent1 | agent2 | + | D | M | + """ + + Scenario: Print story syntax in native language + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + + [К тому же|Также|И] there is agent + [Когда|Если] I erase agent 's memory + [Тогда|То] there should be agent + [Но|А] there should not be agent + + Примеры: + | agent1 | agent2 | + | D | M | + """ + + Scenario: Print available definitions + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + + +
+ + + /^I have (\d+) apples?$/ + /^у меня (\d+) яблоко?$/ + + + /^I found (\d+) apples?$/ + /^Я нашел (\d+) яблоко?$/ + + + + + """ + When I run "behat --no-colors -dl --lang=ru" + Then the output should contain: + """ + default | Given /^у меня (\d+) яблоко?$/ + default | When /^I ate (\d+) apples?$/ + default | When /^Я нашел (\d+) яблоко?$/ + default | Then /^I should have (\d+) apples$/ + """ + + Scenario: Print extended definitions info + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + + +
+ + + /^I have (\d+) apples?$/ + /^у меня (\d+) яблоко?$/ + + + /^I found (\d+) apples?$/ + /^Я нашел (\d+) яблоко?$/ + + + + + """ + When I run "behat --no-colors --lang=ru -d 'нашел'" + Then the output should contain: + """ + default | When /^Я нашел (\d+) яблоко?$/ + | at `FeatureContext::iFoundApples()` + """ diff --git a/vendor/behat/behat/features/tag_filters.feature b/vendor/behat/behat/features/tag_filters.feature new file mode 100644 index 0000000..e20a3be --- /dev/null +++ b/vendor/behat/behat/features/tag_filters.feature @@ -0,0 +1,305 @@ +Feature: Tags + In order to run only needed features + As a Behat user + I need to Behat support features & scenario/outline tags + + Background: + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + + + Examples: + | num | + | 31 | + | 32 | + + @normal + Scenario: + Given Some normal step N38 + + @fast + Scenario Outline: + Given Some fast step N + + Examples: + | num | + | 33 | + | 34 | + + @normal @fast + Scenario Outline: + Given Some normal step N + And Some fast step N37 + + Examples: + | num | + | 35 | + | 36 | + """ + And a file named "features/feature4.feature" with: + """ + Feature: Feature N4 + + @normal + Scenario: + Given Some normal step N41 + And Some fast step N42 + + @fast + Scenario: + Given Some slow step N43 + """ + + Scenario: Single tag + When I run "behat --no-colors -f pretty --tags '@slow' --format-settings='{\"paths\": false}'" + Then it should pass + And the output should contain: + """ + @slow + Feature: Feature N1 + + Background: + Given Some slow step N11 + + Scenario: + Given Some slow step N12 + And Some normal step N13 + + @fast + Scenario: + Given Some fast step N14 + """ + And the output should contain: + """ + Feature: Feature N2 + + Background: + Given Some normal step N21 + + @slow @fast + Scenario: + Given Some slow step N22 + And Some fast step N23 + """ + And the output should contain: + """ + Feature: Feature N3 + + Background: + Given Some normal step N21 + + @slow + Scenario Outline: + Given Some slow step N + + Examples: + | num | + | 31 | + | 32 | + """ + And the output should contain: + """ + 5 scenarios (5 passed) + 12 steps (12 passed) + """ + + Scenario: Or tags + When I run "behat --no-colors -f pretty --tags '@slow,@normal' --format-settings='{\"paths\": false}'" + Then it should pass + And the output should contain: + """ + @slow + Feature: Feature N1 + + Background: + Given Some slow step N11 + + Scenario: + Given Some slow step N12 + And Some normal step N13 + + @fast + Scenario: + Given Some fast step N14 + """ + And the output should contain: + """ + Feature: Feature N2 + + Background: + Given Some normal step N21 + + @slow @fast + Scenario: + Given Some slow step N22 + And Some fast step N23 + """ + And the output should contain: + """ + Feature: Feature N3 + + Background: + Given Some normal step N21 + + @slow + Scenario Outline: + Given Some slow step N + + Examples: + | num | + | 31 | + | 32 | + + @normal + Scenario: + Given Some normal step N38 + + @normal @fast + Scenario Outline: + Given Some normal step N + And Some fast step N37 + + Examples: + | num | + | 35 | + | 36 | + """ + And the output should contain: + """ + Feature: Feature N4 + + @normal + Scenario: + Given Some normal step N41 + And Some fast step N42 + """ + And the output should contain: + """ + 9 scenarios (9 passed) + 22 steps (22 passed) + """ + + + Scenario: Overriding behat.yml filters with CLI options + Given a file named "behat.yml" with: + """ + default: + gherkin: + filters: + tags: ~@slow + """ + When I run "behat --no-colors -f pretty --tags '@slow' --format-settings='{\"paths\": false}'" + Then it should pass + And the output should contain: + """ + @slow + Feature: Feature N1 + + Background: + Given Some slow step N11 + + Scenario: + Given Some slow step N12 + And Some normal step N13 + + @fast + Scenario: + Given Some fast step N14 + """ + And the output should contain: + """ + Feature: Feature N2 + + Background: + Given Some normal step N21 + + @slow @fast + Scenario: + Given Some slow step N22 + And Some fast step N23 + """ + And the output should contain: + """ + Feature: Feature N3 + + Background: + Given Some normal step N21 + + @slow + Scenario Outline: + Given Some slow step N + + Examples: + | num | + | 31 | + | 32 | + """ + And the output should contain: + """ + 5 scenarios (5 passed) + 12 steps (12 passed) + """ diff --git a/vendor/behat/behat/features/traits.feature b/vendor/behat/behat/features/traits.feature new file mode 100644 index 0000000..0c2157c --- /dev/null +++ b/vendor/behat/behat/features/traits.feature @@ -0,0 +1,98 @@ +@php-version @php5.4 +Feature: Support php 5.4 traits + In order to have much cleaner horizontal reusability + As a context developer + I need to be able to use definition traits in my context + + Background: + Given a file named "features/bootstrap/FeatureContext.php" with: + """ + apples = intval($count); + } + + /** + * @When /^I ate (\d+) apples?$/ + */ + public function iAteApples($count) { + $this->apples -= intval($count); + } + + /** + * @When /^I found (\d+) apples?$/ + */ + public function iFoundApples($count) { + $this->apples += intval($count); + } + + /** + * @Then /^I should have (\d+) apples$/ + */ + public function iShouldHaveApples($count) { + PHPUnit_Framework_Assert::assertEquals(intval($count), $this->apples); + } + } + """ + And a file named "features/apples.feature" with: + """ + Feature: Apples story + In order to eat apple + As a little kid + I need to have an apple in my pocket + + Background: + Given I have 3 apples + + Scenario: I'm little hungry + When I ate 1 apple + Then I should have 2 apples + + Scenario: Found more apples + When I found 5 apples + Then I should have 8 apples + + Scenario: Found more apples + When I found 2 apples + Then I should have 5 apples + + Scenario Outline: Other situations + When I ate apples + And I found apples + Then I should have apples + + Examples: + | ate | found | result | + | 3 | 1 | 1 | + | 0 | 4 | 7 | + | 2 | 2 | 3 | + """ + + Scenario: Run feature with failing scenarios + When I run "behat --no-colors -f progress" + Then it should pass with: + """ + ..................... + + 6 scenarios (6 passed) + 21 steps (21 passed) + """ diff --git a/vendor/behat/behat/i18n.php b/vendor/behat/behat/i18n.php new file mode 100644 index 0000000..7696765 --- /dev/null +++ b/vendor/behat/behat/i18n.php @@ -0,0 +1,184 @@ + array( + 'snippet_proposal_title' => '%1% has missing steps. Define them with these snippets:', + 'snippet_missing_title' => 'Snippets for the following steps in the %1% suite were not generated (check your configuration):', + 'skipped_scenarios_title' => 'Skipped scenarios:', + 'failed_scenarios_title' => 'Failed scenarios:', + 'failed_hooks_title' => 'Failed hooks:', + 'failed_steps_title' => 'Failed steps:', + 'pending_steps_title' => 'Pending steps:', + 'scenarios_count' => '{0} No scenarios|{1} 1 scenario|]1,Inf] %1% scenarios', + 'steps_count' => '{0} No steps|{1} 1 step|]1,Inf] %1% steps', + 'passed_count' => '[1,Inf] %1% passed', + 'failed_count' => '[1,Inf] %1% failed', + 'pending_count' => '[1,Inf] %1% pending', + 'undefined_count' => '[1,Inf] %1% undefined', + 'skipped_count' => '[1,Inf] %1% skipped', + ), + 'cs' => array( + 'snippet_proposal_title' => '%1% obsahuje chybné kroky. Definujte je za použití následujícího kódu:', + 'snippet_missing_title' => 'Snippety pro následující kroky v sadě %1% nebyly vygenerovány (zkontrolujte správnost konfigurace):', + 'failed_scenarios_title' => 'Chybné scénáře:', + 'failed_hooks_title' => 'Chybné hooky:', + 'failed_steps_title' => 'Chybné kroky:', + 'pending_steps_title' => 'Čekající kroky:', + 'scenarios_count' => '{0} Žádný scénář|{1} 1 scénář|{2,3,4} %1% scénáře|]4,Inf] %1% scénářů', + 'steps_count' => '{0} Žádné kroky|{1} 1 krok|{2,3,4} %1% kroky|]4,Inf] %1% kroků', + 'passed_count' => '{1} %1% prošel|{2,3,4} %1% prošly|]4,Inf] %1% prošlo', + 'failed_count' => '{1} %1% selhal|{2,3,4} %1% selhaly|]4,Inf] %1% selhalo', + 'pending_count' => '{1} %1% čeká|{2,3,4} %1% čekají|]4,Inf] %1% čeká', + 'undefined_count' => '{1} %1% nedefinován|{2,3,4} %1% nedefinovány|]4,Inf] %1% nedefinováno', + 'skipped_count' => '{1} %1% přeskočen|{2,3,4} %1% přeskočeny|]4,Inf] %1% přeskočeno', + ), + 'de' => array( + 'snippet_proposal_title' => '%1% hat fehlende Schritte. Definiere diese mit den folgenden Snippets:', + 'snippet_missing_title' => 'Snippets für die folgenden Schritte in der %1% Suite wurden nicht generiert (Konfiguration überprüfen):', + 'failed_scenarios_title' => 'Fehlgeschlagene Szenarien:', + 'failed_hooks_title' => 'Fehlgeschlagene Hooks:', + 'failed_steps_title' => 'Fehlgeschlagene Schritte:', + 'pending_steps_title' => 'Ausstehende Schritte:', + 'scenarios_count' => '{0} Kein Szenario|{1} 1 Szenario|]1,Inf] %1% Szenarien', + 'steps_count' => '{0} Kein Schritt|{1} 1 Schritt|]1,Inf] %1% Schritte', + 'passed_count' => '[1,Inf] %1% bestanden', + 'failed_count' => '[1,Inf] %1% fehlgeschlagen', + 'pending_count' => '[1,Inf] %1% ausstehend', + 'undefined_count' => '[1,Inf] %1% nicht definiert', + 'skipped_count' => '[1,Inf] %1% übersprungen', + ), + 'es' => array( + 'snippet_proposal_title' => 'A %1% le faltan pasos. Defínelos con estos pasos:', + 'snippet_missing_title' => 'Las plantillas para los siguientes pasos en %1% no fueron generadas (revisa tu configuración):', + 'failed_scenarios_title' => 'Escenarios fallidos:', + 'failed_hooks_title' => 'Hooks fallidos:', + 'failed_steps_title' => 'Pasos fallidos:', + 'pending_steps_title' => 'Pasos pendientes:', + 'scenarios_count' => '{0} Ningún escenario|{1} 1 escenario|]1,Inf] %1% escenarios', + 'steps_count' => '{0} Ningún paso|{1} 1 paso|]1,Inf] %1% pasos', + 'passed_count' => '[1,Inf] %1% pasaron', + 'failed_count' => '[1,Inf] %1% fallaron', + 'pending_count' => '[1,Inf] %1% pendientes', + 'undefined_count' => '[1,Inf] %1% por definir', + 'skipped_count' => '[1,Inf] %1% saltadas', + ), + 'fr' => array( + 'snippet_proposal_title' => '%1% a des étapes manquantes. Définissez-les avec les modèles suivants :', + 'snippet_missing_title' => 'Les modèles des étapes de la suite %1% n\'ont pas été générés (vérifiez votre configuration):', + 'failed_scenarios_title' => 'Scénarios échoués:', + 'failed_hooks_title' => 'Hooks échoués:', + 'failed_steps_title' => 'Etapes échouées:', + 'pending_steps_title' => 'Etapes en attente:', + 'scenarios_count' => '{0} Pas de scénario|{1} 1 scénario|]1,Inf] %1% scénarios', + 'steps_count' => '{0} Pas d\'étape|{1} 1 étape|]1,Inf] %1% étapes', + 'passed_count' => '[1,Inf] %1% succès', + 'failed_count' => '[1,Inf] %1% échecs', + 'pending_count' => '[1,Inf] %1% en attente', + 'undefined_count' => '[1,Inf] %1% indéfinis', + 'skipped_count' => '[1,Inf] %1% ignorés', + ), + 'it' => array( + 'snippet_proposal_title' => '%1% ha dei passaggi mancanti. Definiscili con questi snippet:', + 'snippet_missing_title' => 'Gli snippet per i seguenti passaggi della suite %1% non sono stati generati (verifica la configurazione):', + 'failed_scenarios_title' => 'Scenari falliti:', + 'failed_hooks_title' => 'Hook falliti:', + 'failed_steps_title' => 'Passaggi falliti:', + 'pending_steps_title' => 'Passaggi in sospeso:', + 'scenarios_count' => '{0} Nessuno scenario|{1} 1 scenario|]1,Inf] %1% scenari', + 'steps_count' => '{0} Nessun passaggio|{1} 1 passaggio|]1,Inf] %1% passaggi', + 'passed_count' => '{1} 1 superato|]1,Inf] %1% superati', + 'failed_count' => '{1} 1 fallito|]1,Inf] %1% falliti', + 'pending_count' => '[1,Inf] %1% in sospeso', + 'undefined_count' => '{1} 1 non definito|]1,Inf] %1% non definiti', + 'skipped_count' => '{1} 1 ignorato|]1,Inf] %1% ignorati', + ), + 'nl' => array( + 'snippet_proposal_title' => 'Ontbrekende stappen in %1%. Definieer ze met de volgende fragmenten:', + 'snippet_missing_title' => 'Fragmenten voor de volgende stappen in de %1% suite werden niet gegenereerd (controleer de configuratie):', + 'failed_scenarios_title' => 'Gefaalde scenario\'s:', + 'failed_hooks_title' => 'Gefaalde hooks:', + 'failed_steps_title' => 'Gefaalde stappen:', + 'pending_steps_title' => 'Onafgewerkte stappen:', + 'scenarios_count' => '{0} Geen scenario\'s|{1} 1 scenario|]1,Inf] %1% scenario\'s', + 'steps_count' => '{0} Geen stappen|{1} 1 stap|]1,Inf] %1% stappen', + 'passed_count' => '[1,Inf] %1% geslaagd', + 'failed_count' => '[1,Inf] %1% gefaald', + 'pending_count' => '[1,Inf] %1% wachtende', + 'undefined_count' => '[1,Inf] %1% niet gedefinieerd', + 'skipped_count' => '[1,Inf] %1% overgeslagen', + ), + 'no' => array( + 'snippet_proposal_title' => '%1% mangler steg. Definer dem med disse snuttene:', + 'snippet_missing_title' => 'Snutter for de følgende stegene i %1%-samlingen ble ikke laget. (Sjekk konfigurasjonen din.):', + 'failed_scenarios_title' => 'Feilende scenarier:', + 'failed_hooks_title' => 'Feilende hooks:', + 'failed_steps_title' => 'Feilende steg:', + 'pending_steps_title' => 'Ikke implementerte steg:', + 'scenarios_count' => '{0} Ingen scenarier|{1} 1 scenario|]1,Inf] %1% scenarier', + 'steps_count' => '{0} Ingen steg|{1} 1 steg|]1,Inf] %1% steg', + 'passed_count' => '[1,Inf] %1% ok', + 'failed_count' => '[1,Inf] %1% feilet', + 'pending_count' => '[1,Inf] %1% ikke implementert', + 'undefined_count' => '[1,Inf] %1% ikke definert', + 'skipped_count' => '[1,Inf] %1% hoppet over', + ), + 'pl' => array( + 'snippet_proposal_title' => '%1% zawiera brakujące kroki. Utwórz je korzystając z tych fragmentów kodu:', + 'snippet_missing_title' => 'Fragmenty kodu dla następujących kroków %1% nie zostały wygenerowane (sprawdź swoją konfigurację):', + 'failed_scenarios_title' => 'Nieudane scenariusze:', + 'failed_hooks_title' => 'Nieudane hooki:', + 'failed_steps_title' => 'Nieudane kroki', + 'pending_steps_title' => 'Oczekujące kroki', + 'scenarios_count' => '{0} Brak scenariuszy|{1} 1 scenariusz|{2,3,4,22,23,24,32,33,34,42,43,44} %1% scenariusze|]4,Inf] %1% scenariuszy', + 'steps_count' => '{0} Brak kroków|{1} 1 krok|{2,3,4,22,23,24,32,33,34,42,43,44} %1% kroki|]4,Inf] %1% kroków', + 'passed_count' => '{1} %1% udany|{2,3,4,22,23,24,32,33,34,42,43,44} %1% udane|]4,Inf] %1% udanych', + 'failed_count' => '{1} %1% nieudany|{2,3,4,22,23,24,32,33,34,42,43,44} %1% nieudane|]4,Inf] %1% nieudanych', + 'pending_count' => '{1} %1% oczekujący|{2,3,4,22,23,24,32,33,34,42,43,44} %1% oczekujące|]4,Inf] %1% oczekujących', + 'undefined_count' => '{1} %1% niezdefiniowany|{2,3,4,22,23,24,32,33,34,42,43,44} %1% niezdefiniowane|]4,Inf] %1% niezdefiniowanych', + 'skipped_count' => '{1} %1% pominięty|{2,3,4,22,23,24,32,33,34,42,43,44} %1% pominięte|]4,Inf] %1% pominiętych', + ), + 'pt' => array( + 'snippet_proposal_title' => '%1% contém definições em falta. Defina-as com estes exemplos:', + 'snippet_missing_title' => 'Os exemplos para as seguintes definições da suite %1% não foram gerados (verifique a configuração):', + 'failed_scenarios_title' => 'Cenários que falharam:', + 'failed_hooks_title' => 'Hooks que falharam:', + 'failed_steps_title' => 'Definições que falharam:', + 'pending_steps_title' => 'Definições por definir:', + 'scenarios_count' => '{0} Nenhum cenário|{1} 1 cenário|]1,Inf] %1% cenários', + 'steps_count' => '{0} Nenhuma definição|{1} 1 definição|]1,Inf] %1% definições', + 'passed_count' => '{1} passou|]1,Inf] %1% passaram', + 'failed_count' => '{1} falhou|]1,Inf] %1% falharam', + 'pending_count' => '[1,Inf] %1% por definir', + 'undefined_count' => '{1} indefinido|]1,Inf] %1% indefinidos', + 'skipped_count' => '{1} omitido|]1,Inf] %1% omitidos', + ), + 'pt-BR' => array( + 'snippet_proposal_title' => '%1% possue etapas faltando. Defina elas com esse(s) trecho(s) de código:', + 'snippet_missing_title' => 'Trecho de códigos para as seguintes etapas em %1% suite não foram geradas (verique sua configuração):', + 'failed_scenarios_title' => 'Cenários falhados:', + 'failed_hooks_title' => 'Hooks falhados:', + 'failed_steps_title' => 'Etapas falhadas:', + 'pending_steps_title' => 'Etapas pendentes:', + 'scenarios_count' => '{0} Nenhum cenário|{1} 1 cenário|]1,Inf] %1% cenários', + 'steps_count' => '{0} Nenhuma etapa|{1} 1 etapa|]1,Inf] %1% etapas', + 'passed_count' => '[1,Inf] %1% passou', + 'failed_count' => '[1,Inf] %1% falhou', + 'pending_count' => '[1,Inf] %1% pendente', + 'undefined_count' => '[1,Inf] %1% indefinido', + 'skipped_count' => '[1,Inf] %1% pulado', + ), + 'ru' => array( + 'snippet_proposal_title' => '%1% не содержит необходимых определений. Вы можете добавить их используя шаблоны:', + 'snippet_missing_title' => 'Шаблоны для следующих шагов в среде %1% не были сгенерированы (проверьте ваши настройки):', + 'skipped_scenarios_title' => 'Пропущенные сценарии:', + 'failed_scenarios_title' => 'Проваленные сценарии:', + 'failed_hooks_title' => 'Проваленные хуки:', + 'failed_steps_title' => 'Проваленные шаги:', + 'pending_steps_title' => 'Шаги в ожидании:', + 'scenarios_count' => '{0} Нет сценариев|{1,21,31} %1% сценарий|{2,3,4,22,23,24} %1% сценария|]4,Inf] %1% сценариев', + 'steps_count' => '{0} Нет шагов|{1,21,31} %1% шаг|{2,3,4,22,23,24} %1% шага|]4,Inf] %1% шагов', + 'passed_count' => '{1,21,31} %1% пройден|]1,Inf] %1% пройдено', + 'failed_count' => '{1,21,31} %1% провален|]1,Inf] %1% провалено', + 'pending_count' => '[1,Inf] %1% в ожидании', + 'undefined_count' => '{1,21,31} %1% не определен|]1,Inf] %1% не определено', + 'skipped_count' => '{1,21,31} %1% пропущен|]1,Inf] %1% пропущено', + ), +); diff --git a/vendor/behat/behat/phpunit.xml.dist b/vendor/behat/behat/phpunit.xml.dist new file mode 100644 index 0000000..42f1ce4 --- /dev/null +++ b/vendor/behat/behat/phpunit.xml.dist @@ -0,0 +1,15 @@ + + + + + + ./tests/Behat/ + + + + + + ./src/Behat/ + + + diff --git a/vendor/behat/behat/src/Behat/Behat/ApplicationFactory.php b/vendor/behat/behat/src/Behat/Behat/ApplicationFactory.php new file mode 100644 index 0000000..3c2e7d3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/ApplicationFactory.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat; + +use Behat\Behat\Context\ServiceContainer\ContextExtension; +use Behat\Behat\Definition\ServiceContainer\DefinitionExtension; +use Behat\Behat\EventDispatcher\ServiceContainer\EventDispatcherExtension; +use Behat\Behat\Gherkin\ServiceContainer\GherkinExtension; +use Behat\Behat\Hook\ServiceContainer\HookExtension; +use Behat\Behat\Output\ServiceContainer\Formatter\PrettyFormatterFactory; +use Behat\Behat\Output\ServiceContainer\Formatter\ProgressFormatterFactory; +use Behat\Behat\Snippet\ServiceContainer\SnippetExtension; +use Behat\Behat\Tester\ServiceContainer\TesterExtension; +use Behat\Behat\Transformation\ServiceContainer\TransformationExtension; +use Behat\Behat\Translator\ServiceContainer\GherkinTranslationsExtension; +use Behat\Testwork\ApplicationFactory as BaseFactory; +use Behat\Testwork\Argument\ServiceContainer\ArgumentExtension; +use Behat\Testwork\Autoloader\ServiceContainer\AutoloaderExtension; +use Behat\Testwork\Call\ServiceContainer\CallExtension; +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\Environment\ServiceContainer\EnvironmentExtension; +use Behat\Testwork\Exception\ServiceContainer\ExceptionExtension; +use Behat\Testwork\Filesystem\ServiceContainer\FilesystemExtension; +use Behat\Testwork\Output\ServiceContainer\Formatter\FormatterFactory; +use Behat\Testwork\Output\ServiceContainer\OutputExtension; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Specification\ServiceContainer\SpecificationExtension; +use Behat\Testwork\Suite\ServiceContainer\SuiteExtension; +use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension; + +/** + * Defines the way behat is created. + * + * @author Konstantin Kudryashov + */ +final class ApplicationFactory extends BaseFactory +{ + const VERSION = '3.0.15'; + + /** + * {@inheritdoc} + */ + protected function getName() + { + return 'behat'; + } + + /** + * {@inheritdoc} + */ + protected function getVersion() + { + return self::VERSION; + } + + /** + * {@inheritdoc} + */ + protected function getDefaultExtensions() + { + $processor = new ServiceProcessor(); + + return array( + new ArgumentExtension(), + new AutoloaderExtension(array('' => '%paths.base%/features/bootstrap')), + new SuiteExtension($processor), + new OutputExtension('pretty', $this->getDefaultFormatterFactories($processor), $processor), + new ExceptionExtension($processor), + new GherkinExtension($processor), + new CallExtension($processor), + new TranslatorExtension(), + new GherkinTranslationsExtension(), + new TesterExtension($processor), + new CliExtension($processor), + new EnvironmentExtension($processor), + new SpecificationExtension($processor), + new FilesystemExtension(), + new ContextExtension($processor), + new SnippetExtension($processor), + new DefinitionExtension($processor), + new EventDispatcherExtension($processor), + new HookExtension(), + new TransformationExtension($processor), + ); + } + + /** + * {@inheritdoc} + */ + protected function getEnvironmentVariableName() + { + return 'BEHAT_PARAMS'; + } + + /** + * {@inheritdoc} + */ + protected function getConfigPath() + { + $cwd = rtrim(getcwd(), DIRECTORY_SEPARATOR); + $paths = array_filter( + array( + $cwd . DIRECTORY_SEPARATOR . 'behat.yml', + $cwd . DIRECTORY_SEPARATOR . 'behat.yml.dist', + $cwd . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'behat.yml', + $cwd . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'behat.yml.dist', + ), + 'is_file' + ); + + if (count($paths)) { + return current($paths); + } + + return null; + } + + /** + * Returns default formatter factories. + * + * @param ServiceProcessor $processor + * + * @return FormatterFactory[] + */ + private function getDefaultFormatterFactories(ServiceProcessor $processor) + { + return array( + new PrettyFormatterFactory($processor), + new ProgressFormatterFactory($processor), + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Annotation/AnnotationReader.php b/vendor/behat/behat/src/Behat/Behat/Context/Annotation/AnnotationReader.php new file mode 100644 index 0000000..84f7ac9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Annotation/AnnotationReader.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Annotation; + +use Behat\Behat\Context\Reader\AnnotatedContextReader; +use Behat\Testwork\Call\Callee; +use ReflectionMethod; + +/** + * Reads custom annotation of a provided context method into a Callee. + * + * @see AnnotatedContextReader + * + * @author Konstantin Kudryashov + */ +interface AnnotationReader +{ + /** + * Reads all callees associated with a provided method. + * + * @param string $contextClass + * @param ReflectionMethod $method + * @param string $docLine + * @param string $description + * + * @return null|Callee + */ + public function readCallee($contextClass, ReflectionMethod $method, $docLine, $description); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Argument/ArgumentResolver.php b/vendor/behat/behat/src/Behat/Behat/Context/Argument/ArgumentResolver.php new file mode 100644 index 0000000..e218276 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Argument/ArgumentResolver.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Argument; + +use Behat\Behat\Context\Environment\Handler\ContextEnvironmentHandler; +use ReflectionClass; + +/** + * Resolves arguments of context constructors. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +interface ArgumentResolver +{ + /** + * Resolves context constructor arguments. + * + * @param ReflectionClass $classReflection + * @param mixed[] $arguments + * + * @return mixed[] + */ + public function resolveArguments(ReflectionClass $classReflection, array $arguments); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Context.php b/vendor/behat/behat/src/Behat/Behat/Context/Context.php new file mode 100644 index 0000000..b9ac895 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Context.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context; + +/** + * Marks a custom user-defined class as a behat context. + * + * @author Konstantin Kudryashov + */ +interface Context +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/ClassGenerator.php b/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/ClassGenerator.php new file mode 100644 index 0000000..d2a7409 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/ClassGenerator.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\ContextClass; + +use Behat\Behat\Context\Suite\Setup\SuiteWithContextsSetup; +use Behat\Testwork\Suite\Suite; + +/** + * Generates context classes (as a string). + * + * @see SuiteWithContextsSetup + * + * @author Konstantin Kudryashov + */ +interface ClassGenerator +{ + /** + * Checks if generator supports provided context class. + * + * @param Suite $suite + * @param string $contextClass + * + * @return Boolean + */ + public function supportsSuiteAndClass(Suite $suite, $contextClass); + + /** + * Generates context class code. + * + * @param Suite $suite + * @param string $contextClass + * + * @return string The context class source code + */ + public function generateClass(Suite $suite, $contextClass); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/ClassResolver.php b/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/ClassResolver.php new file mode 100644 index 0000000..464f68f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/ClassResolver.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\ContextClass; + +use Behat\Behat\Context\Environment\Handler\ContextEnvironmentHandler; + +/** + * Resolves arbitrary context strings into a context classes. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +interface ClassResolver +{ + /** + * Checks if resolvers supports provided class. + * + * @param string $contextString + * + * @return Boolean + */ + public function supportsClass($contextString); + + /** + * Resolves context class. + * + * @param string $contextClass + * + * @return string + */ + public function resolveClass($contextClass); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/SimpleClassGenerator.php b/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/SimpleClassGenerator.php new file mode 100644 index 0000000..fad5419 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/SimpleClassGenerator.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\ContextClass; + +use Behat\Testwork\Suite\Suite; + +/** + * Generates basic PHP 5.3+ class with an optional namespace. + * + * @author Konstantin Kudryashov + */ +final class SimpleClassGenerator implements ClassGenerator +{ + /** + * @var string + */ + protected static $template = <<<'PHP' + $namespace, + '{className}' => $contextClass, + ) + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/ContextFactory.php b/vendor/behat/behat/src/Behat/Behat/Context/ContextFactory.php new file mode 100644 index 0000000..da515e0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/ContextFactory.php @@ -0,0 +1,139 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context; + +use Behat\Behat\Context\Argument\ArgumentResolver; +use Behat\Behat\Context\Initializer\ContextInitializer; +use Behat\Testwork\Argument\ArgumentOrganiser; +use ReflectionClass; + +/** + * Instantiates contexts using registered argument resolvers and context initializers. + * + * @author Konstantin Kudryashov + */ +final class ContextFactory +{ + /** + * @var ArgumentOrganiser + */ + private $argumentOrganiser; + /** + * @var ArgumentResolver[] + */ + private $argumentResolvers = array(); + /** + * @var ContextInitializer[] + */ + private $contextInitializers = array(); + + /** + * Initialises factory. + * + * @param ArgumentOrganiser $argumentOrganiser + */ + public function __construct(ArgumentOrganiser $argumentOrganiser) + { + $this->argumentOrganiser = $argumentOrganiser; + } + + /** + * Registers context argument resolver. + * + * @param ArgumentResolver $resolver + */ + public function registerArgumentResolver(ArgumentResolver $resolver) + { + $this->argumentResolvers[] = $resolver; + } + + /** + * Registers context initializer. + * + * @param ContextInitializer $initializer + */ + public function registerContextInitializer(ContextInitializer $initializer) + { + $this->contextInitializers[] = $initializer; + } + + /** + * Creates and initializes context class. + * + * @param string $class + * @param array $arguments + * + * @return Context + */ + public function createContext($class, array $arguments = array()) + { + $reflection = new ReflectionClass($class); + $arguments = $this->createArguments($reflection, $arguments); + $context = $this->createInstance($reflection, $arguments); + $this->initializeInstance($context); + + return $context; + } + + /** + * Resolves arguments for a specific class using registered argument resolvers. + * + * @param ReflectionClass $reflection + * @param array $arguments + * + * @return mixed[] + */ + private function createArguments(ReflectionClass $reflection, array $arguments) + { + foreach ($this->argumentResolvers as $resolver) { + $arguments = $resolver->resolveArguments($reflection, $arguments); + } + + if (!$reflection->hasMethod('__construct') || !count($arguments)) { + return $arguments; + } + + $constructor = $reflection->getConstructor(); + + return $this->argumentOrganiser->organiseArguments($constructor, $arguments); + } + + /** + * Creates context instance. + * + * @param ReflectionClass $reflection + * @param array $arguments + * + * @return Context + */ + private function createInstance(ReflectionClass $reflection, array $arguments) + { + if (count($arguments)) { + return $reflection->newInstanceArgs($arguments); + } + + return $reflection->newInstance(); + } + + /** + * Initializes context class and returns new context instance. + * + * @param Context $context + * + * @return Context + */ + private function initializeInstance(Context $context) + { + foreach ($this->contextInitializers as $initializer) { + $initializer->initializeContext($context); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/CustomSnippetAcceptingContext.php b/vendor/behat/behat/src/Behat/Behat/Context/CustomSnippetAcceptingContext.php new file mode 100644 index 0000000..db646ce --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/CustomSnippetAcceptingContext.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context; + +use Behat\Behat\Context\Snippet\Generator\ContextSnippetGenerator; + +/** + * Context that implements this interface is treated as a custom-snippet-friendly context. + * + * @see ContextSnippetGenerator + * + * @author Konstantin Kudryashov + */ +interface CustomSnippetAcceptingContext extends SnippetAcceptingContext +{ + /** + * Returns type of the snippets that this context accepts. + * + * Behat implements a couple of types by default: "regex" and "turnip" + * + * @return string + */ + public static function getAcceptedSnippetType(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Environment/ContextEnvironment.php b/vendor/behat/behat/src/Behat/Behat/Context/Environment/ContextEnvironment.php new file mode 100644 index 0000000..690eebb --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Environment/ContextEnvironment.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Environment; + +use Behat\Behat\Context\Environment\Handler\ContextEnvironmentHandler; +use Behat\Testwork\Environment\Environment; + +/** + * Represents test environment based on a collection of contexts. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +interface ContextEnvironment extends Environment +{ + /** + * Checks if environment has any contexts registered. + * + * @return Boolean + */ + public function hasContexts(); + + /** + * Returns list of registered context classes. + * + * @return string[] + */ + public function getContextClasses(); + + /** + * Checks if environment contains context with the specified class name. + * + * @param string $class + * + * @return Boolean + */ + public function hasContextClass($class); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Environment/Handler/ContextEnvironmentHandler.php b/vendor/behat/behat/src/Behat/Behat/Context/Environment/Handler/ContextEnvironmentHandler.php new file mode 100644 index 0000000..a047981 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Environment/Handler/ContextEnvironmentHandler.php @@ -0,0 +1,177 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Environment\Handler; + +use Behat\Behat\Context\ContextClass\ClassResolver; +use Behat\Behat\Context\ContextFactory; +use Behat\Behat\Context\Environment\InitializedContextEnvironment; +use Behat\Behat\Context\Environment\UninitializedContextEnvironment; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Environment\Exception\EnvironmentIsolationException; +use Behat\Testwork\Environment\Handler\EnvironmentHandler; +use Behat\Testwork\Suite\Exception\SuiteConfigurationException; +use Behat\Testwork\Suite\Suite; + +/** + * Handles build and initialisation of the context-based environments. + * + * @see ContextFactory + * + * @author Konstantin Kudryashov + */ +final class ContextEnvironmentHandler implements EnvironmentHandler +{ + /** + * @var ContextFactory + */ + private $factory; + /** + * @var ClassResolver[] + */ + private $classResolvers = array(); + + /** + * Initializes handler. + * + * @param ContextFactory $factory + */ + public function __construct(ContextFactory $factory) + { + $this->factory = $factory; + } + + /** + * Registers context class resolver. + * + * @param ClassResolver $resolver + */ + public function registerClassResolver(ClassResolver $resolver) + { + $this->classResolvers[] = $resolver; + } + + /** + * {@inheritdoc} + */ + public function supportsSuite(Suite $suite) + { + return $suite->hasSetting('contexts'); + } + + /** + * {@inheritdoc} + */ + public function buildEnvironment(Suite $suite) + { + $environment = new UninitializedContextEnvironment($suite); + foreach ($this->getNormalizedContextSettings($suite) as $context) { + $environment->registerContextClass($this->resolveClass($context[0]), $context[1]); + } + + return $environment; + } + + /** + * {@inheritdoc} + */ + public function supportsEnvironmentAndSubject(Environment $environment, $testSubject = null) + { + return $environment instanceof UninitializedContextEnvironment; + } + + /** + * {@inheritdoc} + */ + public function isolateEnvironment(Environment $uninitializedEnvironment, $testSubject = null) + { + if (!$uninitializedEnvironment instanceof UninitializedContextEnvironment) { + throw new EnvironmentIsolationException(sprintf( + 'ContextEnvironmentHandler does not support isolation of `%s` environment.', + get_class($uninitializedEnvironment) + ), $uninitializedEnvironment); + } + + $environment = new InitializedContextEnvironment($uninitializedEnvironment->getSuite()); + foreach ($uninitializedEnvironment->getContextClassesWithArguments() as $class => $arguments) { + $context = $this->factory->createContext($class, $arguments); + $environment->registerContext($context); + } + + return $environment; + } + + /** + * Returns normalized suite context settings. + * + * @param Suite $suite + * + * @return array + */ + private function getNormalizedContextSettings(Suite $suite) + { + return array_map( + function ($context) { + $class = $context; + $arguments = array(); + + if (is_array($context)) { + $class = current(array_keys($context)); + $arguments = $context[$class]; + } + + return array($class, $arguments); + }, + $this->getSuiteContexts($suite) + ); + } + + /** + * Returns array of context classes configured for the provided suite. + * + * @param Suite $suite + * + * @return string[] + * + * @throws SuiteConfigurationException If `contexts` setting is not an array + */ + private function getSuiteContexts(Suite $suite) + { + if (!is_array($suite->getSetting('contexts'))) { + throw new SuiteConfigurationException( + sprintf('`contexts` setting of the "%s" suite is expected to be an array, %s given.', + $suite->getName(), + gettype($suite->getSetting('contexts')) + ), + $suite->getName() + ); + } + + return $suite->getSetting('contexts'); + } + + /** + * Resolves class using registered class resolvers. + * + * @param string $class + * + * @return string + */ + private function resolveClass($class) + { + foreach ($this->classResolvers as $resolver) { + if ($resolver->supportsClass($class)) { + return $resolver->resolveClass($class); + } + } + + return $class; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Environment/InitializedContextEnvironment.php b/vendor/behat/behat/src/Behat/Behat/Context/Environment/InitializedContextEnvironment.php new file mode 100644 index 0000000..c26826e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Environment/InitializedContextEnvironment.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Environment; + +use Behat\Behat\Context\Context; +use Behat\Behat\Context\Environment\Handler\ContextEnvironmentHandler; +use Behat\Behat\Context\Exception\ContextNotFoundException; +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Suite\Suite; + +/** + * Context environment based on a list of instantiated context objects. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +final class InitializedContextEnvironment implements ContextEnvironment +{ + /** + * @var string + */ + private $suite; + /** + * @var Context[] + */ + private $contexts = array(); + + /** + * Initializes environment. + * + * @param Suite $suite + */ + public function __construct(Suite $suite) + { + $this->suite = $suite; + } + + /** + * Registers context instance in the environment. + * + * @param Context $context + */ + public function registerContext(Context $context) + { + $this->contexts[get_class($context)] = $context; + } + + /** + * {@inheritdoc} + */ + public function getSuite() + { + return $this->suite; + } + + /** + * {@inheritdoc} + */ + public function hasContexts() + { + return count($this->contexts) > 0; + } + + /** + * {@inheritdoc} + */ + public function getContextClasses() + { + return array_keys($this->contexts); + } + + /** + * {@inheritdoc} + */ + public function hasContextClass($class) + { + return isset($this->contexts[$class]); + } + + /** + * Returns list of registered context instances. + * + * @return Context[] + */ + public function getContexts() + { + return array_values($this->contexts); + } + + /** + * Returns registered context by its class name. + * + * @param string $class + * + * @return Context + * + * @throws ContextNotFoundException If context is not in the environment + */ + public function getContext($class) + { + if (!$this->hasContextClass($class)) { + throw new ContextNotFoundException(sprintf( + '`%s` context is not found in the suite environment. Have you registered it?', + $class + ), $class); + } + + return $this->contexts[$class]; + } + + /** + * {@inheritdoc} + */ + public function bindCallee(Callee $callee) + { + $callable = $callee->getCallable(); + + if ($callee->isAnInstanceMethod()) { + return array($this->getContext($callable[0]), $callable[1]); + } + + return $callable; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Environment/Reader/ContextEnvironmentReader.php b/vendor/behat/behat/src/Behat/Behat/Context/Environment/Reader/ContextEnvironmentReader.php new file mode 100644 index 0000000..71759e9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Environment/Reader/ContextEnvironmentReader.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Environment\Reader; + +use Behat\Behat\Context\Environment\ContextEnvironment; +use Behat\Behat\Context\Reader\ContextReader; +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Environment\Exception\EnvironmentReadException; +use Behat\Testwork\Environment\Reader\EnvironmentReader; + +/** + * Reads context-based environment callees using registered context loaders. + * + * @author Konstantin Kudryashov + */ +final class ContextEnvironmentReader implements EnvironmentReader +{ + /** + * @var ContextReader[] + */ + private $contextReaders = array(); + + /** + * Registers context loader. + * + * @param ContextReader $contextReader + */ + public function registerContextReader(ContextReader $contextReader) + { + $this->contextReaders[] = $contextReader; + } + + /** + * {@inheritdoc} + */ + public function supportsEnvironment(Environment $environment) + { + return $environment instanceof ContextEnvironment; + } + + /** + * {@inheritdoc} + */ + public function readEnvironmentCallees(Environment $environment) + { + if (!$environment instanceof ContextEnvironment) { + throw new EnvironmentReadException(sprintf( + 'ContextEnvironmentReader does not support `%s` environment.', + get_class($environment) + ), $environment); + } + + $callees = array(); + foreach ($environment->getContextClasses() as $contextClass) { + $callees = array_merge( + $callees, + $this->readContextCallees($environment, $contextClass) + ); + } + + return $callees; + } + + /** + * Reads callees from a specific suite's context. + * + * @param ContextEnvironment $environment + * @param string $contextClass + * + * @return Callee[] + */ + private function readContextCallees(ContextEnvironment $environment, $contextClass) + { + $callees = array(); + foreach ($this->contextReaders as $loader) { + $callees = array_merge( + $callees, + $loader->readContextCallees($environment, $contextClass) + ); + } + + return $callees; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Environment/UninitializedContextEnvironment.php b/vendor/behat/behat/src/Behat/Behat/Context/Environment/UninitializedContextEnvironment.php new file mode 100644 index 0000000..d0ff985 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Environment/UninitializedContextEnvironment.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Environment; + +use Behat\Behat\Context\Environment\Handler\ContextEnvironmentHandler; +use Behat\Behat\Context\Exception\ContextNotFoundException; +use Behat\Behat\Context\Exception\WrongContextClassException; +use Behat\Testwork\Environment\StaticEnvironment; + +/** + * Context environment based on a list of context classes. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +final class UninitializedContextEnvironment extends StaticEnvironment implements ContextEnvironment +{ + /** + * @var array[] + */ + private $contextClasses = array(); + + /** + * Registers context class. + * + * @param string $contextClass + * @param null|array $arguments + * + * @throws ContextNotFoundException If class does not exist + * @throws WrongContextClassException if class does not implement Context interface + */ + public function registerContextClass($contextClass, array $arguments = null) + { + if (!class_exists($contextClass)) { + throw new ContextNotFoundException(sprintf( + '`%s` context class not found and can not be used.', + $contextClass + ), $contextClass); + } + + $reflClass = new \ReflectionClass($contextClass); + + if (!$reflClass->implementsInterface('Behat\Behat\Context\Context')) { + throw new WrongContextClassException(sprintf( + 'Every context class must implement Behat Context interface, but `%s` does not.', + $contextClass + ), $contextClass); + } + + $this->contextClasses[$contextClass] = $arguments ? : array(); + } + + /** + * {@inheritdoc} + */ + public function hasContexts() + { + return count($this->contextClasses) > 0; + } + + /** + * {@inheritdoc} + */ + public function getContextClasses() + { + return array_keys($this->contextClasses); + } + + /** + * {@inheritdoc} + */ + public function hasContextClass($class) + { + return isset($this->contextClasses[$class]); + } + + /** + * Returns context classes with their arguments. + * + * @return array[] + */ + public function getContextClassesWithArguments() + { + return $this->contextClasses; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Exception/ContextException.php b/vendor/behat/behat/src/Behat/Behat/Context/Exception/ContextException.php new file mode 100644 index 0000000..bc1a427 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Exception/ContextException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Exception; + +use Behat\Testwork\Exception\TestworkException; + +/** + * Represents an exception thrown during context handling. + * + * @author Konstantin Kudryashov + */ +interface ContextException extends TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Exception/ContextNotFoundException.php b/vendor/behat/behat/src/Behat/Behat/Context/Exception/ContextNotFoundException.php new file mode 100644 index 0000000..64cfde9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Exception/ContextNotFoundException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Exception; + +use InvalidArgumentException; + +/** + * Represents an exception thrown when provided context class is not found. + * + * @author Konstantin Kudryashov + */ +final class ContextNotFoundException extends InvalidArgumentException implements ContextException +{ + /** + * @var string + */ + private $class; + + /** + * Initializes exception. + * + * @param string $message + * @param string $class + */ + public function __construct($message, $class) + { + $this->class = $class; + + parent::__construct($message); + } + + /** + * Returns not found classname. + * + * @return string + */ + public function getClass() + { + return $this->class; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Exception/UnknownTranslationResourceException.php b/vendor/behat/behat/src/Behat/Behat/Context/Exception/UnknownTranslationResourceException.php new file mode 100644 index 0000000..2c4a761 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Exception/UnknownTranslationResourceException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Exception; + +use InvalidArgumentException; + +/** + * Represents an exception when provided translation resource is not recognised. + * + * @author Konstantin Kudryashov + */ +final class UnknownTranslationResourceException extends InvalidArgumentException implements ContextException +{ + /** + * @var string + */ + private $resource; + + /** + * Initializes exception. + * + * @param string $message + * @param string $class + */ + public function __construct($message, $class) + { + $this->resource = $class; + + parent::__construct($message); + } + + /** + * Returns unsupported resource. + * + * @return string + */ + public function getResource() + { + return $this->resource; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Exception/WrongContextClassException.php b/vendor/behat/behat/src/Behat/Behat/Context/Exception/WrongContextClassException.php new file mode 100644 index 0000000..69ccc8c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Exception/WrongContextClassException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Exception; + +use InvalidArgumentException; + +/** + * Represents an exception when provided class exists, but is not an acceptable as a context. + * + * @author Konstantin Kudryashov + */ +final class WrongContextClassException extends InvalidArgumentException implements ContextException +{ + /** + * @var string + */ + private $class; + + /** + * Initializes exception. + * + * @param integer $message + * @param string $class + */ + public function __construct($message, $class) + { + $this->class = $class; + + parent::__construct($message); + } + + /** + * Returns not found classname. + * + * @return string + */ + public function getClass() + { + return $this->class; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Initializer/ContextInitializer.php b/vendor/behat/behat/src/Behat/Behat/Context/Initializer/ContextInitializer.php new file mode 100644 index 0000000..3d2b356 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Initializer/ContextInitializer.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Initializer; + +use Behat\Behat\Context\Context; + +/** + * Initializes contexts using custom logic. + * + * @author Konstantin Kudryashov + */ +interface ContextInitializer +{ + /** + * Initializes provided context. + * + * @param Context $context + */ + public function initializeContext(Context $context); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Reader/AnnotatedContextReader.php b/vendor/behat/behat/src/Behat/Behat/Context/Reader/AnnotatedContextReader.php new file mode 100644 index 0000000..1bbfc14 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Reader/AnnotatedContextReader.php @@ -0,0 +1,232 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Reader; + +use Behat\Behat\Context\Annotation\AnnotationReader; +use Behat\Behat\Context\Environment\ContextEnvironment; +use Behat\Testwork\Call\Callee; +use ReflectionClass; +use ReflectionException; +use ReflectionMethod; + +/** + * Reads context callees by annotations using registered annotation readers. + * + * @author Konstantin Kudryashov + */ +final class AnnotatedContextReader implements ContextReader +{ + const DOCLINE_TRIMMER_REGEX = '/^\/\*\*\s*|^\s*\*\s*|\s*\*\/$|\s*$/'; + + /** + * @var string[] + */ + private static $ignoreAnnotations = array( + '@param', + '@return', + '@throws', + '@see', + '@uses', + '@todo' + ); + /** + * @var AnnotationReader[] + */ + private $readers = array(); + + /** + * Registers annotation reader. + * + * @param AnnotationReader $reader + */ + public function registerAnnotationReader(AnnotationReader $reader) + { + $this->readers[] = $reader; + } + + /** + * {@inheritdoc} + */ + public function readContextCallees(ContextEnvironment $environment, $contextClass) + { + $reflection = new ReflectionClass($contextClass); + + $callees = array(); + foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { + foreach ($this->readMethodCallees($reflection->getName(), $method) as $callee) { + $callees[] = $callee; + } + } + + return $callees; + } + + /** + * Loads callees associated with specific method. + * + * @param string $class + * @param ReflectionMethod $method + * + * @return Callee[] + */ + private function readMethodCallees($class, ReflectionMethod $method) + { + $callees = array(); + + // read parent annotations + try { + $prototype = $method->getPrototype(); + // error occurs on every second PHP stable release - getPrototype() returns itself + if ($prototype->getDeclaringClass()->getName() !== $method->getDeclaringClass()->getName()) { + $callees = array_merge($callees, $this->readMethodCallees($class, $prototype)); + } + } catch (ReflectionException $e) { + } + + if ($docBlock = $method->getDocComment()) { + $callees = array_merge($callees, $this->readDocBlockCallees($class, $method, $docBlock)); + } + + return $callees; + } + + /** + * Reads callees from the method doc block. + * + * @param string $class + * @param ReflectionMethod $method + * @param string $docBlock + * + * @return Callee[] + */ + private function readDocBlockCallees($class, ReflectionMethod $method, $docBlock) + { + $callees = array(); + $description = $this->readDescription($docBlock); + + foreach (explode("\n", $docBlock) as $docLine) { + $docLine = preg_replace(self::DOCLINE_TRIMMER_REGEX, '', $docLine); + + if ($this->isEmpty($docLine)) { + continue; + } + + if ($this->isNotAnnotation($docLine)) { + continue; + } + + if ($callee = $this->readDocLineCallee($class, $method, $docLine, $description)) { + $callees[] = $callee; + } + } + + return $callees; + } + + /** + * Extracts a description from the provided docblock, + * with support for multiline descriptions. + * + * @param string $docBlock + * + * @return string + */ + private function readDescription($docBlock) + { + // Remove indentation + $description = preg_replace('/^[\s\t]*/m', '', $docBlock); + + // Remove block comment syntax + $description = preg_replace('/^\/\*\*\s*|^\s*\*\s|^\s*\*\/$/m', '', $description); + + // Remove annotations + $description = preg_replace('/^@.*$/m', '', $description); + + // Ignore docs after a "--" separator + if (preg_match('/^--.*$/m', $description)) { + $descriptionParts = preg_split('/^--.*$/m', $description); + $description = array_shift($descriptionParts); + } + + // Trim leading and trailing newlines + $description = trim($description, "\r\n"); + + return $description; + } + + /** + * Checks if provided doc lien is empty. + * + * @param string $docLine + * + * @return Boolean + */ + private function isEmpty($docLine) + { + return '' == $docLine; + } + + /** + * Checks if provided doc line is not an annotation. + * + * @param string $docLine + * + * @return Boolean + */ + private function isNotAnnotation($docLine) + { + return '@' !== substr($docLine, 0, 1); + } + + /** + * Reads callee from provided doc line using registered annotation readers. + * + * @param string $class + * @param ReflectionMethod $method + * @param string $docLine + * @param null|string $description + * + * @return null|Callee + */ + private function readDocLineCallee($class, ReflectionMethod $method, $docLine, $description = null) + { + if ($this->isIgnoredAnnotation($docLine)) { + return null; + } + + foreach ($this->readers as $reader) { + if ($callee = $reader->readCallee($class, $method, $docLine, $description)) { + return $callee; + } + } + + return null; + } + + /** + * Checks if provided doc line is one of the ignored annotations. + * + * @param string $docLine + * + * @return Boolean + */ + private function isIgnoredAnnotation($docLine) + { + $lowDocLine = strtolower($docLine); + foreach (self::$ignoreAnnotations as $ignoredAnnotation) { + if ($ignoredAnnotation == substr($lowDocLine, 0, strlen($ignoredAnnotation))) { + return true; + } + } + + return false; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Reader/ContextReader.php b/vendor/behat/behat/src/Behat/Behat/Context/Reader/ContextReader.php new file mode 100644 index 0000000..b8a9156 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Reader/ContextReader.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Reader; + +use Behat\Behat\Context\Environment\ContextEnvironment; +use Behat\Testwork\Call\Callee; + +/** + * Reads callees from a context class. + * + * @author Konstantin Kudryashov + */ +interface ContextReader +{ + /** + * Reads callees from specific environment & context. + * + * @param ContextEnvironment $environment + * @param string $contextClass + * + * @return Callee[] + */ + public function readContextCallees(ContextEnvironment $environment, $contextClass); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Reader/ContextReaderCachedPerContext.php b/vendor/behat/behat/src/Behat/Behat/Context/Reader/ContextReaderCachedPerContext.php new file mode 100644 index 0000000..8a51662 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Reader/ContextReaderCachedPerContext.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Reader; + +use Behat\Behat\Context\Environment\ContextEnvironment; + +/** + * Proxies call to another reader and caches context callees for a length of an entire exercise. + * + * @author Konstantin Kudryashov + */ +final class ContextReaderCachedPerContext implements ContextReader +{ + /** + * @var ContextReader + */ + private $childReader; + /** + * @var array[] + */ + private $cachedCallees = array(); + + /** + * Initializes reader. + * + * @param ContextReader $childReader + */ + public function __construct(ContextReader $childReader) + { + $this->childReader = $childReader; + } + + /** + * {@inheritdoc} + */ + public function readContextCallees(ContextEnvironment $environment, $contextClass) + { + if (isset($this->cachedCallees[$contextClass])) { + return $this->cachedCallees[$contextClass]; + } + + return $this->cachedCallees[$contextClass] = $this->childReader->readContextCallees( + $environment, $contextClass + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Reader/ContextReaderCachedPerSuite.php b/vendor/behat/behat/src/Behat/Behat/Context/Reader/ContextReaderCachedPerSuite.php new file mode 100644 index 0000000..4a8bfd5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Reader/ContextReaderCachedPerSuite.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Reader; + +use Behat\Behat\Context\Environment\ContextEnvironment; + +/** + * Proxies call to another reader and caches callees for a length of an entire suite. + * + * @author Konstantin Kudryashov + */ +final class ContextReaderCachedPerSuite implements ContextReader +{ + /** + * @var ContextReader + */ + private $childReader; + /** + * @var array[] + */ + private $cachedCallees = array(); + + /** + * Initializes reader. + * + * @param ContextReader $childReader + */ + public function __construct(ContextReader $childReader) + { + $this->childReader = $childReader; + } + + /** + * {@inheritdoc} + */ + public function readContextCallees(ContextEnvironment $environment, $contextClass) + { + $key = $this->generateCacheKey($environment, $contextClass); + + if (isset($this->cachedCallees[$key])) { + return $this->cachedCallees[$key]; + } + + return $this->cachedCallees[$key] = $this->childReader->readContextCallees( + $environment, $contextClass + ); + } + + /** + * Generates cache key. + * + * @param ContextEnvironment $environment + * @param string $contextClass + * + * @return string + */ + private function generateCacheKey(ContextEnvironment $environment, $contextClass) + { + return $environment->getSuite()->getName() . $contextClass; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Reader/TranslatableContextReader.php b/vendor/behat/behat/src/Behat/Behat/Context/Reader/TranslatableContextReader.php new file mode 100644 index 0000000..11327ee --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Reader/TranslatableContextReader.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Reader; + +use Behat\Behat\Context\Environment\ContextEnvironment; +use Behat\Behat\Context\Exception\UnknownTranslationResourceException; +use Behat\Behat\Context\TranslatableContext; +use Symfony\Component\Translation\Translator; + +/** + * Reads translation resources from translatable contexts. + * + * @author Konstantin Kudryashov + */ +final class TranslatableContextReader implements ContextReader +{ + /** + * @var Translator + */ + private $translator; + + /** + * Initializes loader. + * + * @param Translator $translator + */ + public function __construct(Translator $translator) + { + $this->translator = $translator; + } + + /** + * {@inheritdoc} + * + * @see TranslatableContext + */ + public function readContextCallees(ContextEnvironment $environment, $contextClass) + { + $reflClass = new \ReflectionClass($contextClass); + + if (!$reflClass->implementsInterface('Behat\Behat\Context\TranslatableContext')) { + return array(); + } + + $assetsId = $environment->getSuite()->getName(); + foreach (call_user_func(array($contextClass, 'getTranslationResources')) as $path) { + $this->addTranslationResource($path, $assetsId); + } + + return array(); + } + + /** + * Adds translation resource. + * + * @param string $path + * @param string $assetsId + * + * @throws UnknownTranslationResourceException + */ + private function addTranslationResource($path, $assetsId) + { + switch ($ext = pathinfo($path, PATHINFO_EXTENSION)) { + case 'yml': + $this->addTranslatorResource('yaml', $path, basename($path, '.' . $ext), $assetsId); + break; + case 'xliff': + $this->addTranslatorResource('xliff', $path, basename($path, '.' . $ext), $assetsId); + break; + case 'php': + $this->addTranslatorResource('php', $path, basename($path, '.' . $ext), $assetsId); + break; + default: + throw new UnknownTranslationResourceException(sprintf( + 'Can not read translations from `%s`. File type is not supported.', + $path + ), $path); + } + } + + /** + * Adds resource to translator instance. + * + * @param string $type + * @param string $path + * @param string $language + * @param string $assetsId + */ + private function addTranslatorResource($type, $path, $language, $assetsId) + { + $this->translator->addResource($type, $path, $language, $assetsId); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/ServiceContainer/ContextExtension.php b/vendor/behat/behat/src/Behat/Behat/Context/ServiceContainer/ContextExtension.php new file mode 100644 index 0000000..976b6ec --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/ServiceContainer/ContextExtension.php @@ -0,0 +1,369 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\ServiceContainer; + +use Behat\Behat\Definition\ServiceContainer\DefinitionExtension; +use Behat\Behat\Snippet\ServiceContainer\SnippetExtension; +use Behat\Testwork\Argument\ServiceContainer\ArgumentExtension; +use Behat\Testwork\Autoloader\ServiceContainer\AutoloaderExtension; +use Behat\Testwork\Environment\ServiceContainer\EnvironmentExtension; +use Behat\Testwork\Filesystem\ServiceContainer\FilesystemExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Suite\ServiceContainer\SuiteExtension; +use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Behat context extension. + * + * Extends Behat with context services. + * + * @author Konstantin Kudryashov + */ +final class ContextExtension implements Extension +{ + /** + * Available services + */ + const FACTORY_ID = 'context.factory'; + + /* + * Available extension points + */ + const CLASS_RESOLVER_TAG = 'context.class_resolver'; + const ARGUMENT_RESOLVER_TAG = 'context.argument_resolver'; + const INITIALIZER_TAG = 'context.initializer'; + const READER_TAG = 'context.reader'; + const ANNOTATION_READER_TAG = 'context.annotation_reader'; + const CLASS_GENERATOR_TAG = 'context.class_generator'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes compiler pass. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'contexts'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadFactory($container); + $this->loadEnvironmentHandler($container); + $this->loadEnvironmentReader($container); + $this->loadSuiteSetup($container); + $this->loadSnippetAppender($container); + $this->loadSnippetGenerators($container); + $this->loadDefaultClassGenerators($container); + $this->loadDefaultContextReaders($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processClassResolvers($container); + $this->processArgumentResolvers($container); + $this->processContextInitializers($container); + $this->processContextReaders($container); + $this->processClassGenerators($container); + $this->processAnnotationReaders($container); + } + + /** + * Loads context factory. + * + * @param ContainerBuilder $container + */ + private function loadFactory(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\ContextFactory', array( + new Reference(ArgumentExtension::CONSTRUCTOR_ARGUMENT_ORGANISER_ID) + )); + $container->setDefinition(self::FACTORY_ID, $definition); + } + + /** + * Loads context environment handlers. + * + * @param ContainerBuilder $container + */ + private function loadEnvironmentHandler(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\Environment\Handler\ContextEnvironmentHandler', array( + new Reference(self::FACTORY_ID) + )); + $definition->addTag(EnvironmentExtension::HANDLER_TAG, array('priority' => 50)); + $container->setDefinition(self::getEnvironmentHandlerId(), $definition); + } + + /** + * Loads context environment readers. + * + * @param ContainerBuilder $container + */ + private function loadEnvironmentReader(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\Environment\Reader\ContextEnvironmentReader'); + $definition->addTag(EnvironmentExtension::READER_TAG, array('priority' => 50)); + $container->setDefinition(self::getEnvironmentReaderId(), $definition); + } + + /** + * Loads context environment setup. + * + * @param ContainerBuilder $container + */ + private function loadSuiteSetup(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\Suite\Setup\SuiteWithContextsSetup', array( + new Reference(AutoloaderExtension::CLASS_LOADER_ID), + new Reference(FilesystemExtension::LOGGER_ID) + )); + $definition->addTag(SuiteExtension::SETUP_TAG, array('priority' => 20)); + $container->setDefinition(self::getSuiteSetupId(), $definition); + } + + /** + * Loads context snippet appender. + * + * @param ContainerBuilder $container + */ + private function loadSnippetAppender(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\Snippet\Appender\ContextSnippetAppender', array( + new Reference(FilesystemExtension::LOGGER_ID) + )); + $definition->addTag(SnippetExtension::APPENDER_TAG, array('priority' => 50)); + $container->setDefinition(SnippetExtension::APPENDER_TAG . '.context', $definition); + } + + /** + * Loads context snippet generators. + * + * @param ContainerBuilder $container + */ + private function loadSnippetGenerators(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\Snippet\Generator\ContextSnippetGenerator', array( + new Reference(DefinitionExtension::PATTERN_TRANSFORMER_ID) + )); + $definition->addTag(SnippetExtension::GENERATOR_TAG, array('priority' => 50)); + $container->setDefinition(SnippetExtension::GENERATOR_TAG . '.context', $definition); + } + + /** + * Loads default context class generators. + * + * @param ContainerBuilder $container + */ + private function loadDefaultClassGenerators(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\ContextClass\SimpleClassGenerator'); + $definition->addTag(self::CLASS_GENERATOR_TAG, array('priority' => 50)); + $container->setDefinition(self::CLASS_GENERATOR_TAG . '.simple', $definition); + } + + /** + * Loads default context readers. + * + * @param ContainerBuilder $container + */ + private function loadDefaultContextReaders(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\Reader\AnnotatedContextReader'); + $container->setDefinition(self::getAnnotatedContextReaderId(), $definition); + + $definition = new Definition('Behat\Behat\Context\Reader\ContextReaderCachedPerContext', array( + new Reference(self::getAnnotatedContextReaderId()) + )); + $definition->addTag(self::READER_TAG, array('priority' => 50)); + $container->setDefinition(self::getAnnotatedContextReaderId() . '.cached', $definition); + + $definition = new Definition('Behat\Behat\Context\Reader\TranslatableContextReader', array( + new Reference(TranslatorExtension::TRANSLATOR_ID) + )); + $container->setDefinition(self::READER_TAG . '.translatable', $definition); + + $definition = new Definition('Behat\Behat\Context\Reader\ContextReaderCachedPerSuite', array( + new Reference(self::READER_TAG . '.translatable') + )); + $definition->addTag(self::READER_TAG, array('priority' => 50)); + $container->setDefinition(self::READER_TAG . '.translatable.cached', $definition); + } + + /** + * Processes all context initializers. + * + * @param ContainerBuilder $container + */ + private function processClassResolvers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::CLASS_RESOLVER_TAG); + $definition = $container->getDefinition(self::getEnvironmentHandlerId()); + + foreach ($references as $reference) { + $definition->addMethodCall('registerClassResolver', array($reference)); + } + } + + /** + * Processes all context initializers. + * + * @param ContainerBuilder $container + */ + private function processArgumentResolvers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::ARGUMENT_RESOLVER_TAG); + $definition = $container->getDefinition(self::FACTORY_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerArgumentResolver', array($reference)); + } + } + + /** + * Processes all context initializers. + * + * @param ContainerBuilder $container + */ + private function processContextInitializers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::INITIALIZER_TAG); + $definition = $container->getDefinition(self::FACTORY_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerContextInitializer', array($reference)); + } + } + + /** + * Processes all context readers. + * + * @param ContainerBuilder $container + */ + private function processContextReaders(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::READER_TAG); + $definition = $container->getDefinition(self::getEnvironmentReaderId()); + + foreach ($references as $reference) { + $definition->addMethodCall('registerContextReader', array($reference)); + } + } + + /** + * Processes all class generators. + * + * @param ContainerBuilder $container + */ + private function processClassGenerators(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::CLASS_GENERATOR_TAG); + $definition = $container->getDefinition(self::getSuiteSetupId()); + + foreach ($references as $reference) { + $definition->addMethodCall('registerClassGenerator', array($reference)); + } + } + + /** + * Processes all annotation readers. + * + * @param ContainerBuilder $container + */ + private function processAnnotationReaders(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::ANNOTATION_READER_TAG); + $definition = $container->getDefinition(self::getAnnotatedContextReaderId()); + + foreach ($references as $reference) { + $definition->addMethodCall('registerAnnotationReader', array($reference)); + } + } + + /** + * Returns context environment handler service id. + * + * @return string + */ + private static function getEnvironmentHandlerId() + { + return EnvironmentExtension::HANDLER_TAG . '.context'; + } + + /** + * Returns context environment reader id. + * + * @return string + */ + private static function getEnvironmentReaderId() + { + return EnvironmentExtension::READER_TAG . '.context'; + } + + /** + * Returns context suite setup id. + * + * @return string + */ + private static function getSuiteSetupId() + { + return SuiteExtension::SETUP_TAG . '.suite_with_contexts'; + } + + /** + * Returns annotated context reader id. + * + * @return string + */ + private static function getAnnotatedContextReaderId() + { + return self::READER_TAG . '.annotated'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Appender/ContextSnippetAppender.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Appender/ContextSnippetAppender.php new file mode 100644 index 0000000..5b49d31 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Appender/ContextSnippetAppender.php @@ -0,0 +1,124 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Snippet\Appender; + +use Behat\Behat\Snippet\AggregateSnippet; +use Behat\Behat\Snippet\Appender\SnippetAppender; +use Behat\Testwork\Filesystem\FilesystemLogger; +use ReflectionClass; + +/** + * Appends context-related snippets to their context classes. + * + * @author Konstantin Kudryashov + */ +final class ContextSnippetAppender implements SnippetAppender +{ + /** + * @const PendingException class + */ + const PENDING_EXCEPTION_CLASS = 'Behat\Behat\Tester\Exception\PendingException'; + + /** + * @var FilesystemLogger + */ + private $logger; + + /** + * Initializes appender. + * + * @param null|FilesystemLogger $logger + */ + public function __construct(FilesystemLogger $logger = null) + { + $this->logger = $logger; + } + + /** + * {@inheritdoc} + */ + public function supportsSnippet(AggregateSnippet $snippet) + { + return 'context' === $snippet->getType(); + } + + /** + * {@inheritdoc} + */ + public function appendSnippet(AggregateSnippet $snippet) + { + foreach ($snippet->getTargets() as $contextClass) { + $reflection = new ReflectionClass($contextClass); + $content = file_get_contents($reflection->getFileName()); + + if (!$this->isPendingExceptionImported($content)) { + $content = $this->importPendingException($content); + } + + $generated = rtrim(strtr($snippet->getSnippet(), array('\\' => '\\\\', '$' => '\\$'))); + $content = preg_replace('/}\s*$/', "\n" . $generated . "\n}\n", $content); + $path = $reflection->getFileName(); + + file_put_contents($path, $content); + + $this->logSnippetAddition($snippet, $path); + } + } + + /** + * Checks if context file already has pending exception in it. + * + * @param string $contextFileContent + * + * @return Boolean + */ + private function isPendingExceptionImported($contextFileContent) + { + $pendingExceptionImportRegex = sprintf( + '@use[^;]*%s.*;@ms', + preg_quote(self::PENDING_EXCEPTION_CLASS, '@') + ); + + return 1 === preg_match($pendingExceptionImportRegex, $contextFileContent); + } + + /** + * Adds use-block for pending exception. + * + * @param string $contextFileContent + * + * @return string + */ + private function importPendingException($contextFileContent) + { + $replaceWith = "\$1" . 'use ' . self::PENDING_EXCEPTION_CLASS . ";\n\$2;"; + + return preg_replace('@^(.*)(use\s+[^;]*);@m', $replaceWith, $contextFileContent, 1); + } + + /** + * Logs snippet addition to the provided path (if logger is given). + * + * @param AggregateSnippet $snippet + * @param string $path + */ + private function logSnippetAddition(AggregateSnippet $snippet, $path) + { + if (!$this->logger) { + return; + } + + $steps = $snippet->getSteps(); + $reason = sprintf("`%s` definition added", $steps[0]->getText()); + + $this->logger->fileUpdated($path, $reason); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/ContextSnippet.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/ContextSnippet.php new file mode 100644 index 0000000..017f352 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/ContextSnippet.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Snippet; + +use Behat\Behat\Snippet\Snippet; +use Behat\Gherkin\Node\StepNode; + +/** + * Represents a definition snippet for a context class. + * + * @author Konstantin Kudryashov + */ +final class ContextSnippet implements Snippet +{ + /** + * @var StepNode + */ + private $step; + /** + * @var string + */ + private $template; + /** + * @var string + */ + private $contextClass; + + /** + * Initializes definition snippet. + * + * @param StepNode $step + * @param string $template + * @param string $contextClass + */ + public function __construct(StepNode $step, $template, $contextClass) + { + $this->step = $step; + $this->template = $template; + $this->contextClass = $contextClass; + } + + /** + * {@inheritdoc} + */ + public function getType() + { + return 'context'; + } + + /** + * {@inheritdoc} + */ + public function getHash() + { + return md5($this->template); + } + + /** + * {@inheritdoc} + */ + public function getSnippet() + { + return sprintf($this->template, $this->step->getKeywordType()); + } + + /** + * {@inheritdoc} + */ + public function getStep() + { + return $this->step; + } + + /** + * {@inheritdoc} + */ + public function getTarget() + { + return $this->contextClass; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextSnippetGenerator.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextSnippetGenerator.php new file mode 100644 index 0000000..67b665a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextSnippetGenerator.php @@ -0,0 +1,339 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Snippet\Generator; + +use Behat\Behat\Context\Environment\ContextEnvironment; +use Behat\Behat\Context\Snippet\ContextSnippet; +use Behat\Behat\Definition\Pattern\PatternTransformer; +use Behat\Behat\Snippet\Exception\EnvironmentSnippetGenerationException; +use Behat\Behat\Snippet\Generator\SnippetGenerator; +use Behat\Gherkin\Node\PyStringNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Gherkin\Node\TableNode; +use Behat\Testwork\Environment\Environment; +use ReflectionClass; + +/** + * Generates snippets for a context class. + * + * @author Konstantin Kudryashov + */ +final class ContextSnippetGenerator implements SnippetGenerator +{ + /** + * @var string[string] + */ + private static $proposedMethods = array(); + /** + * @var string + */ + private static $templateTemplate = <<patternTransformer = $patternTransformer; + } + + /** + * {@inheritdoc} + */ + public function supportsEnvironmentAndStep(Environment $environment, StepNode $step) + { + if (!$environment instanceof ContextEnvironment) { + return false; + } + + if (!$environment->hasContexts()) { + return false; + } + + return null !== $this->getSnippetAcceptingContextClass($environment); + } + + /** + * {@inheritdoc} + */ + public function generateSnippet(Environment $environment, StepNode $step) + { + if (!$environment instanceof ContextEnvironment) { + throw new EnvironmentSnippetGenerationException(sprintf( + 'ContextSnippetGenerator does not support `%s` environment.', + get_class($environment) + ), $environment); + } + + $contextClass = $this->getSnippetAcceptingContextClass($environment); + $patternType = $this->getPatternType($contextClass); + $stepText = $step->getText(); + $pattern = $this->patternTransformer->generatePattern($patternType, $stepText); + + $methodName = $this->getMethodName($contextClass, $pattern->getCanonicalText(), $pattern->getPattern()); + $methodArguments = $this->getMethodArguments($step, $pattern->getPlaceholderCount()); + $snippetTemplate = $this->getSnippetTemplate($pattern->getPattern(), $methodName, $methodArguments); + + return new ContextSnippet($step, $snippetTemplate, $contextClass); + } + + /** + * Returns snippet-accepting context class. + * + * @param ContextEnvironment $environment + * + * @return null|string + */ + private function getSnippetAcceptingContextClass(ContextEnvironment $environment) + { + foreach ($environment->getContextClasses() as $class) { + if (in_array('Behat\Behat\Context\SnippetAcceptingContext', class_implements($class))) { + return $class; + } + } + + return null; + } + + /** + * Returns snippet-type that provided context class accepts. + * + * @param string $contextClass + * + * @return null|string + */ + private function getPatternType($contextClass) + { + if (!in_array('Behat\Behat\Context\CustomSnippetAcceptingContext', class_implements($contextClass))) { + return null; + } + + return $contextClass::getAcceptedSnippetType(); + } + + /** + * Generates method name using step text and regex. + * + * @param string $contextClass + * @param string $canonicalText + * @param string $pattern + * + * @return string + */ + private function getMethodName($contextClass, $canonicalText, $pattern) + { + $methodName = $this->deduceMethodName($canonicalText); + $methodName = $this->getUniqueMethodName($contextClass, $pattern, $methodName); + + return $methodName; + } + + /** + * Returns an array of method argument names from step and token count. + * + * @param StepNode $step + * @param integer $tokenCount + * + * @return string[] + */ + private function getMethodArguments(StepNode $step, $tokenCount) + { + $args = array(); + for ($i = 0; $i < $tokenCount; $i++) { + $args[] = '$arg' . ($i + 1); + } + + foreach ($step->getArguments() as $argument) { + $args[] = $this->getMethodArgument($argument); + } + + return $args; + } + + /** + * Generates snippet template using regex, method name and arguments. + * + * @param string $pattern + * @param string $methodName + * @param string[] $methodArguments + * + * @return string + */ + private function getSnippetTemplate($pattern, $methodName, array $methodArguments) + { + return sprintf( + self::$templateTemplate, + str_replace('%', '%%', $pattern), + $methodName, + implode(', ', $methodArguments) + ); + } + + /** + * Generates definition method name based on the step text. + * + * @param string $canonicalText + * + * @return string + */ + private function deduceMethodName($canonicalText) + { + // check that method name is not empty + if (0 !== strlen($canonicalText)) { + $canonicalText[0] = strtolower($canonicalText[0]); + + return $canonicalText; + } + + return 'stepDefinition1'; + } + + /** + * Ensures uniqueness of the method name in the context. + * + * @param string $contextClass + * @param string $stepPattern + * @param string $name + * + * @return string + */ + private function getUniqueMethodName($contextClass, $stepPattern, $name) + { + $reflection = new ReflectionClass($contextClass); + + $number = $this->getMethodNumberFromTheMethodName($name); + list($name, $number) = $this->getMethodNameNotExistentInContext($reflection, $name, $number); + $name = $this->getMethodNameNotProposedEarlier($contextClass, $stepPattern, $name, $number); + + return $name; + } + + /** + * Tries to deduct method number from the provided method name. + * + * @param string $methodName + * + * @return integer + */ + private function getMethodNumberFromTheMethodName($methodName) + { + $methodNumber = 2; + if (preg_match('/(\d+)$/', $methodName, $matches)) { + $methodNumber = intval($matches[1]); + } + + return $methodNumber; + } + + /** + * Tries to guess method name that is not yet defined in the context class. + * + * @param ReflectionClass $reflection + * @param string $methodName + * @param integer $methodNumber + * + * @return array + */ + private function getMethodNameNotExistentInContext(ReflectionClass $reflection, $methodName, $methodNumber) + { + while ($reflection->hasMethod($methodName)) { + $methodName = preg_replace('/\d+$/', '', $methodName); + $methodName .= $methodNumber++; + } + + return array($methodName, $methodNumber); + } + + /** + * Tries to guess method name that is not yet proposed to the context class. + * + * @param string $contextClass + * @param string $stepPattern + * @param string $name + * @param integer $number + * + * @return string + */ + private function getMethodNameNotProposedEarlier($contextClass, $stepPattern, $name, $number) + { + foreach ($this->getAlreadyProposedMethods($contextClass) as $proposedPattern => $proposedMethod) { + if ($proposedPattern === $stepPattern) { + continue; + } + + while ($proposedMethod === $name) { + $name = preg_replace('/\d+$/', '', $name); + $name .= $number++; + } + } + + $this->markMethodAsAlreadyProposed($contextClass, $stepPattern, $name); + + return $name; + } + + /** + * Returns already proposed method names. + * + * @param string $contextClass + * + * @return string[] + */ + private function getAlreadyProposedMethods($contextClass) + { + return isset(self::$proposedMethods[$contextClass]) ? self::$proposedMethods[$contextClass] : array(); + } + + /** + * Marks method as proposed one. + * + * @param string $contextClass + * @param string $stepPattern + * @param string $methodName + */ + private function markMethodAsAlreadyProposed($contextClass, $stepPattern, $methodName) + { + self::$proposedMethods[$contextClass][$stepPattern] = $methodName; + } + + /** + * Returns method argument. + * + * @param string $argument + * + * @return string + */ + private function getMethodArgument($argument) + { + $arg = '__unknown__'; + if ($argument instanceof PyStringNode) { + $arg = 'PyStringNode $string'; + } elseif ($argument instanceof TableNode) { + $arg = 'TableNode $table'; + } + + return $arg; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/SnippetAcceptingContext.php b/vendor/behat/behat/src/Behat/Behat/Context/SnippetAcceptingContext.php new file mode 100644 index 0000000..0582154 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/SnippetAcceptingContext.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context; + +use Behat\Behat\Context\Snippet\Generator\ContextSnippetGenerator; + +/** + * Context that implements this interface is treated as a snippet-friendly context. + * + * @see ContextSnippetGenerator + * + * @author Konstantin Kudryashov + */ +interface SnippetAcceptingContext extends Context +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Suite/Setup/SuiteWithContextsSetup.php b/vendor/behat/behat/src/Behat/Behat/Context/Suite/Setup/SuiteWithContextsSetup.php new file mode 100644 index 0000000..0bc41db --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Suite/Setup/SuiteWithContextsSetup.php @@ -0,0 +1,246 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context\Suite\Setup; + +use Behat\Behat\Context\ContextClass\ClassGenerator; +use Behat\Behat\Context\Exception\ContextNotFoundException; +use Behat\Testwork\Filesystem\FilesystemLogger; +use Behat\Testwork\Suite\Exception\SuiteConfigurationException; +use Behat\Testwork\Suite\Setup\SuiteSetup; +use Behat\Testwork\Suite\Suite; +use Symfony\Component\ClassLoader\ClassLoader; + +/** + * Generates classes for all contexts in the suite using autoloader. + * + * @author Konstantin Kudryashov + */ +final class SuiteWithContextsSetup implements SuiteSetup +{ + /** + * @var ClassLoader + */ + private $autoloader; + /** + * @var null|FilesystemLogger + */ + private $logger; + /** + * @var ClassGenerator[] + */ + private $classGenerators = array(); + + /** + * Initializes setup. + * + * @param ClassLoader $autoloader + * @param null|FilesystemLogger $logger + */ + public function __construct(ClassLoader $autoloader, FilesystemLogger $logger = null) + { + $this->autoloader = $autoloader; + $this->logger = $logger; + } + + /** + * Registers class generator. + * + * @param ClassGenerator $generator + */ + public function registerClassGenerator(ClassGenerator $generator) + { + $this->classGenerators[] = $generator; + } + + /** + * {@inheritdoc} + */ + public function supportsSuite(Suite $suite) + { + return $suite->hasSetting('contexts'); + } + + /** + * {@inheritdoc} + */ + public function setupSuite(Suite $suite) + { + foreach ($this->getNormalizedContextClasses($suite) as $class) { + if (class_exists($class)) { + continue; + } + + $this->ensureContextDirectory($path = $this->findClassFile($class)); + + if ($content = $this->generateClass($suite, $class)) { + $this->createContextFile($path, $content); + } + } + } + + /** + * Returns normalized context classes. + * + * @param Suite $suite + * + * @return string[] + */ + private function getNormalizedContextClasses(Suite $suite) + { + return array_map( + function ($context) { + return is_array($context) ? current(array_keys($context)) : $context; + }, + $this->getSuiteContexts($suite) + ); + } + + /** + * Returns array of context classes configured for the provided suite. + * + * @param Suite $suite + * + * @return string[] + * + * @throws SuiteConfigurationException If `contexts` setting is not an array + */ + private function getSuiteContexts(Suite $suite) + { + $contexts = $suite->getSetting('contexts'); + + if (!is_array($contexts)) { + throw new SuiteConfigurationException( + sprintf('`contexts` setting of the "%s" suite is expected to be an array, `%s` given.', + $suite->getName(), + gettype($contexts) + ), + $suite->getName() + ); + } + + return $contexts; + } + + /** + * Creates context directory in the filesystem. + * + * @param string $path + */ + private function createContextDirectory($path) + { + mkdir($path, 0777, true); + + if ($this->logger) { + $this->logger->directoryCreated($path, 'place your context classes here'); + } + } + + /** + * Creates context class file in the filesystem. + * + * @param string $path + * @param string $content + */ + private function createContextFile($path, $content) + { + file_put_contents($path, $content); + + if ($this->logger) { + $this->logger->fileCreated($path, 'place your definitions, transformations and hooks here'); + } + } + + /** + * Finds file to store a class. + * + * @param string $class + * + * @return string + * + * @throws ContextNotFoundException If class file could not be determined + */ + private function findClassFile($class) + { + list($classpath, $classname) = $this->findClasspathAndClass($class); + $classpath .= str_replace('_', DIRECTORY_SEPARATOR, $classname) . '.php'; + + foreach ($this->autoloader->getPrefixes() as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + return current($dirs) . DIRECTORY_SEPARATOR . $classpath; + } + } + + if ($dirs = $this->autoloader->getFallbackDirs()) { + return current($dirs) . DIRECTORY_SEPARATOR . $classpath; + } + + throw new ContextNotFoundException(sprintf( + 'Could not find where to put "%s" class. Have you configured autoloader properly?', + $class + ), $class); + } + + /** + * Generates class using registered class generators. + * + * @param Suite $suite + * @param string $class + * + * @return null|string + */ + private function generateClass(Suite $suite, $class) + { + $content = null; + foreach ($this->classGenerators as $generator) { + if ($generator->supportsSuiteAndClass($suite, $class)) { + $content = $generator->generateClass($suite, $class); + } + } + + return $content; + } + + /** + * Ensures that directory for a classpath exists. + * + * @param string $classpath + */ + private function ensureContextDirectory($classpath) + { + if (!is_dir(dirname($classpath))) { + $this->createContextDirectory(dirname($classpath)); + } + } + + /** + * Finds classpath and classname from class. + * + * @param string $class + * + * @return array + */ + private function findClasspathAndClass($class) + { + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $classpath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)) . DIRECTORY_SEPARATOR; + $classname = substr($class, $pos + 1); + + return array($classpath, $classname); + } + + // PEAR-like class name + $classpath = null; + $classname = $class; + + return array($classpath, $classname); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/TranslatableContext.php b/vendor/behat/behat/src/Behat/Behat/Context/TranslatableContext.php new file mode 100644 index 0000000..91bbb05 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/TranslatableContext.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Context; + +use Behat\Behat\Context\Reader\TranslatableContextReader; + +/** + * Context that implements this interface is also treated as a translation provider for all it's callees. + * + * @see TranslatableContextReader + * + * @author Konstantin Kudryashov + */ +interface TranslatableContext extends Context +{ + /** + * Returns array of Translator-supported resource paths. + * + * For instance: + * + * * array(__DIR__.'/../'ru.yml) + * * array(__DIR__.'/../'en.xliff) + * * array(__DIR__.'/../'de.php) + * + * @return string[] + */ + public static function getTranslationResources(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Call/DefinitionCall.php b/vendor/behat/behat/src/Behat/Behat/Definition/Call/DefinitionCall.php new file mode 100644 index 0000000..0c68af2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Call/DefinitionCall.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Call; + +use Behat\Behat\Definition\Definition; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Call\EnvironmentCall; +use Behat\Testwork\Environment\Environment; + +/** + * Enhances environment call with definition information. + * + * @author Konstantin Kudryashov + */ +final class DefinitionCall extends EnvironmentCall +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var StepNode + */ + private $step; + + /** + * Initializes definition call. + * + * @param Environment $environment + * @param FeatureNode $feature + * @param StepNode $step + * @param Definition $definition + * @param array $arguments + * @param null|integer $errorReportingLevel + */ + public function __construct( + Environment $environment, + FeatureNode $feature, + StepNode $step, + Definition $definition, + array $arguments, + $errorReportingLevel = null + ) { + parent::__construct($environment, $definition, $arguments, $errorReportingLevel); + + $this->feature = $feature; + $this->step = $step; + } + + /** + * Returns step feature node. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns definition step node. + * + * @return StepNode + */ + public function getStep() + { + return $this->step; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Call/Given.php b/vendor/behat/behat/src/Behat/Behat/Definition/Call/Given.php new file mode 100644 index 0000000..324ffb8 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Call/Given.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Call; + +/** + * Given steps definition. + * + * @author Konstantin Kudryashov + */ +final class Given extends RuntimeDefinition +{ + /** + * Initializes definition. + * + * @param string $pattern + * @param callable $callable + * @param null|string $description + */ + public function __construct($pattern, $callable, $description = null) + { + parent::__construct('Given', $pattern, $callable, $description); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Call/RuntimeDefinition.php b/vendor/behat/behat/src/Behat/Behat/Definition/Call/RuntimeDefinition.php new file mode 100644 index 0000000..4c2c494 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Call/RuntimeDefinition.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Call; + +use Behat\Behat\Definition\Definition; +use Behat\Testwork\Call\RuntimeCallee; + +/** + * Represents a step definition created and executed in the runtime. + * + * @author Konstantin Kudryashov + */ +abstract class RuntimeDefinition extends RuntimeCallee implements Definition +{ + /** + * @var string + */ + private $type; + /** + * @var string + */ + private $pattern; + + /** + * Initializes definition. + * + * @param string $type + * @param string $pattern + * @param callable $callable + * @param null|string $description + */ + public function __construct($type, $pattern, $callable, $description = null) + { + $this->type = $type; + $this->pattern = $pattern; + + parent::__construct($callable, $description); + } + + /** + * {@inheritdoc} + */ + public function getType() + { + return $this->type; + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return $this->getType() . ' ' . $this->getPattern(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Call/Then.php b/vendor/behat/behat/src/Behat/Behat/Definition/Call/Then.php new file mode 100644 index 0000000..50dabc1 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Call/Then.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Call; + +/** + * Then steps definition. + * + * @author Konstantin Kudryashov + */ +final class Then extends RuntimeDefinition +{ + /** + * Initializes definition. + * + * @param string $pattern + * @param callable $callable + * @param null|string $description + */ + public function __construct($pattern, $callable, $description = null) + { + parent::__construct('Then', $pattern, $callable, $description); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Call/When.php b/vendor/behat/behat/src/Behat/Behat/Definition/Call/When.php new file mode 100644 index 0000000..1ff6560 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Call/When.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Call; + +/** + * When steps definition. + * + * @author Konstantin Kudryashov + */ +final class When extends RuntimeDefinition +{ + /** + * Initializes definition. + * + * @param string $pattern + * @param callable $callable + * @param null|string $description + */ + public function __construct($pattern, $callable, $description = null) + { + parent::__construct('When', $pattern, $callable, $description); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Cli/AvailableDefinitionsController.php b/vendor/behat/behat/src/Behat/Behat/Definition/Cli/AvailableDefinitionsController.php new file mode 100644 index 0000000..eaa22d4 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Cli/AvailableDefinitionsController.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Cli; + +use Behat\Behat\Definition\DefinitionWriter; +use Behat\Behat\Definition\Printer\ConsoleDefinitionInformationPrinter; +use Behat\Behat\Definition\Printer\ConsoleDefinitionListPrinter; +use Behat\Behat\Definition\Printer\DefinitionPrinter; +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\Suite\SuiteRepository; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Shows all currently available definitions to the user. + * + * @author Konstantin Kudryashov + */ +final class AvailableDefinitionsController implements Controller +{ + /** + * @var SuiteRepository + */ + private $suiteRepository; + /** + * @var DefinitionWriter + */ + private $writer; + /** + * @var ConsoleDefinitionListPrinter + */ + private $listPrinter; + /** + * @var ConsoleDefinitionInformationPrinter + */ + private $infoPrinter; + + /** + * Initializes controller. + * + * @param SuiteRepository $suiteRepository + * @param DefinitionWriter $writer + * @param ConsoleDefinitionListPrinter $listPrinter + * @param ConsoleDefinitionInformationPrinter $infoPrinter + */ + public function __construct( + SuiteRepository $suiteRepository, + DefinitionWriter $writer, + ConsoleDefinitionListPrinter $listPrinter, + ConsoleDefinitionInformationPrinter $infoPrinter + ) { + $this->suiteRepository = $suiteRepository; + $this->writer = $writer; + $this->listPrinter = $listPrinter; + $this->infoPrinter = $infoPrinter; + } + + /** + * {@inheritdoc} + */ + public function configure(Command $command) + { + $command->addOption('--definitions', '-d', InputOption::VALUE_REQUIRED, + "Print all available step definitions:" . PHP_EOL . + "- use --definitions l to just list definition expressions." . PHP_EOL . + "- use --definitions i to show definitions with extended info." . PHP_EOL . + "- use --definitions 'needle' to find specific definitions." . PHP_EOL . + "Use --lang to see definitions in specific language." + ); + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + if (null === $argument = $input->getOption('definitions')) { + return null; + } + + $printer = $this->getDefinitionPrinter($argument); + foreach ($this->suiteRepository->getSuites() as $suite) { + $this->writer->printSuiteDefinitions($printer, $suite); + } + + return 0; + } + + /** + * Returns definition printer for provided option argument. + * + * @param string $argument + * + * @return DefinitionPrinter + */ + private function getDefinitionPrinter($argument) + { + if ('l' === $argument) { + return $this->listPrinter; + } + + if ('i' !== $argument) { + $this->infoPrinter->setSearchCriterion($argument); + } + + return $this->infoPrinter; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Context/Annotation/DefinitionAnnotationReader.php b/vendor/behat/behat/src/Behat/Behat/Definition/Context/Annotation/DefinitionAnnotationReader.php new file mode 100644 index 0000000..baa6c88 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Context/Annotation/DefinitionAnnotationReader.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Context\Annotation; + +use Behat\Behat\Context\Annotation\AnnotationReader; +use ReflectionMethod; + +/** + * Reads definition annotations from the context class. + * + * @author Konstantin Kudryashov + */ +final class DefinitionAnnotationReader implements AnnotationReader +{ + /** + * @var string + */ + private static $regex = '/^\@(given|when|then)\s+(.+)$/i'; + /** + * @var string[] + */ + private static $classes = array( + 'given' => 'Behat\Behat\Definition\Call\Given', + 'when' => 'Behat\Behat\Definition\Call\When', + 'then' => 'Behat\Behat\Definition\Call\Then', + ); + + /** + * {@inheritdoc} + */ + public function readCallee($contextClass, ReflectionMethod $method, $docLine, $description) + { + if (!preg_match(self::$regex, $docLine, $match)) { + return null; + } + + $type = strtolower($match[1]); + $class = self::$classes[$type]; + $pattern = $match[2]; + $callable = array($contextClass, $method->getName()); + + return new $class($pattern, $callable, $description); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Definition.php b/vendor/behat/behat/src/Behat/Behat/Definition/Definition.php new file mode 100644 index 0000000..43b78b5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Definition.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition; + +use Behat\Testwork\Call\Callee; + +/** + * Represents a step definition. + * + * @author Konstantin Kudryashov + */ +interface Definition extends Callee +{ + /** + * Returns definition type (Given|When|Then). + * + * @return string + */ + public function getType(); + + /** + * Returns step pattern exactly as it was defined. + * + * @return string + */ + public function getPattern(); + + /** + * Represents definition as a string. + * + * @return string + */ + public function __toString(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/DefinitionFinder.php b/vendor/behat/behat/src/Behat/Behat/Definition/DefinitionFinder.php new file mode 100644 index 0000000..14d2763 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/DefinitionFinder.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition; + +use Behat\Behat\Definition\Search\SearchEngine; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; + +/** + * Finds specific step definition in environment using registered search engines. + * + * @author Konstantin Kudryashov + */ +final class DefinitionFinder +{ + /** + * @var SearchEngine[] + */ + private $engines = array(); + + /** + * Registers definition search engine. + * + * @param SearchEngine $searchEngine + */ + public function registerSearchEngine(SearchEngine $searchEngine) + { + $this->engines[] = $searchEngine; + } + + /** + * Searches definition for a provided step in a provided environment. + * + * @param Environment $environment + * @param FeatureNode $feature + * @param StepNode $step + * + * @return SearchResult + */ + public function findDefinition(Environment $environment, FeatureNode $feature, StepNode $step) + { + foreach ($this->engines as $engine) { + $result = $engine->searchDefinition($environment, $feature, $step); + + if (null !== $result && $result->hasMatch()) { + return $result; + } + } + + return new SearchResult(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/DefinitionRepository.php b/vendor/behat/behat/src/Behat/Behat/Definition/DefinitionRepository.php new file mode 100644 index 0000000..b1db15a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/DefinitionRepository.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition; + +use Behat\Behat\Definition\Exception\RedundantStepException; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Environment\EnvironmentManager; + +/** + * Provides step definitions using environment manager. + * + * @author Konstantin Kudryashov + */ +final class DefinitionRepository +{ + /** + * @var EnvironmentManager + */ + private $environmentManager; + + /** + * Initializes repository. + * + * @param EnvironmentManager $environmentManager + */ + public function __construct(EnvironmentManager $environmentManager) + { + $this->environmentManager = $environmentManager; + } + + /** + * Returns all available definitions for a specific environment. + * + * @param Environment $environment + * + * @return Definition[] + * + * @throws RedundantStepException + */ + public function getEnvironmentDefinitions(Environment $environment) + { + $patterns = array(); + $definitions = array(); + + foreach ($this->environmentManager->readEnvironmentCallees($environment) as $callee) { + if (!$callee instanceof Definition) { + continue; + } + + $pattern = $callee->getPattern(); + if (isset($patterns[$pattern])) { + throw new RedundantStepException($callee, $patterns[$pattern]); + } + + $patterns[$pattern] = $callee; + + $definitions[] = $callee; + } + + return $definitions; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/DefinitionWriter.php b/vendor/behat/behat/src/Behat/Behat/Definition/DefinitionWriter.php new file mode 100644 index 0000000..204d1ae --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/DefinitionWriter.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition; + +use Behat\Behat\Definition\Printer\DefinitionPrinter; +use Behat\Testwork\Environment\EnvironmentManager; +use Behat\Testwork\Suite\Suite; + +/** + * Prints definitions using provided printer. + * + * @author Konstantin Kudryashov + */ +final class DefinitionWriter +{ + /** + * @var EnvironmentManager + */ + private $environmentManager; + /** + * @var DefinitionRepository + */ + private $repository; + + /** + * Initializes writer. + * + * @param EnvironmentManager $environmentManager + * @param DefinitionRepository $repository + */ + public function __construct(EnvironmentManager $environmentManager, DefinitionRepository $repository) + { + $this->environmentManager = $environmentManager; + $this->repository = $repository; + } + + /** + * Prints definitions for provided suite using printer. + * + * @param DefinitionPrinter $printer + * @param Suite $suite + */ + public function printSuiteDefinitions(DefinitionPrinter $printer, $suite) + { + $environment = $this->environmentManager->buildEnvironment($suite); + $definitions = $this->repository->getEnvironmentDefinitions($environment); + + $printer->printDefinitions($suite, $definitions); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Exception/AmbiguousMatchException.php b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/AmbiguousMatchException.php new file mode 100644 index 0000000..bb5ba33 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/AmbiguousMatchException.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Exception; + +use Behat\Behat\Definition\Definition; +use RuntimeException; + +/** + * Represents an exception caused by an ambiguous step definition match. + * + * If multiple definitions match the same step, behat is not able to determine which one is better and thus this + * exception is thrown and test suite is stopped. + * + * @author Konstantin Kudryashov + */ +final class AmbiguousMatchException extends RuntimeException implements SearchException +{ + /** + * @var string + */ + private $text; + /** + * @var Definition[] + */ + private $matches = array(); + + /** + * Initializes ambiguous exception. + * + * @param string $text step description + * @param Definition[] $matches ambiguous matches (array of Definition's) + */ + public function __construct($text, array $matches) + { + $this->text = $text; + $this->matches = $matches; + + $message = sprintf("Ambiguous match of \"%s\":", $text); + foreach ($matches as $definition) { + $message .= sprintf( + "\nto `%s` from %s", + $definition->getPattern(), + $definition->getPath() + ); + } + + parent::__construct($message); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Exception/DefinitionException.php b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/DefinitionException.php new file mode 100644 index 0000000..07ee2e4 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/DefinitionException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Exception; + +use Behat\Testwork\Exception\TestworkException; + +/** + * Represents an exception thrown during step definition handling. + * + * @author Konstantin Kudryashov + */ +interface DefinitionException extends TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Exception/InvalidPatternException.php b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/InvalidPatternException.php new file mode 100644 index 0000000..1990bea --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/InvalidPatternException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Exception; + +use InvalidArgumentException; + +/** + * Represents an exception caused by an invalid definition pattern (not able to transform it to a regex). + * + * @author Christophe Coevoet + */ +final class InvalidPatternException extends InvalidArgumentException implements DefinitionException +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Exception/RedundantStepException.php b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/RedundantStepException.php new file mode 100644 index 0000000..8a47c5e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/RedundantStepException.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Exception; + +use Behat\Behat\Definition\Definition; +use RuntimeException; + +/** + * Represents an exception caused by a redundant step definition. + * + * If multiple step definitions in the boundaries of the same suite use same regular expression, behat is not able + * to determine which one is better and thus this exception is thrown and test suite is stopped. + * + * @author Konstantin Kudryashov + */ +final class RedundantStepException extends RuntimeException implements SearchException +{ + /** + * Initializes redundant exception. + * + * @param Definition $step2 duplicate step definition + * @param Definition $step1 firstly matched step definition + */ + public function __construct(Definition $step2, Definition $step1) + { + $message = sprintf( + "Step \"%s\" is already defined in %s\n\n%s\n%s", + $step2->getPattern(), $step1->getPath(), $step1->getPath(), $step2->getPath() + ); + + parent::__construct($message); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Exception/SearchException.php b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/SearchException.php new file mode 100644 index 0000000..bc3457b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/SearchException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Exception; + +/** + * Represents an exception caused by a definition search. + * + * @author Konstantin Kudryashov + */ +interface SearchException extends DefinitionException +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Exception/UnknownPatternException.php b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/UnknownPatternException.php new file mode 100644 index 0000000..bc23cb3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/UnknownPatternException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Exception; + +use InvalidArgumentException; + +/** + * Represents an exception caused by an unrecognised definition pattern. + * + * @author Konstantin Kudryashov + */ +final class UnknownPatternException extends InvalidArgumentException implements DefinitionException +{ + /** + * @var string + */ + private $pattern; + + /** + * Initializes exception. + * + * @param string $message + * @param integer $pattern + */ + public function __construct($message, $pattern) + { + $this->pattern = $pattern; + + parent::__construct($message); + } + + /** + * Returns pattern that caused exception. + * + * @return string + */ + public function getPattern() + { + return $this->pattern; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Exception/UnsupportedPatternTypeException.php b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/UnsupportedPatternTypeException.php new file mode 100644 index 0000000..17114e6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Exception/UnsupportedPatternTypeException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Exception; + +use InvalidArgumentException; + +/** + * Represents an exception caused by an unsupported pattern type. + * + * @author Konstantin Kudryashov + */ +final class UnsupportedPatternTypeException extends InvalidArgumentException implements DefinitionException +{ + /** + * @var string + */ + private $type; + + /** + * Initializes exception. + * + * @param string $message + * @param string $type + */ + public function __construct($message, $type) + { + $this->type = $type; + + parent::__construct($message); + } + + /** + * Returns pattern type that caused exception. + * + * @return string + */ + public function getType() + { + return $this->type; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Pattern.php b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Pattern.php new file mode 100644 index 0000000..0a3834f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Pattern.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Pattern; + +/** + * Step definition pattern. + * + * @author Konstantin Kudryashov + */ +final class Pattern +{ + /** + * @var string + */ + private $canonicalText; + /** + * @var string + */ + private $pattern; + /** + * @var integer + */ + private $placeholderCount; + + /** + * Initializes pattern. + * + * @param string $canonicalText + * @param string $pattern + * @param integer $placeholderCount + */ + public function __construct($canonicalText, $pattern, $placeholderCount = 0) + { + $this->canonicalText = $canonicalText; + $this->pattern = $pattern; + $this->placeholderCount = $placeholderCount; + } + + /** + * Returns canonical step text. + * + * @return string + */ + public function getCanonicalText() + { + return $this->canonicalText; + } + + /** + * Returns pattern. + * + * @return string + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * Returns pattern placeholder count. + * + * @return integer + */ + public function getPlaceholderCount() + { + return $this->placeholderCount; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/PatternTransformer.php b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/PatternTransformer.php new file mode 100644 index 0000000..6af5bac --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/PatternTransformer.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Pattern; + +use Behat\Behat\Definition\Exception\UnknownPatternException; +use Behat\Behat\Definition\Exception\UnsupportedPatternTypeException; +use Behat\Behat\Definition\Pattern\Policy\PatternPolicy; + +/** + * Transforms patterns using registered policies. + * + * @author Konstantin Kudryashov + */ +final class PatternTransformer +{ + /** + * @var PatternPolicy[] + */ + private $policies = array(); + + /** + * Registers pattern policy. + * + * @param PatternPolicy $policy + */ + public function registerPatternPolicy(PatternPolicy $policy) + { + $this->policies[] = $policy; + } + + /** + * Generates pattern. + * + * @param string $type + * @param string $stepText + * + * @return Pattern + * + * @throws UnsupportedPatternTypeException + */ + public function generatePattern($type, $stepText) + { + foreach ($this->policies as $policy) { + if ($policy->supportsPatternType($type)) { + return $policy->generatePattern($stepText); + } + } + + throw new UnsupportedPatternTypeException(sprintf('Can not find policy for a pattern type `%s`.', $type), $type); + } + + /** + * Transforms pattern string to regex. + * + * @param string $pattern + * + * @return string + * + * @throws UnknownPatternException + */ + public function transformPatternToRegex($pattern) + { + foreach ($this->policies as $policy) { + if ($policy->supportsPattern($pattern)) { + return $policy->transformPatternToRegex($pattern); + } + } + + throw new UnknownPatternException(sprintf('Can not find policy for a pattern `%s`.', $pattern), $pattern); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/PatternPolicy.php b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/PatternPolicy.php new file mode 100644 index 0000000..2476241 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/PatternPolicy.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Pattern\Policy; + +use Behat\Behat\Definition\Pattern\Pattern; +use Behat\Behat\Definition\Pattern\PatternTransformer; + +/** + * Defines a way to handle custom definition patterns. + * + * @see PatternTransformer + * + * @author Konstantin Kudryashov + */ +interface PatternPolicy +{ + /** + * Checks if policy supports pattern type. + * + * @param string $type + * + * @return Boolean + */ + public function supportsPatternType($type); + + /** + * Generates pattern for step text. + * + * @param string $stepText + * + * @return Pattern + */ + public function generatePattern($stepText); + + /** + * Checks if policy supports pattern. + * + * @param string $pattern + * + * @return Boolean + */ + public function supportsPattern($pattern); + + /** + * Transforms pattern string to regex. + * + * @param string $pattern + * + * @return string + */ + public function transformPatternToRegex($pattern); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/RegexPatternPolicy.php b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/RegexPatternPolicy.php new file mode 100644 index 0000000..6ea50a2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/RegexPatternPolicy.php @@ -0,0 +1,135 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Pattern\Policy; + +use Behat\Behat\Definition\Exception\InvalidPatternException; +use Behat\Behat\Definition\Pattern\Pattern; +use Behat\Transliterator\Transliterator; + +/** + * Defines a way to handle regex patterns. + * + * @author Konstantin Kudryashov + */ +final class RegexPatternPolicy implements PatternPolicy +{ + /** + * @var string[string] + */ + private static $replacePatterns = array( + "/(?<=\W|^)\\\'(?:((?!\\').)*)\\\'(?=\W|$)/" => "'([^']*)'", // Single quoted strings + '/(?<=\W|^)\"(?:[^\"]*)\"(?=\W|$)/' => "\"([^\"]*)\"", // Double quoted strings + '/(?<=\W|^)(\d+)(?=\W|$)/' => "(\\d+)", // Numbers + ); + + /** + * {@inheritdoc} + */ + public function supportsPatternType($type) + { + return 'regex' === $type; + } + + /** + * {@inheritdoc} + */ + public function generatePattern($stepText) + { + $canonicalText = $this->generateCanonicalText($stepText); + $stepRegex = $this->generateRegex($stepText); + $placeholderCount = $this->countPlaceholders($stepText, $stepRegex); + + return new Pattern($canonicalText, '/^' . $stepRegex . '$/', $placeholderCount); + } + + /** + * {@inheritdoc} + */ + public function supportsPattern($pattern) + { + return (bool) preg_match('/^(?:\\{.*\\}|([~\\/#`]).*\1)[imsxADSUXJu]*$/s', $pattern); + } + + /** + * {@inheritdoc} + */ + public function transformPatternToRegex($pattern) + { + if (false === @preg_match($pattern, 'anything')) { + $error = error_get_last(); + $errorMessage = isset($error['message']) ? $error['message'] : ''; + + throw new InvalidPatternException(sprintf('The regex `%s` is invalid: %s', $pattern, $errorMessage)); + } + + return $pattern; + } + + /** + * Generates regex from step text. + * + * @param string $stepText + * + * @return string + */ + private function generateRegex($stepText) + { + return preg_replace( + array_keys(self::$replacePatterns), + array_values(self::$replacePatterns), + $this->escapeStepText($stepText) + ); + } + + /** + * Generates canonical text for step text. + * + * @param string $stepText + * + * @return string + */ + private function generateCanonicalText($stepText) + { + $canonicalText = preg_replace(array_keys(self::$replacePatterns), '', $stepText); + $canonicalText = Transliterator::transliterate($canonicalText, ' '); + $canonicalText = preg_replace('/[^a-zA-Z\_\ ]/', '', $canonicalText); + $canonicalText = str_replace(' ', '', ucwords($canonicalText)); + + return $canonicalText; + } + + /** + * Counts regex placeholders using provided text. + * + * @param string $stepText + * @param string $stepRegex + * + * @return integer + */ + private function countPlaceholders($stepText, $stepRegex) + { + preg_match('/^' . $stepRegex . '$/', $stepText, $matches); + + return count($matches) ? count($matches) - 1 : 0; + } + + /** + * Returns escaped step text. + * + * @param string $stepText + * + * @return string + */ + private function escapeStepText($stepText) + { + return preg_replace('/([\/\[\]\(\)\\\^\$\.\|\?\*\+\'])/', '\\\\$1', $stepText); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/TurnipPatternPolicy.php b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/TurnipPatternPolicy.php new file mode 100644 index 0000000..2722bef --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/TurnipPatternPolicy.php @@ -0,0 +1,183 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Pattern\Policy; + +use Behat\Behat\Definition\Pattern\Pattern; +use Behat\Transliterator\Transliterator; + +/** + * Defines a way to handle turnip patterns. + * + * @author Konstantin Kudryashov + */ +final class TurnipPatternPolicy implements PatternPolicy +{ + const TOKEN_REGEX = "[\"']?(?P<%s>(?<=\")[^\"]*(?=\")|(?<=')[^']*(?=')|[\w\.\,]+)['\"]?"; + + const PLACEHOLDER_REGEXP = "/\\\:(\w+)/"; + const OPTIONAL_WORD_REGEXP = '/(\s)?\\\\\(([^\\\]+)\\\\\)(\s)?/'; + const ALTERNATIVE_WORD_REGEXP = '/(\w+)\\\\\/(\w+)/'; + + /** + * @var string[] + */ + private static $placeholderPatterns = array( + "/(?escapeAlternationSyntax($pattern); + $canonicalText = $this->generateCanonicalText($stepText); + + return new Pattern($canonicalText, $pattern, $count); + } + + /** + * {@inheritdoc} + */ + public function supportsPattern($pattern) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function transformPatternToRegex($pattern) + { + $regex = preg_quote($pattern, '/'); + + $regex = $this->replaceTokensWithRegexCaptureGroups($regex); + $regex = $this->replaceTurnipOptionalEndingWithRegex($regex); + $regex = $this->replaceTurnipAlternativeWordsWithRegex($regex); + + return '/^' . $regex . '$/i'; + } + + /** + * Generates canonical text for step text. + * + * @param string $stepText + * + * @return string + */ + private function generateCanonicalText($stepText) + { + $canonicalText = preg_replace(self::$placeholderPatterns, '', $stepText); + $canonicalText = Transliterator::transliterate($canonicalText, ' '); + $canonicalText = preg_replace('/[^a-zA-Z\_\ ]/', '', $canonicalText); + $canonicalText = str_replace(' ', '', ucwords($canonicalText)); + + return $canonicalText; + } + + /** + * Replaces turnip tokens with regex capture groups. + * + * @param string $regex + * + * @return string + */ + private function replaceTokensWithRegexCaptureGroups($regex) + { + $tokenRegex = self::TOKEN_REGEX; + + return preg_replace_callback( + self::PLACEHOLDER_REGEXP, + function ($match) use ($tokenRegex) { return sprintf($tokenRegex, $match[1]); }, + $regex + ); + } + + /** + * Replaces turnip optional ending with regex non-capturing optional group. + * + * @param string $regex + * + * @return string + */ + private function replaceTurnipOptionalEndingWithRegex($regex) + { + return preg_replace(self::OPTIONAL_WORD_REGEXP, '(?:\1)?(?:\2)?(?:\3)?', $regex); + } + + /** + * Replaces turnip alternative words with regex non-capturing alternating group. + * + * @param string $regex + * + * @return string + */ + private function replaceTurnipAlternativeWordsWithRegex($regex) + { + $regex = preg_replace(self::ALTERNATIVE_WORD_REGEXP, '(?:\1|\2)', $regex); + $regex = $this->removeEscapingOfAlternationSyntax($regex); + + return $regex; + } + + /** + * Adds escaping to alternation syntax in pattern. + * + * By default, Turnip treats `/` as alternation syntax. Meaning `one/two` for Turnip + * means either `one` or `two`. Sometimes though you'll want to use slash character + * with different purpose (URL, UNIX paths). In this case, you would escape slashes + * with backslash. + * + * This method adds escaping to all slashes in generated snippets. + * + * @param string $pattern + * + * @return string + */ + private function escapeAlternationSyntax($pattern) + { + return str_replace('/', '\/', $pattern); + } + + /** + * Removes escaping of alternation syntax from regex. + * + * This method removes those escaping backslashes from your slashes, so your steps + * could be matched against your escaped definitions. + * + * @param string $regex + * + * @return string + */ + private function removeEscapingOfAlternationSyntax($regex) + { + return str_replace('\\\/', '/', $regex); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionInformationPrinter.php b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionInformationPrinter.php new file mode 100644 index 0000000..ea7c736 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionInformationPrinter.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Printer; + +use Behat\Behat\Definition\Definition; +use Behat\Testwork\Suite\Suite; + +/** + * Prints definitions with full information about them. + * + * @author Konstantin Kudryashov + */ +final class ConsoleDefinitionInformationPrinter extends ConsoleDefinitionPrinter +{ + /** + * @var null|string + */ + private $searchCriterion; + + /** + * Sets search criterion. + * + * @param string $criterion + */ + public function setSearchCriterion($criterion) + { + $this->searchCriterion = $criterion; + } + + /** + * {@inheritdoc} + */ + public function printDefinitions(Suite $suite, $definitions) + { + $search = $this->searchCriterion; + $output = array(); + + foreach ($definitions as $definition) { + $definition = $this->translateDefinition($suite, $definition); + $pattern = $definition->getPattern(); + + if (null !== $search && false === mb_strpos($pattern, $search, 0, 'utf8')) { + continue; + } + + $lines = array_merge( + $this->extractHeader($suite, $definition), + $this->extractDescription($suite, $definition), + $this->extractFooter($suite, $definition) + ); + + $output[] = implode(PHP_EOL, $lines) . PHP_EOL; + } + + $this->write(rtrim(implode(PHP_EOL, $output))); + } + + /** + * Extracts the formatted header from the definition. + * + * @param Suite $suite + * @param Definition $definition + * + * @return string[] + */ + private function extractHeader(Suite $suite, Definition $definition) + { + $pattern = $definition->getPattern(); + $lines = array(); + $lines[] = strtr( + '{suite} | {type} {regex}', array( + '{suite}' => $suite->getName(), + '{type}' => $definition->getType(), + '{regex}' => $pattern, + ) + ); + + return $lines; + } + + /** + * Extracts the formatted description from the definition. + * + * @param Suite $suite + * @param Definition $definition + * + * @return string[] + */ + private function extractDescription(Suite $suite, Definition $definition) + { + $definition = $this->translateDefinition($suite, $definition); + + $lines = array(); + if ($description = $definition->getDescription()) { + foreach (explode("\n", $description) as $descriptionLine) { + $lines[] = strtr( + '{space}| {description}', array( + '{space}' => str_pad('', mb_strlen($suite->getName(), 'utf8') + 1), + '{description}' => $descriptionLine + ) + ); + } + } + + return $lines; + } + + /** + * Extracts the formatted footer from the definition. + * + * @param Suite $suite + * @param Definition $definition + * + * @return string[] + */ + private function extractFooter(Suite $suite, Definition $definition) + { + $lines = array(); + $lines[] = strtr( + '{space}| at `{path}`', array( + '{space}' => str_pad('', mb_strlen($suite->getName(), 'utf8') + 1), + '{path}' => $definition->getPath() + ) + ); + + return $lines; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionListPrinter.php b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionListPrinter.php new file mode 100644 index 0000000..8ea4592 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionListPrinter.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Printer; + +use Behat\Testwork\Suite\Suite; + +/** + * Prints simple definitions list. + * + * @author Konstantin Kudryashov + */ +final class ConsoleDefinitionListPrinter extends ConsoleDefinitionPrinter +{ + /** + * {@inheritdoc} + */ + public function printDefinitions(Suite $suite, $definitions) + { + $output = array(); + + foreach ($definitions as $definition) { + $definition = $this->translateDefinition($suite, $definition); + + $output[] = strtr( + '{suite} | {type} {regex}', array( + '{suite}' => $suite->getName(), + '{type}' => str_pad($definition->getType(), 5, ' ', STR_PAD_LEFT), + '{regex}' => $definition->getPattern(), + ) + ); + } + + $this->write(rtrim(implode(PHP_EOL, $output))); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionPrinter.php b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionPrinter.php new file mode 100644 index 0000000..2013da2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionPrinter.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Printer; + +use Behat\Behat\Definition\Definition; +use Behat\Behat\Definition\Pattern\PatternTransformer; +use Behat\Behat\Definition\Translator\DefinitionTranslator; +use Behat\Testwork\Suite\Suite; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Represents console-based definition printer. + * + * @author Konstantin Kudryashov + */ +abstract class ConsoleDefinitionPrinter implements DefinitionPrinter +{ + /** + * @var OutputInterface + */ + private $output; + /** + * @var PatternTransformer + */ + private $patternTransformer; + /** + * @var DefinitionTranslator + */ + private $translator; + + /** + * Initializes printer. + * + * @param OutputInterface $output + * @param PatternTransformer $patternTransformer + * @param DefinitionTranslator $translator + */ + public function __construct( + OutputInterface $output, + PatternTransformer $patternTransformer, + DefinitionTranslator $translator + ) { + $this->output = $output; + $this->patternTransformer = $patternTransformer; + $this->translator = $translator; + + $output->getFormatter()->setStyle('def_regex', new OutputFormatterStyle('yellow')); + $output->getFormatter()->setStyle( + 'def_regex_capture', + new OutputFormatterStyle('yellow', null, array('bold')) + ); + $output->getFormatter()->setStyle( + 'def_dimmed', + new OutputFormatterStyle('black', null, array('bold')) + ); + } + + /** + * Writes text to the console. + * + * @param string $text + */ + final protected function write($text) + { + $this->output->writeln($text); + $this->output->writeln(''); + } + + /** + * Translates definition using translator. + * + * @param Suite $suite + * @param Definition $definition + * + * @return Definition + */ + final protected function translateDefinition(Suite $suite, Definition $definition) + { + return $this->translator->translateDefinition($suite, $definition); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Printer/DefinitionPrinter.php b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/DefinitionPrinter.php new file mode 100644 index 0000000..826ce5b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/DefinitionPrinter.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Printer; + +use Behat\Behat\Definition\Definition; +use Behat\Testwork\Suite\Suite; + +/** + * Prints provided definition. + * + * @author Konstantin Kudryashov + */ +interface DefinitionPrinter +{ + /** + * Prints definition. + * + * @param Suite $suite + * @param Definition[] $definitions + */ + public function printDefinitions(Suite $suite, $definitions); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Search/RepositorySearchEngine.php b/vendor/behat/behat/src/Behat/Behat/Definition/Search/RepositorySearchEngine.php new file mode 100644 index 0000000..6b69485 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Search/RepositorySearchEngine.php @@ -0,0 +1,130 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Search; + +use Behat\Behat\Definition\Definition; +use Behat\Behat\Definition\DefinitionRepository; +use Behat\Behat\Definition\Exception\AmbiguousMatchException; +use Behat\Behat\Definition\Pattern\PatternTransformer; +use Behat\Behat\Definition\SearchResult; +use Behat\Behat\Definition\Translator\DefinitionTranslator; +use Behat\Gherkin\Node\ArgumentInterface; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Argument\ArgumentOrganiser; +use Behat\Testwork\Environment\Environment; + +/** + * Searches for a step definition using definition repository. + * + * @see DefinitionRepository + * + * @author Konstantin Kudryashov + */ +final class RepositorySearchEngine implements SearchEngine +{ + /** + * @var DefinitionRepository + */ + private $repository; + /** + * @var PatternTransformer + */ + private $patternTransformer; + /** + * @var DefinitionTranslator + */ + private $translator; + /** + * @var ArgumentOrganiser + */ + private $argumentOrganiser; + + /** + * Initializes search engine. + * + * @param DefinitionRepository $repository + * @param PatternTransformer $patternTransformer + * @param DefinitionTranslator $translator + * @param ArgumentOrganiser $argumentOrganiser + */ + public function __construct( + DefinitionRepository $repository, + PatternTransformer $patternTransformer, + DefinitionTranslator $translator, + ArgumentOrganiser $argumentOrganiser + ) { + $this->repository = $repository; + $this->patternTransformer = $patternTransformer; + $this->translator = $translator; + $this->argumentOrganiser = $argumentOrganiser; + } + + /** + * {@inheritdoc} + * + * @throws AmbiguousMatchException + */ + public function searchDefinition( + Environment $environment, + FeatureNode $feature, + StepNode $step + ) { + $suite = $environment->getSuite(); + $language = $feature->getLanguage(); + $stepText = $step->getText(); + $multi = $step->getArguments(); + + $definitions = array(); + $result = null; + + foreach ($this->repository->getEnvironmentDefinitions($environment) as $definition) { + $definition = $this->translator->translateDefinition($suite, $definition, $language); + + if (!$newResult = $this->match($definition, $stepText, $multi)) { + continue; + } + + $result = $newResult; + $definitions[] = $newResult->getMatchedDefinition(); + } + + if (count($definitions) > 1) { + throw new AmbiguousMatchException($result->getMatchedText(), $definitions); + } + + return $result; + } + + /** + * Attempts to match provided definition against a step text. + * + * @param Definition $definition + * @param string $stepText + * @param ArgumentInterface[] $multiline + * + * @return null|SearchResult + */ + private function match(Definition $definition, $stepText, array $multiline) + { + $regex = $this->patternTransformer->transformPatternToRegex($definition->getPattern()); + + if (!preg_match($regex, $stepText, $match)) { + return null; + } + + $function = $definition->getReflection(); + $match = array_merge($match, array_values($multiline)); + $arguments = $this->argumentOrganiser->organiseArguments($function, $match); + + return new SearchResult($definition, $stepText, $arguments); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Search/SearchEngine.php b/vendor/behat/behat/src/Behat/Behat/Definition/Search/SearchEngine.php new file mode 100644 index 0000000..a869adc --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Search/SearchEngine.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Search; + +use Behat\Behat\Definition\DefinitionFinder; +use Behat\Behat\Definition\SearchResult; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; + +/** + * Searches for a step definition in a specific environment. + * + * @see DefinitionFinder + * + * @author Konstantin Kudryashov + */ +interface SearchEngine +{ + /** + * Searches for a step definition. + * + * @param Environment $environment + * @param FeatureNode $feature + * @param StepNode $step + * + * @return null|SearchResult + */ + public function searchDefinition(Environment $environment, FeatureNode $feature, StepNode $step); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/SearchResult.php b/vendor/behat/behat/src/Behat/Behat/Definition/SearchResult.php new file mode 100644 index 0000000..158f635 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/SearchResult.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition; + +/** + * Step definition search result. + * + * @author Konstantin Kudryashov + */ +final class SearchResult +{ + /** + * @var null|Definition + */ + private $definition; + /** + * @var null|string + */ + private $matchedText; + /** + * @var null|array + */ + private $arguments; + + /** + * Registers search match. + * + * @param null|Definition $definition + * @param null|string $matchedText + * @param null|array $arguments + */ + public function __construct(Definition $definition = null, $matchedText = null, array $arguments = null) + { + $this->definition = $definition; + $this->matchedText = $matchedText; + $this->arguments = $arguments; + } + + /** + * Checks if result contains a match. + * + * @return Boolean + */ + public function hasMatch() + { + return null !== $this->definition; + } + + /** + * Returns matched definition. + * + * @return null|Definition + */ + public function getMatchedDefinition() + { + return $this->definition; + } + + /** + * Returns matched text. + * + * @return null|string + */ + public function getMatchedText() + { + return $this->matchedText; + } + + /** + * Returns matched definition arguments. + * + * @return null|array + */ + public function getMatchedArguments() + { + return $this->arguments; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/ServiceContainer/DefinitionExtension.php b/vendor/behat/behat/src/Behat/Behat/Definition/ServiceContainer/DefinitionExtension.php new file mode 100644 index 0000000..68f56ae --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/ServiceContainer/DefinitionExtension.php @@ -0,0 +1,307 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\ServiceContainer; + +use Behat\Behat\Context\ServiceContainer\ContextExtension; +use Behat\Testwork\Argument\ServiceContainer\ArgumentExtension; +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\Environment\ServiceContainer\EnvironmentExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Suite\ServiceContainer\SuiteExtension; +use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Extends Behat with definition services. + * + * @author Konstantin Kudryashov + */ +final class DefinitionExtension implements Extension +{ + /* + * Available services + */ + const FINDER_ID = 'definition.finder'; + const REPOSITORY_ID = 'definition.repository'; + const PATTERN_TRANSFORMER_ID = 'definition.pattern_transformer'; + const WRITER_ID = 'definition.writer'; + const DEFINITION_TRANSLATOR_ID = 'definition.translator'; + + /* + * Available extension points + */ + const SEARCH_ENGINE_TAG = 'definition.search_engine'; + const PATTERN_POLICY_TAG = 'definition.pattern_policy'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes compiler pass. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'definitions'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadFinder($container); + $this->loadRepository($container); + $this->loadWriter($container); + $this->loadPatternTransformer($container); + $this->loadDefinitionTranslator($container); + $this->loadDefaultSearchEngines($container); + $this->loadDefaultPatternPolicies($container); + $this->loadAnnotationReader($container); + $this->loadDefinitionPrinters($container); + $this->loadController($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processSearchEngines($container); + $this->processPatternPolicies($container); + } + + /** + * Loads definition finder. + * + * @param ContainerBuilder $container + */ + private function loadFinder(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\DefinitionFinder'); + $container->setDefinition(self::FINDER_ID, $definition); + } + + /** + * Loads definition repository. + * + * @param ContainerBuilder $container + */ + private function loadRepository(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\DefinitionRepository', array( + new Reference(EnvironmentExtension::MANAGER_ID) + )); + $container->setDefinition(self::REPOSITORY_ID, $definition); + } + + /** + * Loads definition writer. + * + * @param ContainerBuilder $container + */ + private function loadWriter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\DefinitionWriter', array( + new Reference(EnvironmentExtension::MANAGER_ID), + new Reference(self::REPOSITORY_ID) + )); + $container->setDefinition(self::WRITER_ID, $definition); + } + + /** + * Loads definition pattern transformer. + * + * @param ContainerBuilder $container + */ + private function loadPatternTransformer(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\Pattern\PatternTransformer'); + $container->setDefinition(self::PATTERN_TRANSFORMER_ID, $definition); + } + + /** + * Loads definition translator. + * + * @param ContainerBuilder $container + */ + private function loadDefinitionTranslator(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\Translator\DefinitionTranslator', array( + new Reference(TranslatorExtension::TRANSLATOR_ID) + )); + $container->setDefinition(self::DEFINITION_TRANSLATOR_ID, $definition); + } + + /** + * Loads default search engines. + * + * @param ContainerBuilder $container + */ + private function loadDefaultSearchEngines(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\Search\RepositorySearchEngine', array( + new Reference(self::REPOSITORY_ID), + new Reference(self::PATTERN_TRANSFORMER_ID), + new Reference(self::DEFINITION_TRANSLATOR_ID), + new Reference(ArgumentExtension::PREG_MATCH_ARGUMENT_ORGANISER_ID) + )); + $definition->addTag(self::SEARCH_ENGINE_TAG, array('priority' => 50)); + $container->setDefinition(self::SEARCH_ENGINE_TAG . '.repository', $definition); + } + + /** + * Loads default pattern policies. + * + * @param ContainerBuilder $container + */ + private function loadDefaultPatternPolicies(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\Pattern\Policy\TurnipPatternPolicy'); + $definition->addTag(self::PATTERN_POLICY_TAG, array('priority' => 50)); + $container->setDefinition(self::PATTERN_POLICY_TAG . '.turnip', $definition); + + $definition = new Definition('Behat\Behat\Definition\Pattern\Policy\RegexPatternPolicy'); + $definition->addTag(self::PATTERN_POLICY_TAG, array('priority' => 60)); + $container->setDefinition(self::PATTERN_POLICY_TAG . '.regex', $definition); + } + + /** + * Loads definition annotation reader. + * + * @param ContainerBuilder $container + */ + private function loadAnnotationReader(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\Context\Annotation\DefinitionAnnotationReader'); + $definition->addTag(ContextExtension::ANNOTATION_READER_TAG, array('priority' => 50)); + $container->setDefinition(ContextExtension::ANNOTATION_READER_TAG . '.definition', $definition); + } + + /** + * Loads definition printers. + * + * @param ContainerBuilder $container + */ + private function loadDefinitionPrinters(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\Printer\ConsoleDefinitionInformationPrinter', array( + new Reference(CliExtension::OUTPUT_ID), + new Reference(self::PATTERN_TRANSFORMER_ID), + new Reference(self::DEFINITION_TRANSLATOR_ID) + )); + $container->setDefinition($this->getInformationPrinterId(), $definition); + + $definition = new Definition('Behat\Behat\Definition\Printer\ConsoleDefinitionListPrinter', array( + new Reference(CliExtension::OUTPUT_ID), + new Reference(self::PATTERN_TRANSFORMER_ID), + new Reference(self::DEFINITION_TRANSLATOR_ID) + )); + $container->setDefinition($this->getListPrinterId(), $definition); + } + + /** + * Loads definition controller. + * + * @param ContainerBuilder $container + */ + private function loadController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Definition\Cli\AvailableDefinitionsController', array( + new Reference(SuiteExtension::REGISTRY_ID), + new Reference(self::WRITER_ID), + new Reference($this->getListPrinterId()), + new Reference($this->getInformationPrinterId()) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 500)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.available_definitions', $definition); + } + + /** + * Processes all search engines in the container. + * + * @param ContainerBuilder $container + */ + private function processSearchEngines(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::SEARCH_ENGINE_TAG); + $definition = $container->getDefinition(self::FINDER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerSearchEngine', array($reference)); + } + } + + /** + * Processes all pattern policies. + * + * @param ContainerBuilder $container + */ + private function processPatternPolicies(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::PATTERN_POLICY_TAG); + $definition = $container->getDefinition(self::PATTERN_TRANSFORMER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerPatternPolicy', array($reference)); + } + } + + /** + * returns list printer service id. + * + * @return string + */ + private function getListPrinterId() + { + return 'definition.list_printer'; + } + + /** + * Returns information printer service id. + * + * @return string + */ + private function getInformationPrinterId() + { + return 'definition.information_printer'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Translator/DefinitionTranslator.php b/vendor/behat/behat/src/Behat/Behat/Definition/Translator/DefinitionTranslator.php new file mode 100644 index 0000000..163478c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Translator/DefinitionTranslator.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Translator; + +use Behat\Behat\Definition\Definition; +use Behat\Testwork\Suite\Suite; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Translates definitions using translator component. + * + * @author Konstantin Kudryashov + */ +final class DefinitionTranslator +{ + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * Initialises definition translator. + * + * @param TranslatorInterface $translator + */ + public function __construct(TranslatorInterface $translator) + { + $this->translator = $translator; + } + + /** + * Attempts to translate definition using translator and produce translated one on success. + * + * @param Suite $suite + * @param Definition $definition + * @param null|string $language + * + * @return Definition|TranslatedDefinition + */ + public function translateDefinition(Suite $suite, Definition $definition, $language = null) + { + $assetsId = $suite->getName(); + $pattern = $definition->getPattern(); + + $translatedPattern = $this->translator->trans($pattern, array(), $assetsId, $language); + if ($pattern != $translatedPattern) { + return new TranslatedDefinition($definition, $translatedPattern, $language); + } + + return $definition; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Definition/Translator/TranslatedDefinition.php b/vendor/behat/behat/src/Behat/Behat/Definition/Translator/TranslatedDefinition.php new file mode 100644 index 0000000..69813fa --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Translator/TranslatedDefinition.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Definition\Translator; + +use Behat\Behat\Definition\Definition; + +/** + * Represents definition translated to the specific language. + * + * @author Konstantin Kudryashov + */ +final class TranslatedDefinition implements Definition +{ + /** + * @var Definition + */ + private $definition; + /** + * @var string + */ + private $translatedPattern; + /** + * @var string + */ + private $language; + + /** + * Initialises translated definition. + * + * @param Definition $definition + * @param string $translatedPattern + * @param string $language + */ + public function __construct(Definition $definition, $translatedPattern, $language) + { + $this->definition = $definition; + $this->translatedPattern = $translatedPattern; + $this->language = $language; + } + + /** + * {@inheritdoc} + */ + public function getType() + { + return $this->definition->getType(); + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return $this->translatedPattern; + } + + /** + * Returns original (not translated) pattern. + * + * @return string + */ + public function getOriginalPattern() + { + return $this->definition->getPattern(); + } + + /** + * Returns language definition was translated to. + * + * @return string + */ + public function getLanguage() + { + return $this->language; + } + + /** + * {@inheritdoc} + */ + public function getDescription() + { + return $this->definition->getDescription(); + } + + /** + * {@inheritdoc} + */ + public function getPath() + { + return $this->definition->getPath(); + } + + /** + * {@inheritdoc} + */ + public function isAMethod() + { + return $this->definition->isAMethod(); + } + + /** + * {@inheritdoc} + */ + public function isAnInstanceMethod() + { + return $this->definition->isAnInstanceMethod(); + } + + /** + * {@inheritdoc} + */ + public function getCallable() + { + return $this->definition->getCallable(); + } + + /** + * {@inheritdoc} + */ + public function getReflection() + { + return $this->definition->getReflection(); + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return $this->definition->__toString(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Cli/StopOnFailureController.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Cli/StopOnFailureController.php new file mode 100644 index 0000000..0767b9a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Cli/StopOnFailureController.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Cli; + +use Behat\Behat\EventDispatcher\Event\AfterScenarioTested; +use Behat\Behat\EventDispatcher\Event\ExampleTested; +use Behat\Behat\EventDispatcher\Event\ScenarioTested; +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\EventDispatcher\Event\AfterExerciseAborted; +use Behat\Testwork\EventDispatcher\Event\AfterSuiteAborted; +use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted; +use Behat\Testwork\EventDispatcher\Event\SuiteTested; +use Behat\Testwork\Tester\Result\TestResult; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Stops tests on first scenario failure. + * + * @author Konstantin Kudryashov + */ +final class StopOnFailureController implements Controller +{ + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * Initializes controller. + * + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(EventDispatcherInterface $eventDispatcher) + { + $this->eventDispatcher = $eventDispatcher; + } + + /** + * Configures command to be executable by the controller. + * + * @param Command $command + */ + public function configure(Command $command) + { + $command->addOption('--stop-on-failure', null, InputOption::VALUE_NONE, + 'Stop processing on first failed scenario.' + ); + } + + /** + * Executes controller. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return null|integer + */ + public function execute(InputInterface $input, OutputInterface $output) + { + if (!$input->getOption('stop-on-failure')) { + return null; + } + + $this->eventDispatcher->addListener(ScenarioTested::AFTER, array($this, 'exitOnFailure'), -100); + $this->eventDispatcher->addListener(ExampleTested::AFTER, array($this, 'exitOnFailure'), -100); + } + + /** + * Exits if scenario is a failure and if stopper is enabled. + * + * @param AfterScenarioTested $event + */ + public function exitOnFailure(AfterScenarioTested $event) + { + if (TestResult::FAILED !== $event->getTestResult()->getResultCode()) { + return; + } + + $this->eventDispatcher->dispatch(SuiteTested::AFTER, new AfterSuiteAborted($event->getEnvironment())); + $this->eventDispatcher->dispatch(ExerciseCompleted::AFTER, new AfterExerciseAborted()); + + exit(1); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterBackgroundSetup.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterBackgroundSetup.php new file mode 100644 index 0000000..59b32ad --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterBackgroundSetup.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\BackgroundNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterSetup; +use Behat\Testwork\Tester\Setup\Setup; + +/** + * Represents an event right after background was setup for testing. + * + * @author Konstantin Kudryashov + */ +final class AfterBackgroundSetup extends BackgroundTested implements AfterSetup +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var BackgroundNode + */ + private $background; + /** + * @var Setup + */ + private $setup; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param BackgroundNode $background + * @param Setup $setup + */ + public function __construct(Environment $env, FeatureNode $feature, BackgroundNode $background, Setup $setup) + { + parent::__construct($env); + + $this->feature = $feature; + $this->background = $background; + $this->setup = $setup; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario node. + * + * @return ScenarioInterface + */ + public function getScenario() + { + return $this->background; + } + + /** + * Returns background node. + * + * @return BackgroundNode + */ + public function getBackground() + { + return $this->background; + } + + /** + * Returns current test setup. + * + * @return Setup + */ + public function getSetup() + { + return $this->setup; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterBackgroundTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterBackgroundTested.php new file mode 100644 index 0000000..76e1577 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterBackgroundTested.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\BackgroundNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterTested; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents an event in which background was tested. + * + * @author Konstantin Kudryashov + */ +final class AfterBackgroundTested extends BackgroundTested implements AfterTested +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var BackgroundNode + */ + private $background; + /** + * @var TestResult + */ + private $result; + /** + * @var Teardown + */ + private $teardown; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param BackgroundNode $background + * @param TestResult $result + * @param Teardown $teardown + */ + public function __construct( + Environment $env, + FeatureNode $feature, + BackgroundNode $background, + TestResult $result, + Teardown $teardown + ) { + parent::__construct($env); + + $this->feature = $feature; + $this->background = $background; + $this->result = $result; + $this->teardown = $teardown; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario node. + * + * @return ScenarioInterface + */ + public function getScenario() + { + return $this->background; + } + + /** + * Returns background node. + * + * @return BackgroundNode + */ + public function getBackground() + { + return $this->background; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } + + /** + * Returns current test teardown. + * + * @return Teardown + */ + public function getTeardown() + { + return $this->teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterFeatureSetup.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterFeatureSetup.php new file mode 100644 index 0000000..73076ea --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterFeatureSetup.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterSetup; +use Behat\Testwork\Tester\Setup\Setup; + +/** + * Represents an event right after feature is setup for a test. + * + * @author Konstantin Kudryashov + */ +final class AfterFeatureSetup extends FeatureTested implements AfterSetup +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var Setup + */ + private $setup; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Setup $setup + */ + public function __construct(Environment $env, FeatureNode $feature, Setup $setup) + { + parent::__construct($env); + + $this->feature = $feature; + $this->setup = $setup; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns current test setup. + * + * @return Setup + */ + public function getSetup() + { + return $this->setup; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterFeatureTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterFeatureTested.php new file mode 100644 index 0000000..ed19128 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterFeatureTested.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterTested; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents an event right after feature was tested. + * + * @author Konstantin Kudryashov + */ +final class AfterFeatureTested extends FeatureTested implements AfterTested +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var TestResult + */ + private $result; + /** + * @var Teardown + */ + private $teardown; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param TestResult $result + * @param Teardown $teardown + */ + public function __construct(Environment $env, FeatureNode $feature, TestResult $result, Teardown $teardown) + { + parent::__construct($env); + + $this->feature = $feature; + $this->result = $result; + $this->teardown = $teardown; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } + + /** + * Returns current test teardown. + * + * @return Teardown + */ + public function getTeardown() + { + return $this->teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterOutlineSetup.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterOutlineSetup.php new file mode 100644 index 0000000..3251d24 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterOutlineSetup.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterSetup; +use Behat\Testwork\Tester\Setup\Setup; + +/** + * Represents an event right after outline setup. + * + * @author Konstantin Kudryashov + */ +final class AfterOutlineSetup extends OutlineTested implements AfterSetup +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var OutlineNode + */ + private $outline; + /** + * @var Setup + */ + private $setup; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param OutlineNode $outline + * @param Setup $setup + */ + public function __construct(Environment $env, FeatureNode $feature, OutlineNode $outline, Setup $setup) + { + parent::__construct($env); + + $this->feature = $feature; + $this->outline = $outline; + $this->setup = $setup; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns outline node. + * + * @return OutlineNode + */ + public function getOutline() + { + return $this->outline; + } + + /** + * Returns current test setup. + * + * @return Setup + */ + public function getSetup() + { + return $this->setup; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterOutlineTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterOutlineTested.php new file mode 100644 index 0000000..b4fd1a2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterOutlineTested.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterTested; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents an event after outline was tested. + * + * @author Konstantin Kudryashov + */ +final class AfterOutlineTested extends OutlineTested implements AfterTested +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var OutlineNode + */ + private $outline; + /** + * @var TestResult + */ + private $result; + /** + * @var Teardown + */ + private $teardown; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param OutlineNode $outline + * @param TestResult $result + * @param Teardown $teardown + */ + public function __construct( + Environment $env, + FeatureNode $feature, + OutlineNode $outline, + TestResult $result, + Teardown $teardown + ) { + parent::__construct($env); + + $this->feature = $feature; + $this->outline = $outline; + $this->result = $result; + $this->teardown = $teardown; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns outline node. + * + * @return OutlineNode + */ + public function getOutline() + { + return $this->outline; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } + + /** + * Returns current test teardown. + * + * @return Teardown + */ + public function getTeardown() + { + return $this->teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterScenarioSetup.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterScenarioSetup.php new file mode 100644 index 0000000..38666bf --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterScenarioSetup.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\ScenarioNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterSetup; +use Behat\Testwork\Tester\Setup\Setup; + +/** + * Represents an event after scenario setup. + * + * @author Konstantin Kudryashov + */ +final class AfterScenarioSetup extends ScenarioTested implements AfterSetup +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var Scenario + */ + private $scenario; + /** + * @var Setup + */ + private $setup; + + /** + * Initializes event + * + * @param Environment $env + * @param FeatureNode $feature + * @param Scenario $scenario + * @param Setup $setup + */ + public function __construct(Environment $env, FeatureNode $feature, Scenario $scenario, Setup $setup) + { + parent::__construct($env); + + $this->feature = $feature; + $this->scenario = $scenario; + $this->setup = $setup; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario node. + * + * @return ScenarioNode + */ + public function getScenario() + { + return $this->scenario; + } + + /** + * Returns current test setup. + * + * @return Setup + */ + public function getSetup() + { + return $this->setup; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterScenarioTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterScenarioTested.php new file mode 100644 index 0000000..6af6f18 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterScenarioTested.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\ScenarioNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterTested; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents an event after scenario has been tested. + * + * @author Konstantin Kudryashov + */ +final class AfterScenarioTested extends ScenarioTested implements AfterTested +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var Scenario + */ + private $scenario; + /** + * @var TestResult + */ + private $result; + /** + * @var Teardown + */ + private $teardown; + + /** + * Initializes event + * + * @param Environment $env + * @param FeatureNode $feature + * @param Scenario $scenario + * @param TestResult $result + * @param Teardown $teardown + */ + public function __construct( + Environment $env, + FeatureNode $feature, + Scenario $scenario, + TestResult $result, + Teardown $teardown + ) { + parent::__construct($env); + + $this->feature = $feature; + $this->scenario = $scenario; + $this->result = $result; + $this->teardown = $teardown; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario node. + * + * @return ScenarioNode + */ + public function getScenario() + { + return $this->scenario; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } + + /** + * Returns current test teardown. + * + * @return Teardown + */ + public function getTeardown() + { + return $this->teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterStepSetup.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterStepSetup.php new file mode 100644 index 0000000..cf9b6c5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterStepSetup.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterSetup; +use Behat\Testwork\Tester\Setup\Setup; + +/** + * Represents an event after step setup. + * + * @author Konstantin Kudryashov + */ +final class AfterStepSetup extends StepTested implements AfterSetup +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var StepNode + */ + private $step; + /** + * @var Setup + */ + private $setup; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + * @param Setup $setup + */ + public function __construct(Environment $env, FeatureNode $feature, StepNode $step, Setup $setup) + { + parent::__construct($env); + + $this->feature = $feature; + $this->step = $step; + $this->setup = $setup; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns step node. + * + * @return StepNode + */ + public function getStep() + { + return $this->step; + } + + /** + * Returns current test setup. + * + * @return Setup + */ + public function getSetup() + { + return $this->setup; + } + + /** + * Checks if step call, setup or teardown produced any output (stdOut or exception). + * + * @return Boolean + */ + public function hasOutput() + { + return $this->setup->hasOutput(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterStepTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterStepTested.php new file mode 100644 index 0000000..37b497b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/AfterStepTested.php @@ -0,0 +1,154 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Behat\Tester\Result\ExecutedStepResult; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterTested; +use Behat\Testwork\Tester\Result\ExceptionResult; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents an event after step has been tested. + * + * @author Konstantin Kudryashov + */ +final class AfterStepTested extends StepTested implements AfterTested +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var StepNode + */ + private $step; + /** + * @var StepResult + */ + private $result; + /** + * @var Teardown + */ + private $teardown; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + * @param StepResult $result + * @param Teardown $teardown + */ + public function __construct( + Environment $env, + FeatureNode $feature, + StepNode $step, + StepResult $result, + Teardown $teardown + ) { + parent::__construct($env); + + $this->feature = $feature; + $this->step = $step; + $this->result = $result; + $this->teardown = $teardown; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns step node. + * + * @return StepNode + */ + public function getStep() + { + return $this->step; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } + + /** + * Returns current test teardown. + * + * @return Teardown + */ + public function getTeardown() + { + return $this->teardown; + } + + /** + * Checks if step call, setup or teardown produced any output (stdOut or exception). + * + * @return Boolean + */ + public function hasOutput() + { + return $this->teardownHasOutput() || $this->resultHasException() || $this->resultCallHasOutput(); + } + + /** + * Checks if step teardown has output. + * + * @return Boolean + */ + private function teardownHasOutput() + { + return $this->teardown->hasOutput(); + } + + /** + * Checks if result has produced exception. + * + * @return Boolean + */ + private function resultHasException() + { + return $this->result instanceof ExceptionResult && $this->result->getException(); + } + + /** + * Checks if result is executed and call result has produced exception or stdOut. + * + * @return Boolean + */ + private function resultCallHasOutput() + { + if (!$this->result instanceof ExecutedStepResult) { + return false; + } + + return $this->result->getCallResult()->hasStdOut() || $this->result->getCallResult()->hasException(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BackgroundTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BackgroundTested.php new file mode 100644 index 0000000..f67f855 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BackgroundTested.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\BackgroundNode; +use Behat\Gherkin\Node\NodeInterface; +use Behat\Testwork\EventDispatcher\Event\LifecycleEvent; + +/** + * Represents a background event. + * + * @author Konstantin Kudryashov + */ +abstract class BackgroundTested extends LifecycleEvent implements ScenarioLikeTested +{ + const BEFORE = 'tester.background_tested.before'; + const AFTER_SETUP = 'tester.background_tested.after_setup'; + const BEFORE_TEARDOWN = 'tester.background_tested.before_teardown'; + const AFTER = 'tester.background_tested.after'; + + /** + * Returns background node. + * + * @return BackgroundNode + */ + abstract public function getBackground(); + + /** + * Returns node. + * + * @return NodeInterface + */ + final public function getNode() + { + return $this->getBackground(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeBackgroundTeardown.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeBackgroundTeardown.php new file mode 100644 index 0000000..b416717 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeBackgroundTeardown.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\BackgroundNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTeardown; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an event right before background teardown. + * + * @author Konstantin Kudryashov + */ +final class BeforeBackgroundTeardown extends BackgroundTested implements BeforeTeardown +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var BackgroundNode + */ + private $background; + /** + * @var TestResult + */ + private $result; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param BackgroundNode $background + * @param TestResult $result + */ + public function __construct( + Environment $env, + FeatureNode $feature, + BackgroundNode $background, + TestResult $result + ) { + parent::__construct($env); + + $this->feature = $feature; + $this->background = $background; + $this->result = $result; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario node. + * + * @return ScenarioInterface + */ + public function getScenario() + { + return $this->background; + } + + /** + * Returns background node. + * + * @return BackgroundNode + */ + public function getBackground() + { + return $this->background; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeBackgroundTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeBackgroundTested.php new file mode 100644 index 0000000..d88a6f9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeBackgroundTested.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\BackgroundNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTested; + +/** + * Represents a BeforeBackgroundTested event. + * + * @author Konstantin Kudryashov + */ +final class BeforeBackgroundTested extends BackgroundTested implements BeforeTested +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var BackgroundNode + */ + private $background; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param BackgroundNode $background + */ + public function __construct(Environment $env, FeatureNode $feature, BackgroundNode $background) + { + parent::__construct($env); + + $this->feature = $feature; + $this->background = $background; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario node. + * + * @return ScenarioInterface + */ + public function getScenario() + { + return $this->background; + } + + /** + * Returns background node. + * + * @return BackgroundNode + */ + public function getBackground() + { + return $this->background; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeFeatureTeardown.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeFeatureTeardown.php new file mode 100644 index 0000000..82c9c7b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeFeatureTeardown.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTeardown; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an event right before feature is teardown. + * + * @author Konstantin Kudryashov + */ +final class BeforeFeatureTeardown extends FeatureTested implements BeforeTeardown +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var TestResult + */ + private $result; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param TestResult $result + */ + public function __construct(Environment $env, FeatureNode $feature, TestResult $result) + { + parent::__construct($env); + + $this->feature = $feature; + $this->result = $result; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeFeatureTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeFeatureTested.php new file mode 100644 index 0000000..1f2f4ea --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeFeatureTested.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTested; + +/** + * Represents an event before feature tested. + * + * @author Konstantin Kudryashov + */ +final class BeforeFeatureTested extends FeatureTested implements BeforeTested +{ + /** + * @var FeatureNode + */ + private $feature; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + */ + public function __construct(Environment $env, FeatureNode $feature) + { + parent::__construct($env); + + $this->feature = $feature; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeOutlineTeardown.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeOutlineTeardown.php new file mode 100644 index 0000000..7980267 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeOutlineTeardown.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTeardown; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an event right before outline teardown. + * + * @author Konstantin Kudryashov + */ +final class BeforeOutlineTeardown extends OutlineTested implements BeforeTeardown +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var OutlineNode + */ + private $outline; + /** + * @var TestResult + */ + private $result; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param OutlineNode $outline + * @param TestResult $result + */ + public function __construct( + Environment $env, + FeatureNode $feature, + OutlineNode $outline, + TestResult $result + ) { + parent::__construct($env); + + $this->feature = $feature; + $this->outline = $outline; + $this->result = $result; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns outline node. + * + * @return OutlineNode + */ + public function getOutline() + { + return $this->outline; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeOutlineTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeOutlineTested.php new file mode 100644 index 0000000..25aa4fd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeOutlineTested.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTested; + +/** + * Represents an event before outline is tested. + * + * @author Konstantin Kudryashov + */ +final class BeforeOutlineTested extends OutlineTested implements BeforeTested +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var OutlineNode + */ + private $outline; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param OutlineNode $outline + */ + public function __construct(Environment $env, FeatureNode $feature, OutlineNode $outline) + { + parent::__construct($env); + + $this->feature = $feature; + $this->outline = $outline; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns outline node. + * + * @return OutlineNode + */ + public function getOutline() + { + return $this->outline; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeScenarioTeardown.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeScenarioTeardown.php new file mode 100644 index 0000000..da413b4 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeScenarioTeardown.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\ScenarioNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTeardown; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an event before scenario teardown. + * + * @author Konstantin Kudryashov + */ +final class BeforeScenarioTeardown extends ScenarioTested implements BeforeTeardown +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var Scenario + */ + private $scenario; + /** + * @var TestResult + */ + private $result; + + /** + * Initializes event + * + * @param Environment $env + * @param FeatureNode $feature + * @param Scenario $scenario + * @param TestResult $result + */ + public function __construct( + Environment $env, + FeatureNode $feature, + Scenario $scenario, + TestResult $result + ) { + parent::__construct($env); + + $this->feature = $feature; + $this->scenario = $scenario; + $this->result = $result; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario node. + * + * @return ScenarioNode + */ + public function getScenario() + { + return $this->scenario; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeScenarioTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeScenarioTested.php new file mode 100644 index 0000000..d2737b8 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeScenarioTested.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\ScenarioNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTested; + +/** + * Represents an event before scenario is tested. + * + * @author Konstantin Kudryashov + */ +final class BeforeScenarioTested extends ScenarioTested implements BeforeTested +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var Scenario + */ + private $scenario; + + /** + * Initializes event + * + * @param Environment $env + * @param FeatureNode $feature + * @param Scenario $scenario + */ + public function __construct(Environment $env, FeatureNode $feature, Scenario $scenario) + { + parent::__construct($env); + + $this->feature = $feature; + $this->scenario = $scenario; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario node. + * + * @return ScenarioNode + */ + public function getScenario() + { + return $this->scenario; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeStepTeardown.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeStepTeardown.php new file mode 100644 index 0000000..6d9b9c6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeStepTeardown.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Behat\Tester\Result\ExecutedStepResult; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTeardown; +use Behat\Testwork\Tester\Result\ExceptionResult; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an event before step teardown. + * + * @author Konstantin Kudryashov + */ +final class BeforeStepTeardown extends StepTested implements BeforeTeardown +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var StepNode + */ + private $step; + /** + * @var StepResult + */ + private $result; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + * @param StepResult $result + */ + public function __construct( + Environment $env, + FeatureNode $feature, + StepNode $step, + StepResult $result + ) { + parent::__construct($env); + + $this->feature = $feature; + $this->step = $step; + $this->result = $result; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns step node. + * + * @return StepNode + */ + public function getStep() + { + return $this->step; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } + + /** + * Checks if step call produced any output (stdOut or exception). + * + * @return Boolean + */ + public function hasOutput() + { + return $this->resultHasException() || $this->resultCallHasOutput(); + } + + /** + * Checks if result has produced exception. + * + * @return Boolean + */ + private function resultHasException() + { + return $this->result instanceof ExceptionResult && $this->result->getException(); + } + + /** + * Checks if result is executed and call result has produced exception or stdOut. + * + * @return Boolean + */ + private function resultCallHasOutput() + { + if (!$this->result instanceof ExecutedStepResult) { + return false; + } + + return $this->result->getCallResult()->hasStdOut() || $this->result->getCallResult()->hasException(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeStepTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeStepTested.php new file mode 100644 index 0000000..22b1e09 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/BeforeStepTested.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\BeforeTested; + +/** + * Represents an event before step test. + * + * @author Konstantin Kudryashov + */ +final class BeforeStepTested extends StepTested implements BeforeTested +{ + /** + * @var FeatureNode + */ + private $feature; + /** + * @var StepNode + */ + private $step; + + /** + * Initializes event. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + */ + public function __construct(Environment $env, FeatureNode $feature, StepNode $step) + { + parent::__construct($env); + + $this->feature = $feature; + $this->step = $step; + } + + /** + * Returns feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns step node. + * + * @return StepNode + */ + public function getStep() + { + return $this->step; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/ExampleTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/ExampleTested.php new file mode 100644 index 0000000..1bb1a42 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/ExampleTested.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +/** + * Represents an example event. + * + * @author Konstantin Kudryashov + */ +interface ExampleTested +{ + const BEFORE = 'tester.example_tested.before'; + const AFTER_SETUP = 'tester.example_tested.after_setup'; + const BEFORE_TEARDOWN = 'tester.example_tested.before_teardown'; + const AFTER = 'tester.example_tested.after'; +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/FeatureTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/FeatureTested.php new file mode 100644 index 0000000..f29c31c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/FeatureTested.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\NodeInterface; +use Behat\Testwork\EventDispatcher\Event\LifecycleEvent; + +/** + * Represents a feature event. + * + * @author Konstantin Kudryashov + */ +abstract class FeatureTested extends LifecycleEvent implements GherkinNodeTested +{ + const BEFORE = 'tester.feature_tested.before'; + const AFTER_SETUP = 'tester.feature_tested.after_setup'; + const BEFORE_TEARDOWN = 'tester.feature_tested.before_teardown'; + const AFTER = 'tester.feature_tested.after'; + + /** + * Returns feature. + * + * @return FeatureNode + */ + abstract public function getFeature(); + + /** + * Returns node. + * + * @return NodeInterface + */ + final public function getNode() + { + return $this->getFeature(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/GherkinNodeTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/GherkinNodeTested.php new file mode 100644 index 0000000..3d1fe07 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/GherkinNodeTested.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\NodeInterface; + +/** + * Represents a Gherkin node based event. + * + * @author Konstantin Kudryashov + */ +interface GherkinNodeTested +{ + /** + * Returns node. + * + * @return NodeInterface + */ + public function getNode(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/OutlineTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/OutlineTested.php new file mode 100644 index 0000000..149fc4f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/OutlineTested.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\NodeInterface; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\EventDispatcher\Event\LifecycleEvent; + +/** + * Represents an outline event. + * + * @author Konstantin Kudryashov + */ +abstract class OutlineTested extends LifecycleEvent implements GherkinNodeTested +{ + const BEFORE = 'tester.outline_tested.before'; + const AFTER_SETUP = 'tester.outline_tested.after_setup'; + const BEFORE_TEARDOWN = 'tester.outline_tested.before_teardown'; + const AFTER = 'tester.outline_tested.after'; + + /** + * Returns feature. + * + * @return FeatureNode + */ + abstract public function getFeature(); + + /** + * Returns outline node. + * + * @return OutlineNode + */ + abstract public function getOutline(); + + /** + * Returns node. + * + * @return NodeInterface + */ + final public function getNode() + { + return $this->getOutline(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/ScenarioLikeTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/ScenarioLikeTested.php new file mode 100644 index 0000000..bd74185 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/ScenarioLikeTested.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; + +/** + * Represents an event of scenario-like structure (Scenario, Background, Example). + * + * @author Konstantin Kudryashov + */ +interface ScenarioLikeTested extends GherkinNodeTested +{ + /** + * Returns feature node. + * + * @return FeatureNode + */ + public function getFeature(); + + /** + * Returns scenario node. + * + * @return ScenarioInterface + */ + public function getScenario(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/ScenarioTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/ScenarioTested.php new file mode 100644 index 0000000..2251b4a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/ScenarioTested.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Testwork\EventDispatcher\Event\LifecycleEvent; + +/** + * Represents a scenario event. + * + * @author Konstantin Kudryashov + */ +abstract class ScenarioTested extends LifecycleEvent implements ScenarioLikeTested +{ + const BEFORE = 'tester.scenario_tested.before'; + const AFTER_SETUP = 'tester.scenario_tested.after_setup'; + const BEFORE_TEARDOWN = 'tester.scenario_tested.before_teardown'; + const AFTER = 'tester.scenario_tested.after'; + + /** + * {@inheritdoc} + */ + final public function getNode() + { + return $this->getScenario(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/StepTested.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/StepTested.php new file mode 100644 index 0000000..7053d0d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Event/StepTested.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Event; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\EventDispatcher\Event\LifecycleEvent; + +/** + * Represents a step event. + * + * @author Konstantin Kudryashov + */ +abstract class StepTested extends LifecycleEvent implements GherkinNodeTested +{ + const BEFORE = 'tester.step_tested.before'; + const AFTER_SETUP = 'tester.step_tested.after_setup'; + const BEFORE_TEARDOWN = 'tester.step_tested.before_teardown'; + const AFTER = 'tester.step_tested.after'; + + /** + * Returns feature. + * + * @return FeatureNode + */ + abstract public function getFeature(); + + /** + * Returns step node. + * + * @return StepNode + */ + abstract public function getStep(); + + /** + * {@inheritdoc} + */ + final public function getNode() + { + return $this->getStep(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/ServiceContainer/EventDispatcherExtension.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/ServiceContainer/EventDispatcherExtension.php new file mode 100644 index 0000000..29ab58c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/ServiceContainer/EventDispatcherExtension.php @@ -0,0 +1,156 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\ServiceContainer; + +use Behat\Behat\EventDispatcher\Event\ExampleTested; +use Behat\Behat\EventDispatcher\Event\ScenarioTested; +use Behat\Behat\Tester\ServiceContainer\TesterExtension; +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension as BaseExtension; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Extends Testwork EventDispatcherExtension with additional event-dispatching testers. + * + * @author Konstantin Kudryashov + */ +class EventDispatcherExtension extends BaseExtension +{ + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + parent::load($container, $config); + + $this->loadStopOnFailureController($container); + $this->loadEventDispatchingBackgroundTester($container); + $this->loadEventDispatchingFeatureTester($container); + $this->loadEventDispatchingOutlineTester($container); + $this->loadEventDispatchingScenarioTester($container); + $this->loadEventDispatchingExampleTester($container); + $this->loadEventDispatchingStepTester($container); + } + + /** + * Loads stop on failure controller. + * + * @param ContainerBuilder $container + */ + protected function loadStopOnFailureController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\EventDispatcher\Cli\StopOnFailureController', array( + new Reference(EventDispatcherExtension::DISPATCHER_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 100)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.stop_on_failure', $definition); + } + + /** + * Loads event-dispatching background tester. + * + * @param ContainerBuilder $container + */ + protected function loadEventDispatchingBackgroundTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\EventDispatcher\Tester\EventDispatchingBackgroundTester', array( + new Reference(TesterExtension::BACKGROUND_TESTER_ID), + new Reference(self::DISPATCHER_ID) + )); + $definition->addTag(TesterExtension::BACKGROUND_TESTER_WRAPPER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::BACKGROUND_TESTER_WRAPPER_TAG . '.event_dispatching', $definition); + } + + /** + * Loads event-dispatching feature tester. + * + * @param ContainerBuilder $container + */ + protected function loadEventDispatchingFeatureTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\EventDispatcher\Tester\EventDispatchingFeatureTester', array( + new Reference(TesterExtension::SPECIFICATION_TESTER_ID), + new Reference(self::DISPATCHER_ID) + )); + $definition->addTag(TesterExtension::SPECIFICATION_TESTER_WRAPPER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::SPECIFICATION_TESTER_WRAPPER_TAG . '.event_dispatching', $definition); + } + + /** + * Loads event-dispatching outline tester. + * + * @param ContainerBuilder $container + */ + protected function loadEventDispatchingOutlineTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\EventDispatcher\Tester\EventDispatchingOutlineTester', array( + new Reference(TesterExtension::OUTLINE_TESTER_ID), + new Reference(self::DISPATCHER_ID) + )); + $definition->addTag(TesterExtension::OUTLINE_TESTER_WRAPPER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::OUTLINE_TESTER_WRAPPER_TAG . '.event_dispatching', $definition); + } + + /** + * Loads event-dispatching scenario tester. + * + * @param ContainerBuilder $container + */ + protected function loadEventDispatchingScenarioTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\EventDispatcher\Tester\EventDispatchingScenarioTester', array( + new Reference(TesterExtension::SCENARIO_TESTER_ID), + new Reference(self::DISPATCHER_ID), + ScenarioTested::BEFORE, + ScenarioTested::AFTER_SETUP, + ScenarioTested::BEFORE_TEARDOWN, + ScenarioTested::AFTER + )); + $definition->addTag(TesterExtension::SCENARIO_TESTER_WRAPPER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::SCENARIO_TESTER_WRAPPER_TAG . '.event_dispatching', $definition); + } + + /** + * Loads event-dispatching example tester. + * + * @param ContainerBuilder $container + */ + protected function loadEventDispatchingExampleTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\EventDispatcher\Tester\EventDispatchingScenarioTester', array( + new Reference(TesterExtension::EXAMPLE_TESTER_ID), + new Reference(self::DISPATCHER_ID), + ExampleTested::BEFORE, + ExampleTested::AFTER_SETUP, + ExampleTested::BEFORE_TEARDOWN, + ExampleTested::AFTER + )); + $definition->addTag(TesterExtension::EXAMPLE_TESTER_WRAPPER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::EXAMPLE_TESTER_WRAPPER_TAG . '.event_dispatching', $definition); + } + + /** + * Loads event-dispatching step tester. + * + * @param ContainerBuilder $container + */ + protected function loadEventDispatchingStepTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\EventDispatcher\Tester\EventDispatchingStepTester', array( + new Reference(TesterExtension::STEP_TESTER_ID), + new Reference(self::DISPATCHER_ID) + )); + $definition->addTag(TesterExtension::STEP_TESTER_WRAPPER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::STEP_TESTER_WRAPPER_TAG . '.event_dispatching', $definition); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingBackgroundTester.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingBackgroundTester.php new file mode 100644 index 0000000..d947df5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingBackgroundTester.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Tester; + +use Behat\Behat\EventDispatcher\Event\AfterBackgroundSetup; +use Behat\Behat\EventDispatcher\Event\AfterBackgroundTested; +use Behat\Behat\EventDispatcher\Event\BackgroundTested; +use Behat\Behat\EventDispatcher\Event\BeforeBackgroundTeardown; +use Behat\Behat\EventDispatcher\Event\BeforeBackgroundTested; +use Behat\Behat\Tester\BackgroundTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Background tester dispatching BEFORE/AFTER events. + * + * @author Konstantin Kudryashov + */ +final class EventDispatchingBackgroundTester implements BackgroundTester +{ + /** + * @var BackgroundTester + */ + private $baseTester; + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * Initializes tester. + * + * @param BackgroundTester $baseTester + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(BackgroundTester $baseTester, EventDispatcherInterface $eventDispatcher) + { + $this->baseTester = $baseTester; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, $skip) + { + $event = new BeforeBackgroundTested($env, $feature, $feature->getBackground()); + $this->eventDispatcher->dispatch($event::BEFORE, $event); + + $setup = $this->baseTester->setUp($env, $feature, $skip); + + $event = new AfterBackgroundSetup($env, $feature, $feature->getBackground(), $setup); + $this->eventDispatcher->dispatch($event::AFTER_SETUP, $event); + + return $setup; + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, $skip) + { + return $this->baseTester->test($env, $feature, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, $skip, TestResult $result) + { + $event = new BeforeBackgroundTeardown($env, $feature, $feature->getBackground(), $result); + $this->eventDispatcher->dispatch(BackgroundTested::BEFORE_TEARDOWN, $event); + + $teardown = $this->baseTester->tearDown($env, $feature, $skip, $result); + + $event = new AfterBackgroundTested($env, $feature, $feature->getBackground(), $result, $teardown); + $this->eventDispatcher->dispatch(BackgroundTested::AFTER, $event); + + return $teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingFeatureTester.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingFeatureTester.php new file mode 100644 index 0000000..2bd0ad5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingFeatureTester.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Tester; + +use Behat\Behat\EventDispatcher\Event\AfterFeatureSetup; +use Behat\Behat\EventDispatcher\Event\AfterFeatureTested; +use Behat\Behat\EventDispatcher\Event\BeforeFeatureTeardown; +use Behat\Behat\EventDispatcher\Event\BeforeFeatureTested; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\SpecificationTester; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Feature tester dispatching BEFORE/AFTER events during tests. + * + * @author Konstantin Kudryashov + */ +final class EventDispatchingFeatureTester implements SpecificationTester +{ + /** + * @var SpecificationTester + */ + private $baseTester; + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * Initializes tester. + * + * @param SpecificationTester $baseTester + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(SpecificationTester $baseTester, EventDispatcherInterface $eventDispatcher) + { + $this->baseTester = $baseTester; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, $feature, $skip) + { + $event = new BeforeFeatureTested($env, $feature); + $this->eventDispatcher->dispatch($event::BEFORE, $event); + + $setup = $this->baseTester->setUp($env, $feature, $skip); + + $event = new AfterFeatureSetup($env, $feature, $setup); + $this->eventDispatcher->dispatch($event::AFTER_SETUP, $event); + + return $setup; + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, $feature, $skip) + { + return $this->baseTester->test($env, $feature, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, $feature, $skip, TestResult $result) + { + $event = new BeforeFeatureTeardown($env, $feature, $result); + $this->eventDispatcher->dispatch($event::BEFORE_TEARDOWN, $event); + + $teardown = $this->baseTester->tearDown($env, $feature, $skip, $result); + + $event = new AfterFeatureTested($env, $feature, $result, $teardown); + $this->eventDispatcher->dispatch($event::AFTER, $event); + + return $teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingOutlineTester.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingOutlineTester.php new file mode 100644 index 0000000..13d257c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingOutlineTester.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Tester; + +use Behat\Behat\EventDispatcher\Event\AfterOutlineSetup; +use Behat\Behat\EventDispatcher\Event\AfterOutlineTested; +use Behat\Behat\EventDispatcher\Event\BeforeOutlineTeardown; +use Behat\Behat\EventDispatcher\Event\BeforeOutlineTested; +use Behat\Behat\Tester\OutlineTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Outline tester dispatching BEFORE/AFTER events during tests. + * + * @author Konstantin Kudryashov + */ +final class EventDispatchingOutlineTester implements OutlineTester +{ + /** + * @var OutlineTester + */ + private $baseTester; + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * Initializes tester. + * + * @param OutlineTester $baseTester + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(OutlineTester $baseTester, EventDispatcherInterface $eventDispatcher) + { + $this->baseTester = $baseTester; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, OutlineNode $outline, $skip) + { + $event = new BeforeOutlineTested($env, $feature, $outline); + $this->eventDispatcher->dispatch($event::BEFORE, $event); + + $setup = $this->baseTester->setUp($env, $feature, $outline, $skip); + + $event = new AfterOutlineSetup($env, $feature, $outline, $setup); + $this->eventDispatcher->dispatch($event::AFTER_SETUP, $event); + + return $setup; + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, OutlineNode $outline, $skip) + { + return $this->baseTester->test($env, $feature, $outline, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, OutlineNode $outline, $skip, TestResult $result) + { + $event = new BeforeOutlineTeardown($env, $feature, $outline, $result); + $this->eventDispatcher->dispatch($event::BEFORE_TEARDOWN, $event); + + $teardown = $this->baseTester->tearDown($env, $feature, $outline, $skip, $result); + + $event = new AfterOutlineTested($env, $feature, $outline, $result, $teardown); + $this->eventDispatcher->dispatch($event::AFTER, $event); + + return $teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingScenarioTester.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingScenarioTester.php new file mode 100644 index 0000000..44eb131 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingScenarioTester.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Tester; + +use Behat\Behat\EventDispatcher\Event\AfterScenarioSetup; +use Behat\Behat\EventDispatcher\Event\AfterScenarioTested; +use Behat\Behat\EventDispatcher\Event\BeforeScenarioTeardown; +use Behat\Behat\EventDispatcher\Event\BeforeScenarioTested; +use Behat\Behat\Tester\ScenarioTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface as Scenario; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Scenario tester dispatching BEFORE/AFTER events during tests. + * + * @author Konstantin Kudryashov + */ +final class EventDispatchingScenarioTester implements ScenarioTester +{ + /** + * @var ScenarioTester + */ + private $baseTester; + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + /** + * @var string + */ + private $beforeEventName; + /** + * @var string + */ + private $afterSetupEventName; + /** + * @var string + */ + private $beforeTeardownEventName; + /** + * @var string + */ + private $afterEventName; + + /** + * Initializes tester. + * + * @param ScenarioTester $baseTester + * @param EventDispatcherInterface $eventDispatcher + * @param string $beforeEventName + * @param string $afterSetupEventName + * @param string $beforeTeardownEventName + * @param string $afterEventName + */ + public function __construct( + ScenarioTester $baseTester, + EventDispatcherInterface $eventDispatcher, + $beforeEventName, + $afterSetupEventName, + $beforeTeardownEventName, + $afterEventName + ) { + $this->baseTester = $baseTester; + $this->eventDispatcher = $eventDispatcher; + $this->beforeEventName = $beforeEventName; + $this->afterSetupEventName = $afterSetupEventName; + $this->beforeTeardownEventName = $beforeTeardownEventName; + $this->afterEventName = $afterEventName; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, Scenario $scenario, $skip) + { + $event = new BeforeScenarioTested($env, $feature, $scenario); + $this->eventDispatcher->dispatch($this->beforeEventName, $event); + + $setup = $this->baseTester->setUp($env, $feature, $scenario, $skip); + + $event = new AfterScenarioSetup($env, $feature, $scenario, $setup); + $this->eventDispatcher->dispatch($this->afterSetupEventName, $event); + + return $setup; + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, Scenario $scenario, $skip) + { + return $this->baseTester->test($env, $feature, $scenario, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, Scenario $scenario, $skip, TestResult $result) + { + $event = new BeforeScenarioTeardown($env, $feature, $scenario, $result); + $this->eventDispatcher->dispatch($this->beforeTeardownEventName, $event); + + $teardown = $this->baseTester->tearDown($env, $feature, $scenario, $skip, $result); + + $event = new AfterScenarioTested($env, $feature, $scenario, $result, $teardown); + $this->eventDispatcher->dispatch($this->afterEventName, $event); + + return $teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingStepTester.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingStepTester.php new file mode 100644 index 0000000..6bf3c46 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/EventDispatchingStepTester.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\EventDispatcher\Tester; + +use Behat\Behat\EventDispatcher\Event\AfterStepSetup; +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Behat\EventDispatcher\Event\BeforeStepTeardown; +use Behat\Behat\EventDispatcher\Event\BeforeStepTested; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Behat\Tester\StepTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Step tester dispatching BEFORE/AFTER events during tests. + * + * @author Konstantin Kudryashov + */ +final class EventDispatchingStepTester implements StepTester +{ + /** + * @var StepTester + */ + private $baseTester; + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * Initializes tester. + * + * @param StepTester $baseTester + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(StepTester $baseTester, EventDispatcherInterface $eventDispatcher) + { + $this->baseTester = $baseTester; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, StepNode $step, $skip) + { + $event = new BeforeStepTested($env, $feature, $step); + $this->eventDispatcher->dispatch($event::BEFORE, $event); + + $setup = $this->baseTester->setUp($env, $feature, $step, $skip); + + $event = new AfterStepSetup($env, $feature, $step, $setup); + $this->eventDispatcher->dispatch($event::AFTER_SETUP, $event); + + return $setup; + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, StepNode $step, $skip) + { + return $this->baseTester->test($env, $feature, $step, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, StepNode $step, $skip, StepResult $result) + { + $event = new BeforeStepTeardown($env, $feature, $step, $result); + $this->eventDispatcher->dispatch($event::BEFORE_TEARDOWN, $event); + + $teardown = $this->baseTester->tearDown($env, $feature, $step, $skip, $result); + + $event = new AfterStepTested($env, $feature, $step, $result, $teardown); + $this->eventDispatcher->dispatch($event::AFTER, $event); + + return $teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Gherkin/Cli/FilterController.php b/vendor/behat/behat/src/Behat/Behat/Gherkin/Cli/FilterController.php new file mode 100644 index 0000000..7f13989 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/Cli/FilterController.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Gherkin\Cli; + +use Behat\Gherkin\Filter\NameFilter; +use Behat\Gherkin\Filter\RoleFilter; +use Behat\Gherkin\Filter\TagFilter; +use Behat\Gherkin\Gherkin; +use Behat\Testwork\Cli\Controller; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Configures default Gherkin filters. + * + * @author Konstantin Kudryashov + */ +final class FilterController implements Controller +{ + /** + * @var Gherkin + */ + private $gherkin; + + /** + * Initializes controller. + * + * @param Gherkin $gherkin + */ + public function __construct(Gherkin $gherkin) + { + $this->gherkin = $gherkin; + } + + /** + * Configures command to be executable by the controller. + * + * @param Command $command + */ + public function configure(Command $command) + { + $command + ->addOption( + '--name', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + "Only executeCall the feature elements which match part" . PHP_EOL . + "of the given name or regex." + ) + ->addOption( + '--tags', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + "Only executeCall the features or scenarios with tags" . PHP_EOL . + "matching tag filter expression." + ) + ->addOption( + '--role', null, InputOption::VALUE_REQUIRED, + "Only executeCall the features with actor role matching" . PHP_EOL . + "a wildcard." + ); + } + + /** + * Executes controller. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return null|integer + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $filters = array(); + + foreach ($input->getOption('name') as $name) { + $filters[] = new NameFilter($name); + } + + foreach ($input->getOption('tags') as $tags) { + $filters[] = new TagFilter($tags); + } + + if ($role = $input->getOption('role')) { + $filters[] = new RoleFilter($role); + } + + if (count($filters)) { + $this->gherkin->setFilters($filters); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Gherkin/Cli/SyntaxController.php b/vendor/behat/behat/src/Behat/Behat/Gherkin/Cli/SyntaxController.php new file mode 100644 index 0000000..a3e3f6c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/Cli/SyntaxController.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Gherkin\Cli; + +use Behat\Gherkin\Keywords\KeywordsDumper; +use Behat\Testwork\Cli\Controller; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Prints example of the feature to present all available syntax keywords. + * + * @author Konstantin Kudryashov + */ +final class SyntaxController implements Controller +{ + /** + * @var KeywordsDumper + */ + private $keywordsDumper; + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * Initializes controller. + * + * @param KeywordsDumper $dumper + * @param TranslatorInterface $translator + */ + public function __construct(KeywordsDumper $dumper, TranslatorInterface $translator) + { + $dumper->setKeywordsDumperFunction(array($this, 'dumpKeywords')); + $this->keywordsDumper = $dumper; + $this->translator = $translator; + } + + /** + * Configures command to be executable by the controller. + * + * @param Command $command + */ + public function configure(Command $command) + { + $command + ->addOption( + '--story-syntax', null, InputOption::VALUE_NONE, + "Print *.feature example." . PHP_EOL . + "Use --lang to see specific language." + ); + } + + /** + * Executes controller. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return null|integer + */ + public function execute(InputInterface $input, OutputInterface $output) + { + if (!$input->getOption('story-syntax')) { + return null; + } + + $output->getFormatter()->setStyle('gherkin_keyword', new OutputFormatterStyle('green', null, array('bold'))); + $output->getFormatter()->setStyle('gherkin_comment', new OutputFormatterStyle('yellow')); + + $story = $this->keywordsDumper->dump($this->translator->getLocale()); + $story = preg_replace('/^\#.*/', '$0', $story); + $output->writeln($story); + $output->writeln(''); + + return 0; + } + + /** + * Keywords dumper. + * + * @param array $keywords keywords list + * + * @return string + */ + public function dumpKeywords(array $keywords) + { + $dump = '' . implode('|', $keywords) . ''; + + if (1 < count($keywords)) { + return '[' . $dump . ']'; + } + + return $dump; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Gherkin/ServiceContainer/GherkinExtension.php b/vendor/behat/behat/src/Behat/Behat/Gherkin/ServiceContainer/GherkinExtension.php new file mode 100644 index 0000000..6abf68c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/ServiceContainer/GherkinExtension.php @@ -0,0 +1,363 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Gherkin\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\Filesystem\ServiceContainer\FilesystemExtension; +use Behat\Testwork\ServiceContainer\Exception\ExtensionException; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Specification\ServiceContainer\SpecificationExtension; +use Behat\Testwork\Suite\ServiceContainer\SuiteExtension; +use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension; +use ReflectionClass; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Extends Behat with gherkin suites and features. + * + * @author Konstantin Kudryashov + */ +final class GherkinExtension implements Extension +{ + /* + * Available services + */ + const MANAGER_ID = 'gherkin'; + const KEYWORDS_DUMPER_ID = 'gherkin.keywords_dumper'; + + /* + * Available extension points + */ + const LOADER_TAG = 'gherkin.loader'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'gherkin'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + $builder + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('cache') + ->info('Sets the gherkin parser cache folder') + ->defaultValue( + is_writable(sys_get_temp_dir()) + ? sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'behat_gherkin_cache' + : null + ) + ->end() + ->arrayNode('filters') + ->info('Sets the gherkin filters (overridable by CLI options)') + ->performNoDeepMerging() + ->defaultValue(array()) + ->useAttributeAsKey('name') + ->prototype('scalar')->end() + ->end() + ->end() + ; + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadParameters($container); + $this->loadGherkin($container); + $this->loadKeywords($container); + $this->loadParser($container); + $this->loadDefaultLoaders($container, $config['cache']); + $this->loadProfileFilters($container, $config['filters']); + $this->loadSyntaxController($container); + $this->loadFilterController($container); + $this->loadSuiteWithPathsSetup($container); + $this->loadFilesystemFeatureLocator($container); + $this->loadFilesystemScenariosListLocator($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processLoaders($container); + } + + /** + * Loads default container parameters. + * + * @param ContainerBuilder $container + */ + private function loadParameters(ContainerBuilder $container) + { + $container->setParameter('gherkin.paths.lib', $this->getLibPath()); + $container->setParameter('gherkin.paths.i18n', '%gherkin.paths.lib%/i18n.php'); + $container->setParameter( + 'suite.generic.default_settings', + array( + 'paths' => array('%paths.base%/features'), + 'contexts' => array('FeatureContext') + ) + ); + } + + /** + * Returns gherkin library path. + * + * @return string + */ + private function getLibPath() + { + $reflection = new ReflectionClass('Behat\Gherkin\Gherkin'); + $libPath = rtrim(dirname($reflection->getFilename()) . '/../../../', DIRECTORY_SEPARATOR); + + return $libPath; + } + + /** + * Loads gherkin service. + * + * @param ContainerBuilder $container + */ + private function loadGherkin(ContainerBuilder $container) + { + $definition = new Definition('Behat\Gherkin\Gherkin'); + $container->setDefinition(self::MANAGER_ID, $definition); + } + + /** + * Loads keyword services. + * + * @param ContainerBuilder $container + */ + private function loadKeywords(ContainerBuilder $container) + { + $definition = new Definition('Behat\Gherkin\Keywords\CachedArrayKeywords', array( + '%gherkin.paths.i18n%' + )); + $container->setDefinition('gherkin.keywords', $definition); + + $definition = new Definition('Behat\Gherkin\Keywords\KeywordsDumper', array( + new Reference('gherkin.keywords') + )); + $container->setDefinition(self::KEYWORDS_DUMPER_ID, $definition); + } + + /** + * Loads gherkin parser. + * + * @param ContainerBuilder $container + */ + private function loadParser(ContainerBuilder $container) + { + $definition = new Definition('Behat\Gherkin\Parser', array( + new Reference('gherkin.lexer') + )); + $container->setDefinition('gherkin.parser', $definition); + + $definition = new Definition('Behat\Gherkin\Lexer', array( + new Reference('gherkin.keywords') + )); + $container->setDefinition('gherkin.lexer', $definition); + } + + /** + * Loads gherkin loaders. + * + * @param ContainerBuilder $container + * @param string $cachePath + */ + private function loadDefaultLoaders(ContainerBuilder $container, $cachePath) + { + $definition = new Definition('Behat\Gherkin\Loader\GherkinFileLoader', array( + new Reference('gherkin.parser') + )); + + if ($cachePath) { + $cacheDefinition = new Definition('Behat\Gherkin\Cache\FileCache', array($cachePath)); + } else { + $cacheDefinition = new Definition('Behat\Gherkin\Cache\MemoryCache'); + } + + $definition->addMethodCall('setCache', array($cacheDefinition)); + $definition->addTag(self::LOADER_TAG, array('priority' => 50)); + $container->setDefinition('gherkin.loader.gherkin_file', $definition); + } + + /** + * Loads profile-level gherkin filters. + * + * @param ContainerBuilder $container + * @param array $filters + */ + private function loadProfileFilters(ContainerBuilder $container, array $filters) + { + $gherkin = $container->getDefinition(self::MANAGER_ID); + foreach ($filters as $type => $filterString) { + $filter = $this->createFilterDefinition($type, $filterString); + $gherkin->addMethodCall('addFilter', array($filter)); + } + } + + /** + * Loads syntax controller. + * + * @param ContainerBuilder $container + */ + private function loadSyntaxController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Gherkin\Cli\SyntaxController', array( + new Reference(self::KEYWORDS_DUMPER_ID), + new Reference(TranslatorExtension::TRANSLATOR_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 600)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.gherkin_syntax', $definition); + } + + /** + * Loads filter controller. + * + * @param ContainerBuilder $container + */ + private function loadFilterController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Gherkin\Cli\FilterController', array( + new Reference(self::MANAGER_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 700)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.gherkin_filters', $definition); + } + + /** + * Loads suite with paths setup. + * + * @param ContainerBuilder $container + */ + private function loadSuiteWithPathsSetup(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Gherkin\Suite\Setup\SuiteWithPathsSetup', array( + '%paths.base%', + new Reference(FilesystemExtension::LOGGER_ID) + )); + $definition->addTag(SuiteExtension::SETUP_TAG, array('priority' => 50)); + $container->setDefinition(SuiteExtension::SETUP_TAG . '.suite_with_paths', $definition); + } + + /** + * Loads filesystem feature locator. + * + * @param ContainerBuilder $container + */ + private function loadFilesystemFeatureLocator(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Gherkin\Specification\Locator\FilesystemFeatureLocator', array( + new Reference(self::MANAGER_ID), + '%paths.base%' + )); + $definition->addTag(SpecificationExtension::LOCATOR_TAG, array('priority' => 60)); + $container->setDefinition(SpecificationExtension::LOCATOR_TAG . '.filesystem_feature', $definition); + } + + /** + * Loads filesystem scenarios list locator. + * + * @param ContainerBuilder $container + */ + private function loadFilesystemScenariosListLocator(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Gherkin\Specification\Locator\FilesystemScenariosListLocator', array( + new Reference(self::MANAGER_ID) + )); + $definition->addTag(SpecificationExtension::LOCATOR_TAG, array('priority' => 50)); + $container->setDefinition(SpecificationExtension::LOCATOR_TAG . '.filesystem_scenarios_list', $definition); + } + + /** + * Processes all available gherkin loaders. + * + * @param ContainerBuilder $container + */ + private function processLoaders(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::LOADER_TAG); + $definition = $container->getDefinition(self::MANAGER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('addLoader', array($reference)); + } + } + + /** + * Creates filter definition of provided type. + * + * @param string $type + * @param string $filterString + * + * @return Definition + * + * @throws ExtensionException If filter type is not recognised + */ + private function createFilterDefinition($type, $filterString) + { + if ('role' === $type) { + return new Definition('Behat\Gherkin\Filter\RoleFilter', array($filterString)); + } + + if ('name' === $type) { + return new Definition('Behat\Gherkin\Filter\NameFilter', array($filterString)); + } + + if ('tags' === $type) { + return new Definition('Behat\Gherkin\Filter\TagFilter', array($filterString)); + } + + throw new ExtensionException(sprintf( + '`%s` filter is not supported by the `filters` option of gherkin extension. Supported types are `%s`.', + $type, + implode('`, `', array('role', 'name', 'tags')) + ), 'gherkin'); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/LazyFeatureIterator.php b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/LazyFeatureIterator.php new file mode 100644 index 0000000..e213165 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/LazyFeatureIterator.php @@ -0,0 +1,202 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Gherkin\Specification; + +use Behat\Gherkin\Filter\FilterInterface; +use Behat\Gherkin\Filter\NameFilter; +use Behat\Gherkin\Filter\RoleFilter; +use Behat\Gherkin\Filter\TagFilter; +use Behat\Gherkin\Gherkin; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Suite\Exception\SuiteConfigurationException; +use Behat\Testwork\Suite\Suite; + +/** + * Lazily iterates (parses one-by-one) over features. + * + * @author Konstantin Kudryashov + */ +final class LazyFeatureIterator implements SpecificationIterator +{ + /** + * @var Suite + */ + private $suite; + /** + * @var Gherkin + */ + private $gherkin; + /** + * @var string[] + */ + private $paths = array(); + /** + * @var FilterInterface[] + */ + private $filters = array(); + /** + * @var integer + */ + private $position = 0; + /** + * @var FeatureNode[] + */ + private $features = array(); + /** + * @var FeatureNode + */ + private $currentFeature; + + /** + * Initializes specifications. + * + * @param Suite $suite + * @param Gherkin $gherkin + * @param string[] $paths + * @param FilterInterface[] $filters + */ + public function __construct(Suite $suite, Gherkin $gherkin, array $paths, array $filters = array()) + { + $this->suite = $suite; + $this->gherkin = $gherkin; + $this->paths = array_values($paths); + $this->filters = array_merge($this->getSuiteFilters($suite), $filters); + } + + /** + * {@inheritdoc} + */ + public function getSuite() + { + return $this->suite; + } + + /** + * {@inheritdoc} + */ + public function rewind() + { + $this->position = 0; + $this->moveToNextAvailableFeature(); + } + + /** + * {@inheritdoc} + */ + public function next() + { + $this->moveToNextAvailableFeature(); + } + + /** + * {@inheritdoc} + */ + public function valid() + { + return null !== $this->currentFeature; + } + + /** + * {@inheritdoc} + */ + public function key() + { + return $this->position; + } + + /** + * {@inheritdoc} + */ + public function current() + { + return $this->currentFeature; + } + + /** + * Returns list of filters from suite settings. + * + * @param Suite $suite + * + * @return FilterInterface[] + */ + private function getSuiteFilters(Suite $suite) + { + if (!$suite->hasSetting('filters') || !is_array($suite->getSetting('filters'))) { + return array(); + } + + $filters = array(); + foreach ($suite->getSetting('filters') as $type => $filterString) { + $filters[] = $this->createFilter($type, $filterString, $suite); + } + + return $filters; + } + + /** + * Creates filter of provided type. + * + * @param string $type + * @param string $filterString + * @param Suite $suite + * + * @return FilterInterface + * + * @throws SuiteConfigurationException If filter type is not recognised + */ + private function createFilter($type, $filterString, Suite $suite) + { + if ('role' === $type) { + return new RoleFilter($filterString); + } + + if ('name' === $type) { + return new NameFilter($filterString); + } + + if ('tags' === $type) { + return new TagFilter($filterString); + } + + throw new SuiteConfigurationException(sprintf( + '`%s` filter is not supported by the `%s` suite. Supported types are `%s`.', + $type, + $suite->getName(), + implode('`, `', array('role', 'name', 'tags')) + ), $suite->getName()); + } + + /** + * Parses paths consequently. + */ + private function moveToNextAvailableFeature() + { + while (!count($this->features) && $this->position < count($this->paths)) { + $this->features = $this->parseFeature($this->paths[$this->position]); + $this->position++; + } + + $this->currentFeature = array_shift($this->features); + } + + /** + * Parses feature at path. + * + * @param string $path + * + * @return FeatureNode[] + */ + private function parseFeature($path) + { + return $this->gherkin->load($path, $this->filters); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemFeatureLocator.php b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemFeatureLocator.php new file mode 100644 index 0000000..b604f5d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemFeatureLocator.php @@ -0,0 +1,171 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Gherkin\Specification\Locator; + +use Behat\Behat\Gherkin\Specification\LazyFeatureIterator; +use Behat\Gherkin\Filter\PathsFilter; +use Behat\Gherkin\Gherkin; +use Behat\Testwork\Specification\Locator\SpecificationLocator; +use Behat\Testwork\Specification\NoSpecificationsIterator; +use Behat\Testwork\Suite\Exception\SuiteConfigurationException; +use Behat\Testwork\Suite\Suite; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use RegexIterator; + +/** + * Loads gherkin features from the filesystem using gherkin parser. + * + * @author Konstantin Kudryashov + */ +final class FilesystemFeatureLocator implements SpecificationLocator +{ + /** + * @var Gherkin + */ + private $gherkin; + /** + * @var string + */ + private $basePath; + + /** + * Initializes loader. + * + * @param Gherkin $gherkin + * @param string $basePath + */ + public function __construct(Gherkin $gherkin, $basePath) + { + $this->gherkin = $gherkin; + $this->basePath = $basePath; + } + + /** + * {@inheritdoc} + */ + public function getLocatorExamples() + { + return array( + "a dir (features/)", + "a feature (*.feature)", + "a scenario at specific line (*.feature:10).", + "all scenarios at or after a specific line (*.feature:10-*).", + "all scenarios at a line within a specific range (*.feature:10-20)." + ); + } + + /** + * {@inheritdoc} + */ + public function locateSpecifications(Suite $suite, $locator) + { + if (!$suite->hasSetting('paths')) { + return new NoSpecificationsIterator($suite); + } + + $suiteLocators = $this->getSuitePaths($suite); + + if ($locator) { + $filters = array(new PathsFilter($suiteLocators)); + + return new LazyFeatureIterator($suite, $this->gherkin, $this->findFeatureFiles($locator), $filters); + } + + $featurePaths = array(); + foreach ($suiteLocators as $suiteLocator) { + $featurePaths = array_merge($featurePaths, $this->findFeatureFiles($suiteLocator)); + } + + return new LazyFeatureIterator($suite, $this->gherkin, $featurePaths); + } + + /** + * Returns array of feature paths configured for the provided suite. + * + * @param Suite $suite + * + * @return string[] + * + * @throws SuiteConfigurationException If `paths` setting is not an array + */ + private function getSuitePaths(Suite $suite) + { + if (!is_array($suite->getSetting('paths'))) { + throw new SuiteConfigurationException( + sprintf('`paths` setting of the "%s" suite is expected to be an array, %s given.', + $suite->getName(), + gettype($suite->getSetting('paths')) + ), + $suite->getName() + ); + } + + return $suite->getSetting('paths'); + } + + /** + * Loads feature files paths from provided path. + * + * @param string $path + * + * @return string[] + */ + private function findFeatureFiles($path) + { + $absolutePath = $this->findAbsolutePath($path); + + if (!$absolutePath) { + return array($path); + } + + if (is_file($absolutePath)) { + return array($absolutePath); + } + + $iterator = new RegexIterator( + new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($absolutePath) + ), '/^.+\.feature$/i', + RegexIterator::MATCH + ); + $paths = array_map('strval', iterator_to_array($iterator)); + uasort($paths, 'strnatcasecmp'); + + return $paths; + } + + /** + * Finds absolute path for provided relative (relative to base features path). + * + * @param string $path Relative path + * + * @return string + */ + private function findAbsolutePath($path) + { + if (is_file($path) || is_dir($path)) { + return realpath($path); + } + + if (null === $this->basePath) { + return false; + } + + if (is_file($this->basePath . DIRECTORY_SEPARATOR . $path) + || is_dir($this->basePath . DIRECTORY_SEPARATOR . $path) + ) { + return realpath($this->basePath . DIRECTORY_SEPARATOR . $path); + } + + return false; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemScenariosListLocator.php b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemScenariosListLocator.php new file mode 100644 index 0000000..59141df --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemScenariosListLocator.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Gherkin\Specification\Locator; + +use Behat\Behat\Gherkin\Specification\LazyFeatureIterator; +use Behat\Gherkin\Gherkin; +use Behat\Testwork\Specification\Locator\SpecificationLocator; +use Behat\Testwork\Specification\NoSpecificationsIterator; +use Behat\Testwork\Suite\Suite; + +/** + * Loads gherkin features using a file with the list of scenarios. + * + * @author Konstantin Kudryashov + */ +final class FilesystemScenariosListLocator implements SpecificationLocator +{ + /** + * @var Gherkin + */ + private $gherkin; + + /** + * Initializes locator. + * + * @param Gherkin $gherkin + */ + public function __construct(Gherkin $gherkin) + { + $this->gherkin = $gherkin; + } + + /** + * {@inheritdoc} + */ + public function getLocatorExamples() + { + return array("a scenarios list file (*.scenarios)."); + } + + /** + * {@inheritdoc} + */ + public function locateSpecifications(Suite $suite, $locator) + { + if (!is_file($locator) || 'scenarios' !== pathinfo($locator, PATHINFO_EXTENSION)) { + return new NoSpecificationsIterator($suite); + } + + $scenarios = explode("\n", trim(file_get_contents($locator))); + + return new LazyFeatureIterator($suite, $this->gherkin, $scenarios); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Gherkin/Suite/Setup/SuiteWithPathsSetup.php b/vendor/behat/behat/src/Behat/Behat/Gherkin/Suite/Setup/SuiteWithPathsSetup.php new file mode 100644 index 0000000..65c7c8f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/Suite/Setup/SuiteWithPathsSetup.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Gherkin\Suite\Setup; + +use Behat\Testwork\Filesystem\FilesystemLogger; +use Behat\Testwork\Suite\Setup\SuiteSetup; +use Behat\Testwork\Suite\Suite; + +/** + * Sets up gherkin suite in the filesystem (creates feature folders). + * + * @author Konstantin Kudryashov + */ +final class SuiteWithPathsSetup implements SuiteSetup +{ + /** + * @var string + */ + private $basePath; + /** + * @var null|FilesystemLogger + */ + private $logger; + + /** + * Initializes setup. + * + * @param string $basePath + * @param null|FilesystemLogger $logger + */ + public function __construct($basePath, FilesystemLogger $logger = null) + { + $this->basePath = $basePath; + $this->logger = $logger; + } + + /** + * {@inheritdoc} + */ + public function supportsSuite(Suite $suite) + { + return $suite->hasSetting('paths') && is_array($suite->getSetting('paths')); + } + + /** + * {@inheritdoc} + */ + public function setupSuite(Suite $suite) + { + foreach ($suite->getSetting('paths') as $locator) { + if (0 !== strpos($locator, '@') && !is_dir($path = $this->locatePath($locator))) { + $this->createFeatureDirectory($path); + } + } + } + + /** + * Creates feature directory. + * + * @param string $path + */ + private function createFeatureDirectory($path) + { + mkdir($path, 0777, true); + + if ($this->logger) { + $this->logger->directoryCreated($path, 'place your *.feature files here'); + } + } + + /** + * Locates path from a relative one. + * + * @param string $path + * + * @return string + */ + private function locatePath($path) + { + if ($this->isAbsolutePath($path)) { + return $path; + } + + return $this->basePath . DIRECTORY_SEPARATOR . $path; + } + + /** + * Returns whether the file path is an absolute path. + * + * @param string $file A file path + * + * @return Boolean + */ + private function isAbsolutePath($file) + { + if ($file[0] == '/' || $file[0] == '\\' + || (strlen($file) > 3 && ctype_alpha($file[0]) + && $file[1] == ':' + && ($file[2] == '\\' || $file[2] == '/') + ) + || null !== parse_url($file, PHP_URL_SCHEME) + ) { + return true; + } + + return false; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Call/AfterFeature.php b/vendor/behat/behat/src/Behat/Behat/Hook/Call/AfterFeature.php new file mode 100644 index 0000000..9041f1b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Call/AfterFeature.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Call; + +use Behat\Behat\Hook\Scope\FeatureScope; + +/** + * Represents an AfterFeature hook. + * + * @author Konstantin Kudryashov + */ +final class AfterFeature extends RuntimeFeatureHook +{ + /** + * Initializes hook. + * + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + */ + public function __construct($filterString, $callable, $description = null) + { + parent::__construct(FeatureScope::AFTER, $filterString, $callable, $description); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'AfterFeature'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Call/AfterScenario.php b/vendor/behat/behat/src/Behat/Behat/Hook/Call/AfterScenario.php new file mode 100644 index 0000000..70fbaaf --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Call/AfterScenario.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Call; + +use Behat\Behat\Hook\Scope\ScenarioScope; + +/** + * Represents an AfterScenario hook. + * + * @author Konstantin Kudryashov + */ +final class AfterScenario extends RuntimeScenarioHook +{ + /** + * Initializes hook. + * + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + */ + public function __construct($filterString, $callable, $description = null) + { + parent::__construct(ScenarioScope::AFTER, $filterString, $callable, $description); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'AfterScenario'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Call/AfterStep.php b/vendor/behat/behat/src/Behat/Behat/Hook/Call/AfterStep.php new file mode 100644 index 0000000..684ef79 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Call/AfterStep.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Call; + +use Behat\Behat\Hook\Scope\StepScope; + +/** + * Represents an AfterStep hook. + * + * @author Konstantin Kudryashov + */ +final class AfterStep extends RuntimeStepHook +{ + /** + * Initializes hook. + * + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + */ + public function __construct($filterString, $callable, $description = null) + { + parent::__construct(StepScope::AFTER, $filterString, $callable, $description); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'AfterStep'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Call/BeforeFeature.php b/vendor/behat/behat/src/Behat/Behat/Hook/Call/BeforeFeature.php new file mode 100644 index 0000000..60e326d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Call/BeforeFeature.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Call; + +use Behat\Behat\Hook\Scope\FeatureScope; + +/** + * Represents a BeforeFeature hook. + * + * @author Konstantin Kudryashov + */ +final class BeforeFeature extends RuntimeFeatureHook +{ + /** + * Initializes hook. + * + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + */ + public function __construct($filterString, $callable, $description = null) + { + parent::__construct(FeatureScope::BEFORE, $filterString, $callable, $description); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'BeforeFeature'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Call/BeforeScenario.php b/vendor/behat/behat/src/Behat/Behat/Hook/Call/BeforeScenario.php new file mode 100644 index 0000000..114def0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Call/BeforeScenario.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Call; + +use Behat\Behat\Hook\Scope\ScenarioScope; + +/** + * Represents a BeforeScenario hook. + * + * @author Konstantin Kudryashov + */ +final class BeforeScenario extends RuntimeScenarioHook +{ + /** + * Initializes hook. + * + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + */ + public function __construct($filterString, $callable, $description = null) + { + parent::__construct(ScenarioScope::BEFORE, $filterString, $callable, $description); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'BeforeScenario'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Call/BeforeStep.php b/vendor/behat/behat/src/Behat/Behat/Hook/Call/BeforeStep.php new file mode 100644 index 0000000..390f918 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Call/BeforeStep.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Call; + +use Behat\Behat\Hook\Scope\StepScope; + +/** + * Represents a BeforeStep hook. + * + * @author Konstantin Kudryashov + */ +final class BeforeStep extends RuntimeStepHook +{ + /** + * Initializes hook. + * + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + */ + public function __construct($filterString, $callable, $description = null) + { + parent::__construct(StepScope::BEFORE, $filterString, $callable, $description); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'BeforeStep'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Call/RuntimeFeatureHook.php b/vendor/behat/behat/src/Behat/Behat/Hook/Call/RuntimeFeatureHook.php new file mode 100644 index 0000000..b3d4fb2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Call/RuntimeFeatureHook.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Call; + +use Behat\Behat\Hook\Scope\FeatureScope; +use Behat\Gherkin\Filter\NameFilter; +use Behat\Gherkin\Filter\TagFilter; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Call\Exception\BadCallbackException; +use Behat\Testwork\Hook\Call\RuntimeFilterableHook; +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Represents a feature hook. + * + * @author Konstantin Kudryashov + */ +abstract class RuntimeFeatureHook extends RuntimeFilterableHook +{ + /** + * Initializes hook. + * + * @param string $scopeName + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + * + * @throws BadCallbackException If callback is method, but not a static one + */ + public function __construct($scopeName, $filterString, $callable, $description = null) + { + parent::__construct($scopeName, $filterString, $callable, $description); + + if ($this->isAnInstanceMethod()) { + throw new BadCallbackException(sprintf( + 'Feature hook callback: %s::%s() must be a static method', + $callable[0], + $callable[1] + ), $callable); + } + } + + /** + * {@inheritdoc} + */ + public function filterMatches(HookScope $scope) + { + if (!$scope instanceof FeatureScope) { + return false; + } + + if (null === ($filterString = $this->getFilterString())) { + return true; + } + + return $this->isMatch($scope->getFeature(), $filterString); + } + + /** + * @param FeatureNode $feature + * @param string $filterString + * + * @return Boolean + */ + private function isMatch(FeatureNode $feature, $filterString) + { + if (false !== strpos($filterString, '@')) { + return $this->isMatchTagFilter($feature, $filterString); + } + + if (!empty($filterString)) { + return $this->isMatchNameFilter($feature, $filterString); + } + + return false; + } + + /** + * Checks if feature matches tag filter. + * + * @param FeatureNode $feature + * @param string $filterString + * + * @return Boolean + */ + private function isMatchTagFilter(FeatureNode $feature, $filterString) + { + $filter = new TagFilter($filterString); + + return $filter->isFeatureMatch($feature); + } + + /** + * Checks if feature matches name filter. + * + * @param FeatureNode $feature + * @param string $filterString + * + * @return Boolean + */ + private function isMatchNameFilter(FeatureNode $feature, $filterString) + { + $filter = new NameFilter($filterString); + + return $filter->isFeatureMatch($feature); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Call/RuntimeScenarioHook.php b/vendor/behat/behat/src/Behat/Behat/Hook/Call/RuntimeScenarioHook.php new file mode 100644 index 0000000..56e25f9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Call/RuntimeScenarioHook.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Call; + +use Behat\Behat\Hook\Scope\ScenarioScope; +use Behat\Gherkin\Filter\NameFilter; +use Behat\Gherkin\Filter\TagFilter; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; +use Behat\Testwork\Hook\Call\RuntimeFilterableHook; +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Represents a scenario hook. + * + * @author Konstantin Kudryashov + */ +abstract class RuntimeScenarioHook extends RuntimeFilterableHook +{ + /** + * {@inheritdoc} + */ + public function filterMatches(HookScope $scope) + { + if (!$scope instanceof ScenarioScope) { + return false; + } + + if (null === ($filterString = $this->getFilterString())) { + return true; + } + + return $this->isMatch($scope->getFeature(), $scope->getScenario(), $filterString); + } + + /** + * Checks if nodes match filter. + * + * @param FeatureNode $feature + * @param ScenarioInterface $scenario + * @param string $filterString + * + * @return Boolean + */ + protected function isMatch(FeatureNode $feature, ScenarioInterface $scenario, $filterString) + { + if (false !== strpos($filterString, '@')) { + return $this->isMatchTagFilter($feature, $scenario, $filterString); + } + + if (!empty($filterString)) { + return $this->isMatchNameFilter($scenario, $filterString); + } + + return false; + } + + /** + * Checks if node match tag filter. + * + * @param FeatureNode $feature + * @param ScenarioInterface $scenario + * @param string $filterString + * + * @return Boolean + */ + protected function isMatchTagFilter(FeatureNode $feature, ScenarioInterface $scenario, $filterString) + { + $filter = new TagFilter($filterString); + + if ($filter->isFeatureMatch($feature)) { + return true; + } + + return $filter->isScenarioMatch($feature, $scenario); + } + + /** + * Checks if scenario matches name filter. + * + * @param ScenarioInterface $scenario + * @param string $filterString + * + * @return Boolean + */ + protected function isMatchNameFilter(ScenarioInterface $scenario, $filterString) + { + $filter = new NameFilter($filterString); + + return $filter->isScenarioMatch($scenario); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Call/RuntimeStepHook.php b/vendor/behat/behat/src/Behat/Behat/Hook/Call/RuntimeStepHook.php new file mode 100644 index 0000000..a1326c3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Call/RuntimeStepHook.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Call; + +use Behat\Behat\Hook\Scope\StepScope; +use Behat\Gherkin\Filter\NameFilter; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Hook\Call\RuntimeFilterableHook; +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Represents a step hook. + * + * @author Konstantin Kudryashov + */ +abstract class RuntimeStepHook extends RuntimeFilterableHook +{ + /** + * {@inheritdoc} + */ + public function filterMatches(HookScope $scope) + { + if (!$scope instanceof StepScope) { + return false; + } + + if (null === ($filterString = $this->getFilterString())) { + return true; + } + + if (!empty($filterString)) { + $filter = new NameFilter($filterString); + + if ($filter->isFeatureMatch($scope->getFeature())) { + return true; + } + + return $this->isStepMatch($scope->getStep(), $filterString); + } + + return false; + } + + /** + * Checks if Feature matches specified filter. + * + * @param StepNode $step + * @param string $filterString + * + * @return Boolean + */ + private function isStepMatch(StepNode $step, $filterString) + { + if ('/' === $filterString[0]) { + return 1 === preg_match($filterString, $step->getText()); + } + + return false !== mb_strpos($step->getText(), $filterString, 0, 'utf8'); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Context/Annotation/HookAnnotationReader.php b/vendor/behat/behat/src/Behat/Behat/Hook/Context/Annotation/HookAnnotationReader.php new file mode 100644 index 0000000..86a95cc --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Context/Annotation/HookAnnotationReader.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Context\Annotation; + +use Behat\Behat\Context\Annotation\AnnotationReader; +use Behat\Testwork\Hook\Call\RuntimeHook; +use ReflectionMethod; + +/** + * Reads hook callees from context method annotations. + * + * @author Konstantin Kudryashov + */ +final class HookAnnotationReader implements AnnotationReader +{ + /** + * @var string + */ + private static $regex = '/^\@(beforesuite|aftersuite|beforefeature|afterfeature|beforescenario|afterscenario|beforestep|afterstep)(?:\s+(.+))?$/i'; + /** + * @var string[] + */ + private static $classes = array( + 'beforesuite' => 'Behat\Testwork\Hook\Call\BeforeSuite', + 'aftersuite' => 'Behat\Testwork\Hook\Call\AfterSuite', + 'beforefeature' => 'Behat\Behat\Hook\Call\BeforeFeature', + 'afterfeature' => 'Behat\Behat\Hook\Call\AfterFeature', + 'beforescenario' => 'Behat\Behat\Hook\Call\BeforeScenario', + 'afterscenario' => 'Behat\Behat\Hook\Call\AfterScenario', + 'beforestep' => 'Behat\Behat\Hook\Call\BeforeStep', + 'afterstep' => 'Behat\Behat\Hook\Call\AfterStep' + ); + + /** + * Loads step callees (if exist) associated with specific method. + * + * @param string $contextClass + * @param ReflectionMethod $method + * @param string $docLine + * @param string $description + * + * @return null|RuntimeHook + */ + public function readCallee($contextClass, ReflectionMethod $method, $docLine, $description) + { + if (!preg_match(self::$regex, $docLine, $match)) { + return null; + } + + $type = strtolower($match[1]); + $class = self::$classes[$type]; + $pattern = isset($match[2]) ? $match[2] : null; + $callable = array($contextClass, $method->getName()); + + return new $class($pattern, $callable, $description); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Scope/AfterFeatureScope.php b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/AfterFeatureScope.php new file mode 100644 index 0000000..4a321e9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/AfterFeatureScope.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Scope; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Hook\Scope\AfterTestScope; +use Behat\Testwork\Suite\Suite; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an AfterFeature hook scope. + * + * @author Konstantin Kudryashov + */ +final class AfterFeatureScope implements FeatureScope, AfterTestScope +{ + /** + * @var Environment + */ + private $environment; + /** + * @var FeatureNode + */ + private $feature; + /** + * @var TestResult + */ + private $result; + + /** + * Initializes scope. + * + * @param Environment $env + * @param FeatureNode $feature + * @param TestResult $result + */ + public function __construct(Environment $env, FeatureNode $feature, TestResult $result) + { + $this->environment = $env; + $this->feature = $feature; + $this->result = $result; + } + + /** + * Returns hook scope name. + * + * @return string + */ + public function getName() + { + return self::AFTER; + } + + /** + * Returns hook suite. + * + * @return Suite + */ + public function getSuite() + { + return $this->environment->getSuite(); + } + + /** + * Returns hook environment. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * Returns scope feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Scope/AfterScenarioScope.php b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/AfterScenarioScope.php new file mode 100644 index 0000000..45985d9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/AfterScenarioScope.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Scope; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface as Scenario; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Hook\Scope\AfterTestScope; +use Behat\Testwork\Suite\Suite; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an AfterScenario hook scope. + * + * @author Konstantin Kudryashov + */ +final class AfterScenarioScope implements ScenarioScope, AfterTestScope +{ + /** + * @var Environment + */ + private $environment; + /** + * @var FeatureNode + */ + private $feature; + /** + * @var Scenario + */ + private $scenario; + /** + * @var TestResult + */ + private $result; + + /** + * Initializes scope. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Scenario $scenario + * @param TestResult $result + */ + public function __construct(Environment $env, FeatureNode $feature, Scenario $scenario, TestResult $result) + { + $this->environment = $env; + $this->feature = $feature; + $this->scenario = $scenario; + $this->result = $result; + } + + /** + * Returns hook scope name. + * + * @return string + */ + public function getName() + { + return self::AFTER; + } + + /** + * Returns hook suite. + * + * @return Suite + */ + public function getSuite() + { + return $this->environment->getSuite(); + } + + /** + * Returns hook environment. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * Returns scope feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario. + * + * @return Scenario + */ + public function getScenario() + { + return $this->scenario; + } + + /** + * Returns test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Scope/AfterStepScope.php b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/AfterStepScope.php new file mode 100644 index 0000000..54d63f0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/AfterStepScope.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Scope; + +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Hook\Scope\AfterTestScope; +use Behat\Testwork\Suite\Suite; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an AfterStep hook scope. + * + * @author Konstantin Kudryashov + */ +final class AfterStepScope implements StepScope, AfterTestScope +{ + /** + * @var Environment + */ + private $environment; + /** + * @var FeatureNode + */ + private $feature; + /** + * @var StepNode + */ + private $step; + /** + * @var StepResult + */ + private $result; + + /** + * Initializes scope. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + * @param StepResult $result + */ + public function __construct(Environment $env, FeatureNode $feature, StepNode $step, StepResult $result) + { + $this->environment = $env; + $this->feature = $feature; + $this->step = $step; + $this->result = $result; + } + + /** + * Returns hook scope name. + * + * @return string + */ + public function getName() + { + return self::AFTER; + } + + /** + * Returns hook suite. + * + * @return Suite + */ + public function getSuite() + { + return $this->environment->getSuite(); + } + + /** + * Returns hook environment. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * Returns scope feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scope step. + * + * @return StepNode + */ + public function getStep() + { + return $this->step; + } + + /** + * Returns test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Scope/BeforeFeatureScope.php b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/BeforeFeatureScope.php new file mode 100644 index 0000000..73254de --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/BeforeFeatureScope.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Scope; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Suite\Suite; + +/** + * Represents a BeforeFeature hook scope. + * + * @author Konstantin Kudryashov + */ +final class BeforeFeatureScope implements FeatureScope +{ + /** + * @var Environment + */ + private $environment; + /** + * @var FeatureNode + */ + private $feature; + + /** + * Initializes scope. + * + * @param Environment $env + * @param FeatureNode $feature + */ + public function __construct(Environment $env, FeatureNode $feature) + { + $this->environment = $env; + $this->feature = $feature; + } + + /** + * Returns hook scope name. + * + * @return string + */ + public function getName() + { + return self::BEFORE; + } + + /** + * Returns hook suite. + * + * @return Suite + */ + public function getSuite() + { + return $this->environment->getSuite(); + } + + /** + * Returns hook environment. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * Returns scope feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Scope/BeforeScenarioScope.php b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/BeforeScenarioScope.php new file mode 100644 index 0000000..af4178e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/BeforeScenarioScope.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Scope; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface as Scenario; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Suite\Suite; + +/** + * Represents a BeforeScenario hook scope. + * + * @author Konstantin Kudryashov + */ +final class BeforeScenarioScope implements ScenarioScope +{ + /** + * @var Environment + */ + private $environment; + /** + * @var FeatureNode + */ + private $feature; + /** + * @var Scenario + */ + private $scenario; + + /** + * Initializes scope. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Scenario $scenario + */ + public function __construct(Environment $env, FeatureNode $feature, Scenario $scenario) + { + $this->environment = $env; + $this->feature = $feature; + $this->scenario = $scenario; + } + + /** + * Returns hook scope name. + * + * @return string + */ + public function getName() + { + return self::BEFORE; + } + + /** + * Returns hook suite. + * + * @return Suite + */ + public function getSuite() + { + return $this->environment->getSuite(); + } + + /** + * Returns hook environment. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * Returns scope feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scenario. + * + * @return Scenario + */ + public function getScenario() + { + return $this->scenario; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Scope/BeforeStepScope.php b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/BeforeStepScope.php new file mode 100644 index 0000000..72e1cad --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/BeforeStepScope.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Scope; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Suite\Suite; + +/** + * Represents a BeforeStep hook scope. + * + * @author Konstantin Kudryashov + */ +final class BeforeStepScope implements StepScope +{ + /** + * @var Environment + */ + private $environment; + /** + * @var FeatureNode + */ + private $feature; + /** + * @var StepNode + */ + private $step; + + /** + * Initializes scope. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + */ + public function __construct(Environment $env, FeatureNode $feature, StepNode $step) + { + $this->environment = $env; + $this->feature = $feature; + $this->step = $step; + } + + /** + * Returns hook scope name. + * + * @return string + */ + public function getName() + { + return self::BEFORE; + } + + /** + * Returns hook suite. + * + * @return Suite + */ + public function getSuite() + { + return $this->environment->getSuite(); + } + + /** + * Returns hook environment. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * Returns scope feature. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } + + /** + * Returns scope step. + * + * @return StepNode + */ + public function getStep() + { + return $this->step; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Scope/FeatureScope.php b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/FeatureScope.php new file mode 100644 index 0000000..fe87469 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/FeatureScope.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Scope; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Represents a feature hook scope. + * + * @author Konstantin Kudryashov + */ +interface FeatureScope extends HookScope +{ + const BEFORE = 'feature.before'; + const AFTER = 'feature.after'; + + /** + * Returns scope feature. + * + * @return FeatureNode + */ + public function getFeature(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Scope/ScenarioScope.php b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/ScenarioScope.php new file mode 100644 index 0000000..30073e5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/ScenarioScope.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Scope; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface as Scenario; +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Represents a scenario hook scope. + * + * @author Konstantin Kudryashov + */ +interface ScenarioScope extends HookScope +{ + const BEFORE = 'feature.before'; + const AFTER = 'feature.after'; + + /** + * Returns scope feature. + * + * @return FeatureNode + */ + public function getFeature(); + + /** + * Returns scenario. + * + * @return Scenario + */ + public function getScenario(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Scope/StepScope.php b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/StepScope.php new file mode 100644 index 0000000..c07a79b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Scope/StepScope.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Scope; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Represents a step hook scope. + * + * @author Konstantin Kudryashov + */ +interface StepScope extends HookScope +{ + const BEFORE = 'step.before'; + const AFTER = 'step.after'; + + /** + * Returns scope feature. + * + * @return FeatureNode + */ + public function getFeature(); + + /** + * Returns scope step. + * + * @return StepNode + */ + public function getStep(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/ServiceContainer/HookExtension.php b/vendor/behat/behat/src/Behat/Behat/Hook/ServiceContainer/HookExtension.php new file mode 100644 index 0000000..76d4be9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/ServiceContainer/HookExtension.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\ServiceContainer; + +use Behat\Behat\Context\ServiceContainer\ContextExtension; +use Behat\Behat\Tester\ServiceContainer\TesterExtension; +use Behat\Testwork\Hook\ServiceContainer\HookExtension as BaseExtension; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Extends Testwork HookExtension with additional behat services. + * + * @author Konstantin Kudryashov + */ +final class HookExtension extends BaseExtension +{ + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + parent::load($container, $config); + + $this->loadAnnotationReader($container); + } + + /** + * Loads hookable testers. + * + * @param ContainerBuilder $container + */ + protected function loadHookableTesters(ContainerBuilder $container) + { + parent::loadHookableTesters($container); + + $definition = new Definition('Behat\Behat\Hook\Tester\HookableFeatureTester', array( + new Reference(TesterExtension::SPECIFICATION_TESTER_ID), + new Reference(self::DISPATCHER_ID) + )); + $definition->addTag(TesterExtension::SPECIFICATION_TESTER_WRAPPER_TAG, array('priority' => 9999)); + $container->setDefinition(TesterExtension::SPECIFICATION_TESTER_WRAPPER_TAG . '.hookable', $definition); + + $definition = new Definition('Behat\Behat\Hook\Tester\HookableScenarioTester', array( + new Reference(TesterExtension::SCENARIO_TESTER_ID), + new Reference(self::DISPATCHER_ID) + ) + ); + $definition->addTag(TesterExtension::SCENARIO_TESTER_WRAPPER_TAG, array('priority' => 9999)); + $container->setDefinition(TesterExtension::SCENARIO_TESTER_WRAPPER_TAG . '.hookable', $definition); + + $definition = new Definition('Behat\Behat\Hook\Tester\HookableScenarioTester', array( + new Reference(TesterExtension::EXAMPLE_TESTER_ID), + new Reference(self::DISPATCHER_ID) + ) + ); + $definition->addTag(TesterExtension::EXAMPLE_TESTER_WRAPPER_TAG, array('priority' => 9999)); + $container->setDefinition(TesterExtension::EXAMPLE_TESTER_WRAPPER_TAG . '.hookable', $definition); + + $definition = new Definition('Behat\Behat\Hook\Tester\HookableStepTester', array( + new Reference(TesterExtension::STEP_TESTER_ID), + new Reference(self::DISPATCHER_ID) + )); + $definition->addTag(TesterExtension::STEP_TESTER_WRAPPER_TAG, array('priority' => 9999)); + $container->setDefinition(TesterExtension::STEP_TESTER_WRAPPER_TAG . '.hookable', $definition); + } + + /** + * Loads hook annotation reader. + * + * @param ContainerBuilder $container + */ + private function loadAnnotationReader(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Hook\Context\Annotation\HookAnnotationReader'); + $definition->addTag(ContextExtension::ANNOTATION_READER_TAG, array('priority' => 50)); + $container->setDefinition(ContextExtension::ANNOTATION_READER_TAG . '.hook', $definition); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Tester/HookableFeatureTester.php b/vendor/behat/behat/src/Behat/Behat/Hook/Tester/HookableFeatureTester.php new file mode 100644 index 0000000..288c6c0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Tester/HookableFeatureTester.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Tester; + +use Behat\Behat\Hook\Scope\AfterFeatureScope; +use Behat\Behat\Hook\Scope\BeforeFeatureScope; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Hook\HookDispatcher; +use Behat\Testwork\Hook\Tester\Setup\HookedSetup; +use Behat\Testwork\Hook\Tester\Setup\HookedTeardown; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\SpecificationTester; + +/** + * Feature tester which dispatches hooks during its execution. + * + * @author Konstantin Kudryashov + */ +final class HookableFeatureTester implements SpecificationTester +{ + /** + * @var SpecificationTester + */ + private $baseTester; + /** + * @var HookDispatcher + */ + private $hookDispatcher; + + /** + * Initializes tester. + * + * @param SpecificationTester $baseTester + * @param HookDispatcher $hookDispatcher + */ + public function __construct(SpecificationTester $baseTester, HookDispatcher $hookDispatcher) + { + $this->baseTester = $baseTester; + $this->hookDispatcher = $hookDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, $spec, $skip) + { + $setup = $this->baseTester->setUp($env, $spec, $skip); + + if ($skip) { + return $setup; + } + + $scope = new BeforeFeatureScope($env, $spec); + $hookCallResults = $this->hookDispatcher->dispatchScopeHooks($scope); + + return new HookedSetup($setup, $hookCallResults); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, $spec, $skip) + { + return $this->baseTester->test($env, $spec, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, $spec, $skip, TestResult $result) + { + $teardown = $this->baseTester->tearDown($env, $spec, $skip, $result); + + if ($skip) { + return $teardown; + } + + $scope = new AfterFeatureScope($env, $spec, $result); + $hookCallResults = $this->hookDispatcher->dispatchScopeHooks($scope); + + return new HookedTeardown($teardown, $hookCallResults); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Tester/HookableScenarioTester.php b/vendor/behat/behat/src/Behat/Behat/Hook/Tester/HookableScenarioTester.php new file mode 100644 index 0000000..2ec0c06 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Tester/HookableScenarioTester.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Tester; + +use Behat\Behat\Hook\Scope\AfterScenarioScope; +use Behat\Behat\Hook\Scope\BeforeScenarioScope; +use Behat\Behat\Tester\ScenarioTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface as Scenario; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Hook\HookDispatcher; +use Behat\Testwork\Hook\Tester\Setup\HookedSetup; +use Behat\Testwork\Hook\Tester\Setup\HookedTeardown; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Scenario tester which dispatches hooks during its execution. + * + * @author Konstantin Kudryashov + */ +final class HookableScenarioTester implements ScenarioTester +{ + /** + * @var ScenarioTester + */ + private $baseTester; + /** + * @var HookDispatcher + */ + private $hookDispatcher; + + /** + * Initializes tester. + * + * @param ScenarioTester $baseTester + * @param HookDispatcher $hookDispatcher + */ + public function __construct(ScenarioTester $baseTester, HookDispatcher $hookDispatcher) + { + $this->baseTester = $baseTester; + $this->hookDispatcher = $hookDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, Scenario $scenario, $skip) + { + $setup = $this->baseTester->setUp($env, $feature, $scenario, $skip); + + if ($skip) { + return $setup; + } + + $scope = new BeforeScenarioScope($env, $feature, $scenario); + $hookCallResults = $this->hookDispatcher->dispatchScopeHooks($scope); + + return new HookedSetup($setup, $hookCallResults); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, Scenario $scenario, $skip) + { + return $this->baseTester->test($env, $feature, $scenario, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, Scenario $scenario, $skip, TestResult $result) + { + $teardown = $this->baseTester->tearDown($env, $feature, $scenario, $skip, $result); + + if ($skip) { + return $teardown; + } + + $scope = new AfterScenarioScope($env, $feature, $scenario, $result); + $hookCallResults = $this->hookDispatcher->dispatchScopeHooks($scope); + + return new HookedTeardown($teardown, $hookCallResults); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Hook/Tester/HookableStepTester.php b/vendor/behat/behat/src/Behat/Behat/Hook/Tester/HookableStepTester.php new file mode 100644 index 0000000..590d1f5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Hook/Tester/HookableStepTester.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Hook\Tester; + +use Behat\Behat\Hook\Scope\AfterStepScope; +use Behat\Behat\Hook\Scope\BeforeStepScope; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Behat\Tester\StepTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Hook\HookDispatcher; +use Behat\Testwork\Hook\Tester\Setup\HookedSetup; +use Behat\Testwork\Hook\Tester\Setup\HookedTeardown; + +/** + * Step tester which dispatches hooks during its execution. + * + * @author Konstantin Kudryashov + */ +final class HookableStepTester implements StepTester +{ + /** + * @var StepTester + */ + private $baseTester; + /** + * @var HookDispatcher + */ + private $hookDispatcher; + + /** + * Initializes tester. + * + * @param StepTester $baseTester + * @param HookDispatcher $hookDispatcher + */ + public function __construct(StepTester $baseTester, HookDispatcher $hookDispatcher) + { + $this->baseTester = $baseTester; + $this->hookDispatcher = $hookDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, StepNode $step, $skip) + { + $setup = $this->baseTester->setUp($env, $feature, $step, $skip); + + if ($skip) { + return $setup; + } + + $scope = new BeforeStepScope($env, $feature, $step); + $hookCallResults = $this->hookDispatcher->dispatchScopeHooks($scope); + + return new HookedSetup($setup, $hookCallResults); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, StepNode $step, $skip) + { + return $this->baseTester->test($env, $feature, $step, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, StepNode $step, $skip, StepResult $result) + { + $teardown = $this->baseTester->tearDown($env, $feature, $step, $skip, $result); + + if ($skip) { + return $teardown; + } + + $scope = new AfterStepScope($env, $feature, $step, $result); + $hookCallResults = $this->hookDispatcher->dispatchScopeHooks($scope); + + return new HookedTeardown($teardown, $hookCallResults); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Exception/NodeVisitorNotFoundException.php b/vendor/behat/behat/src/Behat/Behat/Output/Exception/NodeVisitorNotFoundException.php new file mode 100644 index 0000000..5493bd6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Exception/NodeVisitorNotFoundException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Exception; + +use Behat\Testwork\Output\Exception\OutputException; +use InvalidArgumentException; + +/** + * Represents an exception caused by a request for non-existent node visitor. + * + * @author Konstantin Kudryashov + */ +class NodeVisitorNotFoundException extends InvalidArgumentException implements OutputException +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/FeatureListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/FeatureListener.php new file mode 100644 index 0000000..13bc0a4 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/FeatureListener.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\AST; + +use Behat\Behat\EventDispatcher\Event\AfterFeatureSetup; +use Behat\Behat\EventDispatcher\Event\AfterFeatureTested; +use Behat\Behat\EventDispatcher\Event\FeatureTested; +use Behat\Behat\Output\Node\Printer\FeaturePrinter; +use Behat\Behat\Output\Node\Printer\SetupPrinter; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens to feature events and calls appropriate printers. + * + * @author Konstantin Kudryashov + */ +final class FeatureListener implements EventListener +{ + /** + * @var FeaturePrinter + */ + private $featurePrinter; + /** + * @var SetupPrinter + */ + private $setupPrinter; + + /** + * Initializes listener. + * + * @param FeaturePrinter $featurePrinter + * @param SetupPrinter $setupPrinter + */ + public function __construct(FeaturePrinter $featurePrinter, SetupPrinter $setupPrinter) + { + $this->featurePrinter = $featurePrinter; + $this->setupPrinter = $setupPrinter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + if (!$event instanceof FeatureTested) { + return; + } + + $this->printHeaderOnBeforeEvent($formatter, $event); + $this->printFooterOnAfterEvent($formatter, $event); + } + + /** + * Prints feature header on BEFORE event. + * + * @param Formatter $formatter + * @param Event $event + */ + private function printHeaderOnBeforeEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterFeatureSetup) { + return; + } + + $this->setupPrinter->printSetup($formatter, $event->getSetup()); + $this->featurePrinter->printHeader($formatter, $event->getFeature()); + } + + /** + * Prints feature footer on AFTER event. + * + * @param Formatter $formatter + * @param Event $event + */ + private function printFooterOnAfterEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterFeatureTested) { + return; + } + + $this->setupPrinter->printTeardown($formatter, $event->getTeardown()); + $this->featurePrinter->printFooter($formatter, $event->getTestResult()); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/OutlineListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/OutlineListener.php new file mode 100644 index 0000000..bacb12f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/OutlineListener.php @@ -0,0 +1,194 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\AST; + +use Behat\Behat\EventDispatcher\Event\AfterOutlineTested; +use Behat\Behat\EventDispatcher\Event\AfterScenarioSetup; +use Behat\Behat\EventDispatcher\Event\AfterScenarioTested; +use Behat\Behat\EventDispatcher\Event\AfterStepSetup; +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Behat\EventDispatcher\Event\BeforeOutlineTested; +use Behat\Behat\EventDispatcher\Event\ExampleTested; +use Behat\Behat\Output\Node\Printer\ExamplePrinter; +use Behat\Behat\Output\Node\Printer\OutlinePrinter; +use Behat\Behat\Output\Node\Printer\SetupPrinter; +use Behat\Behat\Output\Node\Printer\StepPrinter; +use Behat\Gherkin\Node\ExampleNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens to expanded outline events and calls appropriate printers. + * + * @author Konstantin Kudryashov + */ +final class OutlineListener implements EventListener +{ + /** + * @var OutlinePrinter + */ + private $outlinePrinter; + /** + * @var ExamplePrinter + */ + private $examplePrinter; + /** + * @var StepPrinter + */ + private $stepPrinter; + /** + * @var SetupPrinter + */ + private $stepSetupPrinter; + /** + * @var SetupPrinter + */ + private $exampleSetupPrinter; + /** + * @var ExampleNode + */ + private $example; + + /** + * Initializes listener. + * + * @param OutlinePrinter $outlinePrinter + * @param ExamplePrinter $examplePrinter + * @param StepPrinter $stepPrinter + * @param SetupPrinter $exampleSetupPrinter + * @param SetupPrinter $stepSetupPrinter + */ + public function __construct( + OutlinePrinter $outlinePrinter, + ExamplePrinter $examplePrinter, + StepPrinter $stepPrinter, + SetupPrinter $exampleSetupPrinter, + SetupPrinter $stepSetupPrinter + ) { + $this->outlinePrinter = $outlinePrinter; + $this->examplePrinter = $examplePrinter; + $this->stepPrinter = $stepPrinter; + $this->exampleSetupPrinter = $exampleSetupPrinter; + $this->stepSetupPrinter = $stepSetupPrinter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + $this->printAndCaptureOutlineHeaderOnBeforeEvent($formatter, $event); + $this->printAndForgetOutlineFooterOnAfterEvent($formatter, $event); + $this->printExampleHeaderOnBeforeExampleEvent($formatter, $event); + $this->printExampleFooterOnAfterExampleEvent($formatter, $event, $eventName); + $this->printStepSetupOnBeforeStepEvent($formatter, $event); + $this->printStepOnAfterStepEvent($formatter, $event); + } + + /** + * Prints outline header and captures outline into ivar on BEFORE event. + * + * @param Formatter $formatter + * @param Event $event + */ + private function printAndCaptureOutlineHeaderOnBeforeEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof BeforeOutlineTested) { + return; + } + + $this->outlinePrinter->printHeader($formatter, $event->getFeature(), $event->getOutline()); + } + + /** + * Prints outline footer and removes outline from ivar on AFTER event. + * + * @param Formatter $formatter + * @param Event $event + */ + private function printAndForgetOutlineFooterOnAfterEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterOutlineTested) { + return; + } + + $this->outlinePrinter->printFooter($formatter, $event->getTestResult()); + } + + /** + * Prints example header on example BEFORE event. + * + * @param Formatter $formatter + * @param Event $event + */ + private function printExampleHeaderOnBeforeExampleEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterScenarioSetup) { + return; + } + + $this->example = $event->getScenario(); + + $this->exampleSetupPrinter->printSetup($formatter, $event->getSetup()); + $this->examplePrinter->printHeader($formatter, $event->getFeature(), $this->example); + } + + /** + * Prints example footer on example AFTER event. + * + * @param Formatter $formatter + * @param Event $event + * @param string $eventName + */ + private function printExampleFooterOnAfterExampleEvent(Formatter $formatter, Event $event, $eventName) + { + if (!$event instanceof AfterScenarioTested || ExampleTested::AFTER !== $eventName) { + return; + } + + $this->examplePrinter->printFooter($formatter, $event->getTestResult()); + $this->exampleSetupPrinter->printTeardown($formatter, $event->getTeardown()); + + $this->example = null; + } + + /** + * Prints step setup on step BEFORE event. + * + * @param Formatter $formatter + * @param Event $event + */ + private function printStepSetupOnBeforeStepEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterStepSetup) { + return; + } + + $this->stepSetupPrinter->printSetup($formatter, $event->getSetup()); + } + + /** + * Prints example step on step AFTER event. + * + * @param Formatter $formatter + * @param Event $event + */ + private function printStepOnAfterStepEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterStepTested) { + return; + } + + $this->stepPrinter->printStep($formatter, $this->example, $event->getStep(), $event->getTestResult()); + $this->stepSetupPrinter->printTeardown($formatter, $event->getTeardown()); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/OutlineTableListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/OutlineTableListener.php new file mode 100644 index 0000000..fa77da4 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/OutlineTableListener.php @@ -0,0 +1,260 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\AST; + +use Behat\Behat\EventDispatcher\Event\AfterOutlineTested; +use Behat\Behat\EventDispatcher\Event\AfterScenarioSetup; +use Behat\Behat\EventDispatcher\Event\AfterScenarioTested; +use Behat\Behat\EventDispatcher\Event\AfterStepSetup; +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Behat\EventDispatcher\Event\BeforeOutlineTested; +use Behat\Behat\EventDispatcher\Event\ExampleTested; +use Behat\Behat\EventDispatcher\Event\OutlineTested; +use Behat\Behat\EventDispatcher\Event\StepTested; +use Behat\Behat\Output\Node\Printer\ExampleRowPrinter; +use Behat\Behat\Output\Node\Printer\OutlineTablePrinter; +use Behat\Behat\Output\Node\Printer\SetupPrinter; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Behat\Testwork\Tester\Setup\Setup; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens to outline table events and calls appropriate printers. + * + * @author Konstantin Kudryashov + */ +final class OutlineTableListener implements EventListener +{ + /** + * @var OutlineTablePrinter + */ + private $tablePrinter; + /** + * @var ExampleRowPrinter + */ + private $exampleRowPrinter; + /** + * @var SetupPrinter + */ + private $stepSetupPrinter; + /** + * @var SetupPrinter + */ + private $exampleSetupPrinter; + /** + * @var OutlineNode + */ + private $outline; + /** + * @var Setup + */ + private $exampleSetup; + /** + * @var Boolean + */ + private $headerPrinted = false; + /** + * @var AfterStepSetup[] + */ + private $stepBeforeTestedEvents = array(); + /** + * @var AfterStepTested[] + */ + private $stepAfterTestedEvents = array(); + + /** + * Initializes listener. + * + * @param OutlineTablePrinter $tablePrinter + * @param ExampleRowPrinter $exampleRowPrinter + * @param SetupPrinter $exampleSetupPrinter + * @param SetupPrinter $stepSetupPrinter + */ + public function __construct( + OutlineTablePrinter $tablePrinter, + ExampleRowPrinter $exampleRowPrinter, + SetupPrinter $exampleSetupPrinter, + SetupPrinter $stepSetupPrinter + ) { + $this->tablePrinter = $tablePrinter; + $this->exampleRowPrinter = $exampleRowPrinter; + $this->exampleSetupPrinter = $exampleSetupPrinter; + $this->stepSetupPrinter = $stepSetupPrinter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + if ($event instanceof StepTested) { + $this->captureStepEvent($event); + + return; + } + + $this->captureOutlineOnBeforeOutlineEvent($event); + $this->forgetOutlineOnAfterOutlineEvent($eventName); + $this->captureExampleSetupOnBeforeEvent($event); + + $this->printHeaderOnAfterExampleEvent($formatter, $event, $eventName); + $this->printExampleRowOnAfterExampleEvent($formatter, $event, $eventName); + $this->printFooterOnAfterEvent($formatter, $event); + } + + /** + * Captures step tested event. + * + * @param StepTested $event + */ + private function captureStepEvent(StepTested $event) + { + if ($event instanceof AfterStepSetup) { + $this->stepBeforeTestedEvents[$event->getStep()->getLine()] = $event; + } else { + $this->stepAfterTestedEvents[$event->getStep()->getLine()] = $event; + } + } + + /** + * Captures outline into the ivar on outline BEFORE event. + * + * @param Event $event + */ + private function captureOutlineOnBeforeOutlineEvent(Event $event) + { + if (!$event instanceof BeforeOutlineTested) { + return; + } + + $this->outline = $event->getOutline(); + $this->headerPrinted = false; + } + + /** + * Captures example setup on example BEFORE event. + * + * @param Event $event + */ + private function captureExampleSetupOnBeforeEvent(Event $event) + { + if (!$event instanceof AfterScenarioSetup) { + return; + } + + $this->exampleSetup = $event->getSetup(); + } + + /** + * Removes outline from the ivar on outline AFTER event. + * + * @param string $eventName + */ + private function forgetOutlineOnAfterOutlineEvent($eventName) + { + if (OutlineTested::AFTER !== $eventName) { + return; + } + + $this->outline = null; + } + + /** + * Prints outline header (if has not been printed yet) on example AFTER event. + * + * @param Formatter $formatter + * @param Event $event + * @param string $eventName + */ + private function printHeaderOnAfterExampleEvent(Formatter $formatter, Event $event, $eventName) + { + if (!$event instanceof AfterScenarioTested || ExampleTested::AFTER !== $eventName) { + return; + } + + if ($this->headerPrinted) { + return; + } + + $feature = $event->getFeature(); + $stepTestResults = $this->getStepTestResults(); + + $this->tablePrinter->printHeader($formatter, $feature, $this->outline, $stepTestResults); + $this->headerPrinted = true; + } + + /** + * Prints example row on example AFTER event. + * + * @param Formatter $formatter + * @param Event $event + * @param string $eventName + */ + private function printExampleRowOnAfterExampleEvent(Formatter $formatter, Event $event, $eventName) + { + if (!$event instanceof AfterScenarioTested || ExampleTested::AFTER !== $eventName) { + return; + } + + $example = $event->getScenario(); + + $this->exampleSetupPrinter->printSetup($formatter, $this->exampleSetup); + + foreach ($this->stepBeforeTestedEvents as $beforeEvent) { + $this->stepSetupPrinter->printSetup($formatter, $beforeEvent->getSetup()); + } + + $this->exampleRowPrinter->printExampleRow($formatter, $this->outline, $example, $this->stepAfterTestedEvents); + + foreach ($this->stepAfterTestedEvents as $afterEvent) { + $this->stepSetupPrinter->printTeardown($formatter, $afterEvent->getTeardown()); + } + + $this->exampleSetupPrinter->printTeardown($formatter, $event->getTeardown()); + + $this->exampleSetup = null; + $this->stepBeforeTestedEvents = array(); + $this->stepAfterTestedEvents = array(); + } + + /** + * Prints outline footer on outline AFTER event. + * + * @param Formatter $formatter + * @param Event $event + */ + private function printFooterOnAfterEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterOutlineTested) { + return; + } + + $this->tablePrinter->printFooter($formatter, $event->getTestResult()); + } + + /** + * Returns currently captured step events results. + * + * @return StepResult[] + */ + private function getStepTestResults() + { + return array_map( + function (AfterStepTested $event) { + return $event->getTestResult(); + }, + $this->stepAfterTestedEvents + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/ScenarioNodeListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/ScenarioNodeListener.php new file mode 100644 index 0000000..77ac28e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/ScenarioNodeListener.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\AST; + +use Behat\Behat\EventDispatcher\Event\ScenarioLikeTested; +use Behat\Behat\Output\Node\Printer\ScenarioPrinter; +use Behat\Behat\Output\Node\Printer\SetupPrinter; +use Behat\Testwork\EventDispatcher\Event\AfterSetup; +use Behat\Testwork\EventDispatcher\Event\AfterTested; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens to scenario events and calls appropriate printers (header/footer). + * + * @author Konstantin Kudryashov + */ +final class ScenarioNodeListener implements EventListener +{ + /** + * @var string + */ + private $beforeEventName; + /** + * @var string + */ + private $afterEventName; + /** + * @var ScenarioPrinter + */ + private $scenarioPrinter; + /** + * @var SetupPrinter + */ + private $setupPrinter; + + /** + * Initializes listener. + * + * @param string $beforeEventName + * @param string $afterEventName + * @param ScenarioPrinter $scenarioPrinter + * @param null|SetupPrinter $setupPrinter + */ + public function __construct( + $beforeEventName, + $afterEventName, + ScenarioPrinter $scenarioPrinter, + SetupPrinter $setupPrinter = null + ) { + $this->beforeEventName = $beforeEventName; + $this->afterEventName = $afterEventName; + $this->scenarioPrinter = $scenarioPrinter; + $this->setupPrinter = $setupPrinter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + if (!$event instanceof ScenarioLikeTested) { + return; + } + + $this->printHeaderOnBeforeEvent($formatter, $event, $eventName); + $this->printFooterOnAfterEvent($formatter, $event, $eventName); + } + + /** + * Prints scenario/background header on BEFORE event. + * + * @param Formatter $formatter + * @param ScenarioLikeTested|AfterSetup $event + * @param string $eventName + */ + private function printHeaderOnBeforeEvent(Formatter $formatter, ScenarioLikeTested $event, $eventName) + { + if ($this->beforeEventName !== $eventName || !$event instanceof AfterSetup) { + return; + } + + if ($this->setupPrinter) { + $this->setupPrinter->printSetup($formatter, $event->getSetup()); + } + + $this->scenarioPrinter->printHeader($formatter, $event->getFeature(), $event->getScenario()); + } + + /** + * Prints scenario/background footer on AFTER event. + * + * @param Formatter $formatter + * @param ScenarioLikeTested|AfterTested $event + * @param string $eventName + */ + private function printFooterOnAfterEvent(Formatter $formatter, ScenarioLikeTested $event, $eventName) + { + if ($this->afterEventName !== $eventName || !$event instanceof AfterTested) { + return; + } + + if ($this->setupPrinter) { + $this->setupPrinter->printTeardown($formatter, $event->getTeardown()); + } + + $this->scenarioPrinter->printFooter($formatter, $event->getTestResult()); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/StepListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/StepListener.php new file mode 100644 index 0000000..0d62a56 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/StepListener.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\AST; + +use Behat\Behat\EventDispatcher\Event\AfterStepSetup; +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Behat\EventDispatcher\Event\ExampleTested; +use Behat\Behat\EventDispatcher\Event\ScenarioLikeTested; +use Behat\Behat\EventDispatcher\Event\ScenarioTested; +use Behat\Behat\Output\Node\Printer\SetupPrinter; +use Behat\Behat\Output\Node\Printer\StepPrinter; +use Behat\Gherkin\Node\ScenarioLikeInterface; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens to step events and call appropriate printers. + * + * @author Konstantin Kudryashov + */ +final class StepListener implements EventListener +{ + /** + * @var StepPrinter + */ + private $stepPrinter; + /** + * @var ScenarioLikeInterface + */ + private $scenario; + /** + * @var null|SetupPrinter + */ + private $setupPrinter; + + /** + * Initializes listener. + * + * @param StepPrinter $stepPrinter + * @param null|SetupPrinter $setupPrinter + */ + public function __construct(StepPrinter $stepPrinter, SetupPrinter $setupPrinter = null) + { + $this->stepPrinter = $stepPrinter; + $this->setupPrinter = $setupPrinter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + $this->captureScenarioOnScenarioEvent($event); + $this->forgetScenarioOnAfterEvent($eventName); + $this->printStepSetupOnBeforeEvent($formatter, $event); + $this->printStepOnAfterEvent($formatter, $event); + } + + /** + * Captures scenario into the ivar on scenario/background/example BEFORE event. + * + * @param Event $event + */ + private function captureScenarioOnScenarioEvent(Event $event) + { + if (!$event instanceof ScenarioLikeTested) { + return; + } + + $this->scenario = $event->getScenario(); + } + + /** + * Removes scenario from the ivar on scenario/background/example AFTER event. + * + * @param string $eventName + */ + private function forgetScenarioOnAfterEvent($eventName) + { + if (!in_array($eventName, array(ScenarioTested::AFTER, ExampleTested::AFTER))) { + return; + } + + $this->scenario = null; + } + + private function printStepSetupOnBeforeEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterStepSetup) { + return; + } + + if ($this->setupPrinter) { + $this->setupPrinter->printSetup($formatter, $event->getSetup()); + } + } + + /** + * Prints step on AFTER event. + * + * @param Formatter $formatter + * @param Event $event + */ + private function printStepOnAfterEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterStepTested) { + return; + } + + $this->stepPrinter->printStep($formatter, $this->scenario, $event->getStep(), $event->getTestResult()); + + if ($this->setupPrinter) { + $this->setupPrinter->printTeardown($formatter, $event->getTeardown()); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/SuiteListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/SuiteListener.php new file mode 100644 index 0000000..8e116e0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/AST/SuiteListener.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\AST; + +use Behat\Behat\Output\Node\Printer\SetupPrinter; +use Behat\Testwork\EventDispatcher\Event\AfterSuiteSetup; +use Behat\Testwork\EventDispatcher\Event\AfterSuiteTested; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Behat suite listener. + * + * @author Konstantin Kudryashov + */ +final class SuiteListener implements EventListener +{ + /** + * @var SetupPrinter + */ + private $setupPrinter; + + /** + * Initializes listener. + * + * @param SetupPrinter $setupPrinter + */ + public function __construct(SetupPrinter $setupPrinter) + { + $this->setupPrinter = $setupPrinter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + if ($event instanceof AfterSuiteSetup) { + $this->setupPrinter->printSetup($formatter, $event->getSetup()); + } + + if ($event instanceof AfterSuiteTested) { + $this->setupPrinter->printTeardown($formatter, $event->getTeardown()); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/FireOnlySiblingsListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/FireOnlySiblingsListener.php new file mode 100644 index 0000000..7e57885 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/FireOnlySiblingsListener.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\Flow; + +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Behat fire only siblings listener. + * + * This listener catches all events, but proxies them to further listeners only if they + * live inside specific event lifecycle (between BEFORE and AFTER events). + * + * @author Konstantin Kudryashov + */ +class FireOnlySiblingsListener implements EventListener +{ + /** + * @var string + */ + private $beforeEventName; + /** + * @var string + */ + private $afterEventName; + /** + * @var EventListener + */ + private $descendant; + /** + * @var Boolean + */ + private $inContext = false; + + /** + * Initializes listener. + * + * @param string $beforeEventName + * @param string $afterEventName + * @param EventListener $descendant + */ + public function __construct($beforeEventName, $afterEventName, EventListener $descendant) + { + $this->beforeEventName = $beforeEventName; + $this->afterEventName = $afterEventName; + $this->descendant = $descendant; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + if ($this->beforeEventName === $eventName) { + $this->inContext = true; + } + + if ($this->inContext) { + $this->descendant->listenEvent($formatter, $event, $eventName); + } + + if ($this->afterEventName === $eventName) { + $this->inContext = false; + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/FirstBackgroundFiresFirstListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/FirstBackgroundFiresFirstListener.php new file mode 100644 index 0000000..f9bb95f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/FirstBackgroundFiresFirstListener.php @@ -0,0 +1,137 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\Flow; + +use Behat\Behat\EventDispatcher\Event\BackgroundTested; +use Behat\Behat\EventDispatcher\Event\ExampleTested; +use Behat\Behat\EventDispatcher\Event\FeatureTested; +use Behat\Behat\EventDispatcher\Event\OutlineTested; +use Behat\Behat\EventDispatcher\Event\ScenarioTested; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Behat first background fires first listener. + * + * This listener catches first scenario and background events in the feature and makes sure + * that background event are always fired before scenario events, thus following Gherkin format. + * + * @author Konstantin Kudryashov + */ +class FirstBackgroundFiresFirstListener implements EventListener +{ + /** + * @var \Behat\Testwork\Output\Node\EventListener\EventListener + */ + private $descendant; + /** + * @var Boolean + */ + private $firstBackgroundEnded = false; + /** + * @var Event[] + */ + private $delayedUntilBackgroundEnd = array(); + + /** + * Initializes listener. + * + * @param EventListener $descendant + */ + public function __construct(EventListener $descendant) + { + $this->descendant = $descendant; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + $this->flushStatesIfBeginningOfTheFeature($eventName); + $this->markFirstBackgroundPrintedAfterBackground($eventName); + + if ($this->isEventDelayedUntilFirstBackgroundPrinted($event)) { + $this->delayedUntilBackgroundEnd[] = array($event, $eventName); + + return; + } + + $this->descendant->listenEvent($formatter, $event, $eventName); + $this->fireDelayedEventsOnAfterBackground($formatter, $eventName); + } + + /** + * Flushes state if the event is the BEFORE feature. + * + * @param string $eventName + */ + private function flushStatesIfBeginningOfTheFeature($eventName) + { + if (FeatureTested::BEFORE !== $eventName) { + return; + } + + $this->firstBackgroundEnded = false; + } + + /** + * Marks first background printed. + * + * @param string $eventName + */ + private function markFirstBackgroundPrintedAfterBackground($eventName) + { + if (BackgroundTested::AFTER !== $eventName) { + return; + } + + $this->firstBackgroundEnded = true; + } + + /** + * Checks if provided event should be postponed until background is printed. + * + * @param Event $event + * + * @return Boolean + */ + private function isEventDelayedUntilFirstBackgroundPrinted(Event $event) + { + if (!$event instanceof ScenarioTested && !$event instanceof OutlineTested && !$event instanceof ExampleTested) { + return false; + } + + return !$this->firstBackgroundEnded && $event->getFeature()->hasBackground(); + } + + /** + * Fires delayed events on AFTER background event. + * + * @param Formatter $formatter + * @param string $eventName + */ + private function fireDelayedEventsOnAfterBackground(Formatter $formatter, $eventName) + { + if (BackgroundTested::AFTER !== $eventName) { + return; + } + + foreach ($this->delayedUntilBackgroundEnd as $eventInfo) { + list($event, $eventName) = $eventInfo; + + $this->descendant->listenEvent($formatter, $event, $eventName); + } + + $this->delayedUntilBackgroundEnd = array(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/OnlyFirstBackgroundFiresListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/OnlyFirstBackgroundFiresListener.php new file mode 100644 index 0000000..ad3679c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Flow/OnlyFirstBackgroundFiresListener.php @@ -0,0 +1,202 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\Flow; + +use Behat\Behat\EventDispatcher\Event\AfterStepSetup; +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Behat\EventDispatcher\Event\BackgroundTested; +use Behat\Behat\EventDispatcher\Event\FeatureTested; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Behat only first background fires listener. + * + * This listener catches all in-background events and then proxies them further + * only if they meet one of two conditions: + * + * 1. It is a first background + * 2. It is a failing step + * + * @author Konstantin Kudryashov + */ +class OnlyFirstBackgroundFiresListener implements EventListener +{ + /** + * @var EventListener + */ + private $descendant; + /** + * @var Boolean + */ + private $firstBackgroundEnded = false; + /** + * @var Boolean + */ + private $inBackground = false; + /** + * @var Boolean + */ + private $stepSetupHadOutput = false; + + /** + * Initializes listener. + * + * @param EventListener $descendant + */ + public function __construct(EventListener $descendant) + { + $this->descendant = $descendant; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + $this->flushStatesIfBeginningOfTheFeature($eventName); + $this->markBeginningOrEndOfTheBackground($eventName); + + if ($this->isSkippableEvent($event)) { + return; + } + + $this->markFirstBackgroundPrintedAfterBackground($eventName); + + $this->descendant->listenEvent($formatter, $event, $eventName); + } + + /** + * Flushes state if the event is the BEFORE feature. + * + * @param string $eventName + */ + private function flushStatesIfBeginningOfTheFeature($eventName) + { + if (FeatureTested::BEFORE !== $eventName) { + return; + } + + $this->firstBackgroundEnded = false; + $this->inBackground = false; + } + + /** + * Marks beginning or end of the background. + * + * @param string $eventName + */ + private function markBeginningOrEndOfTheBackground($eventName) + { + if (BackgroundTested::BEFORE === $eventName) { + $this->inBackground = true; + } + + if (BackgroundTested::AFTER === $eventName) { + $this->inBackground = false; + } + } + + /** + * Marks first background printed. + * + * @param string $eventName + */ + private function markFirstBackgroundPrintedAfterBackground($eventName) + { + if (BackgroundTested::AFTER !== $eventName) { + return; + } + + $this->firstBackgroundEnded = true; + } + + /** + * Checks if provided event is skippable. + * + * @param Event $event + * + * @return Boolean + */ + private function isSkippableEvent(Event $event) + { + if (!$this->firstBackgroundEnded) { + return false; + } + + return $event instanceof BackgroundTested || $this->isNonFailingConsequentBackgroundStep($event); + } + + /** + * Checks if provided event is a non-failing step in consequent background. + * + * @param Event $event + * + * @return Boolean + */ + private function isNonFailingConsequentBackgroundStep(Event $event) + { + if (!$this->inBackground) { + return false; + } + + return !$this->isStepEventWithOutput($event); + } + + /** + * Checks if provided event is a step event which setup or teardown produced any output. + * + * @param Event $event + * + * @return Boolean + */ + private function isStepEventWithOutput(Event $event) + { + return $this->isBeforeStepEventWithOutput($event) || $this->isAfterStepWithOutput($event); + } + + /** + * Checks if provided event is a BEFORE step with setup that produced output. + * + * @param Event $event + * + * @return Boolean + */ + private function isBeforeStepEventWithOutput(Event $event) + { + if ($event instanceof AfterStepSetup && $event->hasOutput()) { + $this->stepSetupHadOutput = true; + + return true; + } + + return false; + } + + /** + * Checks if provided event is an AFTER step with teardown that produced output. + * + * @param Event $event + * + * @return Boolean + */ + private function isAfterStepWithOutput(Event $event) + { + if ($event instanceof AfterStepTested && ($this->stepSetupHadOutput || $event->hasOutput())) { + $this->stepSetupHadOutput = false; + + return true; + } + + return false; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/HookStatsListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/HookStatsListener.php new file mode 100644 index 0000000..a8d6007 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/HookStatsListener.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\Statistics; + +use Behat\Behat\Output\Statistics\HookStat; +use Behat\Behat\Output\Statistics\Statistics; +use Behat\Testwork\Call\CallResult; +use Behat\Testwork\EventDispatcher\Event\AfterSetup; +use Behat\Testwork\EventDispatcher\Event\AfterTested; +use Behat\Testwork\Exception\ExceptionPresenter; +use Behat\Testwork\Hook\Tester\Setup\HookedSetup; +use Behat\Testwork\Hook\Tester\Setup\HookedTeardown; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens and records hook stats. + * + * @author Konstantin Kudryashov + */ +final class HookStatsListener implements EventListener +{ + /** + * @var Statistics + */ + private $statistics; + /** + * @var ExceptionPresenter + */ + private $exceptionPresenter; + + /** + * Initializes listener. + * + * @param Statistics $statistics + * @param ExceptionPresenter $exceptionPresenter + */ + public function __construct(Statistics $statistics, ExceptionPresenter $exceptionPresenter) + { + $this->statistics = $statistics; + $this->exceptionPresenter = $exceptionPresenter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + $this->captureHookStatsOnEvent($event); + } + + /** + * Captures hook stats on hooked event. + * + * @param Event $event + */ + private function captureHookStatsOnEvent(Event $event) + { + if ($event instanceof AfterSetup && $event->getSetup() instanceof HookedSetup) { + $this->captureBeforeHookStats($event->getSetup()); + } + + if ($event instanceof AfterTested && $event->getTeardown() instanceof HookedTeardown) { + $this->captureAfterHookStats($event->getTeardown()); + } + } + + /** + * Captures before hook stats. + * + * @param HookedSetup $setup + */ + private function captureBeforeHookStats(HookedSetup $setup) + { + $hookCallResults = $setup->getHookCallResults(); + + foreach ($hookCallResults as $hookCallResult) { + $this->captureHookStat($hookCallResult); + } + } + + /** + * Captures before hook stats. + * + * @param HookedTeardown $teardown + */ + private function captureAfterHookStats(HookedTeardown $teardown) + { + $hookCallResults = $teardown->getHookCallResults(); + + foreach ($hookCallResults as $hookCallResult) { + $this->captureHookStat($hookCallResult); + } + } + + /** + * Captures hook call result. + * + * @param CallResult $hookCallResult + */ + private function captureHookStat(CallResult $hookCallResult) + { + $callee = $hookCallResult->getCall()->getCallee(); + $hook = (string) $callee; + $path = $callee->getPath(); + $stdOut = $hookCallResult->getStdOut(); + $error = $hookCallResult->getException() + ? $this->exceptionPresenter->presentException($hookCallResult->getException()) + : null; + + $stat = new HookStat($hook, $path, $error, $stdOut); + $this->statistics->registerHookStat($stat); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/ScenarioStatsListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/ScenarioStatsListener.php new file mode 100644 index 0000000..f83a38f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/ScenarioStatsListener.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\Statistics; + +use Behat\Behat\EventDispatcher\Event\AfterFeatureTested; +use Behat\Behat\EventDispatcher\Event\AfterScenarioTested; +use Behat\Behat\EventDispatcher\Event\BeforeFeatureTested; +use Behat\Behat\Output\Statistics\ScenarioStat; +use Behat\Behat\Output\Statistics\Statistics; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens and records scenario events to the statistics. + * + * @author Konstantin Kudryashov + */ +final class ScenarioStatsListener implements EventListener +{ + /** + * @var Statistics + */ + private $statistics; + /** + * @var string + */ + private $currentFeaturePath; + + /** + * Initializes listener. + * + * @param Statistics $statistics + */ + public function __construct(Statistics $statistics) + { + $this->statistics = $statistics; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + $this->captureCurrentFeaturePathOnBeforeFeatureEvent($event); + $this->forgetCurrentFeaturePathOnAfterFeatureEvent($event); + $this->captureScenarioOrExampleStatsOnAfterEvent($event); + } + + /** + * Captures current feature file path to the ivar on feature BEFORE event. + * + * @param Event $event + */ + private function captureCurrentFeaturePathOnBeforeFeatureEvent(Event $event) + { + if (!$event instanceof BeforeFeatureTested) { + return; + } + + $this->currentFeaturePath = $event->getFeature()->getFile(); + } + + /** + * Removes current feature file path from the ivar on feature AFTER event. + * + * @param Event $event + */ + private function forgetCurrentFeaturePathOnAfterFeatureEvent($event) + { + if (!$event instanceof AfterFeatureTested) { + return; + } + + $this->currentFeaturePath = null; + } + + /** + * Captures scenario or example stats on their AFTER event. + * + * @param Event $event + */ + private function captureScenarioOrExampleStatsOnAfterEvent(Event $event) + { + if (!$event instanceof AfterScenarioTested) { + return; + } + + $scenario = $event->getScenario(); + $title = $scenario->getTitle(); + $path = sprintf('%s:%d', $this->currentFeaturePath, $scenario->getLine()); + $resultCode = $event->getTestResult()->getResultCode(); + + $stat = new ScenarioStat($title, $path, $resultCode); + $this->statistics->registerScenarioStat($stat); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/StatisticsListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/StatisticsListener.php new file mode 100644 index 0000000..1845e1b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/StatisticsListener.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\Statistics; + +use Behat\Behat\Output\Node\Printer\StatisticsPrinter; +use Behat\Behat\Output\Statistics\Statistics; +use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Collects general suite stats such as time and memory during its execution and prints it afterwards. + * + * @author Konstantin Kudryashov + */ +final class StatisticsListener implements EventListener +{ + /** + * @var Statistics + */ + private $statistics; + /** + * @var StatisticsPrinter + */ + private $printer; + + /** + * Initializes listener. + * + * @param Statistics $statistics + * @param StatisticsPrinter $statisticsPrinter + */ + public function __construct(Statistics $statistics, StatisticsPrinter $statisticsPrinter) + { + $this->statistics = $statistics; + $this->printer = $statisticsPrinter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + $this->startTimerOnBeforeExercise($eventName); + $this->printStatisticsOnAfterExerciseEvent($formatter, $eventName); + } + + /** + * Starts timer on exercise BEFORE event. + * + * @param string $eventName + */ + private function startTimerOnBeforeExercise($eventName) + { + if (ExerciseCompleted::BEFORE !== $eventName) { + return; + } + + $this->statistics->startTimer(); + } + + /** + * Prints statistics on after exercise event. + * + * @param Formatter $formatter + * @param string $eventName + */ + private function printStatisticsOnAfterExerciseEvent(Formatter $formatter, $eventName) + { + if (ExerciseCompleted::AFTER !== $eventName) { + return; + } + + $this->statistics->stopTimer(); + $this->printer->printStatistics($formatter, $this->statistics); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/StepStatsListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/StepStatsListener.php new file mode 100644 index 0000000..a2795d3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/StepStatsListener.php @@ -0,0 +1,158 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\EventListener\Statistics; + +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Behat\EventDispatcher\Event\BeforeFeatureTested; +use Behat\Behat\EventDispatcher\Event\FeatureTested; +use Behat\Behat\Output\Statistics\Statistics; +use Behat\Behat\Output\Statistics\StepStat; +use Behat\Behat\Tester\Exception\PendingException; +use Behat\Behat\Tester\Result\ExecutedStepResult; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Testwork\Exception\ExceptionPresenter; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Behat\Testwork\Tester\Result\ExceptionResult; +use Exception; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens and records step events to statistics. + * + * @author Konstantin Kudryashov + */ +final class StepStatsListener implements EventListener +{ + /** + * @var Statistics + */ + private $statistics; + /** + * @var string + */ + private $currentFeaturePath; + /** + * @var ExceptionPresenter + */ + private $exceptionPresenter; + + /** + * Initializes listener. + * + * @param Statistics $statistics + * @param ExceptionPresenter $exceptionPresenter + */ + public function __construct(Statistics $statistics, ExceptionPresenter $exceptionPresenter) + { + $this->statistics = $statistics; + $this->exceptionPresenter = $exceptionPresenter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + $this->captureCurrentFeaturePathOnBeforeFeatureEvent($event); + $this->forgetCurrentFeaturePathOnAfterFeatureEvent($eventName); + $this->captureStepStatsOnAfterEvent($event); + } + + /** + * Captures current feature file path to the ivar on feature BEFORE event. + * + * @param Event $event + */ + private function captureCurrentFeaturePathOnBeforeFeatureEvent(Event $event) + { + if (!$event instanceof BeforeFeatureTested) { + return; + } + + $this->currentFeaturePath = $event->getFeature()->getFile(); + } + + /** + * Removes current feature file path from the ivar on feature AFTER event. + * + * @param string $eventName + */ + private function forgetCurrentFeaturePathOnAfterFeatureEvent($eventName) + { + if (FeatureTested::AFTER !== $eventName) { + return; + } + + $this->currentFeaturePath = null; + } + + /** + * Captures step stats on step AFTER event. + * + * @param Event $event + */ + private function captureStepStatsOnAfterEvent(Event $event) + { + if (!$event instanceof AfterStepTested) { + return; + } + + $result = $event->getTestResult(); + $step = $event->getStep(); + $text = sprintf('%s %s', $step->getKeyword(), $step->getText()); + $exception = $this->getStepException($result); + + $path = $this->getStepPath($event, $exception); + $error = $exception ? $this->exceptionPresenter->presentException($exception) : null; + $stdOut = $result instanceof ExecutedStepResult ? $result->getCallResult()->getStdOut() : null; + + $resultCode = $result->getResultCode(); + $stat = new StepStat($text, $path, $resultCode, $error, $stdOut); + + $this->statistics->registerStepStat($stat); + } + + /** + * Gets exception from the step test results. + * + * @param StepResult $result + * + * @return null|Exception + */ + private function getStepException(StepResult $result) + { + if ($result instanceof ExceptionResult) { + return $result->getException(); + } + + return null; + } + + /** + * Gets step path from the AFTER test event and exception. + * + * @param AfterStepTested $event + * @param null|Exception $exception + * + * @return string + */ + private function getStepPath(AfterStepTested $event, Exception $exception = null) + { + $path = sprintf('%s:%d', $this->currentFeaturePath, $event->getStep()->getLine()); + + if ($exception && $exception instanceof PendingException) { + $path = $event->getTestResult()->getStepDefinition()->getPath(); + } + + return $path; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/CounterPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/CounterPrinter.php new file mode 100644 index 0000000..ff567db --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/CounterPrinter.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Behat counter printer. + * + * @author Konstantin Kudryashov + */ +final class CounterPrinter +{ + /** + * @var ResultToStringConverter + */ + private $resultConverter; + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * Initializes printer. + * + * @param ResultToStringConverter $resultConverter + * @param TranslatorInterface $translator + */ + public function __construct(ResultToStringConverter $resultConverter, TranslatorInterface $translator) + { + $this->resultConverter = $resultConverter; + $this->translator = $translator; + } + + /** + * Prints scenario and step counters. + * + * @param OutputPrinter $printer + * @param string $intro + * @param array $stats + */ + public function printCounters(OutputPrinter $printer, $intro, array $stats) + { + $stats = array_filter($stats, function ($count) { return 0 !== $count; }); + + if (0 === count($stats)) { + $totalCount = 0; + } else { + $totalCount = array_sum($stats); + } + + $detailedStats = array(); + foreach ($stats as $resultCode => $count) { + $style = $this->resultConverter->convertResultCodeToString($resultCode); + + $transId = $style . '_count'; + $message = $this->translator->transChoice($transId, $count, array('%1%' => $count), 'output'); + + $detailedStats[] = sprintf('{+%s}%s{-%s}', $style, $message, $style); + } + + $message = $this->translator->transChoice($intro, $totalCount, array('%1%' => $totalCount), 'output'); + $printer->write($message); + + if (count($detailedStats)) { + $printer->write(sprintf(' (%s)', implode(', ', $detailedStats))); + } + + $printer->writeln(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ExamplePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ExamplePrinter.php new file mode 100644 index 0000000..048f547 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ExamplePrinter.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Gherkin\Node\ExampleNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints example headers and footers. + * + * @author Konstantin Kudryashov + */ +interface ExamplePrinter +{ + /** + * Prints example header using provided printer. + * + * @param Formatter $formatter + * @param FeatureNode $feature + * @param ExampleNode $example + */ + public function printHeader(Formatter $formatter, FeatureNode $feature, ExampleNode $example); + + /** + * Prints example footer using provided printer. + * + * @param Formatter $formatter + * @param TestResult $result + */ + public function printFooter(Formatter $formatter, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ExampleRowPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ExampleRowPrinter.php new file mode 100644 index 0000000..1b52997 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ExampleRowPrinter.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Gherkin\Node\ExampleNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Output\Formatter; + +/** + * Prints outline example row results. + * + * @author Konstantin Kudryashov + */ +interface ExampleRowPrinter +{ + /** + * Prints example row result using provided printer. + * + * @param Formatter $formatter + * @param OutlineNode $outline + * @param ExampleNode $example + * @param AfterStepTested[] $events + */ + public function printExampleRow(Formatter $formatter, OutlineNode $outline, ExampleNode $example, array $events); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/FeaturePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/FeaturePrinter.php new file mode 100644 index 0000000..699615f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/FeaturePrinter.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints feature headers and footers. + * + * @author Konstantin Kudryashov + */ +interface FeaturePrinter +{ + /** + * Prints feature header using provided formatter. + * + * @param Formatter $formatter + * @param FeatureNode $feature + */ + public function printHeader(Formatter $formatter, FeatureNode $feature); + + /** + * Prints feature footer using provided printer. + * + * @param Formatter $formatter + * @param TestResult $result + */ + public function printFooter(Formatter $formatter, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/ResultToStringConverter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/ResultToStringConverter.php new file mode 100644 index 0000000..dabddfd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/ResultToStringConverter.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Helper; + +use Behat\Behat\Tester\Result\StepResult; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Converts result objects into a string representation. + * + * @author Konstantin Kudryashov + */ +final class ResultToStringConverter +{ + /** + * Converts provided test result to a string. + * + * @param TestResult $result + * + * @return string + */ + public function convertResultToString(TestResult $result) + { + return $this->convertResultCodeToString($result->getResultCode()); + } + + /** + * Converts provided result code to a string. + * + * @param integer $resultCode + * + * @return string + */ + public function convertResultCodeToString($resultCode) + { + switch ($resultCode) { + case TestResult::SKIPPED: + return 'skipped'; + case TestResult::PENDING: + return 'pending'; + case TestResult::FAILED: + return 'failed'; + case StepResult::UNDEFINED: + return 'undefined'; + } + + return 'passed'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/StepTextPainter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/StepTextPainter.php new file mode 100644 index 0000000..d2becc5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/StepTextPainter.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Helper; + +use Behat\Behat\Definition\Definition; +use Behat\Behat\Definition\Pattern\PatternTransformer; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Paints step text (with tokens) according to found definition. + * + * @author Konstantin Kudryashov + */ +final class StepTextPainter +{ + /** + * @var PatternTransformer + */ + private $patternTransformer; + /** + * @var ResultToStringConverter + */ + private $resultConverter; + + /** + * Initializes painter. + * + * @param PatternTransformer $patternTransformer + * @param ResultToStringConverter $resultConverter + */ + public function __construct(PatternTransformer $patternTransformer, ResultToStringConverter $resultConverter) + { + $this->patternTransformer = $patternTransformer; + $this->resultConverter = $resultConverter; + } + + /** + * Colorizes step text arguments according to definition. + * + * @param string $text + * @param Definition $definition + * @param TestResult $result + * + * @return string + */ + public function paintText($text, Definition $definition, TestResult $result) + { + $regex = $this->patternTransformer->transformPatternToRegex($definition->getPattern()); + $style = $this->resultConverter->convertResultToString($result); + $paramStyle = $style . '_param'; + + // If it's just a string - skip + if ('/' !== substr($regex, 0, 1)) { + return $text; + } + + // Find arguments with offsets + $matches = array(); + preg_match($regex, $text, $matches, PREG_OFFSET_CAPTURE); + array_shift($matches); + + // Replace arguments with colorized ones + $shift = 0; + $lastReplacementPosition = 0; + foreach ($matches as $key => $match) { + if (!is_numeric($key) || -1 === $match[1] || false !== strpos($match[0], '<')) { + continue; + } + + $offset = $match[1] + $shift; + $value = $match[0]; + + // Skip inner matches + if ($lastReplacementPosition > $offset) { + continue; + } + $lastReplacementPosition = $offset + strlen($value); + + $begin = substr($text, 0, $offset); + $end = substr($text, $lastReplacementPosition); + $format = "{-$style}{+$paramStyle}%s{-$paramStyle}{+$style}"; + $text = sprintf("%s{$format}%s", $begin, $value, $end); + + // Keep track of how many extra characters are added + $shift += strlen($format) - 2; + $lastReplacementPosition += strlen($format) - 2; + } + + // Replace "<", ">" with colorized ones + $text = preg_replace( + '/(<[^>]+>)/', + "{-$style}{+$paramStyle}\$1{-$paramStyle}{+$style}", + $text + ); + + return $text; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/WidthCalculator.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/WidthCalculator.php new file mode 100644 index 0000000..bef1881 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Helper/WidthCalculator.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Helper; + +use Behat\Gherkin\Node\ExampleNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\StepNode; + +/** + * Calculates width of scenario. Width of scenario = max width of scenario title and scenario step texts. + * + * @author Konstantin Kudryashov + */ +final class WidthCalculator +{ + /** + * Calculates scenario width. + * + * @param Scenario $scenario + * @param integer $indentation + * @param integer $subIndentation + * + * @return integer + */ + public function calculateScenarioWidth(Scenario $scenario, $indentation, $subIndentation) + { + $length = $this->calculateScenarioHeaderWidth($scenario, $indentation); + + foreach ($scenario->getSteps() as $step) { + $stepLength = $this->calculateStepWidth($step, $indentation + $subIndentation); + $length = max($length, $stepLength); + } + + return $length; + } + + /** + * Calculates outline examples width. + * + * @param ExampleNode $example + * @param integer $indentation + * @param integer $subIndentation + * + * @return integer + */ + public function calculateExampleWidth(ExampleNode $example, $indentation, $subIndentation) + { + $length = $this->calculateScenarioHeaderWidth($example, $indentation); + + foreach ($example->getSteps() as $step) { + $stepLength = $this->calculateStepWidth($step, $indentation + $subIndentation); + $length = max($length, $stepLength); + } + + return $length; + } + + /** + * Calculates scenario header width. + * + * @param Scenario $scenario + * @param integer $indentation + * + * @return integer + */ + public function calculateScenarioHeaderWidth(Scenario $scenario, $indentation) + { + $indentText = str_repeat(' ', intval($indentation)); + + if ($scenario instanceof ExampleNode) { + $header = sprintf('%s%s', $indentText, $scenario->getTitle()); + } else { + $title = $scenario->getTitle(); + $lines = explode("\n", $title); + $header = sprintf('%s%s: %s', $indentText, $scenario->getKeyword(), array_shift($lines)); + } + + return mb_strlen(rtrim($header), 'utf8'); + } + + /** + * Calculates step width. + * + * @param StepNode $step + * @param integer $indentation + * + * @return integer + */ + public function calculateStepWidth(StepNode $step, $indentation) + { + $indentText = str_repeat(' ', intval($indentation)); + + $text = sprintf('%s%s %s', $indentText, $step->getKeyword(), $step->getText()); + + return mb_strlen($text, 'utf8'); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ListPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ListPrinter.php new file mode 100644 index 0000000..3f0e4db --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ListPrinter.php @@ -0,0 +1,194 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Behat\Output\Statistics\HookStat; +use Behat\Behat\Output\Statistics\ScenarioStat; +use Behat\Behat\Output\Statistics\StepStat; +use Behat\Testwork\Exception\ExceptionPresenter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Behat list printer. + * + * @author Konstantin Kudryashov + */ +final class ListPrinter +{ + /** + * @var ResultToStringConverter + */ + private $resultConverter; + /** + * @var ExceptionPresenter + */ + private $exceptionPresenter; + /** + * @var TranslatorInterface + */ + private $translator; + /** + * @var string + */ + private $basePath; + + /** + * Initializes printer. + * + * @param ResultToStringConverter $resultConverter + * @param ExceptionPresenter $exceptionPresenter + * @param TranslatorInterface $translator + * @param string $basePath + */ + public function __construct( + ResultToStringConverter $resultConverter, + ExceptionPresenter $exceptionPresenter, + TranslatorInterface $translator, + $basePath + ) { + $this->resultConverter = $resultConverter; + $this->exceptionPresenter = $exceptionPresenter; + $this->translator = $translator; + $this->basePath = $basePath; + } + + /** + * Prints scenarios list. + * + * @param OutputPrinter $printer + * @param string $intro + * @param integer $resultCode + * @param ScenarioStat[] $scenarioStats + */ + public function printScenariosList(OutputPrinter $printer, $intro, $resultCode, array $scenarioStats) + { + if (!count($scenarioStats)) { + return; + } + + $style = $this->resultConverter->convertResultCodeToString($resultCode); + $intro = $this->translator->trans($intro, array(), 'output'); + + $printer->writeln(sprintf('--- {+%s}%s{-%s}' . PHP_EOL, $style, $intro, $style)); + foreach ($scenarioStats as $stat) { + $path = $this->relativizePaths((string) $stat); + $printer->writeln(sprintf(' {+%s}%s{-%s}', $style, $path, $style)); + } + + $printer->writeln(); + } + + /** + * Prints step list. + * + * @param OutputPrinter $printer + * @param string $intro + * @param integer $resultCode + * @param StepStat[] $stepStats + */ + public function printStepList(OutputPrinter $printer, $intro, $resultCode, array $stepStats) + { + if (!count($stepStats)) { + return; + } + + $style = $this->resultConverter->convertResultCodeToString($resultCode); + $intro = $this->translator->trans($intro, array(), 'output'); + + $printer->writeln(sprintf('--- {+%s}%s{-%s}' . PHP_EOL, $style, $intro, $style)); + + foreach ($stepStats as $stepStat) { + $name = $stepStat->getText(); + $path = $stepStat->getPath(); + $stdOut = $stepStat->getStdOut(); + $error = $stepStat->getError(); + + $this->printStat($printer, $name, $path, $style, $stdOut, $error); + } + } + + /** + * Prints failed hooks list. + * + * @param OutputPrinter $printer + * @param string $intro + * @param HookStat[] $failedHookStats + */ + public function printFailedHooksList(OutputPrinter $printer, $intro, array $failedHookStats) + { + if (!count($failedHookStats)) { + return; + } + + $style = $this->resultConverter->convertResultCodeToString(TestResult::FAILED); + $intro = $this->translator->trans($intro, array(), 'output'); + + $printer->writeln(sprintf('--- {+%s}%s{-%s}' . PHP_EOL, $style, $intro, $style)); + foreach ($failedHookStats as $hookStat) { + $name = $hookStat->getName(); + $path = $hookStat->getPath(); + $stdOut = $hookStat->getStdOut(); + $error = $hookStat->getError(); + + $this->printStat($printer, $name, $path, $style, $stdOut, $error); + } + } + + /** + * Prints hook stat. + * + * @param OutputPrinter $printer + * @param string $name + * @param string $path + * @param string $style + * @param null|string $stdOut + * @param null|string $error + */ + private function printStat(OutputPrinter $printer, $name, $path, $style, $stdOut, $error) + { + $path = $this->relativizePaths($path); + $printer->writeln(sprintf(' {+%s}%s{-%s} {+comment}# %s{-comment}', $style, $name, $style, $path)); + + $pad = function ($line) { return ' ' . $line; }; + + if (null !== $stdOut) { + $padText = function ($line) { return ' │ ' . $line; }; + $stdOutString = array_map($padText, explode("\n", $stdOut)); + $printer->writeln(implode("\n", $stdOutString)); + } + + if ($error) { + $exceptionString = implode("\n", array_map($pad, explode("\n", $error))); + $printer->writeln(sprintf('{+%s}%s{-%s}', $style, $exceptionString, $style)); + } + + $printer->writeln(); + } + + /** + * Transforms path to relative. + * + * @param string $path + * + * @return string + */ + private function relativizePaths($path) + { + if (!$this->basePath) { + return $path; + } + + return str_replace($this->basePath . DIRECTORY_SEPARATOR, '', $path); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/OutlinePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/OutlinePrinter.php new file mode 100644 index 0000000..eb460ad --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/OutlinePrinter.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints outline headers and footers. + * + * @author Konstantin Kudryashov + */ +interface OutlinePrinter +{ + /** + * Prints outline header using provided printer. + * + * @param Formatter $formatter + * @param FeatureNode $feature + * @param OutlineNode $outline + */ + public function printHeader(Formatter $formatter, FeatureNode $feature, OutlineNode $outline); + + /** + * Prints outline footer using provided printer. + * + * @param Formatter $formatter + * @param TestResult $result + */ + public function printFooter(Formatter $formatter, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/OutlineTablePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/OutlineTablePrinter.php new file mode 100644 index 0000000..488fae6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/OutlineTablePrinter.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints outline table representation headers and footers. + * + * @author Konstantin Kudryashov + */ +interface OutlineTablePrinter +{ + /** + * Prints outline header using provided printer and first row example step results. + * + * @param Formatter $formatter + * @param FeatureNode $feature + * @param OutlineNode $outline + * @param StepResult[] $results + */ + public function printHeader(Formatter $formatter, FeatureNode $feature, OutlineNode $outline, array $results); + + /** + * Prints outline footer using provided printer. + * + * @param Formatter $formatter + * @param TestResult $result + */ + public function printFooter(Formatter $formatter, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyExamplePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyExamplePrinter.php new file mode 100644 index 0000000..2d5babf --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyExamplePrinter.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\ExamplePrinter; +use Behat\Gherkin\Node\ExampleNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints example header (usually simply an example row) and footer. + * + * @author Konstantin Kudryashov + */ +final class PrettyExamplePrinter implements ExamplePrinter +{ + /** + * @var PrettyPathPrinter + */ + private $pathPrinter; + /** + * @var string + */ + private $indentText; + + /** + * Initializes printer. + * + * @param PrettyPathPrinter $pathPrinter + * @param integer $indentation + */ + public function __construct(PrettyPathPrinter $pathPrinter, $indentation = 6) + { + $this->pathPrinter = $pathPrinter; + $this->indentText = str_repeat(' ', intval($indentation)); + } + + /** + * {@inheritdoc} + */ + public function printHeader(Formatter $formatter, FeatureNode $feature, ExampleNode $example) + { + $this->printTitle($formatter->getOutputPrinter(), $example); + $this->pathPrinter->printScenarioPath($formatter, $feature, $example, mb_strlen($this->indentText, 'utf8')); + } + + /** + * {@inheritdoc} + */ + public function printFooter(Formatter $formatter, TestResult $result) + { + } + + /** + * Prints example title. + * + * @param OutputPrinter $printer + * @param ExampleNode $example + */ + private function printTitle(OutputPrinter $printer, ExampleNode $example) + { + $printer->write(sprintf('%s%s', $this->indentText, $example->getTitle())); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyExampleRowPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyExampleRowPrinter.php new file mode 100644 index 0000000..109dd25 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyExampleRowPrinter.php @@ -0,0 +1,185 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Behat\Output\Node\Printer\ExampleRowPrinter; +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Behat\Tester\Result\ExecutedStepResult; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\ExampleNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\EventDispatcher\Event\AfterTested; +use Behat\Testwork\Exception\ExceptionPresenter; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\ExceptionResult; +use Behat\Testwork\Tester\Result\TestResults; + +/** + * Prints example results in form of a table row. + * + * @author Konstantin Kudryashov + */ +final class PrettyExampleRowPrinter implements ExampleRowPrinter +{ + /** + * @var ResultToStringConverter + */ + private $resultConverter; + /** + * @var ExceptionPresenter + */ + private $exceptionPresenter; + /** + * @var string + */ + private $indentText; + /** + * @var string + */ + private $subIndentText; + + /** + * Initializes printer. + * + * @param ResultToStringConverter $resultConverter + * @param ExceptionPresenter $exceptionPresenter + * @param integer $indentation + * @param integer $subIndentation + */ + public function __construct( + ResultToStringConverter $resultConverter, + ExceptionPresenter $exceptionPresenter, + $indentation = 6, + $subIndentation = 2 + ) { + $this->resultConverter = $resultConverter; + $this->exceptionPresenter = $exceptionPresenter; + $this->indentText = str_repeat(' ', intval($indentation)); + $this->subIndentText = $this->indentText . str_repeat(' ', intval($subIndentation)); + } + + /** + * {@inheritdoc} + */ + public function printExampleRow(Formatter $formatter, OutlineNode $outline, ExampleNode $example, array $events) + { + $rowNum = array_search($example, $outline->getExamples()) + 1; + $wrapper = $this->getWrapperClosure($outline, $example, $events); + $row = $outline->getExampleTable()->getRowAsStringWithWrappedValues($rowNum, $wrapper); + + $formatter->getOutputPrinter()->writeln(sprintf('%s%s', $this->indentText, $row)); + $this->printStepExceptionsAndStdOut($formatter->getOutputPrinter(), $events); + } + + /** + * Creates wrapper-closure for the example table. + * + * @param OutlineNode $outline + * @param ExampleNode $example + * @param AfterStepTested[] $stepEvents + * + * @return callable + */ + private function getWrapperClosure(OutlineNode $outline, ExampleNode $example, array $stepEvents) + { + $resultConverter = $this->resultConverter; + + return function ($value, $column) use ($outline, $example, $stepEvents, $resultConverter) { + $results = array(); + foreach ($stepEvents as $event) { + $index = array_search($event->getStep(), $example->getSteps()); + $header = $outline->getExampleTable()->getRow(0); + $steps = $outline->getSteps(); + $outlineStepText = $steps[$index]->getText(); + + if (false !== strpos($outlineStepText, '<' . $header[$column] . '>')) { + $results[] = $event->getTestResult(); + } + } + + $result = new TestResults($results); + $style = $resultConverter->convertResultToString($result); + + return sprintf('{+%s}%s{-%s}', $style, $value, $style); + }; + } + + /** + * Prints step events exceptions (if has some). + * + * @param OutputPrinter $printer + * @param AfterTested[] $events + */ + private function printStepExceptionsAndStdOut(OutputPrinter $printer, array $events) + { + foreach ($events as $event) { + $this->printStepStdOut($printer, $event->getTestResult()); + $this->printStepException($printer, $event->getTestResult()); + } + } + + /** + * Prints step exception (if has one). + * + * @param OutputPrinter $printer + * @param StepResult $result + */ + private function printStepException(OutputPrinter $printer, StepResult $result) + { + $style = $this->resultConverter->convertResultToString($result); + + if (!$result instanceof ExceptionResult || !$result->hasException()) { + return; + } + + $text = $this->exceptionPresenter->presentException($result->getException()); + $indentedText = implode("\n", array_map(array($this, 'subIndent'), explode("\n", $text))); + $printer->writeln(sprintf('{+%s}%s{-%s}', $style, $indentedText, $style)); + } + + /** + * Prints step output (if has one). + * + * @param OutputPrinter $printer + * @param StepResult $result + */ + private function printStepStdOut(OutputPrinter $printer, StepResult $result) + { + if (!$result instanceof ExecutedStepResult || null === $result->getCallResult()->getStdOut()) { + return; + } + + $callResult = $result->getCallResult(); + $indentedText = $this->subIndentText; + + $pad = function ($line) use ($indentedText) { + return sprintf( + '%s│ {+stdout}%s{-stdout}', $indentedText, $line + ); + }; + + $printer->writeln(implode("\n", array_map($pad, explode("\n", $callResult->getStdOut())))); + } + + /** + * Indents text to the subIndentation level. + * + * @param string $text + * + * @return string + */ + private function subIndent($text) + { + return $this->subIndentText . $text; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyFeaturePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyFeaturePrinter.php new file mode 100644 index 0000000..1a352c7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyFeaturePrinter.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\FeaturePrinter; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\TaggedNodeInterface; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints feature header and footer. + * + * @author Konstantin Kudryashov + */ +final class PrettyFeaturePrinter implements FeaturePrinter +{ + /** + * @var string + */ + private $indentText; + /** + * @var string + */ + private $subIndentText; + + /** + * Initializes printer. + * + * @param integer $indentation + * @param integer $subIndentation + */ + public function __construct($indentation = 0, $subIndentation = 2) + { + $this->indentText = str_repeat(' ', intval($indentation)); + $this->subIndentText = $this->indentText . str_repeat(' ', intval($subIndentation)); + } + + /** + * {@inheritdoc} + */ + public function printHeader(Formatter $formatter, FeatureNode $feature) + { + if ($feature instanceof TaggedNodeInterface) { + $this->printTags($formatter->getOutputPrinter(), $feature->getTags()); + } + + $this->printTitle($formatter->getOutputPrinter(), $feature); + $this->printDescription($formatter->getOutputPrinter(), $feature); + } + + /** + * {@inheritdoc} + */ + public function printFooter(Formatter $formatter, TestResult $result) + { + } + + /** + * Prints feature tags. + * + * @param OutputPrinter $printer + * @param string[] $tags + */ + private function printTags(OutputPrinter $printer, array $tags) + { + if (!count($tags)) { + return; + } + + $tags = array_map(array($this, 'prependTagWithTagSign'), $tags); + $printer->writeln(sprintf('%s{+tag}%s{-tag}', $this->indentText, implode(' ', $tags))); + } + + /** + * Prints feature title using provided printer. + * + * @param OutputPrinter $printer + * @param FeatureNode $feature + */ + private function printTitle(OutputPrinter $printer, FeatureNode $feature) + { + $printer->write(sprintf('%s{+keyword}%s:{-keyword}', $this->indentText, $feature->getKeyword())); + + if ($title = $feature->getTitle()) { + $printer->write(sprintf(' %s', $title)); + } + + $printer->writeln(); + } + + /** + * Prints feature description using provided printer. + * + * @param OutputPrinter $printer + * @param FeatureNode $feature + */ + private function printDescription(OutputPrinter $printer, FeatureNode $feature) + { + if (!$feature->getDescription()) { + $printer->writeln(); + + return; + } + + foreach (explode("\n", $feature->getDescription()) as $descriptionLine) { + $printer->writeln(sprintf('%s%s', $this->subIndentText, $descriptionLine)); + } + + $printer->writeln(); + } + + /** + * Prepends tags string with tag-sign. + * + * @param string $tag + * + * @return string + */ + private function prependTagWithTagSign($tag) + { + return '@' . $tag; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyOutlinePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyOutlinePrinter.php new file mode 100644 index 0000000..8fbc033 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyOutlinePrinter.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Behat\Output\Node\Printer\OutlinePrinter; +use Behat\Behat\Output\Node\Printer\ScenarioPrinter; +use Behat\Behat\Output\Node\Printer\StepPrinter; +use Behat\Behat\Tester\Result\UndefinedStepResult; +use Behat\Gherkin\Node\ExampleTableNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints outline header with outline steps and table header. + * + * @author Konstantin Kudryashov + */ +final class PrettyOutlinePrinter implements OutlinePrinter +{ + /** + * @var ScenarioPrinter + */ + private $scenarioPrinter; + /** + * @var StepPrinter + */ + private $stepPrinter; + /** + * @var ResultToStringConverter + */ + private $resultConverter; + /** + * @var string + */ + private $indentText; + /** + * @var string + */ + private $subIndentText; + + /** + * @param ScenarioPrinter $scenarioPrinter + * @param StepPrinter $stepPrinter + * @param ResultToStringConverter $resultConverter + * @param integer $indentation + * @param integer $subIndentation + */ + public function __construct( + ScenarioPrinter $scenarioPrinter, + StepPrinter $stepPrinter, + ResultToStringConverter $resultConverter, + $indentation = 4, + $subIndentation = 2 + ) { + $this->scenarioPrinter = $scenarioPrinter; + $this->stepPrinter = $stepPrinter; + $this->resultConverter = $resultConverter; + $this->indentText = str_repeat(' ', intval($indentation)); + $this->subIndentText = $this->indentText . str_repeat(' ', intval($subIndentation)); + } + + /** + * {@inheritdoc} + */ + public function printHeader(Formatter $formatter, FeatureNode $feature, OutlineNode $outline) + { + $this->scenarioPrinter->printHeader($formatter, $feature, $outline); + + $this->printExamplesSteps($formatter, $outline, $outline->getSteps()); + $this->printExamplesTableHeader($formatter->getOutputPrinter(), $outline->getExampleTable()); + } + + /** + * {@inheritdoc} + */ + public function printFooter(Formatter $formatter, TestResult $result) + { + $formatter->getOutputPrinter()->writeln(); + } + + /** + * Prints outline steps. + * + * @param Formatter $formatter + * @param OutlineNode $outline + * @param StepNode[] $steps + */ + private function printExamplesSteps(Formatter $formatter, OutlineNode $outline, array $steps) + { + foreach ($steps as $step) { + $this->stepPrinter->printStep($formatter, $outline, $step, new UndefinedStepResult()); + } + + $formatter->getOutputPrinter()->writeln(); + } + + /** + * Prints examples table header. + * + * @param OutputPrinter $printer + * @param ExampleTableNode $table + */ + private function printExamplesTableHeader(OutputPrinter $printer, ExampleTableNode $table) + { + $printer->writeln(sprintf('%s{+keyword}%s:{-keyword}', $this->indentText, $table->getKeyword())); + + $rowNum = 0; + $wrapper = $this->getWrapperClosure(); + $row = $table->getRowAsStringWithWrappedValues($rowNum, $wrapper); + + $printer->writeln(sprintf('%s%s', $this->subIndentText, $row)); + } + + /** + * Creates wrapper-closure for the example header. + * + * @return callable + */ + private function getWrapperClosure() + { + $style = $this->resultConverter->convertResultCodeToString(TestResult::SKIPPED); + + return function ($col) use ($style) { + return sprintf('{+%s_param}%s{-%s_param}', $style, $col, $style); + }; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyOutlineTablePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyOutlineTablePrinter.php new file mode 100644 index 0000000..ea0298e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyOutlineTablePrinter.php @@ -0,0 +1,145 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Behat\Output\Node\Printer\OutlineTablePrinter; +use Behat\Behat\Output\Node\Printer\ScenarioPrinter; +use Behat\Behat\Output\Node\Printer\StepPrinter; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\ExampleTableNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints outline table header and footer. + * + * @author Konstantin Kudryashov + */ +final class PrettyOutlineTablePrinter implements OutlineTablePrinter +{ + /** + * @var ScenarioPrinter + */ + private $scenarioPrinter; + /** + * @var StepPrinter + */ + private $stepPrinter; + /** + * @var ResultToStringConverter + */ + private $resultConverter; + /** + * @var string + */ + private $indentText; + /** + * @var string + */ + private $subIndentText; + + /** + * Initializes printer. + * + * @param ScenarioPrinter $scenarioPrinter + * @param StepPrinter $stepPrinter + * @param ResultToStringConverter $resultConverter + * @param integer $indentation + * @param integer $subIndentation + */ + public function __construct( + ScenarioPrinter $scenarioPrinter, + StepPrinter $stepPrinter, + ResultToStringConverter $resultConverter, + $indentation = 4, + $subIndentation = 2 + ) { + $this->scenarioPrinter = $scenarioPrinter; + $this->stepPrinter = $stepPrinter; + $this->resultConverter = $resultConverter; + $this->indentText = str_repeat(' ', intval($indentation)); + $this->subIndentText = $this->indentText . str_repeat(' ', intval($subIndentation)); + } + + /** + * {@inheritdoc} + */ + public function printHeader(Formatter $formatter, FeatureNode $feature, OutlineNode $outline, array $results) + { + $this->scenarioPrinter->printHeader($formatter, $feature, $outline); + + $this->printExamplesSteps($formatter, $outline, $outline->getSteps(), $results); + $this->printExamplesTableHeader($formatter->getOutputPrinter(), $outline->getExampleTable()); + } + + /** + * {@inheritdoc} + */ + public function printFooter(Formatter $formatter, TestResult $result) + { + $formatter->getOutputPrinter()->writeln(); + } + + /** + * Prints example steps with definition paths (if has some), but without exceptions or state (skipped). + * + * @param Formatter $formatter + * @param OutlineNode $outline + * @param StepNode[] $steps + * @param StepResult[] $results + */ + private function printExamplesSteps(Formatter $formatter, OutlineNode $outline, array $steps, array $results) + { + foreach ($steps as $step) { + $result = $results[$step->getLine()]; + + $this->stepPrinter->printStep($formatter, $outline, $step, $result); + } + + $formatter->getOutputPrinter()->writeln(); + } + + /** + * Prints examples table header. + * + * @param OutputPrinter $printer + * @param ExampleTableNode $table + */ + private function printExamplesTableHeader(OutputPrinter $printer, ExampleTableNode $table) + { + $printer->writeln(sprintf('%s{+keyword}%s:{-keyword}', $this->indentText, $table->getKeyword())); + + $rowNum = 0; + $wrapper = $this->getWrapperClosure(); + $row = $table->getRowAsStringWithWrappedValues($rowNum, $wrapper); + + $printer->writeln(sprintf('%s%s', $this->subIndentText, $row)); + } + + /** + * Creates wrapper-closure for the example header. + * + * @return callable + */ + private function getWrapperClosure() + { + $style = $this->resultConverter->convertResultCodeToString(TestResult::SKIPPED); + + return function ($col) use ($style) { + return sprintf('{+%s_param}%s{-%s_param}', $style, $col, $style); + }; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyPathPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyPathPrinter.php new file mode 100644 index 0000000..9ea0b68 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyPathPrinter.php @@ -0,0 +1,137 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\Helper\WidthCalculator; +use Behat\Behat\Tester\Result\DefinedStepResult; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; + +/** + * Prints paths for scenarios, examples, backgrounds and steps. + * + * @author Konstantin Kudryashov + */ +final class PrettyPathPrinter +{ + /** + * @var WidthCalculator + */ + private $widthCalculator; + /** + * @var string + */ + private $basePath; + + /** + * Initializes printer. + * + * @param WidthCalculator $widthCalculator + * @param string $basePath + */ + public function __construct(WidthCalculator $widthCalculator, $basePath) + { + $this->widthCalculator = $widthCalculator; + $this->basePath = $basePath; + } + + /** + * Prints scenario path comment. + * + * @param Formatter $formatter + * @param FeatureNode $feature + * @param Scenario $scenario + * @param integer $indentation + */ + public function printScenarioPath(Formatter $formatter, FeatureNode $feature, Scenario $scenario, $indentation) + { + $printer = $formatter->getOutputPrinter(); + + if (!$formatter->getParameter('paths')) { + $printer->writeln(); + + return; + } + + $fileAndLine = sprintf('%s:%s', $this->relativizePaths($feature->getFile()), $scenario->getLine()); + $headerWidth = $this->widthCalculator->calculateScenarioHeaderWidth($scenario, $indentation); + $scenarioWidth = $this->widthCalculator->calculateScenarioWidth($scenario, $indentation, 2); + $spacing = str_repeat(' ', max(0, $scenarioWidth - $headerWidth)); + + $printer->writeln(sprintf('%s {+comment}# %s{-comment}', $spacing, $fileAndLine)); + } + + /** + * Prints step path comment. + * + * @param Formatter $formatter + * @param Scenario $scenario + * @param StepNode $step + * @param StepResult $result + * @param integer $indentation + */ + public function printStepPath( + Formatter $formatter, + Scenario $scenario, + StepNode $step, + StepResult $result, + $indentation + ) { + $printer = $formatter->getOutputPrinter(); + + if (!$result instanceof DefinedStepResult || !$result->getStepDefinition() || !$formatter->getParameter('paths')) { + $printer->writeln(); + + return; + } + + $textWidth = $this->widthCalculator->calculateStepWidth($step, $indentation); + $scenarioWidth = $this->widthCalculator->calculateScenarioWidth($scenario, $indentation - 2, 2); + + $this->printDefinedStepPath($printer, $result, $scenarioWidth, $textWidth); + } + + /** + * Prints defined step path. + * + * @param OutputPrinter $printer + * @param DefinedStepResult $result + * @param integer $scenarioWidth + * @param integer $stepWidth + */ + private function printDefinedStepPath(OutputPrinter $printer, DefinedStepResult $result, $scenarioWidth, $stepWidth) + { + $path = $result->getStepDefinition()->getPath(); + $spacing = str_repeat(' ', max(0, $scenarioWidth - $stepWidth)); + + $printer->writeln(sprintf('%s {+comment}# %s{-comment}', $spacing, $path)); + } + + /** + * Transforms path to relative. + * + * @param string $path + * + * @return string + */ + private function relativizePaths($path) + { + if (!$this->basePath) { + return $path; + } + + return str_replace($this->basePath . DIRECTORY_SEPARATOR, '', $path); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyScenarioPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyScenarioPrinter.php new file mode 100644 index 0000000..378a991 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyScenarioPrinter.php @@ -0,0 +1,148 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\ScenarioPrinter; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\TaggedNodeInterface; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints scenario headers (with tags, keyword and long title) and footers. + * + * @author Konstantin Kudryashov + */ +final class PrettyScenarioPrinter implements ScenarioPrinter +{ + /** + * @var PrettyPathPrinter + */ + private $pathPrinter; + /** + * @var string + */ + private $indentText; + /** + * @var string + */ + private $subIndentText; + + /** + * Initializes printer. + * + * @param PrettyPathPrinter $pathPrinter + * @param integer $indentation + * @param integer $subIndentation + */ + public function __construct(PrettyPathPrinter $pathPrinter, $indentation = 2, $subIndentation = 2) + { + $this->pathPrinter = $pathPrinter; + $this->indentText = str_repeat(' ', intval($indentation)); + $this->subIndentText = $this->indentText . str_repeat(' ', intval($subIndentation)); + } + + /** + * {@inheritdoc} + */ + public function printHeader(Formatter $formatter, FeatureNode $feature, Scenario $scenario) + { + if ($scenario instanceof TaggedNodeInterface) { + $this->printTags($formatter->getOutputPrinter(), $scenario->getTags()); + } + + $this->printKeyword($formatter->getOutputPrinter(), $scenario->getKeyword()); + $this->printTitle($formatter->getOutputPrinter(), $scenario->getTitle()); + $this->pathPrinter->printScenarioPath($formatter, $feature, $scenario, mb_strlen($this->indentText, 'utf8')); + $this->printDescription($formatter->getOutputPrinter(), $scenario->getTitle()); + } + + /** + * {@inheritdoc} + */ + public function printFooter(Formatter $formatter, TestResult $result) + { + $formatter->getOutputPrinter()->writeln(); + } + + /** + * Prints scenario tags. + * + * @param OutputPrinter $printer + * @param string[] $tags + */ + private function printTags(OutputPrinter $printer, array $tags) + { + if (!count($tags)) { + return; + } + + $tags = array_map(array($this, 'prependTagWithTagSign'), $tags); + $printer->writeln(sprintf('%s{+tag}%s{-tag}', $this->indentText, implode(' ', $tags))); + } + + /** + * Prints scenario keyword. + * + * @param OutputPrinter $printer + * @param string $keyword + */ + private function printKeyword(OutputPrinter $printer, $keyword) + { + $printer->write(sprintf('%s{+keyword}%s:{-keyword}', $this->indentText, $keyword)); + } + + /** + * Prints scenario title (first line of long title). + * + * @param OutputPrinter $printer + * @param string $longTitle + */ + private function printTitle(OutputPrinter $printer, $longTitle) + { + $description = explode("\n", $longTitle); + $title = array_shift($description); + + if ('' !== $title) { + $printer->write(sprintf(' %s', $title)); + } + } + + /** + * Prints scenario description (other lines of long title). + * + * @param OutputPrinter $printer + * @param string $longTitle + */ + private function printDescription(OutputPrinter $printer, $longTitle) + { + $lines = explode("\n", $longTitle); + array_shift($lines); + + foreach ($lines as $line) { + $printer->writeln(sprintf('%s%s', $this->subIndentText, $line)); + } + } + + /** + * Prepends tags string with tag-sign. + * + * @param string $tag + * + * @return string + */ + private function prependTagWithTagSign($tag) + { + return '@' . $tag; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettySetupPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettySetupPrinter.php new file mode 100644 index 0000000..46bcba3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettySetupPrinter.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Behat\Output\Node\Printer\SetupPrinter; +use Behat\Testwork\Call\CallResult; +use Behat\Testwork\Exception\ExceptionPresenter; +use Behat\Testwork\Hook\Tester\Setup\HookedSetup; +use Behat\Testwork\Hook\Tester\Setup\HookedTeardown; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Prints hooks in a pretty fashion. + * + * @author Konstantin Kudryashov + */ +final class PrettySetupPrinter implements SetupPrinter +{ + /** + * @var ResultToStringConverter + */ + private $resultConverter; + /** + * @var ExceptionPresenter + */ + private $exceptionPresenter; + /** + * @var string + */ + private $indentText; + /** + * @var bool + */ + private $newlineBefore; + /** + * @var bool + */ + private $newlineAfter; + + /** + * Initializes printer. + * + * @param ResultToStringConverter $resultConverter + * @param ExceptionPresenter $exceptionPresenter + * @param integer $indentation + * @param Boolean $newlineBefore + * @param Boolean $newlineAfter + */ + public function __construct( + ResultToStringConverter $resultConverter, + ExceptionPresenter $exceptionPresenter, + $indentation = 0, + $newlineBefore = false, + $newlineAfter = false + ) { + $this->resultConverter = $resultConverter; + $this->exceptionPresenter = $exceptionPresenter; + $this->indentText = str_repeat(' ', intval($indentation)); + $this->newlineBefore = $newlineBefore; + $this->newlineAfter = $newlineAfter; + } + + /** + * {@inheritdoc} + */ + public function printSetup(Formatter $formatter, Setup $setup) + { + if (!$setup instanceof HookedSetup) { + return; + } + + foreach ($setup->getHookCallResults() as $callResult) { + $this->printSetupHookCallResult($formatter->getOutputPrinter(), $callResult); + } + } + + /** + * {@inheritdoc} + */ + public function printTeardown(Formatter $formatter, Teardown $teardown) + { + if (!$teardown instanceof HookedTeardown) { + return; + } + + foreach ($teardown->getHookCallResults() as $callResult) { + $this->printTeardownHookCallResult($formatter->getOutputPrinter(), $callResult); + } + } + + /** + * Prints setup hook call result. + * + * @param OutputPrinter $printer + * @param CallResult $callResult + */ + private function printSetupHookCallResult(OutputPrinter $printer, CallResult $callResult) + { + if (!$callResult->hasStdOut() && !$callResult->hasException()) { + return; + } + + $resultCode = $callResult->hasException() ? TestResult::FAILED : TestResult::PASSED; + $style = $this->resultConverter->convertResultCodeToString($resultCode); + $hook = $callResult->getCall()->getCallee(); + $path = $hook->getPath(); + + $printer->writeln( + sprintf('%s┌─ {+%s}@%s{-%s} {+comment}# %s{-comment}', $this->indentText, $style, $hook, $style, $path) + ); + + $printer->writeln(sprintf('%s│', $this->indentText)); + + $this->printHookCallStdOut($printer, $callResult, $this->indentText); + $this->printHookCallException($printer, $callResult, $this->indentText); + + if ($this->newlineBefore) { + $printer->writeln(); + } + } + + /** + * Prints teardown hook call result. + * + * @param OutputPrinter $printer + * @param CallResult $callResult + */ + private function printTeardownHookCallResult(OutputPrinter $printer, CallResult $callResult) + { + if (!$callResult->hasStdOut() && !$callResult->hasException()) { + return; + } + + $resultCode = $callResult->hasException() ? TestResult::FAILED : TestResult::PASSED; + $style = $this->resultConverter->convertResultCodeToString($resultCode); + $hook = $callResult->getCall()->getCallee(); + $path = $hook->getPath(); + + $printer->writeln(sprintf('%s│', $this->indentText)); + + $this->printHookCallStdOut($printer, $callResult, $this->indentText); + $this->printHookCallException($printer, $callResult, $this->indentText); + + $printer->writeln( + sprintf('%s└─ {+%s}@%s{-%s} {+comment}# %s{-comment}', $this->indentText, $style, $hook, $style, $path) + ); + + if ($this->newlineAfter) { + $printer->writeln(); + } + } + + /** + * Prints hook call output (if has some). + * + * @param OutputPrinter $printer + * @param CallResult $callResult + * @param string $indentText + */ + private function printHookCallStdOut(OutputPrinter $printer, CallResult $callResult, $indentText) + { + if (!$callResult->hasStdOut()) { + return; + } + + $pad = function ($line) use ($indentText) { + return sprintf( + '%s│ {+stdout}%s{-stdout}', $indentText, $line + ); + }; + + $printer->writeln(implode("\n", array_map($pad, explode("\n", $callResult->getStdOut())))); + $printer->writeln(sprintf('%s│', $indentText)); + } + + /** + * Prints hook call exception (if has some). + * + * @param OutputPrinter $printer + * @param CallResult $callResult + * @param string $indentText + */ + private function printHookCallException(OutputPrinter $printer, CallResult $callResult, $indentText) + { + if (!$callResult->hasException()) { + return; + } + + $pad = function ($l) use ($indentText) { + return sprintf( + '%s╳ {+exception}%s{-exception}', $indentText, $l + ); + }; + + $exception = $this->exceptionPresenter->presentException($callResult->getException()); + $printer->writeln(implode("\n", array_map($pad, explode("\n", $exception)))); + $printer->writeln(sprintf('%s│', $indentText)); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettySkippedStepPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettySkippedStepPrinter.php new file mode 100644 index 0000000..718afd3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettySkippedStepPrinter.php @@ -0,0 +1,162 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Behat\Output\Node\Printer\Helper\StepTextPainter; +use Behat\Behat\Output\Node\Printer\StepPrinter; +use Behat\Behat\Tester\Result\DefinedStepResult; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\ArgumentInterface; +use Behat\Gherkin\Node\PyStringNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\IntegerTestResult; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints steps as skipped. + * + * @author Konstantin Kudryashov + */ +final class PrettySkippedStepPrinter implements StepPrinter +{ + /** + * @var StepTextPainter + */ + private $textPainter; + /** + * @var ResultToStringConverter + */ + private $resultConverter; + /** + * @var PrettyPathPrinter + */ + private $pathPrinter; + /** + * @var string + */ + private $indentText; + /** + * @var string + */ + private $subIndentText; + + /** + * Initializes printer. + * + * @param StepTextPainter $textPainter + * @param ResultToStringConverter $resultConverter + * @param PrettyPathPrinter $pathPrinter + * @param integer $indentation + * @param integer $subIndentation + */ + public function __construct( + StepTextPainter $textPainter, + ResultToStringConverter $resultConverter, + PrettyPathPrinter $pathPrinter, + $indentation = 4, + $subIndentation = 2 + ) { + $this->textPainter = $textPainter; + $this->resultConverter = $resultConverter; + $this->pathPrinter = $pathPrinter; + $this->indentText = str_repeat(' ', intval($indentation)); + $this->subIndentText = $this->indentText . str_repeat(' ', intval($subIndentation)); + } + + /** + * {@inheritdoc} + */ + public function printStep(Formatter $formatter, Scenario $scenario, StepNode $step, StepResult $result) + { + $this->printText($formatter->getOutputPrinter(), $step->getKeyword(), $step->getText(), $result); + $this->pathPrinter->printStepPath($formatter, $scenario, $step, $result, mb_strlen($this->indentText, 'utf8')); + $this->printArguments($formatter, $step->getArguments()); + } + + /** + * Prints step text. + * + * @param OutputPrinter $printer + * @param string $stepType + * @param string $stepText + * @param StepResult $result + */ + private function printText(OutputPrinter $printer, $stepType, $stepText, StepResult $result) + { + $style = $this->resultConverter->convertResultCodeToString(TestResult::SKIPPED); + + if ($result instanceof DefinedStepResult && $result->getStepDefinition()) { + $definition = $result->getStepDefinition(); + $stepText = $this->textPainter->paintText( + $stepText, $definition, new IntegerTestResult(TestResult::SKIPPED) + ); + } + + $printer->write(sprintf('%s{+%s}%s %s{-%s}', $this->indentText, $style, $stepType, $stepText, $style)); + } + + /** + * Prints step multiline arguments. + * + * @param Formatter $formatter + * @param ArgumentInterface[] $arguments + */ + private function printArguments(Formatter $formatter, array $arguments) + { + $style = $this->resultConverter->convertResultCodeToString(TestResult::SKIPPED); + + foreach ($arguments as $argument) { + $text = $this->getArgumentString($argument, !$formatter->getParameter('multiline')); + + $indentedText = implode("\n", array_map(array($this, 'subIndent'), explode("\n", $text))); + $formatter->getOutputPrinter()->writeln(sprintf('{+%s}%s{-%s}', $style, $indentedText, $style)); + } + } + + /** + * Returns argument string for provided argument. + * + * @param ArgumentInterface $argument + * @param Boolean $collapse + * + * @return string + */ + private function getArgumentString(ArgumentInterface $argument, $collapse = false) + { + if ($collapse) { + return '...'; + } + + if ($argument instanceof PyStringNode) { + $text = '"""' . "\n" . $argument . "\n" . '"""'; + + return $text; + } + + return (string) $argument; + } + + /** + * Indents text to the subIndentation level. + * + * @param string $text + * + * @return string + */ + private function subIndent($text) + { + return $this->subIndentText . $text; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStatisticsPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStatisticsPrinter.php new file mode 100644 index 0000000..23702c7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStatisticsPrinter.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\CounterPrinter; +use Behat\Behat\Output\Node\Printer\ListPrinter; +use Behat\Behat\Output\Node\Printer\StatisticsPrinter; +use Behat\Behat\Output\Statistics\Statistics; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints exercise statistics. + * + * @author Konstantin Kudryashov + */ +final class PrettyStatisticsPrinter implements StatisticsPrinter +{ + /** + * @var CounterPrinter + */ + private $counterPrinter; + /** + * @var ListPrinter + */ + private $listPrinter; + + /** + * Initializes printer. + * + * @param CounterPrinter $counterPrinter + * @param ListPrinter $listPrinter + */ + public function __construct(CounterPrinter $counterPrinter, ListPrinter $listPrinter) + { + $this->counterPrinter = $counterPrinter; + $this->listPrinter = $listPrinter; + } + + /** + * {@inheritdoc} + */ + public function printStatistics(Formatter $formatter, Statistics $statistics) + { + $printer = $formatter->getOutputPrinter(); + + $scenarioStats = $statistics->getSkippedScenarios(); + $this->listPrinter->printScenariosList($printer, 'skipped_scenarios_title', TestResult::SKIPPED, $scenarioStats); + + $scenarioStats = $statistics->getFailedScenarios(); + $this->listPrinter->printScenariosList($printer, 'failed_scenarios_title', TestResult::FAILED, $scenarioStats); + + $this->counterPrinter->printCounters($printer, 'scenarios_count', $statistics->getScenarioStatCounts()); + $this->counterPrinter->printCounters($printer, 'steps_count', $statistics->getStepStatCounts()); + + if ($formatter->getParameter('timer')) { + $timer = $statistics->getTimer(); + $memory = $statistics->getMemory(); + + $formatter->getOutputPrinter()->writeln(sprintf('%s (%s)', $timer, $memory)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStepPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStepPrinter.php new file mode 100644 index 0000000..8d47da1 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Pretty/PrettyStepPrinter.php @@ -0,0 +1,213 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Pretty; + +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Behat\Output\Node\Printer\Helper\StepTextPainter; +use Behat\Behat\Output\Node\Printer\StepPrinter; +use Behat\Behat\Tester\Result\DefinedStepResult; +use Behat\Behat\Tester\Result\ExecutedStepResult; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\ArgumentInterface; +use Behat\Gherkin\Node\PyStringNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Exception\ExceptionPresenter; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\Tester\Result\ExceptionResult; + +/** + * Prints step. + * + * @author Konstantin Kudryashov + */ +final class PrettyStepPrinter implements StepPrinter +{ + /** + * @var StepTextPainter + */ + private $textPainter; + /** + * @var ResultToStringConverter + */ + private $resultConverter; + /** + * @var PrettyPathPrinter + */ + private $pathPrinter; + /** + * @var ExceptionPresenter + */ + private $exceptionPresenter; + /** + * @var string + */ + private $indentText; + /** + * @var string + */ + private $subIndentText; + + /** + * Initializes printer. + * + * @param StepTextPainter $textPainter + * @param ResultToStringConverter $resultConverter + * @param PrettyPathPrinter $pathPrinter + * @param ExceptionPresenter $exceptionPresenter + * @param integer $indentation + * @param integer $subIndentation + */ + public function __construct( + StepTextPainter $textPainter, + ResultToStringConverter $resultConverter, + PrettyPathPrinter $pathPrinter, + ExceptionPresenter $exceptionPresenter, + $indentation = 4, + $subIndentation = 2 + ) { + $this->textPainter = $textPainter; + $this->resultConverter = $resultConverter; + $this->pathPrinter = $pathPrinter; + $this->exceptionPresenter = $exceptionPresenter; + $this->indentText = str_repeat(' ', intval($indentation)); + $this->subIndentText = $this->indentText . str_repeat(' ', intval($subIndentation)); + } + + /** + * {@inheritdoc} + */ + public function printStep(Formatter $formatter, Scenario $scenario, StepNode $step, StepResult $result) + { + $this->printText($formatter->getOutputPrinter(), $step->getKeyword(), $step->getText(), $result); + $this->pathPrinter->printStepPath($formatter, $scenario, $step, $result, mb_strlen($this->indentText, 'utf8')); + $this->printArguments($formatter, $step->getArguments(), $result); + $this->printStdOut($formatter->getOutputPrinter(), $result); + $this->printException($formatter->getOutputPrinter(), $result); + } + + /** + * Prints step text. + * + * @param OutputPrinter $printer + * @param string $stepType + * @param string $stepText + * @param StepResult $result + */ + private function printText(OutputPrinter $printer, $stepType, $stepText, StepResult $result) + { + if ($result && $result instanceof DefinedStepResult && $result->getStepDefinition()) { + $definition = $result->getStepDefinition(); + $stepText = $this->textPainter->paintText($stepText, $definition, $result); + } + + $style = $this->resultConverter->convertResultToString($result); + $printer->write(sprintf('%s{+%s}%s %s{-%s}', $this->indentText, $style, $stepType, $stepText, $style)); + } + + /** + * Prints step multiline arguments. + * + * @param Formatter $formatter + * @param ArgumentInterface[] $arguments + * @param StepResult $result + */ + private function printArguments(Formatter $formatter, array $arguments, StepResult $result) + { + $style = $this->resultConverter->convertResultToString($result); + + foreach ($arguments as $argument) { + $text = $this->getArgumentString($argument, !$formatter->getParameter('multiline')); + + $indentedText = implode("\n", array_map(array($this, 'subIndent'), explode("\n", $text))); + $formatter->getOutputPrinter()->writeln(sprintf('{+%s}%s{-%s}', $style, $indentedText, $style)); + } + } + + /** + * Prints step output (if has one). + * + * @param OutputPrinter $printer + * @param StepResult $result + */ + private function printStdOut(OutputPrinter $printer, StepResult $result) + { + if (!$result instanceof ExecutedStepResult || null === $result->getCallResult()->getStdOut()) { + return; + } + + $callResult = $result->getCallResult(); + $indentedText = $this->subIndentText; + + $pad = function ($line) use ($indentedText) { + return sprintf( + '%s│ {+stdout}%s{-stdout}', $indentedText, $line + ); + }; + + $printer->writeln(implode("\n", array_map($pad, explode("\n", $callResult->getStdOut())))); + } + + /** + * Prints step exception (if has one). + * + * @param OutputPrinter $printer + * @param StepResult $result + */ + private function printException(OutputPrinter $printer, StepResult $result) + { + $style = $this->resultConverter->convertResultToString($result); + + if (!$result instanceof ExceptionResult || !$result->hasException()) { + return; + } + + $text = $this->exceptionPresenter->presentException($result->getException()); + $indentedText = implode("\n", array_map(array($this, 'subIndent'), explode("\n", $text))); + $printer->writeln(sprintf('{+%s}%s{-%s}', $style, $indentedText, $style)); + } + + /** + * Returns argument string for provided argument. + * + * @param ArgumentInterface $argument + * @param Boolean $collapse + * + * @return string + */ + private function getArgumentString(ArgumentInterface $argument, $collapse = false) + { + if ($collapse) { + return '...'; + } + + if ($argument instanceof PyStringNode) { + $text = '"""' . "\n" . $argument . "\n" . '"""'; + + return $text; + } + + return (string) $argument; + } + + /** + * Indents text to the subIndentation level. + * + * @param string $text + * + * @return string + */ + private function subIndent($text) + { + return $this->subIndentText . $text; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Progress/ProgressStatisticsPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Progress/ProgressStatisticsPrinter.php new file mode 100644 index 0000000..a104178 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Progress/ProgressStatisticsPrinter.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Progress; + +use Behat\Behat\Output\Node\Printer\CounterPrinter; +use Behat\Behat\Output\Node\Printer\ListPrinter; +use Behat\Behat\Output\Node\Printer\StatisticsPrinter; +use Behat\Behat\Output\Statistics\Statistics; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Behat progress statistics printer. + * + * @author Konstantin Kudryashov + */ +final class ProgressStatisticsPrinter implements StatisticsPrinter +{ + /** + * @var CounterPrinter + */ + private $counterPrinter; + /** + * @var ListPrinter + */ + private $listPrinter; + + /** + * Initializes printer. + * + * @param CounterPrinter $counterPrinter + * @param ListPrinter $listPrinter + */ + public function __construct(CounterPrinter $counterPrinter, ListPrinter $listPrinter) + { + $this->counterPrinter = $counterPrinter; + $this->listPrinter = $listPrinter; + } + + /** + * {@inheritdoc} + */ + public function printStatistics(Formatter $formatter, Statistics $statistics) + { + $printer = $formatter->getOutputPrinter(); + + $printer->writeln(); + $printer->writeln(); + + $hookStats = $statistics->getFailedHookStats(); + $this->listPrinter->printFailedHooksList($printer, 'failed_hooks_title', $hookStats); + + $stepStats = $statistics->getFailedSteps(); + $this->listPrinter->printStepList($printer, 'failed_steps_title', TestResult::FAILED, $stepStats); + + $stepStats = $statistics->getPendingSteps(); + $this->listPrinter->printStepList($printer, 'pending_steps_title', TestResult::PENDING, $stepStats); + + $this->counterPrinter->printCounters($printer, 'scenarios_count', $statistics->getScenarioStatCounts()); + $this->counterPrinter->printCounters($printer, 'steps_count', $statistics->getStepStatCounts()); + + if ($formatter->getParameter('timer')) { + $timer = $statistics->getTimer(); + $memory = $statistics->getMemory(); + + $formatter->getOutputPrinter()->writeln(sprintf('%s (%s)', $timer, $memory)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Progress/ProgressStepPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Progress/ProgressStepPrinter.php new file mode 100644 index 0000000..ca1656f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/Progress/ProgressStepPrinter.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer\Progress; + +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Behat\Output\Node\Printer\StepPrinter; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Behat progress step printer. + * + * @author Konstantin Kudryashov + */ +final class ProgressStepPrinter implements StepPrinter +{ + /** + * @var ResultToStringConverter + */ + private $resultConverter; + /** + * @var integer + */ + private $stepsPrinted = 0; + + /** + * Initializes printer. + * + * @param ResultToStringConverter $resultConverter + */ + public function __construct(ResultToStringConverter $resultConverter) + { + $this->resultConverter = $resultConverter; + } + + /** + * {@inheritdoc} + */ + public function printStep(Formatter $formatter, Scenario $scenario, StepNode $step, StepResult $result) + { + $printer = $formatter->getOutputPrinter(); + $style = $this->resultConverter->convertResultToString($result); + + switch ($result->getResultCode()) { + case TestResult::PASSED: + $printer->write("{+$style}.{-$style}"); + break; + case TestResult::SKIPPED: + $printer->write("{+$style}-{-$style}"); + break; + case TestResult::PENDING: + $printer->write("{+$style}P{-$style}"); + break; + case StepResult::UNDEFINED: + $printer->write("{+$style}U{-$style}"); + break; + case TestResult::FAILED: + $printer->write("{+$style}F{-$style}"); + break; + } + + if (++$this->stepsPrinted % 70 == 0) { + $printer->writeln(' ' . $this->stepsPrinted); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ScenarioPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ScenarioPrinter.php new file mode 100644 index 0000000..0260c41 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ScenarioPrinter.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints scenario headers and footers. + * + * @author Konstantin Kudryashov + */ +interface ScenarioPrinter +{ + /** + * Prints scenario header using provided printer. + * + * @param Formatter $formatter + * @param FeatureNode $feature + * @param Scenario $scenario + */ + public function printHeader(Formatter $formatter, FeatureNode $feature, Scenario $scenario); + + /** + * Prints scenario footer using provided printer. + * + * @param Formatter $formatter + * @param TestResult $result + */ + public function printFooter(Formatter $formatter, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/SetupPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/SetupPrinter.php new file mode 100644 index 0000000..5a06527 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/SetupPrinter.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Behat setup printer interface. + * + * @author Konstantin Kudryashov + */ +interface SetupPrinter +{ + /** + * Prints setup state. + * + * @param Formatter $formatter + * @param Setup $setup + */ + public function printSetup(Formatter $formatter, Setup $setup); + + /** + * Prints teardown state. + * + * @param Formatter $formatter + * @param Teardown $teardown + */ + public function printTeardown(Formatter $formatter, Teardown $teardown); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/StatisticsPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/StatisticsPrinter.php new file mode 100644 index 0000000..7999a20 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/StatisticsPrinter.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Behat\Output\Statistics\Statistics; +use Behat\Testwork\Output\Formatter; + +/** + * Prints exercise statistics. + * + * @author Konstantin Kudryashov + */ +interface StatisticsPrinter +{ + /** + * Prints test suite statistics after run. + * + * @param Formatter $formatter + * @param Statistics $statistics + */ + public function printStatistics(Formatter $formatter, Statistics $statistics); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/StepPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/StepPrinter.php new file mode 100644 index 0000000..7b03c4b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/StepPrinter.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Node\Printer; + +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\ScenarioLikeInterface as Scenario; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Output\Formatter; + +/** + * Prints step with optional results. + * + * @author Konstantin Kudryashov + */ +interface StepPrinter +{ + /** + * Prints step using provided printer. + * + * @param Formatter $formatter + * @param Scenario $scenario + * @param StepNode $step + * @param StepResult $result + */ + public function printStep(Formatter $formatter, Scenario $scenario, StepNode $step, StepResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Printer/ConsoleOutputPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Printer/ConsoleOutputPrinter.php new file mode 100644 index 0000000..53b7fc8 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Printer/ConsoleOutputPrinter.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Printer; + +use Behat\Behat\Output\Printer\Formatter\ConsoleFormatter; +use Behat\Testwork\Output\Printer\ConsoleOutputPrinter as BasePrinter; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; + +/** + * Extends default printer with default styles. + * + * @author Konstantin Kudryashov + */ +final class ConsoleOutputPrinter extends BasePrinter +{ + /** + * Creates output formatter that is used to create a console. + * + * @return ConsoleFormatter + */ + protected function createOutputFormatter() + { + $formatter = new ConsoleFormatter($this->isOutputDecorated()); + + foreach ($this->getDefaultStyles() as $name => $style) { + $formatter->setStyle($name, $style); + } + + return $formatter; + } + + /** + * Returns default styles. + * + * @return OutputFormatterStyle[string] + */ + private function getDefaultStyles() + { + return array( + 'keyword' => new OutputFormatterStyle(null, null, array('bold')), + 'stdout' => new OutputFormatterStyle(null, null, array()), + 'exception' => new OutputFormatterStyle('red'), + 'undefined' => new OutputFormatterStyle('yellow'), + 'pending' => new OutputFormatterStyle('yellow'), + 'pending_param' => new OutputFormatterStyle('yellow', null, array('bold')), + 'failed' => new OutputFormatterStyle('red'), + 'failed_param' => new OutputFormatterStyle('red', null, array('bold')), + 'passed' => new OutputFormatterStyle('green'), + 'passed_param' => new OutputFormatterStyle('green', null, array('bold')), + 'skipped' => new OutputFormatterStyle('cyan'), + 'skipped_param' => new OutputFormatterStyle('cyan', null, array('bold')), + 'comment' => new OutputFormatterStyle('black'), + 'tag' => new OutputFormatterStyle('cyan') + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Printer/Formatter/ConsoleFormatter.php b/vendor/behat/behat/src/Behat/Behat/Output/Printer/Formatter/ConsoleFormatter.php new file mode 100644 index 0000000..9b403a6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Printer/Formatter/ConsoleFormatter.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Printer\Formatter; + +use Symfony\Component\Console\Formatter\OutputFormatter as BaseOutputFormatter; + +/** + * Symfony2 Console output formatter extended with custom highlighting tokens support. + * + * @author Konstantin Kudryashov + */ +final class ConsoleFormatter extends BaseOutputFormatter +{ + const CUSTOM_PATTERN = '/{\+([a-z-_]+)}(.*?){\-\\1}/si'; + + /** + * Formats a message according to the given styles. + * + * @param string $message The message to style + * + * @return string The styled message + */ + public function format($message) + { + return preg_replace_callback(self::CUSTOM_PATTERN, array($this, 'replaceStyle'), $message); + } + + /** + * Replaces style of the output. + * + * @param array $match + * + * @return string The replaced style + */ + private function replaceStyle($match) + { + if (!$this->isDecorated()) { + return $match[2]; + } + + if ($this->hasStyle($match[1])) { + $style = $this->getStyle($match[1]); + } else { + return $match[0]; + } + + return $style->apply($match[2]); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/PrettyFormatterFactory.php b/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/PrettyFormatterFactory.php new file mode 100644 index 0000000..2a6d77e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/PrettyFormatterFactory.php @@ -0,0 +1,467 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\ServiceContainer\Formatter; + +use Behat\Behat\Definition\ServiceContainer\DefinitionExtension; +use Behat\Behat\EventDispatcher\Event\BackgroundTested; +use Behat\Behat\EventDispatcher\Event\OutlineTested; +use Behat\Behat\EventDispatcher\Event\ScenarioTested; +use Behat\Testwork\Exception\ServiceContainer\ExceptionExtension; +use Behat\Testwork\Output\ServiceContainer\Formatter\FormatterFactory; +use Behat\Testwork\Output\ServiceContainer\OutputExtension; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Behat pretty formatter factory. + * + * @author Konstantin Kudryashov + */ +class PrettyFormatterFactory implements FormatterFactory +{ + /** + * @var ServiceProcessor + */ + private $processor; + + /* + * Available services + */ + const ROOT_LISTENER_ID = 'output.node.listener.pretty'; + const RESULT_TO_STRING_CONVERTER_ID = 'output.node.printer.result_to_string'; + + /* + * Available extension points + */ + const ROOT_LISTENER_WRAPPER_TAG = 'output.node.listener.pretty.wrapper'; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function buildFormatter(ContainerBuilder $container) + { + $this->loadRootNodeListener($container); + + $this->loadCorePrinters($container); + $this->loadTableOutlinePrinter($container); + $this->loadExpandedOutlinePrinter($container); + $this->loadHookPrinters($container); + $this->loadStatisticsPrinter($container); + $this->loadPrinterHelpers($container); + + $this->loadFormatter($container); + } + + /** + * {@inheritdoc} + */ + public function processFormatter(ContainerBuilder $container) + { + $this->processListenerWrappers($container); + } + + /** + * Loads pretty formatter node event listener. + * + * @param ContainerBuilder $container + */ + protected function loadRootNodeListener(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Output\Node\EventListener\ChainEventListener', array( + array( + new Definition('Behat\Behat\Output\Node\EventListener\AST\SuiteListener', array( + new Reference('output.node.printer.pretty.suite_setup') + )), + new Definition('Behat\Behat\Output\Node\EventListener\AST\FeatureListener', array( + new Reference('output.node.printer.pretty.feature'), + new Reference('output.node.printer.pretty.feature_setup') + )), + $this->proxySiblingEvents( + BackgroundTested::BEFORE, + BackgroundTested::AFTER, + array( + new Definition('Behat\Behat\Output\Node\EventListener\AST\ScenarioNodeListener', array( + BackgroundTested::AFTER_SETUP, + BackgroundTested::AFTER, + new Reference('output.node.printer.pretty.scenario') + )), + new Definition('Behat\Behat\Output\Node\EventListener\AST\StepListener', array( + new Reference('output.node.printer.pretty.step'), + new Reference('output.node.printer.pretty.step_setup') + )), + ) + ), + $this->proxySiblingEvents( + ScenarioTested::BEFORE, + ScenarioTested::AFTER, + array( + new Definition('Behat\Behat\Output\Node\EventListener\AST\ScenarioNodeListener', array( + ScenarioTested::AFTER_SETUP, + ScenarioTested::AFTER, + new Reference('output.node.printer.pretty.scenario'), + new Reference('output.node.printer.pretty.scenario_setup') + )), + new Definition('Behat\Behat\Output\Node\EventListener\AST\StepListener', array( + new Reference('output.node.printer.pretty.step'), + new Reference('output.node.printer.pretty.step_setup') + )), + ) + ), + $this->proxySiblingEvents( + OutlineTested::BEFORE, + OutlineTested::AFTER, + array( + $this->proxyEventsIfParameterIsSet( + 'expand', + false, + new Definition('Behat\Behat\Output\Node\EventListener\AST\OutlineTableListener', array( + new Reference('output.node.printer.pretty.outline_table'), + new Reference('output.node.printer.pretty.example_row'), + new Reference('output.node.printer.pretty.example_setup'), + new Reference('output.node.printer.pretty.example_step_setup') + )) + ), + $this->proxyEventsIfParameterIsSet( + 'expand', + true, + new Definition('Behat\Behat\Output\Node\EventListener\AST\OutlineListener', array( + new Reference('output.node.printer.pretty.outline'), + new Reference('output.node.printer.pretty.example'), + new Reference('output.node.printer.pretty.example_step'), + new Reference('output.node.printer.pretty.example_setup'), + new Reference('output.node.printer.pretty.example_step_setup') + )) + ) + ) + ), + ) + )); + $container->setDefinition(self::ROOT_LISTENER_ID, $definition); + } + + /** + * Loads formatter itself. + * + * @param ContainerBuilder $container + */ + protected function loadFormatter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Statistics\Statistics'); + $container->setDefinition('output.pretty.statistics', $definition); + + $definition = new Definition('Behat\Testwork\Output\NodeEventListeningFormatter', array( + 'pretty', + 'Prints the feature as is.', + array( + 'timer' => true, + 'expand' => false, + 'paths' => true, + 'multiline' => true, + ), + $this->createOutputPrinterDefinition(), + new Definition('Behat\Testwork\Output\Node\EventListener\ChainEventListener', array( + array( + $this->rearrangeBackgroundEvents( + new Reference(self::ROOT_LISTENER_ID) + ), + new Definition('Behat\Behat\Output\Node\EventListener\Statistics\StatisticsListener', array( + new Reference('output.pretty.statistics'), + new Reference('output.node.printer.pretty.statistics') + )), + new Definition('Behat\Behat\Output\Node\EventListener\Statistics\ScenarioStatsListener', array( + new Reference('output.pretty.statistics') + )), + new Definition('Behat\Behat\Output\Node\EventListener\Statistics\StepStatsListener', array( + new Reference('output.pretty.statistics'), + new Reference(ExceptionExtension::PRESENTER_ID) + )), + ) + ) + ) + )); + $definition->addTag(OutputExtension::FORMATTER_TAG, array('priority' => 100)); + $container->setDefinition(OutputExtension::FORMATTER_TAG . '.pretty', $definition); + } + + /** + * Loads feature, scenario and step printers. + * + * @param ContainerBuilder $container + */ + protected function loadCorePrinters(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyFeaturePrinter'); + $container->setDefinition('output.node.printer.pretty.feature', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyPathPrinter', array( + new Reference('output.node.printer.pretty.width_calculator'), + '%paths.base%' + )); + $container->setDefinition('output.node.printer.pretty.path', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyScenarioPrinter', array( + new Reference('output.node.printer.pretty.path'), + )); + $container->setDefinition('output.node.printer.pretty.scenario', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyStepPrinter', array( + new Reference('output.node.printer.pretty.step_text_painter'), + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference('output.node.printer.pretty.path'), + new Reference(ExceptionExtension::PRESENTER_ID) + )); + $container->setDefinition('output.node.printer.pretty.step', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettySkippedStepPrinter', array( + new Reference('output.node.printer.pretty.step_text_painter'), + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference('output.node.printer.pretty.path'), + )); + $container->setDefinition('output.node.printer.pretty.skipped_step', $definition); + } + + /** + * Loads table outline printer. + * + * @param ContainerBuilder $container + */ + protected function loadTableOutlinePrinter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyOutlineTablePrinter', array( + new Reference('output.node.printer.pretty.scenario'), + new Reference('output.node.printer.pretty.skipped_step'), + new Reference(self::RESULT_TO_STRING_CONVERTER_ID) + )); + $container->setDefinition('output.node.printer.pretty.outline_table', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyExampleRowPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(ExceptionExtension::PRESENTER_ID) + )); + $container->setDefinition('output.node.printer.pretty.example_row', $definition); + } + + /** + * Loads expanded outline printer. + * + * @param ContainerBuilder $container + */ + protected function loadExpandedOutlinePrinter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyOutlinePrinter', array( + new Reference('output.node.printer.pretty.scenario'), + new Reference('output.node.printer.pretty.skipped_step'), + new Reference(self::RESULT_TO_STRING_CONVERTER_ID) + )); + $container->setDefinition('output.node.printer.pretty.outline', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyExamplePrinter', array( + new Reference('output.node.printer.pretty.path'), + )); + $container->setDefinition('output.node.printer.pretty.example', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyStepPrinter', array( + new Reference('output.node.printer.pretty.step_text_painter'), + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference('output.node.printer.pretty.path'), + new Reference(ExceptionExtension::PRESENTER_ID), + 8 + )); + $container->setDefinition('output.node.printer.pretty.example_step', $definition); + } + + /** + * Loads hook printers. + * + * @param ContainerBuilder $container + */ + protected function loadHookPrinters(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettySetupPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(ExceptionExtension::PRESENTER_ID), + 0, + true, + true + )); + $container->setDefinition('output.node.printer.pretty.suite_setup', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettySetupPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(ExceptionExtension::PRESENTER_ID), + 0, + false, + true + )); + $container->setDefinition('output.node.printer.pretty.feature_setup', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettySetupPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(ExceptionExtension::PRESENTER_ID), + 2 + )); + $container->setDefinition('output.node.printer.pretty.scenario_setup', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettySetupPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(ExceptionExtension::PRESENTER_ID), + 4 + )); + $container->setDefinition('output.node.printer.pretty.step_setup', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettySetupPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(ExceptionExtension::PRESENTER_ID), + 8 + )); + $container->setDefinition('output.node.printer.pretty.example_step_setup', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettySetupPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(ExceptionExtension::PRESENTER_ID), + 6 + )); + $container->setDefinition('output.node.printer.pretty.example_setup', $definition); + } + + /** + * Loads statistics printer. + * + * @param ContainerBuilder $container + */ + protected function loadStatisticsPrinter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\CounterPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(TranslatorExtension::TRANSLATOR_ID), + )); + $container->setDefinition('output.node.printer.counter', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\ListPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(ExceptionExtension::PRESENTER_ID), + new Reference(TranslatorExtension::TRANSLATOR_ID), + '%paths.base%' + )); + $container->setDefinition('output.node.printer.list', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Pretty\PrettyStatisticsPrinter', array( + new Reference('output.node.printer.counter'), + new Reference('output.node.printer.list') + )); + $container->setDefinition('output.node.printer.pretty.statistics', $definition); + } + + /** + * Loads printer helpers. + * + * @param ContainerBuilder $container + */ + protected function loadPrinterHelpers(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\Helper\WidthCalculator'); + $container->setDefinition('output.node.printer.pretty.width_calculator', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Helper\StepTextPainter', array( + new Reference(DefinitionExtension::PATTERN_TRANSFORMER_ID), + new Reference(self::RESULT_TO_STRING_CONVERTER_ID) + )); + $container->setDefinition('output.node.printer.pretty.step_text_painter', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter'); + $container->setDefinition(self::RESULT_TO_STRING_CONVERTER_ID, $definition); + } + + /** + * Creates output printer definition. + * + * @return Definition + */ + protected function createOutputPrinterDefinition() + { + return new Definition('Behat\Behat\Output\Printer\ConsoleOutputPrinter'); + } + + /** + * Creates root listener definition. + * + * @param mixed $listener + * + * @return Definition + */ + protected function rearrangeBackgroundEvents($listener) + { + return new Definition('Behat\Behat\Output\Node\EventListener\Flow\FirstBackgroundFiresFirstListener', array( + new Definition('Behat\Behat\Output\Node\EventListener\Flow\OnlyFirstBackgroundFiresListener', array( + $listener + )) + )); + } + + /** + * Creates contextual proxy listener. + * + * @param string $beforeEventName + * @param string $afterEventName + * @param Definition[] $listeners + * + * @return Definition + */ + protected function proxySiblingEvents($beforeEventName, $afterEventName, array $listeners) + { + return new Definition('Behat\Behat\Output\Node\EventListener\Flow\FireOnlySiblingsListener', + array( + $beforeEventName, + $afterEventName, + new Definition('Behat\Testwork\Output\Node\EventListener\ChainEventListener', array($listeners)) + ) + ); + } + + /** + * Creates contextual proxy listener. + * + * @param string $name + * @param mixed $value + * @param mixed $listener + * + * @return Definition + */ + protected function proxyEventsIfParameterIsSet($name, $value, Definition $listener) + { + return new Definition('Behat\Testwork\Output\Node\EventListener\Flow\FireOnlyIfFormatterParameterListener', + array($name, $value, $listener) + ); + } + + /** + * Processes all registered pretty formatter node listener wrappers. + * + * @param ContainerBuilder $container + */ + protected function processListenerWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::ROOT_LISTENER_ID, self::ROOT_LISTENER_WRAPPER_TAG); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/ProgressFormatterFactory.php b/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/ProgressFormatterFactory.php new file mode 100644 index 0000000..8261ca3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/ProgressFormatterFactory.php @@ -0,0 +1,193 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\ServiceContainer\Formatter; + +use Behat\Testwork\Exception\ServiceContainer\ExceptionExtension; +use Behat\Testwork\Output\ServiceContainer\Formatter\FormatterFactory; +use Behat\Testwork\Output\ServiceContainer\OutputExtension; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Behat progress formatter factory. + * + * @author Konstantin Kudryashov + */ +class ProgressFormatterFactory implements FormatterFactory +{ + /** + * @var ServiceProcessor + */ + private $processor; + + /* + * Available services + */ + const ROOT_LISTENER_ID = 'output.node.listener.progress'; + const RESULT_TO_STRING_CONVERTER_ID = 'output.node.printer.result_to_string'; + + /* + * Available extension points + */ + const ROOT_LISTENER_WRAPPER_TAG = 'output.node.listener.progress.wrapper'; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function buildFormatter(ContainerBuilder $container) + { + $this->loadRootNodeListener($container); + $this->loadCorePrinters($container); + $this->loadPrinterHelpers($container); + $this->loadFormatter($container); + } + + /** + * {@inheritdoc} + */ + public function processFormatter(ContainerBuilder $container) + { + $this->processListenerWrappers($container); + } + + /** + * Loads progress formatter node event listener. + * + * @param ContainerBuilder $container + */ + protected function loadRootNodeListener(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\EventListener\AST\StepListener', array( + new Reference('output.node.printer.progress.step') + )); + $container->setDefinition(self::ROOT_LISTENER_ID, $definition); + } + + /** + * Loads feature, scenario and step printers. + * + * @param ContainerBuilder $container + */ + protected function loadCorePrinters(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\CounterPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(TranslatorExtension::TRANSLATOR_ID), + )); + $container->setDefinition('output.node.printer.counter', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\ListPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference(ExceptionExtension::PRESENTER_ID), + new Reference(TranslatorExtension::TRANSLATOR_ID), + '%paths.base%' + )); + $container->setDefinition('output.node.printer.list', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Progress\ProgressStepPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID) + )); + $container->setDefinition('output.node.printer.progress.step', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\Progress\ProgressStatisticsPrinter', array( + new Reference('output.node.printer.counter'), + new Reference('output.node.printer.list') + )); + $container->setDefinition('output.node.printer.progress.statistics', $definition); + } + + /** + * Loads printer helpers. + * + * @param ContainerBuilder $container + */ + protected function loadPrinterHelpers(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter'); + $container->setDefinition(self::RESULT_TO_STRING_CONVERTER_ID, $definition); + } + + /** + * Loads formatter itself. + * + * @param ContainerBuilder $container + */ + protected function loadFormatter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Statistics\Statistics'); + $container->setDefinition('output.progress.statistics', $definition); + + $definition = new Definition('Behat\Testwork\Output\NodeEventListeningFormatter', array( + 'progress', + 'Prints one character per step.', + array( + 'timer' => true + ), + $this->createOutputPrinterDefinition(), + new Definition('Behat\Testwork\Output\Node\EventListener\ChainEventListener', array( + array( + new Reference(self::ROOT_LISTENER_ID), + new Definition('Behat\Behat\Output\Node\EventListener\Statistics\StatisticsListener', array( + new Reference('output.progress.statistics'), + new Reference('output.node.printer.progress.statistics') + )), + new Definition('Behat\Behat\Output\Node\EventListener\Statistics\ScenarioStatsListener', array( + new Reference('output.progress.statistics') + )), + new Definition('Behat\Behat\Output\Node\EventListener\Statistics\StepStatsListener', array( + new Reference('output.progress.statistics'), + new Reference(ExceptionExtension::PRESENTER_ID) + )), + new Definition('Behat\Behat\Output\Node\EventListener\Statistics\HookStatsListener', array( + new Reference('output.progress.statistics'), + new Reference(ExceptionExtension::PRESENTER_ID) + )), + ) + ) + ) + )); + $definition->addTag(OutputExtension::FORMATTER_TAG, array('priority' => 100)); + $container->setDefinition(OutputExtension::FORMATTER_TAG . '.progress', $definition); + } + + /** + * Creates output printer definition. + * + * @return Definition + */ + protected function createOutputPrinterDefinition() + { + return new Definition('Behat\Behat\Output\Printer\ConsoleOutputPrinter'); + } + + /** + * Processes all registered pretty formatter node listener wrappers. + * + * @param ContainerBuilder $container + */ + protected function processListenerWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::ROOT_LISTENER_ID, self::ROOT_LISTENER_WRAPPER_TAG); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Statistics/HookStat.php b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/HookStat.php new file mode 100644 index 0000000..e8afc31 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/HookStat.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Statistics; + +/** + * Represents hook stat. + * + * @author Konstantin Kudryashov + */ +final class HookStat +{ + /** + * @var string + */ + private $name; + /** + * @var string + */ + private $path; + /** + * @var string|null + */ + private $error; + /** + * @var string|null + */ + private $stdOut; + + /** + * Initializes hook stat. + * + * @param string $name + * @param string $path + * @param null|string $error + * @param null|string $stdOut + */ + public function __construct($name, $path, $error = null, $stdOut = null) + { + $this->name = $name; + $this->path = $path; + $this->error = $error; + $this->stdOut = $stdOut; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function isSuccessful() + { + return null === $this->error; + } + + /** + * Returns hook standard output (if has some). + * + * @return null|string + */ + public function getStdOut() + { + return $this->stdOut; + } + + /** + * Returns hook exception. + * + * @return string + */ + public function getError() + { + return $this->error; + } + + /** + * Returns hook path. + * + * @return string + */ + public function getPath() + { + return $this->path; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Statistics/ScenarioStat.php b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/ScenarioStat.php new file mode 100644 index 0000000..0af5005 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/ScenarioStat.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Statistics; + +/** + * Behat scenario stat. + * + * @author Konstantin Kudryashov + */ +final class ScenarioStat +{ + /** + * @var string + */ + private $title; + /** + * @var string + */ + private $path; + /** + * @var integer + */ + private $resultCode; + + /** + * Initializes scenario stat. + * + * @param string $title + * @param string $path + * @param integer $resultCode + */ + public function __construct($title, $path, $resultCode) + { + $this->title = $title; + $this->path = $path; + $this->resultCode = $resultCode; + } + + /** + * Returns scenario title. + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Returns scenario path. + * + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * Returns scenario result code. + * + * @return integer + */ + public function getResultCode() + { + return $this->resultCode; + } + + /** + * Returns string representation for a stat. + * + * @return string + */ + public function __toString() + { + return $this->getPath(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Statistics/Statistics.php b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/Statistics.php new file mode 100644 index 0000000..9ba6d68 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/Statistics.php @@ -0,0 +1,239 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Statistics; + +use Behat\Behat\Tester\Result\StepResult; +use Behat\Testwork\Counter\Memory; +use Behat\Testwork\Counter\Timer; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestResults; + +/** + * Collects and provided exercise statistics. + * + * @author Konstantin Kudryashov + */ +final class Statistics +{ + /** + * @var Timer + */ + private $timer; + /** + * @var Memory + */ + private $memory; + /** + * @var array + */ + private $scenarioCounters = array(); + /** + * @var array + */ + private $stepCounters = array(); + /** + * @var ScenarioStat[] + */ + private $failedScenarioStats = array(); + /** + * @var ScenarioStat[] + */ + private $skippedScenarioStats = array(); + /** + * @var StepStat[] + */ + private $failedStepStats = array(); + /** + * @var StepStat[] + */ + private $pendingStepStats = array(); + /** + * @var HookStat[] + */ + private $failedHookStats = array(); + + /** + * Initializes statistics. + */ + public function __construct() + { + $this->scenarioCounters = $this->stepCounters = array( + TestResult::PASSED => 0, + TestResult::FAILED => 0, + StepResult::UNDEFINED => 0, + TestResult::PENDING => 0, + TestResult::SKIPPED => 0 + ); + + $this->timer = new Timer(); + $this->memory = new Memory(); + } + + /** + * Starts timer. + */ + public function startTimer() + { + $this->timer->start(); + } + + /** + * Stops timer. + */ + public function stopTimer() + { + $this->timer->stop(); + } + + /** + * Returns timer object. + * + * @return Timer + */ + public function getTimer() + { + return $this->timer; + } + + /** + * Returns memory usage object. + * + * @return Memory + */ + public function getMemory() + { + return $this->memory; + } + + /** + * Registers scenario stat. + * + * @param ScenarioStat $stat + */ + public function registerScenarioStat(ScenarioStat $stat) + { + if (TestResults::NO_TESTS === $stat->getResultCode()) { + return; + } + + $this->scenarioCounters[$stat->getResultCode()]++; + + if (TestResult::FAILED === $stat->getResultCode()) { + $this->failedScenarioStats[] = $stat; + } + + if (TestResult::SKIPPED === $stat->getResultCode()) { + $this->skippedScenarioStats[] = $stat; + } + } + + /** + * Registers step stat. + * + * @param StepStat $stat + */ + public function registerStepStat(StepStat $stat) + { + $this->stepCounters[$stat->getResultCode()]++; + + if (TestResult::FAILED === $stat->getResultCode()) { + $this->failedStepStats[] = $stat; + } + + if (TestResult::PENDING === $stat->getResultCode()) { + $this->pendingStepStats[] = $stat; + } + } + + /** + * Registers hook stat. + * + * @param HookStat $stat + */ + public function registerHookStat(HookStat $stat) + { + if ($stat->isSuccessful()) { + return; + } + + $this->failedHookStats[] = $stat; + } + + /** + * Returns counters for different scenario result codes. + * + * @return array[] + */ + public function getScenarioStatCounts() + { + return $this->scenarioCounters; + } + + /** + * Returns skipped scenario stats. + * + * @return ScenarioStat[] + */ + public function getSkippedScenarios() + { + return $this->skippedScenarioStats; + } + + /** + * Returns failed scenario stats. + * + * @return ScenarioStat[] + */ + public function getFailedScenarios() + { + return $this->failedScenarioStats; + } + + /** + * Returns counters for different step result codes. + * + * @return array[] + */ + public function getStepStatCounts() + { + return $this->stepCounters; + } + + /** + * Returns failed step stats. + * + * @return StepStat[] + */ + public function getFailedSteps() + { + return $this->failedStepStats; + } + + /** + * Returns pending step stats. + * + * @return StepStat[] + */ + public function getPendingSteps() + { + return $this->pendingStepStats; + } + + /** + * Returns failed hook stats. + * + * @return HookStat[] + */ + public function getFailedHookStats() + { + return $this->failedHookStats; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Statistics/StepStat.php b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/StepStat.php new file mode 100644 index 0000000..09a97eb --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/StepStat.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Output\Statistics; + +/** + * Behat step stat. + * + * @author Konstantin Kudryashov + */ +final class StepStat +{ + /** + * @var string + */ + private $text; + /** + * @var string + */ + private $path; + /** + * @var integer + */ + private $resultCode; + /** + * @var null|string + */ + private $error; + /** + * @var null|string + */ + private $stdOut; + + /** + * Initializes step stat. + * + * @param string $text + * @param string $path + * @param integer $resultCode + * @param null|string $error + * @param null|string $stdOut + */ + public function __construct($text, $path, $resultCode, $error = null, $stdOut = null) + { + $this->text = $text; + $this->path = $path; + $this->resultCode = $resultCode; + $this->error = $error; + $this->stdOut = $stdOut; + } + + /** + * Returns step text. + * + * @return string + */ + public function getText() + { + return $this->text; + } + + /** + * Returns step path. + * + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * Returns step result code. + * + * @return integer + */ + public function getResultCode() + { + return $this->resultCode; + } + + /** + * Returns step error (if has one). + * + * @return null|string + */ + public function getError() + { + return $this->error; + } + + /** + * Returns step output (if has one). + * + * @return null|string + */ + public function getStdOut() + { + return $this->stdOut; + } + + /** + * Returns string representation for a stat. + * + * @return string + */ + public function __toString() + { + return $this->getPath(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/AggregateSnippet.php b/vendor/behat/behat/src/Behat/Behat/Snippet/AggregateSnippet.php new file mode 100644 index 0000000..3398457 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/AggregateSnippet.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet; + +use Behat\Gherkin\Node\StepNode; + +/** + * Aggregates multiple similar snippets with different targets and steps. + * + * @author Konstantin Kudryashov + */ +final class AggregateSnippet +{ + /** + * @var Snippet[] + */ + private $snippets; + + /** + * Initializes snippet. + * + * @param Snippet[] $snippets + */ + public function __construct(array $snippets) + { + $this->snippets = $snippets; + } + + /** + * Returns snippet type. + * + * @return string + */ + public function getType() + { + return current($this->snippets)->getType(); + } + + /** + * Returns snippet unique ID (step type independent). + * + * @return string + */ + public function getHash() + { + return current($this->snippets)->getHash(); + } + + /** + * Returns definition snippet text. + * + * @return string + */ + public function getSnippet() + { + return current($this->snippets)->getSnippet(); + } + + /** + * Returns all steps interested in this snippet. + * + * @return StepNode[] + */ + public function getSteps() + { + return array_unique( + array_map( + function (Snippet $snippet) { + return $snippet->getStep(); + }, + $this->snippets + ), + SORT_REGULAR + ); + } + + /** + * Returns all snippet targets. + * + * @return string[] + */ + public function getTargets() + { + return array_unique( + array_map( + function (Snippet $snippet) { + return $snippet->getTarget(); + }, + $this->snippets + ) + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/Appender/SnippetAppender.php b/vendor/behat/behat/src/Behat/Behat/Snippet/Appender/SnippetAppender.php new file mode 100644 index 0000000..041b8e6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/Appender/SnippetAppender.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet\Appender; + +use Behat\Behat\Snippet\AggregateSnippet; +use Behat\Behat\Snippet\SnippetWriter; + +/** + * Appends snippets to its targets. Used by SnippetWriter. + * + * @see SnippetWriter + * + * @author Konstantin Kudryashov + */ +interface SnippetAppender +{ + /** + * Checks if appender supports snippet. + * + * @param AggregateSnippet $snippet + * + * @return Boolean + */ + public function supportsSnippet(AggregateSnippet $snippet); + + /** + * Appends snippet to the source. + * + * @param AggregateSnippet $snippet + */ + public function appendSnippet(AggregateSnippet $snippet); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/Cli/SnippetsController.php b/vendor/behat/behat/src/Behat/Behat/Snippet/Cli/SnippetsController.php new file mode 100644 index 0000000..8ecdac5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/Cli/SnippetsController.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet\Cli; + +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Behat\EventDispatcher\Event\StepTested; +use Behat\Behat\Snippet\Printer\ConsoleSnippetPrinter; +use Behat\Behat\Snippet\SnippetRegistry; +use Behat\Behat\Snippet\SnippetWriter; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Appends and prints snippets. + * + * @author Konstantin Kudryashov + */ +final class SnippetsController implements Controller +{ + /** + * @var SnippetRegistry + */ + private $registry; + /** + * @var SnippetWriter + */ + private $writer; + /** + * @var ConsoleSnippetPrinter + */ + private $printer; + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + /** + * @var OutputInterface + */ + private $output; + + /** + * Initializes controller. + * + * @param SnippetRegistry $registry + * @param SnippetWriter $writer + * @param ConsoleSnippetPrinter $printer + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct( + SnippetRegistry $registry, + SnippetWriter $writer, + ConsoleSnippetPrinter $printer, + EventDispatcherInterface $eventDispatcher + ) { + $this->registry = $registry; + $this->writer = $writer; + $this->printer = $printer; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * Configures command to be executable by the controller. + * + * @param Command $command + */ + public function configure(Command $command) + { + $command + ->addOption( + '--append-snippets', null, InputOption::VALUE_NONE, + "Appends snippets for undefined steps into main context." + ) + ->addOption( + '--no-snippets', null, InputOption::VALUE_NONE, + "Do not print snippets for undefined steps after stats." + ); + } + + /** + * Executes controller. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return null|integer + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $this->eventDispatcher->addListener(StepTested::AFTER, array($this, 'registerUndefinedStep'), -999); + $this->output = $output; + + if ($input->getOption('append-snippets')) { + $this->eventDispatcher->addListener(ExerciseCompleted::AFTER, array($this, 'appendAllSnippets'), -999); + } + + if (!$input->getOption('no-snippets') && !$input->getOption('append-snippets')) { + $this->eventDispatcher->addListener(ExerciseCompleted::AFTER, array($this, 'printAllSnippets'), -999); + } + + if (!$input->getOption('no-snippets')) { + $this->eventDispatcher->addListener(ExerciseCompleted::AFTER, array($this, 'printUndefinedSteps'), -995); + } + } + + /** + * Registers undefined step. + * + * @param AfterStepTested $event + */ + public function registerUndefinedStep(AfterStepTested $event) + { + if (StepResult::UNDEFINED === $event->getTestResult()->getResultCode()) { + $this->registry->registerUndefinedStep($event->getEnvironment(), $event->getStep()); + } + } + + /** + * Appends all snippets to corresponding targets. + */ + public function appendAllSnippets() + { + $snippets = $this->registry->getSnippets(); + count($snippets) && $this->output->writeln(''); + + $this->writer->appendSnippets($snippets); + } + + /** + * Prints all snippets. + */ + public function printAllSnippets() + { + $snippets = $this->registry->getSnippets(); + count($snippets) && $this->output->writeln(''); + + $this->writer->printSnippets($this->printer, $snippets); + } + + /** + * Prints all undefined steps. + */ + public function printUndefinedSteps() + { + $undefined = $this->registry->getUndefinedSteps(); + count($undefined) && $this->output->writeln(''); + + $this->writer->printUndefinedSteps($this->printer, $undefined); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/Exception/EnvironmentSnippetGenerationException.php b/vendor/behat/behat/src/Behat/Behat/Snippet/Exception/EnvironmentSnippetGenerationException.php new file mode 100644 index 0000000..5b01e2f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/Exception/EnvironmentSnippetGenerationException.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet\Exception; + +use Behat\Testwork\Environment\Environment; +use RuntimeException; + +/** + * Represents exception caused by an attempt to generate snippet for unsupported environment. + * + * @author Konstantin Kudryashov + */ +final class EnvironmentSnippetGenerationException extends RuntimeException implements SnippetException +{ + /** + * @var Environment + */ + private $environment; + + /** + * Initializes exception. + * + * @param string $message + * @param Environment $environment + */ + public function __construct($message, Environment $environment) + { + $this->environment = $environment; + + parent::__construct($message); + } + + /** + * Returns environment that caused exception. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/Exception/SnippetException.php b/vendor/behat/behat/src/Behat/Behat/Snippet/Exception/SnippetException.php new file mode 100644 index 0000000..f3b23ae --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/Exception/SnippetException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet\Exception; + +use Behat\Testwork\Exception\TestworkException; + +/** + * All snippet exceptions should implement this interface. + * + * @author Konstantin Kudryashov + */ +interface SnippetException extends TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/Generator/SnippetGenerator.php b/vendor/behat/behat/src/Behat/Behat/Snippet/Generator/SnippetGenerator.php new file mode 100644 index 0000000..ca7d739 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/Generator/SnippetGenerator.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet\Generator; + +use Behat\Behat\Snippet\Snippet; +use Behat\Behat\Snippet\SnippetRegistry; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; + +/** + * Generates snippet for a specific step in a specific environment. + * + * @see SnippetRegistry + * + * @author Konstantin Kudryashov + */ +interface SnippetGenerator +{ + /** + * Checks if generator supports search query. + * + * @param Environment $environment + * @param StepNode $step + * + * @return Boolean + */ + public function supportsEnvironmentAndStep(Environment $environment, StepNode $step); + + /** + * Generates snippet from search. + * + * @param Environment $environment + * @param StepNode $step + * + * @return Snippet + */ + public function generateSnippet(Environment $environment, StepNode $step); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/Printer/ConsoleSnippetPrinter.php b/vendor/behat/behat/src/Behat/Behat/Snippet/Printer/ConsoleSnippetPrinter.php new file mode 100644 index 0000000..7a5b36e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/Printer/ConsoleSnippetPrinter.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet\Printer; + +use Behat\Behat\Snippet\AggregateSnippet; +use Behat\Gherkin\Node\StepNode; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Behat console-based snippet printer. + * + * Extends default printer with default styles. + * + * @author Konstantin Kudryashov + */ +class ConsoleSnippetPrinter implements SnippetPrinter +{ + /** + * @var OutputInterface + */ + private $output; + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * Initializes printer. + * + * @param OutputInterface $output + * @param TranslatorInterface $translator + */ + public function __construct(OutputInterface $output, TranslatorInterface $translator) + { + $this->output = $output; + $this->translator = $translator; + + $output->getFormatter()->setStyle('snippet_keyword', new OutputFormatterStyle(null, null, array('bold'))); + $output->getFormatter()->setStyle('snippet_undefined', new OutputFormatterStyle('yellow')); + } + + /** + * Prints snippets of specific target. + * + * @param string $targetName + * @param AggregateSnippet[] $snippets + */ + public function printSnippets($targetName, array $snippets) + { + $message = $this->translator->trans('snippet_proposal_title', array('%1%' => $targetName), 'output'); + + $this->output->writeln('--- ' . $message . PHP_EOL); + + foreach ($snippets as $snippet) { + $this->output->writeln(sprintf('%s', $snippet->getSnippet()) . PHP_EOL); + } + } + + /** + * Prints undefined steps of specific suite. + * + * @param string $suiteName + * @param StepNode[] $steps + */ + public function printUndefinedSteps($suiteName, array $steps) + { + $message = $this->translator->trans('snippet_missing_title', array('%1%' => $suiteName), 'output'); + + $this->output->writeln('--- ' . $message . PHP_EOL); + + foreach ($steps as $step) { + $this->output->writeln(sprintf(' %s %s', $step->getKeyword(), $step->getText())); + } + + $this->output->writeln(''); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/Printer/SnippetPrinter.php b/vendor/behat/behat/src/Behat/Behat/Snippet/Printer/SnippetPrinter.php new file mode 100644 index 0000000..a0050af --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/Printer/SnippetPrinter.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet\Printer; + +use Behat\Behat\Snippet\AggregateSnippet; +use Behat\Gherkin\Node\StepNode; + +/** + * Prints all snippets for a target. + * + * @author Konstantin Kudryashov + */ +interface SnippetPrinter +{ + /** + * Prints snippets of the specific target. + * + * @param string $targetName + * @param AggregateSnippet[] $snippets + */ + public function printSnippets($targetName, array $snippets); + + /** + * Prints undefined steps of the specific suite. + * + * @param string $suiteName + * @param StepNode[] $steps + */ + public function printUndefinedSteps($suiteName, array $steps); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/ServiceContainer/SnippetExtension.php b/vendor/behat/behat/src/Behat/Behat/Snippet/ServiceContainer/SnippetExtension.php new file mode 100644 index 0000000..992c371 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/ServiceContainer/SnippetExtension.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides snippet generation, printing and appending functionality. + * + * @author Konstantin Kudryashov + */ +class SnippetExtension implements Extension +{ + /* + * Available services + */ + const REGISTRY_ID = 'snippet.registry'; + const WRITER_ID = 'snippet.writer'; + + /* + * Available extension points + */ + const GENERATOR_TAG = 'snippet.generator'; + const APPENDER_TAG = 'snippet.appender'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'snippets'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadController($container); + $this->loadRegistry($container); + $this->loadWriter($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processGenerators($container); + $this->processAppenders($container); + } + + /** + * @param ContainerBuilder $container + */ + protected function loadController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Snippet\Printer\ConsoleSnippetPrinter', array( + new Reference(CliExtension::OUTPUT_ID), + new Reference(TranslatorExtension::TRANSLATOR_ID) + )); + $container->setDefinition('snippet.printer', $definition); + + $definition = new Definition('Behat\Behat\Snippet\Cli\SnippetsController', array( + new Reference(self::REGISTRY_ID), + new Reference(self::WRITER_ID), + new Reference('snippet.printer'), + new Reference(EventDispatcherExtension::DISPATCHER_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 400)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.snippet', $definition); + } + + /** + * @param ContainerBuilder $container + */ + protected function loadRegistry(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Snippet\SnippetRegistry'); + $container->setDefinition(self::REGISTRY_ID, $definition); + } + + /** + * @param ContainerBuilder $container + */ + protected function loadWriter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Snippet\SnippetWriter'); + $container->setDefinition(self::WRITER_ID, $definition); + } + + /** + * @param ContainerBuilder $container + */ + protected function processGenerators(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::GENERATOR_TAG); + $definition = $container->getDefinition(self::REGISTRY_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerSnippetGenerator', array($reference)); + } + } + + /** + * @param ContainerBuilder $container + */ + protected function processAppenders(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::APPENDER_TAG); + $definition = $container->getDefinition(self::WRITER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerSnippetAppender', array($reference)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/Snippet.php b/vendor/behat/behat/src/Behat/Behat/Snippet/Snippet.php new file mode 100644 index 0000000..b96e445 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/Snippet.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet; + +use Behat\Gherkin\Node\StepNode; + +/** + * Step definition snippet. + * + * @author Konstantin Kudryashov + */ +interface Snippet +{ + /** + * Returns snippet type. + * + * @return string + */ + public function getType(); + + /** + * Returns snippet unique ID (step type independent). + * + * @return string + */ + public function getHash(); + + /** + * Returns definition snippet text. + * + * @return string + */ + public function getSnippet(); + + /** + * Returns step which asked for this snippet. + * + * @return StepNode + */ + public function getStep(); + + /** + * Returns snippet target. + * + * @return string + */ + public function getTarget(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/SnippetRegistry.php b/vendor/behat/behat/src/Behat/Behat/Snippet/SnippetRegistry.php new file mode 100644 index 0000000..0724c3e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/SnippetRegistry.php @@ -0,0 +1,143 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet; + +use Behat\Behat\Snippet\Generator\SnippetGenerator; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; + +/** + * Acts like a snippet repository by producing snippets from registered undefined steps using snippet generators. + * + * @author Konstantin Kudryashov + */ +final class SnippetRegistry implements SnippetRepository +{ + /** + * @var SnippetGenerator[] + */ + private $generators = array(); + /** + * @var UndefinedStep[] + */ + private $undefinedSteps = array(); + /** + * @var AggregateSnippet[] + */ + private $snippets = array(); + /** + * @var Boolean + */ + private $snippetsGenerated = false; + + /** + * Registers snippet generator. + * + * @param SnippetGenerator $generator + */ + public function registerSnippetGenerator(SnippetGenerator $generator) + { + $this->generators[] = $generator; + $this->snippetsGenerated = false; + } + + /** + * Generates and registers snippet. + * + * @param Environment $environment + * @param StepNode $step + * + * @return null|Snippet + */ + public function registerUndefinedStep(Environment $environment, StepNode $step) + { + $this->undefinedSteps[] = new UndefinedStep($environment, $step); + $this->snippetsGenerated = false; + } + + /** + * Returns all generated snippets. + * + * @return AggregateSnippet[] + */ + public function getSnippets() + { + $this->generateSnippets(); + + return $this->snippets; + } + + /** + * Returns steps for which there was no snippet generated. + * + * @return UndefinedStep[] + */ + public function getUndefinedSteps() + { + $this->generateSnippets(); + + return $this->undefinedSteps; + } + + /** + * Generates snippets for undefined steps. + */ + private function generateSnippets() + { + if ($this->snippetsGenerated) { + return null; + } + + $snippetsSet = array(); + foreach ($this->undefinedSteps as $i => $undefinedStep) { + $snippet = $this->generateSnippet($undefinedStep->getEnvironment(), $undefinedStep->getStep()); + + if (!$snippet) { + continue; + } + + if (!isset($snippetsSet[$snippet->getHash()])) { + $snippetsSet[$snippet->getHash()] = array(); + } + + $snippetsSet[$snippet->getHash()][] = $snippet; + unset($this->undefinedSteps[$i]); + } + + $this->snippets = array_values( + array_map( + function (array $snippets) { + return new AggregateSnippet($snippets); + }, + $snippetsSet + ) + ); + $this->undefinedSteps = array_values($this->undefinedSteps); + $this->snippetsGenerated = true; + } + + /** + * @param Environment $environment + * @param StepNode $step + * + * @return null|Snippet + */ + private function generateSnippet(Environment $environment, StepNode $step) + { + foreach ($this->generators as $generator) { + if ($generator->supportsEnvironmentAndStep($environment, $step)) { + return $generator->generateSnippet($environment, $step); + } + } + + return null; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/SnippetRepository.php b/vendor/behat/behat/src/Behat/Behat/Snippet/SnippetRepository.php new file mode 100644 index 0000000..0305c4c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/SnippetRepository.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet; + +/** + * Provides snippets. + * + * @author Konstantin Kudryashov + */ +interface SnippetRepository +{ + /** + * Returns all generated snippets. + * + * @return AggregateSnippet[] + */ + public function getSnippets(); + + /** + * Returns steps for which there was no snippet generated. + * + * @return UndefinedStep[] + */ + public function getUndefinedSteps(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/SnippetWriter.php b/vendor/behat/behat/src/Behat/Behat/Snippet/SnippetWriter.php new file mode 100644 index 0000000..62d6e96 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/SnippetWriter.php @@ -0,0 +1,117 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet; + +use Behat\Behat\Snippet\Appender\SnippetAppender; +use Behat\Behat\Snippet\Printer\SnippetPrinter; + +/** + * Prints or appends snippets to a specific environment using registered appenders and printers. + * + * @author Konstantin Kudryashov + */ +final class SnippetWriter +{ + /** + * @var SnippetAppender[] + */ + private $appenders = array(); + + /** + * Registers snippet appender. + * + * @param SnippetAppender $appender + */ + public function registerSnippetAppender(SnippetAppender $appender) + { + $this->appenders[] = $appender; + } + + /** + * Appends snippets to appropriate targets. + * + * @param AggregateSnippet[] $snippets + */ + public function appendSnippets(array $snippets) + { + foreach ($snippets as $snippet) { + $this->appendSnippet($snippet); + } + } + + /** + * Prints snippets using provided printer. + * + * @param SnippetPrinter $printer + * @param AggregateSnippet[] $snippets + */ + public function printSnippets(SnippetPrinter $printer, array $snippets) + { + $printableSnippets = array(); + foreach ($snippets as $snippet) { + foreach ($snippet->getTargets() as $target) { + $targetSnippets = array(); + + if (isset($printableSnippets[$target])) { + $targetSnippets = $printableSnippets[$target]; + } + + $targetSnippets[] = $snippet; + $printableSnippets[$target] = $targetSnippets; + } + } + + foreach ($printableSnippets as $target => $targetSnippets) { + $printer->printSnippets($target, $targetSnippets); + } + } + + /** + * Prints undefined steps using provided printer. + * + * @param SnippetPrinter $printer + * @param UndefinedStep[] $undefinedSteps + */ + public function printUndefinedSteps(SnippetPrinter $printer, array $undefinedSteps) + { + $printableSteps = array(); + foreach ($undefinedSteps as $undefinedStep) { + $suiteName = $undefinedStep->getEnvironment()->getSuite()->getName(); + $step = $undefinedStep->getStep(); + + if (!isset($printableSteps[$suiteName])) { + $printableSteps[$suiteName] = array(); + } + + $printableSteps[$suiteName][$step->getText()] = $step; + } + + foreach ($printableSteps as $suiteName => $steps) { + $printer->printUndefinedSteps($suiteName, array_values($steps)); + } + } + + /** + * Appends snippet to appropriate targets. + * + * @param AggregateSnippet $snippet + */ + private function appendSnippet(AggregateSnippet $snippet) + { + foreach ($this->appenders as $appender) { + if (!$appender->supportsSnippet($snippet)) { + continue; + } + + $appender->appendSnippet($snippet); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Snippet/UndefinedStep.php b/vendor/behat/behat/src/Behat/Behat/Snippet/UndefinedStep.php new file mode 100644 index 0000000..58e3ddd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/UndefinedStep.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Snippet; + +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; + +/** + * Represents an undefined step in a specific environment. + * + * @author Konstantin Kudryashov + */ +final class UndefinedStep +{ + /** + * @var Environment + */ + private $environment; + /** + * @var StepNode + */ + private $step; + + /** + * Initializes undefined step. + * + * @param Environment $environment + * @param StepNode $step + */ + public function __construct(Environment $environment, StepNode $step) + { + $this->environment = $environment; + $this->step = $step; + } + + /** + * Returns environment that needs this step. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * Returns undefined step node. + * + * @return StepNode + */ + public function getStep() + { + return $this->step; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/BackgroundTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/BackgroundTester.php new file mode 100644 index 0000000..8d70b57 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/BackgroundTester.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Prepares and tests background from a provided feature object against provided environment. + * + * @author Konstantin Kudryashov + */ +interface BackgroundTester +{ + /** + * Sets up background for a test. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Boolean $skip + * + * @return Setup + */ + public function setUp(Environment $env, FeatureNode $feature, $skip); + + /** + * Tests background. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Boolean $skip + * + * @return TestResult + */ + public function test(Environment $env, FeatureNode $feature, $skip); + + /** + * Tears down background after a test. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Boolean $skip + * @param TestResult $result + * + * @return Teardown + */ + public function tearDown(Environment $env, FeatureNode $feature, $skip, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Cli/RerunController.php b/vendor/behat/behat/src/Behat/Behat/Tester/Cli/RerunController.php new file mode 100644 index 0000000..a71519d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Cli/RerunController.php @@ -0,0 +1,176 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Cli; + +use Behat\Behat\EventDispatcher\Event\AfterScenarioTested; +use Behat\Behat\EventDispatcher\Event\ExampleTested; +use Behat\Behat\EventDispatcher\Event\ScenarioTested; +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Caches failed scenarios and reruns only them if `--rerun` option provided. + * + * @author Konstantin Kudryashov + */ +final class RerunController implements Controller +{ + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + /** + * @var null|string + */ + private $cachePath; + /** + * @var string + */ + private $key; + /** + * @var string[] + */ + private $lines = array(); + + /** + * Initializes controller. + * + * @param EventDispatcherInterface $eventDispatcher + * @param null|string $cachePath + */ + public function __construct(EventDispatcherInterface $eventDispatcher, $cachePath) + { + $this->eventDispatcher = $eventDispatcher; + $this->cachePath = null !== $cachePath ? rtrim($cachePath, DIRECTORY_SEPARATOR) : null; + } + + /** + * Configures command to be executable by the controller. + * + * @param Command $command + */ + public function configure(Command $command) + { + $command->addOption('--rerun', null, InputOption::VALUE_NONE, + 'Re-run scenarios that failed during last execution.' + ); + } + + /** + * Executes controller. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return null|integer + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $this->eventDispatcher->addListener(ScenarioTested::AFTER, array($this, 'collectFailedScenario'), -50); + $this->eventDispatcher->addListener(ExampleTested::AFTER, array($this, 'collectFailedScenario'), -50); + $this->eventDispatcher->addListener(ExerciseCompleted::AFTER, array($this, 'writeCache'), -50); + + $this->key = $this->generateKey($input); + + if (!$input->getOption('rerun')) { + return; + } + + if (!$this->getFileName() || !file_exists($this->getFileName())) { + return; + } + + $input->setArgument('paths', $this->getFileName()); + } + + /** + * Records scenario if it is failed. + * + * @param AfterScenarioTested $event + */ + public function collectFailedScenario(AfterScenarioTested $event) + { + if (!$this->getFileName()) { + return; + } + + if ($event->getTestResult()->isPassed()) { + return; + } + + $feature = $event->getFeature(); + $scenario = $event->getScenario(); + + $this->lines[] = $feature->getFile() . ':' . $scenario->getLine(); + } + + /** + * Writes failed scenarios cache. + */ + public function writeCache() + { + if (!$this->getFileName()) { + return; + } + + if (file_exists($this->getFileName())) { + unlink($this->getFileName()); + } + + if (0 === count($this->lines)) { + return; + } + + file_put_contents($this->getFileName(), trim(implode("\n", $this->lines))); + } + + /** + * Generates cache key. + * + * @param InputInterface $input + * + * @return string + */ + private function generateKey(InputInterface $input) + { + return md5( + $input->getParameterOption(array('--profile', '-p')) . + $input->getOption('suite') . + implode(' ', $input->getOption('name')) . + implode(' ', $input->getOption('tags')) . + $input->getOption('role') . + $input->getArgument('paths') + ); + } + + /** + * Returns cache filename (if exists). + * + * @return null|string + */ + private function getFileName() + { + if (null === $this->cachePath || null === $this->key) { + return null; + } + + if (!is_dir($this->cachePath)) { + mkdir($this->cachePath, 0777); + } + + return $this->cachePath . DIRECTORY_SEPARATOR . $this->key . '.scenarios'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Exception/FeatureHasNoBackgroundException.php b/vendor/behat/behat/src/Behat/Behat/Tester/Exception/FeatureHasNoBackgroundException.php new file mode 100644 index 0000000..6d31eb1 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Exception/FeatureHasNoBackgroundException.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Exception; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Exception\TestworkException; +use RuntimeException; + +/** + * Represents exception throw during attempt to test non-existent feature background. + * + * @author Konstantin Kudryashov + */ +final class FeatureHasNoBackgroundException extends RuntimeException implements TestworkException +{ + /** + * @var FeatureNode + */ + private $feature; + + /** + * Initializes exception. + * + * @param string $message + * @param FeatureNode $feature + */ + public function __construct($message, FeatureNode $feature) + { + $this->feature = $feature; + + parent::__construct($message); + } + + /** + * Returns feature that caused exception. + * + * @return FeatureNode + */ + public function getFeature() + { + return $this->feature; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Exception/PendingException.php b/vendor/behat/behat/src/Behat/Behat/Tester/Exception/PendingException.php new file mode 100644 index 0000000..c328bd1 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Exception/PendingException.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Exception; + +use Behat\Testwork\Tester\Exception\TesterException; +use RuntimeException; + +/** + * Represents a pending exception. + * + * @author Konstantin Kudryashov + */ +final class PendingException extends RuntimeException implements TesterException +{ + /** + * Initializes pending exception. + * + * @param string $text + */ + public function __construct($text = 'TODO: write pending definition') + { + parent::__construct($text); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Exception/Stringer/PendingExceptionStringer.php b/vendor/behat/behat/src/Behat/Behat/Tester/Exception/Stringer/PendingExceptionStringer.php new file mode 100644 index 0000000..ef299ce --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Exception/Stringer/PendingExceptionStringer.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Exception\Stringer; + +use Behat\Behat\Tester\Exception\PendingException; +use Behat\Testwork\Exception\Stringer\ExceptionStringer; +use Exception; + +/** + * Strings pending exceptions. + * + * @author Konstantin Kudryashov + */ +class PendingExceptionStringer implements ExceptionStringer +{ + /** + * {@inheritdoc} + */ + public function supportsException(Exception $exception) + { + return $exception instanceof PendingException; + } + + /** + * {@inheritdoc} + */ + public function stringException(Exception $exception, $verbosity) + { + return trim($exception->getMessage()); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/OutlineTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/OutlineTester.php new file mode 100644 index 0000000..863aba3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/OutlineTester.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Prepares and tests provided outline object against provided environment. + * + * @author Konstantin Kudryashov + */ +interface OutlineTester +{ + /** + * Sets up background for a test. + * + * @param Environment $env + * @param FeatureNode $feature + * @param OutlineNode $outline + * @param Boolean $skip + * + * @return Setup + */ + public function setUp(Environment $env, FeatureNode $feature, OutlineNode $outline, $skip); + + /** + * Tests outline. + * + * @param Environment $env + * @param FeatureNode $feature + * @param OutlineNode $outline + * @param Boolean $skip + * + * @return TestResult + */ + public function test(Environment $env, FeatureNode $feature, OutlineNode $outline, $skip); + + /** + * Sets up background for a test. + * + * @param Environment $env + * @param FeatureNode $feature + * @param OutlineNode $outline + * @param Boolean $skip + * @param TestResult $result + * + * @return Teardown + */ + public function tearDown(Environment $env, FeatureNode $feature, OutlineNode $outline, $skip, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Result/DefinedStepResult.php b/vendor/behat/behat/src/Behat/Behat/Tester/Result/DefinedStepResult.php new file mode 100644 index 0000000..ba0c935 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Result/DefinedStepResult.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Result; + +use Behat\Behat\Definition\Definition; + +/** + * Represents a step result that contains step definition. + * + * @author Konstantin Kudryashov + */ +interface DefinedStepResult extends StepResult +{ + /** + * Returns found step definition. + * + * @return null|Definition + */ + public function getStepDefinition(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Result/ExecutedStepResult.php b/vendor/behat/behat/src/Behat/Behat/Tester/Result/ExecutedStepResult.php new file mode 100644 index 0000000..40633ec --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Result/ExecutedStepResult.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Result; + +use Behat\Behat\Definition\SearchResult; +use Behat\Behat\Tester\Exception\PendingException; +use Behat\Testwork\Call\CallResult; +use Behat\Testwork\Tester\Result\ExceptionResult; + +/** + * Represents an executed (successfully or not) step result. + * + * @author Konstantin Kudryashov + */ +final class ExecutedStepResult implements StepResult, DefinedStepResult, ExceptionResult +{ + /** + * @var SearchResult + */ + private $searchResult; + /** + * @var null|CallResult + */ + private $callResult; + + /** + * Initialize test result. + * + * @param SearchResult $searchResult + * @param CallResult $callResult + */ + public function __construct(SearchResult $searchResult, CallResult $callResult) + { + $this->searchResult = $searchResult; + $this->callResult = $callResult; + } + + /** + * Returns definition search result. + * + * @return SearchResult + */ + public function getSearchResult() + { + return $this->searchResult; + } + + /** + * Returns definition call result or null if no call were made. + * + * @return CallResult + */ + public function getCallResult() + { + return $this->callResult; + } + + /** + * {@inheritdoc} + */ + public function getStepDefinition() + { + return $this->searchResult->getMatchedDefinition(); + } + + /** + * {@inheritdoc} + */ + public function hasException() + { + return null !== $this->getException(); + } + + /** + * {@inheritdoc} + */ + public function getException() + { + return $this->callResult->getException(); + } + + /** + * {@inheritdoc} + */ + public function getResultCode() + { + if ($this->callResult->hasException() && $this->callResult->getException() instanceof PendingException) { + return self::PENDING; + } + + if ($this->callResult->hasException()) { + return self::FAILED; + } + + return self::PASSED; + } + + /** + * {@inheritdoc} + */ + public function isPassed() + { + return self::PASSED == $this->getResultCode(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Result/FailedStepSearchResult.php b/vendor/behat/behat/src/Behat/Behat/Tester/Result/FailedStepSearchResult.php new file mode 100644 index 0000000..94fe072 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Result/FailedStepSearchResult.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Result; + +use Behat\Behat\Definition\Exception\SearchException; +use Behat\Testwork\Tester\Result\ExceptionResult; + +/** + * Represents a step test result with a failed definition search. + * + * @author Konstantin Kudryashov + */ +final class FailedStepSearchResult implements StepResult, ExceptionResult +{ + /** + * @var SearchException + */ + private $searchException; + + /** + * Initializes result. + * + * @param SearchException $searchException + */ + public function __construct(SearchException $searchException) + { + $this->searchException = $searchException; + } + + /** + * {@inheritdoc} + */ + public function hasException() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getException() + { + return $this->searchException; + } + + /** + * {@inheritdoc} + */ + public function isPassed() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function getResultCode() + { + return self::FAILED; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Result/SkippedStepResult.php b/vendor/behat/behat/src/Behat/Behat/Tester/Result/SkippedStepResult.php new file mode 100644 index 0000000..7f63d87 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Result/SkippedStepResult.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Result; + +use Behat\Behat\Definition\SearchResult; + +/** + * Represents a skipped step result. + * + * @author Konstantin Kudryashov + */ +final class SkippedStepResult implements StepResult, DefinedStepResult +{ + /** + * @var SearchResult + */ + private $searchResult; + + /** + * Initializes step result. + * + * @param SearchResult $searchResult + */ + public function __construct(SearchResult $searchResult) + { + $this->searchResult = $searchResult; + } + + /** + * {@inheritdoc} + */ + public function getStepDefinition() + { + return $this->searchResult->getMatchedDefinition(); + } + + /** + * {@inheritdoc} + */ + public function isPassed() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function getResultCode() + { + return self::SKIPPED; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Result/StepResult.php b/vendor/behat/behat/src/Behat/Behat/Tester/Result/StepResult.php new file mode 100644 index 0000000..0a898c9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Result/StepResult.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Result; + +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Extends Testwork test result with support for undefined status. + * + * @author Konstantin Kudryashov + */ +interface StepResult extends TestResult +{ + const UNDEFINED = 30; +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Result/UndefinedStepResult.php b/vendor/behat/behat/src/Behat/Behat/Tester/Result/UndefinedStepResult.php new file mode 100644 index 0000000..1268cb7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Result/UndefinedStepResult.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Result; + +/** + * Represents an undefined step result. + * + * @author Konstantin Kudryashov + */ +final class UndefinedStepResult implements StepResult +{ + /** + * {@inheritdoc} + */ + public function isPassed() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function getResultCode() + { + return self::UNDEFINED; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeBackgroundTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeBackgroundTester.php new file mode 100644 index 0000000..976f92d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeBackgroundTester.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Runtime; + +use Behat\Behat\Tester\BackgroundTester; +use Behat\Behat\Tester\Exception\FeatureHasNoBackgroundException; +use Behat\Behat\Tester\StepContainerTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestResults; +use Behat\Testwork\Tester\Setup\SuccessfulSetup; +use Behat\Testwork\Tester\Setup\SuccessfulTeardown; + +/** + * Tester executing background tests in the runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeBackgroundTester implements BackgroundTester +{ + /** + * @var StepContainerTester + */ + private $containerTester; + + /** + * Initializes tester. + * + * @param StepContainerTester $containerTester + */ + public function __construct(StepContainerTester $containerTester) + { + $this->containerTester = $containerTester; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, $skip) + { + return new SuccessfulSetup(); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, $skip) + { + $background = $feature->getBackground(); + + if (null === $background) { + throw new FeatureHasNoBackgroundException(sprintf( + 'Feature `%s` has no background that could be tested.', + $feature->getFile() + ), $feature); + } + + $results = $this->containerTester->test($env, $feature, $background, $skip); + + return new TestResults($results); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, $skip, TestResult $result) + { + return new SuccessfulTeardown(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeFeatureTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeFeatureTester.php new file mode 100644 index 0000000..d25cd50 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeFeatureTester.php @@ -0,0 +1,100 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Runtime; + +use Behat\Behat\Tester\OutlineTester; +use Behat\Behat\Tester\ScenarioTester; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Environment\EnvironmentManager; +use Behat\Testwork\Tester\Result\IntegerTestResult; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestResults; +use Behat\Testwork\Tester\Result\TestWithSetupResult; +use Behat\Testwork\Tester\Setup\SuccessfulSetup; +use Behat\Testwork\Tester\Setup\SuccessfulTeardown; +use Behat\Testwork\Tester\SpecificationTester; + +/** + * Tester executing feature tests in the runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeFeatureTester implements SpecificationTester +{ + /** + * @var ScenarioTester + */ + private $scenarioTester; + /** + * @var OutlineTester + */ + private $outlineTester; + /** + * @var EnvironmentManager + */ + private $envManager; + + /** + * Initializes tester. + * + * @param ScenarioTester $scenarioTester + * @param OutlineTester $outlineTester + * @param EnvironmentManager $envManager + */ + public function __construct( + ScenarioTester $scenarioTester, + OutlineTester $outlineTester, + EnvironmentManager $envManager + ) { + $this->scenarioTester = $scenarioTester; + $this->outlineTester = $outlineTester; + $this->envManager = $envManager; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, $spec, $skip) + { + return new SuccessfulSetup(); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, $feature, $skip = false) + { + $results = array(); + foreach ($feature->getScenarios() as $scenario) { + $isolatedEnvironment = $this->envManager->isolateEnvironment($env, $scenario); + $tester = $scenario instanceof OutlineNode ? $this->outlineTester : $this->scenarioTester; + + $setup = $tester->setUp($isolatedEnvironment, $feature, $scenario, $skip); + $localSkip = !$setup->isSuccessful() || $skip; + $testResult = $tester->test($isolatedEnvironment, $feature, $scenario, $localSkip); + $teardown = $tester->tearDown($isolatedEnvironment, $feature, $scenario, $localSkip, $testResult); + + $integerResult = new IntegerTestResult($testResult->getResultCode()); + $results[] = new TestWithSetupResult($setup, $integerResult, $teardown); + } + + return new TestResults($results); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, $spec, $skip, TestResult $result) + { + return new SuccessfulTeardown(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeOutlineTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeOutlineTester.php new file mode 100644 index 0000000..1c1c38b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeOutlineTester.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Runtime; + +use Behat\Behat\Tester\OutlineTester; +use Behat\Behat\Tester\ScenarioTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\IntegerTestResult; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestResults; +use Behat\Testwork\Tester\Result\TestWithSetupResult; +use Behat\Testwork\Tester\Setup\SuccessfulSetup; +use Behat\Testwork\Tester\Setup\SuccessfulTeardown; + +/** + * Tester executing outline tests in the runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeOutlineTester implements OutlineTester +{ + /** + * @var ScenarioTester + */ + private $scenarioTester; + + /** + * Initializes tester. + * + * @param ScenarioTester $scenarioTester + */ + public function __construct(ScenarioTester $scenarioTester) + { + $this->scenarioTester = $scenarioTester; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, OutlineNode $outline, $skip) + { + return new SuccessfulSetup(); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, OutlineNode $outline, $skip = false) + { + $results = array(); + foreach ($outline->getExamples() as $example) { + $setup = $this->scenarioTester->setUp($env, $feature, $example, $skip); + $localSkip = !$setup->isSuccessful() || $skip; + $testResult = $this->scenarioTester->test($env, $feature, $example, $localSkip); + $teardown = $this->scenarioTester->tearDown($env, $feature, $example, $localSkip, $testResult); + + $integerResult = new IntegerTestResult($testResult->getResultCode()); + $results[] = new TestWithSetupResult($setup, $integerResult, $teardown); + } + + return new TestResults($results); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, OutlineNode $outline, $skip, TestResult $result) + { + return new SuccessfulTeardown(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeScenarioTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeScenarioTester.php new file mode 100644 index 0000000..7ab11a0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeScenarioTester.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Runtime; + +use Behat\Behat\Tester\BackgroundTester; +use Behat\Behat\Tester\StepContainerTester; +use Behat\Behat\Tester\ScenarioTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface as Scenario; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\IntegerTestResult; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestResults; +use Behat\Testwork\Tester\Result\TestWithSetupResult; +use Behat\Testwork\Tester\Setup\SuccessfulSetup; +use Behat\Testwork\Tester\Setup\SuccessfulTeardown; + +/** + * Tester executing scenario or example tests in the runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeScenarioTester implements ScenarioTester +{ + /** + * @var StepContainerTester + */ + private $containerTester; + /** + * @var BackgroundTester + */ + private $backgroundTester; + + /** + * Initializes tester. + * + * @param StepContainerTester $containerTester + * @param BackgroundTester $backgroundTester + */ + public function __construct(StepContainerTester $containerTester, BackgroundTester $backgroundTester) + { + $this->containerTester = $containerTester; + $this->backgroundTester = $backgroundTester; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, Scenario $example, $skip) + { + return new SuccessfulSetup(); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, Scenario $scenario, $skip = false) + { + $results = array(); + + if ($feature->hasBackground()) { + $backgroundResult = $this->testBackground($env, $feature, $skip); + $skip = !$backgroundResult->isPassed() || $skip; + + $results[] = $backgroundResult; + } + + $results = array_merge($results, $this->containerTester->test($env, $feature, $scenario, $skip)); + + return new TestResults($results); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, Scenario $scenario, $skip, TestResult $result) + { + return new SuccessfulTeardown(); + } + + /** + * Tests background of the provided feature against provided environment. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Boolean $skip + * + * @return TestResult + */ + private function testBackground(Environment $env, FeatureNode $feature, $skip) + { + $setup = $this->backgroundTester->setUp($env, $feature, $skip); + $skipSetup = !$setup->isSuccessful() || $skip; + $testResult = $this->backgroundTester->test($env, $feature, $skipSetup); + $teardown = $this->backgroundTester->tearDown($env, $feature, $skipSetup, $testResult); + + $integerResult = new IntegerTestResult($testResult->getResultCode()); + + return new TestWithSetupResult($setup, $integerResult, $teardown); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeStepTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeStepTester.php new file mode 100644 index 0000000..7031eec --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeStepTester.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\Runtime; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Definition\DefinitionFinder; +use Behat\Behat\Definition\Exception\SearchException; +use Behat\Behat\Definition\SearchResult; +use Behat\Behat\Tester\Result\ExecutedStepResult; +use Behat\Behat\Tester\Result\FailedStepSearchResult; +use Behat\Behat\Tester\Result\SkippedStepResult; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Behat\Tester\Result\UndefinedStepResult; +use Behat\Behat\Tester\StepTester; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Setup\SuccessfulSetup; +use Behat\Testwork\Tester\Setup\SuccessfulTeardown; + +/** + * Tester executing step tests in the runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeStepTester implements StepTester +{ + /** + * @var DefinitionFinder + */ + private $definitionFinder; + /** + * @var CallCenter + */ + private $callCenter; + + /** + * Initialize tester. + * + * @param DefinitionFinder $definitionFinder + * @param CallCenter $callCenter + */ + public function __construct(DefinitionFinder $definitionFinder, CallCenter $callCenter) + { + $this->definitionFinder = $definitionFinder; + $this->callCenter = $callCenter; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, StepNode $step, $skip) + { + return new SuccessfulSetup(); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, StepNode $step, $skip = false) + { + try { + $search = $this->searchDefinition($env, $feature, $step); + $result = $this->testDefinition($env, $feature, $step, $search, $skip); + } catch (SearchException $exception) { + $result = new FailedStepSearchResult($exception); + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, StepNode $step, $skip, StepResult $result) + { + return new SuccessfulTeardown(); + } + + /** + * Searches for a definition. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + * + * @return SearchResult + */ + private function searchDefinition(Environment $env, FeatureNode $feature, StepNode $step) + { + return $this->definitionFinder->findDefinition($env, $feature, $step); + } + + /** + * Tests found definition. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + * @param SearchResult $search + * @param Boolean $skip + * + * @return StepResult + */ + private function testDefinition(Environment $env, FeatureNode $feature, StepNode $step, SearchResult $search, $skip) + { + if (!$search->hasMatch()) { + return new UndefinedStepResult(); + } + + if ($skip) { + return new SkippedStepResult($search); + } + + $call = $this->createDefinitionCall($env, $feature, $search, $step); + $result = $this->callCenter->makeCall($call); + + return new ExecutedStepResult($search, $result); + } + + /** + * Creates definition call. + * + * @param Environment $env + * @param FeatureNode $feature + * @param SearchResult $search + * @param StepNode $step + * + * @return DefinitionCall + */ + private function createDefinitionCall(Environment $env, FeatureNode $feature, SearchResult $search, StepNode $step) + { + $definition = $search->getMatchedDefinition(); + $arguments = $search->getMatchedArguments(); + + return new DefinitionCall($env, $feature, $step, $definition, $arguments); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/ScenarioTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/ScenarioTester.php new file mode 100644 index 0000000..2fd2494 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/ScenarioTester.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface as Scenario; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Prepares and tests provided scenario object against provided environment. + * + * @author Konstantin Kudryashov + */ +interface ScenarioTester +{ + /** + * Sets up example for a test. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Scenario $scenario + * @param Boolean $skip + * + * @return Setup + */ + public function setUp(Environment $env, FeatureNode $feature, Scenario $scenario, $skip); + + /** + * Tests example. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Scenario $scenario + * @param Boolean $skip + * + * @return TestResult + */ + public function test(Environment $env, FeatureNode $feature, Scenario $scenario, $skip); + + /** + * Tears down example after a test. + * + * @param Environment $env + * @param FeatureNode $feature + * @param Scenario $scenario + * @param Boolean $skip + * @param TestResult $result + * + * @return Teardown + */ + public function tearDown(Environment $env, FeatureNode $feature, Scenario $scenario, $skip, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/ServiceContainer/TesterExtension.php b/vendor/behat/behat/src/Behat/Behat/Tester/ServiceContainer/TesterExtension.php new file mode 100644 index 0000000..16e4e47 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/ServiceContainer/TesterExtension.php @@ -0,0 +1,297 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester\ServiceContainer; + +use Behat\Behat\Definition\ServiceContainer\DefinitionExtension; +use Behat\Testwork\Call\ServiceContainer\CallExtension; +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\Environment\ServiceContainer\EnvironmentExtension; +use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension; +use Behat\Testwork\Exception\ServiceContainer\ExceptionExtension; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Tester\ServiceContainer\TesterExtension as BaseExtension; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides gherkin testers. + * + * @author Konstantin Kudryashov + */ +class TesterExtension extends BaseExtension +{ + /* + * Available services + */ + const SCENARIO_TESTER_ID = 'tester.scenario'; + const OUTLINE_TESTER_ID = 'tester.outline'; + const EXAMPLE_TESTER_ID = 'tester.example'; + const BACKGROUND_TESTER_ID = 'tester.background'; + const STEP_TESTER_ID = 'tester.step'; + + /** + * Available extension points + */ + const SCENARIO_TESTER_WRAPPER_TAG = 'tester.scenario.wrapper'; + const OUTLINE_TESTER_WRAPPER_TAG = 'tester.outline.wrapper'; + const EXAMPLE_TESTER_WRAPPER_TAG = 'tester.example.wrapper'; + const BACKGROUND_TESTER_WRAPPER_TAG = 'tester.background.wrapper'; + const STEP_TESTER_WRAPPER_TAG = 'tester.step.wrapper'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + + parent::__construct($this->processor); + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + parent::configure($builder); + + $builder + ->children() + ->scalarNode('rerun_cache') + ->info('Sets the rerun cache path') + ->defaultValue( + is_writable(sys_get_temp_dir()) + ? sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'behat_rerun_cache' + : null + ) + ->end() + ->end() + ; + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + parent::load($container, $config); + + $this->loadRerunController($container, $config['rerun_cache']); + $this->loadPendingExceptionStringer($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + parent::process($container); + + $this->processScenarioTesterWrappers($container); + $this->processOutlineTesterWrappers($container); + $this->processExampleTesterWrappers($container); + $this->processBackgroundTesterWrappers($container); + $this->processStepTesterWrappers($container); + } + + /** + * Loads specification tester. + * + * @param ContainerBuilder $container + */ + protected function loadSpecificationTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Tester\Runtime\RuntimeFeatureTester', array( + new Reference(self::SCENARIO_TESTER_ID), + new Reference(self::OUTLINE_TESTER_ID), + new Reference(EnvironmentExtension::MANAGER_ID) + )); + $container->setDefinition(self::SPECIFICATION_TESTER_ID, $definition); + + $this->loadScenarioTester($container); + $this->loadOutlineTester($container); + $this->loadBackgroundTester($container); + $this->loadStepTester($container); + } + + /** + * Loads scenario tester. + * + * @param ContainerBuilder $container + */ + protected function loadScenarioTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Tester\StepContainerTester', array( + new Reference(self::STEP_TESTER_ID) + )); + $container->setDefinition('tester.step_container', $definition); + + $definition = new Definition('Behat\Behat\Tester\Runtime\RuntimeScenarioTester', array( + new Reference('tester.step_container'), + new Reference(self::BACKGROUND_TESTER_ID) + + )); + $container->setDefinition(self::SCENARIO_TESTER_ID, $definition); + } + + /** + * Loads outline tester. + * + * @param ContainerBuilder $container + */ + protected function loadOutlineTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Tester\Runtime\RuntimeOutlineTester', array( + new Reference(self::EXAMPLE_TESTER_ID) + )); + $container->setDefinition(self::OUTLINE_TESTER_ID, $definition); + + $this->loadExampleTester($container); + } + + /** + * Loads example tester. + * + * @param ContainerBuilder $container + */ + protected function loadExampleTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Tester\StepContainerTester', array( + new Reference(self::STEP_TESTER_ID) + )); + $container->setDefinition('tester.step_container', $definition); + + $definition = new Definition('Behat\Behat\Tester\Runtime\RuntimeScenarioTester', array( + new Reference('tester.step_container'), + new Reference(self::BACKGROUND_TESTER_ID) + )); + $container->setDefinition(self::EXAMPLE_TESTER_ID, $definition); + } + + /** + * Loads background tester. + * + * @param ContainerBuilder $container + */ + protected function loadBackgroundTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Tester\StepContainerTester', array( + new Reference(self::STEP_TESTER_ID) + )); + $container->setDefinition('tester.step_container', $definition); + + $definition = new Definition('Behat\Behat\Tester\Runtime\RuntimeBackgroundTester', array( + new Reference('tester.step_container') + )); + $container->setDefinition(self::BACKGROUND_TESTER_ID, $definition); + } + + /** + * Loads step tester. + * + * @param ContainerBuilder $container + */ + protected function loadStepTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Tester\Runtime\RuntimeStepTester', array( + new Reference(DefinitionExtension::FINDER_ID), + new Reference(CallExtension::CALL_CENTER_ID) + )); + $container->setDefinition(self::STEP_TESTER_ID, $definition); + } + + /** + * Loads rerun controller. + * + * @param ContainerBuilder $container + * @param null|string $cachePath + */ + protected function loadRerunController(ContainerBuilder $container, $cachePath) + { + $definition = new Definition('Behat\Behat\Tester\Cli\RerunController', array( + new Reference(EventDispatcherExtension::DISPATCHER_ID), + $cachePath + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 200)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.rerun', $definition); + } + + /** + * Loads pending exception stringer. + * + * @param ContainerBuilder $container + */ + protected function loadPendingExceptionStringer(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Tester\Exception\Stringer\PendingExceptionStringer'); + $definition->addTag(ExceptionExtension::STRINGER_TAG); + $container->setDefinition(ExceptionExtension::STRINGER_TAG . '.pending', $definition); + } + + /** + * Processes all registered scenario tester wrappers. + * + * @param ContainerBuilder $container + */ + protected function processScenarioTesterWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::SCENARIO_TESTER_ID, self::SCENARIO_TESTER_WRAPPER_TAG); + } + + /** + * Processes all registered outline tester wrappers. + * + * @param ContainerBuilder $container + */ + protected function processOutlineTesterWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::OUTLINE_TESTER_ID, self::OUTLINE_TESTER_WRAPPER_TAG); + } + + /** + * Processes all registered example tester wrappers. + * + * @param ContainerBuilder $container + */ + protected function processExampleTesterWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::EXAMPLE_TESTER_ID, self::EXAMPLE_TESTER_WRAPPER_TAG); + } + + /** + * Processes all registered background tester wrappers. + * + * @param ContainerBuilder $container + */ + protected function processBackgroundTesterWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::BACKGROUND_TESTER_ID, self::BACKGROUND_TESTER_WRAPPER_TAG); + } + + /** + * Processes all registered step tester wrappers. + * + * @param ContainerBuilder $container + */ + protected function processStepTesterWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::STEP_TESTER_ID, self::STEP_TESTER_WRAPPER_TAG); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/StepContainerTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/StepContainerTester.php new file mode 100644 index 0000000..543e133 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/StepContainerTester.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepContainerInterface; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\IntegerTestResult; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestWithSetupResult; + +/** + * Tests provided collection of steps against provided environment. + * + * @author Konstantin Kudryashov + */ +final class StepContainerTester +{ + /** + * @var StepTester + */ + private $stepTester; + + /** + * Initializes tester. + * + * @param StepTester $stepTester + */ + public function __construct(StepTester $stepTester) + { + $this->stepTester = $stepTester; + } + + /** + * Tests container. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepContainerInterface $container + * @param Boolean $skip + * + * @return TestResult[] + */ + public function test(Environment $env, FeatureNode $feature, StepContainerInterface $container, $skip) + { + $results = array(); + foreach ($container->getSteps() as $step) { + $setup = $this->stepTester->setUp($env, $feature, $step, $skip); + $skipSetup = !$setup->isSuccessful() || $skip; + + $testResult = $this->stepTester->test($env, $feature, $step, $skipSetup); + $skip = !$testResult->isPassed() || $skip; + + $teardown = $this->stepTester->tearDown($env, $feature, $step, $skipSetup, $testResult); + $skip = $skip || $skipSetup || !$teardown->isSuccessful(); + + $integerResult = new IntegerTestResult($testResult->getResultCode()); + $results[] = new TestWithSetupResult($setup, $integerResult, $teardown); + } + + return $results; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Tester/StepTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/StepTester.php new file mode 100644 index 0000000..d5c995c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/StepTester.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Tester; + +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Prepares and tests provided step object against provided environment. + * + * @author Konstantin Kudryashov + */ +interface StepTester +{ + /** + * Sets up step for a test. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + * @param Boolean $skip + * + * @return Setup + */ + public function setUp(Environment $env, FeatureNode $feature, StepNode $step, $skip); + + /** + * Tests step. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + * @param Boolean $skip + * + * @return StepResult + */ + public function test(Environment $env, FeatureNode $feature, StepNode $step, $skip); + + /** + * Tears down step after a test. + * + * @param Environment $env + * @param FeatureNode $feature + * @param StepNode $step + * @param Boolean $skip + * @param StepResult $result + * + * @return Teardown + */ + public function tearDown(Environment $env, FeatureNode $feature, StepNode $step, $skip, StepResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Call/Filter/DefinitionArgumentsTransformer.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Call/Filter/DefinitionArgumentsTransformer.php new file mode 100644 index 0000000..d6cde91 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Call/Filter/DefinitionArgumentsTransformer.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\Call\Filter; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Transformation\Exception\UnsupportedCallException; +use Behat\Behat\Transformation\Transformer\ArgumentTransformer; +use Behat\Testwork\Call\Call; +use Behat\Testwork\Call\Filter\CallFilter; + +/** + * Handles definition calls by intercepting them and transforming their arguments using transformations. + * + * @author Konstantin Kudryashov + */ +final class DefinitionArgumentsTransformer implements CallFilter +{ + /** + * @var ArgumentTransformer[] + */ + private $argumentTransformers = array(); + + /** + * Registers new argument transformer. + * + * @param ArgumentTransformer $transformer + */ + public function registerArgumentTransformer(ArgumentTransformer $transformer) + { + $this->argumentTransformers[] = $transformer; + } + + /** + * {@inheritdoc} + */ + public function supportsCall(Call $call) + { + return $call instanceof DefinitionCall; + } + + /** + * {@inheritdoc} + */ + public function filterCall(Call $definitionCall) + { + if (!$definitionCall instanceof DefinitionCall) { + throw new UnsupportedCallException(sprintf( + 'DefinitionArgumentTransformer can not filter `%s` call.', + get_class($definitionCall) + ), $definitionCall); + } + + $newArguments = array(); + $transformed = false; + foreach ($definitionCall->getArguments() as $index => $value) { + $newValue = $this->transformArgument($definitionCall, $index, $value); + + if ($newValue !== $value) { + $transformed = true; + } + + $newArguments[$index] = $newValue; + } + + if (!$transformed) { + return $definitionCall; + } + + return new DefinitionCall( + $definitionCall->getEnvironment(), + $definitionCall->getFeature(), + $definitionCall->getStep(), + $definitionCall->getCallee(), + $newArguments, + $definitionCall->getErrorReportingLevel() + ); + } + + /** + * Transforms call argument using registered transformers. + * + * @param DefinitionCall $definitionCall + * @param integer|string $index + * @param mixed $value + * + * @return mixed + */ + private function transformArgument(DefinitionCall $definitionCall, $index, $value) + { + foreach ($this->argumentTransformers as $transformer) { + if (!$transformer->supportsDefinitionAndArgument($definitionCall, $index, $value)) { + continue; + } + + return $transformer->transformArgument($definitionCall, $index, $value); + } + + return $value; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Call/RuntimeTransformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Call/RuntimeTransformation.php new file mode 100644 index 0000000..fb6bf0d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Call/RuntimeTransformation.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\Call; + +use Behat\Behat\Transformation\Transformation; +use Behat\Testwork\Call\RuntimeCallee; + +/** + * Transformation that is created and executed in the runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeTransformation extends RuntimeCallee implements Transformation +{ + /** + * @var string + */ + private $pattern; + + /** + * Initializes transformation. + * + * @param string $pattern + * @param callable $callable + * @param null|string $description + */ + public function __construct($pattern, $callable, $description = null) + { + $this->pattern = $pattern; + + parent::__construct($callable, $description); + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return 'Transform ' . $this->getPattern(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Call/TransformationCall.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Call/TransformationCall.php new file mode 100644 index 0000000..8b57d0b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Call/TransformationCall.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\Call; + +use Behat\Behat\Definition\Definition; +use Behat\Behat\Transformation\Transformation; +use Behat\Testwork\Environment\Call\EnvironmentCall; +use Behat\Testwork\Environment\Environment; + +/** + * Call extended with transformation information. + * + * @author Konstantin Kudryashov + */ +final class TransformationCall extends EnvironmentCall +{ + /** + * @var Definition + */ + private $definition; + + /** + * Initializes call. + * + * @param Environment $environment + * @param Definition $definition + * @param Transformation $transformation + * @param array $arguments + */ + public function __construct( + Environment $environment, + Definition $definition, + Transformation $transformation, + array $arguments + ) { + parent::__construct($environment, $transformation, $arguments); + + $this->definition = $definition; + } + + /** + * Returns transformed definition. + * + * @return Definition + */ + public function getDefinition() + { + return $this->definition; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Context/Annotation/TransformationAnnotationReader.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Context/Annotation/TransformationAnnotationReader.php new file mode 100644 index 0000000..27905b6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Context/Annotation/TransformationAnnotationReader.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\Context\Annotation; + +use Behat\Behat\Context\Annotation\AnnotationReader; +use Behat\Behat\Transformation\Call\RuntimeTransformation; +use ReflectionMethod; + +/** + * Step transformation annotation reader. + * + * Reads step transformations from a context method annotation. + * + * @author Konstantin Kudryashov + */ +class TransformationAnnotationReader implements AnnotationReader +{ + /** + * @var string + */ + private static $regex = '/^\@transform\s+(.+)$/i'; + + /** + * Loads step callees (if exist) associated with specific method. + * + * @param string $contextClass + * @param ReflectionMethod $method + * @param string $docLine + * @param string $description + * + * @return null|RuntimeTransformation + */ + public function readCallee($contextClass, ReflectionMethod $method, $docLine, $description) + { + if (!preg_match(self::$regex, $docLine, $match)) { + return null; + } + + $pattern = $match[1]; + $callable = array($contextClass, $method->getName()); + + return new RuntimeTransformation($pattern, $callable, $description); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Exception/TransformationException.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Exception/TransformationException.php new file mode 100644 index 0000000..f5aef3e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Exception/TransformationException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\Exception; + +use Behat\Testwork\Exception\TestworkException; + +/** + * Represents an exception caused by a transformation. + * + * @author Konstantin Kudryashov + */ +interface TransformationException extends TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Exception/UnsupportedCallException.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Exception/UnsupportedCallException.php new file mode 100644 index 0000000..40d0ab2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Exception/UnsupportedCallException.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\Exception; + +use Behat\Testwork\Call\Call; +use InvalidArgumentException; + +/** + * Represents an exception caused by an attempt to filter an unsupported call. + * + * @author Konstantin Kudryashov + */ +final class UnsupportedCallException extends InvalidArgumentException implements TransformationException +{ + /** + * @var Call + */ + private $call; + + /** + * Initializes exception. + * + * @param string $message + * @param Call $call + */ + public function __construct($message, Call $call) + { + parent::__construct($message); + + $this->call = $call; + } + + /** + * Returns a call that caused exception. + * + * @return Call + */ + public function getCall() + { + return $this->call; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/ServiceContainer/TransformationExtension.php b/vendor/behat/behat/src/Behat/Behat/Transformation/ServiceContainer/TransformationExtension.php new file mode 100644 index 0000000..f322ee9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/ServiceContainer/TransformationExtension.php @@ -0,0 +1,177 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\ServiceContainer; + +use Behat\Behat\Context\ServiceContainer\ContextExtension; +use Behat\Behat\Definition\ServiceContainer\DefinitionExtension; +use Behat\Testwork\Call\ServiceContainer\CallExtension; +use Behat\Testwork\Environment\ServiceContainer\EnvironmentExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides definition arguments transformation functionality. + * + * @author Konstantin Kudryashov + */ +class TransformationExtension implements Extension +{ + /* + * Available services + */ + const REPOSITORY_ID = 'transformation.repository'; + + /* + * Available extension points + */ + const ARGUMENT_TRANSFORMER_TAG = 'transformation.argument_transformer'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ?: new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'transformations'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadDefinitionArgumentsTransformer($container); + $this->loadDefaultTransformers($container); + $this->loadAnnotationReader($container); + $this->loadRepository($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processArgumentsTransformers($container); + } + + /** + * Loads definition arguments transformer. + * + * @param ContainerBuilder $container + */ + protected function loadDefinitionArgumentsTransformer(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Transformation\Call\Filter\DefinitionArgumentsTransformer'); + $definition->addTag(CallExtension::CALL_FILTER_TAG, array('priority' => 200)); + $container->setDefinition($this->getDefinitionArgumentTransformerId(), $definition); + } + + /** + * Loads default transformers. + * + * @param ContainerBuilder $container + */ + protected function loadDefaultTransformers(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Transformation\Transformer\RepositoryArgumentTransformer', array( + new Reference(self::REPOSITORY_ID), + new Reference(CallExtension::CALL_CENTER_ID), + new Reference(DefinitionExtension::PATTERN_TRANSFORMER_ID), + new Reference(TranslatorExtension::TRANSLATOR_ID) + )); + $definition->addTag(self::ARGUMENT_TRANSFORMER_TAG, array('priority' => 50)); + $container->setDefinition(self::ARGUMENT_TRANSFORMER_TAG . '.repository', $definition); + } + + /** + * Loads transformation context annotation reader. + * + * @param ContainerBuilder $container + */ + protected function loadAnnotationReader(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Transformation\Context\Annotation\TransformationAnnotationReader'); + $definition->addTag(ContextExtension::ANNOTATION_READER_TAG, array('priority' => 50)); + $container->setDefinition(ContextExtension::ANNOTATION_READER_TAG . '.transformation', $definition); + } + + /** + * Loads transformations repository. + * + * @param ContainerBuilder $container + */ + protected function loadRepository(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Transformation\TransformationRepository', array( + new Reference(EnvironmentExtension::MANAGER_ID) + )); + $container->setDefinition(self::REPOSITORY_ID, $definition); + } + + /** + * Processes all available argument transformers. + * + * @param ContainerBuilder $container + */ + protected function processArgumentsTransformers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::ARGUMENT_TRANSFORMER_TAG); + $definition = $container->getDefinition($this->getDefinitionArgumentTransformerId()); + + foreach ($references as $reference) { + $definition->addMethodCall('registerArgumentTransformer', array($reference)); + } + } + + /** + * Returns definition argument transformer service id. + * + * @return string + */ + protected function getDefinitionArgumentTransformerId() + { + return CallExtension::CALL_FILTER_TAG . '.definition_argument_transformer'; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation.php new file mode 100644 index 0000000..4fa1ef5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation; + +use Behat\Testwork\Call\Callee; + +/** + * Step transformation interface. + * + * @author Konstantin Kudryashov + */ +interface Transformation extends Callee +{ + /** + * Returns transformation pattern exactly as it was defined. + * + * @return string + */ + public function getPattern(); + + /** + * Represents transformation as a string. + * + * @return string + */ + public function __toString(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/TransformationRepository.php b/vendor/behat/behat/src/Behat/Behat/Transformation/TransformationRepository.php new file mode 100644 index 0000000..2fb0ff5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/TransformationRepository.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation; + +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Environment\EnvironmentManager; + +/** + * Provides transformations using environment manager. + * + * @author Konstantin Kudryashov + */ +final class TransformationRepository +{ + /** + * @var EnvironmentManager + */ + private $environmentManager; + + /** + * Initializes repository. + * + * @param EnvironmentManager $environmentManager + */ + public function __construct(EnvironmentManager $environmentManager) + { + $this->environmentManager = $environmentManager; + } + + /** + * Returns all available definitions for a specific environment. + * + * @param Environment $environment + * + * @return Transformation[] + */ + public function getEnvironmentTransformations(Environment $environment) + { + return array_filter( + $this->environmentManager->readEnvironmentCallees($environment), + function (Callee $callee) { + return $callee instanceof Transformation; + } + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Transformer/ArgumentTransformer.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformer/ArgumentTransformer.php new file mode 100644 index 0000000..4773960 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformer/ArgumentTransformer.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\Transformer; + +use Behat\Behat\Definition\Call\DefinitionCall; + +/** + * Transforms a single argument value. + * + * @author Konstantin Kudryashov + */ +interface ArgumentTransformer +{ + /** + * Checks if transformer supports argument. + * + * @param DefinitionCall $definitionCall + * @param integer|string $argumentIndex + * @param mixed $argumentValue + * + * @return Boolean + */ + public function supportsDefinitionAndArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue); + + /** + * Transforms argument value using transformation and returns a new one. + * + * @param DefinitionCall $definitionCall + * @param integer|string $argumentIndex + * @param mixed $argumentValue + * + * @return mixed + */ + public function transformArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Transformer/RepositoryArgumentTransformer.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformer/RepositoryArgumentTransformer.php new file mode 100644 index 0000000..602738b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformer/RepositoryArgumentTransformer.php @@ -0,0 +1,287 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\Transformer; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Definition\Pattern\PatternTransformer; +use Behat\Behat\Transformation\Call\TransformationCall; +use Behat\Behat\Transformation\Transformation; +use Behat\Behat\Transformation\TransformationRepository; +use Behat\Gherkin\Node\ArgumentInterface; +use Behat\Gherkin\Node\TableNode; +use Behat\Testwork\Call\CallCenter; +use Exception; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Argument transformer based on transformations repository. + * + * @author Konstantin Kudryashov + */ +final class RepositoryArgumentTransformer implements ArgumentTransformer +{ + /** + * @var TransformationRepository + */ + private $repository; + /** + * @var CallCenter + */ + private $callCenter; + /** + * @var PatternTransformer + */ + private $patternTransformer; + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * Initializes transformer. + * + * @param TransformationRepository $repository + * @param CallCenter $callCenter + * @param PatternTransformer $patternTransformer + * @param TranslatorInterface $translator + */ + public function __construct( + TransformationRepository $repository, + CallCenter $callCenter, + PatternTransformer $patternTransformer, + TranslatorInterface $translator + ) { + $this->repository = $repository; + $this->callCenter = $callCenter; + $this->patternTransformer = $patternTransformer; + $this->translator = $translator; + } + + /** + * {@inheritdoc} + */ + public function supportsDefinitionAndArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function transformArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + $environment = $definitionCall->getEnvironment(); + $transformations = $this->repository->getEnvironmentTransformations($environment); + + $newValue = $argumentValue; + foreach ($transformations as $transformation) { + $newValue = $this->transform($definitionCall, $transformation, $argumentIndex, $newValue); + } + + return $newValue; + } + + /** + * Transforms argument value using registered transformers. + * + * @param Transformation $transformation + * @param DefinitionCall $definitionCall + * @param integer|string $index + * @param mixed $value + * + * @return mixed + */ + private function transform(DefinitionCall $definitionCall, Transformation $transformation, $index, $value) + { + if (is_object($value) && !$value instanceof ArgumentInterface) { + return $value; + } + + if ($this->isApplicableTokenTransformation($transformation)) { + return $this->applyTokenTransformation($definitionCall, $transformation, $index, $value); + } + + if ($this->isApplicableTableTransformation($transformation, $value)) { + return $this->applyTableTransformation($definitionCall, $transformation, $value); + } + + if ($this->isApplicablePatternTransformation($definitionCall, $transformation, $value, $arguments)) { + return $this->applyPatternTransformation($definitionCall, $transformation, $arguments); + } + + return $value; + } + + /** + * Checks if provided transformation is token-based. + * + * @param Transformation $transformation + * + * @return Boolean + */ + private function isApplicableTokenTransformation(Transformation $transformation) + { + return 1 === preg_match('/^\:\w+$/', $transformation->getPattern()); + } + + /** + * Applies provided token transformation. + * + * @param DefinitionCall $definitionCall + * @param Transformation $transformation + * @param integer|string $index + * @param mixed $value + * + * @return mixed + */ + private function applyTokenTransformation(DefinitionCall $definitionCall, Transformation $transformation, $index, $value) + { + return $this->isArgumentIndexMatchesTokenPattern($index, $transformation->getPattern()) + ? $this->execute($definitionCall, $transformation, array($value)) + : $value; + } + + /** + * Checks if argument index matches token pattern. + * + * @param integer|string $index + * @param string $pattern + * + * @return Boolean + */ + private function isArgumentIndexMatchesTokenPattern($index, $pattern) + { + return ':' . $index === $pattern; + } + + /** + * Checks if provided transformation is applicable table transformation. + * + * @param Transformation $transformation + * @param mixed $value + * + * @return Boolean + */ + private function isApplicableTableTransformation(Transformation $transformation, $value) + { + if (!$value instanceof TableNode) { + return false; + }; + + return $transformation->getPattern() === 'table:' . implode(',', $value->getRow(0)); + } + + /** + * Applies provided table transformation. + * + * @param DefinitionCall $definitionCall + * @param Transformation $transformation + * @param mixed $value + * + * @return mixed + */ + private function applyTableTransformation(DefinitionCall $definitionCall, Transformation $transformation, $value) + { + return $this->execute($definitionCall, $transformation, array($value)); + } + + /** + * Checks if provided transformation is applicable pattern transformation. + * + * @param DefinitionCall $definitionCall + * @param Transformation|string $transformation + * @param mixed $value + * @param array $match + * + * @return Boolean + */ + private function isApplicablePatternTransformation(DefinitionCall $definitionCall, Transformation $transformation, $value, &$match) + { + $regex = $this->getRegex( + $definitionCall->getEnvironment()->getSuite()->getName(), + $transformation->getPattern(), + $definitionCall->getFeature()->getLanguage() + ); + + if (is_string($value) && preg_match($regex, $value, $match)) { + // take arguments from capture groups if there are some + if (count($match) > 1) { + $match = array_slice($match, 1); + } + + return true; + } + + return false; + } + + /** + * Returns transformation regex. + * + * @param string $assetsId + * @param string $pattern + * @param string $language + * + * @return string + */ + private function getRegex($assetsId, $pattern, $language) + { + $translatedPattern = $this->translator->trans($pattern, array(), $assetsId, $language); + if ($pattern == $translatedPattern) { + return $this->patternTransformer->transformPatternToRegex($pattern); + } + + return $this->patternTransformer->transformPatternToRegex($translatedPattern); + } + + /** + * Applies provided pattern transformation. + * + * @param DefinitionCall $definitionCall + * @param Transformation $transformation + * @param array $arguments + * + * @return mixed + */ + private function applyPatternTransformation(DefinitionCall $definitionCall, Transformation $transformation, array $arguments) + { + return $this->execute($definitionCall, $transformation, $arguments); + } + + /** + * Executes transformation. + * + * @param DefinitionCall $definitionCall + * @param Transformation $transformation + * @param array $arguments + * + * @return mixed + * + * @throws Exception If transformation call throws one + */ + private function execute(DefinitionCall $definitionCall, Transformation $transformation, array $arguments) + { + $call = new TransformationCall( + $definitionCall->getEnvironment(), + $definitionCall->getCallee(), + $transformation, + $arguments + ); + + $result = $this->callCenter->makeCall($call); + + if ($result->hasException()) { + throw $result->getException(); + } + + return $result->getReturn(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Translator/Cli/GherkinTranslationsController.php b/vendor/behat/behat/src/Behat/Behat/Translator/Cli/GherkinTranslationsController.php new file mode 100644 index 0000000..439ad09 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Translator/Cli/GherkinTranslationsController.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Translator\Cli; + +use Behat\Testwork\Cli\Controller; +use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Translation\Translator; + +/** + * Configures translator service and loads default translations. + * + * @author Konstantin Kudryashov + */ +final class GherkinTranslationsController implements Controller +{ + /** + * @var Translator + */ + private $translator; + + /** + * Initializes controller. + * + * @param Translator $translator + */ + public function __construct(Translator $translator) + { + $this->translator = $translator; + } + + /** + * {@inheritdoc} + */ + public function configure(SymfonyCommand $command) + { + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $i18nPath = dirname(dirname(dirname(dirname(dirname(__DIR__))))) . DIRECTORY_SEPARATOR . 'i18n.php'; + + foreach (require($i18nPath) as $lang => $messages) { + $this->translator->addResource('array', $messages, $lang, 'output'); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Translator/ServiceContainer/GherkinTranslationsExtension.php b/vendor/behat/behat/src/Behat/Behat/Translator/ServiceContainer/GherkinTranslationsExtension.php new file mode 100644 index 0000000..f4af2a5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Translator/ServiceContainer/GherkinTranslationsExtension.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Translator\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\Translator\ServiceContainer\TranslatorExtension; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Extends translator service with knowledge about gherkin translations. + * + * @author Konstantin Kudryashov + */ +final class GherkinTranslationsExtension implements Extension +{ + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'gherkin_translations'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadController($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + } + + /** + * Loads translator controller. + * + * @param ContainerBuilder $container + */ + private function loadController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Translator\Cli\GherkinTranslationsController', array( + new Reference(TranslatorExtension::TRANSLATOR_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 9999)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.gherkin_translations', $definition); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ApplicationFactory.php b/vendor/behat/behat/src/Behat/Testwork/ApplicationFactory.php new file mode 100644 index 0000000..ff60404 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ApplicationFactory.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork; + +use Behat\Testwork\Cli\Application; +use Behat\Testwork\ServiceContainer\Configuration\ConfigurationLoader; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; + +/** + * Defines the way application is created. + * + * Extend and implement this class to create an entry point for your framework. + * + * @author Konstantin Kudryashov + */ +abstract class ApplicationFactory +{ + /** + * Returns application name. + * + * @return string + */ + abstract protected function getName(); + + /** + * Returns current application version. + * + * @return string + */ + abstract protected function getVersion(); + + /** + * Returns list of extensions enabled by default. + * + * @return Extension[] + */ + abstract protected function getDefaultExtensions(); + + /** + * Returns the name of configuration environment variable. + * + * @return string + */ + abstract protected function getEnvironmentVariableName(); + + /** + * Returns user config path. + * + * @return null|string + */ + abstract protected function getConfigPath(); + + /** + * Creates application instance. + * + * @return Application + */ + public function createApplication() + { + $configurationLoader = $this->createConfigurationLoader(); + $extensionManager = $this->createExtensionManager(); + + return new Application($this->getName(), $this->getVersion(), $configurationLoader, $extensionManager); + } + + /** + * Creates configuration loader. + * + * @return ConfigurationLoader + */ + protected function createConfigurationLoader() + { + return new ConfigurationLoader($this->getEnvironmentVariableName(), $this->getConfigPath()); + } + + /** + * Creates extension manager. + * + * @return ExtensionManager + */ + protected function createExtensionManager() + { + return new ExtensionManager($this->getDefaultExtensions()); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Argument/ArgumentOrganiser.php b/vendor/behat/behat/src/Behat/Testwork/Argument/ArgumentOrganiser.php new file mode 100644 index 0000000..8659631 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/ArgumentOrganiser.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Argument; + +use ReflectionFunctionAbstract; + +/** + * Organises function arguments using its reflection. + * + * @author Konstantin Kudryashov + */ +interface ArgumentOrganiser +{ + /** + * Organises arguments using function reflection. + * + * @param ReflectionFunctionAbstract $function + * @param mixed[] $arguments + * + * @return mixed[] + */ + public function organiseArguments(ReflectionFunctionAbstract $function, array $arguments); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Argument/ConstructorArgumentOrganiser.php b/vendor/behat/behat/src/Behat/Testwork/Argument/ConstructorArgumentOrganiser.php new file mode 100644 index 0000000..5ab6127 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/ConstructorArgumentOrganiser.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Argument; + +use Behat\Testwork\Argument\Exception\UnknownParameterValueException; +use Behat\Testwork\Argument\Exception\UnsupportedFunctionException; +use ReflectionFunctionAbstract; +use ReflectionMethod; + +/** + * Organises constructor arguments. + * + * @author Konstantin Kudryashov + */ +final class ConstructorArgumentOrganiser implements ArgumentOrganiser +{ + /** + * @var ArgumentOrganiser + */ + private $baseOrganiser; + + /** + * Initializes organiser. + * + * @param ArgumentOrganiser $organiser + */ + public function __construct(ArgumentOrganiser $organiser) + { + $this->baseOrganiser = $organiser; + } + + /** + * {@inheritdoc} + */ + public function organiseArguments(ReflectionFunctionAbstract $constructor, array $arguments) + { + if (!$constructor instanceof ReflectionMethod) { + throw new UnsupportedFunctionException(sprintf( + 'ConstructorArgumentOrganiser can only work with ReflectionMethod, but `%s` given.', + get_class($constructor) + )); + } + + $organisedArguments = $this->baseOrganiser->organiseArguments( + $constructor, + $arguments + ); + + $this->validateArguments($constructor, $arguments, $organisedArguments); + + return $organisedArguments; + } + + /** + * Checks that all provided constructor arguments are present in the constructor. + * + * @param ReflectionMethod $constructor + * @param mixed[] $passedArguments + * @param mixed[] $organisedArguments + * + * @throws UnknownParameterValueException + */ + private function validateArguments( + ReflectionMethod $constructor, + array $passedArguments, + array $organisedArguments + ) { + foreach ($passedArguments as $key => $val) { + if (array_key_exists($key, $organisedArguments)) { + continue; + } + + throw new UnknownParameterValueException( + sprintf( + '`%s::__construct()` does not expect argument `$%s`.', + $constructor->getDeclaringClass()->getName(), + $key + ) + ); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Argument/Exception/ArgumentException.php b/vendor/behat/behat/src/Behat/Testwork/Argument/Exception/ArgumentException.php new file mode 100644 index 0000000..fdcf310 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/Exception/ArgumentException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Argument\Exception; + +use Behat\Testwork\Exception\TestworkException; + +/** + * All argument exceptions extend this interface. + * + * @author Konstantin Kudryashov + */ +interface ArgumentException extends TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Argument/Exception/UnknownParameterValueException.php b/vendor/behat/behat/src/Behat/Testwork/Argument/Exception/UnknownParameterValueException.php new file mode 100644 index 0000000..b83958b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/Exception/UnknownParameterValueException.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Argument\Exception; + +use BadMethodCallException; + +/** + * Represents an exception caused by an unknown function parameter value. + * + * Exception is thrown if provided function parameter value is unknown or missing. + * + * @author Wouter J + */ +final class UnknownParameterValueException extends BadMethodCallException implements ArgumentException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Argument/Exception/UnsupportedFunctionException.php b/vendor/behat/behat/src/Behat/Testwork/Argument/Exception/UnsupportedFunctionException.php new file mode 100644 index 0000000..688c939 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/Exception/UnsupportedFunctionException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Argument\Exception; + +use InvalidArgumentException; + +/** + * Represents an attempt to organise unsupported function arguments. + * + * @author Konstantin Kudryashov + */ +final class UnsupportedFunctionException extends InvalidArgumentException implements ArgumentException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Argument/MixedArgumentOrganiser.php b/vendor/behat/behat/src/Behat/Testwork/Argument/MixedArgumentOrganiser.php new file mode 100644 index 0000000..88ace22 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/MixedArgumentOrganiser.php @@ -0,0 +1,333 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Argument; + +use Behat\Testwork\Argument\Exception\UnknownParameterValueException; +use ReflectionFunctionAbstract; +use ReflectionMethod; +use ReflectionParameter; + +/** + * Organises function arguments using its reflection. + * + * @author Konstantin Kudryashov + */ +final class MixedArgumentOrganiser implements ArgumentOrganiser +{ + private $definedArguments = array(); + + /** + * Organises arguments using function reflection. + * + * @param ReflectionFunctionAbstract $function + * @param mixed[] $arguments + * + * @return mixed[] + */ + public function organiseArguments(ReflectionFunctionAbstract $function, array $arguments) + { + $parameters = $function->getParameters(); + $arguments = $this->prepareArguments($parameters, $arguments); + + $this->validateArguments($function, $parameters, $arguments); + + return $arguments; + } + + /** + * Prepares arguments based on provided parameters. + * + * @param ReflectionParameter[] $parameters + * @param mixed[] $arguments + * + * @return mixed[] + */ + private function prepareArguments(array $parameters, array $arguments) + { + $this->markAllArgumentsUndefined(); + + list($named, $typehinted, $numbered) = $this->splitArguments($parameters, $arguments); + + $arguments = + $this->prepareNamedArguments($parameters, $named) + + $typehinted + + $this->prepareNumberedArguments($parameters, $numbered) + + $this->prepareDefaultArguments($parameters); + + return $this->reorderArguments($parameters, $arguments); + } + + /** + * Splits arguments into three separate arrays - named, numbered and typehinted. + * + * @param ReflectionParameter[] $parameters + * @param mixed[] $arguments + * + * @return array + */ + private function splitArguments(array $parameters, array $arguments) + { + $parameterNames = array_map( + function (ReflectionParameter $parameter) { + return $parameter->getName(); + }, + $parameters + ); + + $namedArguments = array(); + $numberedArguments = array(); + $typehintedArguments = array(); + foreach ($arguments as $key => $val) { + if ($this->isStringKeyAndExistsInParameters($key, $parameterNames)) { + $namedArguments[$key] = $val; + } elseif ($num = $this->getParameterNumberWithTypehintingValue($parameters, $val)) { + $typehintedArguments[$num] = $val; + } else { + $numberedArguments[] = $val; + } + } + + return array($namedArguments, $typehintedArguments, $numberedArguments); + } + + /** + * Checks that provided argument key is a string and it matches some parameter name. + * + * @param mixed $argumentKey + * @param string[] $parameterNames + * + * @return Boolean + */ + private function isStringKeyAndExistsInParameters($argumentKey, $parameterNames) + { + return is_string($argumentKey) && in_array($argumentKey, $parameterNames); + } + + /** + * Tries to find a parameter number, which typehints provided value. + * + * @param ReflectionParameter[] $parameters + * @param mixed $value + * + * @return null|integer + */ + private function getParameterNumberWithTypehintingValue(array $parameters, $value) + { + if (!is_object($value)) { + return null; + } + + foreach ($parameters as $num => $parameter) { + if ($this->isValueMatchesTypehintedParameter($value, $parameter)) { + return $num; + } + } + + return null; + } + + /** + * Checks if value matches typehint of provided parameter. + * + * @param object $value + * @param ReflectionParameter $parameter + * + * @return Boolean + */ + private function isValueMatchesTypehintedParameter($value, ReflectionParameter $parameter) + { + $typehintRefl = $parameter->getClass(); + + return $typehintRefl && $typehintRefl->isInstance($value); + } + + /** + * Captures argument values based on their respective names. + * + * @param ReflectionParameter[] $parameters + * @param mixed[] $namedArguments + * + * @return mixed[] + */ + private function prepareNamedArguments(array $parameters, array $namedArguments) + { + $arguments = array(); + + foreach ($parameters as $num => $parameter) { + $name = $parameter->getName(); + + if (array_key_exists($name, $namedArguments)) { + $arguments[$name] = $namedArguments[$name]; + $this->markArgumentDefined($num); + } + } + + return $arguments; + } + + /** + * Captures argument values for undefined arguments based on their respective numbers. + * + * @param ReflectionParameter[] $parameters + * @param mixed[] $numberedArguments + * + * @return mixed[] + */ + private function prepareNumberedArguments(array $parameters, array $numberedArguments) + { + $arguments = array(); + + $increment = 0; + foreach ($parameters as $num => $parameter) { + if ($this->isArgumentDefined($num)) { + continue; + } + + if (array_key_exists($increment, $numberedArguments)) { + $arguments[$num] = $numberedArguments[$increment++]; + $this->markArgumentDefined($num); + } + } + + return $arguments; + } + + /** + * Captures argument values for undefined arguments based on parameters defaults. + * + * @param ReflectionParameter[] $parameters + * + * @return mixed[] + */ + private function prepareDefaultArguments(array $parameters) + { + $arguments = array(); + + foreach ($parameters as $num => $parameter) { + if ($this->isArgumentDefined($num)) { + continue; + } + + if ($parameter->isDefaultValueAvailable()) { + $arguments[$num] = $parameter->getDefaultValue(); + $this->markArgumentDefined($num); + } + } + + return $arguments; + } + + /** + * Reorders arguments based on their respective parameters order. + * + * @param ReflectionParameter[] $parameters + * @param array $arguments + * + * @return mixed[] + */ + private function reorderArguments(array $parameters, array $arguments) + { + $orderedArguments = array(); + + foreach ($parameters as $num => $parameter) { + $name = $parameter->getName(); + + if (array_key_exists($num, $arguments)) { + $orderedArguments[$num] = $arguments[$num]; + } elseif (array_key_exists($name, $arguments)) { + $orderedArguments[$name] = $arguments[$name]; + } + } + + return $orderedArguments; + } + + /** + * Validates that all arguments are in place, throws exception otherwise. + * + * @param ReflectionFunctionAbstract $function + * @param ReflectionParameter[] $parameters + * @param mixed[] $arguments + * + * @throws UnknownParameterValueException + */ + private function validateArguments( + ReflectionFunctionAbstract $function, + array $parameters, + array $arguments + ) { + foreach ($parameters as $num => $parameter) { + $name = $parameter->getName(); + + if (array_key_exists($num, $arguments) || array_key_exists($name, $arguments)) { + continue; + } + + throw new UnknownParameterValueException(sprintf( + 'Can not find a matching value for an argument `$%s` of the method `%s`.', + $name, + $this->getFunctionPath($function) + )); + } + } + + /** + * Returns function path for a provided reflection. + * + * @param ReflectionFunctionAbstract $function + * + * @return string + */ + private function getFunctionPath(ReflectionFunctionAbstract $function) + { + if ($function instanceof ReflectionMethod) { + return sprintf( + '%s::%s()', + $function->getDeclaringClass()->getName(), + $function->getName() + ); + } + + return sprintf('%s()', $function->getName()); + } + + /** + * Marks arguments at all positions as undefined. + * + * This is used to share state between get*Arguments() methods. + */ + private function markAllArgumentsUndefined() + { + $this->definedArguments = array(); + } + + /** + * Marks an argument at provided position as defined. + * + * @param integer $position + */ + private function markArgumentDefined($position) + { + $this->definedArguments[$position] = true; + } + + /** + * Checks if an argument at provided position is defined. + * + * @param integer $position + * + * @return Boolean + */ + private function isArgumentDefined($position) + { + return isset($this->definedArguments[$position]); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Argument/PregMatchArgumentOrganiser.php b/vendor/behat/behat/src/Behat/Testwork/Argument/PregMatchArgumentOrganiser.php new file mode 100644 index 0000000..2fb0535 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/PregMatchArgumentOrganiser.php @@ -0,0 +1,93 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Argument; + +use ReflectionFunctionAbstract; + +/** + * Organises arguments coming from preg_match results. + * + * @author Konstantin Kudryashov + */ +final class PregMatchArgumentOrganiser implements ArgumentOrganiser +{ + /** + * @var ArgumentOrganiser + */ + private $baseOrganiser; + + /** + * Initialises organiser. + * + * @param ArgumentOrganiser $organiser + */ + public function __construct(ArgumentOrganiser $organiser) + { + $this->baseOrganiser = $organiser; + } + + /** + * {@inheritdoc} + */ + public function organiseArguments(ReflectionFunctionAbstract $function, array $match) + { + $arguments = $this->cleanupMatchDuplicates($match); + + return $this->baseOrganiser->organiseArguments($function, $arguments); + } + + /** + * Cleans up provided preg_match match into a list of arguments. + * + * `preg_match` matches named arguments with named indexes and also + * represents all arguments with numbered indexes. This method removes + * duplication and also drops the first full match element from the + * array. + * + * @param array $match + * + * @return mixed[] + */ + private function cleanupMatchDuplicates(array $match) + { + $cleanMatch = array_slice($match, 1); + $arguments = array(); + + $keys = array_keys($cleanMatch); + for ($keyIndex = 0; $keyIndex < count($keys); $keyIndex++) { + $key = $keys[$keyIndex]; + + $arguments[$key] = $cleanMatch[$key]; + + if ($this->isKeyAStringAndNexOneIsAnInteger($keyIndex, $keys)) { + $keyIndex += 1; + } + } + + return $arguments; + } + + /** + * Checks if key at provided index is a string and next key in the array is an integer. + * + * @param integer $keyIndex + * @param mixed[] $keys + * + * @return Boolean + */ + private function isKeyAStringAndNexOneIsAnInteger($keyIndex, array $keys) + { + $keyIsAString = is_string($keys[$keyIndex]); + $nextKeyIsAnInteger = isset($keys[$keyIndex + 1]) && is_integer($keys[$keyIndex + 1]); + + return $keyIsAString && $nextKeyIsAnInteger; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Argument/ServiceContainer/ArgumentExtension.php b/vendor/behat/behat/src/Behat/Testwork/Argument/ServiceContainer/ArgumentExtension.php new file mode 100644 index 0000000..0219664 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/ServiceContainer/ArgumentExtension.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Argument\ServiceContainer; + +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Enables argument organises for the Testwork. + * + * @author Konstantin Kudryashov + */ +final class ArgumentExtension implements Extension +{ + /* + * Available services + */ + const MIXED_ARGUMENT_ORGANISER_ID = 'argument.mixed_organiser'; + const PREG_MATCH_ARGUMENT_ORGANISER_ID = 'argument.preg_match_organiser'; + const CONSTRUCTOR_ARGUMENT_ORGANISER_ID = 'argument.constructor_organiser'; + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'argument'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $definition = new Definition('Behat\Testwork\Argument\MixedArgumentOrganiser'); + $container->setDefinition(self::MIXED_ARGUMENT_ORGANISER_ID, $definition); + + $definition = new Definition('Behat\Testwork\Argument\PregMatchArgumentOrganiser', array( + new Reference(self::MIXED_ARGUMENT_ORGANISER_ID) + )); + $container->setDefinition(self::PREG_MATCH_ARGUMENT_ORGANISER_ID, $definition); + + $definition = new Definition('Behat\Testwork\Argument\ConstructorArgumentOrganiser', array( + new Reference(self::MIXED_ARGUMENT_ORGANISER_ID) + )); + $container->setDefinition(self::CONSTRUCTOR_ARGUMENT_ORGANISER_ID, $definition); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Autoloader/Cli/AutoloaderController.php b/vendor/behat/behat/src/Behat/Testwork/Autoloader/Cli/AutoloaderController.php new file mode 100644 index 0000000..991eb41 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Autoloader/Cli/AutoloaderController.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Autoloader\Cli; + +use Behat\Testwork\Cli\Controller; +use Symfony\Component\ClassLoader\ClassLoader; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Registers Testwork autoloader. + * + * @author Konstantin Kudryashov + */ +final class AutoloaderController implements Controller +{ + /** + * @var ClassLoader + */ + private $loader; + + /** + * Initializes controller + * + * @param ClassLoader $loader + */ + public function __construct(ClassLoader $loader) + { + $this->loader = $loader; + } + + /** + * {@inheritdoc} + */ + public function configure(Command $command) + { + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $this->loader->register(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Autoloader/ServiceContainer/AutoloaderExtension.php b/vendor/behat/behat/src/Behat/Testwork/Autoloader/ServiceContainer/AutoloaderExtension.php new file mode 100644 index 0000000..2c5f021 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Autoloader/ServiceContainer/AutoloaderExtension.php @@ -0,0 +1,151 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Autoloader\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Extends Testwork with class-loading services. + * + * @author Konstantin Kudryashov + */ +final class AutoloaderExtension implements Extension +{ + /* + * Available services + */ + const CLASS_LOADER_ID = 'class_loader'; + + /** + * @var array + */ + private $defaultPaths = array(); + + /** + * Initializes extension. + * + * @param array $defaultPaths + */ + public function __construct(array $defaultPaths = array()) + { + $this->defaultPaths = $defaultPaths; + } + + /** + * Returns the extension config key. + * + * @return string + */ + public function getConfigKey() + { + return 'autoload'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + $builder + ->beforeNormalization() + ->ifString()->then(function ($path) { + return array('' => $path); + }) + ->end() + + ->defaultValue($this->defaultPaths) + ->treatTrueLike($this->defaultPaths) + ->treatNullLike(array()) + ->treatFalseLike(array()) + + ->prototype('scalar')->end() + ; + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadAutoloader($container); + $this->loadController($container); + $this->setLoaderPrefixes($container, $config); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processLoaderPrefixes($container); + } + + /** + * Loads Symfony2 autoloader. + * + * @param ContainerBuilder $container + */ + private function loadAutoloader(ContainerBuilder $container) + { + $definition = new Definition('Symfony\Component\ClassLoader\ClassLoader'); + $container->setDefinition(self::CLASS_LOADER_ID, $definition); + } + + /** + * Loads controller. + * + * @param ContainerBuilder $container + */ + private function loadController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Autoloader\Cli\AutoloaderController', array( + new Reference(self::CLASS_LOADER_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 9999)); + + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.autoloader', $definition); + } + + /** + * Sets provided prefixes to container. + * + * @param ContainerBuilder $container + * @param array $prefixes + */ + private function setLoaderPrefixes(ContainerBuilder $container, array $prefixes) + { + $container->setParameter('class_loader.prefixes', $prefixes); + } + + /** + * Processes container loader prefixes. + * + * @param ContainerBuilder $container + */ + private function processLoaderPrefixes(ContainerBuilder $container) + { + $loaderDefinition = $container->getDefinition(self::CLASS_LOADER_ID); + $loaderDefinition->addMethodCall('addPrefixes', array($container->getParameter('class_loader.prefixes'))); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Call.php b/vendor/behat/behat/src/Behat/Testwork/Call/Call.php new file mode 100644 index 0000000..efa04de --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Call.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call; + +/** + * Represents any call made inside testwork. + * + * @author Konstantin Kudryashov + */ +interface Call +{ + /** + * Returns callee. + * + * @return Callee + */ + public function getCallee(); + + /** + * Returns bound callable. + * + * @return callable + */ + public function getBoundCallable(); + + /** + * Returns call arguments. + * + * @return array + */ + public function getArguments(); + + /** + * Returns call error reporting level. + * + * @return null|integer + */ + public function getErrorReportingLevel(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/CallCenter.php b/vendor/behat/behat/src/Behat/Testwork/Call/CallCenter.php new file mode 100644 index 0000000..df4e661 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/CallCenter.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call; + +use Behat\Testwork\Call\Exception\CallHandlingException; +use Behat\Testwork\Call\Filter\CallFilter; +use Behat\Testwork\Call\Filter\ResultFilter; +use Behat\Testwork\Call\Handler\CallHandler; +use Exception; + +/** + * Makes calls and handles results using registered handlers. + * + * @author Konstantin Kudryashov + */ +final class CallCenter +{ + /** + * @var CallFilter[] + */ + private $callFilters = array(); + /** + * @var CallHandler[] + */ + private $callHandlers = array(); + /** + * @var ResultFilter[] + */ + private $resultFilters = array(); + + /** + * Registers call filter. + * + * @param CallFilter $filter + */ + public function registerCallFilter(CallFilter $filter) + { + $this->callFilters[] = $filter; + } + + /** + * Registers call handler. + * + * @param CallHandler $handler + */ + public function registerCallHandler(CallHandler $handler) + { + $this->callHandlers[] = $handler; + } + + /** + * Registers call result filter. + * + * @param ResultFilter $filter + */ + public function registerResultFilter(ResultFilter $filter) + { + $this->resultFilters[] = $filter; + } + + /** + * Handles call and its result using registered filters and handlers. + * + * @param Call $call + * + * @return CallResult + */ + public function makeCall(Call $call) + { + try { + $filteredCall = $this->filterCall($call); + $result = $this->handleCall($filteredCall); + $filteredResult = $this->filterResult($result); + } catch (Exception $e) { + return new CallResult($call, null, $e, null); + } + + return $filteredResult; + } + + /** + * Filters call using registered filters and returns a filtered one. + * + * @param Call $call + * + * @return Call + */ + private function filterCall(Call $call) + { + foreach ($this->callFilters as $filter) { + if (!$filter->supportsCall($call)) { + continue; + } + + return $filter->filterCall($call); + } + + return $call; + } + + /** + * Handles call using registered call handlers. + * + * @param Call $call + * + * @return CallResult + * + * @throws CallHandlingException If call handlers didn't produce call result + */ + private function handleCall(Call $call) + { + foreach ($this->callHandlers as $handler) { + if (!$handler->supportsCall($call)) { + continue; + } + + return $handler->handleCall($call); + } + + throw new CallHandlingException(sprintf( + 'None of the registered call handlers could handle a `%s` call.', + $call->getCallee()->getPath() + ), $call); + } + + /** + * Filters call result using registered filters and returns a filtered one. + * + * @param CallResult $result + * + * @return CallResult + */ + private function filterResult(CallResult $result) + { + foreach ($this->resultFilters as $filter) { + if (!$filter->supportsResult($result)) { + continue; + } + + return $filter->filterResult($result); + } + + return $result; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/CallResult.php b/vendor/behat/behat/src/Behat/Testwork/Call/CallResult.php new file mode 100644 index 0000000..ca3c528 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/CallResult.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call; + +use Exception; + +/** + * Represents result of the call. + * + * @author Konstantin Kudryashov + */ +final class CallResult +{ + /** + * @var Call + */ + private $call; + /** + * @var mixed + */ + private $return; + /** + * @var null|Exception + */ + private $exception; + /** + * @var null|string + */ + private $stdOut; + + /** + * Initializes call result. + * + * @param Call $call + * @param mixed $return + * @param null|Exception $exception + * @param null|string $stdOut + */ + public function __construct(Call $call, $return, Exception $exception = null, $stdOut = null) + { + $this->call = $call; + $this->return = $return; + $this->exception = $exception; + $this->stdOut = $stdOut; + } + + /** + * Returns call. + * + * @return Call + */ + public function getCall() + { + return $this->call; + } + + /** + * Returns call return value. + * + * @return mixed + */ + public function getReturn() + { + return $this->return; + } + + /** + * Check if call thrown exception. + * + * @return Boolean + */ + public function hasException() + { + return null !== $this->exception; + } + + /** + * Returns exception thrown by call (if any). + * + * @return null|Exception + */ + public function getException() + { + return $this->exception; + } + + /** + * Checks if call produced stdOut. + * + * @return Boolean + */ + public function hasStdOut() + { + return null !== $this->stdOut; + } + + /** + * Returns stdOut produced by call (if any). + * + * @return null|string + */ + public function getStdOut() + { + return $this->stdOut; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/CallResults.php b/vendor/behat/behat/src/Behat/Testwork/Call/CallResults.php new file mode 100644 index 0000000..f79ea0c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/CallResults.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call; + +use ArrayIterator; +use Countable; +use Iterator; +use IteratorAggregate; + +/** + * Aggregates multiple call results into a collection and provides an informational API on top of that. + * + * @author Konstantin Kudryashov + */ +final class CallResults implements Countable, IteratorAggregate +{ + /** + * @var CallResult[] + */ + private $results; + + /** + * Initializes call results collection. + * + * @param CallResult[] $results + */ + public function __construct(array $results = array()) + { + $this->results = $results; + } + + /** + * Merges results from provided collection into the current one. + * + * @param CallResults $first + * @param CallResults $second + * + * @return CallResults + */ + public static function merge(CallResults $first, CallResults $second) + { + return new static(array_merge($first->toArray(), $second->toArray())); + } + + /** + * Checks if any call in collection throws an exception. + * + * @return Boolean + */ + public function hasExceptions() + { + foreach ($this->results as $result) { + if ($result->hasException()) { + return true; + } + } + + return false; + } + + /** + * Checks if any call in collection produces an output. + * + * @return Boolean + */ + public function hasStdOuts() + { + foreach ($this->results as $result) { + if ($result->hasStdOut()) { + return true; + } + } + + return false; + } + + /** + * Returns amount of results. + * + * @return integer + */ + public function count() + { + return count($this->results); + } + + /** + * Returns collection iterator. + * + * @return Iterator + */ + public function getIterator() + { + return new ArrayIterator($this->results); + } + + /** + * Returns call results array. + * + * @return CallResult[] + */ + public function toArray() + { + return $this->results; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Callee.php b/vendor/behat/behat/src/Behat/Testwork/Call/Callee.php new file mode 100644 index 0000000..c03e776 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Callee.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call; + +use ReflectionFunctionAbstract; + +/** + * Represents callable object. + * + * @author Konstantin Kudryashov + */ +interface Callee +{ + /** + * Returns callee definition path. + * + * @return string + */ + public function getPath(); + + /** + * Returns callee description. + * + * @return string + */ + public function getDescription(); + + /** + * Returns true if callee is a method, false otherwise. + * + * @return Boolean + */ + public function isAMethod(); + + /** + * Returns true if callee is an instance (non-static) method, false otherwise. + * + * @return Boolean + */ + public function isAnInstanceMethod(); + + /** + * Returns callable. + * + * @return callable + */ + public function getCallable(); + + /** + * Returns callable reflection. + * + * @return ReflectionFunctionAbstract + */ + public function getReflection(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Exception/BadCallbackException.php b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/BadCallbackException.php new file mode 100644 index 0000000..de56b4e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/BadCallbackException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call\Exception; + +use InvalidArgumentException; + +/** + * Represents exception caused by a bad callback. + * + * @author Konstantin Kudryashov + */ +final class BadCallbackException extends InvalidArgumentException implements CallException +{ + /** + * @var callable + */ + private $callable; + + /** + * Initializes exception. + * + * @param string $message + * @param callable $callable + */ + public function __construct($message, $callable) + { + $this->callable = $callable; + + parent::__construct($message); + } + + /** + * Returns callback that caused exception. + * + * @return callable + */ + public function getCallable() + { + return $this->callable; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Exception/CallErrorException.php b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/CallErrorException.php new file mode 100644 index 0000000..423abf3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/CallErrorException.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call\Exception; + +use ErrorException; + +/** + * Represents catchable errors raised during call execution. + * + * @author Konstantin Kudryashov + */ +final class CallErrorException extends ErrorException +{ + private $levels = array( + E_WARNING => 'Warning', + E_NOTICE => 'Notice', + E_USER_ERROR => 'User Error', + E_USER_WARNING => 'User Warning', + E_USER_NOTICE => 'User Notice', + E_STRICT => 'Runtime Notice', + E_RECOVERABLE_ERROR => 'Catchable Fatal Error', + ); + + /** + * Initializes error handler exception. + * + * @param integer $level error level + * @param string $message error message + * @param string $file error file + * @param integer $line error line + */ + public function __construct($level, $message, $file, $line) + { + parent::__construct( + sprintf( + '%s: %s in %s line %d', + isset($this->levels[$level]) ? $this->levels[$level] : $level, + $message, + $file, + $line + ) + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Exception/CallException.php b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/CallException.php new file mode 100644 index 0000000..1e3db97 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/CallException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call\Exception; + +use Behat\Testwork\Exception\TestworkException; + +/** + * All call exceptions should implement this interface. + * + * @author Konstantin Kudryashov + */ +interface CallException extends TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Exception/CallHandlingException.php b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/CallHandlingException.php new file mode 100644 index 0000000..f8e670e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/CallHandlingException.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call\Exception; + +use Behat\Testwork\Call\Call; +use RuntimeException; + +/** + * Represents exceptions thrown during call handling phase. + * + * @author Konstantin Kudryashov + */ +final class CallHandlingException extends RuntimeException implements CallException +{ + /** + * @var Call + */ + private $call; + + /** + * Initializes exception. + * + * @param string $message + * @param Call $callable + */ + public function __construct($message, Call $callable) + { + $this->call = $callable; + + parent::__construct($message); + } + + /** + * Returns call that caused exception. + * + * @return Call + */ + public function getCall() + { + return $this->call; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Filter/CallFilter.php b/vendor/behat/behat/src/Behat/Testwork/Call/Filter/CallFilter.php new file mode 100644 index 0000000..5426c16 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Filter/CallFilter.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call\Filter; + +use Behat\Testwork\Call\Call; +use Behat\Testwork\Call\CallCenter; + +/** + * Filters call before its being made and returns a new call. + * + * @see CallCenter + * + * @author Konstantin Kudryashov + */ +interface CallFilter +{ + /** + * Checks if filter supports a call. + * + * @param Call $call + * + * @return Boolean + */ + public function supportsCall(Call $call); + + /** + * Filters a call and returns a new one. + * + * @param Call $call + * + * @return Call + */ + public function filterCall(Call $call); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Filter/ResultFilter.php b/vendor/behat/behat/src/Behat/Testwork/Call/Filter/ResultFilter.php new file mode 100644 index 0000000..ac3ebe0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Filter/ResultFilter.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call\Filter; + +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\CallResult; + +/** + * Filters call results and produces new ones. + * + * @see CallCenter + * + * @author Konstantin Kudryashov + */ +interface ResultFilter +{ + /** + * Checks if filter supports call result. + * + * @param CallResult $result + * + * @return Boolean + */ + public function supportsResult(CallResult $result); + + /** + * Filters call result and returns a new result. + * + * @param CallResult $result + * + * @return CallResult + */ + public function filterResult(CallResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Handler/CallHandler.php b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/CallHandler.php new file mode 100644 index 0000000..e553d2a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/CallHandler.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call\Handler; + +use Behat\Testwork\Call\Call; +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\CallResult; + +/** + * Handles calls and produces call results. + * + * @see CallCenter + * + * @author Konstantin Kudryashov + */ +interface CallHandler +{ + /** + * Checks if handler supports call. + * + * @param Call $call + * + * @return Boolean + */ + public function supportsCall(Call $call); + + /** + * Handles call and returns call result. + * + * @param Call $call + * + * @return CallResult + */ + public function handleCall(Call $call); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Handler/RuntimeCallHandler.php b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/RuntimeCallHandler.php new file mode 100644 index 0000000..6724a7a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/RuntimeCallHandler.php @@ -0,0 +1,139 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call\Handler; + +use Behat\Testwork\Call\Call; +use Behat\Testwork\Call\CallResult; +use Behat\Testwork\Call\Exception\CallErrorException; +use Exception; + +/** + * Handles calls in teh current runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeCallHandler implements CallHandler +{ + /** + * @var integer + */ + private $errorReportingLevel; + + /** + * Initializes executor. + * + * @param integer $errorReportingLevel + */ + public function __construct($errorReportingLevel = E_ALL) + { + $this->errorReportingLevel = $errorReportingLevel; + } + + /** + * {@inheritdoc} + */ + public function supportsCall(Call $call) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function handleCall(Call $call) + { + $this->startErrorAndOutputBuffering($call); + $result = $this->executeCall($call); + $this->stopErrorAndOutputBuffering(); + + return $result; + } + + /** + * Used as a custom error handler when step is running. + * + * @see set_error_handler() + * + * @param integer $level + * @param string $message + * @param string $file + * @param integer $line + * + * @return Boolean + * + * @throws CallErrorException + */ + public function handleError($level, $message, $file, $line) + { + if (0 !== error_reporting()) { + throw new CallErrorException($level, $message, $file, $line); + } + + // error reporting turned off or more likely suppressed with @ + return false; + } + + /** + * Executes single call. + * + * @param Call $call + * + * @return CallResult + */ + private function executeCall(Call $call) + { + $callable = $call->getBoundCallable(); + $arguments = $call->getArguments(); + + $return = $exception = null; + + try { + $return = call_user_func_array($callable, $arguments); + } catch (Exception $caught) { + $exception = $caught; + } + + $stdOud = $this->getBufferedStdOut(); + + return new CallResult($call, $return, $exception, $stdOud); + } + + /** + * Returns buffered stdout. + * + * @return null|string + */ + private function getBufferedStdOut() + { + return ob_get_length() ? ob_get_contents() : null; + } + + /** + * Starts error handler and stdout buffering. + * + * @param Call $call + */ + private function startErrorAndOutputBuffering(Call $call) + { + $errorReporting = $call->getErrorReportingLevel() ? : $this->errorReportingLevel; + set_error_handler(array($this, 'handleError'), $errorReporting); + ob_start(); + } + + /** + * Stops error handler and stdout buffering. + */ + private function stopErrorAndOutputBuffering() + { + ob_end_clean(); + restore_error_handler(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/RuntimeCallee.php b/vendor/behat/behat/src/Behat/Testwork/Call/RuntimeCallee.php new file mode 100644 index 0000000..c764629 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/RuntimeCallee.php @@ -0,0 +1,132 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call; + +use Behat\Testwork\Call\Exception\BadCallbackException; +use ReflectionFunction; +use ReflectionFunctionAbstract; +use ReflectionMethod; + +/** + * Represents callee created and executed in the runtime. + * + * @author Konstantin Kudryashov + */ +class RuntimeCallee implements Callee +{ + /** + * @var callable + */ + private $callable; + /** + * @var null|string + */ + private $description; + /** + * @var ReflectionFunctionAbstract + */ + private $reflection; + /** + * @var string + */ + private $path; + + /** + * Initializes callee. + * + * @param callable $callable + * @param null|string $description + * + * @throws BadCallbackException If invalid callback provided + */ + public function __construct($callable, $description = null) + { + if (!is_array($callable) && !is_callable($callable)) { + throw new BadCallbackException(sprintf( + '%s expects a valid callable, but `%s` given', + get_class($this), + gettype($callable) + ), $callable); + } + + if (is_array($callable)) { + $this->reflection = new ReflectionMethod($callable[0], $callable[1]); + $this->path = $callable[0] . '::' . $callable[1] . '()'; + } else { + $this->reflection = new ReflectionFunction($callable); + $this->path = $this->reflection->getFileName() . ':' . $this->reflection->getStartLine(); + } + + $this->callable = $callable; + $this->description = $description; + } + + /** + * Returns callee description. + * + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * Returns callee definition path. + * + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * Returns callable. + * + * @return callable + */ + public function getCallable() + { + return $this->callable; + } + + /** + * Returns callable reflection. + * + * @return ReflectionFunctionAbstract + */ + public function getReflection() + { + return $this->reflection; + } + + /** + * Returns true if callee is a method, false otherwise. + * + * @return Boolean + */ + public function isAMethod() + { + return $this->reflection instanceof ReflectionMethod; + } + + /** + * Returns true if callee is an instance (non-static) method, false otherwise. + * + * @return Boolean + */ + public function isAnInstanceMethod() + { + return $this->reflection instanceof ReflectionMethod + && !$this->reflection->isStatic(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/ServiceContainer/CallExtension.php b/vendor/behat/behat/src/Behat/Testwork/Call/ServiceContainer/CallExtension.php new file mode 100644 index 0000000..9e2fdd3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/ServiceContainer/CallExtension.php @@ -0,0 +1,172 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Call\ServiceContainer; + +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Provides call services for testwork. + * + * @author Konstantin Kudryashov + */ +final class CallExtension implements Extension +{ + /* + * Available services + */ + const CALL_CENTER_ID = 'call.center'; + + /* + * Available extension points + */ + const CALL_FILTER_TAG = 'call.call_filter'; + const CALL_HANDLER_TAG = 'call.call_handler'; + const RESULT_FILTER_TAG = 'call.result_filter'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'calls'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + $builder + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('error_reporting') + ->info('Call executor will catch exceptions matching this level') + ->defaultValue(E_ALL | E_STRICT) + ->end() + ->end() + ; + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadCallCenter($container); + $this->loadCallHandlers($container, $config['error_reporting']); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processCallFilters($container); + $this->processCallHandlers($container); + $this->processResultFilters($container); + } + + /** + * Loads call center service. + * + * @param ContainerBuilder $container + */ + protected function loadCallCenter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Call\CallCenter'); + $container->setDefinition(self::CALL_CENTER_ID, $definition); + } + + /** + * Loads prebuilt call handlers. + * + * @param ContainerBuilder $container + * @param integer $errorReporting + */ + protected function loadCallHandlers(ContainerBuilder $container, $errorReporting) + { + $definition = new Definition('Behat\Testwork\Call\Handler\RuntimeCallHandler', array($errorReporting)); + $definition->addTag(self::CALL_HANDLER_TAG, array('priority' => 50)); + $container->setDefinition(self::CALL_HANDLER_TAG . '.runtime', $definition); + } + + /** + * Registers all call filters to the CallCenter. + * + * @param ContainerBuilder $container + */ + protected function processCallFilters(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, CallExtension::CALL_FILTER_TAG); + $definition = $container->getDefinition(CallExtension::CALL_CENTER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerCallFilter', array($reference)); + } + } + + /** + * Registers all call handlers to the CallCenter. + * + * @param ContainerBuilder $container + */ + protected function processCallHandlers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, CallExtension::CALL_HANDLER_TAG); + $definition = $container->getDefinition(CallExtension::CALL_CENTER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerCallHandler', array($reference)); + } + } + + /** + * Registers all call result filters to the CallCenter. + * + * @param ContainerBuilder $container + */ + protected function processResultFilters(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, CallExtension::RESULT_FILTER_TAG); + $definition = $container->getDefinition(CallExtension::CALL_CENTER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerResultFilter', array($reference)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Cli/Application.php b/vendor/behat/behat/src/Behat/Testwork/Cli/Application.php new file mode 100644 index 0000000..98bffca --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Cli/Application.php @@ -0,0 +1,209 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Cli; + +use Behat\Testwork\ServiceContainer\Configuration\ConfigurationLoader; +use Behat\Testwork\ServiceContainer\ContainerLoader; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Symfony\Component\Console\Application as BaseApplication; +use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Extends Symfony console application with testwork functionality. + * + * @author Konstantin Kudryashov + */ +final class Application extends BaseApplication +{ + /** + * @var ConfigurationLoader + */ + private $configurationLoader; + /** + * @var ExtensionManager + */ + private $extensionManager; + + /** + * Initializes application. + * + * @param string $name + * @param string $version + * @param ConfigurationLoader $configLoader + * @param ExtensionManager $extensionManager + */ + public function __construct($name, $version, ConfigurationLoader $configLoader, ExtensionManager $extensionManager) + { + $this->configurationLoader = $configLoader; + $this->extensionManager = $extensionManager; + + parent::__construct($name, $version); + } + + /** + * Gets the default input definition. + * + * @return InputDefinition An InputDefinition instance + */ + public function getDefaultInputDefinition() + { + return new InputDefinition(array( + new InputOption('--profile', '-p', InputOption::VALUE_REQUIRED, 'Specify config profile to use.'), + new InputOption('--config', '-c', InputOption::VALUE_REQUIRED, 'Specify config file to use.'), + new InputOption('--verbose', '-v', InputOption::VALUE_NONE, 'Increase verbosity of exceptions.'), + new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message.'), + new InputOption('--config-reference', null, InputOption::VALUE_NONE, 'Display the configuration reference.'), + new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this behat version.'), + new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question.'), + new InputOption( + '--colors', null, InputOption::VALUE_NONE, + 'Force ANSI color in the output. By default color support is' . PHP_EOL . + 'guessed based on your platform and the output if not specified.' + ), + new InputOption('--no-colors', null, InputOption::VALUE_NONE, 'Force no ANSI color in the output.'), + )); + } + + /** + * Runs the current application. + * + * @param InputInterface $input An Input instance + * @param OutputInterface $output An Output instance + * + * @return integer 0 if everything went fine, or an error code + */ + public function doRun(InputInterface $input, OutputInterface $output) + { + if (is_file($path = $input->getParameterOption(array('--config', '-c')))) { + $this->configurationLoader->setConfigurationFilePath($path); + } + + $this->add($this->createCommand($input, $output)); + + if ($input->hasParameterOption(array('--config-reference'))) { + $input = new ArrayInput(array('--config-reference' => true)); + } + + return parent::doRun($input, $output); + } + + protected function getDefaultCommands() + { + $commands = parent::getDefaultCommands(); + + $commands[] = new DumpReferenceCommand($this->extensionManager); + + return $commands; + } + + /** + * Configures container based on provided config file and profile. + * + * @param InputInterface $input + * + * @return array + */ + private function loadConfiguration(InputInterface $input) + { + $profile = $input->getParameterOption(array('--profile', '-p')) ? : 'default'; + + return $this->configurationLoader->loadConfiguration($profile); + } + + /** + * Creates main command for application. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return SymfonyCommand + */ + private function createCommand(InputInterface $input, OutputInterface $output) + { + return $this->createContainer($input, $output)->get('cli.command'); + } + + /** + * Creates container instance, loads extensions and freezes it. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return ContainerInterface + */ + private function createContainer(InputInterface $input, OutputInterface $output) + { + $basePath = rtrim($this->getBasePath(), DIRECTORY_SEPARATOR); + + $container = new ContainerBuilder(); + + $container->setParameter('cli.command.name', $this->getName()); + $container->setParameter('paths.base', $basePath); + + $container->set('cli.input', $input); + $container->set('cli.output', $output); + + $extension = new ContainerLoader($this->extensionManager); + $extension->load($container, $this->loadConfiguration($input)); + $container->addObjectResource($extension); + $container->compile(); + + return $container; + } + + /** + * Returns base path. + * + * @return string + */ + private function getBasePath() + { + if ($configPath = $this->configurationLoader->getConfigurationFilePath()) { + return realpath(dirname($configPath)); + } + + return realpath(getcwd()); + } + + /** + * Gets the name of the command based on input. + * + * @param InputInterface $input The input interface + * + * @return string The command name + */ + protected function getCommandName(InputInterface $input) + { + if ($input->hasParameterOption(array('--config-reference'))) { + return 'dump-reference'; + } + + return $this->getName(); + } + + protected function configureIO(InputInterface $input, OutputInterface $output) + { + if (true === $input->hasParameterOption(array('--colors'))) { + $output->setDecorated(true); + } elseif (true === $input->hasParameterOption(array('--no-colors'))) { + $output->setDecorated(false); + } + + parent::configureIO($input, $output); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Cli/Command.php b/vendor/behat/behat/src/Behat/Testwork/Cli/Command.php new file mode 100644 index 0000000..ae53dfa --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Cli/Command.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Cli; + +use Symfony\Component\Console\Command\Command as BaseCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Extends Symfony console command with a controller-based delegation. + * + * @author Konstantin Kudryashov + */ +final class Command extends BaseCommand +{ + /** + * @var Controller[] + */ + private $controllers = array(); + + /** + * Initializes command. + * + * @param string $commandName + * @param Controller[] $controllers + */ + public function __construct($commandName, array $controllers) + { + $this->controllers = $controllers; + + parent::__construct($commandName); + } + + /** + * Configures the command by running controllers prepare(). + */ + protected function configure() + { + foreach ($this->controllers as $controller) { + $controller->configure($this); + } + } + + /** + * Executes the current command by executing all controllers action(). + * + * @param InputInterface $input An InputInterface instance + * @param OutputInterface $output An OutputInterface instance + * + * @return integer Return code of one of the processors or 0 if none of them returned integer + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + foreach ($this->controllers as $controller) { + if (is_int($return = $controller->execute($input, $output))) { + return $return; + } + } + + return 0; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Cli/Controller.php b/vendor/behat/behat/src/Behat/Testwork/Cli/Controller.php new file mode 100644 index 0000000..e604d67 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Cli/Controller.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Cli; + +use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Represents Testwork Console Controller. + * + * All testwork console controllers should implement this interface. + * + * @author Konstantin Kudryashov + */ +interface Controller +{ + /** + * Configures command to be executable by the controller. + * + * @param SymfonyCommand $command + */ + public function configure(SymfonyCommand $command); + + /** + * Executes controller. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return null|integer + */ + public function execute(InputInterface $input, OutputInterface $output); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Cli/DumpReferenceCommand.php b/vendor/behat/behat/src/Behat/Testwork/Cli/DumpReferenceCommand.php new file mode 100644 index 0000000..d6b57d4 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Cli/DumpReferenceCommand.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Cli; + +use Behat\Testwork\ServiceContainer\Configuration\ConfigurationTree; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper; +use Symfony\Component\Config\Definition\ReferenceDumper; +use Symfony\Component\Console\Command\Command as BaseCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Extends Symfony console application with testwork functionality. + * + * @author Christophe Coevoet + */ +final class DumpReferenceCommand extends BaseCommand +{ + /** + * @var ExtensionManager + */ + private $extensionManager; + + /** + * Initializes dumper. + * + * @param ExtensionManager $extensionManager + */ + public function __construct(ExtensionManager $extensionManager) + { + $this->extensionManager = $extensionManager; + + parent::__construct('dump-reference'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if (class_exists('Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper')) { + $dumper = new YamlReferenceDumper(); + } else { + // Support Symfony Config 2.3 + $dumper = new ReferenceDumper(); + } + + $configTree = new ConfigurationTree(); + + $output->writeln($dumper->dumpNode($configTree->getConfigTree($this->extensionManager->getExtensions()))); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Cli/ServiceContainer/CliExtension.php b/vendor/behat/behat/src/Behat/Testwork/Cli/ServiceContainer/CliExtension.php new file mode 100644 index 0000000..4b9fba8 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Cli/ServiceContainer/CliExtension.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Cli\ServiceContainer; + +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Provides console services for testwork. + * + * @author Konstantin Kudryashov + */ +final class CliExtension implements Extension +{ + /* + * Available services + */ + const COMMAND_ID = 'cli.command'; + const INPUT_ID = 'cli.input'; + const OUTPUT_ID = 'cli.output'; + + /* + * Available extension points + */ + const CONTROLLER_TAG = 'cli.controller'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ?: new ServiceProcessor(); + } + + /** + * Returns the extension config key. + * + * @return string + */ + public function getConfigKey() + { + return 'cli'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadCommand($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processControllers($container); + } + + /** + * Loads application command. + * + * @param ContainerBuilder $container + */ + protected function loadCommand(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Cli\Command', array('%cli.command.name%', array())); + $container->setDefinition(self::COMMAND_ID, $definition); + } + + /** + * Processes all controllers in container. + * + * @param ContainerBuilder $container + */ + protected function processControllers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::CONTROLLER_TAG); + $container->getDefinition(self::COMMAND_ID)->replaceArgument(1, $references); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Counter/Exception/TimerException.php b/vendor/behat/behat/src/Behat/Testwork/Counter/Exception/TimerException.php new file mode 100644 index 0000000..72238fd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Counter/Exception/TimerException.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Counter\Exception; + +use Behat\Testwork\Exception\TestworkException; +use LogicException; + +/** + * Represents exception caused by timer handling. + * + * @author Konstantin Kudryashov + */ +final class TimerException extends LogicException implements TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Counter/Memory.php b/vendor/behat/behat/src/Behat/Testwork/Counter/Memory.php new file mode 100644 index 0000000..f7d8605 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Counter/Memory.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Counter; + +/** + * Counts amount of system memory being used. + * + * @author Konstantin Kudryashov + */ +final class Memory +{ + /** + * @var string[] + */ + private $units = array('B', 'Kb', 'Mb', 'Gb', 'Tb'); + + /** + * Returns current memory usage. + * + * @return integer + */ + public function getMemoryUsage() + { + return memory_get_usage(); + } + + /** + * Presents memory usage in human-readable form. + * + * @return string + */ + public function __toString() + { + return $this->humanize($this->getMemoryUsage()); + } + + /** + * Humanizes usage information. + * + * @param integer $bytes + * + * @return string + */ + private function humanize($bytes) + { + $e = intval(floor(log($bytes) / log(1024))); + + if (!isset($this->units[$e])) { + return 'Can not calculate memory usage'; + } + + return sprintf('%.2f%s', ($bytes / pow(1024, floor($e))), $this->units[$e]); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Counter/Timer.php b/vendor/behat/behat/src/Behat/Testwork/Counter/Timer.php new file mode 100644 index 0000000..65025a3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Counter/Timer.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Counter; + +use Behat\Testwork\Counter\Exception\TimerException; + +/** + * Provides time counting functionality. + * + * @author Konstantin Kudryashov + */ +final class Timer +{ + /** + * @var null|float + */ + private $starTime; + /** + * @var null|float + */ + private $stopTime; + + /** + * Starts timer. + */ + public function start() + { + $this->starTime = microtime(true); + } + + /** + * Stops timer. + * + * @throws TimerException If timer has not been started + */ + public function stop() + { + if (!$this->starTime) { + throw new TimerException('You can not stop timer that has not been started.'); + } + + $this->stopTime = microtime(true); + } + + /** + * @return null|float + * + * @throws TimerException If timer has not been started + */ + public function getTime() + { + if (!$this->starTime) { + throw new TimerException('You can not get time from timer that never been started.'); + } + + $stopTime = $this->stopTime; + if (!$this->stopTime) { + $stopTime = microtime(true); + } + + return $stopTime - $this->starTime; + } + + /** + * Returns number of minutes passed. + * + * @return integer + */ + public function getMinutes() + { + return intval(floor($this->getTime() / 60)); + } + + /** + * Returns number of seconds passed. + * + * @return float + */ + public function getSeconds() + { + return round($this->getTime() - ($this->getMinutes() * 60), 3); + } + + /** + * Returns string representation of time passed. + * + * @return string + */ + public function __toString() + { + if (!$this->starTime || !$this->stopTime) { + return '0m0s'; + } + + return sprintf('%dm%.2fs', $this->getMinutes(), $this->getSeconds()); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/Call/EnvironmentCall.php b/vendor/behat/behat/src/Behat/Testwork/Environment/Call/EnvironmentCall.php new file mode 100644 index 0000000..39d34f7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/Call/EnvironmentCall.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment\Call; + +use Behat\Testwork\Call\Call; +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Environment\Environment; + +/** + * Represents environment-based call. + * + * @author Konstantin Kudryashov + */ +class EnvironmentCall implements Call +{ + /** + * @var Environment + */ + private $environment; + /** + * @var Callee + */ + private $callee; + /** + * @var array + */ + private $arguments; + /** + * @var null|integer + */ + private $errorReportingLevel; + + /** + * Initializes call. + * + * @param Environment $environment + * @param Callee $callee + * @param array $arguments + * @param null|integer $errorReportingLevel + */ + public function __construct( + Environment $environment, + Callee $callee, + array $arguments, + $errorReportingLevel = null + ) { + $this->environment = $environment; + $this->callee = $callee; + $this->arguments = $arguments; + $this->errorReportingLevel = $errorReportingLevel; + } + + /** + * Returns environment this call is executed from. + * + * @return Environment + */ + final public function getEnvironment() + { + return $this->environment; + } + + /** + * {@inheritdoc} + */ + final public function getCallee() + { + return $this->callee; + } + + /** + * {@inheritdoc} + */ + final public function getBoundCallable() + { + return $this->environment->bindCallee($this->callee); + } + + /** + * {@inheritdoc} + */ + final public function getArguments() + { + return $this->arguments; + } + + /** + * {@inheritdoc} + */ + final public function getErrorReportingLevel() + { + return $this->errorReportingLevel; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/Environment.php b/vendor/behat/behat/src/Behat/Testwork/Environment/Environment.php new file mode 100644 index 0000000..0850015 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/Environment.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment; + +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Suite\Suite; + +/** + * Represents Testwork test environment. + * + * @author Konstantin Kudryashov + */ +interface Environment +{ + /** + * Returns environment suite. + * + * @return Suite + */ + public function getSuite(); + + /** + * Creates callable using provided Callee. + * + * @param Callee $callee + * + * @return callable + */ + public function bindCallee(Callee $callee); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/EnvironmentManager.php b/vendor/behat/behat/src/Behat/Testwork/Environment/EnvironmentManager.php new file mode 100644 index 0000000..b1dda50 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/EnvironmentManager.php @@ -0,0 +1,121 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment; + +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Environment\Exception\EnvironmentBuildException; +use Behat\Testwork\Environment\Exception\EnvironmentIsolationException; +use Behat\Testwork\Environment\Handler\EnvironmentHandler; +use Behat\Testwork\Environment\Reader\EnvironmentReader; +use Behat\Testwork\Suite\Suite; + +/** + * Builds, isolates and reads environments using registered handlers and readers. + * + * @author Konstantin Kudryashov + */ +final class EnvironmentManager +{ + /** + * @var EnvironmentHandler[] + */ + private $handlers = array(); + /** + * @var EnvironmentReader[] + */ + private $readers = array(); + + /** + * Registers environment handler. + * + * @param EnvironmentHandler $handler + */ + public function registerEnvironmentHandler(EnvironmentHandler $handler) + { + $this->handlers[] = $handler; + } + + /** + * Registers environment reader. + * + * @param EnvironmentReader $reader + */ + public function registerEnvironmentReader(EnvironmentReader $reader) + { + $this->readers[] = $reader; + } + + /** + * Builds new environment for provided test suite. + * + * @param Suite $suite + * + * @return Environment + * + * @throws EnvironmentBuildException + */ + public function buildEnvironment(Suite $suite) + { + foreach ($this->handlers as $handler) { + if ($handler->supportsSuite($suite)) { + return $handler->buildEnvironment($suite); + } + } + + throw new EnvironmentBuildException(sprintf( + 'None of the registered environment handlers seem to support `%s` suite.', + $suite->getName() + ), $suite); + } + + /** + * Creates new isolated test environment using built one. + * + * @param Environment $environment + * @param mixed $testSubject + * + * @return Environment + * + * @throws EnvironmentIsolationException If appropriate environment handler is not found + */ + public function isolateEnvironment(Environment $environment, $testSubject = null) + { + foreach ($this->handlers as $handler) { + if ($handler->supportsEnvironmentAndSubject($environment, $testSubject)) { + return $handler->isolateEnvironment($environment, $testSubject); + } + } + + throw new EnvironmentIsolationException(sprintf( + 'None of the registered environment handlers seem to support `%s` environment.', + get_class($environment) + ), $environment, $testSubject); + } + + /** + * Reads all callees from environment using registered environment readers. + * + * @param Environment $environment + * + * @return Callee[] + */ + public function readEnvironmentCallees(Environment $environment) + { + $callees = array(); + foreach ($this->readers as $reader) { + if ($reader->supportsEnvironment($environment)) { + $callees = array_merge($callees, $reader->readEnvironmentCallees($environment)); + } + } + + return $callees; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentBuildException.php b/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentBuildException.php new file mode 100644 index 0000000..4c3bb92 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentBuildException.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment\Exception; + +use Behat\Testwork\Suite\Suite; +use RuntimeException; + +/** + * Represents exception thrown during an environment build process. + * + * @author Konstantin Kudryashov + */ +final class EnvironmentBuildException extends RuntimeException implements EnvironmentException +{ + /** + * @var Suite + */ + private $suite; + + /** + * Initializes exception. + * + * @param string $message + * @param Suite $suite + */ + public function __construct($message, Suite $suite) + { + $this->suite = $suite; + + parent::__construct($message); + } + + /** + * Returns suite that caused exception. + * + * @return Suite + */ + public function getSuite() + { + return $this->suite; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentException.php b/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentException.php new file mode 100644 index 0000000..4b8579f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment\Exception; + +use Behat\Testwork\Exception\TestworkException; + +/** + * All environment exceptions should implement this interface. + * + * @author Konstantin Kudryashov + */ +interface EnvironmentException extends TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentIsolationException.php b/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentIsolationException.php new file mode 100644 index 0000000..6f517ae --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentIsolationException.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment\Exception; + +use Behat\Testwork\Environment\Environment; +use RuntimeException; + +/** + * Represents exception thrown during environment isolation process. + * + * @author Konstantin Kudryashov + */ +final class EnvironmentIsolationException extends RuntimeException implements EnvironmentException +{ + /** + * @var Environment + */ + private $environment; + /** + * @var mixed + */ + private $subject; + + /** + * Initializes exception. + * + * @param string $message + * @param Environment $environment + * @param mixed $testSubject + */ + public function __construct($message, Environment $environment, $testSubject = null) + { + $this->environment = $environment; + $this->subject = $testSubject; + + parent::__construct($message); + } + + /** + * Returns environment that caused exception. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * Returns test subject that caused exception. + * + * @return mixed + */ + public function getSubject() + { + return $this->subject; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentReadException.php b/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentReadException.php new file mode 100644 index 0000000..07ed513 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/Exception/EnvironmentReadException.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment\Exception; + +use Behat\Testwork\Environment\Environment; +use RuntimeException; + +/** + * Represents exception thrown during an environment read. + * + * @author Konstantin Kudryashov + */ +final class EnvironmentReadException extends RuntimeException implements EnvironmentException +{ + /** + * @var Environment + */ + private $environment; + + /** + * Initializes exception. + * + * @param string $message + * @param Environment $environment + */ + public function __construct($message, Environment $environment) + { + $this->environment = $environment; + + parent::__construct($message); + } + + /** + * Returns environment that caused exception. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/Handler/EnvironmentHandler.php b/vendor/behat/behat/src/Behat/Testwork/Environment/Handler/EnvironmentHandler.php new file mode 100644 index 0000000..f2b6b98 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/Handler/EnvironmentHandler.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment\Handler; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Environment\EnvironmentManager; +use Behat\Testwork\Suite\Suite; + +/** + * Handles test environment building and isolation. + * + * @see EnvironmentManager + * + * @author Konstantin Kudryashov + */ +interface EnvironmentHandler +{ + /** + * Checks if handler supports provided suite. + * + * @param Suite $suite + * + * @return Boolean + */ + public function supportsSuite(Suite $suite); + + /** + * Builds environment object based on provided suite. + * + * @param Suite $suite + * + * @return Environment + */ + public function buildEnvironment(Suite $suite); + + /** + * Checks if handler supports provided environment. + * + * @param Environment $environment + * @param mixed $testSubject + * + * @return Boolean + */ + public function supportsEnvironmentAndSubject(Environment $environment, $testSubject = null); + + /** + * Isolates provided environment. + * + * @param Environment $environment + * @param mixed $testSubject + * + * @return Environment + */ + public function isolateEnvironment(Environment $environment, $testSubject = null); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/Handler/StaticEnvironmentHandler.php b/vendor/behat/behat/src/Behat/Testwork/Environment/Handler/StaticEnvironmentHandler.php new file mode 100644 index 0000000..6b399cc --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/Handler/StaticEnvironmentHandler.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment\Handler; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Environment\StaticEnvironment; +use Behat\Testwork\Suite\Suite; + +/** + * Represents environment handler based on static calls (without any isolation). + * + * @author Konstantin Kudryashov + */ +final class StaticEnvironmentHandler implements EnvironmentHandler +{ + /** + * {@inheritdoc} + */ + public function supportsSuite(Suite $suite) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function buildEnvironment(Suite $suite) + { + return new StaticEnvironment($suite); + } + + /** + * {@inheritdoc} + */ + public function supportsEnvironmentAndSubject(Environment $environment, $testSubject = null) + { + return $environment instanceof StaticEnvironment; + } + + /** + * {@inheritdoc} + */ + public function isolateEnvironment(Environment $environment, $testSubject = null) + { + return $environment; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/Reader/EnvironmentReader.php b/vendor/behat/behat/src/Behat/Testwork/Environment/Reader/EnvironmentReader.php new file mode 100644 index 0000000..dcf66fd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/Reader/EnvironmentReader.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment\Reader; + +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Environment\EnvironmentManager; + +/** + * Reads callees from a provided environment. + * + * @see EnvironmentManager + * + * @author Konstantin Kudryashov + */ +interface EnvironmentReader +{ + /** + * Checks if reader supports an environment. + * + * @param Environment $environment + * + * @return Boolean + */ + public function supportsEnvironment(Environment $environment); + + /** + * Reads callees from an environment. + * + * @param Environment $environment + * + * @return Callee[] + */ + public function readEnvironmentCallees(Environment $environment); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/ServiceContainer/EnvironmentExtension.php b/vendor/behat/behat/src/Behat/Testwork/Environment/ServiceContainer/EnvironmentExtension.php new file mode 100644 index 0000000..e06f058 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/ServiceContainer/EnvironmentExtension.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment\ServiceContainer; + +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Testwork test environment extension. + * + * Extends testwork with environment services. + * + * @author Konstantin Kudryashov + */ +final class EnvironmentExtension implements Extension +{ + /* + * Available services + */ + const MANAGER_ID = 'environment.manager'; + + /* + * Available extension points + */ + const HANDLER_TAG = 'environment.handler'; + const READER_TAG = 'environment.reader'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'environments'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadManager($container); + $this->loadStaticEnvironmentHandler($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processHandlers($container); + $this->processReaders($container); + } + + /** + * Loads environment manager. + * + * @param ContainerBuilder $container + */ + protected function loadManager(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Environment\EnvironmentManager'); + $container->setDefinition(self::MANAGER_ID, $definition); + } + + /** + * Loads static environments handler. + * + * @param ContainerBuilder $container + */ + protected function loadStaticEnvironmentHandler(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Environment\Handler\StaticEnvironmentHandler'); + $definition->addTag(self::HANDLER_TAG, array('priority' => 0)); + $container->setDefinition(self::HANDLER_TAG . '.static', $definition); + } + + /** + * Processes all environment handlers. + * + * @param ContainerBuilder $container + */ + protected function processHandlers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::HANDLER_TAG); + $definition = $container->getDefinition(self::MANAGER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerEnvironmentHandler', array($reference)); + } + } + + /** + * Processes all environment readers. + * + * @param ContainerBuilder $container + */ + protected function processReaders(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::READER_TAG); + $definition = $container->getDefinition(self::MANAGER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerEnvironmentReader', array($reference)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Environment/StaticEnvironment.php b/vendor/behat/behat/src/Behat/Testwork/Environment/StaticEnvironment.php new file mode 100644 index 0000000..3396b63 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Environment/StaticEnvironment.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Environment; + +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Suite\Suite; + +/** + * Represents static calls environment. + * + * @author Konstantin Kudryashov + */ +class StaticEnvironment implements Environment +{ + /** + * @var Suite + */ + private $suite; + + /** + * Initializes environment. + * + * @param Suite $suite + */ + public function __construct(Suite $suite) + { + $this->suite = $suite; + } + + /** + * {@inheritdoc} + */ + final public function getSuite() + { + return $this->suite; + } + + /** + * {@inheritdoc} + */ + final public function bindCallee(Callee $callee) + { + return $callee->getCallable(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Cli/SigintController.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Cli/SigintController.php new file mode 100644 index 0000000..24a639c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Cli/SigintController.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Cli; + +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\EventDispatcher\Event\AfterExerciseAborted; +use Behat\Testwork\EventDispatcher\Event\ExerciseCompleted; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Aborts exercise on SIGINT signal. + * + * @author Konstantin Kudryashov + */ +final class SigintController implements Controller +{ + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * Initializes controller. + * + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(EventDispatcherInterface $eventDispatcher) + { + $this->eventDispatcher = $eventDispatcher; + } + + /** + * {@inheritdoc} + */ + public function configure(Command $command) + { + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + if (function_exists('pcntl_signal')) { + declare(ticks = 1); + pcntl_signal(SIGINT, array($this, 'abortExercise')); + } + } + + /** + * Dispatches AFTER exercise event and exits program. + */ + public function abortExercise() + { + $this->eventDispatcher->dispatch(ExerciseCompleted::AFTER, new AfterExerciseAborted()); + + exit(1); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseAborted.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseAborted.php new file mode 100644 index 0000000..18c9aae --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseAborted.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +/** + * Represents an event in which exercise was aborted. + * + * @author Konstantin Kudryashov + */ +final class AfterExerciseAborted extends ExerciseCompleted +{ + /** + * {@inheritdoc} + */ + public function getSpecificationIterators() + { + return array(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseCompleted.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseCompleted.php new file mode 100644 index 0000000..b2eec9f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseCompleted.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents an event in which exercise was completed. + * + * @author Konstantin Kudryashov + */ +final class AfterExerciseCompleted extends ExerciseCompleted implements AfterTested +{ + /** + * @var SpecificationIterator[] + */ + private $specificationIterators; + /** + * @var TestResult + */ + private $result; + /** + * @var Teardown + */ + private $teardown; + + /** + * Initializes event. + * + * @param SpecificationIterator[] $specificationIterators + * @param TestResult $result + * @param Teardown $teardown + */ + public function __construct(array $specificationIterators, TestResult $result, Teardown $teardown) + { + $this->specificationIterators = $specificationIterators; + $this->result = $result; + $this->teardown = $teardown; + } + + /** + * Returns specification iterators. + * + * @return SpecificationIterator[] + */ + public function getSpecificationIterators() + { + return $this->specificationIterators; + } + + /** + * Returns exercise test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } + + /** + * Returns exercise teardown result. + * + * @return Teardown + */ + public function getTeardown() + { + return $this->teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseSetup.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseSetup.php new file mode 100644 index 0000000..b77de06 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterExerciseSetup.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Setup\Setup; + +/** + * Represents an event in which exercise is prepared to be executed. + * + * @author Konstantin Kudryashov + */ +final class AfterExerciseSetup extends ExerciseCompleted implements AfterSetup +{ + /** + * @var SpecificationIterator[] + */ + private $specificationIterators; + /** + * @var Setup + */ + private $setup; + + /** + * Initializes event. + * + * @param SpecificationIterator[] $specificationIterators + * @param Setup $setup + */ + public function __construct(array $specificationIterators, Setup $setup) + { + $this->specificationIterators = $specificationIterators; + $this->setup = $setup; + } + + /** + * Returns specification iterators. + * + * @return SpecificationIterator[] + */ + public function getSpecificationIterators() + { + return $this->specificationIterators; + } + + /** + * Returns exercise setup result. + * + * @return Setup + */ + public function getSetup() + { + return $this->setup; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSetup.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSetup.php new file mode 100644 index 0000000..f820caf --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSetup.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Tester\Setup\Setup; + +/** + * Represents an event right after a test setup. + * + * @author Konstantin Kudryashov + */ +interface AfterSetup +{ + /** + * Returns current test setup. + * + * @return Setup + */ + public function getSetup(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteAborted.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteAborted.php new file mode 100644 index 0000000..97c8a7a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteAborted.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Specification\NoSpecificationsIterator; + +/** + * Represents an event in which suite was aborted. + * + * @author Konstantin Kudryashov + */ +final class AfterSuiteAborted extends SuiteTested +{ + /** + * {@inheritdoc} + */ + public function getSpecificationIterator() + { + return new NoSpecificationsIterator($this->getSuite()); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteSetup.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteSetup.php new file mode 100644 index 0000000..591e54b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteSetup.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Setup\Setup; + +/** + * Represents an event right after a suite setup. + * + * @author Konstantin Kudryashov + */ +final class AfterSuiteSetup extends SuiteTested implements AfterSetup +{ + /** + * @var SpecificationIterator + */ + private $iterator; + /** + * @var Setup + */ + private $setup; + + /** + * Initializes event. + * + * @param Environment $env + * @param SpecificationIterator $iterator + * @param Setup $setup + */ + public function __construct(Environment $env, SpecificationIterator $iterator, Setup $setup) + { + parent::__construct($env); + + $this->iterator = $iterator; + $this->setup = $setup; + } + + /** + * Returns specification iterator. + * + * @return SpecificationIterator + */ + public function getSpecificationIterator() + { + return $this->iterator; + } + + /** + * Returns current test setup. + * + * @return Setup + */ + public function getSetup() + { + return $this->setup; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteTested.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteTested.php new file mode 100644 index 0000000..b68a4ec --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterSuiteTested.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents an event in which suite was tested. + * + * @author Konstantin Kudryashov + */ +final class AfterSuiteTested extends SuiteTested implements AfterTested +{ + /** + * @var SpecificationIterator + */ + private $iterator; + /** + * @var TestResult + */ + private $result; + /** + * @var Teardown + */ + private $teardown; + + /** + * Initializes event. + * + * @param Environment $env + * @param SpecificationIterator $iterator + * @param TestResult $result + * @param Teardown $teardown + */ + public function __construct( + Environment $env, + SpecificationIterator $iterator, + TestResult $result, + Teardown $teardown + ) { + parent::__construct($env); + + $this->iterator = $iterator; + $this->result = $result; + $this->teardown = $teardown; + } + + /** + * Returns specification iterator. + * + * @return SpecificationIterator + */ + public function getSpecificationIterator() + { + return $this->iterator; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } + + /** + * Returns current test teardown. + * + * @return Teardown + */ + public function getTeardown() + { + return $this->teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterTested.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterTested.php new file mode 100644 index 0000000..1bec416 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/AfterTested.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents an event right after a test was completed. + * + * @author Konstantin Kudryashov + */ +interface AfterTested +{ + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult(); + + /** + * Returns current test teardown. + * + * @return Teardown + */ + public function getTeardown(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeExerciseCompleted.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeExerciseCompleted.php new file mode 100644 index 0000000..dc0a22c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeExerciseCompleted.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Specification\SpecificationIterator; + +/** + * Represents an event in which exercise is prepared to be executed. + * + * @author Konstantin Kudryashov + */ +final class BeforeExerciseCompleted extends ExerciseCompleted implements BeforeTested +{ + /** + * @var SpecificationIterator[] + */ + private $specificationIterators; + + /** + * Initializes event. + * + * @param SpecificationIterator[] $specificationIterators + */ + public function __construct(array $specificationIterators) + { + $this->specificationIterators = $specificationIterators; + } + + /** + * Returns specification iterators. + * + * @return SpecificationIterator[] + */ + public function getSpecificationIterators() + { + return $this->specificationIterators; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeExerciseTeardown.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeExerciseTeardown.php new file mode 100644 index 0000000..5892a08 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeExerciseTeardown.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an event right before exercise teardown. + * + * @author Konstantin Kudryashov + */ +final class BeforeExerciseTeardown extends ExerciseCompleted implements BeforeTeardown +{ + /** + * @var SpecificationIterator[] + */ + private $specificationIterators; + /** + * @var TestResult + */ + private $result; + + /** + * Initializes event. + * + * @param SpecificationIterator[] $specificationIterators + * @param TestResult $result + */ + public function __construct(array $specificationIterators, TestResult $result) + { + $this->specificationIterators = $specificationIterators; + $this->result = $result; + } + + /** + * Returns specification iterators. + * + * @return SpecificationIterator[] + */ + public function getSpecificationIterators() + { + return $this->specificationIterators; + } + + /** + * Returns exercise test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeSuiteTeardown.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeSuiteTeardown.php new file mode 100644 index 0000000..3138217 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeSuiteTeardown.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an event right before suite teardown. + * + * @author Konstantin Kudryashov + */ +final class BeforeSuiteTeardown extends SuiteTested implements BeforeTeardown +{ + /** + * @var SpecificationIterator + */ + private $iterator; + /** + * @var TestResult + */ + private $result; + + /** + * Initializes event. + * + * @param Environment $env + * @param SpecificationIterator $iterator + * @param TestResult $result + */ + public function __construct(Environment $env, SpecificationIterator $iterator, TestResult $result) + { + parent::__construct($env); + + $this->iterator = $iterator; + $this->result = $result; + } + + /** + * Returns specification iterator. + * + * @return SpecificationIterator + */ + public function getSpecificationIterator() + { + return $this->iterator; + } + + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeSuiteTested.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeSuiteTested.php new file mode 100644 index 0000000..819be30 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeSuiteTested.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Specification\SpecificationIterator; + +/** + * Represents an event in which suite is prepared to be tested. + * + * @author Konstantin Kudryashov + */ +final class BeforeSuiteTested extends SuiteTested implements BeforeTested +{ + /** + * @var SpecificationIterator + */ + private $iterator; + + /** + * Initializes event. + * + * @param Environment $env + * @param SpecificationIterator $iterator + */ + public function __construct(Environment $env, SpecificationIterator $iterator) + { + parent::__construct($env); + + $this->iterator = $iterator; + } + + /** + * Returns specification iterator. + * + * @return SpecificationIterator + */ + public function getSpecificationIterator() + { + return $this->iterator; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeTeardown.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeTeardown.php new file mode 100644 index 0000000..66a82c6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeTeardown.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents an event right before a teardown. + * + * @author Konstantin Kudryashov + */ +interface BeforeTeardown +{ + /** + * Returns current test result. + * + * @return TestResult + */ + public function getTestResult(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeTested.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeTested.php new file mode 100644 index 0000000..27e9728 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/BeforeTested.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +/** + * Represents an event just before test setup is started. + * + * @author Konstantin Kudryashov + */ +interface BeforeTested +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/ExerciseCompleted.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/ExerciseCompleted.php new file mode 100644 index 0000000..026592b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/ExerciseCompleted.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Specification\SpecificationIterator; +use Symfony\Component\EventDispatcher\Event; + +/** + * Represents an exercise event. + * + * @author Konstantin Kudryashov + */ +abstract class ExerciseCompleted extends Event +{ + const BEFORE = 'tester.exercise_completed.before'; + const AFTER_SETUP = 'tester.exercise_completed.after_setup'; + const BEFORE_TEARDOWN = 'tester.exercise_completed.before_teardown'; + const AFTER = 'tester.exercise_completed.after'; + + /** + * Returns specification iterators. + * + * @return SpecificationIterator[] + */ + abstract public function getSpecificationIterators(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/LifecycleEvent.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/LifecycleEvent.php new file mode 100644 index 0000000..50191b4 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/LifecycleEvent.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Suite\Suite; +use Symfony\Component\EventDispatcher\Event; + +/** + * Represents an event which holds references to current suite and environment. + * + * @author Konstantin Kudryashov + */ +abstract class LifecycleEvent extends Event +{ + /** + * @var Environment + */ + private $environment; + + /** + * Initializes scenario event. + * + * @param Environment $env + */ + public function __construct(Environment $env) + { + $this->environment = $env; + } + + /** + * Returns suite in which this event was fired. + * + * @return Suite + */ + public function getSuite() + { + return $this->environment->getSuite(); + } + + /** + * Returns environment in which this event was fired. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->environment; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/SuiteTested.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/SuiteTested.php new file mode 100644 index 0000000..2ded66a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Event/SuiteTested.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Event; + +use Behat\Testwork\Specification\SpecificationIterator; + +/** + * Represents a suite event. + * + * @author Konstantin Kudryashov + */ +abstract class SuiteTested extends LifecycleEvent +{ + const BEFORE = 'tester.suite_tested.before'; + const AFTER_SETUP = 'tester.suite_tested.after_setup'; + const BEFORE_TEARDOWN = 'tester.suite_tested.before_teardown'; + const AFTER = 'tester.suite_tested.after'; + + /** + * Returns specification iterator. + * + * @return SpecificationIterator + */ + abstract public function getSpecificationIterator(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/ServiceContainer/EventDispatcherExtension.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/ServiceContainer/EventDispatcherExtension.php new file mode 100644 index 0000000..72376da --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/ServiceContainer/EventDispatcherExtension.php @@ -0,0 +1,165 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Tester\ServiceContainer\TesterExtension; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides event dispatching service. + * + * @author Konstantin Kudryashov + */ +class EventDispatcherExtension implements Extension +{ + /* + * Available services + */ + const DISPATCHER_ID = 'event_dispatcher'; + + /* + * Available extension points + */ + const SUBSCRIBER_TAG = 'event_dispatcher.subscriber'; + + /** + * @var ServiceProcessor + */ + protected $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'events'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadSigintController($container); + $this->loadEventDispatcher($container); + $this->loadEventDispatchingExercise($container); + $this->loadEventDispatchingSuiteTester($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processSubscribers($container); + } + + /** + * Loads sigint controller + * + * @param ContainerBuilder $container + */ + protected function loadSigintController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\EventDispatcher\Cli\SigintController', array( + new Reference(EventDispatcherExtension::DISPATCHER_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 9999)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.sigint', $definition); + } + + /** + * Loads event dispatcher. + * + * @param ContainerBuilder $container + */ + protected function loadEventDispatcher(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\EventDispatcher\TestworkEventDispatcher'); + $container->setDefinition(self::DISPATCHER_ID, $definition); + } + + /** + * Loads event-dispatching exercise. + * + * @param ContainerBuilder $container + */ + protected function loadEventDispatchingExercise(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\EventDispatcher\Tester\EventDispatchingExercise', array( + new Reference(TesterExtension::EXERCISE_ID), + new Reference(self::DISPATCHER_ID) + )); + $definition->addTag(TesterExtension::EXERCISE_WRAPPER_TAG); + $container->setDefinition(TesterExtension::EXERCISE_WRAPPER_TAG . '.event_dispatching', $definition); + } + + /** + * Loads event-dispatching suite tester. + * + * @param ContainerBuilder $container + */ + protected function loadEventDispatchingSuiteTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\EventDispatcher\Tester\EventDispatchingSuiteTester', array( + new Reference(TesterExtension::SUITE_TESTER_ID), + new Reference(self::DISPATCHER_ID) + )); + $definition->addTag(TesterExtension::SUITE_TESTER_WRAPPER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::SUITE_TESTER_WRAPPER_TAG . '.event_dispatching', $definition); + } + + /** + * Registers all available event subscribers. + * + * @param ContainerBuilder $container + */ + protected function processSubscribers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::SUBSCRIBER_TAG); + $definition = $container->getDefinition(self::DISPATCHER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('addSubscriber', array($reference)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Tester/EventDispatchingExercise.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Tester/EventDispatchingExercise.php new file mode 100644 index 0000000..10f3419 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Tester/EventDispatchingExercise.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Tester; + +use Behat\Testwork\EventDispatcher\Event\AfterExerciseCompleted; +use Behat\Testwork\EventDispatcher\Event\AfterExerciseSetup; +use Behat\Testwork\EventDispatcher\Event\BeforeExerciseCompleted; +use Behat\Testwork\EventDispatcher\Event\BeforeExerciseTeardown; +use Behat\Testwork\Tester\Exercise; +use Behat\Testwork\Tester\Result\TestResult; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Exercise dispatching BEFORE/AFTER events during its execution. + * + * @author Konstantin Kudryashov + */ +final class EventDispatchingExercise implements Exercise +{ + /** + * @var Exercise + */ + private $baseExercise; + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * Initializes exercise. + * + * @param Exercise $baseExercise + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(Exercise $baseExercise, EventDispatcherInterface $eventDispatcher) + { + $this->baseExercise = $baseExercise; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(array $iterators, $skip) + { + $event = new BeforeExerciseCompleted($iterators); + $this->eventDispatcher->dispatch($event::BEFORE, $event); + + $setup = $this->baseExercise->setUp($iterators, $skip); + + $event = new AfterExerciseSetup($iterators, $setup); + $this->eventDispatcher->dispatch($event::AFTER_SETUP, $event); + + return $setup; + } + + /** + * {@inheritdoc} + */ + public function test(array $iterators, $skip = false) + { + return $this->baseExercise->test($iterators, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(array $iterators, $skip, TestResult $result) + { + $event = new BeforeExerciseTeardown($iterators, $result); + $this->eventDispatcher->dispatch($event::BEFORE_TEARDOWN, $event); + + $teardown = $this->baseExercise->tearDown($iterators, $skip, $result); + + $event = new AfterExerciseCompleted($iterators, $result, $teardown); + $this->eventDispatcher->dispatch($event::AFTER, $event); + + return $teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Tester/EventDispatchingSuiteTester.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Tester/EventDispatchingSuiteTester.php new file mode 100644 index 0000000..84b2d07 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/Tester/EventDispatchingSuiteTester.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher\Tester; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\EventDispatcher\Event\AfterSuiteSetup; +use Behat\Testwork\EventDispatcher\Event\AfterSuiteTested; +use Behat\Testwork\EventDispatcher\Event\BeforeSuiteTeardown; +use Behat\Testwork\EventDispatcher\Event\BeforeSuiteTested; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\SuiteTester; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Suite tester dispatching BEFORE/AFTER events during testing. + * + * @author Konstantin Kudryashov + */ +final class EventDispatchingSuiteTester implements SuiteTester +{ + /** + * @var SuiteTester + */ + private $baseTester; + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + + /** + * Initializes tester. + * + * @param SuiteTester $baseTester + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(SuiteTester $baseTester, EventDispatcherInterface $eventDispatcher) + { + $this->baseTester = $baseTester; + $this->eventDispatcher = $eventDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, SpecificationIterator $iterator, $skip) + { + $event = new BeforeSuiteTested($env, $iterator); + $this->eventDispatcher->dispatch($event::BEFORE, $event); + + $setup = $this->baseTester->setUp($env, $iterator, $skip); + + $event = new AfterSuiteSetup($env, $iterator, $setup); + $this->eventDispatcher->dispatch($event::AFTER_SETUP, $event); + + return $setup; + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, SpecificationIterator $iterator, $skip = false) + { + return $this->baseTester->test($env, $iterator, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, SpecificationIterator $iterator, $skip, TestResult $result) + { + $event = new BeforeSuiteTeardown($env, $iterator, $result); + $this->eventDispatcher->dispatch($event::BEFORE_TEARDOWN, $event); + + $teardown = $this->baseTester->tearDown($env, $iterator, $skip, $result); + + $event = new AfterSuiteTested($env, $iterator, $result, $teardown); + $this->eventDispatcher->dispatch($event::AFTER, $event); + + return $teardown; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/TestworkEventDispatcher.php b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/TestworkEventDispatcher.php new file mode 100644 index 0000000..c1200f3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/EventDispatcher/TestworkEventDispatcher.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\EventDispatcher; + +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; + +/** + * Extends Symfony2 event dispatcher with catch-all listeners. + * + * @author Konstantin Kudryashov + */ +final class TestworkEventDispatcher extends EventDispatcher +{ + const BEFORE_ALL_EVENTS = '*~'; + const AFTER_ALL_EVENTS = '~*'; + + /** + * {@inheritdoc} + */ + public function dispatch($eventName, Event $event = null) + { + if (null === $event) { + $event = new Event(); + } + + if (method_exists($event, 'setName')) { + $event->setName($eventName); + } + + $this->doDispatch($this->getListeners($eventName), $eventName, $event); + + return $event; + } + + /** + * {@inheritdoc} + */ + public function getListeners($eventName = null) + { + if (null == $eventName || self::BEFORE_ALL_EVENTS === $eventName) { + return parent::getListeners($eventName); + } + + return array_merge( + parent::getListeners(self::BEFORE_ALL_EVENTS), + parent::getListeners($eventName), + parent::getListeners(self::AFTER_ALL_EVENTS) + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Exception/Cli/VerbosityController.php b/vendor/behat/behat/src/Behat/Testwork/Exception/Cli/VerbosityController.php new file mode 100644 index 0000000..bc86fb5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Exception/Cli/VerbosityController.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Exception\Cli; + +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\Exception\ExceptionPresenter; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Controls exception default verbosity level. + * + * @author Konstantin Kudryashov + */ +final class VerbosityController implements Controller +{ + /** + * @var ExceptionPresenter + */ + private $exceptionPresenter; + + /** + * Initializes controller. + * + * @param ExceptionPresenter $exceptionPresenter + */ + public function __construct(ExceptionPresenter $exceptionPresenter) + { + $this->exceptionPresenter = $exceptionPresenter; + } + + /** + * Configures command to be executable by the controller. + * + * @param Command $command + */ + public function configure(Command $command) + { + } + + /** + * Executes controller. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return null|integer + */ + public function execute(InputInterface $input, OutputInterface $output) + { + if ($output->getVerbosity() !== OutputInterface::VERBOSITY_NORMAL) { + $this->exceptionPresenter->setDefaultVerbosity($output->getVerbosity()); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Exception/ExceptionPresenter.php b/vendor/behat/behat/src/Behat/Testwork/Exception/ExceptionPresenter.php new file mode 100644 index 0000000..fce59bb --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Exception/ExceptionPresenter.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Exception; + +use Behat\Testwork\Exception\Stringer\ExceptionStringer; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Exception; + +/** + * Presents exceptions as strings using registered stringers. + * + * @author Konstantin Kudryashov + */ +final class ExceptionPresenter +{ + /** + * @var string + */ + private $basePath; + + /** + * @var ExceptionStringer[] + */ + private $stringers = array(); + /** + * @var integer + */ + private $defaultVerbosity = OutputPrinter::VERBOSITY_NORMAL; + + /** + * Initializes presenter. + * + * @param string $basePath + * @param integer $defaultVerbosity + */ + public function __construct($basePath = null, $defaultVerbosity = OutputPrinter::VERBOSITY_NORMAL) + { + if (null !== $basePath) { + $realBasePath = realpath($basePath); + + if ($realBasePath) { + $basePath = $realBasePath; + } + } + + $this->basePath = $basePath; + $this->defaultVerbosity = $defaultVerbosity; + } + + /** + * Registers exception stringer. + * + * @param ExceptionStringer $stringer + */ + public function registerExceptionStringer(ExceptionStringer $stringer) + { + $this->stringers[] = $stringer; + } + + /** + * Sets default verbosity to a specified level. + * + * @param integer $defaultVerbosity + */ + public function setDefaultVerbosity($defaultVerbosity) + { + $this->defaultVerbosity = $defaultVerbosity; + } + + /** + * Presents exception as a string. + * + * @param Exception $exception + * @param integer $verbosity + * + * @return string + */ + public function presentException(Exception $exception, $verbosity = null) + { + $verbosity = $verbosity ?: $this->defaultVerbosity; + + foreach ($this->stringers as $stringer) { + if ($stringer->supportsException($exception)) { + return $this->relativizePaths($stringer->stringException($exception, $verbosity)); + } + } + + if (OutputPrinter::VERBOSITY_VERY_VERBOSE <= $verbosity) { + return $this->relativizePaths(trim($exception)); + } + + return trim($this->relativizePaths($exception->getMessage()) . ' (' . get_class($exception) . ')'); + } + + /** + * Relativizes absolute paths in the text. + * + * @param string $text + * + * @return string + */ + private function relativizePaths($text) + { + if (!$this->basePath) { + return $text; + } + + return str_replace($this->basePath . DIRECTORY_SEPARATOR, '', $text); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Exception/ServiceContainer/ExceptionExtension.php b/vendor/behat/behat/src/Behat/Testwork/Exception/ServiceContainer/ExceptionExtension.php new file mode 100644 index 0000000..ac89715 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Exception/ServiceContainer/ExceptionExtension.php @@ -0,0 +1,169 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Exception\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides exception handling services. + * + * @author Konstantin Kudryashov + */ +final class ExceptionExtension implements Extension +{ + /* + * Available services + */ + const PRESENTER_ID = 'exception.presenter'; + + /* + * Available extension points + */ + const STRINGER_TAG = 'exception.stringer'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'exceptions'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + $builder + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('verbosity') + ->info('Output verbosity') + ->example(sprintf('%d, %d, %d, %d', + OutputPrinter::VERBOSITY_NORMAL, + OutputPrinter::VERBOSITY_VERBOSE, + OutputPrinter::VERBOSITY_VERY_VERBOSE, + OutputPrinter::VERBOSITY_DEBUG + )) + ->defaultValue(OutputPrinter::VERBOSITY_NORMAL) + ->end() + ->end() + ; + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadPresenter($container, $config['verbosity']); + $this->loadDefaultStringers($container); + $this->loadVerbosityController($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processStringers($container); + } + + /** + * Loads exception presenter. + * + * @param ContainerBuilder $container + * @param integer $verbosity + */ + protected function loadPresenter(ContainerBuilder $container, $verbosity) + { + $definition = new Definition('Behat\Testwork\Exception\ExceptionPresenter', array( + '%paths.base%', + $verbosity + )); + $container->setDefinition(self::PRESENTER_ID, $definition); + } + + /** + * Loads default stringer. + * + * @param ContainerBuilder $container + */ + protected function loadDefaultStringers(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Exception\Stringer\PHPUnitExceptionStringer'); + $definition->addTag(self::STRINGER_TAG, array('priority' => 50)); + $container->setDefinition(self::STRINGER_TAG . '.phpunit', $definition); + + $definition = new Definition('Behat\Testwork\Exception\Stringer\TestworkExceptionStringer'); + $definition->addTag(self::STRINGER_TAG, array('priority' => 50)); + $container->setDefinition(self::STRINGER_TAG . '.testwork', $definition); + } + + /** + * Processes all available exception stringers. + * + * @param ContainerBuilder $container + */ + protected function processStringers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::STRINGER_TAG); + $definition = $container->getDefinition(self::PRESENTER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerExceptionStringer', array($reference)); + } + } + + /** + * Loads verbosity controller. + * + * @param ContainerBuilder $container + */ + protected function loadVerbosityController($container) + { + $definition = new Definition('Behat\Testwork\Exception\Cli\VerbosityController', array( + new Reference(self::PRESENTER_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 9999)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.exception_verbosity', $definition); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/ExceptionStringer.php b/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/ExceptionStringer.php new file mode 100644 index 0000000..eab7061 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/ExceptionStringer.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Exception\Stringer; + +use Behat\Testwork\Exception\ExceptionPresenter; +use Exception; + +/** + * Finds a best way to present as a string particular. + * + * @see ExceptionPresenter + * + * @author Konstantin Kudryashov + */ +interface ExceptionStringer +{ + /** + * Checks if stringer supports provided exception. + * + * @param Exception $exception + * + * @return Boolean + */ + public function supportsException(Exception $exception); + + /** + * Strings provided exception. + * + * @param Exception $exception + * @param integer $verbosity + * + * @return string + */ + public function stringException(Exception $exception, $verbosity); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/PHPUnitExceptionStringer.php b/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/PHPUnitExceptionStringer.php new file mode 100644 index 0000000..3534924 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/PHPUnitExceptionStringer.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Exception\Stringer; + +use Exception; +use PHPUnit_Framework_Exception; +use PHPUnit_Framework_TestFailure; + +/** + * Strings PHPUnit assertion exceptions. + * + * @see ExceptionPresenter + * + * @author Konstantin Kudryashov + */ +final class PHPUnitExceptionStringer implements ExceptionStringer +{ + /** + * {@inheritdoc} + */ + public function supportsException(Exception $exception) + { + return $exception instanceof PHPUnit_Framework_Exception; + } + + /** + * {@inheritdoc} + */ + public function stringException(Exception $exception, $verbosity) + { + // PHPUnit assertion exceptions do not include expected / observed info in their + // messages, but expect the test listeners to format that info like the following + // (see e.g. PHPUnit_TextUI_ResultPrinter::printDefectTrace) + return trim(PHPUnit_Framework_TestFailure::exceptionToString($exception)); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/TestworkExceptionStringer.php b/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/TestworkExceptionStringer.php new file mode 100644 index 0000000..5a5e599 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/TestworkExceptionStringer.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Exception\Stringer; + +use Behat\Testwork\Call\Exception\CallErrorException; +use Behat\Testwork\Exception\TestworkException; +use Exception; + +/** + * Strings Testwork exceptions. + * + * @author Konstantin Kudryashov + */ +final class TestworkExceptionStringer implements ExceptionStringer +{ + /** + * {@inheritdoc} + */ + public function supportsException(Exception $exception) + { + return $exception instanceof TestworkException || $exception instanceof CallErrorException; + } + + /** + * {@inheritdoc} + */ + public function stringException(Exception $exception, $verbosity) + { + return trim($exception->getMessage()); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Exception/TestworkException.php b/vendor/behat/behat/src/Behat/Testwork/Exception/TestworkException.php new file mode 100644 index 0000000..a140b00 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Exception/TestworkException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Exception; + +/** + * All testwork exceptions implement this interface. + * + * @author Konstantin Kudryashov + */ +interface TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Filesystem/ConsoleFilesystemLogger.php b/vendor/behat/behat/src/Behat/Testwork/Filesystem/ConsoleFilesystemLogger.php new file mode 100644 index 0000000..d08c498 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Filesystem/ConsoleFilesystemLogger.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Filesystem; + +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Logs filesystem operations to the console. + * + * @author Konstantin Kudryashov + */ +final class ConsoleFilesystemLogger implements FilesystemLogger +{ + /** + * @var string + */ + private $basePath; + /** + * @var OutputInterface + */ + private $output; + + /** + * Initializes logger. + * + * @param string $basePath + * @param OutputInterface $output + */ + public function __construct($basePath, OutputInterface $output) + { + $this->basePath = $basePath; + $this->output = $output; + } + + /** + * {@inheritdoc} + */ + public function directoryCreated($path, $reason) + { + $this->output->writeln( + sprintf( + '+d %s - %s', + str_replace($this->basePath . DIRECTORY_SEPARATOR, '', realpath($path)), + $reason + ) + ); + } + + /** + * {@inheritdoc} + */ + public function fileCreated($path, $reason) + { + $this->output->writeln( + sprintf( + '+f %s - %s', + str_replace($this->basePath . DIRECTORY_SEPARATOR, '', realpath($path)), + $reason + ) + ); + } + + /** + * {@inheritdoc} + */ + public function fileUpdated($path, $reason) + { + $this->output->writeln( + sprintf( + 'u %s - %s', + str_replace($this->basePath . DIRECTORY_SEPARATOR, '', realpath($path)), + $reason + ) + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Filesystem/FilesystemLogger.php b/vendor/behat/behat/src/Behat/Testwork/Filesystem/FilesystemLogger.php new file mode 100644 index 0000000..77f0a75 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Filesystem/FilesystemLogger.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Filesystem; + +/** + * Logs filesystem operations. + * + * @author Konstantin Kudryashov + */ +interface FilesystemLogger +{ + /** + * Logs directory creation. + * + * @param string $path + * @param string $reason + */ + public function directoryCreated($path, $reason); + + /** + * Logs file creation. + * + * @param string $path + * @param string $reason + */ + public function fileCreated($path, $reason); + + /** + * Logs file update. + * + * @param string $path + * @param string $reason + */ + public function fileUpdated($path, $reason); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Filesystem/ServiceContainer/FilesystemExtension.php b/vendor/behat/behat/src/Behat/Testwork/Filesystem/ServiceContainer/FilesystemExtension.php new file mode 100644 index 0000000..4fdc537 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Filesystem/ServiceContainer/FilesystemExtension.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Filesystem\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides filesystem services for testwork. + * + * @author Konstantin Kudryashov + */ +final class FilesystemExtension implements Extension +{ + /* + * Available services + */ + const LOGGER_ID = 'filesystem.logger'; + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'filesystem'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadFilesystemLogger($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + } + + /** + * Loads filesystem logger. + * + * @param ContainerBuilder $container + */ + protected function loadFilesystemLogger(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Filesystem\ConsoleFilesystemLogger', array( + '%paths.base%', + new Reference(CliExtension::OUTPUT_ID) + )); + $container->setDefinition(self::LOGGER_ID, $definition); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Call/AfterSuite.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/AfterSuite.php new file mode 100644 index 0000000..0154d59 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/AfterSuite.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Call; + +use Behat\Testwork\Hook\Scope\SuiteScope; + +/** + * Represents AfterSuite hook. + * + * @author Konstantin Kudryashov + */ +final class AfterSuite extends RuntimeSuiteHook +{ + /** + * Initializes hook. + * + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + */ + public function __construct($filterString, $callable, $description = null) + { + parent::__construct(SuiteScope::AFTER, $filterString, $callable, $description); + } + + /** + * Returns hook name. + * + * @return string + */ + public function getName() + { + return 'AfterSuite'; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Call/BeforeSuite.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/BeforeSuite.php new file mode 100644 index 0000000..e06fb44 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/BeforeSuite.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Call; + +use Behat\Testwork\Hook\Scope\SuiteScope; + +/** + * Represents BeforeSuite hook. + * + * @author Konstantin Kudryashov + */ +final class BeforeSuite extends RuntimeSuiteHook +{ + /** + * Initializes hook. + * + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + */ + public function __construct($filterString, $callable, $description = null) + { + parent::__construct(SuiteScope::BEFORE, $filterString, $callable, $description); + } + + /** + * Returns hook name. + * + * @return string + */ + public function getName() + { + return 'BeforeSuite'; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Call/HookCall.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/HookCall.php new file mode 100644 index 0000000..38b7a0d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/HookCall.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Call; + +use Behat\Testwork\Environment\Call\EnvironmentCall; +use Behat\Testwork\Hook\Hook; +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Represents a hook call. + * + * @author Konstantin Kudryashov + */ +final class HookCall extends EnvironmentCall +{ + /** + * @var HookScope + */ + private $scope; + + /** + * Initializes hook call. + * + * @param HookScope $scope + * @param Hook $hook + * @param null|integer $errorReportingLevel + */ + public function __construct(HookScope $scope, Hook $hook, $errorReportingLevel = null) + { + parent::__construct($scope->getEnvironment(), $hook, array($scope), $errorReportingLevel); + + $this->scope = $scope; + } + + /** + * Returns hook scope. + * + * @return HookScope + */ + public function getScope() + { + return $this->scope; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeFilterableHook.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeFilterableHook.php new file mode 100644 index 0000000..a8d392c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeFilterableHook.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Call; + +use Behat\Testwork\Hook\FilterableHook; + +/** + * Represents runtime hook, filterable by filter string. + * + * @author Konstantin Kudryashov + */ +abstract class RuntimeFilterableHook extends RuntimeHook implements FilterableHook +{ + /** + * @var null|string + */ + private $filterString; + + /** + * Initializes hook. + * + * @param string $scopeName + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + */ + public function __construct($scopeName, $filterString, $callable, $description = null) + { + $this->filterString = $filterString; + + parent::__construct($scopeName, $callable, $description); + } + + /** + * Returns hook filter string (if has one). + * + * @return null|string + */ + public function getFilterString() + { + return $this->filterString; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return trim($this->getName() . ' ' . $this->getFilterString()); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeHook.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeHook.php new file mode 100644 index 0000000..5242fa8 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeHook.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Call; + +use Behat\Testwork\Call\RuntimeCallee; +use Behat\Testwork\Hook\Hook; + +/** + * Represents a hook executed during the execution runtime. + * + * @author Konstantin Kudryashov + */ +abstract class RuntimeHook extends RuntimeCallee implements Hook +{ + /** + * @var string + */ + private $scopeName; + + /** + * Initializes hook. + * + * @param string $scopeName + * @param callable $callable + * @param null|string $description + */ + public function __construct($scopeName, $callable, $description = null) + { + $this->scopeName = $scopeName; + + parent::__construct($callable, $description); + } + + /** + * {@inheritdoc} + */ + public function getScopeName() + { + return $this->scopeName; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return $this->getName(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeSuiteHook.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeSuiteHook.php new file mode 100644 index 0000000..237bc76 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Call/RuntimeSuiteHook.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Call; + +use Behat\Testwork\Call\Exception\BadCallbackException; +use Behat\Testwork\Hook\Scope\HookScope; +use Behat\Testwork\Hook\Scope\SuiteScope; +use Behat\Testwork\Suite\Suite; + +/** + * Represents suite hook executed in the runtime. + * + * @author Konstantin Kudryashov + */ +abstract class RuntimeSuiteHook extends RuntimeFilterableHook +{ + /** + * Initializes hook. + * + * @param string $scopeName + * @param null|string $filterString + * @param callable $callable + * @param null|string $description + * + * @throws BadCallbackException If callback is method, but not a static one + */ + public function __construct($scopeName, $filterString, $callable, $description = null) + { + parent::__construct($scopeName, $filterString, $callable, $description); + + if ($this->isAnInstanceMethod()) { + throw new BadCallbackException(sprintf( + 'Suite hook callback: %s::%s() must be a static method', + $callable[0], + $callable[1] + ), $callable); + } + } + + /** + * {@inheritdoc} + */ + public function filterMatches(HookScope $scope) + { + if (!$scope instanceof SuiteScope) { + return false; + } + if (null === ($filterString = $this->getFilterString())) { + return true; + } + + if (!empty($filterString)) { + return $this->isSuiteMatch($scope->getSuite(), $filterString); + } + + return false; + } + + /** + * Checks if Feature matches specified filter. + * + * @param Suite $suite + * @param string $filterString + * + * @return Boolean + */ + private function isSuiteMatch(Suite $suite, $filterString) + { + if ('/' === $filterString[0]) { + return 1 === preg_match($filterString, $suite->getName()); + } + + return false !== mb_strpos($suite->getName(), $filterString, 0, 'utf8'); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/FilterableHook.php b/vendor/behat/behat/src/Behat/Testwork/Hook/FilterableHook.php new file mode 100644 index 0000000..48ece6a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/FilterableHook.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook; + +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Represents hook that is filterable by the provided scope. + * + * @author Konstantin Kudryashov + */ +interface FilterableHook extends Hook +{ + /** + * Checks that current hook matches provided hook scope. + * + * @param HookScope $scope + * + * @return Boolean + */ + public function filterMatches(HookScope $scope); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Hook.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Hook.php new file mode 100644 index 0000000..19719ec --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Hook.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook; + +use Behat\Testwork\Call\Callee; + +/** + * Represents a Testwork hook. + * + * @author Konstantin Kudryashov + */ +interface Hook extends Callee +{ + /** + * Returns hook name. + * + * @return string + */ + public function getName(); + + /** + * Returns hook scope name. + * + * @return string + */ + public function getScopeName(); + + /** + * Represents hook as a string. + * + * @return string + */ + public function __toString(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/HookDispatcher.php b/vendor/behat/behat/src/Behat/Testwork/Hook/HookDispatcher.php new file mode 100644 index 0000000..0dd7508 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/HookDispatcher.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook; + +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\CallResult; +use Behat\Testwork\Call\CallResults; +use Behat\Testwork\Hook\Call\HookCall; +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Dispatches registered hooks for provided events. + * + * @author Konstantin Kudryashov + */ +final class HookDispatcher +{ + /** + * @var HookRepository + */ + private $repository; + /** + * @var CallCenter + */ + private $callCenter; + + /** + * Initializes hook dispatcher. + * + * @param HookRepository $repository + * @param CallCenter $callCenter + */ + public function __construct(HookRepository $repository, CallCenter $callCenter) + { + $this->repository = $repository; + $this->callCenter = $callCenter; + } + + /** + * Dispatches hooks for a specified event. + * + * @param HookScope $scope + * + * @return CallResults + */ + public function dispatchScopeHooks(HookScope $scope) + { + $results = array(); + foreach ($this->repository->getScopeHooks($scope) as $hook) { + $results[] = $this->dispatchHook($scope, $hook); + } + + return new CallResults($results); + } + + /** + * Dispatches single event hook. + * + * @param HookScope $scope + * @param Hook $hook + * + * @return CallResult + */ + private function dispatchHook(HookScope $scope, Hook $hook) + { + return $this->callCenter->makeCall(new HookCall($scope, $hook)); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/HookRepository.php b/vendor/behat/behat/src/Behat/Testwork/Hook/HookRepository.php new file mode 100644 index 0000000..527a11a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/HookRepository.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook; + +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Environment\EnvironmentManager; +use Behat\Testwork\Hook\Scope\HookScope; + +/** + * Finds hooks using provided environments or scopes. + * + * @author Konstantin Kudryashov + */ +final class HookRepository +{ + /** + * @var EnvironmentManager + */ + private $environmentManager; + + /** + * Initializes repository. + * + * @param EnvironmentManager $environmentManager + */ + public function __construct(EnvironmentManager $environmentManager) + { + $this->environmentManager = $environmentManager; + } + + /** + * Returns all available hooks for a specific environment. + * + * @param Environment $environment + * + * @return Hook[] + */ + public function getEnvironmentHooks(Environment $environment) + { + return array_filter( + $this->environmentManager->readEnvironmentCallees($environment), + function (Callee $callee) { + return $callee instanceof Hook; + } + ); + } + + /** + * Returns hooks for a specific event. + * + * @param HookScope $scope + * + * @return Hook[] + */ + public function getScopeHooks(HookScope $scope) + { + return array_filter( + $this->getEnvironmentHooks($scope->getEnvironment()), + function (Hook $hook) use ($scope) { + if ($scope->getName() !== $hook->getScopeName()) { + return false; + } + + return !($hook instanceof FilterableHook && !$hook->filterMatches($scope)); + } + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/AfterSuiteScope.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/AfterSuiteScope.php new file mode 100644 index 0000000..59b07c7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/AfterSuiteScope.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Scope; + +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents a scope for AfterSuite hook. + * + * @author Konstantin Kudryashov + */ +final class AfterSuiteScope implements SuiteScope, AfterTestScope +{ + /** + * @var Environment + */ + private $environment; + /** + * @var SpecificationIterator + */ + private $iterator; + /** + * @var TestResult + */ + private $result; + + /** + * Initializes scope. + * + * @param Environment $environment + * @param SpecificationIterator $iterator + * @param TestResult $result + */ + public function __construct(Environment $environment, SpecificationIterator $iterator, TestResult $result) + { + $this->environment = $environment; + $this->iterator = $iterator; + $this->result = $result; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return self::AFTER; + } + + /** + * {@inheritdoc} + */ + public function getSuite() + { + return $this->environment->getSuite(); + } + + /** + * {@inheritdoc} + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * {@inheritdoc} + */ + public function getSpecificationIterator() + { + return $this->iterator; + } + + /** + * {@inheritdoc} + */ + public function getTestResult() + { + return $this->result; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/AfterTestScope.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/AfterTestScope.php new file mode 100644 index 0000000..30c5fd5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/AfterTestScope.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Scope; + +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Represents a hook scope for After* hooks. + * + * @author Konstantin Kudryashov + */ +interface AfterTestScope extends HookScope +{ + /** + * Returns test result. + * + * @return TestResult + */ + public function getTestResult(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/BeforeSuiteScope.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/BeforeSuiteScope.php new file mode 100644 index 0000000..5c982cb --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/BeforeSuiteScope.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Scope; + +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Environment\Environment; + +/** + * Represents a scope for BeforeSuite hook. + * + * @author Konstantin Kudryashov + */ +final class BeforeSuiteScope implements SuiteScope +{ + /** + * @var Environment + */ + private $environment; + /** + * @var SpecificationIterator + */ + private $iterator; + + /** + * Initializes scope. + * + * @param Environment $env + * @param SpecificationIterator $iterator + */ + public function __construct(Environment $env, SpecificationIterator $iterator) + { + $this->environment = $env; + $this->iterator = $iterator; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return self::BEFORE; + } + + /** + * {@inheritdoc} + */ + public function getSuite() + { + return $this->environment->getSuite(); + } + + /** + * {@inheritdoc} + */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * {@inheritdoc} + */ + public function getSpecificationIterator() + { + return $this->iterator; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/HookScope.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/HookScope.php new file mode 100644 index 0000000..d7014fd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/HookScope.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Scope; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Hook\HookDispatcher; +use Behat\Testwork\Hook\HookRepository; +use Behat\Testwork\Suite\Suite; + +/** + * Represents an object used to find appropriate hooks. + * + * @see HookDispatcher + * @see HookRepository + * + * @author Konstantin Kudryashov + */ +interface HookScope +{ + /** + * Returns hook scope name. + * + * @return string + */ + public function getName(); + + /** + * Returns hook suite. + * + * @return Suite + */ + public function getSuite(); + + /** + * Returns hook environment. + * + * @return Environment + */ + public function getEnvironment(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/SuiteScope.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/SuiteScope.php new file mode 100644 index 0000000..6cc308f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Scope/SuiteScope.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Scope; + +use Behat\Testwork\Specification\SpecificationIterator; + +/** + * Represents a suite hook. + * + * @author Konstantin Kudryashov + */ +interface SuiteScope extends HookScope +{ + const BEFORE = 'suite.before'; + const AFTER = 'suite.after'; + + /** + * Returns specification iterator. + * + * @return SpecificationIterator + */ + public function getSpecificationIterator(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/ServiceContainer/HookExtension.php b/vendor/behat/behat/src/Behat/Testwork/Hook/ServiceContainer/HookExtension.php new file mode 100644 index 0000000..fee6de4 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/ServiceContainer/HookExtension.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\ServiceContainer; + +use Behat\Behat\Tester\ServiceContainer\TesterExtension; +use Behat\Testwork\Call\ServiceContainer\CallExtension; +use Behat\Testwork\Environment\ServiceContainer\EnvironmentExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides test hooking services for testwork. + * + * @author Konstantin Kudryashov + */ +class HookExtension implements Extension +{ + /* + * Available services + */ + const DISPATCHER_ID = 'hook.dispatcher'; + const REPOSITORY_ID = 'hook.repository'; + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'hooks'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadDispatcher($container); + $this->loadRepository($container); + $this->loadHookableTesters($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + } + + /** + * Loads hook dispatcher. + * + * @param ContainerBuilder $container + */ + protected function loadDispatcher(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Hook\HookDispatcher', array( + new Reference(self::REPOSITORY_ID), + new Reference(CallExtension::CALL_CENTER_ID) + )); + $container->setDefinition(self::DISPATCHER_ID, $definition); + } + + /** + * Loads hook repository. + * + * @param ContainerBuilder $container + */ + protected function loadRepository(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Hook\HookRepository', array( + new Reference(EnvironmentExtension::MANAGER_ID) + )); + $container->setDefinition(self::REPOSITORY_ID, $definition); + } + + /** + * Loads hookable testers. + * + * @param ContainerBuilder $container + */ + protected function loadHookableTesters(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Hook\Tester\HookableSuiteTester', array( + new Reference(TesterExtension::SUITE_TESTER_ID), + new Reference(self::DISPATCHER_ID) + )); + $definition->addTag(TesterExtension::SUITE_TESTER_WRAPPER_TAG, array('priority' => 9999)); + $container->setDefinition(TesterExtension::SUITE_TESTER_WRAPPER_TAG . '.hookable', $definition); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Tester/HookableSuiteTester.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Tester/HookableSuiteTester.php new file mode 100644 index 0000000..1277e82 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Tester/HookableSuiteTester.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Tester; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Hook\HookDispatcher; +use Behat\Testwork\Hook\Scope\AfterSuiteScope; +use Behat\Testwork\Hook\Scope\BeforeSuiteScope; +use Behat\Testwork\Hook\Tester\Setup\HookedSetup; +use Behat\Testwork\Hook\Tester\Setup\HookedTeardown; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\SuiteTester; + +/** + * Suite tester which dispatches hooks during its execution. + * + * @author Konstantin Kudryashov + */ +final class HookableSuiteTester implements SuiteTester +{ + /** + * @var SuiteTester + */ + private $baseTester; + /** + * @var HookDispatcher + */ + private $hookDispatcher; + + /** + * Initializes tester. + * + * @param SuiteTester $baseTester + * @param HookDispatcher $hookDispatcher + */ + public function __construct(SuiteTester $baseTester, HookDispatcher $hookDispatcher) + { + $this->baseTester = $baseTester; + $this->hookDispatcher = $hookDispatcher; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, SpecificationIterator $iterator, $skip) + { + $setup = $this->baseTester->setUp($env, $iterator, $skip); + + if ($skip) { + return $setup; + } + + $scope = new BeforeSuiteScope($env, $iterator); + $hookCallResults = $this->hookDispatcher->dispatchScopeHooks($scope); + + return new HookedSetup($setup, $hookCallResults); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, SpecificationIterator $iterator, $skip) + { + return $this->baseTester->test($env, $iterator, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, SpecificationIterator $iterator, $skip, TestResult $result) + { + $teardown = $this->baseTester->tearDown($env, $iterator, $skip, $result); + + if ($skip) { + return $teardown; + } + + $scope = new AfterSuiteScope($env, $iterator, $result); + $hookCallResults = $this->hookDispatcher->dispatchScopeHooks($scope); + + return new HookedTeardown($teardown, $hookCallResults); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Tester/Setup/HookedSetup.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Tester/Setup/HookedSetup.php new file mode 100644 index 0000000..3ba4478 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Tester/Setup/HookedSetup.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Tester\Setup; + +use Behat\Testwork\Call\CallResults; +use Behat\Testwork\Tester\Setup\Setup; + +/** + * Represents hooked test setup. + * + * @author Konstantin Kudryashov + */ +final class HookedSetup implements Setup +{ + /** + * @var Setup + */ + private $setup; + /** + * @var CallResults + */ + private $hookCallResults; + + /** + * Initializes setup. + * + * @param Setup $setup + * @param CallResults $hookCallResults + */ + public function __construct(Setup $setup, CallResults $hookCallResults) + { + $this->setup = $setup; + $this->hookCallResults = $hookCallResults; + } + + /** + * {@inheritdoc} + */ + public function isSuccessful() + { + if ($this->hookCallResults->hasExceptions()) { + return false; + } + + return $this->setup->isSuccessful(); + } + + /** + * {@inheritdoc} + */ + public function hasOutput() + { + return $this->hookCallResults->hasStdOuts() || $this->hookCallResults->hasExceptions(); + } + + /** + * Returns hook call results. + * + * @return CallResults + */ + public function getHookCallResults() + { + return $this->hookCallResults; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Hook/Tester/Setup/HookedTeardown.php b/vendor/behat/behat/src/Behat/Testwork/Hook/Tester/Setup/HookedTeardown.php new file mode 100644 index 0000000..5400be9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Hook/Tester/Setup/HookedTeardown.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Hook\Tester\Setup; + +use Behat\Testwork\Call\CallResults; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents hooked test teardown. + * + * @author Konstantin Kudryashov + */ +final class HookedTeardown implements Teardown +{ + /** + * @var Teardown + */ + private $teardown; + /** + * @var CallResults + */ + private $hookCallResults; + + /** + * Initializes setup. + * + * @param Teardown $teardown + * @param CallResults $hookCallResults + */ + public function __construct(Teardown $teardown, CallResults $hookCallResults) + { + $this->teardown = $teardown; + $this->hookCallResults = $hookCallResults; + } + + /** + * {@inheritdoc} + */ + public function isSuccessful() + { + if ($this->hookCallResults->hasExceptions()) { + return false; + } + + return $this->teardown->isSuccessful(); + } + + /** + * {@inheritdoc} + */ + public function hasOutput() + { + return $this->hookCallResults->hasStdOuts() || $this->hookCallResults->hasExceptions(); + } + + /** + * Returns hook call results. + * + * @return CallResults + */ + public function getHookCallResults() + { + return $this->hookCallResults; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Cli/OutputController.php b/vendor/behat/behat/src/Behat/Testwork/Output/Cli/OutputController.php new file mode 100644 index 0000000..ae88651 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Cli/OutputController.php @@ -0,0 +1,253 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Cli; + +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\OutputManager; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Configures formatters based on user input. + * + * @author Konstantin Kudryashov + */ +class OutputController implements Controller +{ + /** + * @var OutputManager + */ + private $manager; + + /** + * Initializes controller. + * + * @param OutputManager $manager + */ + public function __construct(OutputManager $manager) + { + $this->manager = $manager; + } + + /** + * {@inheritdoc} + */ + public function configure(Command $command) + { + $command + ->addOption( + '--format', '-f', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'How to format tests output. pretty is default.' . PHP_EOL . + 'Available formats are:' . PHP_EOL . $this->getFormatterDescriptions() . + 'You can use multiple formats at the same time.' + ) + ->addOption( + '--out', '-o', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Write format output to a file/directory instead of' . PHP_EOL . + 'STDOUT (output_path). You can also provide different' . PHP_EOL . + 'outputs to multiple formats.' + ) + ->addOption( + '--format-settings', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, + 'Set formatters parameters using json object.' . PHP_EOL . + 'Keys are parameter names, values are values.' + ); + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $formats = $input->getOption('format'); + $outputs = $input->getOption('out'); + + $this->configureFormatters($formats, $input, $output); + $this->configureOutputs($formats, $outputs, $output->isDecorated()); + } + + /** + * Configures formatters based on container, input and output configurations. + * + * @param array $formats + * @param InputInterface $input + * @param OutputInterface $output + */ + protected function configureFormatters(array $formats, InputInterface $input, OutputInterface $output) + { + $this->enableFormatters($formats); + $this->setFormattersParameters($input, $output); + } + + /** + * Enables formatters. + * + * @param array $formats + */ + protected function enableFormatters(array $formats) + { + if (count($formats)) { + $this->manager->disableAllFormatters(); + foreach ($formats as $format) { + $this->manager->enableFormatter($format); + } + } + } + + /** + * Sets formatters parameters based on input & output. + * + * @param InputInterface $input + * @param OutputInterface $output + */ + protected function setFormattersParameters(InputInterface $input, OutputInterface $output) + { + $this->manager->setFormattersParameter('output_decorate', $output->isDecorated()); + + if ($input->getOption('format-settings')) { + foreach ($input->getOption('format-settings') as $jsonSettings) { + $this->loadJsonSettings($jsonSettings); + } + } + } + + /** + * Locates output path from relative one. + * + * @param string $path + * + * @return string + */ + protected function locateOutputPath($path) + { + if ($this->isAbsolutePath($path)) { + return $path; + } + + $path = getcwd() . DIRECTORY_SEPARATOR . $path; + + if (!file_exists($path)) { + touch($path); + $path = realpath($path); + unlink($path); + } else { + $path = realpath($path); + } + + return $path; + } + + /** + * Initializes multiple formatters with different outputs. + * + * @param array $formats + * @param array $outputs + * @param Boolean $decorated + */ + private function configureOutputs(array $formats, array $outputs, $decorated = false) + { + if (1 == count($outputs) && !$this->isStandardOutput($outputs[0])) { + $outputPath = $this->locateOutputPath($outputs[0]); + + $this->manager->setFormattersParameter('output_path', $outputPath); + $this->manager->setFormattersParameter('output_decorate', $decorated); + + return; + } + + foreach ($outputs as $i => $out) { + if ($this->isStandardOutput($out)) { + continue; + } + + $outputPath = $this->locateOutputPath($out); + if (isset($formats[$i])) { + $this->manager->setFormatterParameter($formats[$i], 'output_path', $outputPath); + $this->manager->setFormatterParameter($formats[$i], 'output_decorate', $decorated); + } + } + } + + /** + * Checks if provided output identifier represents standard output. + * + * @param string $outputId + * + * @return Boolean + */ + private function isStandardOutput($outputId) + { + return 'std' === $outputId || 'null' === $outputId || 'false' === $outputId; + } + + /** + * Returns whether the file path is an absolute path. + * + * @param string $file A file path + * + * @return Boolean + */ + private function isAbsolutePath($file) + { + if ($file[0] == '/' || $file[0] == '\\' + || (strlen($file) > 3 && ctype_alpha($file[0]) + && $file[1] == ':' + && ($file[2] == '\\' || $file[2] == '/') + ) + || null !== parse_url($file, PHP_URL_SCHEME) + ) { + return true; + } + + return false; + } + + /** + * Returns formatters description. + * + * @return string + */ + private function getFormatterDescriptions() + { + return implode( + PHP_EOL, + array_map( + function (Formatter $formatter) { + $comment = '- ' . $formatter->getName() . ': '; + $comment .= $formatter->getDescription(); + + return $comment; + }, $this->manager->getFormatters() + ) + ) . PHP_EOL; + } + + /** + * Loads JSON settings as formatter parameters. + * + * @param string $jsonSettings + */ + private function loadJsonSettings($jsonSettings) + { + $settings = @json_decode($jsonSettings, true); + + if (!is_array($settings)) { + return; + } + + foreach ($settings as $name => $value) { + $this->manager->setFormattersParameter($name, $value); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Exception/BadOutputPathException.php b/vendor/behat/behat/src/Behat/Testwork/Output/Exception/BadOutputPathException.php new file mode 100644 index 0000000..edd773c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Exception/BadOutputPathException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Exception; + +use InvalidArgumentException; + +/** + * Represents an exception thrown because user provided bad output path. + * + * @author Konstantin Kudryashov + */ +class BadOutputPathException extends InvalidArgumentException implements PrinterException +{ + /** + * @var string + */ + private $path; + + /** + * Initializes exception. + * + * @param string $message + * @param string $path + */ + public function __construct($message, $path) + { + $this->path = $path; + + parent::__construct($message); + } + + /** + * Returns exception causing path. + * + * @return string + */ + public function getPath() + { + return $this->path; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Exception/FormatterNotFoundException.php b/vendor/behat/behat/src/Behat/Testwork/Output/Exception/FormatterNotFoundException.php new file mode 100644 index 0000000..43b3371 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Exception/FormatterNotFoundException.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Exception; + +use InvalidArgumentException; + +/** + * Represents an exception thrown because requested formatter is not found. + * + * @author Konstantin Kudryashov + */ +class FormatterNotFoundException extends InvalidArgumentException implements OutputException +{ + /** + * @var string + */ + private $name; + + /** + * Initializes exception. + * + * @param string $message + * @param string $name + */ + public function __construct($message, $name) + { + parent::__construct($message); + } + + /** + * Returns formatter name. + * + * @return string + */ + public function getName() + { + return $this->name; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Exception/OutputException.php b/vendor/behat/behat/src/Behat/Testwork/Output/Exception/OutputException.php new file mode 100644 index 0000000..cba1a7d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Exception/OutputException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Exception; + +use Behat\Testwork\Exception\TestworkException; + +/** + * Represents an output exception. + * + * @author Konstantin Kudryashov + */ +interface OutputException extends TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Exception/PrinterException.php b/vendor/behat/behat/src/Behat/Testwork/Output/Exception/PrinterException.php new file mode 100644 index 0000000..283ed14 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Exception/PrinterException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Exception; + +/** + * Represents a printer exception. + * + * @author Konstantin Kudryashov + */ +interface PrinterException extends OutputException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Formatter.php b/vendor/behat/behat/src/Behat/Testwork/Output/Formatter.php new file mode 100644 index 0000000..23a87c6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Formatter.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output; + +use Behat\Testwork\Output\Printer\OutputPrinter; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * Represents Testwork output formatter. + * + * @see OutputManager + * + * @author Konstantin Kudryashov + */ +interface Formatter extends EventSubscriberInterface +{ + /** + * Returns formatter name. + * + * @return string + */ + public function getName(); + + /** + * Returns formatter description. + * + * @return string + */ + public function getDescription(); + + /** + * Returns formatter output printer. + * + * @return OutputPrinter + */ + public function getOutputPrinter(); + + /** + * Sets formatter parameter. + * + * @param string $name + * @param mixed $value + */ + public function setParameter($name, $value); + + /** + * Returns parameter name. + * + * @param string $name + * + * @return mixed + */ + public function getParameter($name); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Node/EventListener/ChainEventListener.php b/vendor/behat/behat/src/Behat/Testwork/Output/Node/EventListener/ChainEventListener.php new file mode 100644 index 0000000..0c76bac --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Node/EventListener/ChainEventListener.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Node\EventListener; + +use ArrayIterator; +use Behat\Testwork\Output\Formatter; +use Countable; +use IteratorAggregate; +use Symfony\Component\EventDispatcher\Event; + +/** + * Used to compose formatter event listeners. + * + * @author Konstantin Kudryashov + */ +class ChainEventListener implements EventListener, Countable, IteratorAggregate +{ + /** + * @var EventListener[] + */ + private $listeners; + + /** + * Initializes collection. + * + * @param EventListener[] $listeners + */ + public function __construct(array $listeners) + { + $this->listeners = $listeners; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + foreach ($this->listeners as $listener) { + $listener->listenEvent($formatter, $event, $eventName); + } + } + + /** + * {@inheritdoc} + */ + public function count() + { + return count($this->listeners); + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new ArrayIterator($this->listeners); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Node/EventListener/EventListener.php b/vendor/behat/behat/src/Behat/Testwork/Output/Node/EventListener/EventListener.php new file mode 100644 index 0000000..6fbc078 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Node/EventListener/EventListener.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Node\EventListener; + +use Behat\Testwork\Output\Formatter; +use Symfony\Component\EventDispatcher\Event; + +/** + * Used to define formatter event listeners. + * + * @author Konstantin Kudryashov + */ +interface EventListener +{ + /** + * Notifies listener about an event. + * + * @param Formatter $formatter + * @param Event $event + * @param string $eventName + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Node/EventListener/Flow/FireOnlyIfFormatterParameterListener.php b/vendor/behat/behat/src/Behat/Testwork/Output/Node/EventListener/Flow/FireOnlyIfFormatterParameterListener.php new file mode 100644 index 0000000..0df21eb --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Node/EventListener/Flow/FireOnlyIfFormatterParameterListener.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Node\EventListener\Flow; + +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Catches all events, but proxies them only if formatter has specific parameter set to a specific value. + * + * @author Konstantin Kudryashov + */ +class FireOnlyIfFormatterParameterListener implements EventListener +{ + /** + * @var string + */ + private $name; + /** + * @var mixed + */ + private $value; + /** + * @var EventListener + */ + private $descendant; + + /** + * Initializes listener. + * + * @param string $name + * @param mixed $value + * @param EventListener $descendant + */ + public function __construct($name, $value, EventListener $descendant) + { + $this->name = $name; + $this->value = $value; + $this->descendant = $descendant; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + if ($this->value !== $formatter->getParameter($this->name)) { + return; + } + + $this->descendant->listenEvent($formatter, $event, $eventName); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/NodeEventListeningFormatter.php b/vendor/behat/behat/src/Behat/Testwork/Output/NodeEventListeningFormatter.php new file mode 100644 index 0000000..3894d49 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/NodeEventListeningFormatter.php @@ -0,0 +1,126 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output; + +use Behat\Testwork\EventDispatcher\TestworkEventDispatcher; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Behat\Testwork\Output\Printer\OutputPrinter; +use Symfony\Component\EventDispatcher\Event; + +/** + * Formatter built around the idea of event delegation and composition. + * + * @author Konstantin Kudryashov + */ +final class NodeEventListeningFormatter implements Formatter +{ + /** + * @var OutputPrinter + */ + private $printer; + /** + * @var array + */ + private $parameters; + /** + * @var EventListener + */ + private $listener; + /** + * @var string + */ + private $name; + /** + * @var string + */ + private $description; + + /** + * Initializes formatter. + * + * @param string $name + * @param string $description + * @param array $parameters + * @param OutputPrinter $printer + * @param EventListener $listener + */ + public function __construct($name, $description, array $parameters, OutputPrinter $printer, EventListener $listener) + { + $this->name = $name; + $this->description = $description; + $this->parameters = $parameters; + $this->printer = $printer; + $this->listener = $listener; + } + + /** + * Returns an array of event names this subscriber wants to listen to. + * + * @return array The event names to listen to + */ + public static function getSubscribedEvents() + { + return array(TestworkEventDispatcher::BEFORE_ALL_EVENTS => 'listenEvent'); + } + + /** + * Proxies event to the listener. + * + * @param Event $event + * @param null|string $eventName + */ + public function listenEvent(Event $event, $eventName = null) + { + $eventName = $eventName ?: $event->getName(); + + $this->listener->listenEvent($this, $event, $eventName); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function getDescription() + { + return $this->description; + } + + /** + * {@inheritdoc} + */ + public function getOutputPrinter() + { + return $this->printer; + } + + /** + * {@inheritdoc} + */ + public function setParameter($name, $value) + { + $this->parameters[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function getParameter($name) + { + return isset($this->parameters[$name]) ? $this->parameters[$name] : null; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/OutputManager.php b/vendor/behat/behat/src/Behat/Testwork/Output/OutputManager.php new file mode 100644 index 0000000..cdf7760 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/OutputManager.php @@ -0,0 +1,208 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output; + +use Behat\Testwork\Output\Exception\FormatterNotFoundException; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Manages formatters and their configuration. + * + * @author Konstantin Kudryashov + */ +final class OutputManager +{ + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + /** + * @var Formatter[] + */ + private $formatters = array(); + + /** + * Initializes manager. + * + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(EventDispatcherInterface $eventDispatcher) + { + $this->eventDispatcher = $eventDispatcher; + } + + /** + * Registers formatter. + * + * @param Formatter $formatter + */ + public function registerFormatter(Formatter $formatter) + { + if (isset($this->formatters[$formatter->getName()])) { + $this->disableFormatter($formatter->getName()); + } + + $this->formatters[$formatter->getName()] = $formatter; + } + + /** + * Checks if formatter is registered. + * + * @param string $name + * + * @return Boolean + */ + public function isFormatterRegistered($name) + { + return isset($this->formatters[$name]); + } + + /** + * Returns formatter by name provided. + * + * @param string $name + * + * @return Formatter + * + * @throws FormatterNotFoundException + */ + public function getFormatter($name) + { + if (!$this->isFormatterRegistered($name)) { + throw new FormatterNotFoundException(sprintf( + '`%s` formatter is not found or has not been properly registered. Registered formatters: `%s`.', + $name, + implode('`, `', array_keys($this->formatters)) + ), $name); + } + + return $this->formatters[$name]; + } + + /** + * Returns all registered formatters. + * + * @return Formatter[] + */ + public function getFormatters() + { + return $this->formatters; + } + + /** + * Enable formatter by name provided. + * + * @param string $formatter + */ + public function enableFormatter($formatter) + { + if (!$this->isFormatterRegistered($formatter) && class_exists($formatter)) { + $formatterInstance = new $formatter(); + $formatter = $formatterInstance->getName(); + + if (!$this->isFormatterRegistered($formatter)) { + $this->registerFormatter($formatterInstance); + } + } + + $this->eventDispatcher->addSubscriber($this->getFormatter($formatter)); + } + + /** + * Disable formatter by name provided. + * + * @param string $formatter + */ + public function disableFormatter($formatter) + { + $this->eventDispatcher->removeSubscriber($this->getFormatter($formatter)); + } + + /** + * Disable all registered formatters. + */ + public function disableAllFormatters() + { + array_map(array($this, 'disableFormatter'), array_keys($this->formatters)); + } + + /** + * Sets provided parameter to said formatter. + * + * @param string $formatter + * @param string $parameterName + * @param mixed $parameterValue + */ + public function setFormatterParameter($formatter, $parameterName, $parameterValue) + { + $formatter = $this->getFormatter($formatter); + $printer = $formatter->getOutputPrinter(); + + switch ($parameterName) { + case 'output_verbosity': + $printer->setOutputVerbosity($parameterValue); + + return; + case 'output_path': + $printer->setOutputPath($parameterValue); + + return; + case 'output_decorate': + $printer->setOutputDecorated($parameterValue); + + return; + case 'output_styles': + $printer->setOutputStyles($parameterValue); + + return; + } + + $formatter->setParameter($parameterName, $parameterValue); + } + + /** + * Sets provided formatter parameters. + * + * @param string $formatter + * @param array $parameters + */ + public function setFormatterParameters($formatter, array $parameters) + { + foreach ($parameters as $key => $val) { + $this->setFormatterParameter($formatter, $key, $val); + } + } + + /** + * Sets provided parameter to all registered formatters. + * + * @param string $parameterName + * @param mixed $parameterValue + */ + public function setFormattersParameter($parameterName, $parameterValue) + { + foreach (array_keys($this->formatters) as $formatter) { + $this->setFormatterParameter($formatter, $parameterName, $parameterValue); + } + } + + /** + * Sets provided parameters to all registered formatters. + * + * @param array $parameters + */ + public function setFormattersParameters(array $parameters) + { + foreach ($parameters as $key => $val) { + $this->setFormattersParameter($key, $val); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Printer/ConsoleOutputPrinter.php b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/ConsoleOutputPrinter.php new file mode 100644 index 0000000..2d5855d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/ConsoleOutputPrinter.php @@ -0,0 +1,264 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Printer; + +use Behat\Testwork\Output\Exception\BadOutputPathException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\StreamOutput; + +/** + * Symfony2\Console-based output printer. + * + * @author Konstantin Kudryashov + */ +class ConsoleOutputPrinter implements OutputPrinter +{ + /** + * @var null|string + */ + private $outputPath; + /** + * @var array + */ + private $outputStyles = array(); + /** + * @var null|Boolean + */ + private $outputDecorated = null; + /** + * @var integer + */ + private $verbosityLevel = 0; + /** + * @var OutputInterface + */ + private $output; + + /** + * Sets output path. + * + * @param string $path + */ + public function setOutputPath($path) + { + $this->outputPath = $path; + $this->flush(); + } + + /** + * Returns output path. + * + * @return null|string + */ + public function getOutputPath() + { + return $this->outputPath; + } + + /** + * Sets output styles. + * + * @param array $styles + */ + public function setOutputStyles(array $styles) + { + $this->outputStyles = $styles; + $this->flush(); + } + + /** + * Returns output styles. + * + * @return array + */ + public function getOutputStyles() + { + return $this->outputStyles; + } + + /** + * Forces output to be decorated. + * + * @param Boolean $decorated + */ + public function setOutputDecorated($decorated) + { + $this->outputDecorated = $decorated; + $this->flush(); + } + + /** + * Returns output decoration status. + * + * @return null|Boolean + */ + public function isOutputDecorated() + { + return $this->outputDecorated; + } + + /** + * Sets output verbosity level. + * + * @param integer $level + */ + public function setOutputVerbosity($level) + { + $this->verbosityLevel = intval($level); + $this->flush(); + } + + /** + * Returns output verbosity level. + * + * @return integer + */ + public function getOutputVerbosity() + { + return $this->verbosityLevel; + } + + /** + * Writes message(s) to output console. + * + * @param string|array $messages message or array of messages + */ + public function write($messages) + { + $this->getWritingConsole()->write($messages, false); + } + + /** + * Writes newlined message(s) to output console. + * + * @param string|array $messages message or array of messages + */ + public function writeln($messages = '') + { + $this->getWritingConsole()->write($messages, true); + } + + /** + * Clear output console, so on next write formatter will need to init (create) it again. + */ + public function flush() + { + $this->output = null; + } + + /** + * Creates output formatter that is used to create a console. + * + * @return OutputFormatter + */ + protected function createOutputFormatter() + { + return new OutputFormatter(); + } + + /** + * Configure output console parameters. + * + * @param StreamOutput $console + */ + protected function configureOutputConsole(StreamOutput $console) + { + $verbosity = $this->verbosityLevel ? StreamOutput::VERBOSITY_VERBOSE : StreamOutput::VERBOSITY_NORMAL; + $console->setVerbosity($verbosity); + + if (null !== $this->outputDecorated) { + $console->getFormatter()->setDecorated($this->outputDecorated); + } + } + + /** + * Returns new output stream for console. + * + * Override this method & call flushOutputConsole() to write output in another stream + * + * @return resource + * + * @throws BadOutputPathException + */ + protected function createOutputStream() + { + if (null === $this->outputPath) { + $stream = fopen('php://stdout', 'w'); + } elseif (!is_dir($this->outputPath)) { + $stream = fopen($this->outputPath, 'w'); + } else { + throw new BadOutputPathException(sprintf( + 'Filename expected as `output_path` parameter, but got `%s`.', + $this->outputPath + ), $this->outputPath); + } + + return $stream; + } + + /** + * Returns new output console. + * + * @param null|resource $stream + * + * @return StreamOutput + * + * @uses createOutputStream() + */ + final protected function createOutputConsole($stream = null) + { + $stream = $stream ? : $this->createOutputStream(); + $format = $this->createOutputFormatter(); + + // set user-defined styles + foreach ($this->outputStyles as $name => $options) { + $style = new OutputFormatterStyle(); + + if (isset($options[0])) { + $style->setForeground($options[0]); + } + if (isset($options[1])) { + $style->setBackground($options[1]); + } + if (isset($options[2])) { + $style->setOptions($options[2]); + } + + $format->setStyle($name, $style); + } + + $console = new StreamOutput( + $stream, + StreamOutput::VERBOSITY_NORMAL, + $this->outputDecorated, + $format + ); + $this->configureOutputConsole($console); + + return $console; + } + + /** + * Returns output instance, prepared to write. + * + * @return StreamOutput + */ + final protected function getWritingConsole() + { + if (null === $this->output) { + $this->output = $this->createOutputConsole(); + } + + return $this->output; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Printer/OutputPrinter.php b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/OutputPrinter.php new file mode 100644 index 0000000..6cc23b6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/OutputPrinter.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Printer; + +/** + * Isolates all console/filesystem writing. + * + * @author Konstantin Kudryashov + */ +interface OutputPrinter +{ + const VERBOSITY_NORMAL = 1; + const VERBOSITY_VERBOSE = 2; + const VERBOSITY_VERY_VERBOSE = 3; + const VERBOSITY_DEBUG = 4; + + /** + * Sets output path. + * + * @param string $path + */ + public function setOutputPath($path); + + /** + * Returns output path. + * + * @return null|string + */ + public function getOutputPath(); + + /** + * Sets output styles. + * + * @param array $styles + */ + public function setOutputStyles(array $styles); + + /** + * Returns output styles. + * + * @return array + */ + public function getOutputStyles(); + + /** + * Forces output to be decorated. + * + * @param Boolean $decorated + */ + public function setOutputDecorated($decorated); + + /** + * Returns output decoration status. + * + * @return null|Boolean + */ + public function isOutputDecorated(); + + /** + * Sets output verbosity level. + * + * @param integer $level + */ + public function setOutputVerbosity($level); + + /** + * Returns output verbosity level. + * + * @return integer + */ + public function getOutputVerbosity(); + + /** + * Writes message(s) to output console. + * + * @param string|array $messages message or array of messages + */ + public function write($messages); + + /** + * Writes newlined message(s) to output console. + * + * @param string|array $messages message or array of messages + */ + public function writeln($messages = ''); + + /** + * Clear output console, so on next write formatter will need to init (create) it again. + */ + public function flush(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/ServiceContainer/Formatter/FormatterFactory.php b/vendor/behat/behat/src/Behat/Testwork/Output/ServiceContainer/Formatter/FormatterFactory.php new file mode 100644 index 0000000..c80b552 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/ServiceContainer/Formatter/FormatterFactory.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\ServiceContainer\Formatter; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Provides a way to easily define custom formatters. + * + * @author Konstantin Kudryashov + */ +interface FormatterFactory +{ + /** + * Builds formatter configuration. + * + * @param ContainerBuilder $container + */ + public function buildFormatter(ContainerBuilder $container); + + /** + * Processes formatter configuration. + * + * @param ContainerBuilder $container + */ + public function processFormatter(ContainerBuilder $container); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/ServiceContainer/OutputExtension.php b/vendor/behat/behat/src/Behat/Testwork/Output/ServiceContainer/OutputExtension.php new file mode 100644 index 0000000..f49babe --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/ServiceContainer/OutputExtension.php @@ -0,0 +1,223 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension; +use Behat\Testwork\Output\ServiceContainer\Formatter\FormatterFactory; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides output management services for testwork. + * + * @author Konstantin Kudryashov + */ +final class OutputExtension implements Extension +{ + /* + * Available services + */ + const MANAGER_ID = 'output.manager'; + + /* + * Available extension points + */ + const FORMATTER_TAG = 'output.formatter'; + + /** + * @var string + */ + private $defaultFormatter; + /** + * @var FormatterFactory[] + */ + private $factories; + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param string $defaultFormatter + * @param FormatterFactory[] $formatterFactories + * @param null|ServiceProcessor $processor + */ + public function __construct($defaultFormatter, array $formatterFactories, ServiceProcessor $processor = null) + { + $this->defaultFormatter = $defaultFormatter; + $this->factories = $formatterFactories; + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * Registers formatter factory. + * + * @param FormatterFactory $factory + */ + public function registerFormatterFactory(FormatterFactory $factory) + { + $this->factories[] = $factory; + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'formatters'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + $builder + ->defaultValue(array($this->defaultFormatter => array('enabled' => true))) + ->useAttributeAsKey('name') + ->prototype('array') + ->beforeNormalization() + ->ifTrue(function ($a) { + return is_array($a) && !isset($a['enabled']); + }) + ->then(function ($a) { + return array_merge($a, array('enabled' => true)); + }) + ->end() + ->useAttributeAsKey('name') + ->treatTrueLike(array('enabled' => true)) + ->treatNullLike(array('enabled' => true)) + ->treatFalseLike(array('enabled' => false)) + ->prototype('variable')->end() + ->end() + ; + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadOutputController($container); + $this->loadFormatters($container); + $this->loadManager($container, $config); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processFormatters($container); + $this->processDynamicallyRegisteredFormatters($container); + } + + /** + * Loads output controller. + * + * @param ContainerBuilder $container + */ + private function loadOutputController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Output\Cli\OutputController', array( + new Reference(self::MANAGER_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 1000)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.output', $definition); + } + + /** + * Loads output manager. + * + * @param ContainerBuilder $container + * @param array $formatters + */ + private function loadManager(ContainerBuilder $container, array $formatters) + { + $definition = new Definition('Behat\Testwork\Output\OutputManager', array( + new Reference(EventDispatcherExtension::DISPATCHER_ID) + )); + + foreach ($formatters as $name => $parameters) { + if ($parameters['enabled']) { + $definition->addMethodCall('enableFormatter', array($name)); + } else { + $definition->addMethodCall('disableFormatter', array($name)); + } + + unset($parameters['enabled']); + $definition->addMethodCall('setFormatterParameters', array($name, $parameters)); + } + + $container->setDefinition(self::MANAGER_ID, $definition); + } + + /** + * Loads default formatters using registered factories. + * + * @param ContainerBuilder $container + */ + private function loadFormatters(ContainerBuilder $container) + { + foreach ($this->factories as $factory) { + $factory->buildFormatter($container); + } + } + + /** + * Processes formatters using registered factories. + * + * @param ContainerBuilder $container + */ + private function processFormatters(ContainerBuilder $container) + { + foreach ($this->factories as $factory) { + $factory->processFormatter($container); + } + } + + /** + * Processes all available output formatters. + * + * @param ContainerBuilder $container + */ + private function processDynamicallyRegisteredFormatters(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::FORMATTER_TAG); + $definition = $container->getDefinition(self::MANAGER_ID); + + $previousCalls = $definition->getMethodCalls(); + $definition->setMethodCalls(); + + foreach ($references as $reference) { + $definition->addMethodCall('registerFormatter', array($reference)); + } + + foreach ($previousCalls as $call) { + $definition->addMethodCall($call[0], $call[1]); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Configuration/ConfigurationLoader.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Configuration/ConfigurationLoader.php new file mode 100644 index 0000000..13e611e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Configuration/ConfigurationLoader.php @@ -0,0 +1,258 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer\Configuration; + +use Behat\Testwork\ServiceContainer\Exception\ConfigurationLoadingException; +use Symfony\Component\Yaml\Yaml; + +/** + * Loads configuration from different sources. + * + * @author Konstantin Kudryashov + */ +final class ConfigurationLoader +{ + /** + * @var null|string + */ + private $configurationPath; + /** + * @var null|string + */ + private $environmentVariable; + /** + * @var Boolean + */ + private $profileFound; + + /** + * Constructs reader. + * + * @param string $environmentVariableName Environment variable name + * @param string $configurationPath Configuration file path + */ + public function __construct($environmentVariableName = null, $configurationPath = null) + { + $this->environmentVariable = $environmentVariableName; + $this->configurationPath = $configurationPath; + } + + /** + * Sets environment variable name. + * + * @param null|string $variable + */ + public function setEnvironmentVariableName($variable) + { + $this->environmentVariable = $variable; + } + + /** + * Returns environment variable name. + * + * @return null|string + */ + public function getEnvironmentVariableName() + { + return $this->environmentVariable; + } + + /** + * Sets configuration file path. + * + * @param null|string $path + */ + public function setConfigurationFilePath($path) + { + $this->configurationPath = $path; + } + + /** + * Returns configuration file path. + * + * @return null|string + */ + public function getConfigurationFilePath() + { + return $this->configurationPath; + } + + /** + * Reads configuration sequence for specific profile. + * + * @param string $profile Profile name + * + * @return array + * + * @throws ConfigurationLoadingException + */ + public function loadConfiguration($profile = 'default') + { + $configs = array(); + $this->profileFound = false; + + // first is ENV config + foreach ($this->loadEnvironmentConfiguration() as $config) { + $configs[] = $config; + } + + // second is file configuration (if there is some) + if ($this->configurationPath) { + foreach ($this->loadFileConfiguration($this->configurationPath, $profile) as $config) { + $configs[] = $config; + } + } + + // if specific profile has not been found + if ('default' !== $profile && !$this->profileFound) { + throw new ConfigurationLoadingException(sprintf( + 'Can not find configuration for `%s` profile.', + $profile + )); + } + + return $configs; + } + + /** + * Loads information from environment variable. + * + * @return array + * + * @throws ConfigurationLoadingException If environment variable environment var is set to invalid JSON + */ + protected function loadEnvironmentConfiguration() + { + $configs = array(); + + if (!$this->environmentVariable) { + return $configs; + } + + if ($envConfig = getenv($this->environmentVariable)) { + $config = @json_decode($envConfig, true); + + if (!$config) { + throw new ConfigurationLoadingException(sprintf( + 'Environment variable `%s` should contain a valid JSON, but it is set to `%s`.', + $this->environmentVariable, + $envConfig + )); + } + + $configs[] = $config; + } + + return $configs; + } + + /** + * Loads information from YAML configuration file. + * + * @param string $configPath Config file path + * @param string $profile Profile name + * + * @return array + * + * @throws ConfigurationLoadingException If config file is not found + */ + protected function loadFileConfiguration($configPath, $profile) + { + if (!is_file($configPath) || !is_readable($configPath)) { + throw new ConfigurationLoadingException(sprintf('Configuration file `%s` not found.', $configPath)); + } + + $basePath = rtrim(dirname($configPath), DIRECTORY_SEPARATOR); + $config = (array) Yaml::parse(file_get_contents($configPath)); + + return $this->loadConfigs($basePath, $config, $profile); + } + + /** + * Loads configs for provided config and profile. + * + * @param string $basePath + * @param array $config + * @param string $profile + * + * @return array + */ + private function loadConfigs($basePath, array $config, $profile) + { + $configs = array(); + + // first load default profile from current config, but only if custom profile requested + if ('default' !== $profile && isset($config['default'])) { + $configs[] = $config['default']; + } + + // then recursively load profiles from imports + if (isset($config['imports']) && is_array($config['imports'])) { + $configs = array_merge($configs, $this->loadImports($basePath, $config['imports'], $profile)); + } + + // then load specific profile from current config + if (isset($config[$profile])) { + $configs[] = $config[$profile]; + $this->profileFound = true; + } + + return $configs; + } + + /** + * Loads all provided imports. + * + * @param string $basePath + * @param array $paths + * @param string $profile + * + * @return array + */ + private function loadImports($basePath, array $paths, $profile) + { + $configs = array(); + foreach ($paths as $path) { + foreach ($this->parseImport($basePath, $path, $profile) as $importConfig) { + $configs[] = $importConfig; + } + } + + return $configs; + } + + /** + * Parses import. + * + * @param string $basePath + * @param string $path + * @param string $profile + * + * @return array + * + * @throws ConfigurationLoadingException If import file not found + */ + private function parseImport($basePath, $path, $profile) + { + if (!file_exists($path) && file_exists($basePath . DIRECTORY_SEPARATOR . $path)) { + $path = $basePath . DIRECTORY_SEPARATOR . $path; + } + + if (!file_exists($path)) { + throw new ConfigurationLoadingException(sprintf( + 'Can not import `%s` configuration file. File not found.', + $path + )); + } + + return $this->loadFileConfiguration($path, $profile); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Configuration/ConfigurationTree.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Configuration/ConfigurationTree.php new file mode 100644 index 0000000..d713cbc --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Configuration/ConfigurationTree.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer\Configuration; + +use Behat\Testwork\ServiceContainer\Extension; +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\NodeInterface; + +/** + * Builds configuration tree using provided lists of core and custom extensions. + * + * @author Konstantin Kudryashov + */ +final class ConfigurationTree +{ + /** + * Generates the configuration tree. + * + * @param Extension[] $extensions + * + * @return NodeInterface + */ + public function getConfigTree(array $extensions) + { + $tree = new TreeBuilder(); + $root = $tree->root('testwork'); + + foreach ($extensions as $extension) { + $extension->configure($root->children()->arrayNode($extension->getConfigKey())); + } + + return $tree->buildTree(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ContainerLoader.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ContainerLoader.php new file mode 100644 index 0000000..a723777 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ContainerLoader.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer; + +use Behat\Testwork\ServiceContainer\Configuration\ConfigurationTree; +use Behat\Testwork\ServiceContainer\Exception\ExtensionException; +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; + +/** + * Loads Symfony DI container with testwork extension services. + * + * @author Konstantin Kudryashov + */ +final class ContainerLoader +{ + /** + * @var ExtensionManager + */ + private $extensionManager; + /** + * @var ConfigurationTree + */ + private $configuration; + /** + * @var Processor + */ + private $processor; + + /** + * Initialize extension. + * + * @param ExtensionManager $extensionManager + * @param null|ConfigurationTree $configuration + * @param null|Processor $processor + */ + public function __construct( + ExtensionManager $extensionManager, + ConfigurationTree $configuration = null, + Processor $processor = null + ) { + $this->extensionManager = $extensionManager; + $this->configuration = $configuration ? : new ConfigurationTree(); + $this->processor = $processor ? : new Processor(); + } + + /** + * Loads container extension. + * + * @param ContainerBuilder $container + * @param array $configs + */ + public function load(ContainerBuilder $container, array $configs) + { + $configs = $this->initializeExtensions($container, $configs); + $config = $this->processConfig($configs); + + $this->loadExtensions($container, $config); + } + + /** + * Processes config against extensions. + * + * @param array $configs + * + * @return array + */ + private function processConfig(array $configs) + { + $tree = $this->configuration->getConfigTree($this->extensionManager->getExtensions()); + + return $this->processor->process($tree, $configs); + } + + /** + * Initializes extensions using provided config. + * + * @param ContainerBuilder $container + * @param array $configs + * + * @return array + */ + private function initializeExtensions(ContainerBuilder $container, array $configs) + { + foreach ($configs as $i => $config) { + if (isset($config['extensions'])) { + foreach ($config['extensions'] as $extensionLocator => $extensionConfig) { + $extension = $this->extensionManager->activateExtension($extensionLocator); + $configs[$i][$extension->getConfigKey()] = $extensionConfig; + } + + unset($configs[$i]['extensions']); + } + } + + $this->extensionManager->initializeExtensions(); + + $container->setParameter('extensions', $this->extensionManager->getExtensionClasses()); + + return $configs; + } + + /** + * Loads all extensions into container using provided config. + * + * @param ContainerBuilder $container + * @param array $config + * + * @throws ExtensionException + */ + private function loadExtensions(ContainerBuilder $container, array $config) + { + // Load default extensions first + foreach ($this->extensionManager->getExtensions() as $extension) { + $extensionConfig = array(); + if (isset($config[$extension->getConfigKey()])) { + $extensionConfig = $config[$extension->getConfigKey()]; + unset($config[$extension->getConfigKey()]); + } + + $this->loadExtension($container, $extension, $extensionConfig); + } + + // Load activated extensions + foreach ($config as $extensionConfigKey => $extensionConfig) { + if (null === $extension = $this->extensionManager->getExtension($extensionConfigKey)) { + throw new ExtensionException( + sprintf('None of the activated extensions use `%s` config section.', $extensionConfigKey), $extensionConfigKey + ); + } + + $this->loadExtension($container, $extension, $extensionConfig); + } + } + + /** + * Loads extension configuration. + * + * @param ContainerBuilder $container + * @param Extension $extension + * @param array $config + */ + private function loadExtension(ContainerBuilder $container, Extension $extension, array $config) + { + $tempContainer = new ContainerBuilder(new ParameterBag(array( + 'paths.base' => $container->getParameter('paths.base'), + 'extensions' => $container->getParameter('extensions'), + ))); + $tempContainer->addObjectResource($extension); + $extension->load($container, $config); + $container->merge($tempContainer); + $container->addCompilerPass($extension); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ConfigurationLoadingException.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ConfigurationLoadingException.php new file mode 100644 index 0000000..be18620 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ConfigurationLoadingException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer\Exception; + +use InvalidArgumentException; + +/** + * Represents exception thrown during configuration load. + * + * @author Konstantin Kudryashov + */ +final class ConfigurationLoadingException extends InvalidArgumentException implements ServiceContainerException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ExtensionException.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ExtensionException.php new file mode 100644 index 0000000..eb4e16d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ExtensionException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer\Exception; + +use RuntimeException; + +/** + * Extension exception. + * + * @author Konstantin Kudryashov + */ +class ExtensionException extends RuntimeException implements ServiceContainerException +{ + /** + * @var string + */ + private $extensionName; + + /** + * Initializes exception. + * + * @param string $message + * @param string $extensionName + */ + public function __construct($message, $extensionName) + { + $this->extensionName = $extensionName; + + parent::__construct($message); + } + + /** + * Returns name of the extension that caused exception. + * + * @return string + */ + public function getExtensionName() + { + return $this->extensionName; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ExtensionInitializationException.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ExtensionInitializationException.php new file mode 100644 index 0000000..b57aa66 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ExtensionInitializationException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer\Exception; + +/** + * Represents exception thrown during extension initialization phase. + * + * @author Konstantin Kudryashov + */ +final class ExtensionInitializationException extends ExtensionException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ProcessingException.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ProcessingException.php new file mode 100644 index 0000000..b5da8b4 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ProcessingException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer\Exception; + +use RuntimeException; + +/** + * Represents an exception thrown during processing phase. + * + * @author Konstantin Kudryashov + */ +final class ProcessingException extends RuntimeException implements ServiceContainerException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ServiceContainerException.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ServiceContainerException.php new file mode 100644 index 0000000..a7035c5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Exception/ServiceContainerException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer\Exception; + +use Behat\Testwork\Exception\TestworkException; + +/** + * Represents service container exception. + * + * @author Konstantin Kudryashov + */ +interface ServiceContainerException extends TestworkException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Extension.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Extension.php new file mode 100644 index 0000000..9533dca --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Extension.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer; + +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Represents Testwork extension mechanism. + * + * Extensions are the core entities in Testwork. Almost all framework functionality in Testwork and its different + * implementations is provided through extensions. + * + * @author Konstantin Kudryashov + */ +interface Extension extends CompilerPassInterface +{ + /** + * Returns the extension config key. + * + * @return string + */ + public function getConfigKey(); + + /** + * Initializes other extensions. + * + * This method is called immediately after all extensions are activated but + * before any extension `configure()` method is called. This allows extensions + * to hook into the configuration of other extensions providing such an + * extension point. + * + * @param ExtensionManager $extensionManager + */ + public function initialize(ExtensionManager $extensionManager); + + /** + * Setups configuration for the extension. + * + * @param ArrayNodeDefinition $builder + */ + public function configure(ArrayNodeDefinition $builder); + + /** + * Loads extension services into temporary container. + * + * @param ContainerBuilder $container + * @param array $config + */ + public function load(ContainerBuilder $container, array $config); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ExtensionManager.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ExtensionManager.php new file mode 100644 index 0000000..2e5c9df --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ExtensionManager.php @@ -0,0 +1,216 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer; + +use Behat\Testwork\ServiceContainer\Exception\ExtensionInitializationException; + +/** + * Manages both default and 3rd-party extensions. + * + * @author Konstantin Kudryashov + */ +final class ExtensionManager +{ + /** + * @var string + */ + private $extensionsPath; + /** + * @var Extension[] + */ + private $extensions = array(); + /** + * @var Extension[string] + */ + private $locatedExtensions = array(); + + /** + * Initializes manager. + * + * @param Extension[] $extensions List of default extensions + * @param null|string $extensionsPath Base path where to search custom extension files + */ + public function __construct(array $extensions, $extensionsPath = null) + { + foreach ($extensions as $extension) { + $this->extensions[$extension->getConfigKey()] = $extension; + } + + $this->extensionsPath = $extensionsPath; + } + + /** + * Sets path to directory in which manager will try to find extension files. + * + * @param null|string $path + */ + public function setExtensionsPath($path) + { + $this->extensionsPath = $path; + } + + /** + * Activate extension by its locator. + * + * @param string $locator phar file name, php file name, class name + * + * @return Extension + */ + public function activateExtension($locator) + { + $extension = $this->initialize($locator); + + return $this->extensions[$extension->getConfigKey()] = $extension; + } + + /** + * Returns specific extension by its name. + * + * @param string $key + * + * @return Extension + */ + public function getExtension($key) + { + return isset($this->extensions[$key]) ? $this->extensions[$key] : null; + } + + /** + * Returns all available extensions. + * + * @return Extension[] + */ + public function getExtensions() + { + return $this->extensions; + } + + /** + * Returns activated extension names. + * + * @return array + */ + public function getExtensionClasses() + { + return array_map('get_class', array_values($this->extensions)); + } + + /** + * Initializes all activated and predefined extensions. + */ + public function initializeExtensions() + { + foreach ($this->extensions as $extension) { + $extension->initialize($this); + } + } + + /** + * Attempts to guess full extension class from relative. + * + * @param string $locator + * + * @return string + */ + private function getFullExtensionClass($locator) + { + $parts = explode('\\', $locator); + $name = preg_replace('/Extension$/', '', end($parts)) . 'Extension'; + + return $locator . '\\ServiceContainer\\' . $name; + } + + /** + * Initializes extension by id. + * + * @param string $locator + * + * @return Extension + * + * @throws ExtensionInitializationException + */ + private function initialize($locator) + { + if (isset($this->locatedExtensions[$locator])) { + return $this->locatedExtensions[$locator]; + } + + $extension = $this->instantiateExtension($locator); + $this->validateExtensionInstance($extension, $locator); + + return $this->locatedExtensions[$locator] = $extension; + } + + /** + * Instantiates extension from its locator. + * + * @param string $locator + * + * @return Extension + * + * @throws ExtensionInitializationException + */ + private function instantiateExtension($locator) + { + if (class_exists($class = $locator)) { + return new $class; + } + + if (class_exists($class = $this->getFullExtensionClass($locator))) { + return new $class; + } + + if (file_exists($locator)) { + return require($locator); + } + + if (file_exists($path = $this->extensionsPath . DIRECTORY_SEPARATOR . $locator)) { + return require($path); + } + + throw new ExtensionInitializationException(sprintf( + '`%s` extension file or class could not be located.', + $locator + ), $locator); + } + + /** + * Validates extension instance. + * + * @param Extension $extension + * @param string $locator + * + * @throws ExtensionInitializationException + */ + private function validateExtensionInstance($extension, $locator) + { + if (null === $extension) { + throw new ExtensionInitializationException(sprintf( + '`%s` extension could not be found.', + $locator + ), $locator); + } + + if (!is_object($extension)) { + throw new ExtensionInitializationException(sprintf( + '`%s` extension could not be initialized.', + $locator + ), $locator); + } + + if (!$extension instanceof Extension) { + throw new ExtensionInitializationException(sprintf( + '`%s` extension class should implement Testwork Extension interface.', + get_class($extension) + ), $locator); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ServiceProcessor.php b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ServiceProcessor.php new file mode 100644 index 0000000..a57810e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ServiceProcessor.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\ServiceContainer; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides additional service finding functionality. + * + * @author Konstantin Kudryashov + * @author Christophe Coevoet + */ +final class ServiceProcessor +{ + /** + * Finds and sorts (by priority) service references by provided tag. + * + * @param ContainerBuilder $container + * @param string $tag + * + * @return Reference[] + */ + public function findAndSortTaggedServices(ContainerBuilder $container, $tag) + { + $serviceTags = array(); + foreach ($container->findTaggedServiceIds($tag) as $id => $tags) { + $firstTags = current($tags); + + $serviceTags[] = array_merge(array('priority' => 0), $firstTags, array('id' => $id)); + } + + usort($serviceTags, function ($tag1, $tag2) { return $tag2['priority'] - $tag1['priority']; }); + $serviceReferences = array_map(function ($tag) { return new Reference($tag['id']); }, $serviceTags); + + return $serviceReferences; + } + + /** + * Processes wrappers of a service, found by provided tag. + * + * The wrappers are applied by descending priority. + * The first argument of the wrapper service receives the inner service. + * + * @param ContainerBuilder $container + * @param string $target The id of the service being decorated + * @param string $wrapperTag The tag used by wrappers + */ + public function processWrapperServices(ContainerBuilder $container, $target, $wrapperTag) + { + $references = $this->findAndSortTaggedServices($container, $wrapperTag); + + foreach ($references as $reference) { + $id = (string) $reference; + $renamedId = $id . '.inner'; + + // This logic is based on Symfony\Component\DependencyInjection\Compiler\DecoratorServicePass + + // we create a new alias/service for the service we are replacing + // to be able to reference it in the new one + if ($container->hasAlias($target)) { + $alias = $container->getAlias($target); + $public = $alias->isPublic(); + $container->setAlias($renamedId, new Alias((string) $alias, false)); + } else { + $definition = $container->getDefinition($target); + $public = $definition->isPublic(); + $definition->setPublic(false); + $container->setDefinition($renamedId, $definition); + } + + $container->setAlias($target, new Alias($id, $public)); + // Replace the reference so that users don't need to bother about the way the inner service is referenced + $wrappingService = $container->getDefinition($id); + $wrappingService->replaceArgument(0, new Reference($renamedId)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Specification/GroupedSpecificationIterator.php b/vendor/behat/behat/src/Behat/Testwork/Specification/GroupedSpecificationIterator.php new file mode 100644 index 0000000..4a23ef9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Specification/GroupedSpecificationIterator.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Specification; + +use Behat\Testwork\Suite\Suite; + +/** + * Iterates over specification iterators grouped by their suite. + * + * @author Konstantin Kudryashov + */ +final class GroupedSpecificationIterator implements SpecificationIterator +{ + /** + * @var Suite + */ + private $suite; + /** + * @var SpecificationIterator[] + */ + private $iterators; + /** + * @var integer + */ + private $position = 0; + + /** + * Initializes iterator. + * + * @param Suite $suite + * @param SpecificationIterator[] $specificationIterators + */ + public function __construct(Suite $suite, array $specificationIterators) + { + $this->suite = $suite; + $this->iterators = $specificationIterators; + } + + /** + * Groups specifications by their suite. + * + * @param SpecificationIterator[] $specificationIterators + * + * @return GroupedSpecificationIterator[] + */ + public static function group(array $specificationIterators) + { + $groupedSpecifications = array(); + foreach ($specificationIterators as $specificationIterator) { + $groupedSpecifications[$specificationIterator->getSuite()->getName()][] = $specificationIterator; + } + + return array_map( + function ($iterator) { + return new GroupedSpecificationIterator($iterator[0]->getSuite(), $iterator); + }, + $groupedSpecifications + ); + } + + /** + * {@inheritdoc} + */ + public function getSuite() + { + return $this->suite; + } + + /** + * {@inheritdoc} + */ + public function rewind() + { + $this->position = 0; + while (isset($this->iterators[$this->position])) { + $this->iterators[$this->position]->rewind(); + + if ($this->iterators[$this->position]->valid()) { + break; + } + $this->position++; + } + } + + /** + * {@inheritdoc} + */ + public function next() + { + $this->iterators[$this->position]->next(); + while (!$this->iterators[$this->position]->valid()) { + $this->position++; + + if (!isset($this->iterators[$this->position])) { + break; + } + + $this->iterators[$this->position]->rewind(); + } + } + + /** + * {@inheritdoc} + */ + public function valid() + { + return isset($this->iterators[$this->position]) && $this->iterators[$this->position]->valid(); + } + + /** + * {@inheritdoc} + */ + public function current() + { + return $this->iterators[$this->position]->current(); + } + + /** + * {@inheritdoc} + */ + public function key() + { + return $this->position + $this->iterators[$this->position]->key(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Specification/Locator/SpecificationLocator.php b/vendor/behat/behat/src/Behat/Testwork/Specification/Locator/SpecificationLocator.php new file mode 100644 index 0000000..372fbea --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Specification/Locator/SpecificationLocator.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Specification\Locator; + +use Behat\Testwork\Specification\SpecificationFinder; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Suite\Suite; + +/** + * Provides a custom way to locate specification by provided suite and locator string. + * + * @see SpecificationFinder + * + * @author Konstantin Kudryashov + */ +interface SpecificationLocator +{ + /** + * Returns array of strings representing examples of supported specification locators. + * + * @return string[] + */ + public function getLocatorExamples(); + + /** + * Locates specifications and wraps them into iterator. + * + * @param Suite $suite + * @param string $locator + * + * @return SpecificationIterator + */ + public function locateSpecifications(Suite $suite, $locator); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Specification/NoSpecificationsIterator.php b/vendor/behat/behat/src/Behat/Testwork/Specification/NoSpecificationsIterator.php new file mode 100644 index 0000000..95cfc6a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Specification/NoSpecificationsIterator.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Specification; + +use Behat\Testwork\Suite\Suite; +use EmptyIterator; + +/** + * Represents empty specification iterator. + * + * Return an instance of this class from locator if no specifications are found. + * + * @author Konstantin Kudryashov + */ +final class NoSpecificationsIterator extends EmptyIterator implements SpecificationIterator +{ + /** + * @var Suite + */ + private $suite; + + /** + * Initializes iterator. + * + * @param Suite $suite + */ + public function __construct(Suite $suite) + { + $this->suite = $suite; + } + + /** + * Returns suite that was used to load subjects. + * + * @return Suite + */ + public function getSuite() + { + return $this->suite; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Specification/ServiceContainer/SpecificationExtension.php b/vendor/behat/behat/src/Behat/Testwork/Specification/ServiceContainer/SpecificationExtension.php new file mode 100644 index 0000000..03ca52d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Specification/ServiceContainer/SpecificationExtension.php @@ -0,0 +1,115 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Specification\ServiceContainer; + +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; + +/** + * Extends testwork with test specification services. + * + * @author Konstantin Kudryashov + */ +final class SpecificationExtension implements Extension +{ + /* + * Available services + */ + const FINDER_ID = 'specifications.finder'; + + /* + * Available extension points + */ + const LOCATOR_TAG = 'specifications.locator'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'specifications'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadFinder($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processLocators($container); + } + + /** + * Loads specification finder. + * + * @param ContainerBuilder $container + */ + private function loadFinder(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Specification\SpecificationFinder'); + $container->setDefinition(self::FINDER_ID, $definition); + } + + /** + * Processes specification locators. + * + * @param ContainerBuilder $container + */ + private function processLocators(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::LOCATOR_TAG); + $definition = $container->getDefinition(self::FINDER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerSpecificationLocator', array($reference)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Specification/SpecificationArrayIterator.php b/vendor/behat/behat/src/Behat/Testwork/Specification/SpecificationArrayIterator.php new file mode 100644 index 0000000..c48292d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Specification/SpecificationArrayIterator.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Specification; + +use ArrayIterator; +use Behat\Testwork\Suite\Suite; + +/** + * Iterates over specifications array. + * + * Return instance of this class from locator if specifications cannot be searched lazily. + * + * @author Christophe Coevoet + */ +final class SpecificationArrayIterator extends ArrayIterator implements SpecificationIterator +{ + /** + * @var Suite + */ + private $suite; + + /** + * Initializes iterator. + * + * @param Suite $suite + * @param mixed[] $specifications + */ + public function __construct(Suite $suite, $specifications = array()) + { + $this->suite = $suite; + + parent::__construct($specifications); + } + + /** + * {@inheritdoc} + */ + public function getSuite() + { + return $this->suite; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Specification/SpecificationFinder.php b/vendor/behat/behat/src/Behat/Testwork/Specification/SpecificationFinder.php new file mode 100644 index 0000000..5204bd5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Specification/SpecificationFinder.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Specification; + +use Behat\Testwork\Specification\Locator\SpecificationLocator; +use Behat\Testwork\Suite\Suite; + +/** + * Finds test specifications for provided suites using registered locators. + * + * @author Konstantin Kudryashov + */ +final class SpecificationFinder +{ + /** + * @var SpecificationLocator[] + */ + private $specificationLocators = array(); + + /** + * Registers specification locator. + * + * @param SpecificationLocator $locator + */ + public function registerSpecificationLocator(SpecificationLocator $locator) + { + $this->specificationLocators[] = $locator; + } + + /** + * Returns array of strings representing examples of supported specification locators. + * + * @return string[] + */ + public function getExampleLocators() + { + $examples = array(); + foreach ($this->specificationLocators as $locator) { + $examples = array_merge($examples, $locator->getLocatorExamples()); + } + + return $examples; + } + + /** + * Finds all specifications for all provided suites matching provided locator and wraps them into a spec iterator. + * + * @param Suite[] $suites + * @param null|string $locator + * + * @return SpecificationIterator[] + */ + public function findSuitesSpecifications(array $suites, $locator = null) + { + $iterators = array(); + foreach ($suites as $suite) { + $iterators = array_merge($iterators, $this->findSuiteSpecifications($suite, $locator)); + } + + return $iterators; + } + + /** + * Creates suite specification iterator for provided locator. + * + * @param Suite $suite + * @param null|string $locator + * + * @return SpecificationIterator[] + */ + private function findSuiteSpecifications(Suite $suite, $locator = null) + { + $iterators = array(); + foreach ($this->specificationLocators as $specificationLocator) { + $iterators[] = $specificationLocator->locateSpecifications($suite, $locator); + } + + return $iterators; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Specification/SpecificationIterator.php b/vendor/behat/behat/src/Behat/Testwork/Specification/SpecificationIterator.php new file mode 100644 index 0000000..c96ad6c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Specification/SpecificationIterator.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Specification; + +use Behat\Testwork\Suite\Suite; +use Iterator; + +/** + * Iterates over test specifications. + * + * @author Konstantin Kudryashov + */ +interface SpecificationIterator extends Iterator +{ + /** + * Returns suite that was used to load specifications. + * + * @return Suite + */ + public function getSuite(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Cli/InitializationController.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Cli/InitializationController.php new file mode 100644 index 0000000..dc8ac0c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Cli/InitializationController.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Cli; + +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\Suite\SuiteBootstrapper; +use Behat\Testwork\Suite\SuiteRepository; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Initializes registered test suites. + * + * @author Konstantin Kudryashov + */ +final class InitializationController implements Controller +{ + /** + * @var SuiteRepository + */ + private $repository; + /** + * @var SuiteBootstrapper + */ + private $bootstrapper; + + /** + * Initializes controller. + * + * @param SuiteRepository $repository + * @param SuiteBootstrapper $bootstrapper + */ + public function __construct(SuiteRepository $repository, SuiteBootstrapper $bootstrapper) + { + $this->repository = $repository; + $this->bootstrapper = $bootstrapper; + } + + /** + * {@inheritdoc} + */ + public function configure(Command $command) + { + $command->addOption('--init', null, InputOption::VALUE_NONE, + 'Initialize all registered test suites.' + ); + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + if (!$input->getOption('init')) { + return null; + } + + $suites = $this->repository->getSuites(); + $this->bootstrapper->bootstrapSuites($suites); + + $output->write(PHP_EOL); + + return 0; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Cli/SuiteController.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Cli/SuiteController.php new file mode 100644 index 0000000..ea1a23a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Cli/SuiteController.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Cli; + +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\Suite\Exception\SuiteNotFoundException; +use Behat\Testwork\Suite\SuiteRegistry; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Sets up registered test suites. + * + * @author Konstantin Kudryashov + */ +final class SuiteController implements Controller +{ + /** + * @var SuiteRegistry + */ + private $registry; + /** + * @var array + */ + private $suiteConfigurations = array(); + + /** + * Initializes controller. + * + * @param SuiteRegistry $registry + * @param array $suiteConfigurations + */ + public function __construct(SuiteRegistry $registry, array $suiteConfigurations) + { + $this->registry = $registry; + $this->suiteConfigurations = $suiteConfigurations; + } + + /** + * {@inheritdoc} + */ + public function configure(Command $command) + { + $command->addOption('--suite', '-s', InputOption::VALUE_REQUIRED, + 'Only execute a specific suite.' + ); + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $exerciseSuiteName = $input->getOption('suite'); + + if (null !== $exerciseSuiteName && !isset($this->suiteConfigurations[$exerciseSuiteName])) { + throw new SuiteNotFoundException(sprintf( + '`%s` suite is not found or has not been properly registered.', + $exerciseSuiteName + ), $exerciseSuiteName); + } + + foreach ($this->suiteConfigurations as $name => $config) { + if (null !== $exerciseSuiteName && $exerciseSuiteName !== $name) { + continue; + } + + $this->registry->registerSuiteConfiguration( + $name, $config['type'], $config['settings'] + ); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/ParameterNotFoundException.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/ParameterNotFoundException.php new file mode 100644 index 0000000..5005884 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/ParameterNotFoundException.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Exception; + +/** + * Represents an exception thrown when user tries to access non-existent suite parameter. + * + * @author Konstantin Kudryashov + */ +final class ParameterNotFoundException extends SuiteException +{ + /** + * @var string + */ + private $parameter; + + /** + * Initializes exception. + * + * @param string $message + * @param string $name + * @param string $parameter + */ + public function __construct($message, $name, $parameter) + { + $this->parameter = $parameter; + + parent::__construct($message, $name); + } + + /** + * Returns parameter that caused exception. + * + * @return string + */ + public function getParameter() + { + return $this->parameter; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteConfigurationException.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteConfigurationException.php new file mode 100644 index 0000000..73f366c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteConfigurationException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Exception; + +/** + * Represents an exception throw during suite configuration phase. + * + * @author Konstantin Kudryashov + */ +final class SuiteConfigurationException extends SuiteException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteException.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteException.php new file mode 100644 index 0000000..2027089 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteException.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Exception; + +use Behat\Testwork\Exception\TestworkException; +use Exception; +use InvalidArgumentException; + +/** + * Represents a suite exception. + * + * @author Konstantin Kudryashov + */ +class SuiteException extends InvalidArgumentException implements TestworkException +{ + /** + * @var string + */ + private $name; + + /** + * Initializes exception. + * + * @param string $message + * @param string $name + * @param Exception|null $previous + */ + public function __construct($message, $name, Exception $previous = null) + { + $this->name = $name; + + parent::__construct($message, 0, $previous); + } + + /** + * Returns name of the suite that caused exception. + * + * @return string + */ + public function getSuiteName() + { + return $this->name; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteGenerationException.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteGenerationException.php new file mode 100644 index 0000000..d6b418b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteGenerationException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Exception; + +/** + * Represents a suite exception thrown during suite generation phase. + * + * @author Konstantin Kudryashov + */ +final class SuiteGenerationException extends SuiteException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteNotFoundException.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteNotFoundException.php new file mode 100644 index 0000000..95e0244 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteNotFoundException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Exception; + +/** + * Represents an exception thrown when trying to access non-registered suite. + * + * @author Konstantin Kudryashov + */ +final class SuiteNotFoundException extends SuiteException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteSetupException.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteSetupException.php new file mode 100644 index 0000000..5ceeb7e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Exception/SuiteSetupException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Exception; + +/** + * Represents a suite exception thrown during a suite setup phase. + * + * @author Konstantin Kudryashov + */ +final class SuiteSetupException extends SuiteException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Generator/GenericSuiteGenerator.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Generator/GenericSuiteGenerator.php new file mode 100644 index 0000000..36f6141 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Generator/GenericSuiteGenerator.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Generator; + +use Behat\Testwork\Suite\GenericSuite; + +/** + * Generates generic test suites. + * + * @author Konstantin Kudryashov + */ +final class GenericSuiteGenerator implements SuiteGenerator +{ + /** + * @var array + */ + private $defaultSettings = array(); + + /** + * Initializes suite generator. + * + * @param array $defaultSettings + */ + public function __construct(array $defaultSettings = array()) + { + $this->defaultSettings = $defaultSettings; + } + + /** + * {@inheritdoc} + */ + public function supportsTypeAndSettings($type, array $settings) + { + return null === $type; + } + + /** + * {@inheritdoc} + */ + public function generateSuite($suiteName, array $settings) + { + return new GenericSuite($suiteName, $this->mergeDefaultSettings($settings)); + } + + /** + * Merges provided settings into default ones. + * + * @param array $settings + * + * @return array + */ + private function mergeDefaultSettings(array $settings) + { + return array_merge($this->defaultSettings, $settings); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Generator/SuiteGenerator.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Generator/SuiteGenerator.php new file mode 100644 index 0000000..876d6b6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Generator/SuiteGenerator.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Generator; + +use Behat\Testwork\Suite\Suite; +use Behat\Testwork\Suite\SuiteRegistry; + +/** + * Generates a suite using provided name, settings and parameters. + * + * @see SuiteRegistry + * + * @author Konstantin Kudryashov + */ +interface SuiteGenerator +{ + /** + * Checks if generator support provided suite type and settings. + * + * @param string $type + * @param array $settings + * + * @return Boolean + */ + public function supportsTypeAndSettings($type, array $settings); + + /** + * Generate suite with provided name and settings. + * + * @param string $suiteName + * @param array $settings + * + * @return Suite + */ + public function generateSuite($suiteName, array $settings); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/GenericSuite.php b/vendor/behat/behat/src/Behat/Testwork/Suite/GenericSuite.php new file mode 100644 index 0000000..1e5f4ad --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/GenericSuite.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite; + +use Behat\Testwork\Suite\Exception\ParameterNotFoundException; + +/** + * Represents generic (no specific attributes) test suite. + * + * @author Konstantin Kudryashov + */ +final class GenericSuite implements Suite +{ + /** + * @var string + */ + private $name; + /** + * @var array + */ + private $settings = array(); + + /** + * Initializes suite. + * + * @param string $name + * @param array $settings + */ + public function __construct($name, array $settings) + { + $this->name = $name; + $this->settings = $settings; + } + + /** + * Returns unique suite name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Returns suite settings. + * + * @return array + */ + public function getSettings() + { + return $this->settings; + } + + /** + * Checks if a setting with provided name exists. + * + * @param string $key + * + * @return Boolean + */ + public function hasSetting($key) + { + return isset($this->settings[$key]); + } + + /** + * Returns setting value by its key. + * + * @param string $key + * + * @return mixed + * + * @throws ParameterNotFoundException If setting is not set + */ + public function getSetting($key) + { + if (!$this->hasSetting($key)) { + throw new ParameterNotFoundException(sprintf( + '`%s` suite does not have a `%s` setting.', + $this->getName(), + $key + ), $this->getName(), $key); + } + + return $this->settings[$key]; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/ServiceContainer/SuiteExtension.php b/vendor/behat/behat/src/Behat/Testwork/Suite/ServiceContainer/SuiteExtension.php new file mode 100644 index 0000000..563ff99 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/ServiceContainer/SuiteExtension.php @@ -0,0 +1,272 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Extends testwork with suite-related services. + * + * @author Konstantin Kudryashov + */ +final class SuiteExtension implements Extension +{ + /* + * Available services + */ + const REGISTRY_ID = 'suite.registry'; + const BOOTSTRAPPER_ID = 'suite.bootstrapper'; + + /* + * Available extension points + */ + const GENERATOR_TAG = 'suite.generator'; + const SETUP_TAG = 'suite.setup'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'suites'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + $builder + ->defaultValue(array('default' => array( + 'enabled' => true, + 'type' => null, + 'settings' => array() + ))) + ->treatNullLike(array()) + ->treatFalseLike(array()) + ->useAttributeAsKey('name') + ->prototype('array') + ->beforeNormalization() + ->ifTrue(function ($suite) { + return is_array($suite) && count($suite); + }) + ->then(function ($suite) { + $suite['settings'] = isset($suite['settings']) + ? $suite['settings'] + : array(); + + foreach ($suite as $key => $val) { + $suiteKeys = array('enabled', 'type', 'settings'); + if (!in_array($key, $suiteKeys)) { + $suite['settings'][$key] = $val; + unset($suite[$key]); + } + } + + return $suite; + }) + ->end() + ->addDefaultsIfNotSet() + ->treatTrueLike(array('enabled' => true)) + ->treatNullLike(array('enabled' => true)) + ->treatFalseLike(array('enabled' => false)) + ->children() + ->booleanNode('enabled') + ->info('Enables/disables suite') + ->defaultTrue() + ->end() + ->scalarNode('type') + ->info('Specifies suite type') + ->defaultValue(null) + ->end() + ->arrayNode('settings') + ->info('Specifies suite extra settings') + ->defaultValue(array()) + ->useAttributeAsKey('name') + ->prototype('variable')->end() + ->end() + ->end() + ->end() + ; + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->setSuiteConfigurations($container, $config); + $this->loadRegistryController($container); + $this->loadBootstrapController($container); + $this->loadRegistry($container); + $this->loadBootstrapper($container); + $this->loadGenericSuiteGenerator($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processGenerators($container); + $this->processSetups($container); + } + + /** + * Generates and sets suites parameter to container. + * + * @param ContainerBuilder $container + * @param array $suites + */ + private function setSuiteConfigurations(ContainerBuilder $container, array $suites) + { + $configuredSuites = array(); + foreach ($suites as $name => $config) { + if (!$config['enabled']) { + continue; + } + + $configuredSuites[$name] = array( + 'type' => $config['type'], + 'settings' => $config['settings'], + ); + } + + $container->setParameter('suite.configurations', $configuredSuites); + } + + /** + * Loads suite registry controller. + * + * @param ContainerBuilder $container + */ + private function loadRegistryController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Suite\Cli\SuiteController', array( + new Reference(self::REGISTRY_ID), + '%suite.configurations%' + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 1100)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.suite', $definition); + } + + /** + * Loads suite bootstrap controller. + * + * @param ContainerBuilder $container + */ + private function loadBootstrapController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Suite\Cli\InitializationController', array( + new Reference(self::REGISTRY_ID), + new Reference(self::BOOTSTRAPPER_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 900)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.initialization', $definition); + } + + /** + * Loads suite registry. + * + * @param ContainerBuilder $container + */ + private function loadRegistry(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Suite\SuiteRegistry'); + $container->setDefinition(self::REGISTRY_ID, $definition); + } + + /** + * Loads suite bootstrapper. + * + * @param ContainerBuilder $container + */ + private function loadBootstrapper(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Suite\SuiteBootstrapper'); + $container->setDefinition(self::BOOTSTRAPPER_ID, $definition); + } + + /** + * Loads generic suite generator. + * + * @param ContainerBuilder $container + */ + private function loadGenericSuiteGenerator(ContainerBuilder $container) + { + $container->setParameter('suite.generic.default_settings', array()); + + $definition = new Definition('Behat\Testwork\Suite\Generator\GenericSuiteGenerator', array( + '%suite.generic.default_settings%' + )); + $definition->addTag(SuiteExtension::GENERATOR_TAG, array('priority' => 50)); + $container->setDefinition(SuiteExtension::GENERATOR_TAG . '.generic', $definition); + } + + /** + * Processes suite generators. + * + * @param ContainerBuilder $container + */ + private function processGenerators(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::GENERATOR_TAG); + $definition = $container->getDefinition(self::REGISTRY_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerSuiteGenerator', array($reference)); + } + } + + /** + * Processes suite setups. + * + * @param ContainerBuilder $container + */ + private function processSetups(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::SETUP_TAG); + $definition = $container->getDefinition(self::BOOTSTRAPPER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerSuiteSetup', array($reference)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Setup/SuiteSetup.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Setup/SuiteSetup.php new file mode 100644 index 0000000..6165624 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Setup/SuiteSetup.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite\Setup; + +use Behat\Testwork\Suite\Suite; +use Behat\Testwork\Suite\SuiteBootstrapper; + +/** + * Sets up supported test suite. + * + * @see SuiteBootstrapper + * + * @author Konstantin Kudryashov + */ +interface SuiteSetup +{ + /** + * Checks if setup supports provided suite. + * + * @param Suite $suite + * + * @return Boolean + */ + public function supportsSuite(Suite $suite); + + /** + * Sets up provided suite. + * + * @param Suite $suite + */ + public function setupSuite(Suite $suite); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/Suite.php b/vendor/behat/behat/src/Behat/Testwork/Suite/Suite.php new file mode 100644 index 0000000..782f8fd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/Suite.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite; + +/** + * Represents a Testwork suite. Suite is a collection of tests. + * + * @author Konstantin Kudryashov + */ +interface Suite +{ + /** + * Returns unique suite name. + * + * @return string + */ + public function getName(); + + /** + * Returns suite settings. + * + * @return array + */ + public function getSettings(); + + /** + * Checks if a setting with provided name exists. + * + * @param string $key + * + * @return Boolean + */ + public function hasSetting($key); + + /** + * Returns setting value by its key. + * + * @param string $key + * + * @return mixed + */ + public function getSetting($key); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/SuiteBootstrapper.php b/vendor/behat/behat/src/Behat/Testwork/Suite/SuiteBootstrapper.php new file mode 100644 index 0000000..28d0af1 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/SuiteBootstrapper.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite; + +use Behat\Testwork\Suite\Setup\SuiteSetup; + +/** + * Configures provided suites using registered suite setups. + * + * @author Konstantin Kudryashov + */ +final class SuiteBootstrapper +{ + /** + * @var SuiteSetup[] + */ + private $setups = array(); + + /** + * Registers suite setup. + * + * @param SuiteSetup $setup + */ + public function registerSuiteSetup(SuiteSetup $setup) + { + $this->setups[] = $setup; + } + + /** + * Bootstraps provided suites using registered setups. + * + * @param Suite[] $suites + */ + public function bootstrapSuites(array $suites) + { + array_map(array($this, 'bootstrapSuite'), $suites); + } + + /** + * Bootstraps provided suite using registered setup. + * + * @param Suite $suite + */ + public function bootstrapSuite(Suite $suite) + { + foreach ($this->setups as $setup) { + if ($setup->supportsSuite($suite)) { + $setup->setupSuite($suite); + } + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/SuiteRegistry.php b/vendor/behat/behat/src/Behat/Testwork/Suite/SuiteRegistry.php new file mode 100644 index 0000000..5ad98fd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/SuiteRegistry.php @@ -0,0 +1,125 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite; + +use Behat\Testwork\Suite\Exception\SuiteConfigurationException; +use Behat\Testwork\Suite\Exception\SuiteGenerationException; +use Behat\Testwork\Suite\Generator\SuiteGenerator; + +/** + * Acts like a suite repository by auto-generating suites for registered suite configurations using registered + * generators. + * + * @author Konstantin Kudryashov + */ +final class SuiteRegistry implements SuiteRepository +{ + /** + * @var Boolean + */ + private $suitesGenerated = false; + /** + * @var SuiteGenerator[] + */ + private $generators = array(); + /** + * @var array + */ + private $suiteConfigurations = array(); + /** + * @var Suite[] + */ + private $suites = array(); + + /** + * Registers suite generator. + * + * @param SuiteGenerator $generator + */ + public function registerSuiteGenerator(SuiteGenerator $generator) + { + $this->generators[] = $generator; + $this->suitesGenerated = false; + } + + /** + * Registers suite using provided name, type & parameters. + * + * @param string $name + * @param string $type + * @param array $settings + * + * @throws SuiteConfigurationException + */ + public function registerSuiteConfiguration($name, $type, array $settings) + { + if (isset($this->suiteConfigurations[$name])) { + throw new SuiteConfigurationException(sprintf( + 'Suite configuration for a suite "%s" is already registered.', + $name + ), $name); + } + + $this->suiteConfigurations[$name] = array($type, $settings); + $this->suitesGenerated = false; + } + + /** + * Returns all available suites. + * + * @return Suite[] + */ + public function getSuites() + { + if ($this->suitesGenerated) { + return $this->suites; + } + + $this->suites = array(); + foreach ($this->suiteConfigurations as $name => $configuration) { + list($type, $settings) = $configuration; + + $this->suites[] = $this->generateSuite($name, $type, $settings); + } + + $this->suitesGenerated = true; + + return $this->suites; + } + + /** + * Generates suite using registered generators. + * + * @param string $name + * @param string $type + * @param array $settings + * + * @return Suite + * + * @throws SuiteGenerationException If no appropriate generator found + */ + private function generateSuite($name, $type, array $settings) + { + foreach ($this->generators as $generator) { + if (!$generator->supportsTypeAndSettings($type, $settings)) { + continue; + } + + return $generator->generateSuite($name, $settings); + } + + throw new SuiteGenerationException(sprintf( + 'Can not find suite generator for a suite `%s` of type `%s`.', + $name, + $type + ), $name); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Suite/SuiteRepository.php b/vendor/behat/behat/src/Behat/Testwork/Suite/SuiteRepository.php new file mode 100644 index 0000000..7795cc9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/SuiteRepository.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Suite; + +/** + * Represents a way to retrieve suites. + * + * @author Konstantin Kudryashov + */ +interface SuiteRepository +{ + /** + * Returns all available suites. + * + * @return Suite[] + */ + public function getSuites(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Cli/ExerciseController.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Cli/ExerciseController.php new file mode 100644 index 0000000..91ae3c9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Cli/ExerciseController.php @@ -0,0 +1,176 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Cli; + +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\Specification\SpecificationFinder; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Suite\Suite; +use Behat\Testwork\Suite\SuiteRepository; +use Behat\Testwork\Tester\Exception\WrongPathsException; +use Behat\Testwork\Tester\Exercise; +use Behat\Testwork\Tester\Result\IntegerTestResult; +use Behat\Testwork\Tester\Result\ResultInterpreter; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestResults; +use Behat\Testwork\Tester\Result\TestWithSetupResult; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Executes exercise. + * + * @author Konstantin Kudryashov + */ +final class ExerciseController implements Controller +{ + /** + * @var SuiteRepository + */ + private $suiteRepository; + /** + * @var SpecificationFinder + */ + private $specificationFinder; + /** + * @var Exercise + */ + private $exercise; + /** + * @var ResultInterpreter + */ + private $resultInterpreter; + /** + * @var Boolean + */ + private $skip; + + /** + * Initializes controller. + * + * @param SuiteRepository $suiteRepository + * @param SpecificationFinder $specificationFinder + * @param Exercise $exercise + * @param ResultInterpreter $resultInterpreter + * @param Boolean $skip + */ + public function __construct( + SuiteRepository $suiteRepository, + SpecificationFinder $specificationFinder, + Exercise $exercise, + ResultInterpreter $resultInterpreter, + $skip = false + ) { + $this->suiteRepository = $suiteRepository; + $this->specificationFinder = $specificationFinder; + $this->exercise = $exercise; + $this->resultInterpreter = $resultInterpreter; + $this->skip = $skip; + } + + /** + * {@inheritdoc} + */ + public function configure(Command $command) + { + $locatorsExamples = implode(PHP_EOL, array_map( + function ($locator) { + return '- ' . $locator; + }, $this->specificationFinder->getExampleLocators() + )); + + $command + ->addArgument('paths', InputArgument::OPTIONAL, + 'Optional path(s) to execute. Could be:' . PHP_EOL . $locatorsExamples + ) + ->addOption('--dry-run', null, InputOption::VALUE_NONE, + 'Invokes formatters without executing the tests and hooks.' + ); + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $specs = $this->findSpecifications($input); + $result = $this->testSpecifications($input, $specs); + + if ($input->getArgument('paths') && TestResults::NO_TESTS === $result->getResultCode()) { + throw new WrongPathsException( + sprintf('No specifications found at path(s) `%s`.', $input->getArgument('paths')), + $input->getArgument('paths') + ); + } + + return $this->resultInterpreter->interpretResult($result); + } + + /** + * Finds exercise specifications. + * + * @param InputInterface $input + * + * @return SpecificationIterator[] + */ + private function findSpecifications(InputInterface $input) + { + return $this->findSuitesSpecifications($this->getAvailableSuites(), $input->getArgument('paths')); + } + + /** + * Tests exercise specifications. + * + * @param InputInterface $input + * @param SpecificationIterator[] $specifications + * + * @return TestResult + */ + private function testSpecifications(InputInterface $input, array $specifications) + { + $skip = $input->getOption('dry-run') || $this->skip; + + $setup = $this->exercise->setUp($specifications, $skip); + $skip = !$setup->isSuccessful() || $skip; + $testResult = $this->exercise->test($specifications, $skip); + $teardown = $this->exercise->tearDown($specifications, $skip, $testResult); + + $result = new IntegerTestResult($testResult->getResultCode()); + + return new TestWithSetupResult($setup, $result, $teardown); + } + + /** + * Returns all currently available suites. + * + * @return Suite[] + */ + private function getAvailableSuites() + { + return $this->suiteRepository->getSuites(); + } + + /** + * Finds specification iterators for all provided suites using locator. + * + * @param Suite[] $suites + * @param null|string $locator + * + * @return SpecificationIterator[] + */ + private function findSuitesSpecifications($suites, $locator) + { + return $this->specificationFinder->findSuitesSpecifications($suites, $locator); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Cli/StrictController.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Cli/StrictController.php new file mode 100644 index 0000000..1e610be --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Cli/StrictController.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Cli; + +use Behat\Testwork\Cli\Controller; +use Behat\Testwork\Tester\Result\Interpretation\StrictInterpretation; +use Behat\Testwork\Tester\Result\ResultInterpreter; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Configures Testwork to interpret test results strictly. + * + * @author Konstantin Kudryashov + */ +final class StrictController implements Controller +{ + /** + * @var ResultInterpreter + */ + private $resultInterpreter; + /** + * @var Boolean + */ + private $strict; + + /** + * Initializes controller. + * + * @param ResultInterpreter $resultInterpreter + * @param Boolean $strict + */ + public function __construct(ResultInterpreter $resultInterpreter, $strict = false) + { + $this->resultInterpreter = $resultInterpreter; + $this->strict = $strict; + } + + /** + * {@inheritdoc} + */ + public function configure(Command $command) + { + $command->addOption('--strict', null, InputOption::VALUE_NONE, + 'Passes only if all tests are explicitly passing.' + ); + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + if (!$this->strict && !$input->getOption('strict')) { + return; + } + + $this->resultInterpreter->registerResultInterpretation(new StrictInterpretation()); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Exception/TesterException.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Exception/TesterException.php new file mode 100644 index 0000000..2bede7c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Exception/TesterException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Exception; + +/** + * Represents an exception caused by a tester. + * + * @author Konstantin Kudryashov + */ +interface TesterException +{ +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Exception/WrongPathsException.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Exception/WrongPathsException.php new file mode 100644 index 0000000..c429957 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Exception/WrongPathsException.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Exception; + +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * Represents exception caused by a wrong paths argument. + * + * @author Konstantin Kudryashov + */ +final class WrongPathsException extends RuntimeException implements TesterException +{ + /** + * @var string + */ + private $path; + + /** + * Initializes exception. + * + * @param string $message + * @param string $path + */ + public function __construct($message, $path) + { + parent::__construct($message); + + $this->path = $path; + } + + /** + * Returns path that caused exception. + * + * @return string + */ + public function getPath() + { + return $this->path; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Exercise.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Exercise.php new file mode 100644 index 0000000..6a19c1e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Exercise.php @@ -0,0 +1,55 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester; + +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Prepares and tests provided exercise specifications. + * + * @author Konstantin Kudryashov + */ +interface Exercise +{ + /** + * Sets up exercise for a test. + * + * @param SpecificationIterator[] $iterators + * @param Boolean $skip + * + * @return Setup + */ + public function setUp(array $iterators, $skip); + + /** + * Tests suites specifications. + * + * @param SpecificationIterator[] $iterators + * @param Boolean $skip + * + * @return TestResult + */ + public function test(array $iterators, $skip); + + /** + * Tears down exercise after a test. + * + * @param SpecificationIterator[] $iterators + * @param Boolean $skip + * @param TestResult $result + * + * @return Teardown + */ + public function tearDown(array $iterators, $skip, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Result/ExceptionResult.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/ExceptionResult.php new file mode 100644 index 0000000..f30edcf --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/ExceptionResult.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Result; + +use Exception; + +/** + * Represents a result, that possibly produced an exception. + * + * @author Konstantin Kudryashov + */ +interface ExceptionResult extends TestResult +{ + /** + * Checks that the test result has exception. + * + * @return Boolean + */ + public function hasException(); + + /** + * Returns exception that test result has. + * + * @return null|Exception + */ + public function getException(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Result/IntegerTestResult.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/IntegerTestResult.php new file mode 100644 index 0000000..8dad2fc --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/IntegerTestResult.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Result; + +/** + * Represents an integer test result. + * + * @author Konstantin Kudryashov + */ +final class IntegerTestResult implements TestResult +{ + /** + * @var integer + */ + private $resultCode; + + /** + * Initializes test result. + * + * @param integer $resultCode + */ + public function __construct($resultCode) + { + $this->resultCode = $resultCode; + } + + /** + * {@inheritdoc} + */ + public function isPassed() + { + return self::PASSED == $this->getResultCode(); + } + + /** + * {@inheritdoc} + */ + public function getResultCode() + { + return $this->resultCode; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/ResultInterpretation.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/ResultInterpretation.php new file mode 100644 index 0000000..555e75f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/ResultInterpretation.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Result\Interpretation; + +use Behat\Testwork\Tester\Result\ResultInterpreter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Interprets particular test result by saying if it's failure or not. + * + * @see ResultInterpreter + * + * @author Konstantin Kudryashov + */ +interface ResultInterpretation +{ + /** + * Checks if provided test result should be considered as a failure. + * + * @param TestResult $result + * + * @return Boolean + */ + public function isFailure(TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/SoftInterpretation.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/SoftInterpretation.php new file mode 100644 index 0000000..fca891b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/SoftInterpretation.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Result\Interpretation; + +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Interprets test results softly - everything that is not an explicit failure is a pass. + * + * @author Konstantin Kudryashov + */ +final class SoftInterpretation implements ResultInterpretation +{ + /** + * {@inheritdoc} + */ + public function isFailure(TestResult $result) + { + return TestResult::FAILED <= $result->getResultCode(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/StrictInterpretation.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/StrictInterpretation.php new file mode 100644 index 0000000..0a43d8d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/Interpretation/StrictInterpretation.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Result\Interpretation; + +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Interprets test results strictly - everything that is not an explicit pass is a failure. + * + * @author Konstantin Kudryashov + */ +final class StrictInterpretation implements ResultInterpretation +{ + /** + * {@inheritdoc} + */ + public function isFailure(TestResult $result) + { + return !$result->isPassed(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Result/ResultInterpreter.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/ResultInterpreter.php new file mode 100644 index 0000000..5ea9ad1 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/ResultInterpreter.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Result; + +use Behat\Testwork\Tester\Result\Interpretation\ResultInterpretation; + +/** + * Interprets provided test result (as 1 or 0) using registered interpretations. + * + * @author Konstantin Kudryashov + */ +final class ResultInterpreter +{ + /** + * @var ResultInterpretation[] + */ + private $interpretations = array(); + + /** + * Registers result interpretation. + * + * @param ResultInterpretation $interpretation + */ + public function registerResultInterpretation(ResultInterpretation $interpretation) + { + $this->interpretations[] = $interpretation; + } + + /** + * Interprets result as a UNIX return code (0 for success, 1 for failure). + * + * @param TestResult $result + * + * @return integer + */ + public function interpretResult(TestResult $result) + { + foreach ($this->interpretations as $interpretation) { + if ($interpretation->isFailure($result)) { + return 1; + } + } + + return 0; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Result/TestResult.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/TestResult.php new file mode 100644 index 0000000..9d55796 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/TestResult.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Result; + +/** + * Represents a test result. + * + * @author Konstantin Kudryashov + */ +interface TestResult +{ + const PASSED = 0; + const SKIPPED = 10; + const PENDING = 20; + const FAILED = 99; + + /** + * Checks that test has passed. + * + * @return Boolean + */ + public function isPassed(); + + /** + * Returns tester result code. + * + * @return integer + */ + public function getResultCode(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Result/TestResults.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/TestResults.php new file mode 100644 index 0000000..5102f37 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/TestResults.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Result; + +use ArrayIterator; +use Countable; +use IteratorAggregate; + +/** + * Aggregates multiple test results into a collection and provides informational API on top of that. + * + * @author Konstantin Kudryashov + */ +final class TestResults implements TestResult, Countable, IteratorAggregate +{ + const NO_TESTS = -100; + + /** + * @var TestResult[] + */ + private $results; + + /** + * Initializes test results collection. + * + * @param TestResult[] $results + */ + public function __construct(array $results = array()) + { + $this->results = $results; + } + + /** + * {@inheritdoc} + */ + public function isPassed() + { + return self::PASSED == $this->getResultCode(); + } + + /** + * {@inheritdoc} + */ + public function getResultCode() + { + $resultCode = static::NO_TESTS; + foreach ($this->results as $result) { + $resultCode = max($resultCode, $result->getResultCode()); + } + + return $resultCode; + } + + /** + * {@inheritdoc} + */ + public function count() + { + return count($this->results); + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new ArrayIterator($this->results); + } + + /** + * Returns test results array. + * + * @return TestResult[] + */ + public function toArray() + { + return $this->results; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Result/TestWithSetupResult.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/TestWithSetupResult.php new file mode 100644 index 0000000..e9fa4f7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Result/TestWithSetupResult.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Result; + +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Represents a test result with both setup and teardown attached. + * + * @author Konstantin Kudryashov + */ +final class TestWithSetupResult implements TestResult +{ + /** + * @var Setup + */ + private $setup; + /** + * @var TestResult + */ + private $result; + /** + * @var Teardown + */ + private $teardown; + + /** + * Initializes test result. + * + * @param Setup $setup + * @param TestResult $result + * @param Teardown $teardown + */ + public function __construct(Setup $setup, TestResult $result, Teardown $teardown) + { + $this->setup = $setup; + $this->result = $result; + $this->teardown = $teardown; + } + + /** + * {@inheritdoc} + */ + public function isPassed() + { + return self::PASSED == $this->getResultCode(); + } + + /** + * {@inheritdoc} + */ + public function getResultCode() + { + if (!$this->setup->isSuccessful()) { + return self::FAILED; + } + + if (!$this->teardown->isSuccessful()) { + return self::FAILED; + } + + return $this->result->getResultCode(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Runtime/RuntimeExercise.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Runtime/RuntimeExercise.php new file mode 100644 index 0000000..2f831dd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Runtime/RuntimeExercise.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Runtime; + +use Behat\Testwork\Environment\EnvironmentManager; +use Behat\Testwork\Specification\GroupedSpecificationIterator; +use Behat\Testwork\Tester\Exercise; +use Behat\Testwork\Tester\Result\IntegerTestResult; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestResults; +use Behat\Testwork\Tester\Result\TestWithSetupResult; +use Behat\Testwork\Tester\Setup\SuccessfulSetup; +use Behat\Testwork\Tester\Setup\SuccessfulTeardown; +use Behat\Testwork\Tester\SuiteTester; + +/** + * Tester executing exercises in the runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeExercise implements Exercise +{ + /** + * @var EnvironmentManager + */ + private $envManager; + /** + * @var SuiteTester + */ + private $suiteTester; + + /** + * Initializes tester. + * + * @param EnvironmentManager $envManager + * @param SuiteTester $suiteTester + */ + public function __construct(EnvironmentManager $envManager, SuiteTester $suiteTester) + { + $this->envManager = $envManager; + $this->suiteTester = $suiteTester; + } + + /** + * {@inheritdoc} + */ + public function setUp(array $iterators, $skip) + { + return new SuccessfulSetup(); + } + + /** + * {@inheritdoc} + */ + public function test(array $iterators, $skip = false) + { + $results = array(); + foreach (GroupedSpecificationIterator::group($iterators) as $iterator) { + $environment = $this->envManager->buildEnvironment($iterator->getSuite()); + + $setup = $this->suiteTester->setUp($environment, $iterator, $skip); + $localSkip = !$setup->isSuccessful() || $skip; + $testResult = $this->suiteTester->test($environment, $iterator, $localSkip); + $teardown = $this->suiteTester->tearDown($environment, $iterator, $localSkip, $testResult); + + $integerResult = new IntegerTestResult($testResult->getResultCode()); + $results[] = new TestWithSetupResult($setup, $integerResult, $teardown); + } + + return new TestResults($results); + } + + /** + * {@inheritdoc} + */ + public function tearDown(array $iterators, $skip, TestResult $result) + { + return new SuccessfulTeardown(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Runtime/RuntimeSuiteTester.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Runtime/RuntimeSuiteTester.php new file mode 100644 index 0000000..b67838d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Runtime/RuntimeSuiteTester.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Runtime; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Result\IntegerTestResult; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestResults; +use Behat\Testwork\Tester\Result\TestWithSetupResult; +use Behat\Testwork\Tester\Setup\SuccessfulSetup; +use Behat\Testwork\Tester\Setup\SuccessfulTeardown; +use Behat\Testwork\Tester\SpecificationTester; +use Behat\Testwork\Tester\SuiteTester; + +/** + * Tester executing suite tests in the runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeSuiteTester implements SuiteTester +{ + /** + * @var SpecificationTester + */ + private $specTester; + + /** + * Initializes tester. + * + * @param SpecificationTester $specTester + */ + public function __construct(SpecificationTester $specTester) + { + $this->specTester = $specTester; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, SpecificationIterator $iterator, $skip) + { + return new SuccessfulSetup(); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, SpecificationIterator $iterator, $skip = false) + { + $results = array(); + foreach ($iterator as $specification) { + $setup = $this->specTester->setUp($env, $specification, $skip); + $localSkip = !$setup->isSuccessful() || $skip; + $testResult = $this->specTester->test($env, $specification, $localSkip); + $teardown = $this->specTester->tearDown($env, $specification, $localSkip, $testResult); + + $integerResult = new IntegerTestResult($testResult->getResultCode()); + $results[] = new TestWithSetupResult($setup, $integerResult, $teardown); + } + + return new TestResults($results); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, SpecificationIterator $iterator, $skip, TestResult $result) + { + return new SuccessfulTeardown(); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/ServiceContainer/TesterExtension.php b/vendor/behat/behat/src/Behat/Testwork/Tester/ServiceContainer/TesterExtension.php new file mode 100644 index 0000000..55bcfa9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/ServiceContainer/TesterExtension.php @@ -0,0 +1,250 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\Environment\ServiceContainer\EnvironmentExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Behat\Testwork\ServiceContainer\ServiceProcessor; +use Behat\Testwork\Specification\ServiceContainer\SpecificationExtension; +use Behat\Testwork\Suite\ServiceContainer\SuiteExtension; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides tester services. + * + * @author Konstantin Kudryashov + */ +abstract class TesterExtension implements Extension +{ + /* + * Available services + */ + const EXERCISE_ID = 'tester.exercise'; + const SUITE_TESTER_ID = 'tester.suite'; + const SPECIFICATION_TESTER_ID = 'tester.specification'; + const RESULT_INTERPRETER_ID = 'tester.result.interpreter'; + + /** + * Available extension points + */ + const EXERCISE_WRAPPER_TAG = 'tester.exercise.wrapper'; + const SUITE_TESTER_WRAPPER_TAG = 'tester.suite.wrapper'; + const SPECIFICATION_TESTER_WRAPPER_TAG = 'tester.specification.wrapper'; + const RESULT_INTERPRETATION_TAG = 'test.result.interpretation'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ? : new ServiceProcessor(); + } + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'testers'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + $builder + ->addDefaultsIfNotSet() + ->children() + ->booleanNode('strict') + ->info('Sets the strict mode for result interpretation') + ->defaultFalse() + ->end() + ->booleanNode('skip') + ->info('Tells tester to skip all tests') + ->defaultFalse() + ->end() + ->end() + ; + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadExerciseController($container, $config['skip']); + $this->loadStrictController($container, $config['strict']); + $this->loadResultInterpreter($container); + $this->loadExercise($container); + $this->loadSuiteTester($container); + $this->loadSpecificationTester($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processExerciseWrappers($container); + $this->processSuiteTesterWrappers($container); + $this->processSpecificationTesterWrappers($container); + $this->processResultInterpretations($container); + } + + /** + * Loads exercise cli controllers. + * + * @param ContainerBuilder $container + * @param Boolean $skip + */ + protected function loadExerciseController(ContainerBuilder $container, $skip = false) + { + $definition = new Definition('Behat\Testwork\Tester\Cli\ExerciseController', array( + new Reference(SuiteExtension::REGISTRY_ID), + new Reference(SpecificationExtension::FINDER_ID), + new Reference(self::EXERCISE_ID), + new Reference(self::RESULT_INTERPRETER_ID), + $skip + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 0)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.exercise', $definition); + } + + /** + * Loads exercise cli controllers. + * + * @param ContainerBuilder $container + * @param Boolean $strict + */ + protected function loadStrictController(ContainerBuilder $container, $strict = false) + { + $definition = new Definition('Behat\Testwork\Tester\Cli\StrictController', array( + new Reference(self::RESULT_INTERPRETER_ID), + $strict + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 300)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.strict', $definition); + } + + /** + * Loads result interpreter controller + * + * @param ContainerBuilder $container + */ + protected function loadResultInterpreter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Tester\Result\ResultInterpreter'); + $container->setDefinition(self::RESULT_INTERPRETER_ID, $definition); + + $definition = new Definition('Behat\Testwork\Tester\Result\Interpretation\SoftInterpretation'); + $definition->addTag(self::RESULT_INTERPRETATION_TAG); + $container->setDefinition(self::RESULT_INTERPRETATION_TAG . '.soft', $definition); + } + + /** + * Loads exercise tester. + * + * @param ContainerBuilder $container + */ + protected function loadExercise(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Tester\Runtime\RuntimeExercise', array( + new Reference(EnvironmentExtension::MANAGER_ID), + new Reference(self::SUITE_TESTER_ID) + )); + $container->setDefinition(self::EXERCISE_ID, $definition); + } + + /** + * Loads suite tester. + * + * @param ContainerBuilder $container + */ + protected function loadSuiteTester(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Tester\Runtime\RuntimeSuiteTester', array( + new Reference(self::SPECIFICATION_TESTER_ID) + )); + $container->setDefinition(self::SUITE_TESTER_ID, $definition); + } + + /** + * Loads specification tester. + * + * @param ContainerBuilder $container + */ + abstract protected function loadSpecificationTester(ContainerBuilder $container); + + /** + * Processes all registered exercise wrappers. + * + * @param ContainerBuilder $container + */ + protected function processExerciseWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::EXERCISE_ID, self::EXERCISE_WRAPPER_TAG); + } + + /** + * Processes all registered suite tester wrappers. + * + * @param ContainerBuilder $container + */ + protected function processSuiteTesterWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::SUITE_TESTER_ID, self::SUITE_TESTER_WRAPPER_TAG); + } + + /** + * Processes all registered specification tester wrappers. + * + * @param ContainerBuilder $container + */ + protected function processSpecificationTesterWrappers(ContainerBuilder $container) + { + $this->processor->processWrapperServices($container, self::SPECIFICATION_TESTER_ID, self::SPECIFICATION_TESTER_WRAPPER_TAG); + } + + /** + * Processes all registered result interpretations. + * + * @param ContainerBuilder $container + */ + protected function processResultInterpretations(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::RESULT_INTERPRETATION_TAG); + $definition = $container->getDefinition(self::RESULT_INTERPRETER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerResultInterpretation', array($reference)); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/FailedSetup.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/FailedSetup.php new file mode 100644 index 0000000..2130cd3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/FailedSetup.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Setup; + +/** + * Represents a failed setup. + * + * @author Konstantin Kudryashov + */ +final class FailedSetup implements Setup +{ + /** + * {@inheritdoc} + */ + public function isSuccessful() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function hasOutput() + { + return false; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/FailedTeardown.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/FailedTeardown.php new file mode 100644 index 0000000..7fdc74d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/FailedTeardown.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Setup; + +/** + * Represents a failed teardown. + * + * @author Konstantin Kudryashov + */ +final class FailedTeardown implements Teardown +{ + /** + * {@inheritdoc} + */ + public function isSuccessful() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function hasOutput() + { + return false; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/Setup.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/Setup.php new file mode 100644 index 0000000..e904ebb --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/Setup.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Setup; + +/** + * Represents a result of test setUp action. + * + * @author Konstantin Kudryashov + */ +interface Setup +{ + /** + * Returns true if fixtures have been handled successfully. + * + * @return Boolean + */ + public function isSuccessful(); + + /** + * Checks if setup has produced any output. + * + * @return Boolean + */ + public function hasOutput(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/SuccessfulSetup.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/SuccessfulSetup.php new file mode 100644 index 0000000..56686d0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/SuccessfulSetup.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Setup; + +/** + * Represents successful setup. + * + * @author Konstantin Kudryashov + */ +final class SuccessfulSetup implements Setup +{ + /** + * {@inheritdoc} + */ + public function isSuccessful() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function hasOutput() + { + return false; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/SuccessfulTeardown.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/SuccessfulTeardown.php new file mode 100644 index 0000000..8a94d15 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/SuccessfulTeardown.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Setup; + +/** + * Represents successful teardown. + * + * @author Konstantin Kudryashov + */ +final class SuccessfulTeardown implements Teardown +{ + /** + * {@inheritdoc} + */ + public function isSuccessful() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function hasOutput() + { + return false; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/Teardown.php b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/Teardown.php new file mode 100644 index 0000000..fbb445b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Setup/Teardown.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester\Setup; + +/** + * Represents a result of test tearDown action. + * + * @author Konstantin Kudryashov + */ +interface Teardown +{ + /** + * Returns true if fixtures have been handled successfully. + * + * @return Boolean + */ + public function isSuccessful(); + + /** + * Checks if tear down has produced any output. + * + * @return Boolean + */ + public function hasOutput(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/SpecificationTester.php b/vendor/behat/behat/src/Behat/Testwork/Tester/SpecificationTester.php new file mode 100644 index 0000000..9dc106a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/SpecificationTester.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Prepares and tests provided specification against provided environment. + * + * @author Konstantin Kudryashov + */ +interface SpecificationTester +{ + /** + * Sets up specification for a test. + * + * @param Environment $env + * @param mixed $spec + * @param Boolean $skip + * + * @return Setup + */ + public function setUp(Environment $env, $spec, $skip); + + /** + * Tests provided specification. + * + * @param Environment $env + * @param mixed $spec + * @param Boolean $skip + * + * @return TestResult + */ + public function test(Environment $env, $spec, $skip); + + /** + * Tears down specification after a test. + * + * @param Environment $env + * @param mixed $spec + * @param Boolean $skip + * @param TestResult $result + * + * @return Teardown + */ + public function tearDown(Environment $env, $spec, $skip, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Tester/SuiteTester.php b/vendor/behat/behat/src/Behat/Testwork/Tester/SuiteTester.php new file mode 100644 index 0000000..f139f1a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/SuiteTester.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Tester; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Prepares and tests provided suite specifications against provided environment. + * + * @author Konstantin Kudryashov + */ +interface SuiteTester +{ + /** + * Sets up suite for a test. + * + * @param Environment $env + * @param SpecificationIterator $iterator + * @param Boolean $skip + * + * @return Setup + */ + public function setUp(Environment $env, SpecificationIterator $iterator, $skip); + + /** + * Tests provided suite specifications. + * + * @param Environment $env + * @param SpecificationIterator $iterator + * @param Boolean $skip + * + * @return TestResult + */ + public function test(Environment $env, SpecificationIterator $iterator, $skip); + + /** + * Tears down suite after a test. + * + * @param Environment $env + * @param SpecificationIterator $iterator + * @param Boolean $skip + * @param TestResult $result + * + * @return Teardown + */ + public function tearDown(Environment $env, SpecificationIterator $iterator, $skip, TestResult $result); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Translator/Cli/LanguageController.php b/vendor/behat/behat/src/Behat/Testwork/Translator/Cli/LanguageController.php new file mode 100644 index 0000000..676b891 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Translator/Cli/LanguageController.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Translator\Cli; + +use Behat\Testwork\Cli\Controller; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Translation\Translator; + +/** + * Configures translator service to use custom locale. + * + * @author Konstantin Kudryashov + */ +final class LanguageController implements Controller +{ + /** + * @var Translator + */ + private $translator; + + /** + * Initializes controller. + * + * @param Translator $translator + */ + public function __construct(Translator $translator) + { + $this->translator = $translator; + } + + /** + * {@inheritdoc} + */ + public function configure(Command $command) + { + $command->addOption('--lang', null, InputOption::VALUE_REQUIRED, + 'Print output in particular language.' + ); + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + if (!$input->getOption('lang')) { + return; + } + + $this->translator->setLocale($input->getOption('lang')); + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Translator/ServiceContainer/TranslatorExtension.php b/vendor/behat/behat/src/Behat/Testwork/Translator/ServiceContainer/TranslatorExtension.php new file mode 100644 index 0000000..39de237 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Translator/ServiceContainer/TranslatorExtension.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Translator\ServiceContainer; + +use Behat\Testwork\Cli\ServiceContainer\CliExtension; +use Behat\Testwork\ServiceContainer\Extension; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Provides translator service. + * + * @author Konstantin Kudryashov + */ +final class TranslatorExtension implements Extension +{ + /* + * Available services + */ + const TRANSLATOR_ID = 'translator'; + + /** + * {@inheritdoc} + */ + public function getConfigKey() + { + return 'translation'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + $defaultLanguage = $this->getDefaultLanguage() ?: 'en'; + + $builder + ->addDefaultsIfNotSet() + ->children() + ->scalarNode('locale') + ->info('Sets output locale for the tester') + ->defaultValue($defaultLanguage) + ->end() + ->scalarNode('fallback_locale') + ->info('Sets fallback output locale for the tester') + ->defaultValue('en') + ->end() + ->end(); + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $this->loadTranslator($container, $config['locale'], $config['fallback_locale']); + $this->loadController($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + } + + /** + * Loads translator service. + * + * @param ContainerBuilder $container + * @param string $locale + * @param string $fallbackLocale + */ + private function loadTranslator(ContainerBuilder $container, $locale, $fallbackLocale) + { + $definition = new Definition('Symfony\Component\Translation\Translator', array($locale)); + $container->setDefinition(self::TRANSLATOR_ID, $definition); + + $definition->addMethodCall('setFallbackLocales', array(array($fallbackLocale))); + $definition->addMethodCall( + 'addLoader', array( + 'xliff', + new Definition('Symfony\Component\Translation\Loader\XliffFileLoader') + ) + ); + $definition->addMethodCall( + 'addLoader', array( + 'yaml', + new Definition('Symfony\Component\Translation\Loader\YamlFileLoader') + ) + ); + $definition->addMethodCall( + 'addLoader', array( + 'php', + new Definition('Symfony\Component\Translation\Loader\PhpFileLoader') + ) + ); + $definition->addMethodCall( + 'addLoader', array( + 'array', + new Definition('Symfony\Component\Translation\Loader\ArrayLoader') + ) + ); + $container->setDefinition(self::TRANSLATOR_ID, $definition); + } + + /** + * Loads translator controller. + * + * @param ContainerBuilder $container + */ + private function loadController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Translator\Cli\LanguageController', array( + new Reference(self::TRANSLATOR_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 800)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.translator', $definition); + } + + /** + * Tries to guess default user cli language. + * + * @return null|string + */ + private function getDefaultLanguage() + { + $defaultLanguage = null; + if (($locale = getenv('LANG')) && preg_match('/^([a-z]{2})/', $locale, $matches)) { + $defaultLanguage = $matches[1]; + + return $defaultLanguage; + } + + return $defaultLanguage; + } +} diff --git a/vendor/behat/behat/tests/Behat/Tests/Testwork/Subject/GroupedSubjectIteratorTest.php b/vendor/behat/behat/tests/Behat/Tests/Testwork/Subject/GroupedSubjectIteratorTest.php new file mode 100644 index 0000000..a0802c4 --- /dev/null +++ b/vendor/behat/behat/tests/Behat/Tests/Testwork/Subject/GroupedSubjectIteratorTest.php @@ -0,0 +1,36 @@ +prophesize('Behat\Testwork\Suite\Suite')->reveal(); + + $iterator = new GroupedSpecificationIterator($suite, array( + new NoSpecificationsIterator($suite), + new SpecificationArrayIterator($suite, array($this->prophesize()->reveal())), + )); + + $this->assertEquals(1, iterator_count($iterator)); + } + + public function testIterationWithEmptyInMiddle() + { + $suite = $this->prophesize('Behat\Testwork\Suite\Suite')->reveal(); + + $iterator = new GroupedSpecificationIterator($suite, array( + new SpecificationArrayIterator($suite, array($this->prophesize()->reveal())), + new NoSpecificationsIterator($suite), + new SpecificationArrayIterator($suite, array($this->prophesize()->reveal())), + )); + + $this->assertEquals(2, iterator_count($iterator)); + } +} diff --git a/vendor/behat/gherkin/.travis.yml b/vendor/behat/gherkin/.travis.yml new file mode 100644 index 0000000..304a3e1 --- /dev/null +++ b/vendor/behat/gherkin/.travis.yml @@ -0,0 +1,30 @@ +language: php + +sudo: false + +cache: + directories: + - $HOME/.composer/cache/files + +php: [5.3, 5.4, 5.5, 5.6, 7.0, hhvm] + +matrix: + include: + # Add testing against LTS versions + - php: 5.5 + env: SYMFONY_VERSION='2.3.*' + - php: 5.5 + env: SYMFONY_VERSION='2.7.*' + +before_install: + - composer self-update + - if [ "$SYMFONY_VERSION" != "" ]; then composer require --no-update symfony/yaml=$SYMFONY_VERSION; fi; + +install: + - composer install + +script: vendor/bin/phpunit -v --coverage-clover=coverage.clover + +after_script: + # don't upload coverage on PHP 7 and HHVM as it cannot be generated. We don't want to tell Scrutinizer that the coverage generation failed. + - if [[ "7.0" != "$TRAVIS_PHP_VERSION" && "$TRAVIS_PHP_VERSION" != "hhvm" ]]; then wget https://scrutinizer-ci.com/ocular.phar && php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi diff --git a/vendor/behat/gherkin/CHANGES.md b/vendor/behat/gherkin/CHANGES.md new file mode 100644 index 0000000..9e49323 --- /dev/null +++ b/vendor/behat/gherkin/CHANGES.md @@ -0,0 +1,341 @@ +4.4.0 / 2015-09-19 +================== + + * Added validation enforcing that all rows of a `TableNode` have the same number of columns + * Added `TableNode::getColumn` to get a column from the table + * Sync 18n with cucumber + +4.3.0 / 2014-06-06 +================== + + * Added `setFilters(array)` method to `Gherkin` class + * Added `NarrativeFilter` for non-english `RoleFilter` lovers + +4.2.1 / 2014-06-06 +================== + + * Fix parsing of features without line feed at the end + +4.2.0 / 2014-05-27 +================== + + * Added `getKeyword()` and `getKeywordType()` methods to `StepNode`, deprecated `getType()`. + Thanks to @kibao + +4.1.3 / 2014-05-25 +================== + + * Properly handle tables with rows terminating in whitespace + +4.1.2 / 2014-05-14 +================== + + * Handle case where Gherkin cache is broken + +4.1.1 / 2014-05-05 +================== + + * Fixed the compatibility with PHP 5.6-beta by avoiding to use the broken PHP array function + * The YamlFileLoader no longer extend from ArrayLoader but from AbstractFileLoader + +4.1.0 / 2014-04-20 +================== + + * Fixed scenario tag filtering + * Do not allow multiple multiline step arguments + * Sync 18n with cucumber + +4.0.0 / 2014-01-05 +================== + + * Changed the behavior when no loader can be found for the resource. Instead of throwing an exception, the + Gherkin class now returns an empty array. + +3.1.3 / 2014-01-04 +================== + + * Dropped the dependency on the Symfony Finder by using SPL iterators directly + * Added testing on HHVM on Travis. HHVM is officially supported (previous release was actually already compatible) + +3.1.2 / 2014-01-01 +================== + + * All paths passed to PathsFilter are converted using realpath + +3.1.1 / 2013-12-31 +================== + + * Add `ComplexFilterInterace` that has complex behavior for scenarios and requires to pass + feature too + * `TagFilter` is an instance of a `ComplexFilterInterace` now + +3.1.0 / 2013-12-31 +================== + + * Example node is a scenario + * Nodes do not have uprefs (memory usage fix) + * Scenario filters do not depend on feature nodes + +3.0.5 / 2014-01-01 +================== + + * All paths passed to PathsFilter are converted using realpath + +3.0.4 / 2013-12-31 +================== + + * TableNode is now traversable using foreach + * All possibly thrown exceptions implement Gherkin\Exception interface + * Sync i18n with cucumber + +3.0.3 / 2013-09-15 +================== + + * Extend ExampleNode with additional methods + +3.0.2 / 2013-09-14 +================== + + * Extract `KeywordNodeInterface` and `ScenarioLikeInterface` + * Add `getIndex()` methods to scenarios, outlines, steps and examples + * Throw proper exception for fractured node tree + +3.0.1 / 2013-09-14 +================== + + * Use versioned subfolder in FileCache + +3.0.0 / 2013-09-14 +================== + + * A lot of optimizations in Parser and Lexer + * Node tree is now immutable by nature (no setters) + * Example nodes are now part of the node tree. They are lazily generated by Outline node + * Sync with latest cucumber i18n + +2.3.4 / 2013-08-11 +================== + + * Fix leaks in memory cache + +2.3.3 / 2013-08-11 +================== + + * Fix encoding bug introduced with previous release + * Sync i18n with cucumber + +2.3.2 / 2013-08-11 +================== + + * Explicitly use utf8 encoding + +2.3.1 / 2013-08-10 +================== + + * Support `an` prefix with RoleFilter + +2.3.0 / 2013-08-04 +================== + + * Add RoleFilter + * Add PathsFilter + * Add MemoryCache + +2.2.9 / 2013-03-02 +================== + + * Fix dependency version requirement + +2.2.8 / 2013-03-02 +================== + + * Features filtering behavior change. Now emptified (by filtering) features + that do not match filter themselves are removed from resultset. + * Small potential bug fix in TableNode + +2.2.7 / 2013-01-27 +================== + + * Fixed bug in i18n syncing script + * Resynced Gherkin i18n + +2.2.6 / 2013-01-26 +================== + + * Support long row hashes in tables ([see](https://github.com/Behat/Gherkin/issues/40)) + * Synced Gherkin i18n + +2.2.5 / 2012-09-26 +================== + + * Fixed issue with loading empty features + * Synced Gherkin i18n + +2.2.4 / 2012-08-03 +================== + + * Fixed exception message for "no loader found" + +2.2.3 / 2012-08-03 +================== + + * Fixed minor loader bug with empty base path + * Synced Gherkin i18n + +2.2.2 / 2012-07-01 +================== + + * Added ability to filter outline scenarios by line and range filters + * Synced Gherkin i18n + * Refactored table parser to read row line numbers too + +2.2.1 / 2012-05-04 +================== + + * Fixed StepNode `getLanguage()` and `getFile()` + +2.2.0 / 2012-05-03 +================== + + * Features freeze after parsing + * Implemented GherkinDumper (@Halleck45) + * Synced i18n with Cucumber + * Updated inline documentation + +2.1.1 / 2012-03-09 +================== + + * Fixed caching bug, where `isFresh()` always returned false + +2.1.0 / 2012-03-09 +================== + + * Added parser caching layer + * Added support for table delimiter escaping (use `\|` for that) + * Added LineRangeFilter (thanks @headrevision) + * Synced i18n dictionary with cucumber/gherkin + +2.0.2 / 2012-02-04 +================== + + * Synced i18n dictionary with cucumber/gherkin + +2.0.1 / 2012-01-26 +================== + + * Fixed issue about parsing features without indentation + +2.0.0 / 2012-01-19 +================== + + * Background titles support + * Correct parsing of titles/descriptions (hirarchy lexing) + * Migration to the cucumber/gherkin i18n dictionary + * Speed optimizations + * Refactored KeywordsDumper + * New loaders + * Bugfixes + +1.1.4 / 2012-01-08 +================== + + * Read feature description even if it looks like a step + +1.1.3 / 2011-12-14 +================== + + * Removed file loading routines from Parser (fixes `is_file()` issue on some systems - thanks + @flodocteurklein) + +1.1.2 / 2011-12-01 +================== + + * Updated spanish trasnaltion (@anbotero) + * Integration with Composer and Travis CI + +1.1.1 / 2011-07-29 +================== + + * Updated pt language step types (@danielcsgomes) + * Updated vendors + +1.1.0 / 2011-07-16 +================== + + * Return all tags, including inherited in `Scenario::getTags()` + * New `Feature::getOwnTags()` and `Scenario::getOwnTags()` method added, + which returns only own tags + +1.0.8 / 2011-06-29 +================== + + * Fixed comments parsing. + You can’t have comments at the end of a line # like this + # But you can still have comments at the beginning of a line + +1.0.7 / 2011-06-28 +================== + + * Added `getRaw()` method to PyStringNode + * Updated vendors + +1.0.6 / 2011-06-17 +================== + + * Updated vendors + +1.0.5 / 2011-06-10 +================== + + * Fixed bug, introduced with 1.0.4 - hash in PyStrings + +1.0.4 / 2011-06-10 +================== + + * Fixed inability to comment pystrings + +1.0.3 / 2011-04-21 +================== + + * Fixed introduced with 1.0.2 pystring parsing bug + +1.0.2 / 2011-04-18 +================== + + * Fixed bugs in text with comments parsing + +1.0.1 / 2011-04-01 +================== + + * Updated vendors + +1.0.0 / 2011-03-08 +================== + + * Updated vendors + +1.0.0RC2 / 2011-02-25 +===================== + + * Windows support + * Missing phpunit config + +1.0.0RC1 / 2011-02-15 +===================== + + * Huge optimizations to Lexer & Parser + * Additional loaders (Yaml, Array, Directory) + * Filters (Tag, Name, Line) + * Code refactoring + * Nodes optimizations + * Additional tests for exceptions and translations + * Keywords dumper + +0.2.0 / 2011-01-05 +================== + + * New Parser & Lexer (based on AST) + * New verbose parsing exception handling + * New translation mechanics + * 47 brand new translations (see i18n) + * Full test suite for everything from AST nodes to translations diff --git a/vendor/behat/gherkin/CONTRIBUTING.md b/vendor/behat/gherkin/CONTRIBUTING.md new file mode 100644 index 0000000..5e8d97b --- /dev/null +++ b/vendor/behat/gherkin/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Contributing +------------ + +Gherkin is an open source, community-driven project. If you'd like to contribute, feel free to do this, but remember to follow this few simple rules: + +- Make your feature addition or bug fix, +- Always use the `master` branch as base for your changes (all new development happens in `master`), +- Add tests for those changes (please look into `tests/` folder for some examples). This is important so we don't break it in a future version unintentionally, +- Commit your code, but do not mess with `CHANGES.md`, +- __Remember__: when you create Pull Request, always select `master` branch as target (done by default), otherwise it will be closed. + +Running tests +------------- + +Make sure that you don't break anything with your changes by running: + +```bash +$> phpunit +``` + +Contributing to Gherkin Translations +------------------------------------ + +Gherkin supports →40 different languages and you could add more! You might notice +`i18n.php` file in the root of the library. This file is downloaded and **autogenerated** +from original [cucumber/gherkin translations](https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.json). +So, in order to fix/update/add some translation, you should send Pull Request to the +`cucumber/gherkin` repository. `Behat\Gherkin` will redownload/regenerate translations +from there before each release. + +It might sounds difficult, but this way of dictionary sharing gives you ability to +migrate your `*.feature` files from language to language and library to library without +the need to rewrite/modify them - same dictionary (Gherkin) used everywhere. diff --git a/vendor/behat/gherkin/LICENSE b/vendor/behat/gherkin/LICENSE new file mode 100644 index 0000000..14f15e8 --- /dev/null +++ b/vendor/behat/gherkin/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011-2013 Konstantin Kudryashov + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/behat/gherkin/README.md b/vendor/behat/gherkin/README.md new file mode 100644 index 0000000..e7034df --- /dev/null +++ b/vendor/behat/gherkin/README.md @@ -0,0 +1,68 @@ +Behat Gherkin Parser +==================== + +This is the php Gherkin parser for Behat. It comes bundled with more than 40 native languages +(see `i18n.php`) support & clean architecture. + +[![Build Status](https://travis-ci.org/Behat/Gherkin.svg?branch=master)](https://travis-ci.org/Behat/Gherkin) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Behat/Gherkin/badges/quality-score.png?s=04d9d0237c89f4c45a94ba5304234db861dfd036)](https://scrutinizer-ci.com/g/Behat/Gherkin/) +[![Code Coverage](https://scrutinizer-ci.com/g/Behat/Gherkin/badges/coverage.png?s=204ca44800469d295b73d18c91011cb9d2dc99fc)](https://scrutinizer-ci.com/g/Behat/Gherkin/) + +Useful Links +------------ + +- Official Google Group is at [http://groups.google.com/group/behat](http://groups.google.com/group/behat) +- IRC channel on [#freenode](http://freenode.net/) is `#behat` +- [Note on Patches/Pull Requests](CONTRIBUTING.md) + +Usage Example +------------- + +``` php + array( + 'feature' => 'Feature', + 'background' => 'Background', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Scenario Outline|Scenario Template', + 'examples' => 'Examples|Scenarios', + 'given' => 'Given', + 'when' => 'When', + 'then' => 'Then', + 'and' => 'And', + 'but' => 'But' + ), + 'en-pirate' => array( + 'feature' => 'Ahoy matey!', + 'background' => 'Yo-ho-ho', + 'scenario' => 'Heave to', + 'scenario_outline' => 'Shiver me timbers', + 'examples' => 'Dead men tell no tales', + 'given' => 'Gangway!', + 'when' => 'Blimey!', + 'then' => 'Let go and haul', + 'and' => 'Aye', + 'but' => 'Avast!' + ) +)); +$lexer = new Behat\Gherkin\Lexer($keywords); +$parser = new Behat\Gherkin\Parser($lexer); + +$feature = $parser->parse(file_get_contents('some.feature')); +``` + +Installing Dependencies +----------------------- + +``` bash +$> curl http://getcomposer.org/installer | php +$> php composer.phar update +``` + +Contributors +------------ + +* Konstantin Kudryashov [everzet](http://github.com/everzet) [lead developer] +* Other [awesome developers](https://github.com/Behat/Gherkin/graphs/contributors) diff --git a/vendor/behat/gherkin/bin/update_i18n b/vendor/behat/gherkin/bin/update_i18n new file mode 100755 index 0000000..612e255 --- /dev/null +++ b/vendor/behat/gherkin/bin/update_i18n @@ -0,0 +1,32 @@ +#!/usr/bin/env php + $keywords) { + foreach (array('given', 'when', 'then', 'and', 'but') as $type) { + $stepTypes = explode('|', $keywords[$type]); + + if ('*' === $stepTypes[0]) { + array_shift($stepTypes); + } + + usort($stepTypes, function($type1, $type2) { + return mb_strlen($type2, 'utf8') - mb_strlen($type1, 'utf8'); + }); + + $array[$lang][$type] = implode('|', $stepTypes); + } + + // ensure that the order of keys is consistent between updates + ksort($array[$lang]); +} + +// ensure that the languages are sorted to avoid useless diffs between updates. We keep the English first though as it is the reference. +$enData = $array['en']; +unset($array['en']); +ksort($array); +$array = array_merge(array('en' => $enData), $array); + +file_put_contents(__DIR__.'/../i18n.php', '=5.3.1" + }, + + "require-dev": { + "symfony/yaml": "~2.1", + "phpunit/phpunit": "~4.0" + }, + + "suggest": { + "symfony/yaml": "If you want to parse features, represented in YAML files" + }, + + "autoload": { + "psr-0": { + "Behat\\Gherkin": "src/" + } + }, + + "autoload-dev": { + "psr-4": { + "Tests\\Behat\\": "tests/Behat/" + } + }, + + "extra": { + "branch-alias": { + "dev-master": "4.4-dev" + } + } +} diff --git a/vendor/behat/gherkin/i18n.php b/vendor/behat/gherkin/i18n.php new file mode 100644 index 0000000..c5f1c03 --- /dev/null +++ b/vendor/behat/gherkin/i18n.php @@ -0,0 +1,962 @@ + + array ( + 'and' => 'And', + 'background' => 'Background', + 'but' => 'But', + 'examples' => 'Examples|Scenarios', + 'feature' => 'Feature|Business Need|Ability', + 'given' => 'Given', + 'name' => 'English', + 'native' => 'English', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Scenario Outline|Scenario Template', + 'then' => 'Then', + 'when' => 'When', + ), + 'af' => + array ( + 'and' => 'En', + 'background' => 'Agtergrond', + 'but' => 'Maar', + 'examples' => 'Voorbeelde', + 'feature' => 'Funksie|Besigheid Behoefte|Vermoë', + 'given' => 'Gegewe', + 'name' => 'Afrikaans', + 'native' => 'Afrikaans', + 'scenario' => 'Situasie', + 'scenario_outline' => 'Situasie Uiteensetting', + 'then' => 'Dan', + 'when' => 'Wanneer', + ), + 'am' => + array ( + 'and' => 'Եվ', + 'background' => 'Կոնտեքստ', + 'but' => 'Բայց', + 'examples' => 'Օրինակներ', + 'feature' => 'Ֆունկցիոնալություն|Հատկություն', + 'given' => 'Դիցուք', + 'name' => 'Armenian', + 'native' => 'հայերեն', + 'scenario' => 'Սցենար', + 'scenario_outline' => 'Սցենարի կառուցվացքը', + 'then' => 'Ապա', + 'when' => 'Երբ|Եթե', + ), + 'ar' => + array ( + 'and' => 'و', + 'background' => 'الخلفية', + 'but' => 'لكن', + 'examples' => 'امثلة', + 'feature' => 'خاصية', + 'given' => 'بفرض', + 'name' => 'Arabic', + 'native' => 'العربية', + 'scenario' => 'سيناريو', + 'scenario_outline' => 'سيناريو مخطط', + 'then' => 'اذاً|ثم', + 'when' => 'عندما|متى', + ), + 'bg' => + array ( + 'and' => 'И', + 'background' => 'Предистория', + 'but' => 'Но', + 'examples' => 'Примери', + 'feature' => 'Функционалност', + 'given' => 'Дадено', + 'name' => 'Bulgarian', + 'native' => 'български', + 'scenario' => 'Сценарий', + 'scenario_outline' => 'Рамка на сценарий', + 'then' => 'То', + 'when' => 'Когато', + ), + 'bm' => + array ( + 'and' => 'Dan', + 'background' => 'Latar Belakang', + 'but' => 'Tetapi|Tapi', + 'examples' => 'Contoh', + 'feature' => 'Fungsi', + 'given' => 'Diberi|Bagi', + 'name' => 'Malay', + 'native' => 'Bahasa Melayu', + 'scenario' => 'Senario|Situai|Keadaan', + 'scenario_outline' => 'Template Senario|Template Situai|Template Keadaan|Menggariskan Senario', + 'then' => 'Kemudian|Maka', + 'when' => 'Apabila', + ), + 'ca' => + array ( + 'and' => 'I', + 'background' => 'Rerefons|Antecedents', + 'but' => 'Però', + 'examples' => 'Exemples', + 'feature' => 'Característica|Funcionalitat', + 'given' => 'Donada|Donat|Atesa|Atès', + 'name' => 'Catalan', + 'native' => 'català', + 'scenario' => 'Escenari', + 'scenario_outline' => 'Esquema de l\'escenari', + 'then' => 'Aleshores|Cal', + 'when' => 'Quan', + ), + 'cs' => + array ( + 'and' => 'A také|A', + 'background' => 'Pozadí|Kontext', + 'but' => 'Ale', + 'examples' => 'Příklady', + 'feature' => 'Požadavek', + 'given' => 'Za předpokladu|Pokud', + 'name' => 'Czech', + 'native' => 'Česky', + 'scenario' => 'Scénář', + 'scenario_outline' => 'Náčrt Scénáře|Osnova scénáře', + 'then' => 'Pak', + 'when' => 'Když', + ), + 'cy-GB' => + array ( + 'and' => 'A', + 'background' => 'Cefndir', + 'but' => 'Ond', + 'examples' => 'Enghreifftiau', + 'feature' => 'Arwedd', + 'given' => 'Anrhegedig a', + 'name' => 'Welsh', + 'native' => 'Cymraeg', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Scenario Amlinellol', + 'then' => 'Yna', + 'when' => 'Pryd', + ), + 'da' => + array ( + 'and' => 'Og', + 'background' => 'Baggrund', + 'but' => 'Men', + 'examples' => 'Eksempler', + 'feature' => 'Egenskab', + 'given' => 'Givet', + 'name' => 'Danish', + 'native' => 'dansk', + 'scenario' => 'Scenarie', + 'scenario_outline' => 'Abstrakt Scenario', + 'then' => 'Så', + 'when' => 'Når', + ), + 'de' => + array ( + 'and' => 'Und', + 'background' => 'Grundlage', + 'but' => 'Aber', + 'examples' => 'Beispiele', + 'feature' => 'Funktionalität', + 'given' => 'Gegeben seien|Gegeben sei|Angenommen', + 'name' => 'German', + 'native' => 'Deutsch', + 'scenario' => 'Szenario', + 'scenario_outline' => 'Szenariogrundriss', + 'then' => 'Dann', + 'when' => 'Wenn', + ), + 'el' => + array ( + 'and' => 'Και', + 'background' => 'Υπόβαθρο', + 'but' => 'Αλλά', + 'examples' => 'Παραδείγματα|Σενάρια', + 'feature' => 'Δυνατότητα|Λειτουργία', + 'given' => 'Δεδομένου', + 'name' => 'Greek', + 'native' => 'Ελληνικά', + 'scenario' => 'Σενάριο', + 'scenario_outline' => 'Περιγραφή Σεναρίου', + 'then' => 'Τότε', + 'when' => 'Όταν', + ), + 'en-Scouse' => + array ( + 'and' => 'An', + 'background' => 'Dis is what went down', + 'but' => 'Buh', + 'examples' => 'Examples', + 'feature' => 'Feature', + 'given' => 'Youse know when youse got|Givun', + 'name' => 'Scouse', + 'native' => 'Scouse', + 'scenario' => 'The thing of it is', + 'scenario_outline' => 'Wharrimean is', + 'then' => 'Den youse gotta|Dun', + 'when' => 'Youse know like when|Wun', + ), + 'en-au' => + array ( + 'and' => 'Too right', + 'background' => 'First off', + 'but' => 'Yeah nah', + 'examples' => 'You\'ll wanna', + 'feature' => 'Pretty much', + 'given' => 'Y\'know', + 'name' => 'Australian', + 'native' => 'Australian', + 'scenario' => 'Awww, look mate', + 'scenario_outline' => 'Reckon it\'s like', + 'then' => 'But at the end of the day I reckon', + 'when' => 'It\'s just unbelievable', + ), + 'en-lol' => + array ( + 'and' => 'AN', + 'background' => 'B4', + 'but' => 'BUT', + 'examples' => 'EXAMPLZ', + 'feature' => 'OH HAI', + 'given' => 'I CAN HAZ', + 'name' => 'LOLCAT', + 'native' => 'LOLCAT', + 'scenario' => 'MISHUN', + 'scenario_outline' => 'MISHUN SRSLY', + 'then' => 'DEN', + 'when' => 'WEN', + ), + 'en-old' => + array ( + 'and' => 'Ond|7', + 'background' => 'Aer|Ær', + 'but' => 'Ac', + 'examples' => 'Se the|Se þe|Se ðe', + 'feature' => 'Hwaet|Hwæt', + 'given' => 'Thurh|Ðurh|Þurh', + 'name' => 'Old English', + 'native' => 'Englisc', + 'scenario' => 'Swa', + 'scenario_outline' => 'Swa hwaer swa|Swa hwær swa', + 'then' => 'Tha the|Ða ðe|Þa þe|Tha|Ða|Þa', + 'when' => 'Tha|Ða|Þa', + ), + 'en-pirate' => + array ( + 'and' => 'Aye', + 'background' => 'Yo-ho-ho', + 'but' => 'Avast!', + 'examples' => 'Dead men tell no tales', + 'feature' => 'Ahoy matey!', + 'given' => 'Gangway!', + 'name' => 'Pirate', + 'native' => 'Pirate', + 'scenario' => 'Heave to', + 'scenario_outline' => 'Shiver me timbers', + 'then' => 'Let go and haul', + 'when' => 'Blimey!', + ), + 'eo' => + array ( + 'and' => 'Kaj', + 'background' => 'Fono', + 'but' => 'Sed', + 'examples' => 'Ekzemploj', + 'feature' => 'Trajto', + 'given' => 'Donitaĵo|Komence', + 'name' => 'Esperanto', + 'native' => 'Esperanto', + 'scenario' => 'Scenaro|Kazo', + 'scenario_outline' => 'Konturo de la scenaro|Skizo|Kazo-skizo', + 'then' => 'Do', + 'when' => 'Se', + ), + 'es' => + array ( + 'and' => 'E|Y', + 'background' => 'Antecedentes', + 'but' => 'Pero', + 'examples' => 'Ejemplos', + 'feature' => 'Característica', + 'given' => 'Dadas|Dados|Dada|Dado', + 'name' => 'Spanish', + 'native' => 'español', + 'scenario' => 'Escenario', + 'scenario_outline' => 'Esquema del escenario', + 'then' => 'Entonces', + 'when' => 'Cuando', + ), + 'et' => + array ( + 'and' => 'Ja', + 'background' => 'Taust', + 'but' => 'Kuid', + 'examples' => 'Juhtumid', + 'feature' => 'Omadus', + 'given' => 'Eeldades', + 'name' => 'Estonian', + 'native' => 'eesti keel', + 'scenario' => 'Stsenaarium', + 'scenario_outline' => 'Raamstsenaarium', + 'then' => 'Siis', + 'when' => 'Kui', + ), + 'fa' => + array ( + 'and' => 'و', + 'background' => 'زمینه', + 'but' => 'اما', + 'examples' => 'نمونه ها', + 'feature' => 'وِیژگی', + 'given' => 'با فرض', + 'name' => 'Persian', + 'native' => 'فارسی', + 'scenario' => 'سناریو', + 'scenario_outline' => 'الگوی سناریو', + 'then' => 'آنگاه', + 'when' => 'هنگامی', + ), + 'fi' => + array ( + 'and' => 'Ja', + 'background' => 'Tausta', + 'but' => 'Mutta', + 'examples' => 'Tapaukset', + 'feature' => 'Ominaisuus', + 'given' => 'Oletetaan', + 'name' => 'Finnish', + 'native' => 'suomi', + 'scenario' => 'Tapaus', + 'scenario_outline' => 'Tapausaihio', + 'then' => 'Niin', + 'when' => 'Kun', + ), + 'fr' => + array ( + 'and' => 'Et', + 'background' => 'Contexte', + 'but' => 'Mais', + 'examples' => 'Exemples', + 'feature' => 'Fonctionnalité', + 'given' => 'Étant données|Etant données|Etant donnée|Étant donnés|Etant donnés|Étant donnée|Etant donné|Étant donné|Soit', + 'name' => 'French', + 'native' => 'français', + 'scenario' => 'Scénario', + 'scenario_outline' => 'Plan du scénario|Plan du Scénario', + 'then' => 'Alors', + 'when' => 'Lorsqu\'<|Lorsque|Quand', + ), + 'gj' => + array ( + 'and' => 'અને', + 'background' => 'બેકગ્રાઉન્ડ', + 'but' => 'પણ', + 'examples' => 'ઉદાહરણો', + 'feature' => 'લક્ષણ|વ્યાપાર જરૂર|ક્ષમતા', + 'given' => 'આપેલ છે', + 'name' => 'Gujarati', + 'native' => 'ગુજરાતી', + 'scenario' => 'સ્થિતિ', + 'scenario_outline' => 'પરિદ્દશ્ય રૂપરેખા|પરિદ્દશ્ય ઢાંચો', + 'then' => 'પછી', + 'when' => 'ક્યારે', + ), + 'gl' => + array ( + 'and' => 'E', + 'background' => 'Contexto', + 'but' => 'Pero|Mais', + 'examples' => 'Exemplos', + 'feature' => 'Característica', + 'given' => 'Dadas|Dados|Dada|Dado', + 'name' => 'Galician', + 'native' => 'galego', + 'scenario' => 'Escenario', + 'scenario_outline' => 'Esbozo do escenario', + 'then' => 'Entón|Logo', + 'when' => 'Cando', + ), + 'he' => + array ( + 'and' => 'וגם', + 'background' => 'רקע', + 'but' => 'אבל', + 'examples' => 'דוגמאות', + 'feature' => 'תכונה', + 'given' => 'בהינתן', + 'name' => 'Hebrew', + 'native' => 'עברית', + 'scenario' => 'תרחיש', + 'scenario_outline' => 'תבנית תרחיש', + 'then' => 'אזי|אז', + 'when' => 'כאשר', + ), + 'hi' => + array ( + 'and' => 'तथा|और', + 'background' => 'पृष्ठभूमि', + 'but' => 'किन्तु|परन्तु|पर', + 'examples' => 'उदाहरण', + 'feature' => 'रूप लेख', + 'given' => 'चूंकि|यदि|अगर', + 'name' => 'Hindi', + 'native' => 'हिंदी', + 'scenario' => 'परिदृश्य', + 'scenario_outline' => 'परिदृश्य रूपरेखा', + 'then' => 'तदा|तब', + 'when' => 'कदा|जब', + ), + 'hr' => + array ( + 'and' => 'I', + 'background' => 'Pozadina', + 'but' => 'Ali', + 'examples' => 'Primjeri|Scenariji', + 'feature' => 'Osobina|Mogućnost|Mogucnost', + 'given' => 'Zadano|Zadani|Zadan', + 'name' => 'Croatian', + 'native' => 'hrvatski', + 'scenario' => 'Scenarij', + 'scenario_outline' => 'Skica|Koncept', + 'then' => 'Onda', + 'when' => 'Kada|Kad', + ), + 'ht' => + array ( + 'and' => 'Epi|Ak|E', + 'background' => 'Kontèks|Istorik', + 'but' => 'Men', + 'examples' => 'Egzanp', + 'feature' => 'Karakteristik|Mak|Fonksyonalite', + 'given' => 'Sipoze Ke|Sipoze ke|Sipoze', + 'name' => 'Creole', + 'native' => 'kreyòl', + 'scenario' => 'Senaryo', + 'scenario_outline' => 'Plan senaryo|Plan Senaryo|Senaryo deskripsyon|Senaryo Deskripsyon|Dyagram senaryo|Dyagram Senaryo', + 'then' => 'Le sa a|Lè sa a', + 'when' => 'Le|Lè', + ), + 'hu' => + array ( + 'and' => 'És', + 'background' => 'Háttér', + 'but' => 'De', + 'examples' => 'Példák', + 'feature' => 'Jellemző', + 'given' => 'Amennyiben|Adott', + 'name' => 'Hungarian', + 'native' => 'magyar', + 'scenario' => 'Forgatókönyv', + 'scenario_outline' => 'Forgatókönyv vázlat', + 'then' => 'Akkor', + 'when' => 'Amikor|Majd|Ha', + ), + 'id' => + array ( + 'and' => 'Dan', + 'background' => 'Dasar', + 'but' => 'Tapi', + 'examples' => 'Contoh', + 'feature' => 'Fitur', + 'given' => 'Dengan', + 'name' => 'Indonesian', + 'native' => 'Bahasa Indonesia', + 'scenario' => 'Skenario', + 'scenario_outline' => 'Skenario konsep', + 'then' => 'Maka', + 'when' => 'Ketika', + ), + 'is' => + array ( + 'and' => 'Og', + 'background' => 'Bakgrunnur', + 'but' => 'En', + 'examples' => 'Dæmi|Atburðarásir', + 'feature' => 'Eiginleiki', + 'given' => 'Ef', + 'name' => 'Icelandic', + 'native' => 'Íslenska', + 'scenario' => 'Atburðarás', + 'scenario_outline' => 'Lýsing Atburðarásar|Lýsing Dæma', + 'then' => 'Þá', + 'when' => 'Þegar', + ), + 'it' => + array ( + 'and' => 'E', + 'background' => 'Contesto', + 'but' => 'Ma', + 'examples' => 'Esempi', + 'feature' => 'Funzionalità', + 'given' => 'Date|Dati|Data|Dato', + 'name' => 'Italian', + 'native' => 'italiano', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Schema dello scenario', + 'then' => 'Allora', + 'when' => 'Quando', + ), + 'ja' => + array ( + 'and' => 'かつ<', + 'background' => '背景', + 'but' => 'しかし<|ただし<|但し<', + 'examples' => '例|サンプル', + 'feature' => 'フィーチャ|機能', + 'given' => '前提<', + 'name' => 'Japanese', + 'native' => '日本語', + 'scenario' => 'シナリオ', + 'scenario_outline' => 'シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ', + 'then' => 'ならば<', + 'when' => 'もし<', + ), + 'jv' => + array ( + 'and' => 'Lan', + 'background' => 'Dasar', + 'but' => 'Ananging|Nanging|Tapi', + 'examples' => 'Conto|Contone', + 'feature' => 'Fitur', + 'given' => 'Nalikaning|Nalika', + 'name' => 'Javanese', + 'native' => 'Basa Jawa', + 'scenario' => 'Skenario', + 'scenario_outline' => 'Konsep skenario', + 'then' => 'Banjur|Njuk', + 'when' => 'Menawa|Manawa', + ), + 'kn' => + array ( + 'and' => 'ಮತ್ತು', + 'background' => 'ಹಿನ್ನೆಲೆ', + 'but' => 'ಆದರೆ', + 'examples' => 'ಉದಾಹರಣೆಗಳು', + 'feature' => 'ಹೆಚ್ಚಳ', + 'given' => 'ನೀಡಿದ', + 'name' => 'Kannada', + 'native' => 'ಕನ್ನಡ', + 'scenario' => 'ಕಥಾಸಾರಾಂಶ', + 'scenario_outline' => 'ವಿವರಣೆ', + 'then' => 'ನಂತರ', + 'when' => 'ಸ್ಥಿತಿಯನ್ನು', + ), + 'ko' => + array ( + 'and' => '그리고<', + 'background' => '배경', + 'but' => '하지만<|단<', + 'examples' => '예', + 'feature' => '기능', + 'given' => '먼저<|조건<', + 'name' => 'Korean', + 'native' => '한국어', + 'scenario' => '시나리오', + 'scenario_outline' => '시나리오 개요', + 'then' => '그러면<', + 'when' => '만약<|만일<', + ), + 'lt' => + array ( + 'and' => 'Ir', + 'background' => 'Kontekstas', + 'but' => 'Bet', + 'examples' => 'Pavyzdžiai|Scenarijai|Variantai', + 'feature' => 'Savybė', + 'given' => 'Duota', + 'name' => 'Lithuanian', + 'native' => 'lietuvių kalba', + 'scenario' => 'Scenarijus', + 'scenario_outline' => 'Scenarijaus šablonas', + 'then' => 'Tada', + 'when' => 'Kai', + ), + 'lu' => + array ( + 'and' => 'an|a', + 'background' => 'Hannergrond', + 'but' => 'awer|mä', + 'examples' => 'Beispiller', + 'feature' => 'Funktionalitéit', + 'given' => 'ugeholl', + 'name' => 'Luxemburgish', + 'native' => 'Lëtzebuergesch', + 'scenario' => 'Szenario', + 'scenario_outline' => 'Plang vum Szenario', + 'then' => 'dann', + 'when' => 'wann', + ), + 'lv' => + array ( + 'and' => 'Un', + 'background' => 'Konteksts|Situācija', + 'but' => 'Bet', + 'examples' => 'Piemēri|Paraugs', + 'feature' => 'Funkcionalitāte|Fīča', + 'given' => 'Kad', + 'name' => 'Latvian', + 'native' => 'latviešu', + 'scenario' => 'Scenārijs', + 'scenario_outline' => 'Scenārijs pēc parauga', + 'then' => 'Tad', + 'when' => 'Ja', + ), + 'nl' => + array ( + 'and' => 'En', + 'background' => 'Achtergrond', + 'but' => 'Maar', + 'examples' => 'Voorbeelden', + 'feature' => 'Functionaliteit', + 'given' => 'Gegeven|Stel', + 'name' => 'Dutch', + 'native' => 'Nederlands', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Abstract Scenario', + 'then' => 'Dan', + 'when' => 'Als', + ), + 'no' => + array ( + 'and' => 'Og', + 'background' => 'Bakgrunn', + 'but' => 'Men', + 'examples' => 'Eksempler', + 'feature' => 'Egenskap', + 'given' => 'Gitt', + 'name' => 'Norwegian', + 'native' => 'norsk', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Scenariomal|Abstrakt Scenario', + 'then' => 'Så', + 'when' => 'Når', + ), + 'pa' => + array ( + 'and' => 'ਅਤੇ', + 'background' => 'ਪਿਛੋਕੜ', + 'but' => 'ਪਰ', + 'examples' => 'ਉਦਾਹਰਨਾਂ', + 'feature' => 'ਖਾਸੀਅਤ|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ', + 'given' => 'ਜਿਵੇਂ ਕਿ|ਜੇਕਰ', + 'name' => 'Panjabi', + 'native' => 'ਪੰਜਾਬੀ', + 'scenario' => 'ਪਟਕਥਾ', + 'scenario_outline' => 'ਪਟਕਥਾ ਢਾਂਚਾ|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ', + 'then' => 'ਤਦ', + 'when' => 'ਜਦੋਂ', + ), + 'pl' => + array ( + 'and' => 'Oraz|I', + 'background' => 'Założenia', + 'but' => 'Ale', + 'examples' => 'Przykłady', + 'feature' => 'Właściwość|Funkcja|Aspekt|Potrzeba biznesowa', + 'given' => 'Zakładając, że|Zakładając|Mając', + 'name' => 'Polish', + 'native' => 'polski', + 'scenario' => 'Scenariusz', + 'scenario_outline' => 'Szablon scenariusza', + 'then' => 'Wtedy', + 'when' => 'Jeżeli|Kiedy|Jeśli|Gdy', + ), + 'pt' => + array ( + 'and' => 'E', + 'background' => 'Contexto|Cenário de Fundo|Cenario de Fundo|Fundo', + 'but' => 'Mas', + 'examples' => 'Exemplos|Cenários|Cenarios', + 'feature' => 'Funcionalidade|Característica|Caracteristica', + 'given' => 'Dadas|Dados|Dada|Dado', + 'name' => 'Portuguese', + 'native' => 'português', + 'scenario' => 'Cenário|Cenario', + 'scenario_outline' => 'Esquema do Cenário|Esquema do Cenario|Delineação do Cenário|Delineacao do Cenario', + 'then' => 'Entao|Então', + 'when' => 'Quando', + ), + 'ro' => + array ( + 'and' => 'Şi|Și|Si', + 'background' => 'Context', + 'but' => 'Dar', + 'examples' => 'Exemple', + 'feature' => 'Functionalitate|Funcționalitate|Funcţionalitate', + 'given' => 'Daţi fiind|Dați fiind|Dati fiind|Date fiind|Dat fiind', + 'name' => 'Romanian', + 'native' => 'română', + 'scenario' => 'Scenariu', + 'scenario_outline' => 'Structura scenariu|Structură scenariu', + 'then' => 'Atunci', + 'when' => 'Când|Cand', + ), + 'ru' => + array ( + 'and' => 'К тому же|Также|И', + 'background' => 'Предыстория|Контекст', + 'but' => 'Но|А', + 'examples' => 'Примеры', + 'feature' => 'Функция|Функционал|Свойство', + 'given' => 'Допустим|Пусть|Дано', + 'name' => 'Russian', + 'native' => 'русский', + 'scenario' => 'Сценарий', + 'scenario_outline' => 'Структура сценария', + 'then' => 'Тогда|То', + 'when' => 'Когда|Если', + ), + 'sk' => + array ( + 'and' => 'A zároveň|A taktiež|A tiež|A', + 'background' => 'Pozadie', + 'but' => 'Ale', + 'examples' => 'Príklady', + 'feature' => 'Požiadavka|Funkcia|Vlastnosť', + 'given' => 'Za predpokladu|Pokiaľ', + 'name' => 'Slovak', + 'native' => 'Slovensky', + 'scenario' => 'Scenár', + 'scenario_outline' => 'Náčrt Scenáru|Náčrt Scenára|Osnova Scenára', + 'then' => 'Potom|Tak', + 'when' => 'Keď|Ak', + ), + 'sl' => + array ( + 'and' => 'Ter|In', + 'background' => 'Kontekst|Osnova|Ozadje', + 'but' => 'Vendar|Ampak|Toda', + 'examples' => 'Primeri|Scenariji', + 'feature' => 'Funkcionalnost|Funkcija|Možnosti|Moznosti|Lastnost|Značilnost', + 'given' => 'Privzeto|Zaradi|Podano|Dano', + 'name' => 'Slovenian', + 'native' => 'Slovenski', + 'scenario' => 'Scenarij|Primer', + 'scenario_outline' => 'Struktura scenarija|Skica|Koncept|Oris scenarija|Osnutek', + 'then' => 'Takrat|Potem|Nato', + 'when' => 'Kadar|Če|Ce|Ko', + ), + 'sr-Cyrl' => + array ( + 'and' => 'И', + 'background' => 'Контекст|Основа|Позадина', + 'but' => 'Али', + 'examples' => 'Примери|Сценарији', + 'feature' => 'Функционалност|Могућност|Особина', + 'given' => 'За дати|За дате|За дато', + 'name' => 'Serbian', + 'native' => 'Српски', + 'scenario' => 'Сценарио|Пример', + 'scenario_outline' => 'Структура сценарија|Скица|Концепт', + 'then' => 'Онда', + 'when' => 'Када|Кад', + ), + 'sr-Latn' => + array ( + 'and' => 'I', + 'background' => 'Kontekst|Osnova|Pozadina', + 'but' => 'Ali', + 'examples' => 'Primeri|Scenariji', + 'feature' => 'Funkcionalnost|Mogućnost|Mogucnost|Osobina', + 'given' => 'Za dati|Za date|Za dato', + 'name' => 'Serbian (Latin)', + 'native' => 'Srpski (Latinica)', + 'scenario' => 'Scenario|Primer', + 'scenario_outline' => 'Struktura scenarija|Skica|Koncept', + 'then' => 'Onda', + 'when' => 'Kada|Kad', + ), + 'sv' => + array ( + 'and' => 'Och', + 'background' => 'Bakgrund', + 'but' => 'Men', + 'examples' => 'Exempel', + 'feature' => 'Egenskap', + 'given' => 'Givet', + 'name' => 'Swedish', + 'native' => 'Svenska', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Abstrakt Scenario|Scenariomall', + 'then' => 'Så', + 'when' => 'När', + ), + 'ta' => + array ( + 'and' => 'மற்றும்|மேலும் ', + 'background' => 'பின்னணி', + 'but' => 'ஆனால் ', + 'examples' => 'எடுத்துக்காட்டுகள்|காட்சிகள்| நிலைமைகளில்', + 'feature' => 'அம்சம்|வணிக தேவை|திறன்', + 'given' => 'கொடுக்கப்பட்ட', + 'name' => 'Tamil', + 'native' => 'தமிழ்', + 'scenario' => 'காட்சி', + 'scenario_outline' => 'காட்சி சுருக்கம்|காட்சி வார்ப்புரு', + 'then' => 'அப்பொழுது', + 'when' => 'எப்போது', + ), + 'th' => + array ( + 'and' => 'และ', + 'background' => 'แนวคิด', + 'but' => 'แต่', + 'examples' => 'ชุดของตัวอย่าง|ชุดของเหตุการณ์', + 'feature' => 'โครงหลัก|ความต้องการทางธุรกิจ|ความสามารถ', + 'given' => 'กำหนดให้', + 'name' => 'Thai', + 'native' => 'ไทย', + 'scenario' => 'เหตุการณ์', + 'scenario_outline' => 'สรุปเหตุการณ์|โครงสร้างของเหตุการณ์', + 'then' => 'ดังนั้น', + 'when' => 'เมื่อ', + ), + 'tl' => + array ( + 'and' => 'మరియు', + 'background' => 'నేపథ్యం', + 'but' => 'కాని', + 'examples' => 'ఉదాహరణలు', + 'feature' => 'గుణము', + 'given' => 'చెప్పబడినది', + 'name' => 'Telugu', + 'native' => 'తెలుగు', + 'scenario' => 'సన్నివేశం', + 'scenario_outline' => 'కథనం', + 'then' => 'అప్పుడు', + 'when' => 'ఈ పరిస్థితిలో', + ), + 'tlh' => + array ( + 'and' => 'latlh|\'ej', + 'background' => 'mo\'', + 'but' => '\'ach|\'a', + 'examples' => 'ghantoH|lutmey', + 'feature' => 'Qap|Qu\'meH \'ut|perbogh|poQbogh malja\'|laH', + 'given' => 'DaH ghu\' bejlu\'|ghu\' noblu\'', + 'name' => 'Klingon', + 'native' => 'tlhIngan', + 'scenario' => 'lut', + 'scenario_outline' => 'lut chovnatlh', + 'then' => 'vaj', + 'when' => 'qaSDI\'', + ), + 'tr' => + array ( + 'and' => 'Ve', + 'background' => 'Geçmiş', + 'but' => 'Fakat|Ama', + 'examples' => 'Örnekler', + 'feature' => 'Özellik', + 'given' => 'Diyelim ki', + 'name' => 'Turkish', + 'native' => 'Türkçe', + 'scenario' => 'Senaryo', + 'scenario_outline' => 'Senaryo taslağı', + 'then' => 'O zaman', + 'when' => 'Eğer ki', + ), + 'tt' => + array ( + 'and' => 'Һәм|Вә', + 'background' => 'Кереш', + 'but' => 'Ләкин|Әмма', + 'examples' => 'Үрнәкләр|Мисаллар', + 'feature' => 'Мөмкинлек|Үзенчәлеклелек', + 'given' => 'Әйтик', + 'name' => 'Tatar', + 'native' => 'Татарча', + 'scenario' => 'Сценарий', + 'scenario_outline' => 'Сценарийның төзелеше', + 'then' => 'Нәтиҗәдә', + 'when' => 'Әгәр', + ), + 'uk' => + array ( + 'and' => 'А також|Та|І', + 'background' => 'Передумова', + 'but' => 'Але', + 'examples' => 'Приклади', + 'feature' => 'Функціонал', + 'given' => 'Припустимо, що|Припустимо|Нехай|Дано', + 'name' => 'Ukrainian', + 'native' => 'Українська', + 'scenario' => 'Сценарій', + 'scenario_outline' => 'Структура сценарію', + 'then' => 'Тоді|То', + 'when' => 'Коли|Якщо', + ), + 'ur' => + array ( + 'and' => 'اور', + 'background' => 'پس منظر', + 'but' => 'لیکن', + 'examples' => 'مثالیں', + 'feature' => 'صلاحیت|کاروبار کی ضرورت|خصوصیت', + 'given' => 'فرض کیا|بالفرض|اگر', + 'name' => 'Urdu', + 'native' => 'اردو', + 'scenario' => 'منظرنامہ', + 'scenario_outline' => 'منظر نامے کا خاکہ', + 'then' => 'پھر|تب', + 'when' => 'جب', + ), + 'uz' => + array ( + 'and' => 'Ва', + 'background' => 'Тарих', + 'but' => 'Лекин|Бирок|Аммо', + 'examples' => 'Мисоллар', + 'feature' => 'Функционал', + 'given' => 'Агар', + 'name' => 'Uzbek', + 'native' => 'Узбекча', + 'scenario' => 'Сценарий', + 'scenario_outline' => 'Сценарий структураси', + 'then' => 'Унда', + 'when' => 'Агар', + ), + 'vi' => + array ( + 'and' => 'Và', + 'background' => 'Bối cảnh', + 'but' => 'Nhưng', + 'examples' => 'Dữ liệu', + 'feature' => 'Tính năng', + 'given' => 'Biết|Cho', + 'name' => 'Vietnamese', + 'native' => 'Tiếng Việt', + 'scenario' => 'Tình huống|Kịch bản', + 'scenario_outline' => 'Khung tình huống|Khung kịch bản', + 'then' => 'Thì', + 'when' => 'Khi', + ), + 'zh-CN' => + array ( + 'and' => '同时<|并且<|而且<', + 'background' => '背景', + 'but' => '但是<', + 'examples' => '例子', + 'feature' => '功能', + 'given' => '假定<|假设<|假如<', + 'name' => 'Chinese simplified', + 'native' => '简体中文', + 'scenario' => '场景|剧本', + 'scenario_outline' => '场景大纲|剧本大纲', + 'then' => '那么<', + 'when' => '当<', + ), + 'zh-TW' => + array ( + 'and' => '同時<|並且<|而且<', + 'background' => '背景', + 'but' => '但是<', + 'examples' => '例子', + 'feature' => '功能', + 'given' => '假定<|假設<|假如<', + 'name' => 'Chinese traditional', + 'native' => '繁體中文', + 'scenario' => '場景|劇本', + 'scenario_outline' => '場景大綱|劇本大綱', + 'then' => '那麼<', + 'when' => '當<', + ), +); \ No newline at end of file diff --git a/vendor/behat/gherkin/libpath.php b/vendor/behat/gherkin/libpath.php new file mode 100644 index 0000000..35379fe --- /dev/null +++ b/vendor/behat/gherkin/libpath.php @@ -0,0 +1,3 @@ + + + gherkin + pear.behat.org + Behat\Gherkin is a BDD DSL for PHP + + Behat\Gherkin is an open source behavior driven development DSL for php 5.3. + + + Konstantin Kudryashov + everzet + ever.zet@gmail.com + yes + + ##CURRENT_DATE## + + ##GHERKIN_VERSION## + 1.0.0 + + + ##STABILITY## + ##STABILITY## + + MIT + - + + + + ##SOURCE_FILES## + + + + + + + + + + + + + + + + + + + 5.3.1 + + + 1.4.0 + + + pcre + + + simplexml + + + xml + + + mbstring + + + + + diff --git a/vendor/behat/gherkin/phpdoc.ini.dist b/vendor/behat/gherkin/phpdoc.ini.dist new file mode 100644 index 0000000..f983946 --- /dev/null +++ b/vendor/behat/gherkin/phpdoc.ini.dist @@ -0,0 +1,14 @@ +files = "*.php" +ignore = "CVS, .svn, .git, _compiled" +source_path = "./src" +doclet = standard +overview = readme.html +package_comment_dir = ./ +public = on +d = "api" +default_package = "Behat Gherkin" +windowtitle = "Behat Gherkin" +doctitle = "Behat Gherkin: PHP 5.3 Gherkin parser" +header = "Behat Gherkin" +footer = "Behat Gherkin" +tree = on diff --git a/vendor/behat/gherkin/phpunit.xml.dist b/vendor/behat/gherkin/phpunit.xml.dist new file mode 100644 index 0000000..24fc8d8 --- /dev/null +++ b/vendor/behat/gherkin/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + + ./tests/Behat/Gherkin/ + + + + + + ./src/Behat/Gherkin/ + + + diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Cache/CacheInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Cache/CacheInterface.php new file mode 100644 index 0000000..87d4a47 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Cache/CacheInterface.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Cache; + +use Behat\Gherkin\Node\FeatureNode; + +/** + * Parser cache interface. + * + * @author Konstantin Kudryashov + */ +interface CacheInterface +{ + /** + * Checks that cache for feature exists and is fresh. + * + * @param string $path Feature path + * @param integer $timestamp The last time feature was updated + * + * @return Boolean + */ + public function isFresh($path, $timestamp); + + /** + * Reads feature cache from path. + * + * @param string $path Feature path + * + * @return FeatureNode + */ + public function read($path); + + /** + * Caches feature node. + * + * @param string $path Feature path + * @param FeatureNode $feature Feature instance + */ + public function write($path, FeatureNode $feature); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Cache/FileCache.php b/vendor/behat/gherkin/src/Behat/Gherkin/Cache/FileCache.php new file mode 100644 index 0000000..aa1add9 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Cache/FileCache.php @@ -0,0 +1,102 @@ + +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +namespace Behat\Gherkin\Cache; + +use Behat\Gherkin\Exception\CacheException; +use Behat\Gherkin\Node\FeatureNode; + +/** + * File cache. + * Caches feature into a file. + * + * @author Konstantin Kudryashov + */ +class FileCache implements CacheInterface +{ + private $path; + + /** + * Initializes file cache. + * + * @param string $path Path to the folder where to store caches. + */ + public function __construct($path) + { + $this->path = rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'412'; + + if (!is_dir($this->path)) { + mkdir($this->path, 0777, true); + } + } + + /** + * Checks that cache for feature exists and is fresh. + * + * @param string $path Feature path + * @param integer $timestamp The last time feature was updated + * + * @return Boolean + */ + public function isFresh($path, $timestamp) + { + $cachePath = $this->getCachePathFor($path); + + if (!file_exists($cachePath)) { + return false; + } + + return filemtime($cachePath) > $timestamp; + } + + /** + * Reads feature cache from path. + * + * @param string $path Feature path + * + * @return FeatureNode + * + * @throws CacheException + */ + public function read($path) + { + $cachePath = $this->getCachePathFor($path); + $feature = unserialize(file_get_contents($cachePath)); + + if (!$feature instanceof FeatureNode) { + throw new CacheException(sprintf('Can not load cache for a feature "%s" from "%s".', $path, $cachePath )); + } + + return $feature; + } + + /** + * Caches feature node. + * + * @param string $path Feature path + * @param FeatureNode $feature Feature instance + */ + public function write($path, FeatureNode $feature) + { + file_put_contents($this->getCachePathFor($path), serialize($feature)); + } + + /** + * Returns feature cache file path from features path. + * + * @param string $path Feature path + * + * @return string + */ + protected function getCachePathFor($path) + { + return $this->path.'/'.md5($path).'.feature.cache'; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Cache/MemoryCache.php b/vendor/behat/gherkin/src/Behat/Gherkin/Cache/MemoryCache.php new file mode 100644 index 0000000..e404f30 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Cache/MemoryCache.php @@ -0,0 +1,66 @@ + +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +namespace Behat\Gherkin\Cache; + +use Behat\Gherkin\Node\FeatureNode; + +/** + * Memory cache. + * Caches feature into a memory. + * + * @author Konstantin Kudryashov + */ +class MemoryCache implements CacheInterface +{ + private $features = array(); + private $timestamps = array(); + + /** + * Checks that cache for feature exists and is fresh. + * + * @param string $path Feature path + * @param integer $timestamp The last time feature was updated + * + * @return Boolean + */ + public function isFresh($path, $timestamp) + { + if (!isset($this->features[$path])) { + return false; + } + + return $this->timestamps[$path] > $timestamp; + } + + /** + * Reads feature cache from path. + * + * @param string $path Feature path + * + * @return FeatureNode + */ + public function read($path) + { + return $this->features[$path]; + } + + /** + * Caches feature node. + * + * @param string $path Feature path + * @param FeatureNode $feature Feature instance + */ + public function write($path, FeatureNode $feature) + { + $this->features[$path] = $feature; + $this->timestamps[$path] = time(); + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Exception/CacheException.php b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/CacheException.php new file mode 100644 index 0000000..f8b9214 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/CacheException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Exception; + +use RuntimeException; + +/** + * Cache exception. + * + * @author Konstantin Kudryashov + */ +class CacheException extends RuntimeException implements Exception +{ +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Exception/Exception.php b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/Exception.php new file mode 100644 index 0000000..f377e30 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/Exception.php @@ -0,0 +1,15 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Exception; + +interface Exception +{ +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Exception/LexerException.php b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/LexerException.php new file mode 100644 index 0000000..476d81f --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/LexerException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Exception; + +use RuntimeException; + +class LexerException extends RuntimeException implements Exception +{ +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Exception/NodeException.php b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/NodeException.php new file mode 100644 index 0000000..b7d7a4c --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/NodeException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Exception; + +use RuntimeException; + +class NodeException extends RuntimeException implements Exception +{ +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Exception/ParserException.php b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/ParserException.php new file mode 100644 index 0000000..f835e72 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Exception/ParserException.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Exception; + +use RuntimeException; + +class ParserException extends RuntimeException implements Exception +{ +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/ComplexFilter.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/ComplexFilter.php new file mode 100644 index 0000000..a3a3b08 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/ComplexFilter.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\FeatureNode; + +/** + * Abstract filter class. + * + * @author Konstantin Kudryashov + */ +abstract class ComplexFilter implements ComplexFilterInterface +{ + /** + * Filters feature according to the filter. + * + * @param FeatureNode $feature + * + * @return FeatureNode + */ + public function filterFeature(FeatureNode $feature) + { + $scenarios = array(); + foreach ($feature->getScenarios() as $scenario) { + if (!$this->isScenarioMatch($feature, $scenario)) { + continue; + } + + $scenarios[] = $scenario; + } + + return new FeatureNode( + $feature->getTitle(), + $feature->getDescription(), + $feature->getTags(), + $feature->getBackground(), + $scenarios, + $feature->getKeyword(), + $feature->getLanguage(), + $feature->getFile(), + $feature->getLine() + ); + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/ComplexFilterInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/ComplexFilterInterface.php new file mode 100644 index 0000000..8a0ebd5 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/ComplexFilterInterface.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; + +/** + * Filter interface. + * + * @author Konstantin Kudryashov + */ +interface ComplexFilterInterface extends FeatureFilterInterface +{ + /** + * Checks if scenario or outline matches specified filter. + * + * @param FeatureNode $feature Feature node instance + * @param ScenarioInterface $scenario Scenario or Outline node instance + * + * @return Boolean + */ + public function isScenarioMatch(FeatureNode $feature, ScenarioInterface $scenario); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/FeatureFilterInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/FeatureFilterInterface.php new file mode 100644 index 0000000..a7c43ec --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/FeatureFilterInterface.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\FeatureNode; + +/** + * Feature filter interface. + * + * @author Konstantin Kudryashov + */ +interface FeatureFilterInterface +{ + /** + * Checks if Feature matches specified filter. + * + * @param FeatureNode $feature Feature instance + * + * @return Boolean + */ + public function isFeatureMatch(FeatureNode $feature); + + /** + * Filters feature according to the filter and returns new one. + * + * @param FeatureNode $feature + * + * @return FeatureNode + */ + public function filterFeature(FeatureNode $feature); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/FilterInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/FilterInterface.php new file mode 100644 index 0000000..4a531a0 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/FilterInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\ScenarioInterface; + +/** + * Filter interface. + * + * @author Konstantin Kudryashov + */ +interface FilterInterface extends FeatureFilterInterface +{ + /** + * Checks if scenario or outline matches specified filter. + * + * @param ScenarioInterface $scenario Scenario or Outline node instance + * + * @return Boolean + */ + public function isScenarioMatch(ScenarioInterface $scenario); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/LineFilter.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/LineFilter.php new file mode 100644 index 0000000..455e9ac --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/LineFilter.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\ExampleTableNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Gherkin\Node\ScenarioInterface; + +/** + * Filters scenarios by definition line number. + * + * @author Konstantin Kudryashov + */ +class LineFilter implements FilterInterface +{ + protected $filterLine; + + /** + * Initializes filter. + * + * @param string $filterLine Line of the scenario to filter on + */ + public function __construct($filterLine) + { + $this->filterLine = intval($filterLine); + } + + /** + * Checks if Feature matches specified filter. + * + * @param FeatureNode $feature Feature instance + * + * @return Boolean + */ + public function isFeatureMatch(FeatureNode $feature) + { + return $this->filterLine === $feature->getLine(); + } + + /** + * Checks if scenario or outline matches specified filter. + * + * @param ScenarioInterface $scenario Scenario or Outline node instance + * + * @return Boolean + */ + public function isScenarioMatch(ScenarioInterface $scenario) + { + if ($this->filterLine === $scenario->getLine()) { + return true; + } + + if ($scenario instanceof OutlineNode && $scenario->hasExamples()) { + return $this->filterLine === $scenario->getLine() + || in_array($this->filterLine, $scenario->getExampleTable()->getLines()); + } + + return false; + } + + /** + * Filters feature according to the filter and returns new one. + * + * @param FeatureNode $feature + * + * @return FeatureNode + */ + public function filterFeature(FeatureNode $feature) + { + $scenarios = array(); + foreach ($feature->getScenarios() as $scenario) { + if (!$this->isScenarioMatch($scenario)) { + continue; + } + + if ($scenario instanceof OutlineNode && $scenario->hasExamples()) { + $table = $scenario->getExampleTable()->getTable(); + $lines = array_keys($table); + + if (in_array($this->filterLine, $lines)) { + $filteredTable = array($lines[0] => $table[$lines[0]]); + + if ($lines[0] !== $this->filterLine) { + $filteredTable[$this->filterLine] = $table[$this->filterLine]; + } + + $scenario = new OutlineNode( + $scenario->getTitle(), + $scenario->getTags(), + $scenario->getSteps(), + new ExampleTableNode($filteredTable, $scenario->getExampleTable()->getKeyword()), + $scenario->getKeyword(), + $scenario->getLine() + ); + } + } + + $scenarios[] = $scenario; + } + + return new FeatureNode( + $feature->getTitle(), + $feature->getDescription(), + $feature->getTags(), + $feature->getBackground(), + $scenarios, + $feature->getKeyword(), + $feature->getLanguage(), + $feature->getFile(), + $feature->getLine() + ); + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/LineRangeFilter.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/LineRangeFilter.php new file mode 100644 index 0000000..b8062be --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/LineRangeFilter.php @@ -0,0 +1,134 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\ExampleTableNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Gherkin\Node\ScenarioInterface; + +/** + * Filters scenarios by definition line number range. + * + * @author Fabian Kiss + */ +class LineRangeFilter implements FilterInterface +{ + protected $filterMinLine; + protected $filterMaxLine; + + /** + * Initializes filter. + * + * @param string $filterMinLine Minimum line of a scenario to filter on + * @param string $filterMaxLine Maximum line of a scenario to filter on + */ + public function __construct($filterMinLine, $filterMaxLine) + { + $this->filterMinLine = intval($filterMinLine); + if ($filterMaxLine == '*') { + $this->filterMaxLine = PHP_INT_MAX; + } else { + $this->filterMaxLine = intval($filterMaxLine); + } + } + + /** + * Checks if Feature matches specified filter. + * + * @param FeatureNode $feature Feature instance + * + * @return Boolean + */ + public function isFeatureMatch(FeatureNode $feature) + { + return $this->filterMinLine <= $feature->getLine() + && $this->filterMaxLine >= $feature->getLine(); + } + + /** + * Checks if scenario or outline matches specified filter. + * + * @param ScenarioInterface $scenario Scenario or Outline node instance + * + * @return Boolean + */ + public function isScenarioMatch(ScenarioInterface $scenario) + { + if ($this->filterMinLine <= $scenario->getLine() && $this->filterMaxLine >= $scenario->getLine()) { + return true; + } + + if ($scenario instanceof OutlineNode && $scenario->hasExamples()) { + foreach ($scenario->getExampleTable()->getLines() as $line) { + if ($this->filterMinLine <= $line && $this->filterMaxLine >= $line) { + return true; + } + } + } + + return false; + } + + /** + * Filters feature according to the filter. + * + * @param FeatureNode $feature + * + * @return FeatureNode + */ + public function filterFeature(FeatureNode $feature) + { + $scenarios = array(); + foreach ($feature->getScenarios() as $scenario) { + if (!$this->isScenarioMatch($scenario)) { + continue; + } + + if ($scenario instanceof OutlineNode && $scenario->hasExamples()) { + $table = $scenario->getExampleTable()->getTable(); + $lines = array_keys($table); + + $filteredTable = array($lines[0] => $table[$lines[0]]); + unset($table[$lines[0]]); + + foreach ($table as $line => $row) { + if ($this->filterMinLine <= $line && $this->filterMaxLine >= $line) { + $filteredTable[$line] = $row; + } + } + + $scenario = new OutlineNode( + $scenario->getTitle(), + $scenario->getTags(), + $scenario->getSteps(), + new ExampleTableNode($filteredTable, $scenario->getExampleTable()->getKeyword()), + $scenario->getKeyword(), + $scenario->getLine() + ); + } + + $scenarios[] = $scenario; + } + + return new FeatureNode( + $feature->getTitle(), + $feature->getDescription(), + $feature->getTags(), + $feature->getBackground(), + $scenarios, + $feature->getKeyword(), + $feature->getLanguage(), + $feature->getFile(), + $feature->getLine() + ); + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/NameFilter.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/NameFilter.php new file mode 100644 index 0000000..82ae0e5 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/NameFilter.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; + +/** + * Filters scenarios by feature/scenario name. + * + * @author Konstantin Kudryashov + */ +class NameFilter extends SimpleFilter +{ + protected $filterString; + + /** + * Initializes filter. + * + * @param string $filterString Name filter string + */ + public function __construct($filterString) + { + $this->filterString = trim($filterString); + } + + /** + * Checks if Feature matches specified filter. + * + * @param FeatureNode $feature Feature instance + * + * @return Boolean + */ + public function isFeatureMatch(FeatureNode $feature) + { + if ('/' === $this->filterString[0]) { + return 1 === preg_match($this->filterString, $feature->getTitle()); + } + + return false !== mb_strpos($feature->getTitle(), $this->filterString, 0, 'utf8'); + } + + /** + * Checks if scenario or outline matches specified filter. + * + * @param ScenarioInterface $scenario Scenario or Outline node instance + * + * @return Boolean + */ + public function isScenarioMatch(ScenarioInterface $scenario) + { + if ('/' === $this->filterString[0] && 1 === preg_match($this->filterString, $scenario->getTitle())) { + return true; + } elseif (false !== mb_strpos($scenario->getTitle(), $this->filterString, 0, 'utf8')) { + return true; + } + + return false; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/NarrativeFilter.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/NarrativeFilter.php new file mode 100644 index 0000000..61126e5 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/NarrativeFilter.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\ScenarioInterface; +use Behat\Gherkin\Node\FeatureNode; + +/** + * Filters features by their narrative using regular expression. + * + * @author Konstantin Kudryashov + */ +class NarrativeFilter extends SimpleFilter +{ + /** + * @var string + */ + private $regex; + + /** + * Initializes filter. + * + * @param string $regex + */ + public function __construct($regex) + { + $this->regex = $regex; + } + + /** + * Checks if Feature matches specified filter. + * + * @param FeatureNode $feature Feature instance + * + * @return Boolean + */ + public function isFeatureMatch(FeatureNode $feature) + { + return 1 === preg_match($this->regex, $feature->getDescription()); + } + + /** + * Checks if scenario or outline matches specified filter. + * + * @param ScenarioInterface $scenario Scenario or Outline node instance + * + * @return Boolean + */ + public function isScenarioMatch(ScenarioInterface $scenario) + { + return false; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/PathsFilter.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/PathsFilter.php new file mode 100644 index 0000000..fdfa2c7 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/PathsFilter.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; + +/** + * Filters features by their paths. + * + * @author Konstantin Kudryashov + */ +class PathsFilter extends SimpleFilter +{ + protected $filterPaths = array(); + + /** + * Initializes filter. + * + * @param string[] $paths List of approved paths + */ + public function __construct(array $paths) + { + $this->filterPaths = array_map('realpath', $paths); + } + + /** + * Checks if Feature matches specified filter. + * + * @param FeatureNode $feature Feature instance + * + * @return Boolean + */ + public function isFeatureMatch(FeatureNode $feature) + { + foreach ($this->filterPaths as $path) { + if (!$path) { + continue; + } + + if (0 === strpos($feature->getFile(), $path)) { + return true; + } + } + + return false; + } + + /** + * Checks if scenario or outline matches specified filter. + * + * @param ScenarioInterface $scenario Scenario or Outline node instance + * + * @return false This filter is designed to work only with features + */ + public function isScenarioMatch(ScenarioInterface $scenario) + { + return false; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/RoleFilter.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/RoleFilter.php new file mode 100644 index 0000000..19e9377 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/RoleFilter.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; + +/** + * Filters features by their actors role. + * + * @author Konstantin Kudryashov + */ +class RoleFilter extends SimpleFilter +{ + protected $pattern; + + /** + * Initializes filter. + * + * @param string $role Approved role wildcard + */ + public function __construct($role) + { + $this->pattern = '/as an? ' . strtr(preg_quote($role, '/'), array( + '\*' => '.*', + '\?' => '.', + '\[' => '[', + '\]' => ']' + )) . '[$\n]/i'; + } + + /** + * Checks if Feature matches specified filter. + * + * @param FeatureNode $feature Feature instance + * + * @return Boolean + */ + public function isFeatureMatch(FeatureNode $feature) + { + return 1 === preg_match($this->pattern, $feature->getDescription()); + } + + /** + * Checks if scenario or outline matches specified filter. + * + * @param ScenarioInterface $scenario Scenario or Outline node instance + * + * @return false This filter is designed to work only with features + */ + public function isScenarioMatch(ScenarioInterface $scenario) + { + return false; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/SimpleFilter.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/SimpleFilter.php new file mode 100644 index 0000000..10bee8f --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/SimpleFilter.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\FeatureNode; + +/** + * Abstract filter class. + * + * @author Konstantin Kudryashov + */ +abstract class SimpleFilter implements FilterInterface +{ + /** + * Filters feature according to the filter. + * + * @param FeatureNode $feature + * + * @return FeatureNode + */ + public function filterFeature(FeatureNode $feature) + { + if ($this->isFeatureMatch($feature)) { + return $feature; + } + + $scenarios = array(); + foreach ($feature->getScenarios() as $scenario) { + if (!$this->isScenarioMatch($scenario)) { + continue; + } + + $scenarios[] = $scenario; + } + + return new FeatureNode( + $feature->getTitle(), + $feature->getDescription(), + $feature->getTags(), + $feature->getBackground(), + $scenarios, + $feature->getKeyword(), + $feature->getLanguage(), + $feature->getFile(), + $feature->getLine() + ); + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Filter/TagFilter.php b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/TagFilter.php new file mode 100644 index 0000000..fed6c1a --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/TagFilter.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Filter; + +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\ScenarioInterface; + +/** + * Filters scenarios by feature/scenario tag. + * + * @author Konstantin Kudryashov + */ +class TagFilter extends ComplexFilter +{ + protected $filterString; + + /** + * Initializes filter. + * + * @param string $filterString Name filter string + */ + public function __construct($filterString) + { + $this->filterString = trim($filterString); + } + + /** + * Checks if Feature matches specified filter. + * + * @param FeatureNode $feature Feature instance + * + * @return Boolean + */ + public function isFeatureMatch(FeatureNode $feature) + { + return $this->isTagsMatchCondition($feature->getTags()); + } + + /** + * Checks if scenario or outline matches specified filter. + * + * @param FeatureNode $feature Feature node instance + * @param ScenarioInterface $scenario Scenario or Outline node instance + * + * @return Boolean + */ + public function isScenarioMatch(FeatureNode $feature, ScenarioInterface $scenario) + { + return $this->isTagsMatchCondition(array_merge($feature->getTags(), $scenario->getTags())); + } + + /** + * Checks that node matches condition. + * + * @param string[] $tags + * + * @return Boolean + */ + protected function isTagsMatchCondition($tags) + { + $satisfies = true; + + foreach (explode('&&', $this->filterString) as $andTags) { + $satisfiesComma = false; + + foreach (explode(',', $andTags) as $tag) { + $tag = str_replace('@', '', trim($tag)); + + if ('~' === $tag[0]) { + $tag = mb_substr($tag, 1, mb_strlen($tag, 'utf8') - 1, 'utf8'); + $satisfiesComma = !in_array($tag, $tags) || $satisfiesComma; + } else { + $satisfiesComma = in_array($tag, $tags) || $satisfiesComma; + } + } + + $satisfies = (false !== $satisfiesComma && $satisfies && $satisfiesComma) || false; + } + + return $satisfies; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Gherkin.php b/vendor/behat/gherkin/src/Behat/Gherkin/Gherkin.php new file mode 100644 index 0000000..ed0fc8a --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Gherkin.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin; + +use Behat\Gherkin\Filter\FeatureFilterInterface; +use Behat\Gherkin\Filter\LineFilter; +use Behat\Gherkin\Filter\LineRangeFilter; +use Behat\Gherkin\Loader\FileLoaderInterface; +use Behat\Gherkin\Loader\LoaderInterface; + +/** + * Gherkin manager. + * + * @author Konstantin Kudryashov + */ +class Gherkin +{ + /** + * @var LoaderInterface[] + */ + protected $loaders = array(); + /** + * @var FeatureFilterInterface[] + */ + protected $filters = array(); + + /** + * Adds loader to manager. + * + * @param LoaderInterface $loader Feature loader + */ + public function addLoader(LoaderInterface $loader) + { + $this->loaders[] = $loader; + } + + /** + * Adds filter to manager. + * + * @param FeatureFilterInterface $filter Feature filter + */ + public function addFilter(FeatureFilterInterface $filter) + { + $this->filters[] = $filter; + } + + /** + * Sets filters to the parser. + * + * @param FeatureFilterInterface[] $filters + */ + public function setFilters(array $filters) + { + $this->filters = array(); + array_map(array($this, 'addFilter'), $filters); + } + + /** + * Sets base features path. + * + * @param string $path Loaders base path + */ + public function setBasePath($path) + { + foreach ($this->loaders as $loader) { + if ($loader instanceof FileLoaderInterface) { + $loader->setBasePath($path); + } + } + } + + /** + * Loads & filters resource with added loaders. + * + * @param mixed $resource Resource to load + * @param FeatureFilterInterface[] $filters Additional filters + * + * @return array + */ + public function load($resource, array $filters = array()) + { + $filters = array_merge($this->filters, $filters); + + $matches = array(); + if (preg_match('/^(.*)\:(\d+)-(\d+|\*)$/', $resource, $matches)) { + $resource = $matches[1]; + $filters[] = new LineRangeFilter($matches[2], $matches[3]); + } elseif (preg_match('/^(.*)\:(\d+)$/', $resource, $matches)) { + $resource = $matches[1]; + $filters[] = new LineFilter($matches[2]); + } + + $loader = $this->resolveLoader($resource); + + if (null === $loader) { + return array(); + } + + $features = array(); + foreach ($loader->load($resource) as $feature) { + foreach ($filters as $filter) { + $feature = $filter->filterFeature($feature); + + if (!$feature->hasScenarios() && !$filter->isFeatureMatch($feature)) { + continue 2; + } + } + + $features[] = $feature; + } + + return $features; + } + + /** + * Resolves loader by resource. + * + * @param mixed $resource Resource to load + * + * @return LoaderInterface + */ + public function resolveLoader($resource) + { + foreach ($this->loaders as $loader) { + if ($loader->supports($resource)) { + return $loader; + } + } + + return null; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/ArrayKeywords.php b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/ArrayKeywords.php new file mode 100644 index 0000000..35b9b82 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/ArrayKeywords.php @@ -0,0 +1,200 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Keywords; + +/** + * Array initializable keywords holder. + * + * $keywords = new Behat\Gherkin\Keywords\ArrayKeywords(array( + * 'en' => array( + * 'feature' => 'Feature', + * 'background' => 'Background', + * 'scenario' => 'Scenario', + * 'scenario_outline' => 'Scenario Outline|Scenario Template', + * 'examples' => 'Examples|Scenarios', + * 'given' => 'Given', + * 'when' => 'When', + * 'then' => 'Then', + * 'and' => 'And', + * 'but' => 'But' + * ), + * 'ru' => array( + * 'feature' => 'Функционал', + * 'background' => 'Предыстория', + * 'scenario' => 'Сценарий', + * 'scenario_outline' => 'Структура сценария', + * 'examples' => 'Значения', + * 'given' => 'Допустим', + * 'when' => 'Если', + * 'then' => 'То', + * 'and' => 'И', + * 'but' => 'Но' + * ) + * )); + * + * @author Konstantin Kudryashov + */ +class ArrayKeywords implements KeywordsInterface +{ + private $keywords = array(); + private $keywordString = array(); + private $language; + + /** + * Initializes holder with keywords. + * + * @param array $keywords Keywords array + */ + public function __construct(array $keywords) + { + $this->keywords = $keywords; + } + + /** + * Sets keywords holder language. + * + * @param string $language Language name + */ + public function setLanguage($language) + { + if (!isset($this->keywords[$language])) { + $this->language = 'en'; + } else { + $this->language = $language; + } + } + + /** + * Returns Feature keywords (splitted by "|"). + * + * @return string + */ + public function getFeatureKeywords() + { + return $this->keywords[$this->language]['feature']; + } + + /** + * Returns Background keywords (splitted by "|"). + * + * @return string + */ + public function getBackgroundKeywords() + { + return $this->keywords[$this->language]['background']; + } + + /** + * Returns Scenario keywords (splitted by "|"). + * + * @return string + */ + public function getScenarioKeywords() + { + return $this->keywords[$this->language]['scenario']; + } + + /** + * Returns Scenario Outline keywords (splitted by "|"). + * + * @return string + */ + public function getOutlineKeywords() + { + return $this->keywords[$this->language]['scenario_outline']; + } + + /** + * Returns Examples keywords (splitted by "|"). + * + * @return string + */ + public function getExamplesKeywords() + { + return $this->keywords[$this->language]['examples']; + } + + /** + * Returns Given keywords (splitted by "|"). + * + * @return string + */ + public function getGivenKeywords() + { + return $this->keywords[$this->language]['given']; + } + + /** + * Returns When keywords (splitted by "|"). + * + * @return string + */ + public function getWhenKeywords() + { + return $this->keywords[$this->language]['when']; + } + + /** + * Returns Then keywords (splitted by "|"). + * + * @return string + */ + public function getThenKeywords() + { + return $this->keywords[$this->language]['then']; + } + + /** + * Returns And keywords (splitted by "|"). + * + * @return string + */ + public function getAndKeywords() + { + return $this->keywords[$this->language]['and']; + } + + /** + * Returns But keywords (splitted by "|"). + * + * @return string + */ + public function getButKeywords() + { + return $this->keywords[$this->language]['but']; + } + + /** + * Returns all step keywords (Given, When, Then, And, But). + * + * @return string + */ + public function getStepKeywords() + { + if (!isset($this->keywordString[$this->language])) { + $keywords = array_merge( + explode('|', $this->getGivenKeywords()), + explode('|', $this->getWhenKeywords()), + explode('|', $this->getThenKeywords()), + explode('|', $this->getAndKeywords()), + explode('|', $this->getButKeywords()) + ); + + usort($keywords, function ($keyword1, $keyword2) { + return mb_strlen($keyword2, 'utf8') - mb_strlen($keyword1, 'utf8'); + }); + + $this->keywordString[$this->language] = implode('|', $keywords); + } + + return $this->keywordString[$this->language]; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/CachedArrayKeywords.php b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/CachedArrayKeywords.php new file mode 100644 index 0000000..871f196 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/CachedArrayKeywords.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Keywords; + +/** + * File initializable keywords holder. + * + * $keywords = new Behat\Gherkin\Keywords\CachedArrayKeywords($file); + * + * @author Konstantin Kudryashov + */ +class CachedArrayKeywords extends ArrayKeywords +{ + /** + * Initializes holder with file. + * + * @param string $file Cached array path + */ + public function __construct($file) + { + parent::__construct(include($file)); + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/CucumberKeywords.php b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/CucumberKeywords.php new file mode 100644 index 0000000..045918c --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/CucumberKeywords.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Keywords; + +use Symfony\Component\Yaml\Yaml; + +/** + * Cucumber-translations reader. + * + * $keywords = new Behat\Gherkin\Keywords\CucumberKeywords($i18nYmlPath); + * + * @author Konstantin Kudryashov + */ +class CucumberKeywords extends ArrayKeywords +{ + /** + * Initializes holder with yaml string OR file. + * + * @param string $yaml Yaml string + */ + public function __construct($yaml) + { + parent::__construct(Yaml::parse($yaml)); + } + + /** + * Returns Feature keywords (splitted by "|"). + * + * @return string + */ + public function getGivenKeywords() + { + return $this->prepareStepString(parent::getGivenKeywords()); + } + + /** + * Returns When keywords (splitted by "|"). + * + * @return string + */ + public function getWhenKeywords() + { + return $this->prepareStepString(parent::getWhenKeywords()); + } + + /** + * Returns Then keywords (splitted by "|"). + * + * @return string + */ + public function getThenKeywords() + { + return $this->prepareStepString(parent::getThenKeywords()); + } + + /** + * Returns And keywords (splitted by "|"). + * + * @return string + */ + public function getAndKeywords() + { + return $this->prepareStepString(parent::getAndKeywords()); + } + + /** + * Returns But keywords (splitted by "|"). + * + * @return string + */ + public function getButKeywords() + { + return $this->prepareStepString(parent::getButKeywords()); + } + + /** + * Trim *| from the begining of the list. + * + * @param string $keywordsString Keywords string + * + * @return string + */ + private function prepareStepString($keywordsString) + { + if (0 === mb_strpos($keywordsString, '*|', 0, 'UTF-8')) { + $keywordsString = mb_substr($keywordsString, 2, mb_strlen($keywordsString, 'utf8') - 2, 'utf8'); + } + + return $keywordsString; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/KeywordsDumper.php b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/KeywordsDumper.php new file mode 100644 index 0000000..98ac0a5 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/KeywordsDumper.php @@ -0,0 +1,348 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Keywords; + +/** + * Gherkin keywords dumper. + * + * @author Konstantin Kudryashov + */ +class KeywordsDumper +{ + private $keywords; + private $keywordsDumper; + + /** + * Initializes dumper. + * + * @param KeywordsInterface $keywords Keywords instance + */ + public function __construct(KeywordsInterface $keywords) + { + $this->keywords = $keywords; + $this->keywordsDumper = array($this, 'dumpKeywords'); + } + + /** + * Sets keywords mapper function. + * + * Callable should accept 2 arguments (array $keywords and Boolean $isShort) + * + * @param callable $mapper Mapper function + */ + public function setKeywordsDumperFunction($mapper) + { + $this->keywordsDumper = $mapper; + } + + /** + * Defaults keywords dumper. + * + * @param array $keywords Keywords list + * @param Boolean $isShort Is short version + * + * @return string + */ + public function dumpKeywords(array $keywords, $isShort) + { + if ($isShort) { + return 1 < count($keywords) ? '(' . implode('|', $keywords) . ')' : $keywords[0]; + } + + return $keywords[0]; + } + + /** + * Dumps keyworded feature into string. + * + * @param string $language Keywords language + * @param Boolean $short Dump short version + * + * @return string|array String for short version and array of features for extended + */ + public function dump($language, $short = true) + { + $this->keywords->setLanguage($language); + $languageComment = ''; + if ('en' !== $language) { + $languageComment = "# language: $language\n"; + } + + $keywords = explode('|', $this->keywords->getFeatureKeywords()); + + if ($short) { + $keywords = call_user_func($this->keywordsDumper, $keywords, $short); + + return trim($languageComment . $this->dumpFeature($keywords, $short)); + } + + $features = array(); + foreach ($keywords as $keyword) { + $keyword = call_user_func($this->keywordsDumper, array($keyword), $short); + $features[] = trim($languageComment . $this->dumpFeature($keyword, $short)); + } + + return $features; + } + + /** + * Dumps feature example. + * + * @param string $keyword Item keyword + * @param Boolean $short Dump short version? + * + * @return string + */ + protected function dumpFeature($keyword, $short = true) + { + $dump = <<keywords->getBackgroundKeywords()); + if ($short) { + $keywords = call_user_func($this->keywordsDumper, $keywords, $short); + $dump .= $this->dumpBackground($keywords, $short); + } else { + $keyword = call_user_func($this->keywordsDumper, array($keywords[0]), $short); + $dump .= $this->dumpBackground($keyword, $short); + } + + // Scenario + $keywords = explode('|', $this->keywords->getScenarioKeywords()); + if ($short) { + $keywords = call_user_func($this->keywordsDumper, $keywords, $short); + $dump .= $this->dumpScenario($keywords, $short); + } else { + foreach ($keywords as $keyword) { + $keyword = call_user_func($this->keywordsDumper, array($keyword), $short); + $dump .= $this->dumpScenario($keyword, $short); + } + } + + // Outline + $keywords = explode('|', $this->keywords->getOutlineKeywords()); + if ($short) { + $keywords = call_user_func($this->keywordsDumper, $keywords, $short); + $dump .= $this->dumpOutline($keywords, $short); + } else { + foreach ($keywords as $keyword) { + $keyword = call_user_func($this->keywordsDumper, array($keyword), $short); + $dump .= $this->dumpOutline($keyword, $short); + } + } + + return $dump; + } + + /** + * Dumps background example. + * + * @param string $keyword Item keyword + * @param Boolean $short Dump short version? + * + * @return string + */ + protected function dumpBackground($keyword, $short = true) + { + $dump = <<dumpStep( + $this->keywords->getGivenKeywords(), + 'there is agent A', + $short + ); + + // And + $dump .= $this->dumpStep( + $this->keywords->getAndKeywords(), + 'there is agent B', + $short + ); + + return $dump . "\n"; + } + + /** + * Dumps scenario example. + * + * @param string $keyword Item keyword + * @param Boolean $short Dump short version? + * + * @return string + */ + protected function dumpScenario($keyword, $short = true) + { + $dump = <<dumpStep( + $this->keywords->getGivenKeywords(), + 'there is agent J', + $short + ); + + // And + $dump .= $this->dumpStep( + $this->keywords->getAndKeywords(), + 'there is agent K', + $short + ); + + // When + $dump .= $this->dumpStep( + $this->keywords->getWhenKeywords(), + 'I erase agent K\'s memory', + $short + ); + + // Then + $dump .= $this->dumpStep( + $this->keywords->getThenKeywords(), + 'there should be agent J', + $short + ); + + // But + $dump .= $this->dumpStep( + $this->keywords->getButKeywords(), + 'there should not be agent K', + $short + ); + + return $dump . "\n"; + } + + /** + * Dumps outline example. + * + * @param string $keyword Item keyword + * @param Boolean $short Dump short version? + * + * @return string + */ + protected function dumpOutline($keyword, $short = true) + { + $dump = <<dumpStep( + $this->keywords->getGivenKeywords(), + 'there is agent ', + $short + ); + + // And + $dump .= $this->dumpStep( + $this->keywords->getAndKeywords(), + 'there is agent ', + $short + ); + + // When + $dump .= $this->dumpStep( + $this->keywords->getWhenKeywords(), + 'I erase agent \'s memory', + $short + ); + + // Then + $dump .= $this->dumpStep( + $this->keywords->getThenKeywords(), + 'there should be agent ', + $short + ); + + // But + $dump .= $this->dumpStep( + $this->keywords->getButKeywords(), + 'there should not be agent ', + $short + ); + + $keywords = explode('|', $this->keywords->getExamplesKeywords()); + if ($short) { + $keyword = call_user_func($this->keywordsDumper, $keywords, $short); + } else { + $keyword = call_user_func($this->keywordsDumper, array($keywords[0]), $short); + } + + $dump .= <<keywordsDumper, $keywords, $short); + $dump .= <<keywordsDumper, array($keyword), $short); + $dump .= << + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Keywords; + +/** + * Keywords holder interface. + * + * @author Konstantin Kudryashov + */ +interface KeywordsInterface +{ + /** + * Sets keywords holder language. + * + * @param string $language Language name + */ + public function setLanguage($language); + + /** + * Returns Feature keywords (splitted by "|"). + * + * @return string + */ + public function getFeatureKeywords(); + + /** + * Returns Background keywords (splitted by "|"). + * + * @return string + */ + public function getBackgroundKeywords(); + + /** + * Returns Scenario keywords (splitted by "|"). + * + * @return string + */ + public function getScenarioKeywords(); + + /** + * Returns Scenario Outline keywords (splitted by "|"). + * + * @return string + */ + public function getOutlineKeywords(); + + /** + * Returns Examples keywords (splitted by "|"). + * + * @return string + */ + public function getExamplesKeywords(); + + /** + * Returns Given keywords (splitted by "|"). + * + * @return string + */ + public function getGivenKeywords(); + + /** + * Returns When keywords (splitted by "|"). + * + * @return string + */ + public function getWhenKeywords(); + + /** + * Returns Then keywords (splitted by "|"). + * + * @return string + */ + public function getThenKeywords(); + + /** + * Returns And keywords (splitted by "|"). + * + * @return string + */ + public function getAndKeywords(); + + /** + * Returns But keywords (splitted by "|"). + * + * @return string + */ + public function getButKeywords(); + + /** + * Returns all step keywords (splitted by "|"). + * + * @return string + */ + public function getStepKeywords(); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Lexer.php b/vendor/behat/gherkin/src/Behat/Gherkin/Lexer.php new file mode 100644 index 0000000..dcbefcf --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Lexer.php @@ -0,0 +1,609 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin; + +use Behat\Gherkin\Exception\LexerException; +use Behat\Gherkin\Keywords\KeywordsInterface; + +/** + * Gherkin lexer. + * + * @author Konstantin Kudryashov + */ +class Lexer +{ + private $language; + private $lines; + private $linesCount; + private $line; + private $trimmedLine; + private $lineNumber; + private $eos; + private $keywords; + private $keywordsCache = array(); + private $stepKeywordTypesCache = array(); + private $deferredObjects = array(); + private $deferredObjectsCount = 0; + private $stashedToken; + private $inPyString = false; + private $pyStringSwallow = 0; + private $featureStarted = false; + private $allowMultilineArguments = false; + private $allowSteps = false; + + /** + * Initializes lexer. + * + * @param KeywordsInterface $keywords Keywords holder + */ + public function __construct(KeywordsInterface $keywords) + { + $this->keywords = $keywords; + } + + /** + * Sets lexer input. + * + * @param string $input Input string + * @param string $language Language name + * + * @throws Exception\LexerException + */ + public function analyse($input, $language = 'en') + { + // try to detect unsupported encoding + if ('UTF-8' !== mb_detect_encoding($input, 'UTF-8', true)) { + throw new LexerException('Feature file is not in UTF8 encoding'); + } + + $input = strtr($input, array("\r\n" => "\n", "\r" => "\n")); + + $this->lines = explode("\n", $input); + $this->linesCount = count($this->lines); + $this->line = $this->lines[0]; + $this->lineNumber = 1; + $this->trimmedLine = null; + $this->eos = false; + + $this->deferredObjects = array(); + $this->deferredObjectsCount = 0; + $this->stashedToken = null; + $this->inPyString = false; + $this->pyStringSwallow = 0; + + $this->featureStarted = false; + $this->allowMultilineArguments = false; + $this->allowSteps = false; + + $this->keywords->setLanguage($this->language = $language); + $this->keywordsCache = array(); + $this->stepKeywordTypesCache = array(); + } + + /** + * Returns current lexer language. + * + * @return string + */ + public function getLanguage() + { + return $this->language; + } + + /** + * Returns next token or previously stashed one. + * + * @return array + */ + public function getAdvancedToken() + { + return $this->getStashedToken() ?: $this->getNextToken(); + } + + /** + * Defers token. + * + * @param array $token Token to defer + */ + public function deferToken(array $token) + { + $token['deferred'] = true; + $this->deferredObjects[] = $token; + ++$this->deferredObjectsCount; + } + + /** + * Predicts for number of tokens. + * + * @return array + */ + public function predictToken() + { + if (null === $this->stashedToken) { + $this->stashedToken = $this->getNextToken(); + } + + return $this->stashedToken; + } + + /** + * Constructs token with specified parameters. + * + * @param string $type Token type + * @param string $value Token value + * + * @return array + */ + public function takeToken($type, $value = null) + { + return array( + 'type' => $type, + 'line' => $this->lineNumber, + 'value' => $value ?: null, + 'deferred' => false + ); + } + + /** + * Consumes line from input & increments line counter. + */ + protected function consumeLine() + { + ++$this->lineNumber; + + if (($this->lineNumber - 1) === $this->linesCount) { + $this->eos = true; + + return; + } + + $this->line = $this->lines[$this->lineNumber - 1]; + $this->trimmedLine = null; + } + + /** + * Returns trimmed version of line. + * + * @return string + */ + protected function getTrimmedLine() + { + return null !== $this->trimmedLine ? $this->trimmedLine : $this->trimmedLine = trim($this->line); + } + + /** + * Returns stashed token or null if hasn't. + * + * @return array|null + */ + protected function getStashedToken() + { + $stashedToken = $this->stashedToken; + $this->stashedToken = null; + + return $stashedToken; + } + + /** + * Returns deferred token or null if hasn't. + * + * @return array|null + */ + protected function getDeferredToken() + { + if (!$this->deferredObjectsCount) { + return null; + } + + --$this->deferredObjectsCount; + + return array_shift($this->deferredObjects); + } + + /** + * Returns next token from input. + * + * @return array + */ + protected function getNextToken() + { + return $this->getDeferredToken() + ?: $this->scanEOS() + ?: $this->scanLanguage() + ?: $this->scanComment() + ?: $this->scanPyStringOp() + ?: $this->scanPyStringContent() + ?: $this->scanStep() + ?: $this->scanScenario() + ?: $this->scanBackground() + ?: $this->scanOutline() + ?: $this->scanExamples() + ?: $this->scanFeature() + ?: $this->scanTags() + ?: $this->scanTableRow() + ?: $this->scanNewline() + ?: $this->scanText(); + } + + /** + * Scans for token with specified regex. + * + * @param string $regex Regular expression + * @param string $type Expected token type + * + * @return null|array + */ + protected function scanInput($regex, $type) + { + if (!preg_match($regex, $this->line, $matches)) { + return null; + } + + $token = $this->takeToken($type, $matches[1]); + $this->consumeLine(); + + return $token; + } + + /** + * Scans for token with specified keywords. + * + * @param string $keywords Keywords (splitted with |) + * @param string $type Expected token type + * + * @return null|array + */ + protected function scanInputForKeywords($keywords, $type) + { + if (!preg_match('/^(\s*)(' . $keywords . '):\s*(.*)/u', $this->line, $matches)) { + return null; + } + + $token = $this->takeToken($type, $matches[3]); + $token['keyword'] = $matches[2]; + $token['indent'] = mb_strlen($matches[1], 'utf8'); + + $this->consumeLine(); + + // turn off language searching + if ('Feature' === $type) { + $this->featureStarted = true; + } + + // turn off PyString and Table searching + if ('Feature' === $type || 'Scenario' === $type || 'Outline' === $type) { + $this->allowMultilineArguments = false; + } elseif ('Examples' === $type) { + $this->allowMultilineArguments = true; + } + + // turn on steps searching + if ('Scenario' === $type || 'Background' === $type || 'Outline' === $type) { + $this->allowSteps = true; + } + + return $token; + } + + /** + * Scans EOS from input & returns it if found. + * + * @return null|array + */ + protected function scanEOS() + { + if (!$this->eos) { + return null; + } + + return $this->takeToken('EOS'); + } + + /** + * Returns keywords for provided type. + * + * @param string $type Keyword type + * + * @return string + */ + protected function getKeywords($type) + { + if (!isset($this->keywordsCache[$type])) { + $getter = 'get' . $type . 'Keywords'; + $keywords = $this->keywords->$getter(); + + if ('Step' === $type) { + $padded = array(); + foreach (explode('|', $keywords) as $keyword) { + $padded[] = false !== mb_strpos($keyword, '<', 0, 'utf8') + ? mb_substr($keyword, 0, -1, 'utf8') . '\s*' + : $keyword . '\s+'; + } + + $keywords = implode('|', $padded); + } + + $this->keywordsCache[$type] = $keywords; + } + + return $this->keywordsCache[$type]; + } + + /** + * Scans Feature from input & returns it if found. + * + * @return null|array + */ + protected function scanFeature() + { + return $this->scanInputForKeywords($this->getKeywords('Feature'), 'Feature'); + } + + /** + * Scans Background from input & returns it if found. + * + * @return null|array + */ + protected function scanBackground() + { + return $this->scanInputForKeywords($this->getKeywords('Background'), 'Background'); + } + + /** + * Scans Scenario from input & returns it if found. + * + * @return null|array + */ + protected function scanScenario() + { + return $this->scanInputForKeywords($this->getKeywords('Scenario'), 'Scenario'); + } + + /** + * Scans Scenario Outline from input & returns it if found. + * + * @return null|array + */ + protected function scanOutline() + { + return $this->scanInputForKeywords($this->getKeywords('Outline'), 'Outline'); + } + + /** + * Scans Scenario Outline Examples from input & returns it if found. + * + * @return null|array + */ + protected function scanExamples() + { + return $this->scanInputForKeywords($this->getKeywords('Examples'), 'Examples'); + } + + /** + * Scans Step from input & returns it if found. + * + * @return null|array + */ + protected function scanStep() + { + if (!$this->allowSteps) { + return null; + } + + $keywords = $this->getKeywords('Step'); + if (!preg_match('/^\s*(' . $keywords . ')([^\s].+)/u', $this->line, $matches)) { + return null; + } + + $keyword = trim($matches[1]); + $token = $this->takeToken('Step', $keyword); + $token['keyword_type'] = $this->getStepKeywordType($keyword); + $token['text'] = $matches[2]; + + $this->consumeLine(); + $this->allowMultilineArguments = true; + + return $token; + } + + /** + * Scans PyString from input & returns it if found. + * + * @return null|array + */ + protected function scanPyStringOp() + { + if (!$this->allowMultilineArguments) { + return null; + } + + if (false === ($pos = mb_strpos($this->line, '"""', 0, 'utf8'))) { + return null; + } + + $this->inPyString = !$this->inPyString; + $token = $this->takeToken('PyStringOp'); + $this->pyStringSwallow = $pos; + + $this->consumeLine(); + + return $token; + } + + /** + * Scans PyString content. + * + * @return null|array + */ + protected function scanPyStringContent() + { + if (!$this->inPyString) { + return null; + } + + $token = $this->scanText(); + // swallow trailing spaces + $token['value'] = preg_replace('/^\s{0,' . $this->pyStringSwallow . '}/u', '', $token['value']); + + return $token; + } + + /** + * Scans Table Row from input & returns it if found. + * + * @return null|array + */ + protected function scanTableRow() + { + if (!$this->allowMultilineArguments) { + return null; + } + + $line = $this->getTrimmedLine(); + if (!isset($line[0]) || '|' !== $line[0]) { + return null; + } + + $token = $this->takeToken('TableRow'); + $line = mb_substr($line, 1, mb_strlen($line, 'utf8') - 2, 'utf8'); + $columns = array_map(function ($column) { + return trim(str_replace('\\|', '|', $column)); + }, preg_split('/(?consumeLine(); + + return $token; + } + + /** + * Scans Tags from input & returns it if found. + * + * @return null|array + */ + protected function scanTags() + { + $line = $this->getTrimmedLine(); + if (!isset($line[0]) || '@' !== $line[0]) { + return null; + } + + $token = $this->takeToken('Tag'); + $tags = explode('@', mb_substr($line, 1, mb_strlen($line, 'utf8') - 1, 'utf8')); + $tags = array_map('trim', $tags); + $token['tags'] = $tags; + + $this->consumeLine(); + + return $token; + } + + /** + * Scans Language specifier from input & returns it if found. + * + * @return null|array + */ + protected function scanLanguage() + { + if ($this->featureStarted) { + return null; + } + + if ($this->inPyString) { + return null; + } + + if (0 !== mb_strpos(ltrim($this->line), '#', 0, 'utf8')) { + return null; + } + + return $this->scanInput('/^\s*\#\s*language:\s*([\w_\-]+)\s*$/', 'Language'); + } + + /** + * Scans Comment from input & returns it if found. + * + * @return null|array + */ + protected function scanComment() + { + if ($this->inPyString) { + return null; + } + + $line = $this->getTrimmedLine(); + if (0 !== mb_strpos($line, '#', 0, 'utf8')) { + return null; + } + + $token = $this->takeToken('Comment', $line); + $this->consumeLine(); + + return $token; + } + + /** + * Scans Newline from input & returns it if found. + * + * @return null|array + */ + protected function scanNewline() + { + if ('' !== $this->getTrimmedLine()) { + return null; + } + + $token = $this->takeToken('Newline', mb_strlen($this->line, 'utf8')); + $this->consumeLine(); + + return $token; + } + + /** + * Scans text from input & returns it if found. + * + * @return null|array + */ + protected function scanText() + { + $token = $this->takeToken('Text', $this->line); + $this->consumeLine(); + + return $token; + } + + /** + * Returns step type keyword (Given, When, Then, etc.). + * + * @param string $native Step keyword in provided language + * @return string + */ + private function getStepKeywordType($native) + { + if (empty($this->stepKeywordTypesCache)) { + $this->stepKeywordTypesCache = array( + 'Given' => explode('|', $this->keywords->getGivenKeywords()), + 'When' => explode('|', $this->keywords->getWhenKeywords()), + 'Then' => explode('|', $this->keywords->getThenKeywords()), + 'And' => explode('|', $this->keywords->getAndKeywords()), + 'But' => explode('|', $this->keywords->getButKeywords()) + ); + } + + foreach ($this->stepKeywordTypesCache as $type => $keywords) { + if (in_array($native, $keywords) || in_array($native . '<', $keywords)) { + return $type; + } + } + + return 'Given'; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Loader/AbstractFileLoader.php b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/AbstractFileLoader.php new file mode 100644 index 0000000..20932c1 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/AbstractFileLoader.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Loader; + +/** + * Abstract filesystem loader. + * + * @author Konstantin Kudryashov + */ +abstract class AbstractFileLoader implements FileLoaderInterface +{ + protected $basePath; + + /** + * Sets base features path. + * + * @param string $path Base loader path + */ + public function setBasePath($path) + { + $this->basePath = realpath($path); + } + + /** + * Finds relative path for provided absolute (relative to base features path). + * + * @param string $path Absolute path + * + * @return string + */ + protected function findRelativePath($path) + { + if (null !== $this->basePath) { + return strtr($path, array($this->basePath . DIRECTORY_SEPARATOR => '')); + } + + return $path; + } + + /** + * Finds absolute path for provided relative (relative to base features path). + * + * @param string $path Relative path + * + * @return string + */ + protected function findAbsolutePath($path) + { + if (is_file($path) || is_dir($path)) { + return realpath($path); + } + + if (null === $this->basePath) { + return false; + } + + if (is_file($this->basePath . DIRECTORY_SEPARATOR . $path) + || is_dir($this->basePath . DIRECTORY_SEPARATOR . $path)) { + return realpath($this->basePath . DIRECTORY_SEPARATOR . $path); + } + + return false; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Loader/ArrayLoader.php b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/ArrayLoader.php new file mode 100644 index 0000000..3492d6e --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/ArrayLoader.php @@ -0,0 +1,269 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Loader; + +use Behat\Gherkin\Node\BackgroundNode; +use Behat\Gherkin\Node\ExampleTableNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Gherkin\Node\PyStringNode; +use Behat\Gherkin\Node\ScenarioNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Gherkin\Node\TableNode; + +/** + * From-array loader. + * + * @author Konstantin Kudryashov + */ +class ArrayLoader implements LoaderInterface +{ + /** + * Checks if current loader supports provided resource. + * + * @param mixed $resource Resource to load + * + * @return Boolean + */ + public function supports($resource) + { + return is_array($resource) && (isset($resource['features']) || isset($resource['feature'])); + } + + /** + * Loads features from provided resource. + * + * @param mixed $resource Resource to load + * + * @return FeatureNode[] + */ + public function load($resource) + { + $features = array(); + + if (isset($resource['features'])) { + foreach ($resource['features'] as $iterator => $hash) { + $feature = $this->loadFeatureHash($hash, $iterator); + $features[] = $feature; + } + } elseif (isset($resource['feature'])) { + $feature = $this->loadFeatureHash($resource['feature']); + $features[] = $feature; + } + + return $features; + } + + /** + * Loads feature from provided feature hash. + * + * @param array $hash Feature hash + * @param integer $line + * + * @return FeatureNode + */ + protected function loadFeatureHash(array $hash, $line = 0) + { + $hash = array_merge( + array( + 'title' => null, + 'description' => null, + 'tags' => array(), + 'keyword' => 'Feature', + 'language' => 'en', + 'line' => $line, + 'scenarios' => array(), + ), + $hash + ); + $background = isset($hash['background']) ? $this->loadBackgroundHash($hash['background']) : null; + + $scenarios = array(); + foreach ((array) $hash['scenarios'] as $scenarioIterator => $scenarioHash) { + if (isset($scenarioHash['type']) && 'outline' === $scenarioHash['type']) { + $scenarios[] = $this->loadOutlineHash($scenarioHash, $scenarioIterator); + } else { + $scenarios[] = $this->loadScenarioHash($scenarioHash, $scenarioIterator); + } + } + + return new FeatureNode($hash['title'], $hash['description'], $hash['tags'], $background, $scenarios, $hash['keyword'], $hash['language'], null, $hash['line']); + } + + /** + * Loads background from provided hash. + * + * @param array $hash Background hash + * + * @return BackgroundNode + */ + protected function loadBackgroundHash(array $hash) + { + $hash = array_merge( + array( + 'title' => null, + 'keyword' => 'Background', + 'line' => 0, + 'steps' => array(), + ), + $hash + ); + + $steps = $this->loadStepsHash($hash['steps']); + + return new BackgroundNode($hash['title'], $steps, $hash['keyword'], $hash['line']); + } + + /** + * Loads scenario from provided scenario hash. + * + * @param array $hash Scenario hash + * @param integer $line Scenario definition line + * + * @return ScenarioNode + */ + protected function loadScenarioHash(array $hash, $line = 0) + { + $hash = array_merge( + array( + 'title' => null, + 'tags' => array(), + 'keyword' => 'Scenario', + 'line' => $line, + 'steps' => array(), + ), + $hash + ); + + $steps = $this->loadStepsHash($hash['steps']); + + return new ScenarioNode($hash['title'], $hash['tags'], $steps, $hash['keyword'], $hash['line']); + } + + /** + * Loads outline from provided outline hash. + * + * @param array $hash Outline hash + * @param integer $line Outline definition line + * + * @return OutlineNode + */ + protected function loadOutlineHash(array $hash, $line = 0) + { + $hash = array_merge( + array( + 'title' => null, + 'tags' => array(), + 'keyword' => 'Scenario Outline', + 'line' => $line, + 'steps' => array(), + 'examples' => array(), + ), + $hash + ); + + $steps = $this->loadStepsHash($hash['steps']); + + if (isset($hash['examples']['keyword'])) { + $examplesKeyword = $hash['examples']['keyword']; + unset($hash['examples']['keyword']); + } else { + $examplesKeyword = 'Examples'; + } + + $examples = new ExampleTableNode($hash['examples'], $examplesKeyword); + + return new OutlineNode($hash['title'], $hash['tags'], $steps, $examples, $hash['keyword'], $hash['line']); + } + + /** + * Loads steps from provided hash. + * + * @param array $hash + * + * @return StepNode[] + */ + private function loadStepsHash(array $hash) + { + $steps = array(); + foreach ($hash as $stepIterator => $stepHash) { + $steps[] = $this->loadStepHash($stepHash, $stepIterator); + } + + return $steps; + } + + /** + * Loads step from provided hash. + * + * @param array $hash Step hash + * @param integer $line Step definition line + * + * @return StepNode + */ + protected function loadStepHash(array $hash, $line = 0) + { + $hash = array_merge( + array( + 'keyword_type' => 'Given', + 'type' => 'Given', + 'text' => null, + 'keyword' => 'Scenario', + 'line' => $line, + 'arguments' => array(), + ), + $hash + ); + + $arguments = array(); + foreach ($hash['arguments'] as $argumentHash) { + if ('table' === $argumentHash['type']) { + $arguments[] = $this->loadTableHash($argumentHash['rows']); + } elseif ('pystring' === $argumentHash['type']) { + $arguments[] = $this->loadPyStringHash($argumentHash, $hash['line'] + 1); + } + } + + return new StepNode($hash['type'], $hash['text'], $arguments, $hash['line'], $hash['keyword_type']); + } + + /** + * Loads table from provided hash. + * + * @param array $hash Table hash + * + * @return TableNode + */ + protected function loadTableHash(array $hash) + { + return new TableNode($hash); + } + + /** + * Loads PyString from provided hash. + * + * @param array $hash PyString hash + * @param integer $line + * + * @return PyStringNode + */ + protected function loadPyStringHash(array $hash, $line = 0) + { + $line = isset($hash['line']) ? $hash['line'] : $line; + + $strings = array(); + foreach (explode("\n", $hash['text']) as $string) { + $strings[] = $string; + } + + return new PyStringNode($strings, $line); + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Loader/DirectoryLoader.php b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/DirectoryLoader.php new file mode 100644 index 0000000..dcde0e6 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/DirectoryLoader.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Loader; + +use Behat\Gherkin\Gherkin; +use Behat\Gherkin\Node\FeatureNode; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; + +/** + * Directory contents loader. + * + * @author Konstantin Kudryashov + */ +class DirectoryLoader extends AbstractFileLoader +{ + protected $gherkin; + + /** + * Initializes loader. + * + * @param Gherkin $gherkin Gherkin manager + */ + public function __construct(Gherkin $gherkin) + { + $this->gherkin = $gherkin; + } + + /** + * Checks if current loader supports provided resource. + * + * @param mixed $path Resource to load + * + * @return Boolean + */ + public function supports($path) + { + return is_string($path) + && is_dir($this->findAbsolutePath($path)); + } + + /** + * Loads features from provided resource. + * + * @param string $path Resource to load + * + * @return FeatureNode[] + */ + public function load($path) + { + $path = $this->findAbsolutePath($path); + + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS) + ); + $paths = array_map('strval', iterator_to_array($iterator)); + uasort($paths, 'strnatcasecmp'); + + $features = array(); + + foreach ($paths as $path) { + $path = (string) $path; + $loader = $this->gherkin->resolveLoader($path); + + if (null !== $loader) { + $features = array_merge($features, $loader->load($path)); + } + } + + return $features; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Loader/FileLoaderInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/FileLoaderInterface.php new file mode 100644 index 0000000..f18f19a --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/FileLoaderInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Loader; + +/** + * File Loader interface. + * + * @author Konstantin Kudryashov + */ +interface FileLoaderInterface extends LoaderInterface +{ + /** + * Sets base features path. + * + * @param string $path Base loader path + */ + public function setBasePath($path); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Loader/GherkinFileLoader.php b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/GherkinFileLoader.php new file mode 100644 index 0000000..ae8bf99 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/GherkinFileLoader.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Loader; + +use Behat\Gherkin\Cache\CacheInterface; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Parser; + +/** + * Gherkin *.feature files loader. + * + * @author Konstantin Kudryashov + */ +class GherkinFileLoader extends AbstractFileLoader +{ + protected $parser; + protected $cache; + + /** + * Initializes loader. + * + * @param Parser $parser Parser + * @param CacheInterface $cache Cache layer + */ + public function __construct(Parser $parser, CacheInterface $cache = null) + { + $this->parser = $parser; + $this->cache = $cache; + } + + /** + * Sets cache layer. + * + * @param CacheInterface $cache Cache layer + */ + public function setCache(CacheInterface $cache) + { + $this->cache = $cache; + } + + /** + * Checks if current loader supports provided resource. + * + * @param mixed $path Resource to load + * + * @return Boolean + */ + public function supports($path) + { + return is_string($path) + && is_file($absolute = $this->findAbsolutePath($path)) + && 'feature' === pathinfo($absolute, PATHINFO_EXTENSION); + } + + /** + * Loads features from provided resource. + * + * @param string $path Resource to load + * + * @return FeatureNode[] + */ + public function load($path) + { + $path = $this->findAbsolutePath($path); + + if ($this->cache) { + if ($this->cache->isFresh($path, filemtime($path))) { + $feature = $this->cache->read($path); + } elseif (null !== $feature = $this->parseFeature($path)) { + $this->cache->write($path, $feature); + } + } else { + $feature = $this->parseFeature($path); + } + + return null !== $feature ? array($feature) : array(); + } + + /** + * Parses feature at provided absolute path. + * + * @param string $path Feature path + * + * @return FeatureNode + */ + protected function parseFeature($path) + { + $filename = $this->findRelativePath($path); + $content = file_get_contents($path); + $feature = $this->parser->parse($content, $filename); + + return $feature; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Loader/LoaderInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/LoaderInterface.php new file mode 100644 index 0000000..861332c --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/LoaderInterface.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Loader; + +use Behat\Gherkin\Node\FeatureNode; + +/** + * Loader interface. + * + * @author Konstantin Kudryashov + */ +interface LoaderInterface +{ + /** + * Checks if current loader supports provided resource. + * + * @param mixed $resource Resource to load + * + * @return Boolean + */ + public function supports($resource); + + /** + * Loads features from provided resource. + * + * @param mixed $resource Resource to load + * + * @return FeatureNode[] + */ + public function load($resource); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Loader/YamlFileLoader.php b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/YamlFileLoader.php new file mode 100644 index 0000000..0c268fd --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Loader/YamlFileLoader.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Loader; + +use Behat\Gherkin\Node\FeatureNode; +use Symfony\Component\Yaml\Yaml; + +/** + * Yaml files loader. + * + * @author Konstantin Kudryashov + */ +class YamlFileLoader extends AbstractFileLoader +{ + private $loader; + + public function __construct() + { + $this->loader = new ArrayLoader(); + } + + /** + * Checks if current loader supports provided resource. + * + * @param mixed $path Resource to load + * + * @return Boolean + */ + public function supports($path) + { + return is_string($path) + && is_file($absolute = $this->findAbsolutePath($path)) + && 'yml' === pathinfo($absolute, PATHINFO_EXTENSION); + } + + /** + * Loads features from provided resource. + * + * @param string $path Resource to load + * + * @return FeatureNode[] + */ + public function load($path) + { + $path = $this->findAbsolutePath($path); + $hash = Yaml::parse(file_get_contents($path)); + + $features = $this->loader->load($hash); + $filename = $this->findRelativePath($path); + + return array_map(function (FeatureNode $feature) use ($filename) { + return new FeatureNode( + $feature->getTitle(), + $feature->getDescription(), + $feature->getTags(), + $feature->getBackground(), + $feature->getScenarios(), + $feature->getKeyword(), + $feature->getLanguage(), + $filename, + $feature->getLine() + ); + }, $features); + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/ArgumentInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ArgumentInterface.php new file mode 100644 index 0000000..4457f18 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ArgumentInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Gherkin arguments interface. + * + * @author Konstantin Kudryashov + */ +interface ArgumentInterface extends NodeInterface +{ +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/BackgroundNode.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/BackgroundNode.php new file mode 100644 index 0000000..fb1edb4 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/BackgroundNode.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Represents Gherkin Background. + * + * @author Konstantin Kudryashov + */ +class BackgroundNode implements ScenarioLikeInterface +{ + /** + * @var string + */ + private $title; + /** + * @var StepNode[] + */ + private $steps = array(); + /** + * @var string + */ + private $keyword; + /** + * @var integer + */ + private $line; + + /** + * Initializes background. + * + * @param null|string $title + * @param StepNode[] $steps + * @param string $keyword + * @param integer $line + */ + public function __construct($title, array $steps, $keyword, $line) + { + $this->title = $title; + $this->steps = $steps; + $this->keyword = $keyword; + $this->line = $line; + } + + /** + * Returns node type string + * + * @return string + */ + public function getNodeType() + { + return 'Background'; + } + + /** + * Returns background title. + * + * @return null|string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Checks if background has steps. + * + * @return Boolean + */ + public function hasSteps() + { + return 0 < count($this->steps); + } + + /** + * Returns background steps. + * + * @return StepNode[] + */ + public function getSteps() + { + return $this->steps; + } + + /** + * Returns background keyword. + * + * @return string + */ + public function getKeyword() + { + return $this->keyword; + } + + /** + * Returns background declaration line number. + * + * @return integer + */ + public function getLine() + { + return $this->line; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/ExampleNode.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ExampleNode.php new file mode 100644 index 0000000..b4beaba --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ExampleNode.php @@ -0,0 +1,258 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Represents Gherkin Outline Example. + * + * @author Konstantin Kudryashov + */ +class ExampleNode implements ScenarioInterface +{ + /** + * @var string + */ + private $title; + /** + * @var string[] + */ + private $tags; + /** + * @var StepNode[] + */ + private $outlineSteps; + /** + * @var string[] + */ + private $tokens; + /** + * @var integer + */ + private $line; + /** + * @var null|StepNode[] + */ + private $steps; + + /** + * Initializes outline. + * + * @param string $title + * @param string[] $tags + * @param StepNode[] $outlineSteps + * @param string[] $tokens + * @param integer $line + */ + public function __construct($title, array $tags, $outlineSteps, array $tokens, $line) + { + $this->title = $title; + $this->tags = $tags; + $this->outlineSteps = $outlineSteps; + $this->tokens = $tokens; + $this->line = $line; + } + + /** + * Returns node type string + * + * @return string + */ + public function getNodeType() + { + return 'Example'; + } + + /** + * Returns node keyword. + * + * @return string + */ + public function getKeyword() + { + return $this->getNodeType(); + } + + /** + * Returns example title. + * + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Checks if outline is tagged with tag. + * + * @param string $tag + * + * @return Boolean + */ + public function hasTag($tag) + { + return in_array($tag, $this->getTags()); + } + + /** + * Checks if outline has tags (both inherited from feature and own). + * + * @return Boolean + */ + public function hasTags() + { + return 0 < count($this->getTags()); + } + + /** + * Returns outline tags (including inherited from feature). + * + * @return string[] + */ + public function getTags() + { + return $this->tags; + } + + /** + * Checks if outline has steps. + * + * @return Boolean + */ + public function hasSteps() + { + return 0 < count($this->outlineSteps); + } + + /** + * Returns outline steps. + * + * @return StepNode[] + */ + public function getSteps() + { + return $this->steps = $this->steps ? : $this->createExampleSteps(); + } + + /** + * Returns example tokens. + * + * @return string[] + */ + public function getTokens() + { + return $this->tokens; + } + + /** + * Returns outline declaration line number. + * + * @return integer + */ + public function getLine() + { + return $this->line; + } + + /** + * Creates steps for this example from abstract outline steps. + * + * @return StepNode[] + */ + protected function createExampleSteps() + { + $steps = array(); + foreach ($this->outlineSteps as $outlineStep) { + $keyword = $outlineStep->getKeyword(); + $keywordType = $outlineStep->getKeywordType(); + $text = $this->replaceTextTokens($outlineStep->getText()); + $args = $this->replaceArgumentsTokens($outlineStep->getArguments()); + $line = $outlineStep->getLine(); + + $steps[] = new StepNode($keyword, $text, $args, $line, $keywordType); + } + + return $steps; + } + + /** + * Replaces tokens in arguments with row values. + * + * @param ArgumentInterface[] $arguments + * + * @return ArgumentInterface[] + */ + protected function replaceArgumentsTokens(array $arguments) + { + foreach ($arguments as $num => $argument) { + if ($argument instanceof TableNode) { + $arguments[$num] = $this->replaceTableArgumentTokens($argument); + } + if ($argument instanceof PyStringNode) { + $arguments[$num] = $this->replacePyStringArgumentTokens($argument); + } + } + + return $arguments; + } + + /** + * Replaces tokens in table with row values. + * + * @param TableNode $argument + * + * @return TableNode + */ + protected function replaceTableArgumentTokens(TableNode $argument) + { + $table = $argument->getTable(); + foreach ($table as $line => $row) { + foreach (array_keys($row) as $col) { + $table[$line][$col] = $this->replaceTextTokens($table[$line][$col]); + } + } + + return new TableNode($table); + } + + /** + * Replaces tokens in PyString with row values. + * + * @param PyStringNode $argument + * + * @return PyStringNode + */ + protected function replacePyStringArgumentTokens(PyStringNode $argument) + { + $strings = $argument->getStrings(); + foreach ($strings as $line => $string) { + $strings[$line] = $this->replaceTextTokens($strings[$line]); + } + + return new PyStringNode($strings, $argument->getLine()); + } + + /** + * Replaces tokens in text with row values. + * + * @param string $text + * + * @return string + */ + protected function replaceTextTokens($text) + { + foreach ($this->tokens as $key => $val) { + $text = str_replace('<' . $key . '>', $val, $text); + } + + return $text; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/ExampleTableNode.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ExampleTableNode.php new file mode 100644 index 0000000..805e659 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ExampleTableNode.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Represents Gherkin Outline Example Table. + * + * @author Konstantin Kudryashov + */ +class ExampleTableNode extends TableNode +{ + /** + * @var string + */ + private $keyword; + + /** + * Initializes example table. + * + * @param array $table Table in form of [$rowLineNumber => [$val1, $val2, $val3]] + * @param string $keyword + */ + public function __construct(array $table, $keyword) + { + $this->keyword = $keyword; + + parent::__construct($table); + } + + /** + * Returns node type string + * + * @return string + */ + public function getNodeType() + { + return 'ExampleTable'; + } + + /** + * Returns example table keyword. + * + * @return string + */ + public function getKeyword() + { + return $this->keyword; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/FeatureNode.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/FeatureNode.php new file mode 100644 index 0000000..6413659 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/FeatureNode.php @@ -0,0 +1,243 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Represents Gherkin Feature. + * + * @author Konstantin Kudryashov + */ +class FeatureNode implements KeywordNodeInterface, TaggedNodeInterface +{ + /** + * @var null|string + */ + private $title; + /** + * @var null|string + */ + private $description; + /** + * @var string[] + */ + private $tags = array(); + /** + * @var null|BackgroundNode + */ + private $background; + /** + * @var ScenarioInterface[] + */ + private $scenarios = array(); + /** + * @var string + */ + private $keyword; + /** + * @var string + */ + private $language; + /** + * @var null|string + */ + private $file; + /** + * @var integer + */ + private $line; + + /** + * Initializes feature. + * + * @param null|string $title + * @param null|string $description + * @param string[] $tags + * @param null|BackgroundNode $background + * @param ScenarioInterface[] $scenarios + * @param string $keyword + * @param string $language + * @param null|string $file + * @param integer $line + */ + public function __construct( + $title, + $description, + array $tags, + BackgroundNode $background = null, + array $scenarios, + $keyword, + $language, + $file, + $line + ) { + $this->title = $title; + $this->description = $description; + $this->tags = $tags; + $this->background = $background; + $this->scenarios = $scenarios; + $this->keyword = $keyword; + $this->language = $language; + $this->file = $file; + $this->line = $line; + } + + /** + * Returns node type string + * + * @return string + */ + public function getNodeType() + { + return 'Feature'; + } + + /** + * Returns feature title. + * + * @return null|string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Checks if feature has a description. + * + * @return Boolean + */ + public function hasDescription() + { + return !empty($this->description); + } + + /** + * Returns feature description. + * + * @return null|string + */ + public function getDescription() + { + return $this->description; + } + + /** + * Checks if feature is tagged with tag. + * + * @param string $tag + * + * @return Boolean + */ + public function hasTag($tag) + { + return in_array($tag, $this->tags); + } + + /** + * Checks if feature has tags. + * + * @return Boolean + */ + public function hasTags() + { + return 0 < count($this->tags); + } + + /** + * Returns feature tags. + * + * @return string[] + */ + public function getTags() + { + return $this->tags; + } + + /** + * Checks if feature has background. + * + * @return Boolean + */ + public function hasBackground() + { + return null !== $this->background; + } + + /** + * Returns feature background. + * + * @return null|BackgroundNode + */ + public function getBackground() + { + return $this->background; + } + + /** + * Checks if feature has scenarios. + * + * @return Boolean + */ + public function hasScenarios() + { + return 0 < count($this->scenarios); + } + + /** + * Returns feature scenarios. + * + * @return ScenarioInterface[] + */ + public function getScenarios() + { + return $this->scenarios; + } + + /** + * Returns feature keyword. + * + * @return string + */ + public function getKeyword() + { + return $this->keyword; + } + + /** + * Returns feature language. + * + * @return string + */ + public function getLanguage() + { + return $this->language; + } + + /** + * Returns feature file. + * + * @return null|string + */ + public function getFile() + { + return $this->file; + } + + /** + * Returns feature declaration line number. + * + * @return integer + */ + public function getLine() + { + return $this->line; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/KeywordNodeInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/KeywordNodeInterface.php new file mode 100644 index 0000000..e6e412f --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/KeywordNodeInterface.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Gherkin keyword node interface. + * + * @author Konstantin Kudryashov + */ +interface KeywordNodeInterface extends NodeInterface +{ + /** + * Returns node keyword. + * + * @return string + */ + public function getKeyword(); + + /** + * Returns node title. + * + * @return null|string + */ + public function getTitle(); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/NodeInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/NodeInterface.php new file mode 100644 index 0000000..eabe61a --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/NodeInterface.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Gherkin node interface. + * + * @author Konstantin Kudryashov + */ +interface NodeInterface +{ + /** + * Returns node type string + * + * @return string + */ + public function getNodeType(); + + /** + * Returns feature declaration line number. + * + * @return integer + */ + public function getLine(); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/OutlineNode.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/OutlineNode.php new file mode 100644 index 0000000..083b411 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/OutlineNode.php @@ -0,0 +1,217 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Represents Gherkin Outline. + * + * @author Konstantin Kudryashov + */ +class OutlineNode implements ScenarioInterface +{ + /** + * @var string + */ + private $title; + /** + * @var string[] + */ + private $tags; + /** + * @var StepNode[] + */ + private $steps; + /** + * @var ExampleTableNode + */ + private $table; + /** + * @var string + */ + private $keyword; + /** + * @var integer + */ + private $line; + /** + * @var null|ExampleNode[] + */ + private $examples; + + /** + * Initializes outline. + * + * @param null|string $title + * @param string[] $tags + * @param StepNode[] $steps + * @param ExampleTableNode $table + * @param string $keyword + * @param integer $line + */ + public function __construct( + $title, + array $tags, + array $steps, + ExampleTableNode $table, + $keyword, + $line + ) { + $this->title = $title; + $this->tags = $tags; + $this->steps = $steps; + $this->table = $table; + $this->keyword = $keyword; + $this->line = $line; + } + + /** + * Returns node type string + * + * @return string + */ + public function getNodeType() + { + return 'Outline'; + } + + /** + * Returns outline title. + * + * @return null|string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Checks if outline is tagged with tag. + * + * @param string $tag + * + * @return Boolean + */ + public function hasTag($tag) + { + return in_array($tag, $this->getTags()); + } + + /** + * Checks if outline has tags (both inherited from feature and own). + * + * @return Boolean + */ + public function hasTags() + { + return 0 < count($this->getTags()); + } + + /** + * Returns outline tags (including inherited from feature). + * + * @return string[] + */ + public function getTags() + { + return $this->tags; + } + + /** + * Checks if outline has steps. + * + * @return Boolean + */ + public function hasSteps() + { + return 0 < count($this->steps); + } + + /** + * Returns outline steps. + * + * @return StepNode[] + */ + public function getSteps() + { + return $this->steps; + } + + /** + * Checks if outline has examples. + * + * @return Boolean + */ + public function hasExamples() + { + return 0 < count($this->table->getColumnsHash()); + } + + /** + * Returns examples table. + * + * @return ExampleTableNode + */ + public function getExampleTable() + { + return $this->table; + } + + /** + * Returns list of examples for the outline. + * + * @return ExampleNode[] + */ + public function getExamples() + { + return $this->examples = $this->examples ? : $this->createExamples(); + } + + /** + * Returns outline keyword. + * + * @return string + */ + public function getKeyword() + { + return $this->keyword; + } + + /** + * Returns outline declaration line number. + * + * @return integer + */ + public function getLine() + { + return $this->line; + } + + /** + * Creates examples for this outline using examples table. + * + * @return ExampleNode[] + */ + protected function createExamples() + { + $examples = array(); + foreach ($this->table->getColumnsHash() as $rowNum => $row) { + $examples[] = new ExampleNode( + $this->table->getRowAsString($rowNum + 1), + $this->tags, + $this->getSteps(), + $row, + $this->table->getRowLine($rowNum + 1) + ); + } + + return $examples; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/PyStringNode.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/PyStringNode.php new file mode 100644 index 0000000..f0e8948 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/PyStringNode.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Represents Gherkin PyString argument. + * + * @author Konstantin Kudryashov + */ +class PyStringNode implements ArgumentInterface +{ + /** + * @var array + */ + private $strings = array(); + /** + * @var integer + */ + private $line; + + /** + * Initializes PyString. + * + * @param array $strings String in form of [$stringLine] + * @param integer $line Line number where string been started + */ + public function __construct(array $strings, $line) + { + $this->strings = $strings; + $this->line = $line; + } + + /** + * Returns node type. + * + * @return string + */ + public function getNodeType() + { + return 'PyString'; + } + + /** + * Returns entire PyString lines set. + * + * @return array + */ + public function getStrings() + { + return $this->strings; + } + + /** + * Returns raw string. + * + * @return string + */ + public function getRaw() + { + return implode("\n", $this->strings); + } + + /** + * Converts PyString into string. + * + * @return string + */ + public function __toString() + { + return $this->getRaw(); + } + + /** + * Returns line number at which PyString was started. + * + * @return integer + */ + public function getLine() + { + return $this->line; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/ScenarioInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ScenarioInterface.php new file mode 100644 index 0000000..fb29843 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ScenarioInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Gherkin scenario interface. + * + * @author Konstantin Kudryashov + */ +interface ScenarioInterface extends ScenarioLikeInterface, TaggedNodeInterface +{ +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/ScenarioLikeInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ScenarioLikeInterface.php new file mode 100644 index 0000000..88f7934 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ScenarioLikeInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Gherkin scenario-like interface. + * + * @author Konstantin Kudryashov + */ +interface ScenarioLikeInterface extends KeywordNodeInterface, StepContainerInterface +{ +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/ScenarioNode.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ScenarioNode.php new file mode 100644 index 0000000..58267e1 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ScenarioNode.php @@ -0,0 +1,150 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Represents Gherkin Scenario. + * + * @author Konstantin Kudryashov + */ +class ScenarioNode implements ScenarioInterface +{ + /** + * @var string + */ + private $title; + /** + * @var array + */ + private $tags = array(); + /** + * @var StepNode[] + */ + private $steps = array(); + /** + * @var string + */ + private $keyword; + /** + * @var integer + */ + private $line; + + /** + * Initializes scenario. + * + * @param null|string $title + * @param array $tags + * @param StepNode[] $steps + * @param string $keyword + * @param integer $line + */ + public function __construct($title, array $tags, array $steps, $keyword, $line) + { + $this->title = $title; + $this->tags = $tags; + $this->steps = $steps; + $this->keyword = $keyword; + $this->line = $line; + } + + /** + * Returns node type string + * + * @return string + */ + public function getNodeType() + { + return 'Scenario'; + } + + /** + * Returns scenario title. + * + * @return null|string + */ + public function getTitle() + { + return $this->title; + } + + /** + * Checks if scenario is tagged with tag. + * + * @param string $tag + * + * @return Boolean + */ + public function hasTag($tag) + { + return in_array($tag, $this->getTags()); + } + + /** + * Checks if scenario has tags (both inherited from feature and own). + * + * @return Boolean + */ + public function hasTags() + { + return 0 < count($this->getTags()); + } + + /** + * Returns scenario tags (including inherited from feature). + * + * @return array + */ + public function getTags() + { + return $this->tags; + } + + /** + * Checks if scenario has steps. + * + * @return Boolean + */ + public function hasSteps() + { + return 0 < count($this->steps); + } + + /** + * Returns scenario steps. + * + * @return StepNode[] + */ + public function getSteps() + { + return $this->steps; + } + + /** + * Returns scenario keyword. + * + * @return string + */ + public function getKeyword() + { + return $this->keyword; + } + + /** + * Returns scenario declaration line number. + * + * @return integer + */ + public function getLine() + { + return $this->line; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/StepContainerInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/StepContainerInterface.php new file mode 100644 index 0000000..2a5c73d --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/StepContainerInterface.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Gherkin step container interface. + * + * @author Konstantin Kudryashov + */ +interface StepContainerInterface extends NodeInterface +{ + /** + * Checks if container has steps. + * + * @return Boolean + */ + public function hasSteps(); + + /** + * Returns container steps. + * + * @return StepNode[] + */ + public function getSteps(); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/StepNode.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/StepNode.php new file mode 100644 index 0000000..82eaef4 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/StepNode.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +use Behat\Gherkin\Exception\NodeException; + +/** + * Represents Gherkin Step. + * + * @author Konstantin Kudryashov + */ +class StepNode implements NodeInterface +{ + /** + * @var string + */ + private $keyword; + /** + * @var string + */ + private $keywordType; + /** + * @var string + */ + private $text; + /** + * @var ArgumentInterface[] + */ + private $arguments = array(); + /** + * @var integer + */ + private $line; + + /** + * Initializes step. + * + * @param string $keyword + * @param string $text + * @param ArgumentInterface[] $arguments + * @param integer $line + * @param string $keywordType + */ + public function __construct($keyword, $text, array $arguments, $line, $keywordType = null) + { + if (count($arguments) > 1) { + throw new NodeException(sprintf( + 'Steps could have only one argument, but `%s %s` have %d.', + $keyword, + $text, + count($arguments) + )); + } + + $this->keyword = $keyword; + $this->text = $text; + $this->arguments = $arguments; + $this->line = $line; + $this->keywordType = $keywordType ?: 'Given'; + } + + /** + * Returns node type string + * + * @return string + */ + public function getNodeType() + { + return 'Step'; + } + + /** + * Returns step keyword in provided language (Given, When, Then, etc.). + * + * @return string + * + * @deprecated use getKeyword() instead + */ + public function getType() + { + return $this->getKeyword(); + } + + /** + * Returns step keyword in provided language (Given, When, Then, etc.). + * + * @return string + * + */ + public function getKeyword() + { + return $this->keyword; + } + + /** + * Returns step type keyword (Given, When, Then, etc.). + * + * @return string + */ + public function getKeywordType() + { + return $this->keywordType; + } + + /** + * Returns step text. + * + * @return string + */ + public function getText() + { + return $this->text; + } + + /** + * Checks if step has arguments. + * + * @return Boolean + */ + public function hasArguments() + { + return 0 < count($this->arguments); + } + + /** + * Returns step arguments. + * + * @return ArgumentInterface[] + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Returns step declaration line number. + * + * @return integer + */ + public function getLine() + { + return $this->line; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/TableNode.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/TableNode.php new file mode 100644 index 0000000..9e5d174 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/TableNode.php @@ -0,0 +1,313 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +use ArrayIterator; +use Behat\Gherkin\Exception\NodeException; +use Iterator; +use IteratorAggregate; + +/** + * Represents Gherkin Table argument. + * + * @author Konstantin Kudryashov + */ +class TableNode implements ArgumentInterface, IteratorAggregate +{ + /** + * @var array + */ + private $table; + /** + * @var integer + */ + private $maxLineLength = array(); + + /** + * Initializes table. + * + * @param array $table Table in form of [$rowLineNumber => [$val1, $val2, $val3]] + * + * @throws NodeException If the number of columns is not the same in each row + */ + public function __construct(array $table) + { + $this->table = $table; + $columnCount = null; + + foreach ($this->getRows() as $row) { + if ($columnCount === null) { + $columnCount = count($row); + } + + if (count($row) !== $columnCount) { + throw new NodeException('Table does not have same number of columns in every row.'); + } + + foreach ($row as $column => $string) { + if (!isset($this->maxLineLength[$column])) { + $this->maxLineLength[$column] = 0; + } + + $this->maxLineLength[$column] = max($this->maxLineLength[$column], mb_strlen($string, 'utf8')); + } + } + } + + /** + * Returns node type. + * + * @return string + */ + public function getNodeType() + { + return 'Table'; + } + + /** + * Returns table hash, formed by columns (ColumnsHash). + * + * @return array + */ + public function getHash() + { + return $this->getColumnsHash(); + } + + /** + * Returns table hash, formed by columns. + * + * @return array + */ + public function getColumnsHash() + { + $rows = $this->getRows(); + $keys = array_shift($rows); + + $hash = array(); + foreach ($rows as $row) { + $hash[] = array_combine($keys, $row); + } + + return $hash; + } + + /** + * Returns table hash, formed by rows. + * + * @return array + */ + public function getRowsHash() + { + $hash = array(); + + foreach ($this->getRows() as $row) { + $hash[array_shift($row)] = (1 == count($row)) ? $row[0] : $row; + } + + return $hash; + } + + /** + * Returns numerated table lines. + * Line numbers are keys, lines are values. + * + * @return array + */ + public function getTable() + { + return $this->table; + } + + /** + * Returns table rows. + * + * @return array + */ + public function getRows() + { + return array_values($this->table); + } + + /** + * Returns table definition lines. + * + * @return array + */ + public function getLines() + { + return array_keys($this->table); + } + + /** + * Returns specific row in a table. + * + * @param integer $index Row number + * + * @return array + * + * @throws NodeException If row with specified index does not exist + */ + public function getRow($index) + { + $rows = $this->getRows(); + + if (!isset($rows[$index])) { + throw new NodeException(sprintf('Rows #%d does not exist in table.', $index)); + } + + return $rows[$index]; + } + + /** + * Returns specific column in a table. + * + * @param integer $index Column number + * + * @return array + * + * @throws NodeException If column with specified index does not exist + */ + public function getColumn($index) + { + if ($index >= count($this->getRow(0))) { + throw new NodeException(sprintf('Column #%d does not exist in table.', $index)); + } + + $rows = $this->getRows(); + $column = array(); + + foreach ($rows as $row) { + $column[] = $row[$index]; + } + + return $column; + } + + /** + * Returns line number at which specific row was defined. + * + * @param integer $index + * + * @return integer + * + * @throws NodeException If row with specified index does not exist + */ + public function getRowLine($index) + { + $lines = array_keys($this->table); + + if (!isset($lines[$index])) { + throw new NodeException(sprintf('Rows #%d does not exist in table.', $index)); + } + + return $lines[$index]; + } + + /** + * Converts row into delimited string. + * + * @param integer $rowNum Row number + * + * @return string + */ + public function getRowAsString($rowNum) + { + $values = array(); + foreach ($this->getRow($rowNum) as $column => $value) { + $values[] = $this->padRight(' ' . $value . ' ', $this->maxLineLength[$column] + 2); + } + + return sprintf('|%s|', implode('|', $values)); + } + + /** + * Converts row into delimited string. + * + * @param integer $rowNum Row number + * @param callable $wrapper Wrapper function + * + * @return string + */ + public function getRowAsStringWithWrappedValues($rowNum, $wrapper) + { + $values = array(); + foreach ($this->getRow($rowNum) as $column => $value) { + $value = $this->padRight(' ' . $value . ' ', $this->maxLineLength[$column] + 2); + + $values[] = call_user_func($wrapper, $value, $column); + } + + return sprintf('|%s|', implode('|', $values)); + } + + /** + * Converts entire table into string + * + * @return string + */ + public function getTableAsString() + { + $lines = array(); + for ($i = 0; $i < count($this->getRows()); $i++) { + $lines[] = $this->getRowAsString($i); + } + + return implode("\n", $lines); + } + + /** + * Returns line number at which table was started. + * + * @return integer + */ + public function getLine() + { + return $this->getRowLine(0); + } + + /** + * Converts table into string + * + * @return string + */ + public function __toString() + { + return $this->getTableAsString(); + } + + /** + * Retrieves a hash iterator. + * + * @return Iterator + */ + public function getIterator() + { + return new ArrayIterator($this->getHash()); + } + + /** + * Pads string right. + * + * @param string $text Text to pad + * @param integer $length Length + * + * @return string + */ + protected function padRight($text, $length) + { + while ($length > mb_strlen($text, 'utf8')) { + $text = $text . ' '; + } + + return $text; + } +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Node/TaggedNodeInterface.php b/vendor/behat/gherkin/src/Behat/Gherkin/Node/TaggedNodeInterface.php new file mode 100644 index 0000000..cce6bca --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/TaggedNodeInterface.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin\Node; + +/** + * Gherkin tagged node interface. + * + * @author Konstantin Kudryashov + */ +interface TaggedNodeInterface extends NodeInterface +{ + /** + * Checks if node is tagged with tag. + * + * @param string $tag + * + * @return Boolean + */ + public function hasTag($tag); + + /** + * Checks if node has tags (both inherited from feature and own). + * + * @return Boolean + */ + public function hasTags(); + + /** + * Returns node tags (including inherited from feature). + * + * @return string[] + */ + public function getTags(); +} diff --git a/vendor/behat/gherkin/src/Behat/Gherkin/Parser.php b/vendor/behat/gherkin/src/Behat/Gherkin/Parser.php new file mode 100644 index 0000000..97ca852 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Parser.php @@ -0,0 +1,698 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Gherkin; + +use Behat\Gherkin\Exception\LexerException; +use Behat\Gherkin\Exception\ParserException; +use Behat\Gherkin\Node\BackgroundNode; +use Behat\Gherkin\Node\ExampleTableNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Gherkin\Node\PyStringNode; +use Behat\Gherkin\Node\ScenarioInterface; +use Behat\Gherkin\Node\ScenarioNode; +use Behat\Gherkin\Node\StepNode; +use Behat\Gherkin\Node\TableNode; + +/** + * Gherkin parser. + * + * $lexer = new Behat\Gherkin\Lexer($keywords); + * $parser = new Behat\Gherkin\Parser($lexer); + * $featuresArray = $parser->parse('/path/to/feature.feature'); + * + * @author Konstantin Kudryashov + */ +class Parser +{ + private $lexer; + private $input; + private $file; + private $tags = array(); + private $languageSpecifierLine; + + /** + * Initializes parser. + * + * @param Lexer $lexer Lexer instance + */ + public function __construct(Lexer $lexer) + { + $this->lexer = $lexer; + } + + /** + * Parses input & returns features array. + * + * @param string $input Gherkin string document + * @param string $file File name + * + * @return FeatureNode|null + * + * @throws ParserException + */ + public function parse($input, $file = null) + { + $this->languageSpecifierLine = null; + $this->input = $input; + $this->file = $file; + + try { + $this->lexer->analyse($this->input, 'en'); + } catch (LexerException $e) { + throw new ParserException( + sprintf('Lexer exception "%s" thrown for file %s', $e->getMessage(), $file), + 0, + $e + ); + } + + $feature = null; + while ('EOS' !== ($predicted = $this->predictTokenType())) { + $node = $this->parseExpression(); + + if (null === $node || "\n" === $node) { + continue; + } + + if (!$feature && $node instanceof FeatureNode) { + $feature = $node; + continue; + } + + if ($feature && $node instanceof FeatureNode) { + throw new ParserException(sprintf( + 'Only one feature is allowed per feature file. But %s got multiple.', + $this->file + )); + } + + if (is_string($node)) { + throw new ParserException(sprintf( + 'Expected Feature, but got text: "%s"%s', + $node, + $this->file ? ' in file: ' . $this->file : '' + )); + } + + if (!$node instanceof FeatureNode) { + throw new ParserException(sprintf( + 'Expected Feature, but got %s on line: %d%s', + $node->getKeyword(), + $node->getLine(), + $this->file ? ' in file: ' . $this->file : '' + )); + } + } + + return $feature; + } + + /** + * Returns next token if it's type equals to expected. + * + * @param string $type Token type + * + * @return array + * + * @throws Exception\ParserException + */ + protected function expectTokenType($type) + { + $types = (array) $type; + if (in_array($this->predictTokenType(), $types)) { + return $this->lexer->getAdvancedToken(); + } + + $token = $this->lexer->predictToken(); + + throw new ParserException(sprintf( + 'Expected %s token, but got %s on line: %d%s', + implode(' or ', $types), + $this->predictTokenType(), + $token['line'], + $this->file ? ' in file: ' . $this->file : '' + )); + } + + /** + * Returns next token if it's type equals to expected. + * + * @param string $type Token type + * + * @return null|array + */ + protected function acceptTokenType($type) + { + if ($type !== $this->predictTokenType()) { + return null; + } + + return $this->lexer->getAdvancedToken(); + } + + /** + * Returns next token type without real input reading (prediction). + * + * @return string + */ + protected function predictTokenType() + { + $token = $this->lexer->predictToken(); + + return $token['type']; + } + + /** + * Parses current expression & returns Node. + * + * @return string|FeatureNode|BackgroundNode|ScenarioNode|OutlineNode|TableNode|StepNode + * + * @throws ParserException + */ + protected function parseExpression() + { + switch ($type = $this->predictTokenType()) { + case 'Feature': + return $this->parseFeature(); + case 'Background': + return $this->parseBackground(); + case 'Scenario': + return $this->parseScenario(); + case 'Outline': + return $this->parseOutline(); + case 'Examples': + return $this->parseExamples(); + case 'TableRow': + return $this->parseTable(); + case 'PyStringOp': + return $this->parsePyString(); + case 'Step': + return $this->parseStep(); + case 'Text': + return $this->parseText(); + case 'Newline': + return $this->parseNewline(); + case 'Tag': + return $this->parseTags(); + case 'Comment': + return $this->parseComment(); + case 'Language': + return $this->parseLanguage(); + case 'EOS': + return ''; + } + + throw new ParserException(sprintf('Unknown token type: %s', $type)); + } + + /** + * Parses feature token & returns it's node. + * + * @return FeatureNode + * + * @throws ParserException + */ + protected function parseFeature() + { + $token = $this->expectTokenType('Feature'); + + $title = trim($token['value']) ?: null; + $description = null; + $tags = $this->popTags(); + $background = null; + $scenarios = array(); + $keyword = $token['keyword']; + $language = $this->lexer->getLanguage(); + $file = $this->file; + $line = $token['line']; + + // Parse description, background, scenarios & outlines + while ('EOS' !== $this->predictTokenType()) { + $node = $this->parseExpression(); + + if (is_string($node)) { + $text = preg_replace('/^\s{0,' . ($token['indent'] + 2) . '}|\s*$/', '', $node); + $description .= (null !== $description ? "\n" : '') . $text; + continue; + } + + if (!$background && $node instanceof BackgroundNode) { + $background = $node; + continue; + } + + if ($node instanceof ScenarioInterface) { + $scenarios[] = $node; + continue; + } + + if ($background instanceof BackgroundNode && $node instanceof BackgroundNode) { + throw new ParserException(sprintf( + 'Each Feature could have only one Background, but found multiple on lines %d and %d%s', + $background->getLine(), + $node->getLine(), + $this->file ? ' in file: ' . $this->file : '' + )); + } + + if (!$node instanceof ScenarioNode) { + throw new ParserException(sprintf( + 'Expected Scenario, Outline or Background, but got %s on line: %d%s', + $node->getNodeType(), + $node->getLine(), + $this->file ? ' in file: ' . $this->file : '' + )); + } + } + + return new FeatureNode( + rtrim($title) ?: null, + rtrim($description) ?: null, + $tags, + $background, + $scenarios, + $keyword, + $language, + $file, + $line + ); + } + + /** + * Parses background token & returns it's node. + * + * @return BackgroundNode + * + * @throws ParserException + */ + protected function parseBackground() + { + $token = $this->expectTokenType('Background'); + + $title = trim($token['value']); + $keyword = $token['keyword']; + $line = $token['line']; + + if (count($this->popTags())) { + throw new ParserException(sprintf( + 'Background can not be tagged, but it is on line: %d%s', + $line, + $this->file ? ' in file: ' . $this->file : '' + )); + } + + // Parse description and steps + $steps = array(); + $allowedTokenTypes = array('Step', 'Newline', 'Text', 'Comment'); + while (in_array($this->predictTokenType(), $allowedTokenTypes)) { + $node = $this->parseExpression(); + + if ($node instanceof StepNode) { + $steps[] = $this->normalizeStepNodeKeywordType($node, $steps); + continue; + } + + if (!count($steps) && is_string($node)) { + $text = preg_replace('/^\s{0,' . ($token['indent'] + 2) . '}|\s*$/', '', $node); + $title .= "\n" . $text; + continue; + } + + if ("\n" === $node) { + continue; + } + + if (is_string($node)) { + throw new ParserException(sprintf( + 'Expected Step, but got text: "%s"%s', + $node, + $this->file ? ' in file: ' . $this->file : '' + )); + } + + if (!$node instanceof StepNode) { + throw new ParserException(sprintf( + 'Expected Step, but got %s on line: %d%s', + $node->getNodeType(), + $node->getLine(), + $this->file ? ' in file: ' . $this->file : '' + )); + } + } + + return new BackgroundNode(rtrim($title) ?: null, $steps, $keyword, $line); + } + + /** + * Parses scenario token & returns it's node. + * + * @return ScenarioNode + * + * @throws ParserException + */ + protected function parseScenario() + { + $token = $this->expectTokenType('Scenario'); + + $title = trim($token['value']); + $tags = $this->popTags(); + $keyword = $token['keyword']; + $line = $token['line']; + + // Parse description and steps + $steps = array(); + while (in_array($this->predictTokenType(), array('Step', 'Newline', 'Text', 'Comment'))) { + $node = $this->parseExpression(); + + if ($node instanceof StepNode) { + $steps[] = $this->normalizeStepNodeKeywordType($node, $steps); + continue; + } + + if (!count($steps) && is_string($node)) { + $text = preg_replace('/^\s{0,' . ($token['indent'] + 2) . '}|\s*$/', '', $node); + $title .= "\n" . $text; + continue; + } + + if ("\n" === $node) { + continue; + } + + if (is_string($node)) { + throw new ParserException(sprintf( + 'Expected Step, but got text: "%s"%s', + $node, + $this->file ? ' in file: ' . $this->file : '' + )); + } + + if (!$node instanceof StepNode) { + throw new ParserException(sprintf( + 'Expected Step, but got %s on line: %d%s', + $node->getNodeType(), + $node->getLine(), + $this->file ? ' in file: ' . $this->file : '' + )); + } + } + + return new ScenarioNode(rtrim($title) ?: null, $tags, $steps, $keyword, $line); + } + + /** + * Parses scenario outline token & returns it's node. + * + * @return OutlineNode + * + * @throws ParserException + */ + protected function parseOutline() + { + $token = $this->expectTokenType('Outline'); + + $title = trim($token['value']); + $tags = $this->popTags(); + $keyword = $token['keyword']; + $examples = null; + $line = $token['line']; + + // Parse description, steps and examples + $steps = array(); + while (in_array($this->predictTokenType(), array('Step', 'Examples', 'Newline', 'Text', 'Comment'))) { + $node = $this->parseExpression(); + + if ($node instanceof StepNode) { + $steps[] = $this->normalizeStepNodeKeywordType($node, $steps); + continue; + } + + if ($node instanceof ExampleTableNode) { + $examples = $node; + continue; + } + + if (!count($steps) && is_string($node)) { + $text = preg_replace('/^\s{0,' . ($token['indent'] + 2) . '}|\s*$/', '', $node); + $title .= "\n" . $text; + continue; + } + + if ("\n" === $node) { + continue; + } + + if (is_string($node)) { + throw new ParserException(sprintf( + 'Expected Step or Examples table, but got text: "%s"%s', + $node, + $this->file ? ' in file: ' . $this->file : '' + )); + } + + if (!$node instanceof StepNode) { + throw new ParserException(sprintf( + 'Expected Step or Examples table, but got %s on line: %d%s', + $node->getNodeType(), + $node->getLine(), + $this->file ? ' in file: ' . $this->file : '' + )); + } + } + + if (null === $examples) { + throw new ParserException(sprintf( + 'Outline should have examples table, but got none for outline "%s" on line: %d%s', + rtrim($title), + $line, + $this->file ? ' in file: ' . $this->file : '' + )); + } + + return new OutlineNode(rtrim($title) ?: null, $tags, $steps, $examples, $keyword, $line); + } + + /** + * Parses step token & returns it's node. + * + * @return StepNode + */ + protected function parseStep() + { + $token = $this->expectTokenType('Step'); + + $keyword = $token['value']; + $keywordType = $token['keyword_type']; + $text = trim($token['text']); + $line = $token['line']; + + $arguments = array(); + while (in_array($predicted = $this->predictTokenType(), array('PyStringOp', 'TableRow', 'Newline', 'Comment'))) { + if ('Comment' === $predicted || 'Newline' === $predicted) { + $this->acceptTokenType($predicted); + continue; + } + + $node = $this->parseExpression(); + + if ($node instanceof PyStringNode || $node instanceof TableNode) { + $arguments[] = $node; + } + } + + return new StepNode($keyword, $text, $arguments, $line, $keywordType); + } + + /** + * Parses examples table node. + * + * @return ExampleTableNode + */ + protected function parseExamples() + { + $token = $this->expectTokenType('Examples'); + + $keyword = $token['keyword']; + + return new ExampleTableNode($this->parseTableRows(), $keyword); + } + + /** + * Parses table token & returns it's node. + * + * @return TableNode + */ + protected function parseTable() + { + return new TableNode($this->parseTableRows()); + } + + /** + * Parses PyString token & returns it's node. + * + * @return PyStringNode + */ + protected function parsePyString() + { + $token = $this->expectTokenType('PyStringOp'); + + $line = $token['line']; + + $strings = array(); + while ('PyStringOp' !== ($predicted = $this->predictTokenType()) && 'Text' === $predicted) { + $token = $this->expectTokenType('Text'); + + $strings[] = $token['value']; + } + + $this->expectTokenType('PyStringOp'); + + return new PyStringNode($strings, $line); + } + + /** + * Parses tags. + * + * @return BackgroundNode|FeatureNode|OutlineNode|ScenarioNode|StepNode|TableNode|string + */ + protected function parseTags() + { + $token = $this->expectTokenType('Tag'); + $this->tags = array_merge($this->tags, $token['tags']); + + return $this->parseExpression(); + } + + /** + * Returns current set of tags and clears tag buffer. + * + * @return array + */ + protected function popTags() + { + $tags = $this->tags; + $this->tags = array(); + + return $tags; + } + + /** + * Parses next text line & returns it. + * + * @return string + */ + protected function parseText() + { + $token = $this->expectTokenType('Text'); + + return $token['value']; + } + + /** + * Parses next newline & returns \n. + * + * @return string + */ + protected function parseNewline() + { + $this->expectTokenType('Newline'); + + return "\n"; + } + + /** + * Parses next comment token & returns it's string content. + * + * @return BackgroundNode|FeatureNode|OutlineNode|ScenarioNode|StepNode|TableNode|string + */ + protected function parseComment() + { + $this->expectTokenType('Comment'); + + return $this->parseExpression(); + } + + /** + * Parses language block and updates lexer configuration based on it. + * + * @return BackgroundNode|FeatureNode|OutlineNode|ScenarioNode|StepNode|TableNode|string + * + * @throws ParserException + */ + protected function parseLanguage() + { + $token = $this->expectTokenType('Language'); + + if (null === $this->languageSpecifierLine) { + $this->lexer->analyse($this->input, $token['value']); + $this->languageSpecifierLine = $token['line']; + } elseif ($token['line'] !== $this->languageSpecifierLine) { + throw new ParserException(sprintf( + 'Ambiguous language specifiers on lines: %d and %d%s', + $this->languageSpecifierLine, + $token['line'], + $this->file ? ' in file: ' . $this->file : '' + )); + } + + return $this->parseExpression(); + } + + /** + * Parses the rows of a table + * + * @return string[][] + */ + private function parseTableRows() + { + $table = array(); + while (in_array($predicted = $this->predictTokenType(), array('TableRow', 'Newline', 'Comment'))) { + if ('Comment' === $predicted || 'Newline' === $predicted) { + $this->acceptTokenType($predicted); + continue; + } + + $token = $this->expectTokenType('TableRow'); + + $table[$token['line']] = $token['columns']; + } + + return $table; + } + + /** + * Changes step node type for types But, And to type of previous step if it exists else sets to Given + * + * @param StepNode $node + * @param StepNode[] $steps + * @return StepNode + */ + private function normalizeStepNodeKeywordType(StepNode $node, array $steps = array()) + { + if (in_array($node->getKeywordType(), array('And', 'But'))) { + if (($prev = end($steps))) { + $keywordType = $prev->getKeywordType(); + } else { + $keywordType = 'Given'; + } + + $node = new StepNode( + $node->getKeyword(), + $node->getText(), + $node->getArguments(), + $node->getLine(), + $keywordType + ); + } + return $node; + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Cache/FileCacheTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Cache/FileCacheTest.php new file mode 100644 index 0000000..d0a33a2 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Cache/FileCacheTest.php @@ -0,0 +1,67 @@ +assertFalse($this->cache->isFresh('unexisting', time() + 100)); + } + + public function testIsFreshOnFreshFile() + { + $feature = new FeatureNode(null, null, array(), null, array(), null, null, null, null); + + $this->cache->write('some_path', $feature); + + $this->assertFalse($this->cache->isFresh('some_path', time() + 100)); + } + + public function testIsFreshOnOutdated() + { + $feature = new FeatureNode(null, null, array(), null, array(), null, null, null, null); + + $this->cache->write('some_path', $feature); + + $this->assertTrue($this->cache->isFresh('some_path', time() - 100)); + } + + public function testCacheAndRead() + { + $scenarios = array(new ScenarioNode('Some scenario', array(), array(), null, null)); + $feature = new FeatureNode('Some feature', 'some description', array(), null, $scenarios, null, null, null, null); + + $this->cache->write('some_feature', $feature); + $featureRead = $this->cache->read('some_feature'); + + $this->assertEquals($feature, $featureRead); + } + + public function testBrokenCacheRead() + { + $this->setExpectedException('Behat\Gherkin\Exception\CacheException'); + + touch($this->path . '/412/' . md5('broken_feature') . '.feature.cache'); + $this->cache->read('broken_feature'); + } + + protected function setUp() + { + $this->cache = new FileCache($this->path = sys_get_temp_dir() . '/gherkin-test'); + } + + protected function tearDown() + { + foreach (glob($this->path . '/*.feature.cache') as $file) { + unlink((string) $file); + } + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Cache/MemoryCacheTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Cache/MemoryCacheTest.php new file mode 100644 index 0000000..a0bb6c8 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Cache/MemoryCacheTest.php @@ -0,0 +1,51 @@ +assertFalse($this->cache->isFresh('unexisting', time() + 100)); + } + + public function testIsFreshOnFreshFile() + { + $feature = new FeatureNode(null, null, array(), null, array(), null, null, null, null); + + $this->cache->write('some_path', $feature); + + $this->assertFalse($this->cache->isFresh('some_path', time() + 100)); + } + + public function testIsFreshOnOutdated() + { + $feature = new FeatureNode(null, null, array(), null, array(), null, null, null, null); + + $this->cache->write('some_path', $feature); + + $this->assertTrue($this->cache->isFresh('some_path', time() - 100)); + } + + public function testCacheAndRead() + { + $scenarios = array(new ScenarioNode('Some scenario', array(), array(), null, null)); + $feature = new FeatureNode('Some feature', 'some description', array(), null, $scenarios, null, null, null, null); + + $this->cache->write('some_feature', $feature); + $featureRead = $this->cache->read('some_feature'); + + $this->assertEquals($feature, $featureRead); + } + + protected function setUp() + { + $this->cache = new MemoryCache(); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/FilterTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/FilterTest.php new file mode 100644 index 0000000..994e656 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/FilterTest.php @@ -0,0 +1,64 @@ + array( + 'feature' => 'Feature', + 'background' => 'Background', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Scenario Outline|Scenario Template', + 'examples' => 'Examples|Scenarios', + 'given' => 'Given', + 'when' => 'When', + 'then' => 'Then', + 'and' => 'And', + 'but' => 'But' + ) + )) + ) + ); + } + + protected function getGherkinFeature() + { + return << occurs + Then should be visible + + Examples: + | action | outcome | + | act#1 | out#1 | + | act#2 | out#2 | + | act#3 | out#3 | +GHERKIN; + } + + protected function getParsedFeature() + { + return $this->getParser()->parse($this->getGherkinFeature()); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/LineFilterTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/LineFilterTest.php new file mode 100644 index 0000000..846a719 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/LineFilterTest.php @@ -0,0 +1,103 @@ +assertTrue($filter->isFeatureMatch($feature)); + + $filter = new LineFilter(2); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $filter = new LineFilter(3); + $this->assertFalse($filter->isFeatureMatch($feature)); + } + + public function testIsScenarioMatchFilter() + { + $scenario = new ScenarioNode(null, array(), array(), null, 2); + + $filter = new LineFilter(2); + $this->assertTrue($filter->isScenarioMatch($scenario)); + + $filter = new LineFilter(1); + $this->assertFalse($filter->isScenarioMatch($scenario)); + + $filter = new LineFilter(5); + $this->assertFalse($filter->isScenarioMatch($scenario)); + + $outline = new OutlineNode(null, array(), array(), new ExampleTableNode(array(), null), null, 20); + + $filter = new LineFilter(5); + $this->assertFalse($filter->isScenarioMatch($outline)); + + $filter = new LineFilter(20); + $this->assertTrue($filter->isScenarioMatch($outline)); + } + + public function testFilterFeatureScenario() + { + $filter = new LineFilter(2); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#1', $scenarios[0]->getTitle()); + + $filter = new LineFilter(7); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#2', $scenarios[0]->getTitle()); + + $filter = new LineFilter(5); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(0, $scenarios = $feature->getScenarios()); + } + + public function testFilterFeatureOutline() + { + $filter = new LineFilter(13); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#3', $scenarios[0]->getTitle()); + $this->assertCount(4, $scenarios[0]->getExampleTable()->getRows()); + + $filter = new LineFilter(19); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#3', $scenarios[0]->getTitle()); + $this->assertCount(2, $scenarios[0]->getExampleTable()->getRows()); + $this->assertSame(array( + array('action', 'outcome'), + array('act#1', 'out#1'), + ), $scenarios[0]->getExampleTable()->getRows()); + + $filter = new LineFilter(21); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#3', $scenarios[0]->getTitle()); + $this->assertCount(2, $scenarios[0]->getExampleTable()->getRows()); + $this->assertSame(array( + array('action', 'outcome'), + array('act#3', 'out#3'), + ), $scenarios[0]->getExampleTable()->getRows()); + + $filter = new LineFilter(18); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#3', $scenarios[0]->getTitle()); + $this->assertCount(1, $scenarios[0]->getExampleTable()->getRows()); + $this->assertSame(array( + array('action', 'outcome'), + ), $scenarios[0]->getExampleTable()->getRows()); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/LineRangeFilterTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/LineRangeFilterTest.php new file mode 100644 index 0000000..fb8abe1 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/LineRangeFilterTest.php @@ -0,0 +1,101 @@ +assertSame($expected, $filter->isFeatureMatch($feature)); + } + + public function scenarioLineRangeProvider() + { + return array( + array('1', '2', 1), + array('1', '*', 2), + array('2', '2', 1), + array('2', '*', 2), + array('3', '3', 1), + array('3', '*', 1), + array('1', '1', 0), + array('4', '4', 0), + array('4', '*', 0) + ); + } + + /** + * @dataProvider scenarioLineRangeProvider + */ + public function testIsScenarioMatchFilter($filterMinLine, $filterMaxLine, $expectedNumberOfMatches) + { + $scenario = new ScenarioNode(null, array(), array(), null, 2); + $outline = new OutlineNode(null, array(), array(), new ExampleTableNode(array(), null), null, 3); + + $filter = new LineRangeFilter($filterMinLine, $filterMaxLine); + $this->assertEquals( + $expectedNumberOfMatches, + intval($filter->isScenarioMatch($scenario)) + intval($filter->isScenarioMatch($outline)) + ); + } + + public function testFilterFeatureScenario() + { + $filter = new LineRangeFilter(1, 3); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#1', $scenarios[0]->getTitle()); + + $filter = new LineRangeFilter(5, 9); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#2', $scenarios[0]->getTitle()); + + $filter = new LineRangeFilter(5, 6); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(0, $scenarios = $feature->getScenarios()); + } + + public function testFilterFeatureOutline() + { + $filter = new LineRangeFilter(12, 14); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#3', $scenarios[0]->getTitle()); + $this->assertCount(1, $scenarios[0]->getExampleTable()->getRows()); + + $filter = new LineRangeFilter(15, 20); + $feature = $filter->filterFeature($this->getParsedFeature()); + $this->assertCount(1, $scenarios = $feature->getScenarios()); + $this->assertSame('Scenario#3', $scenarios[0]->getTitle()); + $this->assertCount(3, $scenarios[0]->getExampleTable()->getRows()); + $this->assertSame(array( + array('action', 'outcome'), + array('act#1', 'out#1'), + array('act#2', 'out#2'), + ), $scenarios[0]->getExampleTable()->getRows()); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/NameFilterTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/NameFilterTest.php new file mode 100644 index 0000000..24914ec --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/NameFilterTest.php @@ -0,0 +1,79 @@ +assertSame($feature, $filter->filterFeature($feature)); + + $scenarios = array( + new ScenarioNode('scenario1', array(), array(), null, 2), + $matchedScenario = new ScenarioNode('scenario2', array(), array(), null, 4) + ); + $feature = new FeatureNode('feature1', null, array(), null, $scenarios, null, null, null, 1); + $filter = new NameFilter('scenario2'); + $filteredFeature = $filter->filterFeature($feature); + + $this->assertSame(array($matchedScenario), $filteredFeature->getScenarios()); + } + + public function testIsFeatureMatchFilter() + { + $feature = new FeatureNode('random feature title', null, array(), null, array(), null, null, null, 1); + + $filter = new NameFilter('feature1'); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode('feature1', null, array(), null, array(), null, null, null, 1); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode('feature1 title', null, array(), null, array(), null, null, null, 1); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode('some feature1 title', null, array(), null, array(), null, null, null, 1); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode('some feature title', null, array(), null, array(), null, null, null, 1); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $filter = new NameFilter('/fea.ure/'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode('some feaSure title', null, array(), null, array(), null, null, null, 1); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode('some feture title', null, array(), null, array(), null, null, null, 1); + $this->assertFalse($filter->isFeatureMatch($feature)); + } + + public function testIsScenarioMatchFilter() + { + $filter = new NameFilter('scenario1'); + + $scenario = new ScenarioNode('UNKNOWN', array(), array(), null, 2); + $this->assertFalse($filter->isScenarioMatch($scenario)); + + $scenario = new ScenarioNode('scenario1', array(), array(), null, 2); + $this->assertTrue($filter->isScenarioMatch($scenario)); + + $scenario = new ScenarioNode('scenario1 title', array(), array(), null, 2); + $this->assertTrue($filter->isScenarioMatch($scenario)); + + $scenario = new ScenarioNode('some scenario title', array(), array(), null, 2); + $this->assertFalse($filter->isScenarioMatch($scenario)); + + $filter = new NameFilter('/sce.ario/'); + $this->assertTrue($filter->isScenarioMatch($scenario)); + + $filter = new NameFilter('/scen.rio/'); + $this->assertTrue($filter->isScenarioMatch($scenario)); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/NarrativeFilterTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/NarrativeFilterTest.php new file mode 100644 index 0000000..6a50e1e --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/NarrativeFilterTest.php @@ -0,0 +1,34 @@ +assertFalse($filter->isFeatureMatch($feature)); + + $filter = new NarrativeFilter('/as (?:a|an) french user/i'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new NarrativeFilter('/french .*/'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new NarrativeFilter('/^french/'); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $filter = new NarrativeFilter('/user$/'); + $this->assertFalse($filter->isFeatureMatch($feature)); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/PathsFilterTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/PathsFilterTest.php new file mode 100644 index 0000000..eb316c0 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/PathsFilterTest.php @@ -0,0 +1,29 @@ +assertTrue($filter->isFeatureMatch($feature)); + + $filter = new PathsFilter(array('/abc', '/def', dirname(__DIR__))); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new PathsFilter(array('/abc', '/def', __DIR__)); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new PathsFilter(array('/abc', __DIR__, '/def')); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new PathsFilter(array('/abc', '/def', '/wrong/path')); + $this->assertFalse($filter->isFeatureMatch($feature)); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/RoleFilterTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/RoleFilterTest.php new file mode 100644 index 0000000..8e8af3e --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/RoleFilterTest.php @@ -0,0 +1,73 @@ +assertTrue($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('french *'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('french'); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('user'); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('*user'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('French User'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array(), null, array(), null, null, null, 1); + $filter = new RoleFilter('French User'); + $this->assertFalse($filter->isFeatureMatch($feature)); + } + + public function testFeatureRolePrefixedWithAn() + { + $description = <<assertTrue($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('american *'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('american'); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('user'); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('*user'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new RoleFilter('American User'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array(), null, array(), null, null, null, 1); + $filter = new RoleFilter('American User'); + $this->assertFalse($filter->isFeatureMatch($feature)); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/TagFilterTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/TagFilterTest.php new file mode 100644 index 0000000..5c6c9ab --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/TagFilterTest.php @@ -0,0 +1,144 @@ +assertEquals($feature, $filter->filterFeature($feature)); + + $scenarios = array( + new ScenarioNode(null, array(), array(), null, 2), + $matchedScenario = new ScenarioNode(null, array('wip'), array(), null, 4) + ); + $feature = new FeatureNode(null, null, array(), null, $scenarios, null, null, null, 1); + $filteredFeature = $filter->filterFeature($feature); + + $this->assertSame(array($matchedScenario), $filteredFeature->getScenarios()); + + $filter = new TagFilter('~@wip'); + $scenarios = array( + $matchedScenario = new ScenarioNode(null, array(), array(), null, 2), + new ScenarioNode(null, array('wip'), array(), null, 4) + ); + $feature = new FeatureNode(null, null, array(), null, $scenarios, null, null, null, 1); + $filteredFeature = $filter->filterFeature($feature); + + $this->assertSame(array($matchedScenario), $filteredFeature->getScenarios()); + } + + public function testIsFeatureMatchFilter() + { + $feature = new FeatureNode(null, null, array(), null, array(), null, null, null, 1); + + $filter = new TagFilter('@wip'); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array('wip'), null, array(), null, null, null, 1); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new TagFilter('~@done'); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array('wip', 'done'), null, array(), null, null, null, 1); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array('tag1', 'tag2', 'tag3'), null, array(), null, null, null, 1); + $filter = new TagFilter('@tag5,@tag4,@tag6'); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array( + 'tag1', + 'tag2', + 'tag3', + 'tag5' + ), null, array(), null, null, null, 1); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new TagFilter('@wip&&@vip'); + $feature = new FeatureNode(null, null, array('wip', 'done'), null, array(), null, null, null, 1); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array('wip', 'done', 'vip'), null, array(), null, null, null, 1); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new TagFilter('@wip,@vip&&@user'); + $feature = new FeatureNode(null, null, array('wip'), null, array(), null, null, null, 1); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array('vip'), null, array(), null, null, null, 1); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array('wip', 'user'), null, array(), null, null, null, 1); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $feature = new FeatureNode(null, null, array('vip', 'user'), null, array(), null, null, null, 1); + $this->assertTrue($filter->isFeatureMatch($feature)); + } + + public function testIsScenarioMatchFilter() + { + $feature = new FeatureNode(null, null, array('feature-tag'), null, array(), null, null, null, 1); + $scenario = new ScenarioNode(null, array(), array(), null, 2); + + $filter = new TagFilter('@wip'); + $this->assertFalse($filter->isScenarioMatch($feature, $scenario)); + + $filter = new TagFilter('~@done'); + $this->assertTrue($filter->isScenarioMatch($feature, $scenario)); + + $scenario = new ScenarioNode(null, array( + 'tag1', + 'tag2', + 'tag3' + ), array(), null, 2); + $filter = new TagFilter('@tag5,@tag4,@tag6'); + $this->assertFalse($filter->isScenarioMatch($feature, $scenario)); + + $scenario = new ScenarioNode(null, array( + 'tag1', + 'tag2', + 'tag3', + 'tag5' + ), array(), null, 2); + $this->assertTrue($filter->isScenarioMatch($feature, $scenario)); + + $filter = new TagFilter('@wip&&@vip'); + $scenario = new ScenarioNode(null, array('wip', 'not-done'), array(), null, 2); + $this->assertFalse($filter->isScenarioMatch($feature, $scenario)); + + $scenario = new ScenarioNode(null, array( + 'wip', + 'not-done', + 'vip' + ), array(), null, 2); + $this->assertTrue($filter->isScenarioMatch($feature, $scenario)); + + $filter = new TagFilter('@wip,@vip&&@user'); + $scenario = new ScenarioNode(null, array( + 'wip' + ), array(), null, 2); + $this->assertFalse($filter->isScenarioMatch($feature, $scenario)); + + $scenario = new ScenarioNode(null, array('vip'), array(), null, 2); + $this->assertFalse($filter->isScenarioMatch($feature, $scenario)); + + $scenario = new ScenarioNode(null, array('wip', 'user'), array(), null, 2); + $this->assertTrue($filter->isScenarioMatch($feature, $scenario)); + + $filter = new TagFilter('@feature-tag&&@user'); + $scenario = new ScenarioNode(null, array('wip', 'user'), array(), null, 2); + $this->assertTrue($filter->isScenarioMatch($feature, $scenario)); + + $filter = new TagFilter('@feature-tag&&@user'); + $scenario = new ScenarioNode(null, array('wip'), array(), null, 2); + $this->assertFalse($filter->isScenarioMatch($feature, $scenario)); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/directories/phps/some_file.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/directories/phps/some_file.php new file mode 100644 index 0000000..e69de29 diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/addition.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/addition.yml new file mode 100644 index 0000000..7627fe6 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/addition.yml @@ -0,0 +1,29 @@ +feature: + title: Addition + language: en + line: 2 + description: |- + In order to avoid silly mistakes + As a math idiot + I want to be told the sum of two numbers + + scenarios: + - + type: scenario + title: Add two numbers + line: 7 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'I have entered 11 into the calculator', line: 8 } + - { keyword_type: 'Given', type: 'And', text: 'I have entered 12 into the calculator', line: 9 } + - { keyword_type: 'When', type: 'When', text: 'I press add', line: 10 } + - { keyword_type: 'Then', type: 'Then', text: 'the result should be 23 on the screen', line: 11 } + + - + type: scenario + title: Div two numbers + line: 13 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'I have entered 10 into the calculator', line: 14 } + - { keyword_type: 'Given', type: 'And', text: 'I have entered 2 into the calculator', line: 15 } + - { keyword_type: 'When', type: 'When', text: 'I press div', line: 16 } + - { keyword_type: 'Then', type: 'Then', text: 'the result should be 5 on the screen', line: 17 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/background.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/background.yml new file mode 100644 index 0000000..a7b1a7b --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/background.yml @@ -0,0 +1,18 @@ +feature: + title: Feature with background + language: en + line: 1 + description: ~ + + background: + line: 3 + steps: + - { keyword_type: Given, type: Given, text: a passing step, line: 4 } + + scenarios: + - + type: scenario + title: ~ + line: 6 + steps: + - { keyword_type: Given, type: Given, text: a failing step, line: 7 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/background_title.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/background_title.yml new file mode 100644 index 0000000..f69277d --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/background_title.yml @@ -0,0 +1,26 @@ +feature: + title: Feature with titled background + language: en + line: 1 + description: ~ + + background: + line: 3 + title: |- + Some Background + title with + couple + of + | continuous | + """ + strings + steps: + - { keyword_type: Given, type: Given, text: a passing step, line: 10 } + + scenarios: + - + type: scenario + title: ~ + line: 12 + steps: + - { keyword_type: Given, type: Given, text: a failing step, line: 13 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/big_pystring.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/big_pystring.yml new file mode 100644 index 0000000..4e28d66 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/big_pystring.yml @@ -0,0 +1,18 @@ +feature: + line: 1 + title: Big PyString + + scenarios: + - + type: scenario + line: 2 + steps: + - + keyword_type: Then + type: Then + text: it should fail with: + line: 3 + arguments: + - + type: pystring + text: "\n# language: ru\n\nUUUUUU\n\n2 scenarios (2 undefined)\n6 steps (6 undefined)\n\nYou can implement step definitions for undefined steps with these snippets:\n\n$steps->Given('/^I have entered (\d+)$/', function($world, $arg1) {\n throw new \Everzet\Behat\Exception\\Pending();\n});\n\n$steps->Then('/^I must have (\d+)$/', function($world, $arg1) {\n throw new \Everzet\Behat\Exception\\Pending();\n});\n\n$steps->Then('/^String must be \'([^\']*)\'$/', function($world, $arg1) {\n throw new \Everzet\Behat\Exception\\Pending();\n});" diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/clean_tags.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/clean_tags.yml new file mode 100644 index 0000000..014c8d3 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/clean_tags.yml @@ -0,0 +1,20 @@ +feature: + title: Feature N4 + line: 1 + description: ~ + + scenarios: + - + type: scenario + tags: [normal] + line: 4 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'Some normal step N41', line: 5 } + - { keyword_type: 'Given', type: 'And', text: 'Some fast step N42', line: 6 } + + - + type: scenario + tags: [fast] + line: 9 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'Some slow step N43', line: 10 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/commented_out.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/commented_out.yml new file mode 100644 index 0000000..a8a2c51 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/commented_out.yml @@ -0,0 +1,10 @@ +feature: + title: Fibonacci + language: en + line: 1 + description: |- + In order to calculate super fast fibonacci series + As a pythonista + I want to use Python for that + + scenarios: ~ diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/comments.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/comments.yml new file mode 100644 index 0000000..2ae46cb --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/comments.yml @@ -0,0 +1,21 @@ +feature: + title: Using the Console Formatter + language: en + line: 3 + description: |- + In order to verify this error # comment + + + + I want to run this feature using the progress format#comment + So that it can be fixed + + scenarios: + - + type: scenario + title: "A normal feature #comment in scenario title" + line: 19 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'I have a pending step #comment', line: 21 } + - { keyword_type: 'When', type: 'When', text: 'I run this feature with the progress format #comment', line: 24 } + - { keyword_type: 'Then', type: 'Then', text: "I should get a no method error for 'backtrace_line'", line: 31 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/complex_descriptions.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/complex_descriptions.yml new file mode 100644 index 0000000..d0d65dc --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/complex_descriptions.yml @@ -0,0 +1,26 @@ +feature: + title: Complex descriptions + language: en + line: 7 + description: |- + Some description with + | table | row| + + and + + """ + """ + + scenarios: + - + type: scenario + title: |- + Some + | complex | description | + + """ + hell yeah + """ + line: 16 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'one two three', line: 22 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty.yml new file mode 100644 index 0000000..e13f363 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty.yml @@ -0,0 +1,7 @@ +feature: + title: Some feature + language: en + line: 1 + description: ~ + + scenarios: [] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty_scenario.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty_scenario.yml new file mode 100644 index 0000000..43e7201 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty_scenario.yml @@ -0,0 +1,13 @@ +feature: + title: Cucumber command line + language: en + line: 1 + description: |- + In order to write better software + Developers should be able to execute requirements as tests + + scenarios: + - + type: scenario + title: Pending Scenario at the end of a file with whitespace after it + line: 6 diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty_scenario_without_linefeed.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty_scenario_without_linefeed.yml new file mode 100644 index 0000000..43e7201 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty_scenario_without_linefeed.yml @@ -0,0 +1,13 @@ +feature: + title: Cucumber command line + language: en + line: 1 + description: |- + In order to write better software + Developers should be able to execute requirements as tests + + scenarios: + - + type: scenario + title: Pending Scenario at the end of a file with whitespace after it + line: 6 diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty_scenarios.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty_scenarios.yml new file mode 100644 index 0000000..35a144b --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/empty_scenarios.yml @@ -0,0 +1,30 @@ +feature: + title: Math + language: en + line: 1 + description: |- + In order to avoid silly mistakes + As a math idiot + I want to be told the calculation of two numbers + + scenarios: + - + type: scenario + title: Add two numbers + line: 6 + steps: [] + - + type: scenario + title: Div two numbers + line: 7 + steps: [] + - + type: scenario + title: Multiply two numbers + line: 9 + steps: [] + - + type: scenario + title: Sub two numbers + line: 12 + steps: [] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/fibonacci.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/fibonacci.yml new file mode 100644 index 0000000..c450a8b --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/fibonacci.yml @@ -0,0 +1,27 @@ +feature: + title: Fibonacci + language: en + line: 1 + description: |- + In order to calculate super fast fibonacci series + As a pythonista + I want to use Python for that + + scenarios: + - + type: outline + title: Series + line: 6 + steps: + - { keyword_type: 'When', type: 'When', text: 'I ask python to calculate fibonacci up to ', line: 7 } + - { keyword_type: 'Then', type: 'Then', text: 'it should give me ', line: 8 } + + examples: + 11: [ n , series ] + 12: [ 1 , '[]' ] + 13: [ 2 , '[1, 1]' ] + 14: [ 3 , '[1, 1, 2]' ] + 15: [ 4 , '[1, 1, 2, 3]' ] + 16: [ 6 , '[1, 1, 2, 3, 5]' ] + 17: [ 9 , '[1, 1, 2, 3, 5, 8]' ] + 18: [ 100 , '[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]' ] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/hashes_in_quotes.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/hashes_in_quotes.yml new file mode 100644 index 0000000..55abe3b --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/hashes_in_quotes.yml @@ -0,0 +1,29 @@ +feature: + title: "Some '#quoted' string" + language: en + line: 2 + description: |- + In order to avoid silly mistakes + As a "#math" idiot + I want to be told the sum of two numbers + + scenarios: + - + type: scenario + title: Add two numbers + line: 7 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'I have entered 11 into the calculator', line: 8 } + - { keyword_type: 'Given', type: 'And', text: 'I have entered 12 into the calculator', line: 9 } + - { keyword_type: 'When', type: 'When', text: 'I press "#add"', line: 10 } + - { keyword_type: 'Then', type: 'Then', text: 'the result should be 23 on the screen', line: 11 } + + - + type: scenario + title: 'Div "#two" numbers # as' + line: 13 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'I have entered 10 into the calculator', line: 14 } + - { keyword_type: 'Given', type: 'And', text: 'I have entered # 2 into the calculator', line: 15 } + - { keyword_type: 'When', type: 'When', text: 'I press div', line: 16 } + - { keyword_type: 'Then', type: 'Then', text: 'the result should be 5 on the screen', line: 17 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/issue_13.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/issue_13.yml new file mode 100644 index 0000000..091103c --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/issue_13.yml @@ -0,0 +1,49 @@ +feature: + title: test pystring + description: second line + language: en + line: 1 + + scenarios: + - + type: scenario + title: |- + testing py string in scenario + second line + line: 4 + steps: + - + keyword_type: Given + type: Given + text: the pystring is + line: 7 + arguments: + - + type: pystring + text: |- + Test store name + Denmark, Kolding + 6000 + + - + type: outline + title: |- + testing py string in scenario outline + second line + line: 14 + steps: + - + keyword_type: Given + type: Given + text: the pystring is + line: 17 + arguments: + arguments: + - + type: pystring + text: |- + Test store name + Denmark, Kolding + 6000 + examples: + 24: [''] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ja_addition.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ja_addition.yml new file mode 100644 index 0000000..d56aa44 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ja_addition.yml @@ -0,0 +1,21 @@ +feature: + title: '加算' + keyword: 'フィーチャ' + language: ja + line: 2 + description: |- + バカな間違いを避けるために + 数学オンチとして + 2つの数の合計を知りたい + + scenarios: + - + type: scenario + keyword: 'シナリオ' + title: '2つの数の加算について' + line: 7 + steps: + - { keyword_type: 'Given', type: '前提', type: '前提', text: '50 を入力', line: 8 } + - { keyword_type: 'Given', type: 'かつ', type: 'かつ', text: '70 を入力', line: 9 } + - { keyword_type: 'When', type: 'もし', type: 'もし', text: 'add ボタンを押した', line: 10 } + - { keyword_type: 'Then', type: 'ならば', type: 'ならば', text: '結果は 120 を表示', line: 11 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/long_title_feature.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/long_title_feature.yml new file mode 100644 index 0000000..7e30cf5 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/long_title_feature.yml @@ -0,0 +1,13 @@ +feature: + title: https://rspec.lighthouseapp.com/projects/16211/tickets/246-distorted-console-output-for-slightly-complicated-step-regexp-match + language: en + line: 1 + description: ~ + + scenarios: + - + type: scenario + title: See "No Record(s) Found" for Zero Existing + line: 3 + steps: + - { keyword_type: Given, type: Given, text: no public holiday exists in the system, line: 4 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/multiline_name.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/multiline_name.yml new file mode 100644 index 0000000..b41bc58 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/multiline_name.yml @@ -0,0 +1,44 @@ +feature: + title: multiline + language: en + line: 1 + description: ~ + + background: + line: 3 + steps: + - { keyword_type: Given, type: Given, text: passing without a table, line: 4 } + + scenarios: + - + type: scenario + title: |- + I'm a multiline name + which goes on and on and on for three lines + yawn + line: 6 + steps: + - { keyword_type: Given, type: Given, text: passing without a table, line: 9 } + + - + type: outline + title: |- + I'm a multiline name + which goes on and on and on for three lines + yawn + line: 11 + steps: + - { keyword_type: Given, type: 'Given', text: ' without a table', line: 14 } + examples: + 16: [state] + 17: [passing] + + - + type: outline + title: name + line: 19 + steps: + - { keyword_type: Given, type: 'Given', text: ' without a table', line: 20 } + examples: + 22: [state] + 23: [passing] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/multiline_name_with_newlines.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/multiline_name_with_newlines.yml new file mode 100644 index 0000000..d7aebc0 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/multiline_name_with_newlines.yml @@ -0,0 +1,65 @@ +feature: + title: multiline + language: en + line: 1 + description: |- + + Feature description + + With etc. + + background: + line: 8 + steps: + - { keyword_type: Given, type: Given, text: passing without a table, line: 11 } + + scenarios: + - + type: scenario + title: |- + + I'm a multiline name + which goes on and on and on for three lines + yawn + line: 13 + steps: + - { keyword_type: Given, type: Given, text: passing without a table, line: 19 } + + - + type: outline + title: |- + I'm a multiline name + + which goes on and on and on for three lines + + yawn + line: 21 + steps: + - { keyword_type: 'Given', type: 'Given', text: ' without a table', line: 28 } + examples: + 34: [state] + 35: [passing] + + - + type: outline + title: name + line: 37 + steps: + - { keyword_type: 'Given', type: 'Given', text: ' without a table', line: 40 } + examples: + 45: [state] + 46: [passing] + - + type: outline + title: |- + + + I'm a multiline name + which goes on and on and on for three lines + yawn + line: 48 + steps: + - { keyword_type: 'Given', type: 'Given', text: ' without a table', line: 55 } + examples: + 60: [state] + 61: [passing] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/multiplepystrings.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/multiplepystrings.yml new file mode 100644 index 0000000..6c73bba --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/multiplepystrings.yml @@ -0,0 +1,47 @@ +feature: + title: A multiple py string feature + line: 1 + language: en + description: ~ + + scenarios: + - + type: scenario + title: ~ + line: 3 + steps: + - + keyword_type: When + type: When + text: I enter a string + line: 4 + arguments: + - + type: pystring + text: |- + - + a string + with something + be + a + u + ti + ful + + - + keyword_type: Then + type: Then + text: String must be + line: 15 + arguments: + - + type: pystring + text: |- + - + a string + with something + be + a + u + ti + ful diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/outline_with_spaces.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/outline_with_spaces.yml new file mode 100644 index 0000000..c6e8977 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/outline_with_spaces.yml @@ -0,0 +1,33 @@ +feature: + title: Login + language: en + line: 1 + description: |- + To ensure the safety of the application + A regular user of the system + Must authenticate before using the app + + scenarios: + - + type: outline + title: Failed Login + line: 7 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'the user "known_user"', line: 8 } + - { keyword_type: 'When', type: 'When', text: 'I go to the main page', line: 10 } + - { keyword_type: 'Then', type: 'Then', text: 'I should see the login form', line: 11 } + - { keyword_type: 'When', type: 'When', text: 'I fill in "login" with ""', line: 13 } + - { keyword_type: 'When', type: 'And', text: 'I fill in "password" with ""', line: 14 } + - { keyword_type: 'When', type: 'And', text: 'I press "Log In"', line: 15 } + - { keyword_type: 'Then', type: 'Then', text: 'the login request should fail', line: 16 } + - { keyword_type: 'Then', type: 'And', text: 'I should see the error message "Login or Password incorrect"', line: 17 } + examples: + 20: [login, password] + 21: ['', ''] + 22: [unknown_user, ''] + 23: [known_user, ''] + 24: ['', wrong_password] + 25: ['', known_userpass] + 26: [unknown_user, wrong_password] + 27: [unknown_user, known_userpass] + 28: [known_user, wrong_password] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/outline_with_step_table.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/outline_with_step_table.yml new file mode 100644 index 0000000..8c59ff1 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/outline_with_step_table.yml @@ -0,0 +1,29 @@ +feature: + title: Unsubstituted argument placeholder + language: en + line: 1 + description: ~ + + scenarios: + - + type: outline + title: 'See Annual Leave Details (as Management & Human Resource)' + line: 3 + steps: + - + keyword_type: Given + type: Given + text: the following users exist in the system + line: 4 + arguments: + - + type: table + rows: + 5: [ name, email, role_assignments, group_memberships ] + 6: [ Jane, jane@fmail.com, , Sales (manager) ] + 7: [ Max, max@fmail.com, '', Sales (member) ] + 8: [ Carol, carol@fmail.com, '', Sales (member) ] + 9: [ Cat, cat@fmail.com, '', '' ] + examples: + 12: [ role ] + 13: [ HUMAN RESOURCE ] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/pystring.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/pystring.yml new file mode 100644 index 0000000..bc21a9a --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/pystring.yml @@ -0,0 +1,22 @@ +feature: + title: A py string feature + language: en + line: 1 + description: ~ + + scenarios: + - + type: scenario + title: ~ + line: 3 + steps: + - + keyword_type: Then + type: Then + text: I should see + line: 4 + arguments: + - + type: pystring + swallow: 6 + text: "a string with #something" diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_addition.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_addition.yml new file mode 100644 index 0000000..9c0db4a --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_addition.yml @@ -0,0 +1,21 @@ +feature: + title: Сложение чисел + keyword: Функционал + language: ru + line: 2 + description: |- + Чтобы не складывать в уме + Все, у кого с этим туго + Хотят автоматическое сложение целых чисел + + scenarios: + - + type: scenario + keyword: Сценарий + title: Сложение двух целых чисел + line: 7 + steps: + - { keyword_type: 'Given', type: 'Допустим', text: 'я ввожу число 50', line: 8 } + - { keyword_type: 'Given', type: 'И', text: 'затем ввожу число 70', line: 9 } + - { keyword_type: 'Then', type: 'Если', text: 'я нажимаю "+"', line: 10 } + - { keyword_type: 'When', type: 'То', text: 'результатом должно быть число 120', line: 11 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_commented.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_commented.yml new file mode 100644 index 0000000..1097d5d --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_commented.yml @@ -0,0 +1,11 @@ +feature: + title: Тест комментов + keyword: Функционал + language: ru + line: 7 + description: |- + i18n должен правильно считываться + Даже если в начале файла 1000 + комментов! + + scenarios: ~ diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_consecutive_calculations.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_consecutive_calculations.yml new file mode 100644 index 0000000..358d867 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_consecutive_calculations.yml @@ -0,0 +1,34 @@ +feature: + title: Последовательные вычисления + keyword: Функционал + language: ru + line: 2 + description: |- + Чтобы вычислять сложные выражения + Пользователи хотят проводить вычисления над результатом предыдущей операций + + background: + keyword: Предыстория + line: 6 + steps: + - { keyword_type: Given, type: Допустим, text: я сложил 3 и 5, line: 7 } + + scenarios: + - + type: scenario + keyword: Сценарий + title: сложение с результатом последней операций + line: 9 + steps: + - { keyword_type: Then, type: Если, text: 'я ввожу число 4', line: 10 } + - { keyword_type: Then, type: И, text: 'нажимаю "+"', line: 11 } + - { keyword_type: When, type: То, text: 'результатом должно быть число 12', line: 12 } + - + type: scenario + keyword: Сценарий + title: деление результата последней операции + line: 14 + steps: + - { keyword_type: Then, type: Если, text: 'я ввожу число 2', line: 15 } + - { keyword_type: Then, type: И, text: 'нажимаю "/"', line: 16 } + - { keyword_type: When, type: То, text: 'результатом должно быть число 4', line: 17 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_division.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_division.yml new file mode 100644 index 0000000..b4d3005 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/ru_division.yml @@ -0,0 +1,27 @@ +feature: + title: Деление чисел + keyword: Функционал + language: ru + line: 2 + description: |- + Поскольку деление сложный процесс и люди часто допускают ошибки + Нужно дать им возможность делить на калькуляторе + + scenarios: + - + type: outline + keyword: Структура сценария + title: Целочисленное деление + line: 6 + steps: + - { keyword_type: Given, type: 'Допустим', text: 'я ввожу число <делимое>', line: 7 } + - { keyword_type: Given, type: 'И', text: 'затем ввожу число <делитель>', line: 8 } + - { keyword_type: Then, type: 'Если', text: 'я нажимаю "/"', line: 9 } + - { keyword_type: When, type: 'То', text: 'результатом должно быть число <частное>', line: 10 } + + examples: + keyword: Значения + 13: [делимое, делитель, частное] + 14: [100, 2, 50] + 15: [28, 7, 4] + 16: [0, 5, 0] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/start_comments.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/start_comments.yml new file mode 100644 index 0000000..45fcd77 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/start_comments.yml @@ -0,0 +1,18 @@ +feature: + title: Using the Console Formatter + language: en + line: 3 + description: |- + In order to verify this error + I want to run this feature using the progress format + So that it can be fixed + + scenarios: + - + type: scenario + title: A normal feature + line: 8 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'I have a pending step', line: 9 } + - { keyword_type: 'When', type: 'When', text: 'I run this feature with the progress format', line: 10 } + - { keyword_type: 'Then', type: 'Then', text: "I should get a no method error for 'backtrace_line'", line: 11 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/tables.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/tables.yml new file mode 100644 index 0000000..dfe7bd5 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/tables.yml @@ -0,0 +1,42 @@ +feature: + title: A scenario outline + language: en + line: 1 + description: ~ + + scenarios: + - + type: outline + title: ~ + line: 3 + steps: + - { keyword_type: Given, type: Given, text: I add and , line: 4 } + - + keyword_type: When + type: When + text: I pass a table argument + line: 6 + arguments: + - + type: table + rows: + 7: [foo, bar] + 8: [bar, baz] + - { keyword_type: Then, type: Then, text: I the result should be , line: 10 } + - + keyword_type: Then + type: And + text: the table should be properly escaped: + line: 12 + arguments: + - + type: table + rows: + 13: [|a, b, c] + 14: [1, |2, 3] + 15: [2, 3, |4] + + examples: + 18: [ a, b, c ] + 19: [ 1, |2, 3 ] + 20: [ 2, 3, 4 ] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/tags_sample.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/tags_sample.yml new file mode 100644 index 0000000..486d958 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/tags_sample.yml @@ -0,0 +1,35 @@ +feature: + title: Tag samples + language: en + tags: [sample_one] + line: 2 + description: ~ + + scenarios: + - + type: scenario + title: Passing + tags: [sample_two, sample_four] + line: 5 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'missing', line: 6 } + + - + type: outline + title: ~ + tags: [sample_three] + line: 9 + steps: + - { keyword_type: 'Given', type: 'Given', text: '', line: 10 } + + examples: + 12: [state] + 13: [missing] + + - + type: scenario + title: Skipped + tags: [sample_three, sample_four] + line: 16 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'missing', line: 17 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/test_unit.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/test_unit.yml new file mode 100644 index 0000000..fca7e20 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/test_unit.yml @@ -0,0 +1,18 @@ +feature: + title: Test::Unit + language: en + line: 1 + description: |- + In order to please people who like Test::Unit + As a Cucumber user + I want to be able to use assert* in my step definitions + + scenarios: + - + type: scenario + title: assert_equal + line: 6 + steps: + - { keyword_type: 'Given', type: 'Given', text: 'x = 5', line: 7 } + - { keyword_type: 'Given', type: 'And', text: 'y = 5', line: 8 } + - { keyword_type: 'Then', type: 'Then', text: 'I can assert that x == y', line: 9 } diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/trimpystring.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/trimpystring.yml new file mode 100644 index 0000000..3857fdf --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/trimpystring.yml @@ -0,0 +1,29 @@ +feature: + title: A py string feature + language: en + line: 1 + description: ~ + + scenarios: + - + type: scenario + title: ~ + line: 3 + steps: + - + keyword_type: Then + type: Then + text: String must be + line: 4 + arguments: + - + type: pystring + text: |- + - + a string + with something + be + a + u + ti + ful diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/undefined_multiline_args.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/undefined_multiline_args.yml new file mode 100644 index 0000000..84cb8ff --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/etalons/undefined_multiline_args.yml @@ -0,0 +1,38 @@ +feature: + title: undefined multiline args + language: en + line: 1 + description: ~ + + scenarios: + - + type: scenario + title: pystring + line: 3 + steps: + - + keyword_type: Given + type: Given + text: a pystring + line: 4 + arguments: + - + type: pystring + text: ' example' + + - + type: scenario + title: table + line: 9 + steps: + - + keyword_type: Given + type: Given + text: a table + line: 10 + arguments: + - + type: table + rows: + 11: [table] + 12: [example] diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/addition.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/addition.feature new file mode 100644 index 0000000..744184f --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/addition.feature @@ -0,0 +1,17 @@ +# language: en +Feature: Addition + In order to avoid silly mistakes + As a math idiot + I want to be told the sum of two numbers + + Scenario: Add two numbers + Given I have entered 11 into the calculator + And I have entered 12 into the calculator + When I press add + Then the result should be 23 on the screen + + Scenario: Div two numbers + Given I have entered 10 into the calculator + And I have entered 2 into the calculator + When I press div + Then the result should be 5 on the screen diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/background.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/background.feature new file mode 100644 index 0000000..9a3ffb8 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/background.feature @@ -0,0 +1,7 @@ +Feature: Feature with background + + Background: + Given a passing step + + Scenario: + Given a failing step \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/background_title.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/background_title.feature new file mode 100644 index 0000000..d8ed4d3 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/background_title.feature @@ -0,0 +1,13 @@ +Feature: Feature with titled background + + Background: Some Background + title with + couple + of + | continuous | + """ + strings + Given a passing step + + Scenario: + Given a failing step diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/big_pystring.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/big_pystring.feature new file mode 100644 index 0000000..900d6c7 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/big_pystring.feature @@ -0,0 +1,26 @@ +Feature: Big PyString + Scenario: + Then it should fail with: + """ + + # language: ru + + UUUUUU + + 2 scenarios (2 undefined) + 6 steps (6 undefined) + + You can implement step definitions for undefined steps with these snippets: + + $steps->Given('/^I have entered (\d+)$/', function($world, $arg1) { + throw new \Everzet\Behat\Exception\Pending(); + }); + + $steps->Then('/^I must have (\d+)$/', function($world, $arg1) { + throw new \Everzet\Behat\Exception\Pending(); + }); + + $steps->Then('/^String must be \'([^\']*)\'$/', function($world, $arg1) { + throw new \Everzet\Behat\Exception\Pending(); + }); + """ diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/clean_tags.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/clean_tags.feature new file mode 100644 index 0000000..e3e9cc7 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/clean_tags.feature @@ -0,0 +1,10 @@ +Feature: Feature N4 + + @normal + Scenario: + Given Some normal step N41 + And Some fast step N42 + + @fast + Scenario: + Given Some slow step N43 diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/commented_out.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/commented_out.feature new file mode 100644 index 0000000..61d7bef --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/commented_out.feature @@ -0,0 +1,34 @@ +Feature: Fibonacci + In order to calculate super fast fibonacci series + As a pythonista + I want to use Python for that + +# +# Background: +# Given passing without a table +# +# Scenario: I'm a multiline name +# which goes on and on and on for three lines +# yawn +# Given passing without a table +# +# Scenario: +# Then I should see +# """ +# a string with #something +# """ +# +# Scenario Outline: Series +# When I ask python to calculate fibonacci up to +# Then it should give me +# +# Examples: +# | n | series | +# | 1 | [] | +# | 2 | [1, 1] | +# | 3 | [1, 1, 2] | +# | 4 | [1, 1, 2, 3] | +# | 6 | [1, 1, 2, 3, 5] | +# | 9 | [1, 1, 2, 3, 5, 8] | +# | 100 | [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] | +# diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/comments.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/comments.feature new file mode 100644 index 0000000..02ca25c --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/comments.feature @@ -0,0 +1,32 @@ +# Users want to use cucumber, so tests are necessary to verify +# it is all working as expected +Feature: Using the Console Formatter +# com +# comment +#com + In order to verify this error # comment + + + + I want to run this feature using the progress format#comment + # COMMENT + # COMMENT + # COMMENT + # COMMENT + So that it can be fixed + + #comment + Scenario: A normal feature #comment in scenario title + #comment + Given I have a pending step #comment + #comment + #comment + When I run this feature with the progress format #comment + + +#comment + #comment + #comment + + Then I should get a no method error for 'backtrace_line' + diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/complex_descriptions.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/complex_descriptions.feature new file mode 100644 index 0000000..4db3b87 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/complex_descriptions.feature @@ -0,0 +1,22 @@ +# language: en + +# multiline +# comment +# YEAH + +Feature: Complex descriptions + Some description with + | table | row| + + and + + """ + """ + + Scenario: Some + | complex | description | + +""" +hell yeah +""" +Given one two three diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty.feature new file mode 100644 index 0000000..8a560d7 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty.feature @@ -0,0 +1,2 @@ +Feature: Some feature +# \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty_scenario.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty_scenario.feature new file mode 100644 index 0000000..6c661c1 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty_scenario.feature @@ -0,0 +1,7 @@ +Feature: Cucumber command line + In order to write better software + Developers should be able to execute requirements as tests + + + Scenario: Pending Scenario at the end of a file with whitespace after it + diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty_scenario_without_linefeed.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty_scenario_without_linefeed.feature new file mode 100644 index 0000000..7e17ff2 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty_scenario_without_linefeed.feature @@ -0,0 +1,7 @@ +Feature: Cucumber command line + In order to write better software + Developers should be able to execute requirements as tests + + + Scenario: Pending Scenario at the end of a file with whitespace after it + # \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty_scenarios.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty_scenarios.feature new file mode 100644 index 0000000..f17bef5 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/empty_scenarios.feature @@ -0,0 +1,12 @@ +Feature: Math + In order to avoid silly mistakes + As a math idiot + I want to be told the calculation of two numbers + + Scenario: Add two numbers + Scenario: Div two numbers + + Scenario: Multiply two numbers + + + Scenario: Sub two numbers diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/fibonacci.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/fibonacci.feature new file mode 100644 index 0000000..4a743ea --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/fibonacci.feature @@ -0,0 +1,19 @@ +Feature: Fibonacci + In order to calculate super fast fibonacci series + As a pythonista + I want to use Python for that + + Scenario Outline: Series + When I ask python to calculate fibonacci up to + Then it should give me + + Examples: + | n | series | + | 1 | [] | + | 2 | [1, 1] | + | 3 | [1, 1, 2] | + | 4 | [1, 1, 2, 3] | + | 6 | [1, 1, 2, 3, 5] | + | 9 | [1, 1, 2, 3, 5, 8] | + | 100 | [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] | + diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/hashes_in_quotes.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/hashes_in_quotes.feature new file mode 100644 index 0000000..e08fa70 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/hashes_in_quotes.feature @@ -0,0 +1,17 @@ +# language: en +Feature: Some '#quoted' string + In order to avoid silly mistakes + As a "#math" idiot + I want to be told the sum of two numbers + + Scenario: Add two numbers + Given I have entered 11 into the calculator + And I have entered 12 into the calculator + When I press "#add" + Then the result should be 23 on the screen + + Scenario: Div "#two" numbers # as + Given I have entered 10 into the calculator + And I have entered # 2 into the calculator + When I press div + Then the result should be 5 on the screen diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/issue_13.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/issue_13.feature new file mode 100644 index 0000000..4218a97 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/issue_13.feature @@ -0,0 +1,24 @@ +Feature: test pystring +second line + +Scenario: testing py string in scenario +second line + +Given the pystring is +""" +Test store name +Denmark, Kolding +6000 +""" + +Scenario Outline: testing py string in scenario outline +second line + +Given the pystring is +""" +Test store name +Denmark, Kolding +6000 +""" + Examples: + || diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ja_addition.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ja_addition.feature new file mode 100644 index 0000000..b843852 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ja_addition.feature @@ -0,0 +1,11 @@ +# language: ja +フィーチャ: 加算 + バカな間違いを避けるために + 数学オンチとして + 2つの数の合計を知りたい + + シナリオ: 2つの数の加算について + 前提 50 を入力 + かつ 70 を入力 + もし add ボタンを押した + ならば結果は 120 を表示 \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/long_title_feature.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/long_title_feature.feature new file mode 100644 index 0000000..a93cb4d --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/long_title_feature.feature @@ -0,0 +1,4 @@ +Feature: https://rspec.lighthouseapp.com/projects/16211/tickets/246-distorted-console-output-for-slightly-complicated-step-regexp-match + +Scenario: See "No Record(s) Found" for Zero Existing + Given no public holiday exists in the system diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/multiline_name.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/multiline_name.feature new file mode 100644 index 0000000..95b9d55 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/multiline_name.feature @@ -0,0 +1,23 @@ +Feature: multiline + + Background: + Given passing without a table + + Scenario: I'm a multiline name + which goes on and on and on for three lines + yawn + Given passing without a table + + Scenario Outline: I'm a multiline name + which goes on and on and on for three lines + yawn + Given without a table + Examples: + | state | + |passing| + + Scenario Outline: name + Given without a table + Examples: + | state | + |passing| diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/multiline_name_with_newlines.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/multiline_name_with_newlines.feature new file mode 100644 index 0000000..bfc3e06 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/multiline_name_with_newlines.feature @@ -0,0 +1,61 @@ +Feature: multiline + + Feature description + + With etc. + + + Background: + + + Given passing without a table + + Scenario: + I'm a multiline name + which goes on and on and on for three lines + yawn + + + Given passing without a table + + Scenario Outline: I'm a multiline name + + which goes on and on and on for three lines + + yawn + + + Given without a table + + + Examples: + + + | state | + |passing| + + Scenario Outline: name + + + Given without a table + + + Examples: + + | state | + |passing| + + Scenario Outline: + + I'm a multiline name + which goes on and on and on for three lines + yawn + + + Given without a table + + + Examples: + + | state | + |passing| diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/multiplepystrings.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/multiplepystrings.feature new file mode 100644 index 0000000..f5526af --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/multiplepystrings.feature @@ -0,0 +1,25 @@ +Feature: A multiple py string feature + + Scenario: + When I enter a string + """ +- + a string + with something + be + a + u + ti + ful + """ + Then String must be + """ +- + a string + with something + be + a + u + ti + ful + """ diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/outline_with_spaces.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/outline_with_spaces.feature new file mode 100644 index 0000000..e587faa --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/outline_with_spaces.feature @@ -0,0 +1,28 @@ +Feature: Login + To ensure the safety of the application + A regular user of the system + Must authenticate before using the app + + + Scenario Outline: Failed Login + Given the user "known_user" + + When I go to the main page + Then I should see the login form + + When I fill in "login" with "" + And I fill in "password" with "" + And I press "Log In" + Then the login request should fail + And I should see the error message "Login or Password incorrect" + + Examples: + | login | password | + | | | + | unknown_user | | + | known_user | | + | | wrong_password | + | | known_userpass | + | unknown_user | wrong_password | + | unknown_user | known_userpass | + | known_user | wrong_password | diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/outline_with_step_table.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/outline_with_step_table.feature new file mode 100644 index 0000000..9d31771 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/outline_with_step_table.feature @@ -0,0 +1,13 @@ +Feature: Unsubstituted argument placeholder + + Scenario Outline: See Annual Leave Details (as Management & Human Resource) + Given the following users exist in the system + | name | email | role_assignments | group_memberships | + | Jane | jane@fmail.com | | Sales (manager) | + | Max | max@fmail.com | | Sales (member) | + | Carol | carol@fmail.com | | Sales (member) | + | Cat | cat@fmail.com | | | + + Examples: + | role | + | HUMAN RESOURCE | diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/pystring.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/pystring.feature new file mode 100644 index 0000000..601373f --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/pystring.feature @@ -0,0 +1,8 @@ +Feature: A py string feature + + Scenario: + Then I should see + """ + a string with #something + """ + \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_addition.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_addition.feature new file mode 100644 index 0000000..eda5722 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_addition.feature @@ -0,0 +1,11 @@ +# language: ru +Функционал: Сложение чисел + Чтобы не складывать в уме + Все, у кого с этим туго + Хотят автоматическое сложение целых чисел + + Сценарий: Сложение двух целых чисел + Допустим я ввожу число 50 + И затем ввожу число 70 + Если я нажимаю "+" + То результатом должно быть число 120 \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_commented.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_commented.feature new file mode 100644 index 0000000..36cbd05 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_commented.feature @@ -0,0 +1,10 @@ +# Comments +# comments +# COOOOOMMEEEENTS +# +# language: ru + +Функционал: Тест комментов + i18n должен правильно считываться + Даже если в начале файла 1000 + комментов! diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_consecutive_calculations.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_consecutive_calculations.feature new file mode 100644 index 0000000..87cc7f2 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_consecutive_calculations.feature @@ -0,0 +1,17 @@ +# language: ru +Функционал: Последовательные вычисления + Чтобы вычислять сложные выражения + Пользователи хотят проводить вычисления над результатом предыдущей операций + + Предыстория: + Допустим я сложил 3 и 5 + + Сценарий: сложение с результатом последней операций + Если я ввожу число 4 + И нажимаю "+" + То результатом должно быть число 12 + + Сценарий: деление результата последней операции + Если я ввожу число 2 + И нажимаю "/" + То результатом должно быть число 4 \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_division.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_division.feature new file mode 100644 index 0000000..7f024f6 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/ru_division.feature @@ -0,0 +1,16 @@ +# language: ru +Функционал: Деление чисел + Поскольку деление сложный процесс и люди часто допускают ошибки + Нужно дать им возможность делить на калькуляторе + + Структура сценария: Целочисленное деление + Допустим я ввожу число <делимое> + И затем ввожу число <делитель> + Если я нажимаю "/" + То результатом должно быть число <частное> + + Значения: + | делимое | делитель | частное | + | 100 | 2 | 50 | + | 28 | 7 | 4 | + | 0 | 5 | 0 | \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/start_comments.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/start_comments.feature new file mode 100644 index 0000000..45dd501 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/start_comments.feature @@ -0,0 +1,12 @@ +# Users want to use cucumber, so tests are necessary to verify +# it is all working as expected +Feature: Using the Console Formatter + In order to verify this error + I want to run this feature using the progress format + So that it can be fixed + + Scenario: A normal feature + Given I have a pending step + When I run this feature with the progress format + Then I should get a no method error for 'backtrace_line' + diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/tables.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/tables.feature new file mode 100644 index 0000000..92f4c78 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/tables.feature @@ -0,0 +1,20 @@ +Feature: A scenario outline + # COMMENT + Scenario Outline: + Given I add and + # comment + When I pass a table argument + | foo | bar | + | bar | baz | + #comment + Then I the result should be + # comment + And the table should be properly escaped: + | \|a | b | c | + | 1 | \|2 | 3 | + | 2 | 3 | \|4 | +#comment + Examples: + | a | b | c | + | 1 | \|2 | 3 | + | 2 | 3 | 4 | diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/tags_sample.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/tags_sample.feature new file mode 100644 index 0000000..21eaaab --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/tags_sample.feature @@ -0,0 +1,17 @@ +@sample_one +Feature: Tag samples + + @sample_two @sample_four + Scenario: Passing + Given missing + + @sample_three + Scenario Outline: + Given + Examples: + |state| + |missing| + + @sample_three @sample_four + Scenario: Skipped + Given missing \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/test_unit.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/test_unit.feature new file mode 100644 index 0000000..ed08ba4 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/test_unit.feature @@ -0,0 +1,9 @@ +Feature: Test::Unit + In order to please people who like Test::Unit + As a Cucumber user + I want to be able to use assert* in my step definitions + + Scenario: assert_equal + Given x = 5 + And y = 5 + Then I can assert that x == y diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/trimpystring.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/trimpystring.feature new file mode 100644 index 0000000..4e04950 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/trimpystring.feature @@ -0,0 +1,14 @@ +Feature: A py string feature + + Scenario: + Then String must be + """ + - + a string + with something + be + a + u + ti + ful + """ diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/undefined_multiline_args.feature b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/undefined_multiline_args.feature new file mode 100644 index 0000000..ae3c732 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/features/undefined_multiline_args.feature @@ -0,0 +1,12 @@ +Feature: undefined multiline args + + Scenario: pystring + Given a pystring + """ + example + """ + + Scenario: table + Given a table + | table | + |example| \ No newline at end of file diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/i18n.yml b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/i18n.yml new file mode 100644 index 0000000..398c60c --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Fixtures/i18n.yml @@ -0,0 +1,606 @@ + +# +# !!! DON'T TOUCH THIS FILE, IT WAS AUTODOWNLOADED FROM: +# https://github.com/cucumber/gherkin/blob/master/lib/gherkin/i18n.yml +# + +# encoding: UTF-8 +# +# We use ISO 639-1 (language) and ISO 3166 alpha-2 (region - if applicable): +# http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes +# http://en.wikipedia.org/wiki/ISO_3166-1 +# +# If you want several aliases for a keyword, just separate them +# with a | character. The * is a step keyword alias for all translations. +# +# If you do *not* want a trailing space after a keyword, end it with a < character. +# (See Chinese for examples). +# +"en": + name: English + native: English + feature: Feature + background: Background + scenario: Scenario + scenario_outline: Scenario Outline|Scenario Template + examples: Examples|Scenarios + given: "*|Given" + when: "*|When" + then: "*|Then" + and: "*|And" + but: "*|But" + +# Please keep the grammars in alphabetical order by name from here and down. + +"ar": + name: Arabic + native: العربية + feature: خاصية + background: الخلفية + scenario: سيناريو + scenario_outline: سيناريو مخطط + examples: امثلة + given: "*|بفرض" + when: "*|متى|عندما" + then: "*|اذاً|ثم" + and: "*|و" + but: "*|لكن" +"bg": + name: Bulgarian + native: български + feature: Функционалност + background: Предистория + scenario: Сценарий + scenario_outline: Рамка на сценарий + examples: Примери + given: "*|Дадено" + when: "*|Когато" + then: "*|То" + and: "*|И" + but: "*|Но" +"ca": + name: Catalan + native: català + background: Rerefons|Antecedents + feature: Característica|Funcionalitat + scenario: Escenari + scenario_outline: Esquema de l'escenari + examples: Exemples + given: "*|Donat|Donada|Atès|Atesa" + when: "*|Quan" + then: "*|Aleshores|Cal" + and: "*|I" + but: "*|Però" +"cy-GB": + name: Welsh + native: Cymraeg + background: Cefndir + feature: Arwedd + scenario: Scenario + scenario_outline: Scenario Amlinellol + examples: Enghreifftiau + given: "*|Anrhegedig a" + when: "*|Pryd" + then: "*|Yna" + and: "*|A" + but: "*|Ond" +"cs": + name: Czech + native: Česky + feature: Požadavek + background: Pozadí|Kontext + scenario: Scénář + scenario_outline: Náčrt Scénáře|Osnova scénáře + examples: Příklady + given: "*|Pokud" + when: "*|Když" + then: "*|Pak" + and: "*|A také|A" + but: "*|Ale" +"da": + name: Danish + native: dansk + feature: Egenskab + background: Baggrund + scenario: Scenarie + scenario_outline: Abstrakt Scenario + examples: Eksempler + given: "*|Givet" + when: "*|Når" + then: "*|Så" + and: "*|Og" + but: "*|Men" +"de": + name: German + native: Deutsch + feature: Funktionalität + background: Grundlage + scenario: Szenario + scenario_outline: Szenariogrundriss + examples: Beispiele + given: "*|Angenommen|Gegeben sei" + when: "*|Wenn" + then: "*|Dann" + and: "*|Und" + but: "*|Aber" +"en-au": + name: Australian + native: Australian + feature: Crikey + background: Background + scenario: Mate + scenario_outline: Blokes + examples: Cobber + given: "*|Ya know how" + when: "*|When" + then: "*|Ya gotta" + and: "*|N" + but: "*|Cept" +"en-lol": + name: LOLCAT + native: LOLCAT + feature: OH HAI + background: B4 + scenario: MISHUN + scenario_outline: MISHUN SRSLY + examples: EXAMPLZ + given: "*|I CAN HAZ" + when: "*|WEN" + then: "*|DEN" + and: "*|AN" + but: "*|BUT" +"en-pirate": + name: Pirate + native: Pirate + feature: Ahoy matey! + background: Yo-ho-ho + scenario: Heave to + scenario_outline: Shiver me timbers + examples: Dead men tell no tales + given: "*|Gangway!" + when: "*|Blimey!" + then: "*|Let go and haul" + and: "*|Aye" + but: "*|Avast!" +"en-Scouse": + name: Scouse + native: Scouse + feature: Feature + background: "Dis is what went down" + scenario: "The thing of it is" + scenario_outline: "Wharrimean is" + examples: Examples + given: "*|Givun|Youse know when youse got" + when: "*|Wun|Youse know like when" + then: "*|Dun|Den youse gotta" + and: "*|An" + but: "*|Buh" +"en-tx": + name: Texan + native: Texan + feature: Feature + background: Background + scenario: Scenario + scenario_outline: All y'all + examples: Examples + given: "*|Given y'all" + when: "*|When y'all" + then: "*|Then y'all" + and: "*|And y'all" + but: "*|But y'all" +"eo": + name: Esperanto + native: Esperanto + feature: Trajto + background: Fono + scenario: Scenaro + scenario_outline: Konturo de la scenaro + examples: Ekzemploj + given: "*|Donitaĵo" + when: "*|Se" + then: "*|Do" + and: "*|Kaj" + but: "*|Sed" +"es": + name: Spanish + native: español + background: Antecedentes + feature: Característica + scenario: Escenario + scenario_outline: Esquema del escenario + examples: Ejemplos + given: "*|Dado|Dada|Dados|Dadas" + when: "*|Cuando" + then: "*|Entonces" + and: "*|Y" + but: "*|Pero" +"et": + name: Estonian + native: eesti keel + feature: Omadus + background: Taust + scenario: Stsenaarium + scenario_outline: Raamstsenaarium + examples: Juhtumid + given: "*|Eeldades" + when: "*|Kui" + then: "*|Siis" + and: "*|Ja" + but: "*|Kuid" +"fi": + name: Finnish + native: suomi + feature: Ominaisuus + background: Tausta + scenario: Tapaus + scenario_outline: Tapausaihio + examples: Tapaukset + given: "*|Oletetaan" + when: "*|Kun" + then: "*|Niin" + and: "*|Ja" + but: "*|Mutta" +"fr": + name: French + native: français + feature: Fonctionnalité + background: Contexte + scenario: Scénario + scenario_outline: Plan du scénario|Plan du Scénario + examples: Exemples + given: "*|Soit|Etant donné|Etant donnée|Etant donnés|Etant données|Étant donné|Étant donnée|Étant donnés|Étant données" + when: "*|Quand|Lorsque|Lorsqu'<" + then: "*|Alors" + and: "*|Et" + but: "*|Mais" +"he": + name: Hebrew + native: עברית + feature: תכונה + background: רקע + scenario: תרחיש + scenario_outline: תבנית תרחיש + examples: דוגמאות + given: "*|בהינתן" + when: "*|כאשר" + then: "*|אז|אזי" + and: "*|וגם" + but: "*|אבל" +"hr": + name: Croatian + native: hrvatski + feature: Osobina|Mogućnost|Mogucnost + background: Pozadina + scenario: Scenarij + scenario_outline: Skica|Koncept + examples: Primjeri|Scenariji + given: "*|Zadan|Zadani|Zadano" + when: "*|Kada|Kad" + then: "*|Onda" + and: "*|I" + but: "*|Ali" +"hu": + name: Hungarian + native: magyar + feature: Jellemző + background: Háttér + scenario: Forgatókönyv + scenario_outline: Forgatókönyv vázlat + examples: Példák + given: "*|Amennyiben|Adott" + when: "*|Majd|Ha|Amikor" + then: "*|Akkor" + and: "*|És" + but: "*|De" +"id": + name: Indonesian + native: Bahasa Indonesia + feature: Fitur + background: Dasar + scenario: Skenario + scenario_outline: Skenario konsep + examples: Contoh + given: "*|Dengan" + when: "*|Ketika" + then: "*|Maka" + and: "*|Dan" + but: "*|Tapi" +"is": + name: Icelandic + native: Íslenska + feature: Eiginleiki + background: Bakgrunnur + scenario: Atburðarás + scenario_outline: Lýsing Atburðarásar|Lýsing Dæma + examples: Dæmi|Atburðarásir + given: "*|Ef" + when: "*|Þegar" + then: "*|Þá" + and: "*|Og" + but: "*|En" +"it": + name: Italian + native: italiano + feature: Funzionalità + background: Contesto + scenario: Scenario + scenario_outline: Schema dello scenario + examples: Esempi + given: "*|Dato|Data|Dati|Date" + when: "*|Quando" + then: "*|Allora" + and: "*|E" + but: "*|Ma" +"ja": + name: Japanese + native: 日本語 + feature: フィーチャ|機能 + background: 背景 + scenario: シナリオ + scenario_outline: シナリオアウトライン|シナリオテンプレート|テンプレ|シナリオテンプレ + examples: 例|サンプル + given: "*|前提<" + when: "*|もし<" + then: "*|ならば<" + and: "*|かつ<" + but: "*|しかし<|但し<|ただし<" +"ko": + name: Korean + native: 한국어 + background: 배경 + feature: 기능 + scenario: 시나리오 + scenario_outline: 시나리오 개요 + examples: 예 + given: "*|조건<|먼저<" + when: "*|만일<|만약<" + then: "*|그러면<" + and: "*|그리고<" + but: "*|하지만<|단<" +"lt": + name: Lithuanian + native: lietuvių kalba + feature: Savybė + background: Kontekstas + scenario: Scenarijus + scenario_outline: Scenarijaus šablonas + examples: Pavyzdžiai|Scenarijai|Variantai + given: "*|Duota" + when: "*|Kai" + then: "*|Tada" + and: "*|Ir" + but: "*|Bet" +"lu": + name: Luxemburgish + native: Lëtzebuergesch + feature: Funktionalitéit + background: Hannergrond + scenario: Szenario + scenario_outline: Plang vum Szenario + examples: Beispiller + given: "*|ugeholl" + when: "*|wann" + then: "*|dann" + and: "*|an|a" + but: "*|awer|mä" +"lv": + name: Latvian + native: latviešu + feature: Funkcionalitāte|Fīča + background: Konteksts|Situācija + scenario: Scenārijs + scenario_outline: Scenārijs pēc parauga + examples: Piemēri|Paraugs + given: "*|Kad" + when: "*|Ja" + then: "*|Tad" + and: "*|Un" + but: "*|Bet" +"nl": + name: Dutch + native: Nederlands + feature: Functionaliteit + background: Achtergrond + scenario: Scenario + scenario_outline: Abstract Scenario + examples: Voorbeelden + given: "*|Gegeven|Stel" + when: "*|Als" + then: "*|Dan" + and: "*|En" + but: "*|Maar" +"no": + name: Norwegian + native: norsk + feature: Egenskap + background: Bakgrunn + scenario: Scenario + scenario_outline: Scenariomal|Abstrakt Scenario + examples: Eksempler + given: "*|Gitt" + when: "*|Når" + then: "*|Så" + and: "*|Og" + but: "*|Men" +"pl": + name: Polish + native: polski + feature: Właściwość + background: Założenia + scenario: Scenariusz + scenario_outline: Szablon scenariusza + examples: Przykłady + given: "*|Zakładając|Mając" + when: "*|Jeżeli|Jeśli" + then: "*|Wtedy" + and: "*|Oraz|I" + but: "*|Ale" +"pt": + name: Portuguese + native: português + background: Contexto + feature: Funcionalidade + scenario: Cenário|Cenario + scenario_outline: Esquema do Cenário|Esquema do Cenario + examples: Exemplos + given: "*|Dado|Dada|Dados|Dadas" + when: "*|Quando" + then: "*|Então|Entao" + and: "*|E" + but: "*|Mas" +"ro": + name: Romanian + native: română + background: Context + feature: Functionalitate|Funcționalitate|Funcţionalitate + scenario: Scenariu + scenario_outline: Structura scenariu|Structură scenariu + examples: Exemple + given: "*|Date fiind|Dat fiind|Dati fiind|Dați fiind|Daţi fiind" + when: "*|Cand|Când" + then: "*|Atunci" + and: "*|Si|Și|Şi" + but: "*|Dar" +"ru": + name: Russian + native: русский + feature: Функция|Функционал|Свойство + background: Предыстория|Контекст + scenario: Сценарий + scenario_outline: Структура сценария + examples: Примеры + given: "*|Допустим|Дано|Пусть" + when: "*|Если|Когда" + then: "*|То|Тогда" + and: "*|И|К тому же" + but: "*|Но|А" +"sv": + name: Swedish + native: Svenska + feature: Egenskap + background: Bakgrund + scenario: Scenario + scenario_outline: Abstrakt Scenario|Scenariomall + examples: Exempel + given: "*|Givet" + when: "*|När" + then: "*|Så" + and: "*|Och" + but: "*|Men" +"sk": + name: Slovak + native: Slovensky + feature: Požiadavka + background: Pozadie + scenario: Scenár + scenario_outline: Náčrt Scenáru + examples: Príklady + given: "*|Pokiaľ" + when: "*|Keď" + then: "*|Tak" + and: "*|A" + but: "*|Ale" +"sr-Latn": + name: Serbian (Latin) + native: Srpski (Latinica) + feature: Funkcionalnost|Mogućnost|Mogucnost|Osobina + background: Kontekst|Osnova|Pozadina + scenario: Scenario|Primer + scenario_outline: Struktura scenarija|Skica|Koncept + examples: Primeri|Scenariji + given: "*|Zadato|Zadate|Zatati" + when: "*|Kada|Kad" + then: "*|Onda" + and: "*|I" + but: "*|Ali" +"sr-Cyrl": + name: Serbian + native: Српски + feature: Функционалност|Могућност|Особина + background: Контекст|Основа|Позадина + scenario: Сценарио|Пример + scenario_outline: Структура сценарија|Скица|Концепт + examples: Примери|Сценарији + given: "*|Задато|Задате|Задати" + when: "*|Када|Кад" + then: "*|Онда" + and: "*|И" + but: "*|Али" +"tr": + name: Turkish + native: Türkçe + feature: Özellik + background: Geçmiş + scenario: Senaryo + scenario_outline: Senaryo taslağı + examples: Örnekler + given: "*|Diyelim ki" + when: "*|Eğer ki" + then: "*|O zaman" + and: "*|Ve" + but: "*|Fakat|Ama" +"uk": + name: Ukrainian + native: Українська + feature: Функціонал + background: Передумова + scenario: Сценарій + scenario_outline: Структура сценарію + examples: Приклади + given: "*|Припустимо|Припустимо, що|Нехай|Дано" + when: "*|Якщо|Коли" + then: "*|То|Тоді" + and: "*|І|А також|Та" + but: "*|Але" +"uz": + name: Uzbek + native: Узбекча + feature: Функционал + background: Тарих + scenario: Сценарий + scenario_outline: Сценарий структураси + examples: Мисоллар + given: "*|Агар" + when: "*|Агар" + then: "*|Унда" + and: "*|Ва" + but: "*|Лекин|Бирок|Аммо" +"vi": + name: Vietnamese + native: Tiếng Việt + feature: Tính năng + background: Bối cảnh + scenario: Tình huống|Kịch bản + scenario_outline: Khung tình huống|Khung kịch bản + examples: Dữ liệu + given: "*|Biết|Cho" + when: "*|Khi" + then: "*|Thì" + and: "*|Và" + but: "*|Nhưng" +"zh-CN": + name: Chinese simplified + native: 简体中文 + feature: 功能 + background: 背景 + scenario: 场景 + scenario_outline: 场景大纲 + examples: 例子 + given: "*|假如<" + when: "*|当<" + then: "*|那么<" + and: "*|而且<" + but: "*|但是<" +"zh-TW": + name: Chinese traditional + native: 繁體中文 + feature: 功能 + background: 背景 + scenario: 場景|劇本 + scenario_outline: 場景大綱|劇本大綱 + examples: 例子 + given: "*|假設<" + when: "*|當<" + then: "*|那麼<" + and: "*|而且<|並且<" + but: "*|但是<" diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/GherkinTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/GherkinTest.php new file mode 100644 index 0000000..9e5c0cb --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/GherkinTest.php @@ -0,0 +1,184 @@ +getCustomFilterMock(); + $customFilter2 = $this->getCustomFilterMock(); + + $gherkin = new Gherkin(); + $gherkin->addLoader($loader = $this->getLoaderMock()); + $gherkin->addFilter($nameFilter = $this->getNameFilterMock()); + $gherkin->addFilter($tagFilter = $this->getTagFilterMock()); + + $scenario = new ScenarioNode(null, array(), array(), null, null); + $feature = new FeatureNode(null, null, array(), null, array($scenario), null, null, null, null); + + $loader + ->expects($this->once()) + ->method('supports') + ->with($resource = 'some/feature/resource') + ->will($this->returnValue(true)); + $loader + ->expects($this->once()) + ->method('load') + ->with($resource) + ->will($this->returnValue(array($feature))); + + $nameFilter + ->expects($this->once()) + ->method('filterFeature') + ->with($this->identicalTo($feature)) + ->will($this->returnValue($feature)); + $tagFilter + ->expects($this->once()) + ->method('filterFeature') + ->with($this->identicalTo($feature)) + ->will($this->returnValue($feature)); + $customFilter1 + ->expects($this->once()) + ->method('filterFeature') + ->with($this->identicalTo($feature)) + ->will($this->returnValue($feature)); + $customFilter2 + ->expects($this->once()) + ->method('filterFeature') + ->with($this->identicalTo($feature)) + ->will($this->returnValue($feature)); + + $features = $gherkin->load($resource, array($customFilter1, $customFilter2)); + $this->assertEquals(1, count($features)); + + $scenarios = $features[0]->getScenarios(); + $this->assertEquals(1, count($scenarios)); + $this->assertSame($scenario, $scenarios[0]); + } + + public function testNotFoundLoader() + { + $gherkin = new Gherkin(); + + $this->assertEquals(array(), $gherkin->load('some/feature/resource')); + } + + public function testLoaderFiltersFeatures() + { + $gherkin = new Gherkin(); + $gherkin->addLoader($loader = $this->getLoaderMock()); + $gherkin->addFilter($nameFilter = $this->getNameFilterMock()); + + $feature = new FeatureNode(null, null, array(), null, array(), null, null, null, null); + + $loader + ->expects($this->once()) + ->method('supports') + ->with($resource = 'some/feature/resource') + ->will($this->returnValue(true)); + $loader + ->expects($this->once()) + ->method('load') + ->with($resource) + ->will($this->returnValue(array($feature))); + + $nameFilter + ->expects($this->once()) + ->method('filterFeature') + ->with($this->identicalTo($feature)) + ->will($this->returnValue($feature)); + $nameFilter + ->expects($this->once()) + ->method('isFeatureMatch') + ->with($this->identicalTo($feature)) + ->will($this->returnValue(false)); + + $features = $gherkin->load($resource); + $this->assertEquals(0, count($features)); + } + + public function testSetFiltersOverridesAllFilters() + { + $gherkin = new Gherkin(); + $gherkin->addLoader($loader = $this->getLoaderMock()); + $gherkin->addFilter($nameFilter = $this->getNameFilterMock()); + $gherkin->setFilters(array()); + + $feature = new FeatureNode(null, null, array(), null, array(), null, null, null, null); + + $loader + ->expects($this->once()) + ->method('supports') + ->with($resource = 'some/feature/resource') + ->will($this->returnValue(true)); + $loader + ->expects($this->once()) + ->method('load') + ->with($resource) + ->will($this->returnValue(array($feature))); + + $nameFilter + ->expects($this->never()) + ->method('filterFeature'); + $nameFilter + ->expects($this->never()) + ->method('isFeatureMatch'); + + $features = $gherkin->load($resource); + $this->assertEquals(1, count($features)); + } + + public function testSetBasePath() + { + $gherkin = new Gherkin(); + $gherkin->addLoader($loader1 = $this->getLoaderMock()); + $gherkin->addLoader($loader2 = $this->getLoaderMock()); + + $loader1 + ->expects($this->once()) + ->method('setBasePath') + ->with($basePath = '/base/path') + ->will($this->returnValue(null)); + + $loader2 + ->expects($this->once()) + ->method('setBasePath') + ->with($basePath = '/base/path') + ->will($this->returnValue(null)); + + $gherkin->setBasePath($basePath); + } + + protected function getLoaderMock() + { + return $this->getMockBuilder('Behat\Gherkin\Loader\GherkinFileLoader') + ->disableOriginalConstructor() + ->getMock(); + } + + protected function getCustomFilterMock() + { + return $this->getMockBuilder('Behat\Gherkin\Filter\FilterInterface') + ->disableOriginalConstructor() + ->getMock(); + } + + protected function getNameFilterMock() + { + return $this->getMockBuilder('Behat\Gherkin\Filter\NameFilter') + ->disableOriginalConstructor() + ->getMock(); + } + + protected function getTagFilterMock() + { + return $this->getMockBuilder('Behat\Gherkin\Filter\TagFilter') + ->disableOriginalConstructor() + ->getMock(); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Keywords/CachedArrayKeywordsTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Keywords/CachedArrayKeywordsTest.php new file mode 100644 index 0000000..5c71630 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Keywords/CachedArrayKeywordsTest.php @@ -0,0 +1,33 @@ +keywords = new ArrayKeywords(array( + 'en' => array( + 'feature' => 'Feature', + 'background' => 'Background', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Scenario Outline|Scenario Template', + 'examples' => 'Examples|Scenarios', + 'given' => 'Given', + 'when' => 'When', + 'then' => 'Then', + 'and' => 'And', + 'but' => 'But' + ), + 'ru' => array( + 'feature' => 'Функционал|Фича', + 'background' => 'Предыстория|Бэкграунд', + 'scenario' => 'Сценарий|История', + 'scenario_outline' => 'Структура сценария|Аутлайн', + 'examples' => 'Значения', + 'given' => 'Допустим', + 'when' => 'Если|@', + 'then' => 'То', + 'and' => 'И', + 'but' => 'Но' + ) + )); + } + + public function testEnKeywordsDumper() + { + $dumper = new KeywordsDumper($this->keywords); + + $dumped = $dumper->dump('en'); + $etalon = << + And there is agent + When I erase agent 's memory + Then there should be agent + But there should not be agent + + (Examples|Scenarios): + | agent1 | agent2 | + | D | M | +GHERKIN; + + $this->assertEquals($etalon, $dumped); + } + + public function testRuKeywordsDumper() + { + $dumper = new KeywordsDumper($this->keywords); + + $dumped = $dumper->dump('ru'); + $etalon = << + И there is agent + (Если|@) I erase agent 's memory + То there should be agent + Но there should not be agent + + Значения: + | agent1 | agent2 | + | D | M | +GHERKIN; + + $this->assertEquals($etalon, $dumped); + } + + public function testRuKeywordsCustomKeywordsDumper() + { + $dumper = new KeywordsDumper($this->keywords); + $dumper->setKeywordsDumperFunction(function ($keywords) { + return ''.implode(', ', $keywords).''; + }); + + $dumped = $dumper->dump('ru'); + $etalon = <<Функционал, Фича: Internal operations + In order to stay secret + As a secret organization + We need to be able to erase past agents' memory + + Предыстория, Бэкграунд: + Допустим there is agent A + И there is agent B + + Сценарий, История: Erasing agent memory + Допустим there is agent J + И there is agent K + Если, @ I erase agent K's memory + То there should be agent J + Но there should not be agent K + + Структура сценария, Аутлайн: Erasing other agents' memory + Допустим there is agent + И there is agent + Если, @ I erase agent 's memory + То there should be agent + Но there should not be agent + + Значения: + | agent1 | agent2 | + | D | M | +GHERKIN; + + $this->assertEquals($etalon, $dumped); + } + + public function testExtendedVersionDumper() + { + $dumper = new KeywordsDumper($this->keywords); + + $dumped = $dumper->dump('ru', false); + $etalon = array( + << + И there is agent + Если I erase agent 's memory + @ I erase agent 's memory + То there should be agent + Но there should not be agent + + Значения: + | agent1 | agent2 | + | D | M | + + Аутлайн: Erasing other agents' memory + Допустим there is agent + И there is agent + Если I erase agent 's memory + @ I erase agent 's memory + То there should be agent + Но there should not be agent + + Значения: + | agent1 | agent2 | + | D | M | +GHERKIN + , << + И there is agent + Если I erase agent 's memory + @ I erase agent 's memory + То there should be agent + Но there should not be agent + + Значения: + | agent1 | agent2 | + | D | M | + + Аутлайн: Erasing other agents' memory + Допустим there is agent + И there is agent + Если I erase agent 's memory + @ I erase agent 's memory + То there should be agent + Но there should not be agent + + Значения: + | agent1 | agent2 | + | D | M | +GHERKIN + ); + + $this->assertEquals($etalon, $dumped); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Keywords/KeywordsTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Keywords/KeywordsTest.php new file mode 100644 index 0000000..7627821 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Keywords/KeywordsTest.php @@ -0,0 +1,139 @@ +getKeywords(); + $lexer = new Lexer($keywords); + $parser = new Parser($lexer); + $dumper = new KeywordsDumper($keywords); + $keywordsArray = $this->getKeywordsArray(); + + // Remove languages with repeated keywords + unset($keywordsArray['en-old'], $keywordsArray['uz']); + + $data = array(); + foreach ($keywordsArray as $lang => $i18nKeywords) { + $features = array(); + foreach (explode('|', $i18nKeywords['feature']) as $transNum => $featureKeyword) { + $line = 1; + if ('en' !== $lang) { + $line = 2; + } + + $featureLine = $line; + $line += 5; + + $keywords = explode('|', $i18nKeywords['background']); + $backgroundLine = $line; + $line += 1; + $background = new BackgroundNode(null, array_merge( + $this->getSteps($i18nKeywords['given'], 'there is agent A', $line, 'Given'), + $this->getSteps($i18nKeywords['and'], 'there is agent B', $line, 'Given') + ), $keywords[0], $backgroundLine); + + $line += 1; + + $scenarios = array(); + + foreach (explode('|', $i18nKeywords['scenario']) as $scenarioKeyword) { + $scenarioLine = $line; + $line += 1; + + $steps = array_merge( + $this->getSteps($i18nKeywords['given'], 'there is agent J', $line, 'Given'), + $this->getSteps($i18nKeywords['and'], 'there is agent K', $line, 'Given'), + $this->getSteps($i18nKeywords['when'], 'I erase agent K\'s memory', $line, 'When'), + $this->getSteps($i18nKeywords['then'], 'there should be agent J', $line, 'Then'), + $this->getSteps($i18nKeywords['but'], 'there should not be agent K', $line, 'Then') + ); + + $scenarios[] = new ScenarioNode('Erasing agent memory', array(), $steps, $scenarioKeyword, $scenarioLine); + $line += 1; + } + foreach (explode('|', $i18nKeywords['scenario_outline']) as $outlineKeyword) { + $outlineLine = $line; + $line += 1; + + $steps = array_merge( + $this->getSteps($i18nKeywords['given'], 'there is agent ', $line, 'Given'), + $this->getSteps($i18nKeywords['and'], 'there is agent ', $line, 'Given'), + $this->getSteps($i18nKeywords['when'], 'I erase agent \'s memory', $line, 'When'), + $this->getSteps($i18nKeywords['then'], 'there should be agent ', $line, 'Then'), + $this->getSteps($i18nKeywords['but'], 'there should not be agent ', $line, 'Then') + ); + $line += 1; + + $keywords = explode('|', $i18nKeywords['examples']); + $table = new ExampleTableNode(array( + ++$line => array('agent1', 'agent2'), + ++$line => array('D', 'M') + ), $keywords[0]); + $line += 1; + + $scenarios[] = new OutlineNode('Erasing other agents\' memory', array(), $steps, $table, $outlineKeyword, $outlineLine); + $line += 1; + } + + $features[] = new FeatureNode( + 'Internal operations', + <<dump($lang, false); + $parsed = array(); + try { + foreach ($dumped as $num => $dumpedFeature) { + $parsed[] = $parser->parse($dumpedFeature, $lang . '_' . ($num + 1) . '.feature'); + } + } catch (\Exception $e) { + throw new \Exception($e->getMessage() . ":\n" . $dumped, 0, $e); + } + + $data[] = array($lang, $features, $parsed); + } + + return $data; + } + + /** + * @dataProvider translationTestDataProvider + * + * @param string $language language name + * @param array $etalon etalon features (to test against) + * @param array $features array of parsed feature(s) + */ + public function testTranslation($language, array $etalon, array $features) + { + $this->assertEquals($etalon, $features); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/ArrayLoaderTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/ArrayLoaderTest.php new file mode 100644 index 0000000..697d1d3 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/ArrayLoaderTest.php @@ -0,0 +1,379 @@ +loader = new ArrayLoader(); + } + + public function testSupports() + { + $this->assertFalse($this->loader->supports(__DIR__)); + $this->assertFalse($this->loader->supports(__FILE__)); + $this->assertFalse($this->loader->supports('string')); + $this->assertFalse($this->loader->supports(array('wrong_root'))); + $this->assertFalse($this->loader->supports(array('features'))); + $this->assertTrue($this->loader->supports(array('features' => array()))); + $this->assertTrue($this->loader->supports(array('feature' => array()))); + } + + public function testLoadEmpty() + { + $this->assertEquals(array(), $this->loader->load(array('features' => array()))); + } + + public function testLoadFeatures() + { + $features = $this->loader->load(array( + 'features' => array( + array( + 'title' => 'First feature', + 'line' => 3, + ), + array( + 'description' => 'Second feature description', + 'language' => 'ru', + 'tags' => array('some', 'tags') + ) + ), + )); + + $this->assertEquals(2, count($features)); + + $this->assertEquals(3, $features[0]->getLine()); + $this->assertEquals('First feature', $features[0]->getTitle()); + $this->assertNull($features[0]->getDescription()); + $this->assertNull($features[0]->getFile()); + $this->assertEquals('en', $features[0]->getLanguage()); + $this->assertFalse($features[0]->hasTags()); + + $this->assertEquals(1, $features[1]->getLine()); + $this->assertNull($features[1]->getTitle()); + $this->assertEquals('Second feature description', $features[1]->getDescription()); + $this->assertNull($features[1]->getFile()); + $this->assertEquals('ru', $features[1]->getLanguage()); + $this->assertEquals(array('some', 'tags'), $features[1]->getTags()); + } + + public function testLoadScenarios() + { + $features = $this->loader->load(array( + 'features' => array( + array( + 'title' => 'Feature', + 'scenarios' => array( + array( + 'title' => 'First scenario', + 'line' => 2 + ), + array( + 'tags' => array('second', 'scenario', 'tags') + ), + array( + 'tags' => array('third', 'scenario'), + 'line' => 3 + ) + ) + ) + ), + )); + + $this->assertEquals(1, count($features)); + + $scenarios = $features[0]->getScenarios(); + + $this->assertEquals(3, count($scenarios)); + + $this->assertInstanceOf('Behat\Gherkin\Node\ScenarioNode', $scenarios[0]); + $this->assertEquals('First scenario', $scenarios[0]->getTitle()); + $this->assertFalse($scenarios[0]->hasTags()); + $this->assertEquals(2, $scenarios[0]->getLine()); + + $this->assertInstanceOf('Behat\Gherkin\Node\ScenarioNode', $scenarios[1]); + $this->assertNull($scenarios[1]->getTitle()); + $this->assertEquals(array('second', 'scenario', 'tags'), $scenarios[1]->getTags()); + $this->assertEquals(1, $scenarios[1]->getLine()); + + $this->assertInstanceOf('Behat\Gherkin\Node\ScenarioNode', $scenarios[2]); + $this->assertNull($scenarios[2]->getTitle()); + $this->assertEquals(array('third', 'scenario'), $scenarios[2]->getTags()); + $this->assertEquals(3, $scenarios[2]->getLine()); + } + + public function testLoadOutline() + { + $features = $this->loader->load(array( + 'features' => array( + array( + 'title' => 'Feature', + 'scenarios' => array( + array( + 'type' => 'outline', + 'title' => 'First outline', + 'line' => 2 + ), + array( + 'type' => 'outline', + 'tags' => array('second', 'outline', 'tags') + ) + ) + ) + ), + )); + + $this->assertEquals(1, count($features)); + + $outlines = $features[0]->getScenarios(); + + $this->assertEquals(2, count($outlines)); + + $this->assertInstanceOf('Behat\Gherkin\Node\OutlineNode', $outlines[0]); + $this->assertEquals('First outline', $outlines[0]->getTitle()); + $this->assertFalse($outlines[0]->hasTags()); + $this->assertEquals(2, $outlines[0]->getLine()); + + $this->assertInstanceOf('Behat\Gherkin\Node\OutlineNode', $outlines[1]); + $this->assertNull($outlines[1]->getTitle()); + $this->assertEquals(array('second', 'outline', 'tags'), $outlines[1]->getTags()); + $this->assertEquals(1, $outlines[1]->getLine()); + } + + public function testOutlineExamples() + { + $features = $this->loader->load(array( + 'features' => array( + array( + 'title' => 'Feature', + 'scenarios' => array( + array( + 'type' => 'outline', + 'title' => 'First outline', + 'line' => 2, + 'examples' => array( + array('user', 'pass'), + array('ever', 'sdsd'), + array('anto', 'fdfd') + ) + ), + array( + 'type' => 'outline', + 'tags' => array('second', 'outline', 'tags') + ) + ) + ) + ), + )); + + $this->assertEquals(1, count($features)); + + $scenarios = $features[0]->getScenarios(); + $scenario = $scenarios[0]; + + $this->assertEquals( + array(array('user' => 'ever', 'pass' => 'sdsd'), array('user' => 'anto', 'pass' => 'fdfd')), + $scenario->getExampleTable()->getHash() + ); + } + + public function testLoadBackground() + { + $features = $this->loader->load(array( + 'features' => array( + array( + ), + array( + 'background' => array() + ), + array( + 'background' => array( + 'line' => 2 + ) + ), + ) + )); + + $this->assertEquals(3, count($features)); + + $this->assertFalse($features[0]->hasBackground()); + $this->assertTrue($features[1]->hasBackground()); + $this->assertEquals(0, $features[1]->getBackground()->getLine()); + $this->assertTrue($features[2]->hasBackground()); + $this->assertEquals(2, $features[2]->getBackground()->getLine()); + } + + public function testLoadSteps() + { + $features = $this->loader->load(array( + 'features' => array( + array( + 'background' => array( + 'steps' => array( + array('type' => 'Gangway!', 'keyword_type' => 'Given', 'text' => 'bg step 1', 'line' => 3), + array('type' => 'Blimey!', 'keyword_type' => 'When', 'text' => 'bg step 2') + ) + ), + 'scenarios' => array( + array( + 'title' => 'Scenario', + 'steps' => array( + array('type' => 'Gangway!', 'keyword_type' => 'Given', 'text' => 'sc step 1'), + array('type' => 'Blimey!', 'keyword_type' => 'When', 'text' => 'sc step 2') + ) + ), + array( + 'title' => 'Outline', + 'type' => 'outline', + 'steps' => array( + array('type' => 'Gangway!', 'keyword_type' => 'Given', 'text' => 'out step 1'), + array('type' => 'Blimey!', 'keyword_type' => 'When', 'text' => 'out step 2') + ) + ) + ) + ) + ) + )); + + $background = $features[0]->getBackground(); + $this->assertTrue($background->hasSteps()); + $this->assertEquals(2, count($background->getSteps())); + $steps = $background->getSteps(); + $this->assertEquals('Gangway!', $steps[0]->getType()); + $this->assertEquals('Gangway!', $steps[0]->getKeyword()); + $this->assertEquals('Given', $steps[0]->getKeywordType()); + $this->assertEquals('bg step 1', $steps[0]->getText()); + $this->assertEquals(3, $steps[0]->getLine()); + $this->assertEquals('Blimey!', $steps[1]->getType()); + $this->assertEquals('Blimey!', $steps[1]->getKeyword()); + $this->assertEquals('When', $steps[1]->getKeywordType()); + $this->assertEquals('bg step 2', $steps[1]->getText()); + $this->assertEquals(1, $steps[1]->getLine()); + + $scenarios = $features[0]->getScenarios(); + + $scenario = $scenarios[0]; + $this->assertTrue($scenario->hasSteps()); + $this->assertEquals(2, count($scenario->getSteps())); + $steps = $scenario->getSteps(); + $this->assertEquals('Gangway!', $steps[0]->getType()); + $this->assertEquals('Gangway!', $steps[0]->getKeyword()); + $this->assertEquals('Given', $steps[0]->getKeywordType()); + $this->assertEquals('sc step 1', $steps[0]->getText()); + $this->assertEquals(0, $steps[0]->getLine()); + $this->assertEquals('Blimey!', $steps[1]->getType()); + $this->assertEquals('Blimey!', $steps[1]->getKeyword()); + $this->assertEquals('When', $steps[1]->getKeywordType()); + $this->assertEquals('sc step 2', $steps[1]->getText()); + $this->assertEquals(1, $steps[1]->getLine()); + + $outline = $scenarios[1]; + $this->assertTrue($outline->hasSteps()); + $this->assertEquals(2, count($outline->getSteps())); + $steps = $outline->getSteps(); + $this->assertEquals('Gangway!', $steps[0]->getType()); + $this->assertEquals('Gangway!', $steps[0]->getKeyword()); + $this->assertEquals('Given', $steps[0]->getKeywordType()); + $this->assertEquals('out step 1', $steps[0]->getText()); + $this->assertEquals(0, $steps[0]->getLine()); + $this->assertEquals('Blimey!', $steps[1]->getType()); + $this->assertEquals('Blimey!', $steps[1]->getKeyword()); + $this->assertEquals('When', $steps[1]->getKeywordType()); + $this->assertEquals('out step 2', $steps[1]->getText()); + $this->assertEquals(1, $steps[1]->getLine()); + } + + public function testLoadStepArguments() + { + $features = $this->loader->load(array( + 'features' => array( + array( + 'background' => array( + 'steps' => array( + array( + 'type' => 'Gangway!', 'keyword_type' => 'Given', 'text' => 'step with table argument', + 'arguments' => array( + array( + 'type' => 'table', + 'rows' => array( + array('key', 'val'), + array(1, 2), + array(3, 4) + ) + ) + ) + ), + array( + 'type' => 'Blimey!', 'keyword_type' => 'When', 'text' => 'step with pystring argument', + 'arguments' => array( + array( + 'type' => 'pystring', + 'text' => ' some text', + ) + ) + ), + array( + 'type' => 'Let go and haul', 'keyword_type' => 'Then', 'text' => '2nd step with pystring argument', + 'arguments' => array( + array( + 'type' => 'pystring', + 'text' => 'some text', + ) + ) + ) + ) + ) + ) + ) + )); + + $background = $features[0]->getBackground(); + + $this->assertTrue($background->hasSteps()); + + $steps = $background->getSteps(); + + $this->assertEquals(3, count($steps)); + + $arguments = $steps[0]->getArguments(); + $this->assertEquals('Gangway!', $steps[0]->getType()); + $this->assertEquals('Gangway!', $steps[0]->getKeyword()); + $this->assertEquals('Given', $steps[0]->getKeywordType()); + $this->assertEquals('step with table argument', $steps[0]->getText()); + $this->assertInstanceOf('Behat\Gherkin\Node\TableNode', $arguments[0]); + $this->assertEquals(array(array('key'=>1, 'val'=>2), array('key'=>3,'val'=>4)), $arguments[0]->getHash()); + + $arguments = $steps[1]->getArguments(); + $this->assertEquals('Blimey!', $steps[1]->getType()); + $this->assertEquals('Blimey!', $steps[1]->getKeyword()); + $this->assertEquals('When', $steps[1]->getKeywordType()); + $this->assertEquals('step with pystring argument', $steps[1]->getText()); + $this->assertInstanceOf('Behat\Gherkin\Node\PyStringNode', $arguments[0]); + $this->assertEquals(' some text', (string) $arguments[0]); + + $arguments = $steps[2]->getArguments(); + $this->assertEquals('Let go and haul', $steps[2]->getType()); + $this->assertEquals('Let go and haul', $steps[2]->getKeyword()); + $this->assertEquals('Then', $steps[2]->getKeywordType()); + $this->assertEquals('2nd step with pystring argument', $steps[2]->getText()); + $this->assertInstanceOf('Behat\Gherkin\Node\PyStringNode', $arguments[0]); + $this->assertEquals('some text', (string) $arguments[0]); + } + + public function testSingleFeatureArray() + { + $features = $this->loader->load(array( + 'feature' => array( + 'title' => 'Some feature' + ) + )); + + $this->assertEquals(1, count($features)); + $this->assertEquals('Some feature', $features[0]->getTitle()); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/DirectoryLoaderTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/DirectoryLoaderTest.php new file mode 100644 index 0000000..de32708 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/DirectoryLoaderTest.php @@ -0,0 +1,92 @@ +gherkin = $this->createGherkinMock(); + $this->loader = new DirectoryLoader($this->gherkin); + + $this->featuresPath = realpath(__DIR__ . '/../Fixtures/directories'); + } + + protected function createGherkinMock() + { + $gherkin = $this->getMockBuilder('Behat\Gherkin\Gherkin') + ->disableOriginalConstructor() + ->getMock(); + + return $gherkin; + } + + protected function createGherkinFileLoaderMock() + { + $loader = $this->getMockBuilder('Behat\Gherkin\Loader\GherkinFileLoader') + ->disableOriginalConstructor() + ->getMock(); + + return $loader; + } + + public function testSupports() + { + $this->assertFalse($this->loader->supports('non-existent path')); + $this->assertFalse($this->loader->supports('non-existent path:2')); + + $this->assertFalse($this->loader->supports(__DIR__ . ':d')); + $this->assertFalse($this->loader->supports(__DIR__ . '/../Fixtures/features/pystring.feature')); + $this->assertTrue($this->loader->supports(__DIR__)); + $this->assertTrue($this->loader->supports(__DIR__ . '/../Fixtures/features')); + } + + public function testUndefinedFileLoad() + { + $this->gherkin + ->expects($this->once()) + ->method('resolveLoader') + ->with($this->featuresPath.DIRECTORY_SEPARATOR.'phps'.DIRECTORY_SEPARATOR.'some_file.php') + ->will($this->returnValue(null)); + + $this->assertEquals(array(), $this->loader->load($this->featuresPath . '/phps')); + } + + public function testBasePath() + { + $this->gherkin + ->expects($this->once()) + ->method('resolveLoader') + ->with($this->featuresPath.DIRECTORY_SEPARATOR.'phps'.DIRECTORY_SEPARATOR.'some_file.php') + ->will($this->returnValue(null)); + + $this->loader->setBasePath($this->featuresPath); + + $this->assertEquals(array(), $this->loader->load('phps')); + } + + public function testDefinedFileLoad() + { + $loaderMock = $this->createGherkinFileLoaderMock(); + + $this->gherkin + ->expects($this->once()) + ->method('resolveLoader') + ->with($this->featuresPath.DIRECTORY_SEPARATOR.'phps'.DIRECTORY_SEPARATOR.'some_file.php') + ->will($this->returnValue($loaderMock)); + + $loaderMock + ->expects($this->once()) + ->method('load') + ->with($this->featuresPath.DIRECTORY_SEPARATOR.'phps'.DIRECTORY_SEPARATOR.'some_file.php') + ->will($this->returnValue(array('feature1', 'feature2'))); + + $this->assertEquals(array('feature1', 'feature2'), $this->loader->load($this->featuresPath . '/phps')); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/GherkinFileLoaderTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/GherkinFileLoaderTest.php new file mode 100644 index 0000000..8f5d2c1 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/GherkinFileLoaderTest.php @@ -0,0 +1,111 @@ +assertFalse($this->loader->supports('non-existent path')); + $this->assertFalse($this->loader->supports('non-existent path:2')); + + $this->assertFalse($this->loader->supports(__DIR__)); + $this->assertFalse($this->loader->supports(__DIR__ . ':d')); + $this->assertFalse($this->loader->supports(__FILE__)); + $this->assertTrue($this->loader->supports(__DIR__ . '/../Fixtures/features/pystring.feature')); + } + + public function testLoad() + { + $features = $this->loader->load($this->featuresPath . '/pystring.feature'); + $this->assertEquals(1, count($features)); + $this->assertEquals('A py string feature', $features[0]->getTitle()); + $this->assertEquals($this->featuresPath . DIRECTORY_SEPARATOR . 'pystring.feature', $features[0]->getFile()); + + $features = $this->loader->load($this->featuresPath . '/multiline_name.feature'); + $this->assertEquals(1, count($features)); + $this->assertEquals('multiline', $features[0]->getTitle()); + $this->assertEquals($this->featuresPath . DIRECTORY_SEPARATOR . 'multiline_name.feature', $features[0]->getFile()); + } + + public function testParsingUncachedFeature() + { + $cache = $this->getMockBuilder('Behat\Gherkin\Cache\CacheInterface')->getMock(); + $this->loader->setCache($cache); + + $cache->expects($this->once()) + ->method('isFresh') + ->with($path = $this->featuresPath . DIRECTORY_SEPARATOR . 'pystring.feature', filemtime($path)) + ->will($this->returnValue(false)); + + $cache->expects($this->once()) + ->method('write'); + + $features = $this->loader->load($this->featuresPath . '/pystring.feature'); + $this->assertEquals(1, count($features)); + } + + public function testParsingCachedFeature() + { + $cache = $this->getMockBuilder('Behat\Gherkin\Cache\CacheInterface')->getMock(); + $this->loader->setCache($cache); + + $cache->expects($this->once()) + ->method('isFresh') + ->with($path = $this->featuresPath . DIRECTORY_SEPARATOR . 'pystring.feature', filemtime($path)) + ->will($this->returnValue(true)); + + $cache->expects($this->once()) + ->method('read') + ->with($path) + ->will($this->returnValue('cache')); + + $cache->expects($this->never()) + ->method('write'); + + $features = $this->loader->load($this->featuresPath . '/pystring.feature'); + $this->assertEquals('cache', $features[0]); + } + + public function testBasePath() + { + $this->assertFalse($this->loader->supports('features')); + $this->assertFalse($this->loader->supports('tables.feature')); + + $this->loader->setBasePath($this->featuresPath . '/../'); + $this->assertFalse($this->loader->supports('features')); + $this->assertFalse($this->loader->supports('tables.feature')); + $this->assertTrue($this->loader->supports('features/tables.feature')); + + $features = $this->loader->load('features/pystring.feature'); + $this->assertEquals(1, count($features)); + $this->assertEquals('A py string feature', $features[0]->getTitle()); + $this->assertEquals('features' . DIRECTORY_SEPARATOR . 'pystring.feature', $features[0]->getFile()); + + $this->loader->setBasePath($this->featuresPath); + $features = $this->loader->load('multiline_name.feature'); + $this->assertEquals(1, count($features)); + $this->assertEquals('multiline', $features[0]->getTitle()); + $this->assertEquals('multiline_name.feature', $features[0]->getFile()); + } + + protected function setUp() + { + $keywords = new CucumberKeywords(__DIR__ . '/../Fixtures/i18n.yml'); + $parser = new Parser(new Lexer($keywords)); + $this->loader = new GherkinFileLoader($parser); + + $this->featuresPath = realpath(__DIR__ . '/../Fixtures/features'); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/YamlFileLoaderTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/YamlFileLoaderTest.php new file mode 100644 index 0000000..83b2739 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Loader/YamlFileLoaderTest.php @@ -0,0 +1,67 @@ +loader = new YamlFileLoader(); + } + + public function testSupports() + { + $this->assertFalse($this->loader->supports(__DIR__)); + $this->assertFalse($this->loader->supports(__FILE__)); + $this->assertFalse($this->loader->supports('string')); + $this->assertFalse($this->loader->supports(__DIR__ . '/file.yml')); + $this->assertTrue($this->loader->supports(__DIR__ . '/../Fixtures/etalons/addition.yml')); + } + + public function testLoadAddition() + { + $this->loader->setBasePath(__DIR__ . '/../Fixtures'); + $features = $this->loader->load('etalons/addition.yml'); + + $this->assertEquals(1, count($features)); + $this->assertEquals('etalons'.DIRECTORY_SEPARATOR.'addition.yml', $features[0]->getFile()); + $this->assertEquals('Addition', $features[0]->getTitle()); + $this->assertEquals(2, $features[0]->getLine()); + $this->assertEquals('en', $features[0]->getLanguage()); + $expectedDescription = <<assertEquals($expectedDescription, $features[0]->getDescription()); + + $scenarios = $features[0]->getScenarios(); + + $this->assertEquals(2, count($scenarios)); + $this->assertInstanceOf('Behat\Gherkin\Node\ScenarioNode', $scenarios[0]); + $this->assertEquals(7, $scenarios[0]->getLine()); + $this->assertEquals('Add two numbers', $scenarios[0]->getTitle()); + $steps = $scenarios[0]->getSteps(); + $this->assertEquals(4, count($steps)); + $this->assertEquals(9, $steps[1]->getLine()); + $this->assertEquals('And', $steps[1]->getType()); + $this->assertEquals('And', $steps[1]->getKeyword()); + $this->assertEquals('Given', $steps[1]->getKeywordType()); + $this->assertEquals('I have entered 12 into the calculator', $steps[1]->getText()); + + $this->assertInstanceOf('Behat\Gherkin\Node\ScenarioNode', $scenarios[1]); + $this->assertEquals(13, $scenarios[1]->getLine()); + $this->assertEquals('Div two numbers', $scenarios[1]->getTitle()); + $steps = $scenarios[1]->getSteps(); + $this->assertEquals(4, count($steps)); + $this->assertEquals(16, $steps[2]->getLine()); + $this->assertEquals('When', $steps[2]->getType()); + $this->assertEquals('When', $steps[2]->getKeyword()); + $this->assertEquals('When', $steps[2]->getKeywordType()); + $this->assertEquals('I press div', $steps[2]->getText()); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Node/ExampleNodeTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/ExampleNodeTest.php new file mode 100644 index 0000000..c6f46be --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/ExampleNodeTest.php @@ -0,0 +1,92 @@ +', array(), null, 'Given'), + $step2 = new StepNode('Aye!', 'my email is ', array(), null, 'And'), + $step3 = new StepNode('Blimey!', 'I open homepage', array(), null, 'When'), + $step4 = new StepNode('Let go and haul', 'website should recognise me', array(), null, 'Then'), + ); + + $table = new ExampleTableNode(array( + array('name', 'email'), + array('everzet', 'ever.zet@gmail.com'), + array('example', 'example@example.com') + ), 'Examples'); + + $outline = new OutlineNode(null, array(), $steps, $table, null, null); + $examples = $outline->getExamples(); + + $this->assertCount(4, $steps = $examples[0]->getSteps()); + + $this->assertEquals('Gangway!', $steps[0]->getType()); + $this->assertEquals('Gangway!', $steps[0]->getKeyword()); + $this->assertEquals('Given', $steps[0]->getKeywordType()); + $this->assertEquals('I am everzet', $steps[0]->getText()); + $this->assertEquals('Aye!', $steps[1]->getType()); + $this->assertEquals('Aye!', $steps[1]->getKeyword()); + $this->assertEquals('And', $steps[1]->getKeywordType()); + $this->assertEquals('my email is ever.zet@gmail.com', $steps[1]->getText()); + $this->assertEquals('Blimey!', $steps[2]->getType()); + $this->assertEquals('Blimey!', $steps[2]->getKeyword()); + $this->assertEquals('When', $steps[2]->getKeywordType()); + $this->assertEquals('I open homepage', $steps[2]->getText()); + + $this->assertCount(4, $steps = $examples[1]->getSteps()); + + $this->assertEquals('Gangway!', $steps[0]->getType()); + $this->assertEquals('Gangway!', $steps[0]->getKeyword()); + $this->assertEquals('Given', $steps[0]->getKeywordType()); + $this->assertEquals('I am example', $steps[0]->getText()); + $this->assertEquals('Aye!', $steps[1]->getType()); + $this->assertEquals('Aye!', $steps[1]->getKeyword()); + $this->assertEquals('And', $steps[1]->getKeywordType()); + $this->assertEquals('my email is example@example.com', $steps[1]->getText()); + $this->assertEquals('Blimey!', $steps[2]->getType()); + $this->assertEquals('Blimey!', $steps[2]->getKeyword()); + $this->assertEquals('When', $steps[2]->getKeywordType()); + $this->assertEquals('I open homepage', $steps[2]->getText()); + } + + public function testCreateExampleStepsWithArguments() + { + $steps = array( + $step1 = new StepNode('Gangway!', 'I am ', array(), null, 'Given'), + $step2 = new StepNode('Aye!', 'my email is ', array(), null, 'And'), + $step3 = new StepNode('Blimey!', 'I open:', array( + new PyStringNode(array('page: '), null) + ), null, 'When'), + $step4 = new StepNode('Let go and haul', 'website should recognise me', array( + new TableNode(array(array('page', ''))) + ), null, 'Then'), + ); + + $table = new ExampleTableNode(array( + array('name', 'email', 'url'), + array('everzet', 'ever.zet@gmail.com', 'homepage'), + array('example', 'example@example.com', 'other page') + ), 'Examples'); + + $outline = new OutlineNode(null, array(), $steps, $table, null, null); + $examples = $outline->getExamples(); + + $steps = $examples[0]->getSteps(); + + $args = $steps[2]->getArguments(); + $this->assertEquals('page: homepage', $args[0]->getRaw()); + + $args = $steps[3]->getArguments(); + $this->assertEquals('| page | homepage |', $args[0]->getTableAsString()); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Node/OutlineNodeTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/OutlineNodeTest.php new file mode 100644 index 0000000..1e889b8 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/OutlineNodeTest.php @@ -0,0 +1,68 @@ +', array(), null, 'Given'), + new StepNode('Aye!', 'my email is ', array(), null, 'And'), + new StepNode('Blimey!', 'I open homepage', array(), null, 'When'), + new StepNode('Let go and haul', 'website should recognise me', array(), null, 'Then'), + ); + + $table = new ExampleTableNode(array( + array('name', 'email'), + array('everzet', 'ever.zet@gmail.com'), + array('example', 'example@example.com') + ), 'Examples'); + + $outline = new OutlineNode(null, array(), $steps, $table, null, null); + + $this->assertCount(2, $examples = $outline->getExamples()); + $this->assertEquals(1, $examples[0]->getLine()); + $this->assertEquals(2, $examples[1]->getLine()); + $this->assertEquals(array('name' => 'everzet', 'email' => 'ever.zet@gmail.com'), $examples[0]->getTokens()); + $this->assertEquals(array('name' => 'example', 'email' => 'example@example.com'), $examples[1]->getTokens()); + } + + public function testCreatesEmptyExamplesForEmptyExampleTable() + { + $steps = array( + new StepNode('Gangway!', 'I am ', array(), null, 'Given'), + new StepNode('Aye!', 'my email is ', array(), null, 'And'), + new StepNode('Blimey!', 'I open homepage', array(), null, 'When'), + new StepNode('Let go and haul', 'website should recognise me', array(), null, 'Then'), + ); + + $table = new ExampleTableNode(array( + array('name', 'email') + ), 'Examples'); + + $outline = new OutlineNode(null, array(), $steps, $table, null, null); + + $this->assertCount(0, $examples = $outline->getExamples()); + } + + public function testCreatesEmptyExamplesForNoExampleTable() + { + $steps = array( + new StepNode('Gangway!', 'I am ', array(), null, 'Given'), + new StepNode('Aye!', 'my email is ', array(), null, 'And'), + new StepNode('Blimey!', 'I open homepage', array(), null, 'When'), + new StepNode('Let go and haul', 'website should recognise me', array(), null, 'Then'), + ); + + $table = new ExampleTableNode(array(), 'Examples'); + + $outline = new OutlineNode(null, array(), $steps, $table, null, null); + + $this->assertCount(0, $examples = $outline->getExamples()); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Node/PyStringNodeTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/PyStringNodeTest.php new file mode 100644 index 0000000..1beed38 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/PyStringNodeTest.php @@ -0,0 +1,27 @@ +assertEquals(array('line1', 'line2', 'line3'), $str->getStrings()); + } + + public function testGetRaw() + { + $str = new PyStringNode(array('line1', 'line2', 'line3'), 0); + + $expected = <<assertEquals($expected, $str->getRaw()); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Node/StepNodeTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/StepNodeTest.php new file mode 100644 index 0000000..d334415 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/StepNodeTest.php @@ -0,0 +1,20 @@ +setExpectedException('Behat\Gherkin\Exception\NodeException'); + + new StepNode('Gangway!', 'I am on the page:', array( + new PyStringNode(array('one', 'two'), 11), + new TableNode(array(array('one', 'two'))), + ), 10, 'Given'); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Node/TableNodeTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/TableNodeTest.php new file mode 100644 index 0000000..43dfff2 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/TableNodeTest.php @@ -0,0 +1,222 @@ +assertEquals( + array( + array('username' => 'everzet', 'password' => 'qwerty') + , array('username' => 'antono', 'password' => 'pa$sword') + ), + $table->getHash() + ); + + $table = new TableNode(array( + array('username', 'password'), + array('', 'qwerty'), + array('antono', ''), + array('', '') + )); + + $this->assertEquals( + array( + array('username' => '', 'password' => 'qwerty'), + array('username' => 'antono', 'password' => ''), + array('username' => '', 'password' => ''), + ), + $table->getHash() + ); + } + + public function testIterator() + { + $table = new TableNode(array( + array('username', 'password'), + array('', 'qwerty'), + array('antono', ''), + array('', ''), + )); + + $this->assertEquals( + array( + array('username' => '', 'password' => 'qwerty'), + array('username' => 'antono', 'password' => ''), + array('username' => '', 'password' => ''), + ), + iterator_to_array($table) + ); + } + + public function testRowsHashTable() + { + $table = new TableNode(array( + array('username', 'everzet'), + array('password', 'qwerty'), + array('uid', '35'), + )); + + $this->assertEquals( + array('username' => 'everzet', 'password' => 'qwerty', 'uid' => '35'), + $table->getRowsHash() + ); + } + + public function testLongRowsHashTable() + { + $table = new TableNode(array( + array('username', 'everzet', 'marcello'), + array('password', 'qwerty', '12345'), + array('uid', '35', '22') + )); + + $this->assertEquals(array( + 'username' => array('everzet', 'marcello'), + 'password' => array('qwerty', '12345'), + 'uid' => array('35', '22') + ), $table->getRowsHash()); + } + + public function testGetRows() + { + $table = new TableNode(array( + array('username', 'password'), + array('everzet', 'qwerty'), + array('antono', 'pa$sword') + )); + + $this->assertEquals(array( + array('username', 'password'), + array('everzet', 'qwerty'), + array('antono', 'pa$sword') + ), $table->getRows()); + } + + public function testGetLines() + { + $table = new TableNode(array( + 5 => array('username', 'password'), + 10 => array('everzet', 'qwerty'), + 13 => array('antono', 'pa$sword') + )); + + $this->assertEquals(array(5, 10, 13), $table->getLines()); + } + + public function testGetRow() + { + $table = new TableNode(array( + array('username', 'password'), + array('everzet', 'qwerty'), + array('antono', 'pa$sword') + )); + + $this->assertEquals(array('username', 'password'), $table->getRow(0)); + $this->assertEquals(array('antono', 'pa$sword'), $table->getRow(2)); + } + + public function testGetColumn() + { + $table = new TableNode(array( + array('username', 'password'), + array('everzet', 'qwerty'), + array('antono', 'pa$sword') + )); + + $this->assertEquals(array('username', 'everzet', 'antono'), $table->getColumn(0)); + $this->assertEquals(array('password', 'qwerty', 'pa$sword'), $table->getColumn(1)); + + $table = new TableNode(array( + array('username'), + array('everzet'), + array('antono') + )); + + $this->assertEquals(array('username', 'everzet', 'antono'), $table->getColumn(0)); + } + + public function testGetRowWithLineNumbers() + { + $table = new TableNode(array( + 5 => array('username', 'password'), + 10 => array('everzet', 'qwerty'), + 13 => array('antono', 'pa$sword') + )); + + $this->assertEquals(array('username', 'password'), $table->getRow(0)); + $this->assertEquals(array('antono', 'pa$sword'), $table->getRow(2)); + } + + public function testGetTable() + { + $table = new TableNode($a = array( + 5 => array('username', 'password'), + 10 => array('everzet', 'qwerty'), + 13 => array('antono', 'pa$sword') + )); + + $this->assertEquals($a, $table->getTable()); + } + + public function testGetRowLine() + { + $table = new TableNode(array( + 5 => array('username', 'password'), + 10 => array('everzet', 'qwerty'), + 13 => array('antono', 'pa$sword') + )); + + $this->assertEquals(5, $table->getRowLine(0)); + $this->assertEquals(13, $table->getRowLine(2)); + } + + public function testGetRowAsString() + { + $table = new TableNode(array( + 5 => array('username', 'password'), + 10 => array('everzet', 'qwerty'), + 13 => array('antono', 'pa$sword') + )); + + $this->assertEquals('| username | password |', $table->getRowAsString(0)); + $this->assertEquals('| antono | pa$sword |', $table->getRowAsString(2)); + } + + public function testGetTableAsString() + { + $table = new TableNode(array( + 5 => array('id', 'username', 'password'), + 10 => array('42', 'everzet', 'qwerty'), + 13 => array('2', 'antono', 'pa$sword') + )); + + $expected = <<assertEquals($expected, $table->getTableAsString()); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/ParserExceptionsTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/ParserExceptionsTest.php new file mode 100644 index 0000000..67c8435 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/ParserExceptionsTest.php @@ -0,0 +1,274 @@ + array( + 'feature' => 'Feature', + 'background' => 'Background', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Scenario Outline', + 'examples' => 'Examples', + 'given' => 'Given', + 'when' => 'When', + 'then' => 'Then', + 'and' => 'And', + 'but' => 'But' + ), + 'ru' => array( + 'feature' => 'Функционал', + 'background' => 'Предыстория', + 'scenario' => 'Сценарий', + 'scenario_outline' => 'Структура сценария', + 'examples' => 'Значения', + 'given' => 'Допустим', + 'when' => 'То', + 'then' => 'Если', + 'and' => 'И', + 'but' => 'Но' + ) + )); + $this->gherkin = new Parser(new Lexer($keywords)); + } + + public function testStepRightAfterFeature() + { + $feature = <<gherkin->parse($feature); + + $this->assertEquals("\n Given some step-like line", $parsed->getDescription()); + } + + public function testTextInBackground() + { + $feature = <<gherkin->parse($feature); + } + + public function testTextInScenario() + { + $feature = <<gherkin->parse($feature); + + $this->assertCount(2, $scenarios = $feature->getScenarios()); + $firstTitle = <<assertEquals($firstTitle, $scenarios[0]->getTitle()); + $secondTitle = <<assertEquals($secondTitle, $scenarios[1]->getTitle()); + } + + /** + * @expectedException \Behat\Gherkin\Exception\ParserException + */ + public function testAmbigiousLanguage() + { + $feature = <<gherkin->parse($feature); + } + + /** + * @expectedException \Behat\Gherkin\Exception\ParserException + */ + public function testEmptyOutline() + { + $feature = <<gherkin->parse($feature); + } + + /** + * @expectedException \Behat\Gherkin\Exception\ParserException + */ + public function testWrongTagPlacement() + { + $feature = <<gherkin->parse($feature); + } + + /** + * @expectedException \Behat\Gherkin\Exception\ParserException + */ + public function testBackgroundWithTag() + { + $feature = <<gherkin->parse($feature); + } + + /** + * @expectedException \Behat\Gherkin\Exception\ParserException + */ + public function testEndlessPyString() + { + $feature = <<gherkin->parse($feature); + } + + /** + * @expectedException \Behat\Gherkin\Exception\ParserException + */ + public function testWrongStepType() + { + $feature = <<gherkin->parse($feature); + } + + /** + * @expectedException \Behat\Gherkin\Exception\ParserException + */ + public function testMultipleBackgrounds() + { + $feature = <<gherkin->parse($feature); + } + + /** + * @expectedException \Behat\Gherkin\Exception\ParserException + */ + public function testMultipleFeatures() + { + $feature = <<gherkin->parse($feature); + } +} diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/ParserTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/ParserTest.php new file mode 100644 index 0000000..f270c89 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/ParserTest.php @@ -0,0 +1,126 @@ +parseEtalon($fixtureName . '.yml'); + $features = $this->parseFixture($fixtureName . '.feature'); + + $this->assertInternalType('array', $features); + $this->assertEquals(1, count($features)); + $fixture = $features[0]; + + $this->assertEquals($etalon, $fixture); + } + + protected function getGherkinParser() + { + if (null === $this->gherkin) { + $keywords = new ArrayKeywords(array( + 'en' => array( + 'feature' => 'Feature', + 'background' => 'Background', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Scenario Outline', + 'examples' => 'Examples', + 'given' => 'Given', + 'when' => 'When', + 'then' => 'Then', + 'and' => 'And', + 'but' => 'But' + ), + 'ru' => array( + 'feature' => 'Функционал', + 'background' => 'Предыстория', + 'scenario' => 'Сценарий', + 'scenario_outline' => 'Структура сценария', + 'examples' => 'Значения', + 'given' => 'Допустим', + 'when' => 'То', + 'then' => 'Если', + 'and' => 'И', + 'but' => 'Но' + ), + 'ja' => array ( + 'feature' => 'フィーチャ', + 'background' => '背景', + 'scenario' => 'シナリオ', + 'scenario_outline' => 'シナリオアウトライン', + 'examples' => '例|サンプル', + 'given' => '前提<', + 'when' => 'もし<', + 'then' => 'ならば<', + 'and' => 'かつ<', + 'but' => 'しかし<' + ) + )); + $this->gherkin = new Parser(new Lexer($keywords)); + } + + return $this->gherkin; + } + + protected function getYamlParser() + { + if (null === $this->yaml) { + $this->yaml = new YamlFileLoader(); + } + + return $this->yaml; + } + + protected function parseFixture($fixture) + { + $file = __DIR__ . '/Fixtures/features/' . $fixture; + + return array($this->getGherkinParser()->parse(file_get_contents($file), $file)); + } + + protected function parseEtalon($etalon) + { + $features = $this->getYamlParser()->load(__DIR__ . '/Fixtures/etalons/' . $etalon); + $feature = $features[0]; + + return new FeatureNode( + $feature->getTitle(), + $feature->getDescription(), + $feature->getTags(), + $feature->getBackground(), + $feature->getScenarios(), + $feature->getKeyword(), + $feature->getLanguage(), + __DIR__ . '/Fixtures/features/' . basename($etalon, '.yml') . '.feature', + $feature->getLine() + ); + } +} diff --git a/vendor/behat/mink-extension/.travis.yml b/vendor/behat/mink-extension/.travis.yml new file mode 100644 index 0000000..f125a61 --- /dev/null +++ b/vendor/behat/mink-extension/.travis.yml @@ -0,0 +1,38 @@ +language: php + +sudo: false + +cache: + directories: + - $HOME/.composer/cache/files + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - hhvm + +matrix: + include: + - php: 5.5 + env: SYMFONY_VERSION='2.3.*' + # Test against dev dependencies + - php: 5.6 + env: DEPS=dev + +before_install: + - composer self-update + - if [ "$SYMFONY_VERSION" != "" ]; then composer require --no-update symfony/symfony=$SYMFONY_VERSION; fi; + - if [ "$DEPS" = 'dev' ]; then perl -pi -e 's/^}$/,"minimum-stability":"dev"}/' composer.json; fi; + +install: + - composer install --no-progress + +before_script: + - export PATH=./vendor/bin:$PATH + - export PATH=./vendor/bin:$PATH + +script: + - phpspec run -f pretty + - behat -fprogress --strict diff --git a/vendor/behat/mink-extension/LICENSE b/vendor/behat/mink-extension/LICENSE new file mode 100644 index 0000000..29864dd --- /dev/null +++ b/vendor/behat/mink-extension/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012 Konstantin Kudryashov + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/behat/mink-extension/README.md b/vendor/behat/mink-extension/README.md new file mode 100755 index 0000000..ea19c1a --- /dev/null +++ b/vendor/behat/mink-extension/README.md @@ -0,0 +1,44 @@ +# MinkExtension + +[![Build +Status](https://travis-ci.org/Behat/MinkExtension.svg?branch=master)](https://travis-ci.org/Behat/MinkExtension) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Behat/MinkExtension/badges/quality-score.png?s=c6474ca52322f5176a2f0cab10974aeee5e6133c)](https://scrutinizer-ci.com/g/Behat/MinkExtension/) + +MinkExtension is an integration layer between Behat 3.0+ and Mink 1.5+ +and it provides: + +* Additional services for Behat (``Mink``, ``Sessions``, ``Drivers``). +* ``Behat\MinkExtension\Context\MinkAwareContext`` which provides ``Mink`` + instance for your contexts. +* Base ``Behat\MinkExtension\Context\MinkContext`` context which provides base + step definitions and hooks for your contexts or subcontexts. Or it could be + even used as context on its own. + +## Docs + +[Official documentation](doc/index.rst). + +## Translated languages + +For now exist 10 translated languages: `cs`,`de`,`es`,`fr`,`ja`,`nl`,`pl`,`pt`,`ru`,`sv`. + +**Note:** The `ja`,`nl` and `sv` are outdated. + +#### How to add a new translated language? + +If you want to translate another language, you can use as reference the `ru` language file under +[translations folder](https://github.com/Behat/MinkExtension/tree/master/i18n). + +**Important:** The filename must match with the same translated language name in [Behat](https://github.com/Behat/Behat/blob/master/i18n.php) and [Gherkin](https://github.com/Behat/Gherkin/blob/master/i18n.php) in order to work correctly. + +If the language does not exist in [Gherkin](https://github.com/Behat/Gherkin/blob/master/i18n.php). +You should consider [contributing to Gherkin translations](https://github.com/Behat/Gherkin/blob/master/CONTRIBUTING.md#contributing-to-gherkin-translations). + +## Copyright + +Copyright (c) 2012 Konstantin Kudryashov (ever.zet). See LICENSE for details. + +## Contributors + +* Konstantin Kudryashov [everzet](http://github.com/everzet) [lead developer] +* Other [awesome developers](https://github.com/Behat/MinkExtension/graphs/contributors) diff --git a/vendor/behat/mink-extension/behat.yml.dist b/vendor/behat/mink-extension/behat.yml.dist new file mode 100644 index 0000000..e0cbd41 --- /dev/null +++ b/vendor/behat/mink-extension/behat.yml.dist @@ -0,0 +1,11 @@ +default: + suites: + default: + path: %paths.base%/features + contexts: [Behat\MinkExtension\Context\MinkContext] + extensions: + Behat\MinkExtension: + base_url: http://en.wikipedia.org/ + sessions: + default: + goutte: ~ diff --git a/vendor/behat/mink-extension/build.php b/vendor/behat/mink-extension/build.php new file mode 100755 index 0000000..e18f5dd --- /dev/null +++ b/vendor/behat/mink-extension/build.php @@ -0,0 +1,61 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +$filename = 'mink_extension.phar'; + +if (file_exists($filename)) { + unlink($filename); +} + +$phar = new \Phar($filename, 0, 'extension.phar'); +$phar->setSignatureAlgorithm(\Phar::SHA1); +$phar->startBuffering(); + +foreach (findFiles('src') as $path) { + $phar->addFromString($path, file_get_contents(__DIR__.'/'.$path)); +} + +$phar->addFromString('init.php', file_get_contents(__DIR__.'/init.php')); + +$phar->setStub(<< + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +Phar::mapPhar('extension.phar'); + +return require 'phar://extension.phar/init.php'; + +__HALT_COMPILER(); +STUB +); +$phar->stopBuffering(); + +function findFiles($dir) { + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), + RecursiveIteratorIterator::CHILD_FIRST); + + $files = array(); + foreach ($iterator as $path) { + if ($path->isFile()) { + $files[] = $path->getPath().DIRECTORY_SEPARATOR.$path->getFilename(); + } + } + + return $files; +} diff --git a/vendor/behat/mink-extension/composer.json b/vendor/behat/mink-extension/composer.json new file mode 100644 index 0000000..84b4ba2 --- /dev/null +++ b/vendor/behat/mink-extension/composer.json @@ -0,0 +1,40 @@ +{ + "name": "behat/mink-extension", + "type": "behat-extension", + "description": "Mink extension for Behat", + "keywords": ["web", "test", "browser", "gui"], + "homepage": "http://extensions.behat.org/mink", + "license": "MIT", + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com" + }, + { + "name": "Christophe Coevoet", + "email": "stof@notk.org" + } + ], + + "require": { + "php": ">=5.3.2", + "behat/behat": "~3.0,>=3.0.5", + "behat/mink": "~1.5", + "symfony/config": "~2.2" + }, + + "require-dev": { + "phpspec/phpspec": "~2.0", + "behat/mink-goutte-driver": "~1.1" + }, + + "autoload": { + "psr-0": { "Behat\\MinkExtension": "src/" } + }, + + "extra": { + "branch-alias": { + "dev-master": "2.1.x-dev" + } + } +} diff --git a/vendor/behat/mink-extension/doc/index.rst b/vendor/behat/mink-extension/doc/index.rst new file mode 100644 index 0000000..ea65972 --- /dev/null +++ b/vendor/behat/mink-extension/doc/index.rst @@ -0,0 +1,347 @@ +Mink Extension +============== + +You can use Behat to describe anything, that you can describe in business +logic. It’s tools, gui applications, web applications. Most interesting part +is web applications. First, behavioral testing already exists in web world - +it’s called functional or acceptance testing. Almost all popular frameworks +and languages provide functional testing tools. Today we’ll talk about how to +use Behat for functional testing of web applications. `Mink `_ +is a tool exactly for that and this extension provides integration for it. + +Basically, MinkExtension is an integration layer between Behat 3.0+ and Mink 1.4+ +and it provides: + +* Additional services for Behat (``Mink``, ``Sessions``, ``Drivers``). +* ``Behat\MinkExtension\Context\MinkAwareContext`` which provides ``Mink`` + instance for your contexts. +* Base ``Behat\MinkExtension\Context\MinkContext`` context which provides base + step definitions and hooks for your contexts or subcontexts. Or it could be + even used as context on its own. + +Installation +------------ + +This extension requires: + +* Behat 3.0+ +* Mink 1.4+ + +Through Composer +~~~~~~~~~~~~~~~~ + +The easiest way to keep your suite updated is to use `Composer `_: + +1. Install with composer: + + .. code-block:: bash + + $ composer require --dev behat/mink-extension + +2. Activate extension by specifying its class in your ``behat.yml``: + + .. code-block:: yaml + + # behat.yml + default: + # ... + extensions: + Behat\MinkExtension: + base_url: 'http://example.com' + sessions: + default: + goutte: ~ + +Usage +----- + +After installing extension, there would be 6 usage options available for you: + +1. Extending ``Behat\MinkExtension\Context\RawMinkContext`` in your feature suite. + This will give you ability to use a preconfigured `Mink` instance altogether with some + convenience methods: + + * ``getSession($name = null)`` + * ``assertSession($name = null)`` + + ``RawMinkContext`` doesn't provide any hooks or definitions, so you can inherit from it + in as many contexts as you want - you'll never get ``RedundantStepException``. + +2. Extending ``Behat\MinkExtension\Context\MinkContext`` with one of your contexts. + Exactly like the previous option, but also provides lots of predefined step definitions out + of the box. As this context provides step definitions and hooks, you can use it **only once** + inside your feature context tree. + + .. code-block:: php + + getSession()->wait(5000, "$('.suggestions-results').children().length > 0"); + } + } + + .. warning:: + + Keep in mind, that you can not have multiple step definitions with the same regex. + It will cause a ``RedundantException``. So, you can inherit from ``MinkContext`` + only with one of your context/subcontext classes. + +3. Adding ``Behat\MinkExtension\Context\MinkContext`` as context in your suite. + Exactly like previous option, but gives you the ability to keep your main context + class clean. + + .. code-block:: yaml + + default: + suites: + my_suite: + contexts: + - FeatureContext + - Behat\MinkExtension\Context\MinkContext + + .. note:: + + Keep in mind, that you can not have multiple step definitions with the same regex. + It will cause a ``RedundantException``. So, you can inherit from ``MinkContext`` + only with one of your context/subcontext classes. + +4. Implementing ``Behat\MinkExtension\Context\MinkAwareContext`` with your context. + +There are common things between these methods. In each of those, the target context will implement +``setMink(Mink $mink)`` and ``setMinkParameters(array $parameters)`` methods. Those methods would +be automatically called **immediately after** each context creation before each scenario. And +this ``$mink`` instance will be preconfigured based on the settings you've provided in your +``behat.yml``. + +Configuration +------------- + +MinkExtension comes with a flexible configuration system, that gives you +the ability to configure Mink inside Behat to fulfil all your needs. + +Sessions +-------- + +You can register as many Mink sessions as you want. For each session, you +will need to choose the driver you want to use. + +.. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + first_session: + selenium2: ~ + second_session: + goutte: ~ + third_session: + selenium2: ~ + +MinkExtension will set the default Mink session for each scenario based on +the configuration settings ``default_session`` and ``javascript_session`` +and on scenario tags: + +* A scenario tagged with ``@mink:foo`` will use ``foo`` as default session; +* A scenario tagged with ``@javascript`` will use the javascript session as default session; +* Other scenarios will use the default session. + +The default session and the default javascript session can also be configured for +each suite: + +.. code-block:: yaml + + default: + suites: + first: + mink_session: foo + mink_javascript_session: sahi + +If it is not configured explicitly, the javascript session is set to the first +session using a javascript driver in the order of the configuration (it would +be ``first_session`` in the example above as ``selenium2`` supports Javascript). +If it is not configured explicitly, the default session is set to the first +session using a non-javascript driver if any, or to the first javascript session +otherwise (it would be ``second_session`` above as ``goutte`` does not support +javascript). + +Drivers +~~~~~~~ + +First of all, there are drivers enabling configuration. MinkExtension comes +with support for 6 drivers out of the box: + +* ``GoutteDriver`` - headless driver without JavaScript support. In order to use + it, modify your ``behat.yml`` profile: + + .. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + my_session: + goutte: ~ + + .. Tips : HTTPS and self-signed certificate + In case you use Behat/Mink/Goutte to test your application, and want to test an + application secured with HTTPS, but with a self-signed certificate, you can use + the following parameters to avoid the validation error triggered by Guzzle: + + * For ``Guzzle 4`` or later: + + .. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + my_session: + goutte: + guzzle_parameters: + verify: false + + * For ``Guzzle 3`` or earlier: + + .. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + my_session: + goutte: + guzzle_parameters: + ssl.certificate_authority: false + +* ``Selenium2Driver`` - javascript driver. In order to use it, modify your + ``behat.yml`` profile: + + .. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + my_session: + selenium2: ~ + +* ``SauceLabsDriver`` - special flavor of the Selenium2Driver configured to use the + selenium2 hosted installation of saucelabs.com. In order to use it, modify your + ``behat.yml`` profile: + + .. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + my_session: + sauce_labs: ~ + +* ``BrowserStackDriver`` - special flavor of the Selenium2Driver configured to use the + selenium2 hosted installation of browserstack.com. In order to use it, modify your + ``behat.yml`` profile: + + .. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + my_session: + browser_stack: ~ + +* ``SeleniumDriver`` - javascript driver. In order to use it, modify your ``behat.yml`` + profile: + + .. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + my_session: + selenium: ~ + +* ``SahiDriver`` - javascript driver. In order to use it, modify your ``behat.yml`` + profile: + + .. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + my_session: + sahi: ~ + +* ``ZombieDriver`` - zombie.js javascript headless driver. In order to use it, modify + your ``behat.yml`` profile: + + .. code-block:: yaml + + default: + extensions: + Behat\MinkExtension: + sessions: + default: + zombie: ~ + +.. note:: + + The phar version of Mink comes bundled with all 5 drivers and you don't need to do + anything except enabling them in order to use them. + + But if you're using Composer, you need to install drivers that you need first: + + - GoutteDriver - ``behat/mink-goutte-driver`` + - SeleniumDriver - ``behat/mink-selenium-driver`` + - Selenium2Driver (also used for Saucelabs) - ``behat/mink-selenium2-driver`` + - SahiDriver - ``behat/mink-sahi-driver`` + - ZombieDriver - ``behat/mink-zombie-driver`` + +.. note:: + + All drivers share the same API, which means that you could use multiple drivers + for the same suite - which one fits your needs for concrete scenarios. Don't + try to stick to a single driver as there's simply no universal solution - every + driver has its pros and cons. + +Additional Parameters +~~~~~~~~~~~~~~~~~~~~~ + +There's other useful parameters, that you can use to configure your suite: + +* ``base_url`` - if you're using relative paths in your ``*.feature`` files + (and you should), then this option will define which url to use as a basename + for them. +* ``files_path`` - there's a special step definition for file upload inputs + usage. You can use relative paths in those steps. ``files_path`` defines + base path in which Mink should search those relative files. +* ``show_cmd`` - there's a special definition in MinkExtension, that saves + currently opened page into temporary file and opens it with some browser + utility (for debugging). This option defines command to be used for opening. + For example: ``show_cmd: 'firefox %s'``. +* ``show_tmp_dir`` - the temporary folder used to show the opened page (defaults + to the system temp dir) +* ``show_auto`` - Whether the opened page should be shown automatically when + a step fails. +* ``browser_name`` - meta-option, that defines which browser to use for Sahi, + Selenium and Selenium2 drivers. +* ``default_session`` - defines default session (driver) to be used for all + untagged scenarios. Could be any enabled session name. +* ``javascript_session`` - defines javascript session (driver) (the one, which + will be used for ``@javascript`` tagged scenarios). Could be any enabled session + name. +* ``mink_loader`` - path to a file loaded to make Mink available (useful when + using the PHAR archive for Mink, useless when using Composer) diff --git a/vendor/behat/mink-extension/features/search.feature b/vendor/behat/mink-extension/features/search.feature new file mode 100644 index 0000000..b4e08ef --- /dev/null +++ b/vendor/behat/mink-extension/features/search.feature @@ -0,0 +1,16 @@ +Feature: Search + In order to see a word definition + As a website user + I need to be able to search for a word + + Scenario: Searching for a page that does exist + Given I am on "/wiki/Main_Page" + When I fill in "search" with "Behavior Driven Development" + And I press "searchButton" + Then I should see "agile software development" + + Scenario: Searching for a page that does NOT exist + Given I am on "/wiki/Main_Page" + When I fill in "search" with "Glory Driven Development" + And I press "searchButton" + Then I should see "Search results" diff --git a/vendor/behat/mink-extension/i18n/cs.xliff b/vendor/behat/mink-extension/i18n/cs.xliff new file mode 100644 index 0000000..74ec33a --- /dev/null +++ b/vendor/behat/mink-extension/i18n/cs.xliff @@ -0,0 +1,143 @@ + + +
+ + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" hodnotu "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" do "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" do "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" musí obsahovat "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" nesmí obsahovat "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" musí být (?:zaškrtnuto|vybráno|označeno)$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" nesmí být (?:zaškrtnuto|vybráno|označeno)$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" musí obsahovat "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" uvnitř elementu "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) element(?:|y|ů) "(?P[^"]*)"$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/da.xliff b/vendor/behat/mink-extension/i18n/da.xliff new file mode 100644 index 0000000..cf584e3 --- /dev/null +++ b/vendor/behat/mink-extension/i18n/da.xliff @@ -0,0 +1,192 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" med "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with:$/]]> + (?:[^"]|\\")*)" med:$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" til "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" indeholde "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" ikke indeholde "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" være markeret$/]]> + + + (?:[^"]|\\")*)" (?:is|should be) checked$/]]> + (?:[^"]|\\")*)" markeret$/]]> + + + (?:[^"]|\\")*)" should (?:be unchecked|not be checked)$/]]> + (?:[^"]|\\")*)" være afmarkeret$/]]> + + + (?:[^"]|\\")*)" is (?:unchecked|not checked)$/]]> + (?:[^"]|\\")*)" afmarkeret$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" ikke være markeret$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" indeholde "(?P(?:[^"]|\\")*)"$/]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" ikke indeholde "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" i elementet "(?P[^"]*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" i elementet "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) "(?P[^"]*)" elementer?$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/de.xliff b/vendor/behat/mink-extension/i18n/de.xliff new file mode 100644 index 0000000..ed7b3b1 --- /dev/null +++ b/vendor/behat/mink-extension/i18n/de.xliff @@ -0,0 +1,167 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" "(?P(?:[^"]|\\")*)" ein$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" in "(?P(?:[^"]|\\")*)" ein$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" in "(?P(?:[^"]|\\")*)"$/]]> + + + [^"]+)"$/]]> + [^"]+)" sein$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*") übereinstimmen$/]]> + + + \d+)$/]]> + \d+) sein$/]]> + + + \d+)$/]]> + \d+) sein$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" sehen$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" sehen$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" enthalten$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" enthalten$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" im "(?P[^"]*)" Element sehen$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" im "(?P[^"]*)" Element sehen$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" Element (?:|sollte )"(?P(?:[^"]|\\")*)" enthalten$/]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" Element (?:|sollte )nicht "(?P(?:[^"]|\\")*)" enthalten$/]]> + + + [^"]*)" element$/]]> + [^"]*)" Element sehen$/]]> + + + [^"]*)" element$/]]> + [^"]*)" Element sehen$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" Feld (?:|sollte )"(?P(?:[^"]|\\")*)" enthalten$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" Feld (?:|sollte )nicht "(?P(?:[^"]|\\")*)" enthalten$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" checkbox (?:|sollte )aktiviert sein$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" checkbox (?:|sollte )nicht aktiviert sein$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) "(?P[^"]*)" Elemente? sehen$/]]> + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/es.xliff b/vendor/behat/mink-extension/i18n/es.xliff new file mode 100644 index 0000000..6292f92 --- /dev/null +++ b/vendor/behat/mink-extension/i18n/es.xliff @@ -0,0 +1,163 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" con "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" a "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" a "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" debe contener "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" no debe contener "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + [^"]*) debe estar marcada" $/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" no debe estar marcada$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" debe contener "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" en el elemento "(?P[^"]*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" en el elemento "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) "(?P[^"]*)" elementos$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/fr.xliff b/vendor/behat/mink-extension/i18n/fr.xliff new file mode 100644 index 0000000..0cf6adb --- /dev/null +++ b/vendor/behat/mink-extension/i18n/fr.xliff @@ -0,0 +1,171 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" avec "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" pour "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" à "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" devrait contenir "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" ne devrait pas contenir "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + [^"]*)" devrait être cochée$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" ne devrait pas être cochée$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" devrait contenir "(?P(?:[^"]|\\")*)"$/]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" ne devrait pas contenir "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" dans l'élément "(?P[^"]*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" dans l'élément "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) éléments? "(?P[^"]*)"$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/hu.xliff b/vendor/behat/mink-extension/i18n/hu.xliff new file mode 100644 index 0000000..a618fcb --- /dev/null +++ b/vendor/behat/mink-extension/i18n/hu.xliff @@ -0,0 +1,187 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)" oldalon (vagyok|van)$/]]> + + + [^"]+)"$/]]> + [^"]+) oldalra"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" gombot$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" linket$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" mezőt "(?P(?:[^"]|\\")*)" értékkel$/]]> + + + (?:[^"]|\\")*)" with:$/]]> + (?:[^"]|\\")*)" mezőt a következő értékekkel:$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" értékkel (kitöltöm|kitölti) az? "(?P(?:[^"]|\\")*)" mezőt$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)" legördülő listából$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)" legördülő listából$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*) opciót"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" opciót$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" fájlt az? "(?P(?:[^"]|\\")*)" mezőhöz$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" szöveget kell (látnom|látnia)$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*") mintára illeszkedő szöveget (látnom|látnia) kell$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*") mintára illeszkedő szöveget nem szabad (látnom|látnia)$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" szöveget nem szabad (látnom|látnia)$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" mezőnek tartalmaznia kell a következő értéket: "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" mezőnek nem szabad tartalmaznia a következő értéket: "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" jelölőnégyzetnek be kell jelölve lennie$/]]> + + + (?:[^"]|\\")*)" (?:is|should be) checked$/]]> + (?:[^"]|\\")*)" jelölőnégyzetnek be kell lennie jelölve$/]]> + + + (?:[^"]|\\")*)" should (?:be unchecked|not be checked)$/]]> + (?:[^"]|\\")*)" jelölőnégyzetnek törölve kell lennie$/]]> + + + (?:[^"]|\\")*)" is (?:unchecked|not checked)$/]]> + (?:[^"]|\\")*)" jelölőnégyzet törölve van$/]]> + + + [^"]+)"$/]]> + [^"]+)" oldalon kell (lennem|lennie)$/]]> + + + + + + + "([^"]|\\")*")$/]]> + "([^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" tartalmaznia kell a következő értéket: "(?P(?:[^"]|\\")*)"$/]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" nem szabad tartalmaznia a következő értéket: "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" szöveget (látnom|látnia) kell az? "(?P[^"]*)" elemben$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" szöveget nem szabad (látnom|látnia) az? "(?P[^"]*)" elemben$/]]> + + + [^"]*)" element$/]]> + [^"]*)" elemet (látnom|látnia) kell$/]]> + + + [^"]*)" element$/]]> + [^"]*)" elemet nem szabad látnia$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) darab "(?P[^"]*)" elemet kell (látnom|látnia)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/id.xliff b/vendor/behat/mink-extension/i18n/id.xliff new file mode 100644 index 0000000..8e045de --- /dev/null +++ b/vendor/behat/mink-extension/i18n/id.xliff @@ -0,0 +1,187 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" dengan (?:|nilai )"(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with:$/]]> + (?:[^"]|\\")*)" dengan (?:|nilai ):$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" untuk (?:|isian )"(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" untuk (?:|isian )"(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" harus memiliki nilai "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" tidak memiliki nilai "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" dicentang$/]]> + + + (?:[^"]|\\")*)" (?:is|should be) checked$/]]> + (?:[^"]|\\")*)" (?:harus|seharusnya) dicentang$/]]> + + + (?:[^"]|\\")*)" should (?:be unchecked|not be checked)$/]]> + (?:[^"]|\\")*)" tidak (?:harus|seharusnya) dicentang$/]]> + + + (?:[^"]|\\")*)" is (?:unchecked|not checked)$/]]> + (?:[^"]|\\")*)" (?:seharusnya |harus )tidak dicentang$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" harus memiliki nilai "(?P(?:[^"]|\\")*)"$/]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" tidak memiliki nilai "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" pada elemen "(?P[^"]*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" pada elemen "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) elemen "(?P[^"]*)"$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/it.xliff b/vendor/behat/mink-extension/i18n/it.xliff new file mode 100644 index 0000000..34ca281 --- /dev/null +++ b/vendor/behat/mink-extension/i18n/it.xliff @@ -0,0 +1,151 @@ + + +
+ + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" con "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" per il campo "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" a "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" dovrebbe contenere "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" non dovrebbe contenere "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + [^"]*)" dovrebbe essere spuntata$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" non dovrebbe essere spuntata$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" dovrebbe contenere "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" nell'elemento "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) elementi? "(?P[^"]*)"$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/ja.xliff b/vendor/behat/mink-extension/i18n/ja.xliff new file mode 100644 index 0000000..8d4e91f --- /dev/null +++ b/vendor/behat/mink-extension/i18n/ja.xliff @@ -0,0 +1,179 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^\s]+)" を表示している$/u]]> + + + [^"]+)"$/]]> + [^\s]+)" へ移動する$/u]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" ボタンをクリックする$/u]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" のリンク先へ移動する$/u]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" フィールドに "(?P(?:[^"]|\\")*)" と入力する$/u]]> + + + (?:[^"]|\\")*)" with:$/]]> + (?:[^"]|\\")*)" フィールドに以下の値を入力する:$/u]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" という値を "(?P(?:[^"]|\\")*)" に入力する$/u]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)" から選択する$/u]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)" から追加で選択する$/u]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" にチェックをつける$/u]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" のチェックをはずす$/u]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" にあるファイルを "(?P(?:[^"]|\\")*)" に添付する$/u]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" と表示されていること$/u]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" が含まれていること$/u]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" と表示されていないこと$/u]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" が含まれていないこと$/u]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" フィールドに "(?P(?:[^"]|\\")*)" が含まれていること$/u]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" フィールドに "(?P(?:[^"]|\\")*)" が含まれていないこと$/u]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" のチェックがついていること$/u]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" のチェックがはずれていること$/u]]> + + + [^"]+)"$/]]> + [^\s]+) を表示していること$/u]]> + + + + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*") にマッチすること$/u]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" エレメントに "(?P(?:[^"]|\\")*)" という値が含まれていること$/u]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" エレメントに "(?P(?:[^"]|\\")*)" という値が含まれていないこと$/u]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + [^"]*)" エレメントに "(?P(?:[^"]|\\")*)" と表示されていること$/u]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + [^"]*)" エレメントに "(?P(?:[^"]|\\")*)" と表示されていないこと$/u]]> + + + [^"]*)" element$/]]> + [^"]*)" エレメントが表示されていること$/u]]> + + + [^"]*)" element$/]]> + [^"]*)" エレメントが表示されていないこと$/u]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) 個の "(?P[^"]*)" エレメントが表示されていること$/u]]> + + + \d+)$/]]> + \d+) であること$/u]]> + + + \d+)$/]]> + \d+) ではないこと$/u]]> + + + + + + + + + + + + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")" にマッチするテキストが表示されていること$/u]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")" にマッチするテキストが表示されていないこと$/u]]> + + + + diff --git a/vendor/behat/mink-extension/i18n/nl.xliff b/vendor/behat/mink-extension/i18n/nl.xliff new file mode 100644 index 0000000..ac20a3a --- /dev/null +++ b/vendor/behat/mink-extension/i18n/nl.xliff @@ -0,0 +1,191 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)" ben$/]]> + + + [^"]+)"$/]]> + [^"]+)" ga$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" volg$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" invul met "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with:$/]]> + (?:[^"]|\\")*)" invul met:$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" invul in "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" aanvink$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" uitvink$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" toevoeg aan "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" zien$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" bevatten$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" zien$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" niet bevatten$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" "(?P(?:[^"]|\\")*)" bevatten$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" "(?P(?:[^"]|\\")*)" niet bevatten$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" aangevinkt zijn$/]]> + + + (?:[^"]|\\")*)" (?:is|should be) checked$/]]> + (?:[^"]|\\")*)" (?:is|zou moeten zijn) aangevinkt$/]]> + + + (?:[^"]|\\")*)" should (?:be unchecked|not be checked)$/]]> + (?:[^"]|\\")*)" niet aangevinkt zijn$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" niet aangevinkt zijn$/]]> + + + (?:[^"]|\\")*)" is (?:unchecked|not checked)$/]]> + (?:[^"]|\\")*)" is niet aangevinkt$/]]> + + + [^"]+)"$/]]> + [^"]+)" zijn$/]]> + + + + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" "(?P(?:[^"]|\\")*)" bevatten$/]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" niet "(?P(?:[^"]|\\")*)" bevatten$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" zien in "(?P[^"]*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" niet zien in "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)" zien$/]]> + + + [^"]*)" element$/]]> + [^"]*)" niet zien$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) "(?P[^"]*)" elementen zien$/]]> + + + \d+)$/]]> + \d+) zijn$/]]> + + + \d+)$/]]> + \d+) zijn$/]]> + + + + + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/pl.xliff b/vendor/behat/mink-extension/i18n/pl.xliff new file mode 100644 index 0000000..8ba30cc --- /dev/null +++ b/vendor/behat/mink-extension/i18n/pl.xliff @@ -0,0 +1,143 @@ + + +
+ + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" wartością "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" w polu "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" w polu "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" powinno zawierać wartość "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" nie powinno zawierać wartości "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" jest zaznaczone$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" jest odznaczone$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" powinien zawierać "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" wewnątrz elementu "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) element(y|ów)? "(?P[^"]*)"$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/pt-br.xliff b/vendor/behat/mink-extension/i18n/pt-br.xliff new file mode 100644 index 0000000..6a8e41e --- /dev/null +++ b/vendor/behat/mink-extension/i18n/pt-br.xliff @@ -0,0 +1,187 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" com "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with:$/]]> + (?:[^"]|\\")*)" com:$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" no campo "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" no campo "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" deve conter o valor "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" não deve conter o valor "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" deve ser marcado$/]]> + + + (?:[^"]|\\")*)" (?:is|should be) checked$/]]> + (?:[^"]|\\")*)" deve estar marcado$/]]> + + + (?:[^"]|\\")*)" should (?:be unchecked|not be checked)$/]]> + (?:[^"]|\\")*)" deve ser desmarcado$/]]> + + + (?:[^"]|\\")*)" is (?:unchecked|not checked)$/]]> + (?:[^"]|\\")*)" deve estar desmarcado$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + "([^"]|\\")*")$/]]> + "([^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" deve conter "(?P(?:[^"]|\\")*)"$/]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" não deve conter "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" no elemento "(?P[^"]*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" no elemento "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) elementos? "(?P[^"]*)"$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/pt.xliff b/vendor/behat/mink-extension/i18n/pt.xliff new file mode 100644 index 0000000..ac997ca --- /dev/null +++ b/vendor/behat/mink-extension/i18n/pt.xliff @@ -0,0 +1,163 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" com "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" para "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" ao "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" deve conter "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" não deve conter "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" deve (?:ser|estar) marcado$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" não deve (?:ser|estar) marcado$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" deve conter "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" no elemento "(?P[^"]*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" no elemento "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) elementos? "(?P[^"]*)"$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/ru.xliff b/vendor/behat/mink-extension/i18n/ru.xliff new file mode 100644 index 0000000..00309d3 --- /dev/null +++ b/vendor/behat/mink-extension/i18n/ru.xliff @@ -0,0 +1,191 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" значением "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with:$/]]> + (?:[^"]|\\")*)" значениями:$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" в поле "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" в поле "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" должно содержать "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" не должно содержать "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" должна быть отмечена$/]]> + + + (?:[^"]|\\")*)" (?:is|should be) checked$/]]> + (?:[^"]|\\")*)" отмечена$/]]> + + + (?:[^"]|\\")*)" should (?:be unchecked|not be checked)$/]]> + (?:[^"]|\\")*)" не должна быть отмечена$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" должна быть не отмечена$/]]> + + + (?:[^"]|\\")*)" is (?:unchecked|not checked)$/]]> + (?:[^"]|\\")*)" не отмечена$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" должен содержать "(?P(?:[^"]|\\")*)"$/]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" не должен содержать "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" внутри элемента "(?P[^"]*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" внутри элемента "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) элемент(ов|а)? "(?P[^"]*)"$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/sk.xliff b/vendor/behat/mink-extension/i18n/sk.xliff new file mode 100644 index 0000000..8d06b23 --- /dev/null +++ b/vendor/behat/mink-extension/i18n/sk.xliff @@ -0,0 +1,151 @@ + + +
+ + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" (?:hodnotou|hodnotu) "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" (?:hodnotu|hodnotou) "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" do "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" (?:musí obsahovať|malo by obsahovať|by malo obsahovať|obsahuje)(?:| text| hodnotu) "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" (?:nesmie obsahovať|nemalo by obsahovať|by nemalo obsahovať|neobsahuje)(?:| text| hodnotu) "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" (?:by malo byť|je) (?:zaškrtnuté|označené)$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" (?:by nemalo byť|nie je) (?:zaškrtnuté|označené)$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" (?:by mal|mal by|musí) obsahovať(?:| text| hodnotu) "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" v elemente "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) elementov "(?P[^"]*)"$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/sv.xliff b/vendor/behat/mink-extension/i18n/sv.xliff new file mode 100644 index 0000000..d3c60b8 --- /dev/null +++ b/vendor/behat/mink-extension/i18n/sv.xliff @@ -0,0 +1,131 @@ + + +
+ + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" med "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" för "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" till "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" skulle inehålla "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" skulle inte innehålla "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" skulle vara markerat$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" skulle inte vara markerat$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" skulle innehålla "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" i "(?P[^"]*)" elementet$/]]> + + + [^"]*)" element$/]]> + [^"]*)" element$/]]> + + + [^"]*)" element$/]]> + [^"]*)" element$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + + diff --git a/vendor/behat/mink-extension/i18n/zh-CN.xliff b/vendor/behat/mink-extension/i18n/zh-CN.xliff new file mode 100644 index 0000000..99136cb --- /dev/null +++ b/vendor/behat/mink-extension/i18n/zh-CN.xliff @@ -0,0 +1,157 @@ + + +
+ + + [^"]+)"$/]]> + [^\s]+)”$/]]> + + + [^"]+)"$/]]> + [^\s]+)”$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”按钮$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”链接$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”文本框内填写了“(?P(?:[^"]|\\")*)”$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”到“(?P(?:[^"]|\\")*)”文本框$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”选择框里面添加了“(?P + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”选项$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”选项$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)”到“(?P(?:[^"]|\\")*)”文件选择框$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”的内容$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”的内容$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”的内容$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”的内容$/]]> + + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”文本框应该包含值“(?P(?:[^"]|\\")*)”$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)”文本框应该不包含值“(?P(?:[^"]|\\")*)”$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)”选项框应该已经选中了$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)”选项框应该还没有选中$/]]> + + + [^"]+)"$/]]> + [^\s]+)”$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")”$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)”元素应该包含“(?P(?:[^"]|\\")*)”内容$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + [^"]*)”元素应该有“(?P(?:[^"]|\\")*)”内容$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + [^"]*)”元素应该没有“(?P(?:[^"]|\\")*)”内容$/]]> + + + [^"]*)" element$/]]> + [^"]*)”元素$/]]> + + + [^"]*)" element$/]]> + [^"]*)”元素$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) 个“(?P[^"]*)”元素$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + \d+)$/]]> + \d+)$/]]> + + + + + + + + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")”$/]]> + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")”$/]]> + + + + diff --git a/vendor/behat/mink-extension/init.php b/vendor/behat/mink-extension/init.php new file mode 100644 index 0000000..db8e96b --- /dev/null +++ b/vendor/behat/mink-extension/init.php @@ -0,0 +1,19 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +spl_autoload_register(function($class) { + if (false !== strpos($class, 'Behat\\MinkExtension')) { + require_once(__DIR__.'/src/'.str_replace('\\', '/', $class).'.php'); + return true; + } +}, true, false); + +return new Behat\MinkExtension\ServiceContainer\MinkExtension; diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/Context/Initializer/MinkAwareInitializerSpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/Context/Initializer/MinkAwareInitializerSpec.php new file mode 100644 index 0000000..84b208a --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/Context/Initializer/MinkAwareInitializerSpec.php @@ -0,0 +1,33 @@ +beConstructedWith($mink, array('base_url' => 'foo')); + } + + function it_is_a_context_initializer() + { + $this->shouldHaveType('Behat\Behat\Context\Initializer\ContextInitializer'); + } + + function it_does_nothing_for_basic_contexts(Context $context) + { + $this->initializeContext($context); + } + + function it_injects_mink_and_parameters_in_mink_aware_contexts(MinkAwareContext $context, $mink) + { + $context->setMink($mink)->shouldBeCalled(); + $context->setMinkParameters(array('base_url' => 'foo'))->shouldBeCalled(); + $this->initializeContext($context); + } +} diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/Listener/SessionsListenerSpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/Listener/SessionsListenerSpec.php new file mode 100644 index 0000000..be72e21 --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/Listener/SessionsListenerSpec.php @@ -0,0 +1,174 @@ +beConstructedWith($mink, 'goutte', 'selenium2', array('selenium2', 'sahi')); + + $event->getSuite()->willReturn($suite); + $event->getFeature()->willReturn($feature); + $event->getScenario()->willReturn($scenario); + + $suite->hasSetting('mink_session')->willReturn(false); + $suite->getName()->willReturn('default'); + + $feature->hasTag('insulated')->willReturn(false); + $feature->getTags()->willReturn(array()); + $scenario->hasTag('insulated')->willReturn(false); + $scenario->getTags()->willReturn(array()); + } + + function it_is_an_event_subscriber() + { + $this->shouldHaveType('Symfony\Component\EventDispatcher\EventSubscriberInterface'); + } + + function it_resets_the_default_session_before_scenarios($event, $mink) + { + $mink->resetSessions()->shouldBeCalled(); + $mink->setDefaultSessionName('goutte')->shouldBeCalled(); + + $this->prepareDefaultMinkSession($event); + } + + function it_supports_changing_the_default_session_per_suite($event, $mink, $suite) + { + $suite->hasSetting('mink_session')->willReturn(true); + $suite->getSetting('mink_session')->willReturn('test'); + + $mink->resetSessions()->shouldBeCalled(); + $mink->setDefaultSessionName('test')->shouldBeCalled(); + + $this->prepareDefaultMinkSession($event); + } + + function it_fails_for_non_string_default_suite_session($event, $suite) + { + $suite->hasSetting('mink_session')->willReturn(true); + $suite->getSetting('mink_session')->willReturn(array()); + + $this->shouldThrow(new SuiteConfigurationException('`mink_session` setting of the "default" suite is expected to be a string, array given.', 'default')) + ->duringPrepareDefaultMinkSession($event); + } + + function it_switches_to_the_javascript_session_for_tagged_scenarios($event, $mink, $scenario, $suite) + { + $suite->hasSetting('mink_javascript_session')->willReturn(false); + $scenario->getTags()->willReturn(array('javascript')); + $mink->resetSessions()->shouldBeCalled(); + $mink->setDefaultSessionName('selenium2')->shouldBeCalled(); + + $this->prepareDefaultMinkSession($event); + } + + function it_switches_to_the_javascript_session_for_tagged_features($event, $mink, $feature, $suite) + { + $suite->hasSetting('mink_javascript_session')->willReturn(false); + $feature->getTags()->willReturn(array('javascript')); + $mink->resetSessions()->shouldBeCalled(); + $mink->setDefaultSessionName('selenium2')->shouldBeCalled(); + + $this->prepareDefaultMinkSession($event); + } + + function it_supports_changing_the_default_javascript_session_per_suite($event, $mink, $scenario, $suite) + { + $suite->hasSetting('mink_javascript_session')->willReturn(true); + $suite->getSetting('mink_javascript_session')->willReturn('sahi'); + + $scenario->getTags()->willReturn(array('javascript')); + $mink->resetSessions()->shouldBeCalled(); + $mink->setDefaultSessionName('sahi')->shouldBeCalled(); + + $this->prepareDefaultMinkSession($event); + } + + function it_fails_for_non_string_javascript_suite_session($event, $scenario, $suite) + { + $suite->hasSetting('mink_javascript_session')->willReturn(true); + $suite->getSetting('mink_javascript_session')->willReturn(array()); + + $scenario->getTags()->willReturn(array('javascript')); + + $this->shouldThrow(new SuiteConfigurationException('`mink_javascript_session` setting of the "default" suite is expected to be a string, array given.', 'default')) + ->duringPrepareDefaultMinkSession($event); + } + + function it_fails_for_invalid_javascript_suite_session($event, $scenario, $suite) + { + $suite->hasSetting('mink_javascript_session')->willReturn(true); + $suite->getSetting('mink_javascript_session')->willReturn('test'); + + $scenario->getTags()->willReturn(array('javascript')); + + $this->shouldThrow(new SuiteConfigurationException('`mink_javascript_session` setting of the "default" suite is not a javascript session. test given but expected one of selenium2, sahi.', 'default')) + ->duringPrepareDefaultMinkSession($event); + } + + function it_fails_when_the_javascript_session_is_used_but_not_defined($event, $mink, $feature, $suite) + { + $suite->hasSetting('mink_javascript_session')->willReturn(false); + $this->beConstructedWith($mink, 'goutte', null); + $feature->getTags()->willReturn(array('javascript')); + + $this->shouldThrow(new ProcessingException('The @javascript tag cannot be used without enabling a javascript session')) + ->duringPrepareDefaultMinkSession($event); + } + + function it_switches_to_a_named_session($event, $mink, $scenario) + { + $scenario->getTags()->willReturn(array('mink:test')); + $mink->resetSessions()->shouldBeCalled(); + $mink->setDefaultSessionName('test')->shouldBeCalled(); + + $this->prepareDefaultMinkSession($event); + } + + function it_prefers_the_scenario_over_the_feature($event, $mink, $scenario, $feature, $suite) + { + $suite->hasSetting('mink_javascript_session')->willReturn(false); + $scenario->getTags()->willReturn(array('mink:test')); + $feature->getTags()->willReturn(array('javascript')); + $mink->resetSessions()->shouldBeCalled(); + $mink->setDefaultSessionName('test')->shouldBeCalled(); + + $this->prepareDefaultMinkSession($event); + } + + function it_stops_the_sessions_for_insulated_scenarios($event, $mink, $scenario) + { + $scenario->hasTag('insulated')->willReturn(true); + $mink->stopSessions()->shouldBeCalled(); + $mink->setDefaultSessionName('goutte')->shouldBeCalled(); + + $this->prepareDefaultMinkSession($event); + } + + function it_stops_the_sessions_for_insulated_features($event, $mink, $feature) + { + $feature->hasTag('insulated')->willReturn(true); + $mink->stopSessions()->shouldBeCalled(); + $mink->setDefaultSessionName('goutte')->shouldBeCalled(); + + $this->prepareDefaultMinkSession($event); + } + + function it_stops_the_sessions_at_the_end_of_the_exercise($mink) + { + $mink->stopSessions()->shouldBeCalled(); + + $this->tearDownMinkSessions(); + } +} diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/BrowserStackFactorySpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/BrowserStackFactorySpec.php new file mode 100644 index 0000000..00922e7 --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/BrowserStackFactorySpec.php @@ -0,0 +1,24 @@ +shouldHaveType('Behat\MinkExtension\ServiceContainer\Driver\DriverFactory'); + } + + function it_is_named_browser_stack() + { + $this->getDriverName()->shouldReturn('browser_stack'); + } + + function it_supports_javascript() + { + $this->supportsJavascript()->shouldBe(true); + } +} diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/GoutteFactorySpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/GoutteFactorySpec.php new file mode 100644 index 0000000..484e6e7 --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/GoutteFactorySpec.php @@ -0,0 +1,23 @@ +shouldHaveType('Behat\MinkExtension\ServiceContainer\Driver\DriverFactory'); + } + + function it_is_named_goutte() + { + $this->getDriverName()->shouldReturn('goutte'); + } + + function it_does_not_support_javascript() + { + $this->supportsJavascript()->shouldBe(false); + } +} diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/SahiFactorySpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/SahiFactorySpec.php new file mode 100644 index 0000000..abdb7d5 --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/SahiFactorySpec.php @@ -0,0 +1,23 @@ +shouldHaveType('Behat\MinkExtension\ServiceContainer\Driver\DriverFactory'); + } + + function it_is_named_sahi() + { + $this->getDriverName()->shouldReturn('sahi'); + } + + function it_supports_javascript() + { + $this->supportsJavascript()->shouldBe(true); + } +} diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/SauceLabsFactorySpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/SauceLabsFactorySpec.php new file mode 100644 index 0000000..21bb10c --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/SauceLabsFactorySpec.php @@ -0,0 +1,23 @@ +shouldHaveType('Behat\MinkExtension\ServiceContainer\Driver\DriverFactory'); + } + + function it_is_named_sauce_labs() + { + $this->getDriverName()->shouldReturn('sauce_labs'); + } + + function it_supports_javascript() + { + $this->supportsJavascript()->shouldBe(true); + } +} diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/Selenium2FactorySpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/Selenium2FactorySpec.php new file mode 100644 index 0000000..5ec5c16 --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/Selenium2FactorySpec.php @@ -0,0 +1,23 @@ +shouldHaveType('Behat\MinkExtension\ServiceContainer\Driver\DriverFactory'); + } + + function it_is_named_selenium2() + { + $this->getDriverName()->shouldReturn('selenium2'); + } + + function it_supports_javascript() + { + $this->supportsJavascript()->shouldBe(true); + } +} diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/SeleniumFactorySpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/SeleniumFactorySpec.php new file mode 100644 index 0000000..a1fb505 --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/SeleniumFactorySpec.php @@ -0,0 +1,23 @@ +shouldHaveType('Behat\MinkExtension\ServiceContainer\Driver\DriverFactory'); + } + + function it_is_named_selenium() + { + $this->getDriverName()->shouldReturn('selenium'); + } + + function it_supports_javascript() + { + $this->supportsJavascript()->shouldBe(true); + } +} diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/ZombieFactorySpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/ZombieFactorySpec.php new file mode 100644 index 0000000..f0e0445 --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/Driver/ZombieFactorySpec.php @@ -0,0 +1,23 @@ +shouldHaveType('Behat\MinkExtension\ServiceContainer\Driver\DriverFactory'); + } + + function it_is_named_zombie() + { + $this->getDriverName()->shouldReturn('zombie'); + } + + function it_supports_javascript() + { + $this->supportsJavascript()->shouldBe(true); + } +} diff --git a/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/MinkExtensionSpec.php b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/MinkExtensionSpec.php new file mode 100644 index 0000000..c16533b --- /dev/null +++ b/vendor/behat/mink-extension/spec/Behat/MinkExtension/ServiceContainer/MinkExtensionSpec.php @@ -0,0 +1,18 @@ +shouldHaveType('Behat\Testwork\ServiceContainer\Extension'); + } + + function it_is_named_mink() + { + $this->getConfigKey()->shouldReturn('mink'); + } +} diff --git a/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/Initializer/MinkAwareInitializer.php b/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/Initializer/MinkAwareInitializer.php new file mode 100644 index 0000000..bbb45ab --- /dev/null +++ b/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/Initializer/MinkAwareInitializer.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\MinkExtension\Context\Initializer; + +use Behat\Behat\Context\Context; +use Behat\Behat\Context\Initializer\ContextInitializer; + +use Behat\Mink\Mink; +use Behat\MinkExtension\Context\MinkAwareContext; + +/** + * Mink aware contexts initializer. + * Sets Mink instance and parameters to the MinkAware contexts. + * + * @author Konstantin Kudryashov + */ +class MinkAwareInitializer implements ContextInitializer +{ + private $mink; + private $parameters; + + /** + * Initializes initializer. + * + * @param Mink $mink + * @param array $parameters + */ + public function __construct(Mink $mink, array $parameters) + { + $this->mink = $mink; + $this->parameters = $parameters; + } + + /** + * Initializes provided context. + * + * @param Context $context + */ + public function initializeContext(Context $context) + { + if (!$context instanceof MinkAwareContext) { + return; + } + + $context->setMink($this->mink); + $context->setMinkParameters($this->parameters); + } +} diff --git a/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/MinkAwareContext.php b/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/MinkAwareContext.php new file mode 100644 index 0000000..11aaa4f --- /dev/null +++ b/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/MinkAwareContext.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\MinkExtension\Context; + +use Behat\Behat\Context\Context; +use Behat\Mink\Mink; + +/** + * Mink aware interface for contexts. + * + * @author Konstantin Kudryashov + */ +interface MinkAwareContext extends Context +{ + /** + * Sets Mink instance. + * + * @param Mink $mink Mink session manager + */ + public function setMink(Mink $mink); + + /** + * Sets parameters provided for Mink. + * + * @param array $parameters + */ + public function setMinkParameters(array $parameters); +} diff --git a/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/MinkContext.php b/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/MinkContext.php new file mode 100644 index 0000000..90ea038 --- /dev/null +++ b/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/MinkContext.php @@ -0,0 +1,486 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\MinkExtension\Context; + +use Behat\Behat\Context\TranslatableContext; +use Behat\Gherkin\Node\TableNode; + +/** + * Mink context for Behat BDD tool. + * Provides Mink integration and base step definitions. + * + * @author Konstantin Kudryashov + */ +class MinkContext extends RawMinkContext implements TranslatableContext +{ + /** + * Opens homepage. + * + * @Given /^(?:|I )am on (?:|the )homepage$/ + * @When /^(?:|I )go to (?:|the )homepage$/ + */ + public function iAmOnHomepage() + { + $this->visitPath('/'); + } + + /** + * Opens specified page. + * + * @Given /^(?:|I )am on "(?P[^"]+)"$/ + * @When /^(?:|I )go to "(?P[^"]+)"$/ + */ + public function visit($page) + { + $this->visitPath($page); + } + + /** + * Reloads current page. + * + * @When /^(?:|I )reload the page$/ + */ + public function reload() + { + $this->getSession()->reload(); + } + + /** + * Moves backward one page in history. + * + * @When /^(?:|I )move backward one page$/ + */ + public function back() + { + $this->getSession()->back(); + } + + /** + * Moves forward one page in history + * + * @When /^(?:|I )move forward one page$/ + */ + public function forward() + { + $this->getSession()->forward(); + } + + /** + * Presses button with specified id|name|title|alt|value. + * + * @When /^(?:|I )press "(?P