From: jenny Date: Fri, 10 Nov 2017 09:11:28 +0000 (+0000) Subject: Security update for permissions_by_term X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=commitdiff_plain;h=1270d9129ce8f27c9b28b10518e32132c58e0aca Security update for permissions_by_term --- diff --git a/composer.lock b/composer.lock index ec4a0f43c..1e3d12385 100644 --- a/composer.lock +++ b/composer.lock @@ -122,6 +122,481 @@ ], "time": "2017-04-11T20:03:41+00:00" }, + { + "name": "behat/behat", + "version": "v3.4.1", + "source": { + "type": "git", + "url": "https://github.com/Behat/Behat.git", + "reference": "cb51d4b0b11ea6d3897f3589a871a63a33632692" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Behat/zipball/cb51d4b0b11ea6d3897f3589a871a63a33632692", + "reference": "cb51d4b0b11ea6d3897f3589a871a63a33632692", + "shasum": "" + }, + "require": { + "behat/gherkin": "^4.5.1", + "behat/transliterator": "^1.2", + "container-interop/container-interop": "^1.2", + "ext-mbstring": "*", + "php": ">=5.3.3", + "psr/container": "^1.0", + "symfony/class-loader": "~2.1||~3.0", + "symfony/config": "~2.3||~3.0", + "symfony/console": "~2.5||~3.0", + "symfony/dependency-injection": "~2.1||~3.0", + "symfony/event-dispatcher": "~2.1||~3.0", + "symfony/translation": "~2.3||~3.0", + "symfony/yaml": "~2.1||~3.0" + }, + "require-dev": { + "herrera-io/box": "~1.6.1", + "phpunit/phpunit": "~4.5", + "symfony/process": "~2.5|~3.0" + }, + "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.2.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": "2017-09-18T11:10:28+00:00" + }, + { + "name": "behat/gherkin", + "version": "v4.5.1", + "source": { + "type": "git", + "url": "https://github.com/Behat/Gherkin.git", + "reference": "74ac03d52c5e23ad8abd5c5cce4ab0e8dc1b530a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Gherkin/zipball/74ac03d52c5e23ad8abd5c5cce4ab0e8dc1b530a", + "reference": "74ac03d52c5e23ad8abd5c5cce4ab0e8dc1b530a", + "shasum": "" + }, + "require": { + "php": ">=5.3.1" + }, + "require-dev": { + "phpunit/phpunit": "~4.5|~5", + "symfony/phpunit-bridge": "~2.7|~3", + "symfony/yaml": "~2.3|~3" + }, + "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": "2017-08-30T11:04:43+00:00" + }, + { + "name": "behat/mink", + "version": "v1.7.1", + "source": { + "type": "git", + "url": "https://github.com/minkphp/Mink.git", + "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/Mink/zipball/e6930b9c74693dff7f4e58577e1b1743399f3ff9", + "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9", + "shasum": "" + }, + "require": { + "php": ">=5.3.1", + "symfony/css-selector": "~2.1|~3.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0" + }, + "suggest": { + "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", + "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", + "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", + "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Mink\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Browser controller/emulator abstraction for PHP", + "homepage": "http://mink.behat.org/", + "keywords": [ + "browser", + "testing", + "web" + ], + "time": "2016-03-05T08:26:18+00:00" + }, + { + "name": "behat/mink-browserkit-driver", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", + "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/10e67fb4a295efcd62ea0bf16025a85ea19534fb", + "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb", + "shasum": "" + }, + "require": { + "behat/mink": "^1.7.1@dev", + "php": ">=5.3.6", + "symfony/browser-kit": "~2.3|~3.0", + "symfony/dom-crawler": "~2.3|~3.0" + }, + "require-dev": { + "silex/silex": "~1.2", + "symfony/phpunit-bridge": "~2.7|~3.0" + }, + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Symfony2 BrowserKit driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "Mink", + "Symfony2", + "browser", + "testing" + ], + "time": "2016-03-05T08:59:47+00:00" + }, + { + "name": "behat/mink-extension", + "version": "v2.2", + "source": { + "type": "git", + "url": "https://github.com/Behat/MinkExtension.git", + "reference": "5b4bda64ff456104564317e212c823e45cad9d59" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/MinkExtension/zipball/5b4bda64ff456104564317e212c823e45cad9d59", + "reference": "5b4bda64ff456104564317e212c823e45cad9d59", + "shasum": "" + }, + "require": { + "behat/behat": "~3.0,>=3.0.5", + "behat/mink": "~1.5", + "php": ">=5.3.2", + "symfony/config": "~2.2|~3.0" + }, + "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": "2016-02-15T07:55:18+00:00" + }, + { + "name": "behat/mink-goutte-driver", + "version": "v1.2.1", + "source": { + "type": "git", + "url": "https://github.com/minkphp/MinkGoutteDriver.git", + "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", + "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", + "shasum": "" + }, + "require": { + "behat/mink": "~1.6@dev", + "behat/mink-browserkit-driver": "~1.2@dev", + "fabpot/goutte": "~1.0.4|~2.0|~3.1", + "php": ">=5.3.1" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7|~3.0" + }, + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + } + ], + "description": "Goutte driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "browser", + "goutte", + "headless", + "testing" + ], + "time": "2016-03-05T09:04:22+00:00" + }, + { + "name": "behat/mink-selenium2-driver", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/minkphp/MinkSelenium2Driver.git", + "reference": "473a9f3ebe0c134ee1e623ce8a9c852832020288" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/473a9f3ebe0c134ee1e623ce8a9c852832020288", + "reference": "473a9f3ebe0c134ee1e623ce8a9c852832020288", + "shasum": "" + }, + "require": { + "behat/mink": "~1.7@dev", + "instaclick/php-webdriver": "~1.1", + "php": ">=5.3.1" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "type": "mink-driver", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Pete Otaqui", + "email": "pete@otaqui.com", + "homepage": "https://github.com/pete-otaqui" + } + ], + "description": "Selenium2 (WebDriver) driver for Mink framework", + "homepage": "http://mink.behat.org/", + "keywords": [ + "ajax", + "browser", + "javascript", + "selenium", + "testing", + "webdriver" + ], + "time": "2016-03-05T09:10:18+00:00" + }, + { + "name": "behat/transliterator", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/Behat/Transliterator.git", + "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Behat/Transliterator/zipball/826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", + "reference": "826ce7e9c2a6664c0d1f381cbb38b1fb80a7ee2c", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "chuyskywalker/rolling-curl": "^3.1", + "php-yaoi/php-yaoi": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-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": "2017-04-04T11:38:05+00:00" + }, { "name": "caxy/php-htmldiff", "version": "v0.1.5", @@ -515,6 +990,37 @@ "description": "Format text by applying transformations provided by plug-in formatters.", "time": "2017-06-06T19:08:54+00:00" }, + { + "name": "container-interop/container-interop", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8", + "shasum": "" + }, + "require": { + "psr/container": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "homepage": "https://github.com/container-interop/container-interop", + "time": "2017-02-14T19:40:03+00:00" + }, { "name": "cweagans/composer-patches", "version": "1.6.1", @@ -1398,7 +1904,8 @@ "source": "https://cgit.drupalcode.org/advanced_help", "issues": "https://www.drupal.org/project/issues/advanced_help", "irc": "irc://irc.freenode.org/drupal-contribute" - } + }, + "time": "2017-03-31T05:17:03+00:00" }, { "name": "drupal/better_formats", @@ -2707,6 +3214,124 @@ "source": "http://cgit.drupalcode.org/dropzonejs" } }, + { + "name": "drupal/drupal-driver", + "version": "v1.2.1", + "source": { + "type": "git", + "url": "https://github.com/jhedstrom/DrupalDriver.git", + "reference": "125d39918c97f7a08e3110d456a0a1db864dae46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jhedstrom/DrupalDriver/zipball/125d39918c97f7a08e3110d456a0a1db864dae46", + "reference": "125d39918c97f7a08e3110d456a0a1db864dae46", + "shasum": "" + }, + "require": { + "symfony/dependency-injection": "~2.6|~3.0", + "symfony/process": "~2.5|~3.0" + }, + "require-dev": { + "drupal/coder": "~8.2.0", + "drush-ops/behat-drush-endpoint": "*", + "mockery/mockery": "0.9.4", + "phpspec/phpspec": "~2.0", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-0": { + "Drupal\\Component": "src/", + "Drupal\\Driver": "src/", + "Drupal\\Tests\\Driver": "tests/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "authors": [ + { + "name": "Jonathan Hedstrom", + "email": "jhedstrom@gmail.com" + } + ], + "description": "A collection of reusable Drupal drivers", + "homepage": "http://github.com/jhedstrom/DrupalDriver", + "keywords": [ + "drupal", + "test", + "web" + ], + "time": "2016-06-20T16:29:51+00:00" + }, + { + "name": "drupal/drupal-extension", + "version": "v3.3.1", + "source": { + "type": "git", + "url": "https://github.com/jhedstrom/drupalextension.git", + "reference": "2a858760208856391f7e5e4d269fba2c1df110a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jhedstrom/drupalextension/zipball/2a858760208856391f7e5e4d269fba2c1df110a4", + "reference": "2a858760208856391f7e5e4d269fba2c1df110a4", + "shasum": "" + }, + "require": { + "behat/behat": "~3.2", + "behat/mink": "~1.5", + "behat/mink-extension": "~2.0", + "behat/mink-goutte-driver": "~1.0", + "behat/mink-selenium2-driver": "~1.1", + "drupal/drupal-driver": "~1.2", + "symfony/dependency-injection": "~2.7|~3.0", + "symfony/event-dispatcher": "~2.7|~3.0" + }, + "require-dev": { + "behat/mink-zombie-driver": "^1.2", + "phpspec/phpspec": "~2.0", + "phpunit/phpunit": "3.7.*" + }, + "type": "behat-extension", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "psr-0": { + "Drupal\\Drupal": "src/", + "Drupal\\Exception": "src/", + "Drupal\\DrupalExtension": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "authors": [ + { + "name": "Jonathan Hedstrom", + "email": "jhedstrom@gmail.com" + } + ], + "description": "Drupal extension for Behat", + "homepage": "http://drupal.org/project/drupalextension", + "keywords": [ + "drupal", + "test", + "web" + ], + "time": "2017-09-13T19:54:23+00:00" + }, { "name": "drupal/drupalmoduleupgrader", "version": "dev-1.x", @@ -5101,20 +5726,28 @@ }, { "name": "drupal/permissions_by_term", - "version": "1.19.0", + "version": "1.35.0", "source": { "type": "git", "url": "https://git.drupal.org/project/permissions_by_term", - "reference": "8.x-1.19" + "reference": "8.x-1.35" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/permissions_by_term-8.x-1.19.zip", - "reference": "8.x-1.19", - "shasum": "87ecf60dda39138f648ee57fe4e3ce334b187100" + "url": "https://ftp.drupal.org/files/projects/permissions_by_term-8.x-1.35.zip", + "reference": "8.x-1.35", + "shasum": "4f9a7406a81a2e03f90e278fd6921f8fc962f07b" }, "require": { - "drupal/core": "*" + "behat/behat": "^3.1", + "behat/mink": "^1.7", + "behat/mink-extension": "^2.2", + "behat/mink-goutte-driver": "^1.2", + "behat/mink-selenium2-driver": "^1.3", + "drupal/core": "*", + "drupal/drupal-driver": "~1.0", + "drupal/drupal-extension": "~3.0", + "guzzlehttp/guzzle": "^6.0@dev" }, "type": "drupal-module", "extra": { @@ -5122,8 +5755,17 @@ "dev-1.x": "1.x-dev" }, "drupal": { - "version": "8.x-1.19", - "datestamp": "1494360188" + "version": "8.x-1.35", + "datestamp": "1509945000", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "autoload": { + "psr-4": { + "PermissionsByTerm\\": "tests/src/Behat/Context/" } }, "notification-url": "https://packages.drupal.org/8/downloads", @@ -5133,10 +5775,19 @@ "authors": [ { "name": "Peter Majmesku", - "homepage": "https://www.drupal.org/user/786132" + "homepage": "https://www.drupal.org/user/786132", + "email": "p.majmesku@gmail.com" + }, + { + "name": "dakku", + "homepage": "https://www.drupal.org/user/97634" + }, + { + "name": "rackberg", + "homepage": "https://www.drupal.org/user/2806873" } ], - "description": "Limits the selection of specific taxonomy terms by users or roles. Prevents users to display nodes and nodes on views pages, for which which they do not have access by taxonomy term restriction.", + "description": "Restricts access to nodes by taxonomy terms in relation to users and their roles.", "homepage": "https://www.drupal.org/project/permissions_by_term", "support": { "source": "http://cgit.drupalcode.org/permissions_by_term" @@ -5993,7 +6644,8 @@ ], "support": { "source": "http://cgit.drupalcode.org/views_bootstrap" - } + }, + "time": "2017-03-29T14:23:33+00:00" }, { "name": "drupal/views_responsive_grid", @@ -6392,6 +7044,55 @@ ], "time": "2017-06-03T02:28:16+00:00" }, + { + "name": "fabpot/goutte", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/Goutte.git", + "reference": "db5c28f4a010b4161d507d5304e28a7ebf211638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/db5c28f4a010b4161d507d5304e28a7ebf211638", + "reference": "db5c28f4a010b4161d507d5304e28a7ebf211638", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0", + "symfony/browser-kit": "~2.1|~3.0", + "symfony/css-selector": "~2.1|~3.0", + "symfony/dom-crawler": "~2.1|~3.0" + }, + "type": "application", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Goutte\\": "Goutte" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "A simple PHP Web Scraper", + "homepage": "https://github.com/FriendsOfPHP/Goutte", + "keywords": [ + "scraper" + ], + "time": "2017-01-03T13:21:43+00:00" + }, { "name": "gabordemooij/redbean", "version": "v4.3.4", @@ -6694,6 +7395,65 @@ ], "time": "2017-03-20T17:10:46+00:00" }, + { + "name": "instaclick/php-webdriver", + "version": "1.4.5", + "source": { + "type": "git", + "url": "https://github.com/instaclick/php-webdriver.git", + "reference": "6fa959452e774dcaed543faad3a9d1a37d803327" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/6fa959452e774dcaed543faad3a9d1a37d803327", + "reference": "6fa959452e774dcaed543faad3a9d1a37d803327", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "^4.8", + "satooshi/php-coveralls": "^1.0||^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "WebDriver": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Justin Bishop", + "email": "jubishop@gmail.com", + "role": "Developer" + }, + { + "name": "Anthon Pang", + "email": "apang@softwaredevelopment.ca", + "role": "Fork Maintainer" + } + ], + "description": "PHP WebDriver for Selenium 2", + "homepage": "http://instaclick.com/", + "keywords": [ + "browser", + "selenium", + "webdriver", + "webtest" + ], + "time": "2017-06-30T04:02:48+00:00" + }, { "name": "ircmaxell/password-compat", "version": "v1.0.4", @@ -7205,43 +7965,83 @@ "keywords": [ "console" ], - "time": "2016-01-21T16:14:31+00:00" + "time": "2016-01-21T16:14:31+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e6a969a640b00d8daa3c66518b0405fb41ae0c4b", + "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "dflydev/markdown": "~1.0", + "erusev/parsedown": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpDocumentor": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "mike.vanriel@naenius.com" + } + ], + "time": "2016-01-25T08:17:30+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "2.0.5", + "name": "psr/container", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b" + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e6a969a640b00d8daa3c66518b0405fb41ae0c4b", - "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "dflydev/markdown": "~1.0", - "erusev/parsedown": "~1.0" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "phpDocumentor": [ - "src/" - ] + "psr-4": { + "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -7250,11 +8050,20 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "mike.vanriel@naenius.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "time": "2016-01-25T08:17:30+00:00" + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" }, { "name": "psr/http-message", @@ -7764,6 +8573,63 @@ ], "time": "2017-05-09T08:10:41+00:00" }, + { + "name": "symfony/browser-kit", + "version": "v3.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "c2c8ceb1aa9dab9eae54e9150e6a588ce3e53be1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/c2c8ceb1aa9dab9eae54e9150e6a588ce3e53be1", + "reference": "c2c8ceb1aa9dab9eae54e9150e6a588ce3e53be1", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/dom-crawler": "~2.8|~3.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0", + "symfony/process": "~2.8|~3.0" + }, + "suggest": { + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony BrowserKit Component", + "homepage": "https://symfony.com", + "time": "2017-04-12T14:14:56+00:00" + }, { "name": "symfony/class-loader", "version": "v2.8.22", @@ -9659,302 +10525,133 @@ "require": { "php": "^5.6 || ^7.0", "zendframework/zend-escaper": "^2.5", - "zendframework/zend-stdlib": "^2.7 || ^3.1" - }, - "require-dev": { - "phpunit/phpunit": "^6.0.8 || ^5.7.15", - "psr/http-message": "^1.0", - "zendframework/zend-cache": "^2.6", - "zendframework/zend-coding-standard": "~1.0.0", - "zendframework/zend-db": "^2.7", - "zendframework/zend-http": "^2.5.4", - "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", - "zendframework/zend-validator": "^2.6" - }, - "suggest": { - "psr/http-message": "PSR-7 ^1.0, if you wish to use Zend\\Feed\\Reader\\Http\\Psr7ResponseDecorator", - "zendframework/zend-cache": "Zend\\Cache component, for optionally caching feeds between requests", - "zendframework/zend-db": "Zend\\Db component, for use with PubSubHubbub", - "zendframework/zend-http": "Zend\\Http for PubSubHubbub, and optionally for use with Zend\\Feed\\Reader", - "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for easily extending ExtensionManager implementations", - "zendframework/zend-validator": "Zend\\Validator component, for validating email addresses used in Atom feeds and entries ehen using the Writer subcomponent" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev", - "dev-develop": "2.9-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\Feed\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "provides functionality for consuming RSS and Atom feeds", - "homepage": "https://github.com/zendframework/zend-feed", - "keywords": [ - "feed", - "zf2" - ], - "time": "2017-04-01T15:03:14+00:00" - }, - { - "name": "zendframework/zend-stdlib", - "version": "3.1.0", - "source": { - "type": "git", - "url": "https://github.com/zendframework/zend-stdlib.git", - "reference": "debedcfc373a293f9250cc9aa03cf121428c8e78" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/debedcfc373a293f9250cc9aa03cf121428c8e78", - "reference": "debedcfc373a293f9250cc9aa03cf121428c8e78", - "shasum": "" - }, - "require": { - "php": "^5.6 || ^7.0" - }, - "require-dev": { - "athletic/athletic": "~0.1", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "^2.6.2" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.1-dev", - "dev-develop": "3.2-dev" - } - }, - "autoload": { - "psr-4": { - "Zend\\Stdlib\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "homepage": "https://github.com/zendframework/zend-stdlib", - "keywords": [ - "stdlib", - "zf2" - ], - "time": "2016-09-13T14:38:50+00:00" - } - ], - "packages-dev": [ - { - "name": "ajgl/breakpoint-twig-extension", - "version": "0.3.0", - "source": { - "type": "git", - "url": "https://github.com/ajgarlag/AjglBreakpointTwigExtension.git", - "reference": "0dfa4f0ae3bbeb6c8036e3e6d6c204c43b090155" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ajgarlag/AjglBreakpointTwigExtension/zipball/0dfa4f0ae3bbeb6c8036e3e6d6c204c43b090155", - "reference": "0dfa4f0ae3bbeb6c8036e3e6d6c204c43b090155", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "twig/twig": "^1.14" - }, - "require-dev": { - "symfony/framework-bundle": "^2.3", - "symfony/twig-bundle": "^2.3" - }, - "suggest": { - "ext-xdebug": "The Xdebug extension is required for the breakpoint to work", - "symfony/framework-bundle": "The framework bundle to integrate the extension into Symfony", - "symfony/twig-bundle": "The twig bundle to integrate the extension into Symfony" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.4.x-dev" - } - }, - "autoload": { - "psr-4": { - "Ajgl\\Twig\\Extension\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Antonio J. García Lagar", - "email": "aj@garcialagar.es", - "homepage": "http://aj.garcialagar.es", - "role": "developer" - } - ], - "description": "Twig extension to set breakpoints", - "homepage": "https://github.com/ajgarlag/AjglBreakpointTwigExtension", - "keywords": [ - "Xdebug", - "breakpoint", - "twig" - ], - "time": "2016-03-31T18:09:32+00:00" - }, - { - "name": "behat/mink", - "version": "v1.7.1", - "source": { - "type": "git", - "url": "https://github.com/minkphp/Mink.git", - "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/minkphp/Mink/zipball/e6930b9c74693dff7f4e58577e1b1743399f3ff9", - "reference": "e6930b9c74693dff7f4e58577e1b1743399f3ff9", - "shasum": "" - }, - "require": { - "php": ">=5.3.1", - "symfony/css-selector": "~2.1|~3.0" + "zendframework/zend-stdlib": "^2.7 || ^3.1" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" + "phpunit/phpunit": "^6.0.8 || ^5.7.15", + "psr/http-message": "^1.0", + "zendframework/zend-cache": "^2.6", + "zendframework/zend-coding-standard": "~1.0.0", + "zendframework/zend-db": "^2.7", + "zendframework/zend-http": "^2.5.4", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-validator": "^2.6" }, "suggest": { - "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", - "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", - "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", - "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" + "psr/http-message": "PSR-7 ^1.0, if you wish to use Zend\\Feed\\Reader\\Http\\Psr7ResponseDecorator", + "zendframework/zend-cache": "Zend\\Cache component, for optionally caching feeds between requests", + "zendframework/zend-db": "Zend\\Db component, for use with PubSubHubbub", + "zendframework/zend-http": "Zend\\Http for PubSubHubbub, and optionally for use with Zend\\Feed\\Reader", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component, for easily extending ExtensionManager implementations", + "zendframework/zend-validator": "Zend\\Validator component, for validating email addresses used in Atom feeds and entries ehen using the Writer subcomponent" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-master": "2.8-dev", + "dev-develop": "2.9-dev" } }, "autoload": { "psr-4": { - "Behat\\Mink\\": "src/" + "Zend\\Feed\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - } + "BSD-3-Clause" ], - "description": "Browser controller/emulator abstraction for PHP", - "homepage": "http://mink.behat.org/", + "description": "provides functionality for consuming RSS and Atom feeds", + "homepage": "https://github.com/zendframework/zend-feed", "keywords": [ - "browser", - "testing", - "web" + "feed", + "zf2" ], - "time": "2016-03-05T08:26:18+00:00" + "time": "2017-04-01T15:03:14+00:00" }, { - "name": "behat/mink-browserkit-driver", - "version": "v1.3.2", + "name": "zendframework/zend-stdlib", + "version": "3.1.0", "source": { "type": "git", - "url": "https://github.com/minkphp/MinkBrowserKitDriver.git", - "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb" + "url": "https://github.com/zendframework/zend-stdlib.git", + "reference": "debedcfc373a293f9250cc9aa03cf121428c8e78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkBrowserKitDriver/zipball/10e67fb4a295efcd62ea0bf16025a85ea19534fb", - "reference": "10e67fb4a295efcd62ea0bf16025a85ea19534fb", + "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/debedcfc373a293f9250cc9aa03cf121428c8e78", + "reference": "debedcfc373a293f9250cc9aa03cf121428c8e78", "shasum": "" }, "require": { - "behat/mink": "^1.7.1@dev", - "php": ">=5.3.6", - "symfony/browser-kit": "~2.3|~3.0", - "symfony/dom-crawler": "~2.3|~3.0" + "php": "^5.6 || ^7.0" }, "require-dev": { - "silex/silex": "~1.2", - "symfony/phpunit-bridge": "~2.7|~3.0" + "athletic/athletic": "~0.1", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "^2.6.2" }, - "type": "mink-driver", + "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "3.1-dev", + "dev-develop": "3.2-dev" } }, "autoload": { "psr-4": { - "Behat\\Mink\\Driver\\": "src/" + "Zend\\Stdlib\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" - ], - "authors": [ - { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - } + "BSD-3-Clause" ], - "description": "Symfony2 BrowserKit driver for Mink framework", - "homepage": "http://mink.behat.org/", + "homepage": "https://github.com/zendframework/zend-stdlib", "keywords": [ - "Mink", - "Symfony2", - "browser", - "testing" + "stdlib", + "zf2" ], - "time": "2016-03-05T08:59:47+00:00" - }, + "time": "2016-09-13T14:38:50+00:00" + } + ], + "packages-dev": [ { - "name": "behat/mink-goutte-driver", - "version": "v1.2.1", + "name": "ajgl/breakpoint-twig-extension", + "version": "0.3.0", "source": { "type": "git", - "url": "https://github.com/minkphp/MinkGoutteDriver.git", - "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca" + "url": "https://github.com/ajgarlag/AjglBreakpointTwigExtension.git", + "reference": "0dfa4f0ae3bbeb6c8036e3e6d6c204c43b090155" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkGoutteDriver/zipball/8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", - "reference": "8b9ad6d2d95bc70b840d15323365f52fcdaea6ca", + "url": "https://api.github.com/repos/ajgarlag/AjglBreakpointTwigExtension/zipball/0dfa4f0ae3bbeb6c8036e3e6d6c204c43b090155", + "reference": "0dfa4f0ae3bbeb6c8036e3e6d6c204c43b090155", "shasum": "" }, "require": { - "behat/mink": "~1.6@dev", - "behat/mink-browserkit-driver": "~1.2@dev", - "fabpot/goutte": "~1.0.4|~2.0|~3.1", - "php": ">=5.3.1" + "php": ">=5.4.0", + "twig/twig": "^1.14" }, "require-dev": { - "symfony/phpunit-bridge": "~2.7|~3.0" + "symfony/framework-bundle": "^2.3", + "symfony/twig-bundle": "^2.3" }, - "type": "mink-driver", + "suggest": { + "ext-xdebug": "The Xdebug extension is required for the breakpoint to work", + "symfony/framework-bundle": "The framework bundle to integrate the extension into Symfony", + "symfony/twig-bundle": "The twig bundle to integrate the extension into Symfony" + }, + "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "0.4.x-dev" } }, "autoload": { "psr-4": { - "Behat\\Mink\\Driver\\": "src/" + "Ajgl\\Twig\\Extension\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -9963,20 +10660,20 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Antonio J. García Lagar", + "email": "aj@garcialagar.es", + "homepage": "http://aj.garcialagar.es", + "role": "developer" } ], - "description": "Goutte driver for Mink framework", - "homepage": "http://mink.behat.org/", + "description": "Twig extension to set breakpoints", + "homepage": "https://github.com/ajgarlag/AjglBreakpointTwigExtension", "keywords": [ - "browser", - "goutte", - "headless", - "testing" + "Xdebug", + "breakpoint", + "twig" ], - "time": "2016-03-05T09:04:22+00:00" + "time": "2016-03-31T18:09:32+00:00" }, { "name": "doctrine/instantiator", @@ -10076,55 +10773,6 @@ "source": "http://cgit.drupalcode.org/twig_xdebug" } }, - { - "name": "fabpot/goutte", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/FriendsOfPHP/Goutte.git", - "reference": "db5c28f4a010b4161d507d5304e28a7ebf211638" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/Goutte/zipball/db5c28f4a010b4161d507d5304e28a7ebf211638", - "reference": "db5c28f4a010b4161d507d5304e28a7ebf211638", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^6.0", - "php": ">=5.5.0", - "symfony/browser-kit": "~2.1|~3.0", - "symfony/css-selector": "~2.1|~3.0", - "symfony/dom-crawler": "~2.1|~3.0" - }, - "type": "application", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "psr-4": { - "Goutte\\": "Goutte" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - } - ], - "description": "A simple PHP Web Scraper", - "homepage": "https://github.com/FriendsOfPHP/Goutte", - "keywords": [ - "scraper" - ], - "time": "2017-01-03T13:21:43+00:00" - }, { "name": "jcalderonzumba/gastonjs", "version": "v1.0.3", @@ -11096,63 +11744,6 @@ "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", "time": "2015-06-21T13:59:46+00:00" - }, - { - "name": "symfony/browser-kit", - "version": "v3.3.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/browser-kit.git", - "reference": "c2c8ceb1aa9dab9eae54e9150e6a588ce3e53be1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/c2c8ceb1aa9dab9eae54e9150e6a588ce3e53be1", - "reference": "c2c8ceb1aa9dab9eae54e9150e6a588ce3e53be1", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "symfony/dom-crawler": "~2.8|~3.0" - }, - "require-dev": { - "symfony/css-selector": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0" - }, - "suggest": { - "symfony/process": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.3-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\BrowserKit\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony BrowserKit Component", - "homepage": "https://symfony.com", - "time": "2017-04-12T14:14:56+00:00" } ], "aliases": [], diff --git a/vendor/behat/behat/CHANGELOG.md b/vendor/behat/behat/CHANGELOG.md new file mode 100644 index 000000000..26c9c258c --- /dev/null +++ b/vendor/behat/behat/CHANGELOG.md @@ -0,0 +1,890 @@ +# Change Log +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + +## [3.4.1] - 2017-09-18 +### Fixed + * PHP 5.3 style cleanup. + +## [3.4.0] - 2017-09-10 +### Added + * [#1071](https://github.com/Behat/Behat/pull/1071): Services auto-wiring + * [#1054](https://github.com/Behat/Behat/pull/1054): [PSR-11](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-11-container.md) + support for helper containers. + * Support for modern PHPUnit. + +### Fixed + * [#1056](https://github.com/Behat/Behat/pull/1056): Make Gherkin aware of the + base path so it can filter correctly + +### Changed + * [#1069](https://github.com/Behat/Behat/pull/1069): Rework argument validators + +### Deprecated + * [#1054](https://github.com/Behat/Behat/pull/1054): Deprecated usage + of `Interop\Container`. Versions prior to `1.2` are not supported, but `1.2` + is a non-breaking change. If you depend heavily on `Interop`, upgrade to + `1.2`, which is still supported by helper containers. Aim to migrate to + `Psr` before Behat 4.0 shows up on horizon + * PHP versions prior to 5.6 and HHVM were dropped from CI build matrix. It + doesn't mean that we'll start using features of 5.6 yet, it just means we + don't get out of our way to support 5.3 and 5.4 anymore. In 4.0 support will + be completely dropped. + +## [3.3.1] - 2017-05-15 +### Added + * [#976](https://github.com/Behat/Behat/pull/1001): Add tests to check that + snippets treat words containing apostrophes as a single word + +### Fixed + * [#993](https://github.com/Behat/Behat/pull/993) Fix mixed arguments + organizer not marking typehinted arguments as "defined" + * [#992](https://github.com/Behat/Behat/pull/993) Do not misinterpret first + argument as a numbered argument if it is in fact typehinted + * [#1028](https://github.com/Behat/Behat/pull/1028) Parent / Child class + argument ambiguity issue with `MixedArgumentResolver` + +## [3.3.0] - 2016-12-25 +### Added + * [#973](https://github.com/Behat/Behat/pull/974): Added helper containers + * [#973](https://github.com/Behat/Behat/pull/974): Added + `SuiteScopedResolverFactory` extension point + +### Removed + * Removed php 5.3 from the Travis build matrix. You can consider it official + end of support. 5.4 and 5.5 will follow shortly. + +## [3.2.3] - 2016-12-25 +### Fixed + * [#971](https://github.com/Behat/Behat/pull/971): Added support for suite + names with hyphens + +## [3.2.2] - 2016-11-05 +### Fixed + * [#959](https://github.com/Behat/Behat/issues/959): Fix transformations not + sorted properly on different php version + +## [3.2.1] - 2016-09-25 +### Changed + * [#955](https://github.com/Behat/Behat/pull/955): `--snippets-for` is not + required now as interactive mode is the new default + * [#954](https://github.com/Behat/Behat/pull/954): Stop execution on missing + steps when running with `--stop-on-failure` and `--strict` options + +## [3.2.0] - 2016-09-20 +### Added + * [#910](https://github.com/Behat/Behat/pull/910): Return type based + transformations + * [#903](https://github.com/Behat/Behat/pull/903): Multiline step definitions + support + * [#930](https://github.com/Behat/Behat/pull/930): Whole table transformation + * [#935](https://github.com/Behat/Behat/pull/935): Narrative filters in suites + * [#936](https://github.com/Behat/Behat/pull/936): Debug command + * [#931](https://github.com/Behat/Behat/pull/931): Exception handlers + extension point + * [#870](https://github.com/Behat/Behat/pull/870): Added build-related files + and folders to .gitattributes + * [#946](https://github.com/Behat/Behat/pull/946): Official full Windows + support with CI ([AppVeyor](http://appveyor.com)) on every build + +### Changed + * [#922](https://github.com/Behat/Behat/pull/922): Snippets generation revamp + * [#920](https://github.com/Behat/Behat/pull/920): More context for + pending/failed steps with progress formatter + * [#905](https://github.com/Behat/Behat/pull/905): Transformations refactoring + * [#864](https://github.com/Behat/Behat/pull/864): Use only one autoloader if + possible + * [#920](https://github.com/Behat/Behat/pull/920): Improve "No specifications + found" error message + * Refactor changelog to follow [Keep a Changelog](http://keepachangelog.com/) + * Refreshed [CONTRIBUTING.md](CONTRIBUTING.md) + * Refreshed Scrutinizer config + +### Fixed + * [#911](https://github.com/Behat/Behat/pull/911): Fix context isolation for + Scenario Outlines + * [#860](https://github.com/Behat/Behat/pull/860): Include basepath in + `generateKey` + * [#857](https://github.com/Behat/Behat/pull/857): Only cache failed + scenario's for rerun + * [#933](https://github.com/Behat/Behat/pull/933): Save failed runs with suite + information + * [#833](https://github.com/Behat/Behat/pull/833): Properly handle interupts + on PHP7 + * [#904](https://github.com/Behat/Behat/pull/904): Provide clearer exception + message when long token names used + * [#941](https://github.com/Behat/Behat/pull/941): Transformation should be + allowed if printable chars are used + +### Deprecated + * [#922](https://github.com/Behat/Behat/pull/922): `*SnippetAcceptingContext` + interfaces + * [#905](https://github.com/Behat/Behat/pull/905): `RuntimeTransformation` + * [#905](https://github.com/Behat/Behat/pull/905): `Transformation::getPattern` + * [#920](https://github.com/Behat/Behat/pull/920): `StepStat` + +### Removed + * Remove behat.bat (by Konstantin Kudryashov) + +## [3.1.0] - 2016-03-28 +### Changed + * Add support for Symfony 3 (thanks @benji07) + * Add ability to specify execution order of suite (thanks @ciaranmcnulty) + * Add translated keywords in definition printer (thanks @WouterJ) + * Add 'rowtable' transformations (thanks @PurpleBooth) + * Add 'narrative' filters (thanks @WouterJ) + * Add JUnit formatter (thanks @WouterJ and @james75) + * Add Japanese translation (thanks @SNakano) + * Add romanian translation for formatters (thanks @Chriton) + * Add table row transformations (thanks @ciaranmcnulty) + * Add support for negative numbers without surrounding quotes (thanks + @ryancookdev) + * Handle case when non-existent config file is used (thanks @watermanio) + * Handle non-default `error_reporting()` + * Handle PHP7 errors implementing `Throwable` + * Fix autoloading from the global installation (thanks @sroze) + * Fix scenario scope naming (thanks @Taluu) + * Fix output buffering errors (thanks @tscheepers) + * Fix xdebug maximum nesting level errors (thanks @WorkingDevel) + * Fix weird edge case in GroupedSpecificationIterator + * Allow --verbose flag at CLI (thanks @pfrenssen) + * Allow hyphens in suite names (thanks @WouterJ) + * Allow suite settings with null values to exist (thanks @docteurklein) + * Improve "can not generate snippets" message + * Improve performance of Turnip parsing (thanks @Sam-Burns) + * Improve the snippet generation by auto-importing needed classes (thanks + @stof) + +## [3.0.15] - 2015-02-22 +### Changed + * Fix broken null-transformations (Issue #669) + * Improve exception messages (thanks @dantleech) + +## [3.0.14] - 2014-09-23 +### Changed + * Improve generated context class + +## [3.0.13] - 2014-08-28 +### Changed + * 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 +### Changed + * Fix remaining issues with the definition arguments parsing + * Introduce `Testwork\Argument` component + +## [3.0.11] - 2014-07-09 +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 +### Changed + * Fix a small extension registration shortcut issue introduced in previous release (thanks @FrenkyNet) + +## [3.0.5] - 2014-05-06 +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 +### Changed + * Fix warning on empty scenarios + +## [3.0.1] - 2014-04-26 +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 ([b## [4477d7cf3f9550874c609d4edc5a4f55390672c](https://github.com/Behat/Behat/commit/b4477d7cf3f9550874c609d4edc5a4f55390672c)) + +3.0.0rc2] - 2014-01-10 + +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 +### Changed + * 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 +### Changed + * Refactor extension sub-system. Update `ExtensionInterface` + * Avoid trying to create folders for non-fs suites + +## 3.0.0beta2 - 2013-08-13 +### Changed + * Remove support for Symfony 2.0 components + +## 3.0.0beta1 - 2013-08-13 +### Changed + * 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 +### Changed + * First Behat LTS release + * Update Junit formatter to reflect latest junit format (thanks @alistairstead) + * Fix some container options + +## 2.4.6 - 2013-06-06 +### Changed + * 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 +### Changed + * 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 +### Changed + * Fixed `RuntimeException` namespacing error + * Added `FormatterManager::disableFormatter(s)` method + * Updated Gherkin parser and fixed couple of helper bugs + +## 2.4.3 - 2012-07-28 +### Changed + * 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 +### Changed + * Fixed broken autoloading with Composer installation + +## 2.4.1 - 2012-06-26 +### Changed + * 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 +### Changed + * 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 +### Changed + * Fixed formatter language configuration and locale guesser + +## 2.3.4 - 2012-03-28 +### Changed + * Added `StepEvent::getLogicalParent()`. Fixed issue ### 115 + +2.3.3 - 2012-03-09 + +### Changed + * 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 +### Changed + * Fixed bug in `ErrorException`, that caused wrong exceptions on warnings and notices + +## 2.3.1 - 2012-01-26 +### Changed + * Updated error handler to avoid suppressed exceptions + * Autoload bootstrap scripts in their name order + * Updated Gherkin dependency to v## 2.0.1 + +2.3.0 - 2012-01-19 + +### Changed + * 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 +### Changed + * Added ability to search translated definitions with `--definitions` + * Fixed custom formatters use bug + +## 2.2.6 - 2012-01-09 +### Changed + * Fixed pretty and html formatters printing of undefined steps in outlines + +## 2.2.5 - 2012-01-07 +### Changed + * `BEHAT_PARAMS` env variable support (083092e) + * HTML formatter print styles optimization (@davedevelopment) + +## 2.2.4 - 2012-01-04 +### Changed + * Prevent method name duplication with definition snippets + +## 2.2.3 - 2012-01-04 +### Changed + * Fixed couple of `--append-snippets` bugs + +## 2.2.2 - 2011-12-21 +### Changed + * Fixed Composer deps + +## 2.2.1 - 2011-12-21 +### Changed + * Fixed Composer package bin + +## 2.2.0 - 2011-12-14 +### Changed + * 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 +### Changed + * Substep translations support + * Correctly print undefined substeps in pretty printer + * @Transform callback now gets all provided matches + * Always set proper encoding (UTF## 8) + +2.1.2 - 2011-10-12 + +### Changed + * Fixed filtered feature hooks + * Fixed JUnit formatter time output in some locales + +## 2.1.1 - 2011-10-09 +### Changed + * Fixed multiline titles printing bug + * Fixed outline parameter inside step argument printing bug + +## 2.1.0 - 2011-09-12 +### Changed + * 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 +### Changed + * Cleaned ContextDispatcher extension points + * Cleaned context-parameters passing behavior + +## 2.0.4 - 2011-08-02 +### Changed + * 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 +### Changed + * Fixed JUnit formatter CDATA output + +## 2.0.2 - 2011-07-17 +### Changed + * Added extra checks to context instance mapper + * Fixed i18n support in definitions printer + * Refactored Gherkin tags inheritance + +## 2.0.1 - 2011-07-12 +### Changed + * Exception prefix added to statuses. Now you should throw `PendingException` instead of just + `Pending` + +## 2.0.0 - 2011-07-12 +### Changed + * 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 +### Changed + * Updated to the latest Symfony components + +## 1.1.8 - 2011-06-09 +### Changed + * Fixed empty match printing in Pretty and HTML formatters + * Updated to latest Symfony components + +## 1.1.7 - 2011-06-03 +### Changed + * Fixed steps colorization bug in outline + * Additional checks in config import routine + +## 1.1.6 - 2011-05-27 +### Changed + * Updated Symfony vendors + * Refactored console formatters + +## 1.1.5 - 2011-05-17 +### Changed + * Fixed CWD path finding + * Fixed HTML formatter (thanks @glenjamin) + +## 1.1.4 - 2011-05-03 +### Changed + * Fixed `--out` option usage critical bug + * Added ability to specify `output_path` from config file + +## 1.1.3 - 2011-04-28 +### Changed + * 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 +### Changed + * Fixed custom features path locator bug(issue ### 020) + +1.1.1 - 2011-04-21 + +### Changed + * 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 +### Changed + * 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 + * Changed XSD + * Updated vendors + +## 1.0.0RC6 - 2011-03-03 +### Changed + * Cleaned command options + * Added --init option + * Multiple paths support in behat.yml + * Application options refactoring + +## 1.0.0RC5 - 2011-02-25 +### Changed + * Windows support + * Bundled features hooks optimizations + +## 1.0.0RC4 - 2011-02-23 +### Changed + * 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 +### Changed + * Event dispatcher binding optimizations + * Command API optimizations for easier overloading + * Formatter path trimming bugfix + * BehatExtension config merging support + +## 1.0.0RC2 - 2011-02-15 +### Changed + * Step printing option bugfix + +## 1.0.0RC1 - 2011-02-15 +### Changed + * 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 +### Changed + * [Behat,Gherkin] Fixed French support includes (fr) + +## 0.3.6 - 2010-12-06 +### Changed + * [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 +### Changed + * [Behat] Refactored EnvironmentBuilder to allow Environment service definition overload + +## 0.3.4 - 2010-11-18 +### Changed + * [Behat] Introduced environment builder + * [Gherkin,Behat] id locale support + +## 0.3.3 - 2010-11-07 +### Changed + * [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 +### Changed + * [Gherkin] Added ability to specify extended langs (en-US) + * [Behat,Gherkin] Added pt-BR translation + +## 0.3.1 - 2010-11-02 +### Changed + * [Behat] JUnit formatter + * [Behat] Pretty & HTML formatter background hooks fix + * [Behat] Other small fixes + +## 0.3.0 - 2010-11-02 +### Changed + * [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 +### Changed + * [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 +### Changed + * [Behat] Autoguess of colors support + * [Behat] Formatter setup bugfix (properl casing) + +## 0.2.3 - 2010-10-19 +### Changed + * [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 +### Changed + * [Behat] Configuration file/path setting update + +## 0.2.1 - 2010-10-10 +### Changed + * [PEAR] Fix path to phpbin on installation + +## 0.2.0 - 2010-10-08 +### Changed + * [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 +### Changed + * 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 +### Changed + * Refactored code + * Removed logic from object constructors + * Added Loader & Filter interfaces + +## 0.1.3 - 2010-09-14 +### Changed + * 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 +### Changed + * 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 +### Changed + * Added `--tags` option + * Changed environment (world) routines + * Added lots of core tests (writed in Behat itself) + +## 0.1.0 - 2010-09-08 +### Changed + * Initial release + +[Unreleased]: https://github.com/Behat/Behat/compare/v3.4.1...HEAD +[3.4.1]: https://github.com/Behat/Behat/compare/v3.4.0...v3.4.1 +[3.4.0]: https://github.com/Behat/Behat/compare/v3.3.1...v3.4.0 +[3.3.1]: https://github.com/Behat/Behat/compare/v3.3.0...v3.3.1 +[3.3.0]: https://github.com/Behat/Behat/compare/v3.2.3...v3.3.0 +[3.2.3]: https://github.com/Behat/Behat/compare/v3.2.2...v3.2.3 +[3.2.2]: https://github.com/Behat/Behat/compare/v3.2.1...v3.2.2 +[3.2.1]: https://github.com/Behat/Behat/compare/v3.2.0...v3.2.1 +[3.2.0]: https://github.com/Behat/Behat/compare/v3.1.0...v3.2.0 +[3.1.0]: https://github.com/Behat/Behat/compare/v3.0.15...v3.1.0 +[3.0.15]: https://github.com/Behat/Behat/compare/v3.0.14...v3.0.15 +[3.0.14]: https://github.com/Behat/Behat/compare/v3.0.13...v3.0.14 +[3.0.13]: https://github.com/Behat/Behat/compare/v3.0.12...v3.0.13 +[3.0.12]: https://github.com/Behat/Behat/compare/v3.0.11...v3.0.12 +[3.0.11]: https://github.com/Behat/Behat/compare/v3.0.10...v3.0.11 +[3.0.10]: https://github.com/Behat/Behat/compare/v3.0.9...v3.0.10 +[3.0.9]: https://github.com/Behat/Behat/compare/v3.0.8...v3.0.9 +[3.0.8]: https://github.com/Behat/Behat/compare/v3.0.7...v3.0.8 +[3.0.7]: https://github.com/Behat/Behat/compare/v3.0.6...v3.0.7 +[3.0.6]: https://github.com/Behat/Behat/compare/v3.0.5...v3.0.6 +[3.0.5]: https://github.com/Behat/Behat/compare/v3.0.4...v3.0.5 +[3.0.4]: https://github.com/Behat/Behat/compare/v3.0.3...v3.0.4 +[3.0.3]: https://github.com/Behat/Behat/compare/v3.0.2...v3.0.3 +[3.0.2]: https://github.com/Behat/Behat/compare/v3.0.1...v3.0.2 +[3.0.1]: https://github.com/Behat/Behat/compare/v3.0.0...v3.0.1 +[3.0.0]: https://github.com/Behat/Behat/compare/v2.5.5...v3.0.0 diff --git a/vendor/behat/behat/LICENSE b/vendor/behat/behat/LICENSE new file mode 100644 index 000000000..86ebfc8f0 --- /dev/null +++ b/vendor/behat/behat/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2016 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 000000000..22543cb51 --- /dev/null +++ b/vendor/behat/behat/README.md @@ -0,0 +1,73 @@ +![Behat](https://github.com/Behat/logo/raw/master/logo.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) +[![Unix Status](https://travis-ci.org/Behat/Behat.svg?branch=master)](https://travis-ci.org/Behat/Behat) +[![Windows status](https://ci.appveyor.com/api/projects/status/9uc5sellmvbv02ei/branch/master?svg=true)](https://ci.appveyor.com/project/everzet/behat/branch/master) +[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/Behat/Behat/badges/quality-score.png?s=ad84e95fc2405712f88a96d89b4f31dfe5c80fae)](https://scrutinizer-ci.com/g/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 +``` + +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/v3.1.0/src/Behat/Behat/Context/ContextClass/ClassResolver.php#L15-L22)) +and use service constants (like [this one](https://github.com/Behat/Behat/blob/v3.1.0/src/Behat/Behat/Context/ServiceContainer/ContextExtension.php#L46)), +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://docs.behat.org/en/latest/](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 000000000..b7dad59df --- /dev/null +++ b/vendor/behat/behat/bin/behat @@ -0,0 +1,34 @@ +#!/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__); + +if (is_file($autoload = getcwd() . '/vendor/autoload.php')) { + require $autoload; +} + +if (!class_exists('Behat\Behat\ApplicationFactory', true)) { + if (is_file($autoload = __DIR__ . '/../vendor/autoload.php')) { + require($autoload); + } elseif (is_file($autoload = __DIR__ . '/../../../autoload.php')) { + require($autoload); + } else { + 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/composer.json b/vendor/behat/behat/composer.json new file mode 100644 index 000000000..b3dbd81f3 --- /dev/null +++ b/vendor/behat/behat/composer.json @@ -0,0 +1,58 @@ +{ + "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.5.1", + "behat/transliterator": "^1.2", + "symfony/console": "~2.5||~3.0", + "symfony/config": "~2.3||~3.0", + "symfony/dependency-injection": "~2.1||~3.0", + "symfony/event-dispatcher": "~2.1||~3.0", + "symfony/translation": "~2.3||~3.0", + "symfony/yaml": "~2.1||~3.0", + "symfony/class-loader": "~2.1||~3.0", + "psr/container": "^1.0", + "container-interop/container-interop": "^1.2" + }, + + "require-dev": { + "symfony/process": "~2.5|~3.0", + "phpunit/phpunit": "~4.5", + "herrera-io/box": "~1.6.1" + }, + + "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.2.x-dev" + } + }, + + "bin": ["bin/behat"] +} diff --git a/vendor/behat/behat/i18n.php b/vendor/behat/behat/i18n.php new file mode 100644 index 000000000..44eda3c91 --- /dev/null +++ b/vendor/behat/behat/i18n.php @@ -0,0 +1,217 @@ + array( + 'snippet_context_choice' => '%1% suite has undefined steps. Please choose the context to generate snippets:', + 'snippet_proposal_title' => '%1% has missing steps. Define them with these snippets:', + 'snippet_missing_title' => 'Use --snippets-for CLI option to generate snippets for following %1% suite steps:', + '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', + ), + 'ja' => 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} No scenarios|{1} 1 個のシナリオ|]1,Inf] %1% 個のシナリオ', + 'steps_count' => '{0} ステップがありません|{1} 1 個のステップ|]1,Inf] %1% 個のステップ', + 'passed_count' => '[1,Inf] %1% 個成功', + 'failed_count' => '[1,Inf] %1% 個失敗', + 'pending_count' => '[1,Inf] %1% 個保留', + 'undefined_count' => '[1,Inf] %1% 個未定義', + 'skipped_count' => '[1,Inf] %1% 個スキップ', + ), + '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', + ), + 'ro' => array( + 'snippet_proposal_title' => '%1% are pași lipsa. Puteți implementa pașii cu ajutorul acestor fragmente de cod:', + 'snippet_missing_title' => 'Fragmentele de cod pentru urmatorii pași din suita %1% nu au fost generate (contextul tau implementeaza interfata SnippetAcceptingContext?):', + 'skipped_scenarios_title' => 'Scenarii omise:', + 'failed_scenarios_title' => 'Scenarii eșuate:', + 'failed_hooks_title' => 'Hook-uri eșuate:', + 'failed_steps_title' => 'Pași esuați:', + 'pending_steps_title' => 'Pași in așteptare:', + 'scenarios_count' => '{0} Niciun scenariu|{1} 1 scenariu|]1,Inf] %1% scenarii', + 'steps_count' => '{0} Niciun pas|{1} 1 pas|]1,Inf] %1% pasi', + 'passed_count' => '[1,Inf] %1% cu succes', + 'failed_count' => '[1,Inf] %1% fara success', + 'pending_count' => '[1,Inf] %1% in așteptare', + 'undefined_count' => '[1,Inf] %1% fara implementare', + 'skipped_count' => '{1} %1% omis|]1,Inf] %1% omiși', + ), + '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/src/Behat/Behat/ApplicationFactory.php b/vendor/behat/behat/src/Behat/Behat/ApplicationFactory.php new file mode 100644 index 000000000..46a0640e2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/ApplicationFactory.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\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\JUnitFormatterFactory; +use Behat\Behat\Output\ServiceContainer\Formatter\PrettyFormatterFactory; +use Behat\Behat\Output\ServiceContainer\Formatter\ProgressFormatterFactory; +use Behat\Behat\HelperContainer\ServiceContainer\HelperContainerExtension; +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\Ordering\ServiceContainer\OrderingExtension; +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.4.1'; + + /** + * {@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), + new OrderingExtension($processor), + new HelperContainerExtension($processor) + ); + } + + /** + * {@inheritdoc} + */ + protected function getEnvironmentVariableName() + { + return 'BEHAT_PARAMS'; + } + + /** + * {@inheritdoc} + */ + protected function getConfigPath() + { + $cwd = rtrim(getcwd(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + $configDir = $cwd . 'config' . DIRECTORY_SEPARATOR; + $paths = array( + $cwd . 'behat.yaml', + $cwd . 'behat.yml', + $cwd . 'behat.yaml.dist', + $cwd . 'behat.yml.dist', + $configDir . 'behat.yaml', + $configDir . 'behat.yml', + $configDir . 'behat.yaml.dist', + $configDir . 'behat.yml.dist', + ); + + foreach ($paths as $path) { + if (is_file($path)) { + return $path; + } + } + + return null; + } + + /** + * Returns default formatter factories. + * + * @param ServiceProcessor $processor + * + * @return FormatterFactory[] + */ + private function getDefaultFormatterFactories(ServiceProcessor $processor) + { + return array( + new PrettyFormatterFactory($processor), + new ProgressFormatterFactory($processor), + new JUnitFormatterFactory(), + ); + } +} 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 000000000..84f7ac980 --- /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 000000000..e218276be --- /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/Argument/ArgumentResolverFactory.php b/vendor/behat/behat/src/Behat/Behat/Context/Argument/ArgumentResolverFactory.php new file mode 100644 index 000000000..708c38bc7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Argument/ArgumentResolverFactory.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\Argument; + +use Behat\Testwork\Environment\Environment; + +/** + * Creates argument resolvers for provided environment. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +interface ArgumentResolverFactory +{ + /** + * Builds argument resolvers for provided suite. + * + * @param Environment $environment + * + * @return ArgumentResolver[] + */ + public function createArgumentResolvers(Environment $environment); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Argument/CompositeArgumentResolverFactory.php b/vendor/behat/behat/src/Behat/Behat/Context/Argument/CompositeArgumentResolverFactory.php new file mode 100644 index 000000000..fbfd69c83 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Argument/CompositeArgumentResolverFactory.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\Context\Argument; + +use Behat\Testwork\Environment\Environment; + +/** + * Composite factory. Delegates to other (registered) factories to do the job. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +final class CompositeArgumentResolverFactory implements ArgumentResolverFactory +{ + /** + * @var ArgumentResolverFactory[] + */ + private $factories = array(); + + /** + * Registers factory. + * + * @param ArgumentResolverFactory $factory + */ + public function registerFactory(ArgumentResolverFactory $factory) + { + $this->factories[] = $factory; + } + + /** + * {@inheritdoc} + */ + public function createArgumentResolvers(Environment $environment) + { + return array_reduce( + $this->factories, + function (array $resolvers, ArgumentResolverFactory $factory) use ($environment) { + return array_merge($resolvers, $factory->createArgumentResolvers($environment)); + }, + array() + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Argument/CompositeFactory.php b/vendor/behat/behat/src/Behat/Behat/Context/Argument/CompositeFactory.php new file mode 100644 index 000000000..5b3d93f84 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Argument/CompositeFactory.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\Argument; + +use Behat\Testwork\Suite\Suite; + +/** + * Composite factory. Delegates to other (registered) factories to do the job. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + * + * @deprecated and will be removed in 4.0. Use CompositeArgumentResolverFactory instead + */ +final class CompositeFactory implements SuiteScopedResolverFactory +{ + /** + * @var SuiteScopedResolverFactory[] + */ + private $factories = array(); + + /** + * Registers factory. + * + * @param SuiteScopedResolverFactory $factory + */ + public function registerFactory(SuiteScopedResolverFactory $factory) + { + $this->factories[] = $factory; + } + + /** + * {@inheritdoc} + */ + public function generateArgumentResolvers(Suite $suite) + { + return array_reduce( + $this->factories, + function (array $resolvers, SuiteScopedResolverFactory $factory) use ($suite) { + return array_merge($resolvers, $factory->generateArgumentResolvers($suite)); + }, + array() + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Argument/NullFactory.php b/vendor/behat/behat/src/Behat/Behat/Context/Argument/NullFactory.php new file mode 100644 index 000000000..c2e070c40 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Argument/NullFactory.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\Context\Argument; + +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Suite\Suite; + +/** + * NoOp factory. Always returns zero resolvers. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +final class NullFactory implements ArgumentResolverFactory, SuiteScopedResolverFactory +{ + /** + * {@inheritdoc} + */ + public function generateArgumentResolvers(Suite $suite) + { + return array(); + } + + /** + * {@inheritdoc} + */ + public function createArgumentResolvers(Environment $environment) + { + return array(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Argument/SuiteScopedResolverFactory.php b/vendor/behat/behat/src/Behat/Behat/Context/Argument/SuiteScopedResolverFactory.php new file mode 100644 index 000000000..9f953fc2d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Argument/SuiteScopedResolverFactory.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\Testwork\Suite\Suite; + +/** + * Creates argument resolvers for provided suite. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + * + * @deprecated since 3.4. Use `ArgumentResolverFactory` instead + */ +interface SuiteScopedResolverFactory +{ + /** + * Creates argument resolvers for provided suite. + * + * @param Suite $suite + * + * @return ArgumentResolver[] + */ + public function generateArgumentResolvers(Suite $suite); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Argument/SuiteScopedResolverFactoryAdapter.php b/vendor/behat/behat/src/Behat/Behat/Context/Argument/SuiteScopedResolverFactoryAdapter.php new file mode 100644 index 000000000..2317c8eb6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Argument/SuiteScopedResolverFactoryAdapter.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\Behat\Context\Argument; + +use Behat\Testwork\Environment\Environment; + +/** + * Adapts SuiteScopedResolverFactory to new ArgumentResolverFactory interface. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + * + * @deprecated since 3.4. Use `ArgumentResolverFactory` instead + */ +final class SuiteScopedResolverFactoryAdapter implements ArgumentResolverFactory +{ + /** + * @var SuiteScopedResolverFactory + */ + private $factory; + + /** + * Initialises adapter. + * + * @param SuiteScopedResolverFactory $factory + */ + public function __construct(SuiteScopedResolverFactory $factory) + { + $this->factory = $factory; + } + + /** + * {@inheritdoc} + */ + public function createArgumentResolvers(Environment $environment) + { + return $this->factory->generateArgumentResolvers($environment->getSuite()); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Cli/ContextSnippetsController.php b/vendor/behat/behat/src/Behat/Behat/Context/Cli/ContextSnippetsController.php new file mode 100644 index 000000000..3a6edf63c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Cli/ContextSnippetsController.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\Context\Cli; + +use Behat\Behat\Context\Snippet\Generator\AggregatePatternIdentifier; +use Behat\Behat\Context\Snippet\Generator\ContextInterfaceBasedContextIdentifier; +use Behat\Behat\Context\Snippet\Generator\ContextInterfaceBasedPatternIdentifier; +use Behat\Behat\Context\Snippet\Generator\ContextSnippetGenerator; +use Behat\Behat\Context\Snippet\Generator\FixedContextIdentifier; +use Behat\Behat\Context\Snippet\Generator\FixedPatternIdentifier; +use Behat\Behat\Context\Snippet\Generator\AggregateContextIdentifier; +use Behat\Testwork\Cli\Controller; +use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Configures which context snippets are generated for. + * + * @author Konstantin Kudryashov + */ +final class ContextSnippetsController implements Controller +{ + /** + * @var ContextSnippetGenerator + */ + private $generator; + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * Initialises controller. + * + * @param ContextSnippetGenerator $generator + * @param TranslatorInterface $translator + */ + public function __construct(ContextSnippetGenerator $generator, TranslatorInterface $translator) + { + $this->generator = $generator; + $this->translator = $translator; + } + + /** + * {@inheritdoc} + */ + public function configure(SymfonyCommand $command) + { + $command + ->addOption( + '--snippets-for', null, InputOption::VALUE_OPTIONAL, + "Specifies which context class to generate snippets for." + ) + ->addOption( + '--snippets-type', null, InputOption::VALUE_REQUIRED, + "Specifies which type of snippets (turnip, regex) to generate." + ); + } + + /** + * {@inheritdoc} + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $this->generator->setContextIdentifier( + new AggregateContextIdentifier(array( + new ContextInterfaceBasedContextIdentifier(), + new FixedContextIdentifier($input->getOption('snippets-for')), + new InteractiveContextIdentifier($this->translator, $input, $output) + )) + ); + + $this->generator->setPatternIdentifier( + new AggregatePatternIdentifier(array( + new ContextInterfaceBasedPatternIdentifier(), + new FixedPatternIdentifier($input->getOption('snippets-type')) + )) + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Cli/InteractiveContextIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Cli/InteractiveContextIdentifier.php new file mode 100644 index 000000000..c39488ae6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Cli/InteractiveContextIdentifier.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\Behat\Context\Cli; + +use Behat\Behat\Context\Environment\ContextEnvironment; +use Behat\Behat\Context\Snippet\Generator\TargetContextIdentifier; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Interactive identifier that asks user for input. + * + * @author Konstantin Kudryashov + */ +final class InteractiveContextIdentifier implements TargetContextIdentifier +{ + /** + * @var TranslatorInterface + */ + private $translator; + /** + * @var InputInterface + */ + private $input; + /** + * @var OutputInterface + */ + private $output; + + /** + * Initialises identifier. + * + * @param TranslatorInterface $translator + * @param InputInterface $input + * @param OutputInterface $output + */ + public function __construct(TranslatorInterface $translator, InputInterface $input, OutputInterface $output) + { + $this->translator = $translator; + $this->input = $input; + $this->output = $output; + } + + /** + * {@inheritdoc} + */ + public function guessTargetContextClass(ContextEnvironment $environment) + { + if ($this->interactionIsNotSupported()) { + return null; + } + + $suiteName = $environment->getSuite()->getName(); + $contextClasses = $environment->getContextClasses(); + + if (!count($contextClasses)) { + return null; + } + + $message = $this->translator->trans('snippet_context_choice', array('%1%' => $suiteName), 'output'); + $choices = array_values(array_merge(array('None'), $contextClasses)); + $default = current($contextClasses); + + $answer = $this->askQuestion('>> ' . $message, $choices, $default); + + return 'None' !== $answer ? $answer : null; + } + + /** + * Asks user question. + * + * @param string $message + * @param string[] $choices + * @param string $default + * + * @return string + */ + private function askQuestion($message, $choices, $default) + { + $this->output->writeln(''); + $helper = new QuestionHelper(); + $question = new ChoiceQuestion(' ' . $message . "\n", $choices, $default); + + return $helper->ask($this->input, $this->output, $question); + } + + /** + * Checks if interactive mode is supported. + * + * @return Boolean + * + * @deprecated there is a better way to do it - `InputInterface::isInteractive()` method. + * Sadly, this doesn't work properly prior Symfony\Console 2.7 and as we need + * to support 2.5+ until the next major, we are forced to do a more explicit + * check for the CLI option. This should be reverted back to proper a + * `InputInterface::isInteractive()` call as soon as we bump dependencies + * to Symfony\Console 3.x in Behat 4.x. + */ + private function interactionIsNotSupported() + { + return $this->input->hasParameterOption('--no-interaction'); + } +} 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 000000000..b9ac895cc --- /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 000000000..d2a740926 --- /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 000000000..464f68f41 --- /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 000000000..f37ac4497 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/ContextClass/SimpleClassGenerator.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\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 000000000..b7a24422e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/ContextFactory.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\Behat\Context; + +use Behat\Testwork\Argument\Validator; +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(); + /** + * @var Validator + */ + private $validator; + + /** + * Initialises factory. + * + * @param ArgumentOrganiser $argumentOrganiser + */ + public function __construct(ArgumentOrganiser $argumentOrganiser) + { + $this->argumentOrganiser = $argumentOrganiser; + $this->validator = new Validator(); + } + + /** + * 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 + * @param ArgumentResolver[] $singleUseResolvers + * + * @return Context + */ + public function createContext($class, array $arguments = array(), array $singleUseResolvers = array()) + { + $reflection = new ReflectionClass($class); + $resolvers = array_merge($singleUseResolvers, $this->argumentResolvers); + $resolvedArguments = $this->resolveArguments($reflection, $arguments, $resolvers); + $context = $this->createInstance($reflection, $resolvedArguments); + $this->initializeInstance($context); + + return $context; + } + + /** + * Resolves arguments for a specific class using registered argument resolvers. + * + * @param ReflectionClass $reflection + * @param array $arguments + * @param ArgumentResolver[] $resolvers + * + * @return mixed[] + */ + private function resolveArguments(ReflectionClass $reflection, array $arguments, array $resolvers) + { + $newArguments = $arguments; + + foreach ($resolvers as $resolver) { + $newArguments = $resolver->resolveArguments($reflection, $newArguments); + } + + if (!$reflection->hasMethod('__construct')) { + return $newArguments; + } + + $constructor = $reflection->getConstructor(); + $newArguments = $this->argumentOrganiser->organiseArguments($constructor, $newArguments); + $this->validator->validateArguments($constructor, $newArguments); + + return $newArguments; + } + + /** + * Creates context instance. + * + * @param ReflectionClass $reflection + * @param array $arguments + * + * @return mixed + */ + 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 + */ + 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 000000000..5090d304b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/CustomSnippetAcceptingContext.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; + +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 + * + * @deprecated will be removed in 4.0. Use --snippets-for and --snippets-type CLI options instead + */ +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 000000000..690eebb28 --- /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 000000000..d686400dd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Environment/Handler/ContextEnvironmentHandler.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\Context\Environment\Handler; + +use Behat\Behat\Context\Argument\SuiteScopedResolverFactory; +use Behat\Behat\Context\Argument\SuiteScopedResolverFactoryAdapter; +use Behat\Behat\Context\Argument\ArgumentResolverFactory; +use Behat\Behat\Context\Argument\NullFactory; +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 $contextFactory; + /** + * @var ArgumentResolverFactory + */ + private $resolverFactory; + /** + * @var ClassResolver[] + */ + private $classResolvers = array(); + + /** + * Initializes handler. + * + * @param ContextFactory $factory + * @param ArgumentResolverFactory|SuiteScopedResolverFactory $resolverFactory + */ + public function __construct(ContextFactory $factory, $resolverFactory = null) + { + $this->contextFactory = $factory; + + if ($resolverFactory && !$resolverFactory instanceof ArgumentResolverFactory) { + $resolverFactory = new SuiteScopedResolverFactoryAdapter($resolverFactory); + } + + $this->resolverFactory = $resolverFactory ?: new NullFactory(); + } + + /** + * 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()); + $resolvers = $this->resolverFactory->createArgumentResolvers($environment); + + foreach ($uninitializedEnvironment->getContextClassesWithArguments() as $class => $arguments) { + $context = $this->contextFactory->createContext($class, $arguments, $resolvers); + $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 000000000..053354963 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Environment/InitializedContextEnvironment.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\Behat\Context\Environment; + +use Behat\Behat\Context\Context; +use Behat\Behat\Context\Environment\Handler\ContextEnvironmentHandler; +use Behat\Behat\Context\Exception\ContextNotFoundException; +use Behat\Behat\HelperContainer\Environment\ServiceContainerEnvironment; +use Behat\Testwork\Call\Callee; +use Behat\Testwork\Suite\Suite; +use Psr\Container\ContainerInterface; + +/** + * Context environment based on a list of instantiated context objects. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +final class InitializedContextEnvironment implements ContextEnvironment, ServiceContainerEnvironment +{ + /** + * @var string + */ + private $suite; + /** + * @var ContainerInterface + */ + private $serviceContainer; + /** + * @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 setServiceContainer(ContainerInterface $container = null) + { + $this->serviceContainer = $container; + } + + /** + * {@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 getServiceContainer() + { + return $this->serviceContainer; + } + + /** + * {@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 000000000..71759e995 --- /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 000000000..d0ff98551 --- /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 000000000..bc1a4278d --- /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 000000000..64cfde904 --- /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 000000000..2c4a7618f --- /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 000000000..69ccc8cab --- /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 000000000..3d2b35624 --- /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 000000000..a3144740e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Reader/AnnotatedContextReader.php @@ -0,0 +1,245 @@ + + * + * 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); + $docBlock = $this->mergeMultilines($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; + } + + /** + * Merges multiline strings (strings ending with "\") + * + * @param string $docBlock + * + * @return string + */ + private function mergeMultilines($docBlock) + { + return preg_replace("#\\\\$\s*+\*\s*+([^\\\\$]++)#m", '$1', $docBlock); + } + + /** + * 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 000000000..b8a9156f9 --- /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 000000000..8a51662e2 --- /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 000000000..4a8bfd5c6 --- /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 000000000..11327ee40 --- /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 000000000..f4c6917b7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/ServiceContainer/ContextExtension.php @@ -0,0 +1,416 @@ + + * + * 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\Cli\ServiceContainer\CliExtension; +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'; + const CONTEXT_SNIPPET_GENERATOR_ID = 'snippet.generator.context'; + const AGGREGATE_RESOLVER_FACTORY_ID = 'context.argument.aggregate_resolver_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'; + const SUITE_SCOPED_RESOLVER_FACTORY_TAG = 'context.argument.suite_resolver_factory'; + + /** + * @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->loadArgumentResolverFactory($container); + $this->loadEnvironmentHandler($container); + $this->loadEnvironmentReader($container); + $this->loadSuiteSetup($container); + $this->loadSnippetAppender($container); + $this->loadSnippetGenerators($container); + $this->loadSnippetsController($container); + $this->loadDefaultClassGenerators($container); + $this->loadDefaultContextReaders($container); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $this->processClassResolvers($container); + $this->processArgumentResolverFactories($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 argument resolver factory used in the environment handler. + * + * @param ContainerBuilder $container + */ + private function loadArgumentResolverFactory(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\Argument\CompositeArgumentResolverFactory'); + $container->setDefinition(self::AGGREGATE_RESOLVER_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), + new Reference(self::AGGREGATE_RESOLVER_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(self::CONTEXT_SNIPPET_GENERATOR_ID, $definition); + } + + /** + * @param ContainerBuilder $container + */ + protected function loadSnippetsController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Context\Cli\ContextSnippetsController', array( + new Reference(self::CONTEXT_SNIPPET_GENERATOR_ID), + new Reference(TranslatorExtension::TRANSLATOR_ID) + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 410)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.context_snippets', $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 class resolvers. + * + * @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 argument resolver factories. + * + * @param ContainerBuilder $container + */ + private function processArgumentResolverFactories($container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::SUITE_SCOPED_RESOLVER_FACTORY_TAG); + $definition = $container->getDefinition(self::AGGREGATE_RESOLVER_FACTORY_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerFactory', array($reference)); + } + } + + /** + * Processes all argument resolvers. + * + * @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 000000000..5a881f94b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Appender/ContextSnippetAppender.php @@ -0,0 +1,128 @@ + + * + * 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()); + + foreach ($snippet->getUsedClasses() as $class) { + if (!$this->isClassImported($class, $content)) { + $content = $this->importClass($class, $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 class in it. + * + * @param string $class + * @param string $contextFileContent + * + * @return Boolean + */ + private function isClassImported($class, $contextFileContent) + { + $classImportRegex = sprintf( + '@use[^;]*%s.*;@ms', + preg_quote($class, '@') + ); + + return 1 === preg_match($classImportRegex, $contextFileContent); + } + + /** + * Adds use-block for class. + * + * @param string $class + * @param string $contextFileContent + * + * @return string + */ + private function importClass($class, $contextFileContent) + { + $replaceWith = "\$1" . 'use ' . $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 000000000..6ece5f198 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/ContextSnippet.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\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; + /** + * @var string[] + */ + private $usedClasses; + + /** + * Initializes definition snippet. + * + * @param StepNode $step + * @param string $template + * @param string $contextClass + * @param string[] $usedClasses + */ + public function __construct(StepNode $step, $template, $contextClass, array $usedClasses = array()) + { + $this->step = $step; + $this->template = $template; + $this->contextClass = $contextClass; + $this->usedClasses = $usedClasses; + } + + /** + * {@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; + } + + /** + * Returns the classes used in the snippet which should be imported. + * + * @return string[] + */ + public function getUsedClasses() + { + return $this->usedClasses; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/AggregateContextIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/AggregateContextIdentifier.php new file mode 100644 index 000000000..632d93775 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/AggregateContextIdentifier.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\Context\Snippet\Generator; + +use Behat\Behat\Context\Environment\ContextEnvironment; + +/** + * Uses multiple child identifiers - the first one that returns non-null result would + * be the winner. + * + * This behaviour was introduced in 3.x to support the BC for interface-focused + * context identifier, while providing better user experience (no need to explicitly + * call `--snippets-for` on `--append-snippets` when contexts do not implement any + * snippet accepting interfaces). + */ +final class AggregateContextIdentifier implements TargetContextIdentifier +{ + /** + * @var TargetContextIdentifier[] + */ + private $identifiers; + + /** + * Initialises identifier. + * + * @param TargetContextIdentifier[] $identifiers + */ + public function __construct(array $identifiers) + { + $this->identifiers = $identifiers; + } + + /** + * {@inheritdoc} + */ + public function guessTargetContextClass(ContextEnvironment $environment) + { + foreach ($this->identifiers as $identifier) { + $contextClass = $identifier->guessTargetContextClass($environment); + + if (null !== $contextClass) { + return $contextClass; + } + } + + return null; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/AggregatePatternIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/AggregatePatternIdentifier.php new file mode 100644 index 000000000..1e1fc27a2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/AggregatePatternIdentifier.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\Snippet\Generator; + +/** + * Uses multiple child identifiers - the first one that returns non-null result would + * be the winner. + */ +final class AggregatePatternIdentifier implements PatternIdentifier +{ + /** + * @var PatternIdentifier[] + */ + private $identifiers; + + /** + * Initialises identifier. + * + * @param PatternIdentifier[] $identifiers + */ + public function __construct(array $identifiers) + { + $this->identifiers = $identifiers; + } + + /** + * {@inheritdoc} + */ + public function guessPatternType($contextClass) + { + foreach ($this->identifiers as $identifier) { + $pattern = $identifier->guessPatternType($contextClass); + + if (null !== $pattern) { + return $pattern; + } + } + + return null; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/CachedContextIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/CachedContextIdentifier.php new file mode 100644 index 000000000..6ff1bb662 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/CachedContextIdentifier.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\Snippet\Generator; + +use Behat\Behat\Context\Environment\ContextEnvironment; + +/** + * Decorates actual identifier and caches its answers per suite. + * + * @author Konstantin Kudryashov + */ +final class CachedContextIdentifier implements TargetContextIdentifier +{ + /** + * @var TargetContextIdentifier + */ + private $decoratedIdentifier; + /** + * @var array + */ + private $contextClasses = array(); + + /** + * Initialise the identifier. + * + * @param TargetContextIdentifier $identifier + */ + public function __construct(TargetContextIdentifier $identifier) + { + $this->decoratedIdentifier = $identifier; + } + + /** + * {@inheritdoc} + */ + public function guessTargetContextClass(ContextEnvironment $environment) + { + $suiteKey = $environment->getSuite()->getName(); + + if (array_key_exists($suiteKey, $this->contextClasses)) { + return $this->contextClasses[$suiteKey]; + } + + return $this->contextClasses[$suiteKey] = $this->decoratedIdentifier->guessTargetContextClass($environment); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextInterfaceBasedContextIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextInterfaceBasedContextIdentifier.php new file mode 100644 index 000000000..7e1c154a8 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextInterfaceBasedContextIdentifier.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\Snippet\Generator; + +use Behat\Behat\Context\Environment\ContextEnvironment; + +/** + * Identifier that uses context interfaces to guess which one is target. + * + * @author Konstantin Kudryashov + * + * @deprecated in favour of --snippets-for and will be removed in 4.0 + */ +final class ContextInterfaceBasedContextIdentifier implements TargetContextIdentifier +{ + /** + * {@inheritdoc} + */ + public function guessTargetContextClass(ContextEnvironment $environment) + { + foreach ($environment->getContextClasses() as $class) { + if (in_array('Behat\Behat\Context\SnippetAcceptingContext', class_implements($class))) { + return $class; + } + } + + return null; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextInterfaceBasedPatternIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextInterfaceBasedPatternIdentifier.php new file mode 100644 index 000000000..31e956a03 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextInterfaceBasedPatternIdentifier.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\Context\Snippet\Generator; + +/** + * Identifier that uses context interfaces to guess the pattern type. + * + * @author Konstantin Kudryashov + * + * @deprecated in favour of --snippet-type and will be removed in 4.0 + */ +final class ContextInterfaceBasedPatternIdentifier implements PatternIdentifier +{ + /** + * {@inheritdoc} + */ + public function guessPatternType($contextClass) + { + if (!in_array('Behat\Behat\Context\CustomSnippetAcceptingContext', class_implements($contextClass))) { + return null; + } + + return $contextClass::getAcceptedSnippetType(); + } +} 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 000000000..edb2227f5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/ContextSnippetGenerator.php @@ -0,0 +1,360 @@ + + * + * 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; + + $this->setContextIdentifier(new FixedContextIdentifier(null)); + $this->setPatternIdentifier(new FixedPatternIdentifier(null)); + } + + /** + * Sets target context identifier. + * + * @param TargetContextIdentifier $identifier + */ + public function setContextIdentifier(TargetContextIdentifier $identifier) + { + $this->contextIdentifier = new CachedContextIdentifier($identifier); + } + + /** + * Sets target pattern type identifier. + * + * @param PatternIdentifier $identifier + */ + public function setPatternIdentifier(PatternIdentifier $identifier) + { + $this->patternIdentifier = $identifier; + } + + /** + * {@inheritdoc} + */ + public function supportsEnvironmentAndStep(Environment $environment, StepNode $step) + { + if (!$environment instanceof ContextEnvironment) { + return false; + } + + if (!$environment->hasContexts()) { + return false; + } + + return null !== $this->contextIdentifier->guessTargetContextClass($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->contextIdentifier->guessTargetContextClass($environment); + $patternType = $this->patternIdentifier->guessPatternType($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); + + $usedClasses = $this->getUsedClasses($step); + + return new ContextSnippet($step, $snippetTemplate, $contextClass, $usedClasses); + } + + /** + * 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; + } + + /** + * Returns an array of classes used by the snippet template + * + * @param StepNode $step + * + * @return string[] + */ + private function getUsedClasses(StepNode $step) + { + $usedClasses = array('Behat\Behat\Tester\Exception\PendingException'); + + foreach ($step->getArguments() as $argument) { + if ($argument instanceof TableNode) { + $usedClasses[] = 'Behat\Gherkin\Node\TableNode'; + } elseif ($argument instanceof PyStringNode) { + $usedClasses[] = 'Behat\Gherkin\Node\PyStringNode'; + } + } + + return $usedClasses; + } + + /** + * 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/Snippet/Generator/FixedContextIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/FixedContextIdentifier.php new file mode 100644 index 000000000..0d4b8e653 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/FixedContextIdentifier.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\Behat\Context\Snippet\Generator; + +use Behat\Behat\Context\Environment\ContextEnvironment; + +/** + * Identifier that always returns same context, if it is defined in the suite. + * + * @author Konstantin Kudryashov + */ +final class FixedContextIdentifier implements TargetContextIdentifier +{ + /** + * @var + */ + private $contextClass; + + /** + * Initialises identifier. + * + * @param string $contextClass + */ + public function __construct($contextClass) + { + $this->contextClass = $contextClass; + } + + /** + * {@inheritdoc} + */ + public function guessTargetContextClass(ContextEnvironment $environment) + { + if ($environment->hasContextClass($this->contextClass)) { + return $this->contextClass; + } + + return null; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/FixedPatternIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/FixedPatternIdentifier.php new file mode 100644 index 000000000..7358bd41b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/FixedPatternIdentifier.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\Snippet\Generator; + +use Behat\Behat\Context\Context; + +/** + * Identifier that always returns same pattern type. + * + * @author Konstantin Kudryashov + */ +final class FixedPatternIdentifier implements PatternIdentifier +{ + /** + * @var string + */ + private $patternType; + + /** + * Initialises identifier. + * + * @param string $patternType + */ + public function __construct($patternType) + { + $this->patternType = $patternType; + } + + /** + * {@inheritdoc} + */ + public function guessPatternType($contextClass) + { + return $this->patternType; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/PatternIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/PatternIdentifier.php new file mode 100644 index 000000000..c10b7f8f0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/PatternIdentifier.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\Context\Snippet\Generator; + +use Behat\Behat\Context\Context; + +/** + * Identifies target pattern for snippets. + * + * @author Konstantin Kudryashov + */ +interface PatternIdentifier +{ + /** + * Attempts to guess the target pattern type from the context. + * + * @param string $contextClass + * + * @return null|string + */ + public function guessPatternType($contextClass); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/TargetContextIdentifier.php b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/TargetContextIdentifier.php new file mode 100644 index 000000000..d7e534d2d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/Snippet/Generator/TargetContextIdentifier.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\Context\Snippet\Generator; + +use Behat\Behat\Context\Environment\ContextEnvironment; + +/** + * Identifies target context for snippets. + * + * @author Konstantin Kudryashov + */ +interface TargetContextIdentifier +{ + /** + * Attempts to guess the target context class from the environment. + * + * @param ContextEnvironment $environment + * + * @return null|string + */ + public function guessTargetContextClass(ContextEnvironment $environment); +} 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 000000000..2d6f7e9a1 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Context/SnippetAcceptingContext.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\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 + * + * @deprecated will be removed in 4.0. Use --snippets-for CLI option instead + */ +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 000000000..0bc41db7a --- /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 000000000..91bbb0503 --- /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 000000000..0c68af2b5 --- /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 000000000..324ffb8b9 --- /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 000000000..4c2c4946a --- /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 000000000..50dabc176 --- /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 000000000..1ff6560e2 --- /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 000000000..eaa22d400 --- /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 000000000..baa6c88ec --- /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 000000000..43b78b51c --- /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 000000000..14d276393 --- /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 000000000..b1db15ae6 --- /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 000000000..204d1aeb2 --- /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 000000000..bb5ba339a --- /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 000000000..07ee2e464 --- /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 000000000..1990bea8d --- /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 000000000..8a47c5e2e --- /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 000000000..bc3457b33 --- /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 000000000..bc23cb31f --- /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 000000000..17114e644 --- /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 000000000..0a3834ffc --- /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 000000000..6af5bacd6 --- /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 000000000..247624170 --- /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 000000000..6ea50a277 --- /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 000000000..c0732680f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Pattern/Policy/TurnipPatternPolicy.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\Definition\Pattern\Policy; + +use Behat\Behat\Definition\Pattern\Pattern; +use Behat\Behat\Definition\Exception\InvalidPatternException; +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 $regexCache = array(); + + /** + * @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) + { + if (!isset($this->regexCache[$pattern])) { + $this->regexCache[$pattern] = $this->createTransformedRegex($pattern); + } + return $this->regexCache[$pattern]; + } + + /** + * @param string $pattern + * @return string + */ + private function createTransformedRegex($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, + array($this, 'replaceTokenWithRegexCaptureGroup'), + $regex + ); + } + + private function replaceTokenWithRegexCaptureGroup($tokenMatch) + { + if (strlen($tokenMatch[1]) >= 32) { + throw new InvalidPatternException( + "Token name should not exceed 32 characters, but `{$tokenMatch[1]}` was used." + ); + } + + return sprintf(self::TOKEN_REGEX, $tokenMatch[1]); + } + + /** + * 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 000000000..d690982ee --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionInformationPrinter.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\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}' => $this->getDefinitionType($definition), + '{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() + ) + ); + + if ($this->isVerbose()) { + $lines[] = strtr( + '{space}| on `{filepath}[{start}:{end}]`', array( + '{space}' => str_pad('', mb_strlen($suite->getName(), 'utf8') + 1), + '{filepath}' => $definition->getReflection()->getFileName(), + '{start}' => $definition->getReflection()->getStartLine(), + '{end}' => $definition->getReflection()->getEndLine() + ) + ); + } + + 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 000000000..d155d9449 --- /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}' => $this->getDefinitionType($definition, true), + '{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 000000000..bd0546f41 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Printer/ConsoleDefinitionPrinter.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\Definition\Printer; + +use Behat\Behat\Definition\Definition; +use Behat\Behat\Definition\Pattern\PatternTransformer; +use Behat\Behat\Definition\Translator\DefinitionTranslator; +use Behat\Gherkin\Keywords\KeywordsInterface; +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; + /** + * @var KeywordsInterface + */ + private $keywords; + + /** + * Initializes printer. + * + * @param OutputInterface $output + * @param PatternTransformer $patternTransformer + * @param DefinitionTranslator $translator + * @param KeywordsInterface $keywords + */ + public function __construct( + OutputInterface $output, + PatternTransformer $patternTransformer, + DefinitionTranslator $translator, + KeywordsInterface $keywords + ) { + $this->output = $output; + $this->patternTransformer = $patternTransformer; + $this->translator = $translator; + $this->keywords = $keywords; + + $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(''); + } + + final protected function getDefinitionType(Definition $definition, $onlyOne = false) + { + $this->keywords->setLanguage($this->translator->getLocale()); + + $method = 'get'.ucfirst($definition->getType()).'Keywords'; + + $keywords = explode('|', $this->keywords->$method()); + + if ($onlyOne) { + return current($keywords); + } + + return 1 < count($keywords) ? '['.implode('|', $keywords).']' : implode('|', $keywords); + } + + /** + * 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); + } + + /** + * Returns whether verbosity is verbose (-v). + * + * @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise + */ + final protected function isVerbose() + { + return $this->output->isVerbose(); + } +} 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 000000000..826ce5b54 --- /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 000000000..6b694851b --- /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 000000000..a869adcec --- /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 000000000..158f63557 --- /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 000000000..cce43415b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/ServiceContainer/DefinitionExtension.php @@ -0,0 +1,310 @@ + + * + * 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\Behat\Gherkin\ServiceContainer\GherkinExtension; +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), + new Reference(GherkinExtension::KEYWORDS_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), + new Reference(GherkinExtension::KEYWORDS_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 000000000..3192a3d8e --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Definition/Translator/DefinitionTranslator.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\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; + } + + public function getLocale() + { + return $this->translator->getLocale(); + } +} 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 000000000..69813facb --- /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 000000000..d86b34573 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Cli/StopOnFailureController.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\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\Interpretation\ResultInterpretation; +use Behat\Testwork\Tester\Result\Interpretation\SoftInterpretation; +use Behat\Testwork\Tester\Result\Interpretation\StrictInterpretation; +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; + + /** + * @var ResultInterpretation + */ + private $resultInterpretation; + + /** + * Initializes controller. + * + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(EventDispatcherInterface $eventDispatcher) + { + $this->eventDispatcher = $eventDispatcher; + $this->resultInterpretation = new SoftInterpretation(); + } + + /** + * 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; + } + + if ($input->getOption('strict')) { + $this->resultInterpretation = new StrictInterpretation(); + } + + $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 (!$this->resultInterpretation->isFailure($event->getTestResult())) { + 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 000000000..59b32ad63 --- /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 000000000..76e15774c --- /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 000000000..73076ea68 --- /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 000000000..ed19128d5 --- /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 000000000..3251d24ca --- /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 000000000..b4fd1a258 --- /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 000000000..38666bfe1 --- /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 000000000..6af6f181c --- /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 000000000..cf9b6c5f5 --- /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 000000000..37b497bfa --- /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 000000000..f67f855c2 --- /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 000000000..b41671723 --- /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 000000000..d88a6f969 --- /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 000000000..82c9c7b22 --- /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 000000000..1f2f4ea5c --- /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 000000000..7980267dc --- /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 000000000..25aa4fdcd --- /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 000000000..da413b4eb --- /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 000000000..d2737b850 --- /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 000000000..6d9b9c6e9 --- /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 000000000..22b1e0921 --- /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 000000000..1bb1a4206 --- /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 000000000..f29c31c1a --- /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 000000000..3d1fe07b1 --- /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 000000000..149fc4ff7 --- /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 000000000..bd741858a --- /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 000000000..2251b4a27 --- /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 000000000..7053d0d55 --- /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 000000000..252cd03f5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/ServiceContainer/EventDispatcherExtension.php @@ -0,0 +1,175 @@ + + * + * 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); + $this->loadTickingStepTester($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); + } + + /** + * Loads ticking step tester. + * + * @param ContainerBuilder $container + */ + protected function loadTickingStepTester(ContainerBuilder $container) + { + if (!function_exists('pcntl_signal')) { + return; + } + + $definition = new Definition('Behat\Behat\EventDispatcher\Tester\TickingStepTester', array( + new Reference(TesterExtension::STEP_TESTER_ID) + )); + $definition->addTag(TesterExtension::STEP_TESTER_WRAPPER_TAG, array('priority' => 9999)); + $container->setDefinition(TesterExtension::STEP_TESTER_WRAPPER_TAG . '.ticking', $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 000000000..d947df55d --- /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 000000000..2bd0ad5dd --- /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 000000000..13d257cef --- /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 000000000..44eb13120 --- /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 000000000..6bf3c46b2 --- /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/EventDispatcher/Tester/TickingStepTester.php b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/TickingStepTester.php new file mode 100644 index 000000000..401725495 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/EventDispatcher/Tester/TickingStepTester.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\Tester; + +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; + +/** + * Enable ticks during step testing to allow SigintController in Testwork + * to handle an interupt (on PHP7) + * + * @see Behat\Testwork\EventDispatcher\Cli\SigintController + * + * @author Peter Mitchell + */ +final class TickingStepTester implements StepTester +{ + /** + * @var StepTester + */ + private $baseTester; + + /** + * Initializes tester. + * + * @param StepTester $baseTester + */ + public function __construct(StepTester $baseTester) + { + $this->baseTester = $baseTester; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, StepNode $step, $skip) + { + return $this->baseTester->setUp($env, $feature, $step, $skip); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, StepNode $step, $skip) + { + declare(ticks = 1); + + return $this->baseTester->test($env, $feature, $step, $skip); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, StepNode $step, $skip, StepResult $result) + { + return $this->baseTester->tearDown($env, $feature, $step, $skip, $result); + } +} 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 000000000..7f13989f1 --- /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 000000000..a3e3f6cfc --- /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 000000000..c24ddce17 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/ServiceContainer/GherkinExtension.php @@ -0,0 +1,384 @@ + + * + * 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'; + const KEYWORDS_ID = 'gherkin.keywords'; + + /* + * 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); + $this->loadFilesystemRerunScenariosListLocator($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(self::KEYWORDS_ID, $definition); + + $definition = new Definition('Behat\Gherkin\Keywords\KeywordsDumper', array( + new Reference(self::KEYWORDS_ID) + )); + $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->addMethodCall('setBasePath', array('%paths.base%')); + $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); + } + + /** + * Loads filesystem rerun scenarios list locator. + * + * @param ContainerBuilder $container + */ + private function loadFilesystemRerunScenariosListLocator(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Gherkin\Specification\Locator\FilesystemRerunScenariosListLocator', array( + new Reference(self::MANAGER_ID) + )); + $definition->addTag(SpecificationExtension::LOCATOR_TAG, array('priority' => 50)); + $container->setDefinition(SpecificationExtension::LOCATOR_TAG . '.filesystem_rerun_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)); + } + + if ('narrative' === $type) { + return new Definition('Behat\Gherkin\Filter\NarrativeFilter', 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('narrative', '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 000000000..61dd9bdb2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/LazyFeatureIterator.php @@ -0,0 +1,207 @@ + + * + * 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\NarrativeFilter; +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); + } + + if ('narrative' === $type) { + return new NarrativeFilter($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 000000000..d96cf8e1d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemFeatureLocator.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\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, + RecursiveDirectoryIterator::FOLLOW_SYMLINKS | RecursiveDirectoryIterator::SKIP_DOTS + ) + ), + '/^.+\.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/FilesystemRerunScenariosListLocator.php b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemRerunScenariosListLocator.php new file mode 100644 index 000000000..d5ac5b3a3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Gherkin/Specification/Locator/FilesystemRerunScenariosListLocator.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\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 FilesystemRerunScenariosListLocator 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(); + } + + /** + * {@inheritdoc} + */ + public function locateSpecifications(Suite $suite, $locator) + { + if (!is_file($locator) || 'rerun' !== pathinfo($locator, PATHINFO_EXTENSION)) { + return new NoSpecificationsIterator($suite); + } + + $scenarios = json_decode(trim(file_get_contents($locator)), true); + if (empty($scenarios) || empty($scenarios[$suite->getName()])) { + return new NoSpecificationsIterator($suite); + } + + return new LazyFeatureIterator($suite, $this->gherkin, $scenarios[$suite->getName()]); + } +} 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 000000000..59141df80 --- /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 000000000..65c7c8f73 --- /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/HelperContainer/Argument/AutowiringResolver.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Argument/AutowiringResolver.php new file mode 100644 index 000000000..11dde13b9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Argument/AutowiringResolver.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\HelperContainer\Argument; + +use Behat\Behat\Context\Argument\ArgumentResolver; +use Behat\Behat\HelperContainer\ArgumentAutowirer; +use Psr\Container\ContainerInterface; +use ReflectionClass; + +/** + * Resolves arguments that weren't resolved before by autowiring. + * + * @see ContextFactory + * + * @author Konstantin Kudryashov + */ +final class AutowiringResolver implements ArgumentResolver +{ + /** + * @var ArgumentAutowirer + */ + private $autowirer; + + /** + * Initialises resolver. + * + * @param ContainerInterface $container + */ + public function __construct(ContainerInterface $container) + { + $this->autowirer = new ArgumentAutowirer($container); + } + + /** + * {@inheritdoc} + */ + public function resolveArguments(ReflectionClass $classReflection, array $arguments) + { + if ($constructor = $classReflection->getConstructor()) { + return $this->autowirer->autowireArguments($constructor, $arguments); + } + + return $arguments; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/Argument/ServicesResolver.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Argument/ServicesResolver.php new file mode 100644 index 000000000..9e16f32de --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Argument/ServicesResolver.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\Behat\HelperContainer\Argument; + +use Behat\Behat\Context\Argument\ArgumentResolver; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; +use ReflectionClass; + +/** + * Resolves arguments using provided service container. + * + * @see ContextFactory + * + * @author Konstantin Kudryashov + */ +final class ServicesResolver implements ArgumentResolver +{ + /** + * @var ContainerInterface + */ + private $container; + + /** + * Initialises resolver. + * + * @param ContainerInterface $container + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + * + * @throws ContainerExceptionInterface + */ + public function resolveArguments(ReflectionClass $classReflection, array $arguments) + { + return array_map(array($this, 'resolveArgument'), $arguments); + } + + /** + * Attempts to resolve singular argument from container. + * + * Convention is strings starting with `@` are considered services and + * are expected to be present in the container. + * + * @param mixed $value + * + * @return mixed + * + * @throws ContainerExceptionInterface + */ + private function resolveArgument($value) + { + if (0 === mb_strpos($value, '@')) { + return $this->container->get(mb_substr($value, 1)); + } + + return $value; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/Argument/ServicesResolverFactory.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Argument/ServicesResolverFactory.php new file mode 100644 index 000000000..8820288c5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Argument/ServicesResolverFactory.php @@ -0,0 +1,220 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\HelperContainer\Argument; + +use Behat\Behat\Context\Argument\ArgumentResolver; +use Behat\Behat\HelperContainer\Environment\ServiceContainerEnvironment; +use Behat\Behat\Context\Argument\ArgumentResolverFactory; +use Behat\Behat\Context\Argument\SuiteScopedResolverFactory; +use Behat\Behat\HelperContainer\BuiltInServiceContainer; +use Behat\Behat\HelperContainer\Exception\WrongContainerClassException; +use Behat\Behat\HelperContainer\Exception\WrongServicesConfigurationException; +use Behat\Behat\HelperContainer\ServiceContainer\HelperContainerExtension; +use Behat\Testwork\Environment\Environment; +use Behat\Testwork\Suite\Suite; +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\TaggedContainerInterface; + +/** + * Generates ServiceContainer argument resolvers based on suite's `services` setting. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +final class ServicesResolverFactory implements SuiteScopedResolverFactory, ArgumentResolverFactory +{ + /** + * @var TaggedContainerInterface + */ + private $container; + + /** + * Initialises factory. + * + * @param TaggedContainerInterface $container + */ + public function __construct(TaggedContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + * + * @deprecated as part of SuiteScopedResolverFactory deprecation. Would be removed in 4.0 + * + * @throws WrongServicesConfigurationException + * @throws WrongContainerClassException + */ + public function generateArgumentResolvers(Suite $suite) + { + @trigger_error( + 'SuiteScopedResolverFactory::generateArgumentResolvers() was deprecated and will be removed in 4.0', + E_USER_DEPRECATED + ); + + if (!$suite->hasSetting('services')) { + return array(); + } + + $container = $this->createContainer($suite->getSetting('services')); + + return $this->createResolvers($container, false); + } + + /** + * {@inheritdoc} + * + * @throws WrongServicesConfigurationException + * @throws WrongContainerClassException + */ + public function createArgumentResolvers(Environment $environment) + { + $suite = $environment->getSuite(); + + if (!$suite->hasSetting('services')) { + return array(); + } + + $container = $this->createContainer($suite->getSetting('services')); + $autowire = $suite->hasSetting('autowire') && $suite->getSetting('autowire'); + + if ($environment instanceof ServiceContainerEnvironment) { + $environment->setServiceContainer($container); + } + + return $this->createResolvers($container, $autowire); + } + + /** + * Creates container from the setting passed. + * + * @param string $settings + * + * @return mixed + * + * @throws WrongServicesConfigurationException + */ + private function createContainer($settings) + { + if (is_string($settings)) { + return $this->createContainerFromString($settings); + } + + if (is_array($settings)) { + return $this->createContainerFromArray($settings); + } + + throw new WrongServicesConfigurationException( + sprintf('`services` must be either string or an array, but `%s` given.', gettype($settings)) + ); + } + + /** + * Creates custom container using class/constructor given. + * + * @param string $settings + * + * @return mixed + * + * @throws WrongServicesConfigurationException + */ + private function createContainerFromString($settings) + { + if (0 === mb_strpos($settings, '@')) { + return $this->loadContainerFromContainer(mb_substr($settings, 1)); + } + + return $this->createContainerFromClassSpec($settings); + } + + /** + * Creates built-in service container with provided settings. + * + * @param array $settings + * + * @return BuiltInServiceContainer + */ + private function createContainerFromArray(array $settings) + { + return new BuiltInServiceContainer($settings); + } + + /** + * Loads container from string. + * + * @param string $name + * + * @return mixed + * + * @throws WrongServicesConfigurationException + */ + private function loadContainerFromContainer($name) + { + $services = $this->container->findTaggedServiceIds(HelperContainerExtension::HELPER_CONTAINER_TAG); + + if (!array_key_exists($name, $services)) { + throw new WrongServicesConfigurationException( + sprintf('Service container `@%s` was not found.', $name) + ); + } + + return $this->container->get($name); + } + + /** + * Creates container from string-based class spec. + * + * @param string $classSpec + * + * @return mixed + */ + private function createContainerFromClassSpec($classSpec) + { + $constructor = explode('::', $classSpec); + + if (2 === count($constructor)) { + return call_user_func($constructor); + } + + return new $constructor[0]; + } + + /** + * Checks if container implements the correct interface and creates resolver using it. + * + * @param mixed $container + * @param bool $autowire + * + * @return ArgumentResolver[] + * + * @throws WrongContainerClassException + */ + private function createResolvers($container, $autowire) + { + if (!$container instanceof ContainerInterface) { + throw new WrongContainerClassException( + sprintf( + 'Service container is expected to implement `Psr\Container\ContainerInterface`, but `%s` does not.', + get_class($container) + ), + get_class($container) + ); + } + + if ($autowire) { + return array(new ServicesResolver($container), new AutowiringResolver($container)); + } + + return array(new ServicesResolver($container)); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/ArgumentAutowirer.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/ArgumentAutowirer.php new file mode 100644 index 000000000..d4d514728 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/ArgumentAutowirer.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\HelperContainer; + +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; +use ReflectionFunctionAbstract; +use ReflectionParameter; + +/** + * Automatically wires arguments of a given function from inside the container by using type-hitns. + * + * @author Konstantin Kudryashov + */ +final class ArgumentAutowirer +{ + /** + * @var ContainerInterface + */ + private $container; + + /** + * Initialises wirer. + * + * @param ContainerInterface $container + */ + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * Autowires given arguments using provided container. + * + * @param ReflectionFunctionAbstract $reflection + * @param array $arguments + * + * @return array + * + * @throws ContainerExceptionInterface if unset argument typehint can not be resolved from container + */ + public function autowireArguments(ReflectionFunctionAbstract $reflection, array $arguments) + { + $newArguments = $arguments; + foreach ($reflection->getParameters() as $index => $parameter) { + if ($this->isArgumentWireable($newArguments, $index, $parameter)) { + $newArguments[$index] = $this->container->get($parameter->getClass()->getName()); + } + } + + return $newArguments; + } + + /** + * Checks if given argument is wireable. + * + * Argument is wireable if it was not previously set and it has a class type-hint. + * + * @param array $arguments + * @param integer $index + * @param ReflectionParameter $parameter + * + * @return bool + */ + private function isArgumentWireable(array $arguments, $index, ReflectionParameter $parameter) + { + return !isset($arguments[$index]) && !isset($arguments[$parameter->getName()]) && $parameter->getClass(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/BuiltInServiceContainer.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/BuiltInServiceContainer.php new file mode 100644 index 000000000..624bd28e5 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/BuiltInServiceContainer.php @@ -0,0 +1,203 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\HelperContainer; + +use Behat\Behat\HelperContainer\Exception\ServiceNotFoundException; +use Behat\Behat\HelperContainer\Exception\WrongServicesConfigurationException; +use Interop\Container\ContainerInterface; +use ReflectionClass; +use ReflectionMethod; + +/** + * Built-in service container. + * + * @author Konstantin Kudryashov + */ +final class BuiltInServiceContainer implements ContainerInterface +{ + /** + * @var array + */ + private $schema; + /** + * @var array + */ + private $instances; + + /** + * Initialises container using provided service configuration. + * + * @param array $schema + */ + public function __construct(array $schema) + { + $this->schema = $schema; + } + + /** + * {@inheritdoc} + */ + public function has($id) + { + return array_key_exists($id, $this->schema); + } + + /** + * {@inheritdoc} + */ + public function get($id) + { + if (!$this->has($id)) { + throw new ServiceNotFoundException( + sprintf('Service with id `%s` was not defined inside the `services` setting`.', $id), + $id + ); + } + + return $this->instances[$id] = isset($this->instances[$id]) ? $this->instances[$id] : $this->createInstance($id); + } + + /** + * Creates an instance of given service. + * + * @param string $id + * + * @return mixed + */ + private function createInstance($id) + { + $schema = $this->getAndValidateServiceSchema($id); + + $reflection = new ReflectionClass($schema['class']); + $arguments = $schema['arguments']; + + if ($factoryMethod = $this->getAndValidateFactoryMethod($reflection, $schema)) { + return $factoryMethod->invokeArgs(null, $arguments); + } + + return $reflection->newInstanceArgs($arguments); + } + + /** + * Gets and validates a service configuration for a service with given ID. + * + * @param string $id + * + * @throws WrongServicesConfigurationException + * + * @return array|string + */ + private function getAndValidateServiceSchema($id) + { + $schema = $this->schema[$id]; + + if (null === $schema) { + $schema = array('class' => $id); + } + + if (is_string($schema)) { + $schema = array('class' => $schema); + } + + $schema['class'] = $this->getAndValidateClass($id, $schema); + $schema['arguments'] = $this->getAndValidateArguments($schema); + + return $schema; + } + + /** + * Gets and validates a class from schema. + * + * @param string $id + * @param string|array $schema + * + * @return string + */ + private function getAndValidateClass($id, array $schema) + { + if (!isset($schema['class'])) { + $schema['class'] = $id; + } + + return $schema['class']; + } + + /** + * Gets and validates arguments from schema. + * + * @param array $schema + * + * @return array + */ + private function getAndValidateArguments(array $schema) + { + return isset($schema['arguments']) ? (array)$schema['arguments'] : array(); + } + + /** + * Gets and validates a factory method. + * + * @param ReflectionClass $reflection + * @param array $schema + * + * @return null|ReflectionMethod + */ + private function getAndValidateFactoryMethod(ReflectionClass $reflection, array $schema) + { + if (!isset($schema['factory_method'])) { + return null; + } + + $factoryMethod = $schema['factory_method']; + $this->assertFactoryMethodExists($reflection, $factoryMethod); + $method = $reflection->getMethod($factoryMethod); + $this->assertFactoryMethodIsStatic($method); + + return $method; + } + + /** + * Checks if factory method exists. + * + * @param ReflectionClass $class + * @param string $methodName + * + * @throws WrongServicesConfigurationException + */ + private function assertFactoryMethodExists(ReflectionClass $class, $methodName) + { + if (!$class->hasMethod($methodName)) { + throw new WrongServicesConfigurationException(sprintf( + 'Factory method `%s::%s` does not exist.', + $class->getName(), + $methodName + )); + } + } + + /** + * Checks if factory method is static. + * + * @param ReflectionMethod $method + * + * @throws WrongServicesConfigurationException + */ + private function assertFactoryMethodIsStatic(ReflectionMethod $method) + { + if (!$method->isStatic()) { + throw new WrongServicesConfigurationException(sprintf( + 'Service factory methods must be static, but `%s::%s` is not.', + $method->getDeclaringClass()->getName(), + $method->getName() + )); + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/Call/Filter/ServicesResolver.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Call/Filter/ServicesResolver.php new file mode 100644 index 000000000..0c70fef71 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Call/Filter/ServicesResolver.php @@ -0,0 +1,204 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\HelperContainer\Call\Filter; + +use Behat\Behat\Definition\Definition; +use Behat\Behat\HelperContainer\Environment\ServiceContainerEnvironment; +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\HelperContainer\ArgumentAutowirer; +use Behat\Behat\HelperContainer\Exception\UnsupportedCallException; +use Behat\Behat\Transformation\Call\TransformationCall; +use Behat\Behat\Transformation\Transformation; +use Behat\Testwork\Call\Call; +use Behat\Testwork\Call\Filter\CallFilter; +use Behat\Testwork\Environment\Call\EnvironmentCall; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\ContainerInterface; + +/** + * Dynamically resolves call arguments using the service container. + * + * @author Konstantin Kudryashov + */ +final class ServicesResolver implements CallFilter +{ + /** + * {@inheritdoc} + */ + public function supportsCall(Call $call) + { + return ($call instanceof DefinitionCall || $call instanceof TransformationCall) + && $call->getEnvironment() instanceof ServiceContainerEnvironment; + } + + /** + * Filters a call and returns a new one. + * + * @param Call $call + * + * @return Call + * + * @throws UnsupportedCallException + * @throws ContainerExceptionInterface + */ + public function filterCall(Call $call) + { + if ($container = $this->getContainer($call)) { + $autowirer = new ArgumentAutowirer($container); + $newArguments = $autowirer->autowireArguments($call->getCallee()->getReflection(), $call->getArguments()); + + return $this->repackageCallIfNewArguments($call, $newArguments); + } + + return $call; + } + + /** + * Gets container from the call. + * + * @param Call $call + * + * @return null|ContainerInterface + * + * @throws UnsupportedCallException if given call is not EnvironmentCall or environment is not ServiceContainerEnvironment + */ + private function getContainer(Call $call) + { + if (!$call instanceof EnvironmentCall) { + throw new UnsupportedCallException(sprintf( + 'ServicesResolver can not filter `%s` call.', + get_class($call) + ), $call); + } + + $environment = $call->getEnvironment(); + + if (!$environment instanceof ServiceContainerEnvironment) { + throw new UnsupportedCallException(sprintf( + 'ServicesResolver can not filter `%s` call.', + get_class($call) + ), $call); + } + + return $environment->getServiceContainer(); + } + + /** + * Repackages old calls with new arguments, but only if two differ. + * + * @param Call $call + * @param array $arguments + * + * @return Call + * + * @throws UnsupportedCallException if given call is not DefinitionCall or TransformationCall + */ + private function repackageCallIfNewArguments(Call $call, array $arguments) + { + if ($arguments === $call->getArguments()) { + return $call; + } + + return $this->repackageCallWithNewArguments($call, $arguments); + } + + /** + * Repackages old calls with new arguments. + * + * @param Call $call + * @param array $newArguments + * + * @return DefinitionCall|TransformationCall + * + * @throws UnsupportedCallException + */ + private function repackageCallWithNewArguments(Call $call, array $newArguments) + { + if ($call instanceof DefinitionCall) { + return $this->repackageDefinitionCall($call, $newArguments); + } + + if ($call instanceof TransformationCall) { + return $this->repackageTransformationCall($call, $newArguments); + } + + throw new UnsupportedCallException( + sprintf( + 'ServicesResolver can not filter `%s` call.', + get_class($call) + ), $call + ); + } + + /** + * Repackages definition call with new arguments. + * + * @param DefinitionCall $call + * @param array $newArguments + * + * @return DefinitionCall + * + * @throws UnsupportedCallException + */ + private function repackageDefinitionCall(DefinitionCall $call, array $newArguments) + { + $definition = $call->getCallee(); + + if (!$definition instanceof Definition) { + throw new UnsupportedCallException( + sprintf( + 'Something is wrong in callee associated with `%s` call.', + get_class($call) + ), $call + ); + } + + return new DefinitionCall( + $call->getEnvironment(), + $call->getFeature(), + $call->getStep(), + $definition, + $newArguments, + $call->getErrorReportingLevel() + ); + } + + /** + * Repackages transformation call with new arguments. + * + * @param TransformationCall $call + * @param array $newArguments + * + * @return TransformationCall + * + * @throws UnsupportedCallException + */ + private function repackageTransformationCall(TransformationCall $call, array $newArguments) + { + $transformation = $call->getCallee(); + + if (!$transformation instanceof Transformation) { + throw new UnsupportedCallException( + sprintf( + 'Something is wrong in callee associated with `%s` call.', + get_class($call) + ), $call + ); + } + + return new TransformationCall( + $call->getEnvironment(), + $call->getDefinition(), + $transformation, + $newArguments + ); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/Environment/ServiceContainerEnvironment.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Environment/ServiceContainerEnvironment.php new file mode 100644 index 000000000..8f58ba623 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Environment/ServiceContainerEnvironment.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\HelperContainer\Environment; + +use Behat\Testwork\Environment\Environment; +use Psr\Container\ContainerInterface; + +/** + * Represents test environment based on a service locator pattern. + * + * @see ContextEnvironmentHandler + * + * @author Konstantin Kudryashov + */ +interface ServiceContainerEnvironment extends Environment +{ + /** + * Sets/unsets service container for the environment. + * + * @param ContainerInterface|null $container + */ + public function setServiceContainer(ContainerInterface $container = null); + + /** + * Returns environment service container if set. + * + * @return null|ContainerInterface + */ + public function getServiceContainer(); +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/HelperContainerException.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/HelperContainerException.php new file mode 100644 index 000000000..04ab35f96 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/HelperContainerException.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\HelperContainer\Exception; + +use Behat\Testwork\Environment\Exception\EnvironmentException; +use Interop\Container\Exception\ContainerException; + +/** + * All HelperContainer exceptions implement this interface. + * + * @author Konstantin Kudryashov + */ +interface HelperContainerException extends ContainerException, EnvironmentException +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/ServiceNotFoundException.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/ServiceNotFoundException.php new file mode 100644 index 000000000..02bd601b7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/ServiceNotFoundException.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\HelperContainer\Exception; + +use Interop\Container\Exception\NotFoundException; +use InvalidArgumentException; + +/** + * Represents an exception thrown when service ID is not found inside the container. + * + * @author Konstantin Kudryashov + */ +final class ServiceNotFoundException extends InvalidArgumentException implements HelperContainerException, NotFoundException +{ + /** + * @var string + */ + private $serviceId; + + /** + * Initializes exception. + * + * @param string $message + * @param string $serviceId + */ + public function __construct($message, $serviceId) + { + $this->serviceId = $serviceId; + + parent::__construct($message); + } + + /** + * Returns service ID that caused exception. + * + * @return string + */ + public function getServiceId() + { + return $this->serviceId; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/UnsupportedCallException.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/UnsupportedCallException.php new file mode 100644 index 000000000..7f16ca82f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/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\HelperContainer\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 HelperContainerException +{ + /** + * @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/HelperContainer/Exception/WrongContainerClassException.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/WrongContainerClassException.php new file mode 100644 index 000000000..5dd8321c6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/WrongContainerClassException.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\HelperContainer\Exception; + +use InvalidArgumentException; + +/** + * Represents an exception when provided class exists, but is not an acceptable as a container. + * + * @author Konstantin Kudryashov + */ +final class WrongContainerClassException extends InvalidArgumentException implements HelperContainerException +{ + /** + * @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/HelperContainer/Exception/WrongServicesConfigurationException.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/WrongServicesConfigurationException.php new file mode 100644 index 000000000..fd65f027b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/Exception/WrongServicesConfigurationException.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\HelperContainer\Exception; + +use RuntimeException; + +/** + * Represents an exception when wrong value passed into `services` setting. + * + * @author Konstantin Kudryashov + */ +final class WrongServicesConfigurationException extends RuntimeException implements HelperContainerException +{ +} diff --git a/vendor/behat/behat/src/Behat/Behat/HelperContainer/ServiceContainer/HelperContainerExtension.php b/vendor/behat/behat/src/Behat/Behat/HelperContainer/ServiceContainer/HelperContainerExtension.php new file mode 100644 index 000000000..1d5100f5c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/HelperContainer/ServiceContainer/HelperContainerExtension.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\HelperContainer\ServiceContainer; + +use Behat\Behat\Context\ServiceContainer\ContextExtension; +use Behat\Behat\HelperContainer\Exception\WrongServicesConfigurationException; +use Behat\Testwork\Call\ServiceContainer\CallExtension; +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; + +/** + * Behat helper container extension. + * + * Extends Behat with helper containers support. + * + * @author Konstantin Kudryashov + */ +final class HelperContainerExtension implements Extension +{ + /* + * Available extension points + */ + const HELPER_CONTAINER_TAG = 'helper_container.container'; + + /** + * @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 'helper_container'; + } + + /** + * {@inheritdoc} + */ + public function initialize(ExtensionManager $extensionManager) + { + } + + /** + * {@inheritdoc} + */ + public function configure(ArrayNodeDefinition $builder) + { + } + + /** + * {@inheritdoc} + */ + public function load(ContainerBuilder $container, array $config) + { + $definition = new Definition('Behat\Behat\HelperContainer\Argument\ServicesResolverFactory', array($container)); + $definition->addTag(ContextExtension::SUITE_SCOPED_RESOLVER_FACTORY_TAG, array('priority' => 0)); + $container->setDefinition(ContextExtension::SUITE_SCOPED_RESOLVER_FACTORY_TAG . '.helper_container', $definition); + + $definition = new Definition('Behat\Behat\HelperContainer\Call\Filter\ServicesResolver'); + $definition->addTag(CallExtension::CALL_FILTER_TAG, array('priority' => 0)); + $container->setDefinition(CallExtension::CALL_FILTER_TAG . '.helper_container', $definition); + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, self::HELPER_CONTAINER_TAG); + + foreach ($references as $reference) { + if ($this->isDefinitionShared($container->getDefinition((string) $reference))) { + throw new WrongServicesConfigurationException(sprintf( + 'Container services must not be configured as shared, but `@%s` is.', $reference + )); + } + } + } + + /** + * Checks if provided definition is shared. + * + * @param Definition $definition + * + * @return bool + * + * @todo Remove after upgrading to Symfony 2.8+ + */ + private function isDefinitionShared(Definition $definition) + { + if (method_exists($definition, 'isShared')) { + return $definition->isShared(); + } else if (method_exists($definition, 'getScope')) { + return $definition->getScope() !== ContainerBuilder::SCOPE_PROTOTYPE; + } + + 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 000000000..9041f1b4f --- /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 000000000..70fbaafcd --- /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 000000000..684ef7971 --- /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 000000000..60e326da3 --- /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 000000000..114def00a --- /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 000000000..390f91893 --- /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 000000000..b3d4fb24b --- /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 000000000..56e25f999 --- /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 000000000..a1326c3cf --- /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 000000000..86a95cca5 --- /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 000000000..4a321e976 --- /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 000000000..45985d9fb --- /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 000000000..54d63f06b --- /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 000000000..73254de4e --- /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 000000000..af4178eb6 --- /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 000000000..72e1cadd6 --- /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 000000000..fe87469de --- /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 000000000..c5238bc79 --- /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 = 'scenario.before'; + const AFTER = 'scenario.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 000000000..c07a79b02 --- /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 000000000..76d4be9be --- /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 000000000..288c6c006 --- /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 000000000..2ec0c06b1 --- /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 000000000..590d1f5a1 --- /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 000000000..5493bd667 --- /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 000000000..13bc0a415 --- /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 000000000..bacb12f3a --- /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 000000000..fa77da454 --- /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 000000000..77ac28e70 --- /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 000000000..0d62a56ef --- /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 000000000..8e116e06d --- /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 000000000..7e5788554 --- /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 000000000..f9bb95f64 --- /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 000000000..ad3679c8f --- /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/JUnit/JUnitFeatureElementListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/JUnit/JUnitFeatureElementListener.php new file mode 100644 index 000000000..465efb6ab --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/JUnit/JUnitFeatureElementListener.php @@ -0,0 +1,187 @@ + + * + * 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\JUnit; + +use Behat\Behat\EventDispatcher\Event\AfterFeatureTested; +use Behat\Behat\EventDispatcher\Event\AfterScenarioTested; +use Behat\Behat\EventDispatcher\Event\AfterStepSetup; +use Behat\Behat\EventDispatcher\Event\AfterStepTested; +use Behat\Behat\EventDispatcher\Event\BeforeFeatureTested; +use Behat\Behat\EventDispatcher\Event\ScenarioTested; +use Behat\Behat\EventDispatcher\Event\StepTested; +use Behat\Behat\Output\Node\Printer\FeaturePrinter; +use Behat\Behat\Output\Node\Printer\JUnit\JUnitScenarioPrinter; +use Behat\Behat\Output\Node\Printer\SetupPrinter; +use Behat\Behat\Output\Node\Printer\StepPrinter; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\EventDispatcher\Event\AfterSetup; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens to feature, scenario and step events and calls appropriate printers. + * + * @author Wouter J + */ +final class JUnitFeatureElementListener implements EventListener +{ + /** + * @var FeaturePrinter + */ + private $featurePrinter; + /** + * @var JUnitScenarioPrinter + */ + private $scenarioPrinter; + /** + * @var StepPrinter + */ + private $stepPrinter; + /** + * @var SetupPrinter + */ + private $setupPrinter; + /** + * @var FeatureNode + */ + private $beforeFeatureTestedEvent; + /** + * @var AfterScenarioTested[] + */ + private $afterScenarioTestedEvents = array(); + /** + * @var AfterStepTested[] + */ + private $afterStepTestedEvents = array(); + /** + * @var AfterSetup[] + */ + private $afterStepSetupEvents = array(); + + /** + * Initializes listener. + * + * @param FeaturePrinter $featurePrinter + * @param JUnitScenarioPrinter $scenarioPrinter + * @param StepPrinter $stepPrinter + * @param SetupPrinter $setupPrinter + */ + public function __construct(FeaturePrinter $featurePrinter, + JUnitScenarioPrinter $scenarioPrinter, + StepPrinter $stepPrinter, + SetupPrinter $setupPrinter) + { + $this->featurePrinter = $featurePrinter; + $this->scenarioPrinter = $scenarioPrinter; + $this->stepPrinter = $stepPrinter; + $this->setupPrinter = $setupPrinter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + if ($event instanceof ScenarioTested) { + $this->captureScenarioEvent($event); + } + + if ($event instanceof StepTested + || $event instanceof AfterStepSetup + ) { + $this->captureStepEvent($event); + } + + $this->captureFeatureOnBeforeEvent($event); + $this->printFeatureOnAfterEvent($formatter, $event); + } + + /** + * Captures scenario tested event. + * + * @param ScenarioTested $event + */ + private function captureScenarioEvent(ScenarioTested $event) + { + if ($event instanceof AfterScenarioTested) { + $this->afterScenarioTestedEvents[$event->getScenario()->getLine()] = array( + 'event' => $event, + 'step_events' => $this->afterStepTestedEvents, + 'step_setup_events' => $this->afterStepSetupEvents, + ); + + $this->afterStepTestedEvents = array(); + $this->afterStepSetupEvents = array(); + } + } + + /** + * Captures feature on BEFORE event. + * + * @param Event $event + */ + private function captureFeatureOnBeforeEvent(Event $event) + { + if (!$event instanceof BeforeFeatureTested) { + return; + } + + $this->beforeFeatureTestedEvent = $event->getFeature(); + } + + /** + * Captures step tested event. + * + * @param Event $event + */ + private function captureStepEvent(Event $event) + { + if ($event instanceof AfterStepTested) { + $this->afterStepTestedEvents[$event->getStep()->getLine()] = $event; + } + if ($event instanceof AfterStepSetup) { + $this->afterStepSetupEvents[$event->getStep()->getLine()] = $event; + } + } + + /** + * Prints the feature on AFTER event. + * + * @param Formatter $formatter + * @param Event $event + */ + public function printFeatureOnAfterEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterFeatureTested) { + return; + } + + $this->featurePrinter->printHeader($formatter, $this->beforeFeatureTestedEvent); + + foreach ($this->afterScenarioTestedEvents as $afterScenario) { + $afterScenarioTested = $afterScenario['event']; + $this->scenarioPrinter->printOpenTag($formatter, $afterScenarioTested->getFeature(), $afterScenarioTested->getScenario(), $afterScenarioTested->getTestResult()); + + /** @var AfterStepSetup $afterStepSetup */ + foreach ($afterScenario['step_setup_events'] as $afterStepSetup) { + $this->setupPrinter->printSetup($formatter, $afterStepSetup->getSetup()); + } + foreach ($afterScenario['step_events'] as $afterStepTested) { + $this->stepPrinter->printStep($formatter, $afterScenarioTested->getScenario(), $afterStepTested->getStep(), $afterStepTested->getTestResult()); + $this->setupPrinter->printTeardown($formatter, $afterStepTested->getTeardown()); + } + } + + $this->featurePrinter->printFooter($formatter, $event->getTestResult()); + $this->afterScenarioTestedEvents = array(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/JUnit/JUnitOutlineStoreListener.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/JUnit/JUnitOutlineStoreListener.php new file mode 100644 index 000000000..4458ebb73 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/JUnit/JUnitOutlineStoreListener.php @@ -0,0 +1,111 @@ + + * + * 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\JUnit; + +use Behat\Behat\EventDispatcher\Event\BeforeOutlineTested; +use Behat\Behat\Output\Node\Printer\SuitePrinter; +use Behat\Gherkin\Node\ExampleNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Testwork\EventDispatcher\Event\AfterSuiteTested; +use Behat\Testwork\EventDispatcher\Event\BeforeSuiteTested; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Node\EventListener\EventListener; +use Symfony\Component\EventDispatcher\Event; + +/** + * Listens for Outline events store the current one + * + * @author James Watson + */ +final class JUnitOutlineStoreListener implements EventListener +{ + + /** + * @var SuitePrinter + */ + private $suitePrinter; + + /** + * @var array + */ + private $lineScenarioMap = array(); + + /** + * Initializes listener. + * + * @param SuitePrinter $suitePrinter + */ + public function __construct(SuitePrinter $suitePrinter) + { + $this->suitePrinter = $suitePrinter; + } + + /** + * {@inheritdoc} + */ + public function listenEvent(Formatter $formatter, Event $event, $eventName) + { + $this->captureOutlineOnBeforeOutlineEvent($event); + + $this->printHeaderOnBeforeSuiteTestedEvent($formatter, $event); + $this->printFooterOnAfterSuiteTestedEvent($formatter, $event); + } + + /** + * Captures outline into the ivar on outline BEFORE event. + * + * @param Event $event + */ + private function captureOutlineOnBeforeOutlineEvent(Event $event) + { + if (!$event instanceof BeforeOutlineTested) { + return; + } + + $outline = $event->getOutline(); + foreach ($outline->getExamples() as $example) { + $this->lineScenarioMap[$example->getLine()] = $outline; + } + } + + /** + * @param Formatter $formatter + * @param Event $event + */ + private function printHeaderOnBeforeSuiteTestedEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof BeforeSuiteTested) { + return; + } + $this->suitePrinter->printHeader($formatter, $event->getSuite()); + } + + /** + * @param Formatter $formatter + * @param Event $event + */ + private function printFooterOnAfterSuiteTestedEvent(Formatter $formatter, Event $event) + { + if (!$event instanceof AfterSuiteTested) { + return; + } + $this->suitePrinter->printFooter($formatter, $event->getSuite()); + } + + /** + * @param ExampleNode $scenario + * @return OutlineNode + */ + public function getCurrentOutline(ExampleNode $scenario) + { + return $this->lineScenarioMap[$scenario->getLine()]; + } +} 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 000000000..a8d6007b9 --- /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 000000000..f83a38f78 --- /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 000000000..1845e1b64 --- /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 000000000..2f84d052b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/EventListener/Statistics/StepStatsListener.php @@ -0,0 +1,195 @@ + + * + * 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\BeforeScenarioTested; +use Behat\Behat\EventDispatcher\Event\FeatureTested; +use Behat\Behat\EventDispatcher\Event\ScenarioTested; +use Behat\Behat\Output\Statistics\StepStatV2; +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; + /** + * @var string + */ + private $scenarioTitle; + /** + * @var string + */ + private $scenarioPath; + + /** + * 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->captureScenarioOnBeforeFeatureEvent($event); + $this->forgetScenarioOnAfterFeatureEvent($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 current scenario title and path on scenario BEFORE event. + * + * @param Event $event + */ + private function captureScenarioOnBeforeFeatureEvent(Event $event) + { + if (!$event instanceof BeforeScenarioTested) { + return; + } + + $this->scenarioTitle = sprintf('%s: %s', $event->getScenario()->getKeyword(), $event->getScenario()->getTitle()); + $this->scenarioPath = sprintf('%s:%s', $this->currentFeaturePath, $event->getScenario()->getLine()); + } + + private function forgetScenarioOnAfterFeatureEvent($eventName) + { + if (ScenarioTested::AFTER !== $eventName) { + return; + } + + $this->scenarioTitle = $this->scenarioPath = 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 StepStatV2($this->scenarioTitle, $this->scenarioPath, $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 000000000..ff567dba3 --- /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 000000000..048f5475a --- /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 000000000..1b5299783 --- /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 000000000..699615f00 --- /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 000000000..dabddfd7d --- /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 000000000..d2becc573 --- /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 000000000..bef188128 --- /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/JUnit/JUnitFeaturePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitFeaturePrinter.php new file mode 100644 index 000000000..6b6e87184 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitFeaturePrinter.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\Output\Node\Printer\JUnit; + +use Behat\Behat\Output\Node\Printer\FeaturePrinter; +use Behat\Behat\Output\Statistics\PhaseStatistics; +use Behat\Behat\Tester\Result\StepResult; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\JUnitOutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints the element. + * + * @author Wouter J + */ +final class JUnitFeaturePrinter implements FeaturePrinter +{ + /** + * @var PhaseStatistics + */ + private $statistics; + + public function __construct(PhaseStatistics $statistics) + { + $this->statistics = $statistics; + } + + /** + * {@inheritDoc} + */ + public function printHeader(Formatter $formatter, FeatureNode $feature) + { + $stats = $this->statistics->getScenarioStatCounts(); + + if (0 === count($stats)) { + $totalCount = 0; + } else { + $totalCount = array_sum($stats); + } + + /** @var JUnitOutputPrinter $outputPrinter */ + $outputPrinter = $formatter->getOutputPrinter(); + + $outputPrinter->addTestsuite(array( + 'name' => $feature->getTitle(), + 'tests' => $totalCount, + 'skipped' => $stats[TestResult::SKIPPED], + 'failures' => $stats[TestResult::FAILED], + 'errors' => $stats[TestResult::PENDING] + $stats[StepResult::UNDEFINED], + )); + $this->statistics->reset(); + } + + /** + * {@inheritDoc} + */ + public function printFooter(Formatter $formatter, TestResult $result) + { + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitScenarioPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitScenarioPrinter.php new file mode 100644 index 000000000..cf61eaab9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitScenarioPrinter.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\Output\Node\Printer\JUnit; + +use Behat\Behat\Output\Node\EventListener\JUnit\JUnitOutlineStoreListener; +use Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter; +use Behat\Gherkin\Node\ExampleNode; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Node\OutlineNode; +use Behat\Gherkin\Node\ScenarioLikeInterface; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\JUnitOutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; + +/** + * Prints the element. + * + * @author Wouter J + */ +final class JUnitScenarioPrinter +{ + /** + * @var ResultToStringConverter + */ + private $resultConverter; + + /** + * @var JUnitOutlineStoreListener + */ + private $outlineStoreListener; + + /** + * @var OutlineNode + */ + private $lastOutline; + + /** + * @var int + */ + private $outlineStepCount; + + public function __construct(ResultToStringConverter $resultConverter, JUnitOutlineStoreListener $outlineListener) + { + $this->resultConverter = $resultConverter; + $this->outlineStoreListener = $outlineListener; + } + + /** + * {@inheritDoc} + */ + public function printOpenTag(Formatter $formatter, FeatureNode $feature, ScenarioLikeInterface $scenario, TestResult $result) + { + $name = implode(' ', array_map(function ($l) { + return trim($l); + }, explode("\n", $scenario->getTitle()))); + + if ($scenario instanceof ExampleNode) { + $name = $this->buildExampleName($scenario); + } + + /** @var JUnitOutputPrinter $outputPrinter */ + $outputPrinter = $formatter->getOutputPrinter(); + + $outputPrinter->addTestcase(array( + 'name' => $name, + 'status' => $this->resultConverter->convertResultToString($result) + )); + } + + /** + * @param ExampleNode $scenario + * @return string + */ + private function buildExampleName(ExampleNode $scenario) + { + $currentOutline = $this->outlineStoreListener->getCurrentOutline($scenario); + if ($currentOutline === $this->lastOutline) { + $this->outlineStepCount++; + } else { + $this->lastOutline = $currentOutline; + $this->outlineStepCount = 1; + } + + $name = $currentOutline->getTitle() . ' #' . $this->outlineStepCount; + return $name; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitSetupPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitSetupPrinter.php new file mode 100644 index 000000000..401c7e911 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitSetupPrinter.php @@ -0,0 +1,87 @@ + + */ +class JUnitSetupPrinter implements SetupPrinter +{ + + /** @var ExceptionPresenter */ + private $exceptionPresenter; + + public function __construct(ExceptionPresenter $exceptionPresenter) + { + $this->exceptionPresenter = $exceptionPresenter; + } + + /** + * {@inheritdoc} + */ + public function printSetup(Formatter $formatter, Setup $setup) + { + if (!$setup->isSuccessful()) { + if ($setup instanceof HookedSetup) { + $this->handleHookCalls($formatter, $setup->getHookCallResults(), 'setup'); + } + } + } + + /** + * {@inheritdoc} + */ + public function printTeardown(Formatter $formatter, Teardown $teardown) + { + if (!$teardown->isSuccessful()) { + if ($teardown instanceof HookedTeardown) { + $this->handleHookCalls($formatter, $teardown->getHookCallResults(), 'teardown'); + } + } + } + + /** + * @param Formatter $formatter + * @param CallResults $results + * @param string $messageType + */ + private function handleHookCalls(Formatter $formatter, CallResults $results, $messageType) + { + /** @var CallResult $hookCallResult */ + foreach ($results as $hookCallResult) { + if ($hookCallResult->hasException()) { + /** @var HookCall $call */ + $call = $hookCallResult->getCall(); + $scope = $call->getScope(); + /** @var JUnitOutputPrinter $outputPrinter */ + $outputPrinter = $formatter->getOutputPrinter(); + + $message = ''; + if ($scope instanceof StepScope) { + $message .= $scope->getStep()->getKeyword() . ' ' . $scope->getStep()->getText() . ': '; + } + $message .= $this->exceptionPresenter->presentException($hookCallResult->getException()); + + $attributes = array( + 'message' => $message, + 'type' => $messageType, + ); + + $outputPrinter->addTestcaseChild('failure', $attributes); + + } + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitStepPrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitStepPrinter.php new file mode 100644 index 000000000..dcca50d76 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitStepPrinter.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\Output\Node\Printer\JUnit; + +use Behat\Behat\Tester\Result\StepResult; +use Behat\Behat\Output\Node\Printer\StepPrinter; +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\JUnitOutputPrinter; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\ExceptionResult; + +/** + * Prints step with optional results. + * + * @author Wouter J + * @author James Watson + */ +class JUnitStepPrinter implements StepPrinter +{ + /** + * @var ExceptionPresenter + */ + private $exceptionPresenter; + + public function __construct(ExceptionPresenter $exceptionPresenter) + { + $this->exceptionPresenter = $exceptionPresenter; + } + + /** + * 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) + { + /** @var JUnitOutputPrinter $outputPrinter */ + $outputPrinter = $formatter->getOutputPrinter(); + + $message = $step->getKeyword() . ' ' . $step->getText(); + + if ($result instanceof ExceptionResult && $result->hasException()) { + $message .= ': ' . $this->exceptionPresenter->presentException($result->getException()); + } + + $attributes = array('message' => $message); + + switch ($result->getResultCode()) { + case TestResult::FAILED: + $outputPrinter->addTestcaseChild('failure', $attributes); + break; + + case TestResult::PENDING: + $attributes['type'] = 'pending'; + $outputPrinter->addTestcaseChild('error', $attributes); + break; + + case StepResult::UNDEFINED: + $attributes['type'] = 'undefined'; + $outputPrinter->addTestcaseChild('error', $attributes); + break; + } + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitSuitePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitSuitePrinter.php new file mode 100644 index 000000000..7e5efadc8 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/JUnit/JUnitSuitePrinter.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\JUnit; + +use Behat\Behat\Output\Node\Printer\SuitePrinter; +use Behat\Behat\Output\Statistics\PhaseStatistics; +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Output\Printer\JUnitOutputPrinter; +use Behat\Testwork\Suite\Suite; + +/** + * Creates new JUnit report file. + * + * @author Wouter J + */ +final class JUnitSuitePrinter implements SuitePrinter +{ + /** + * @var PhaseStatistics + */ + private $statistics; + + public function __construct(PhaseStatistics $statistics = null) + { + $this->statistics = $statistics; + } + + /** + * {@inheritDoc} + */ + public function printHeader(Formatter $formatter, Suite $suite) + { + if ($this->statistics) { + $this->statistics->reset(); + } + + /** @var JUnitOutputPrinter $outputPrinter */ + $outputPrinter = $formatter->getOutputPrinter(); + $outputPrinter->createNewFile($suite->getName()); + } + + /** + * {@inheritDoc} + */ + public function printFooter(Formatter $formatter, Suite $suite) + { + $formatter->getOutputPrinter()->flush(); + } +} 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 000000000..31e8388ee --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/ListPrinter.php @@ -0,0 +1,271 @@ + + * + * 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\StepStatV2; +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 $num => $stepStat) { + if ($stepStat instanceof StepStatV2) { + $this->printStepStat($printer, $num + 1, $stepStat, $style); + } elseif ($stepStat instanceof StepStat) { + $this->printStat($printer, $stepStat->getText(), $stepStat->getPath(), $style, $stepStat->getStdOut(), $stepStat->getError()); + } + } + } + + /** + * 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) { + $this->printHookStat($printer, $hookStat, $style); + } + } + + /** + * Prints hook stat. + * + * @param OutputPrinter $printer + * @param string $name + * @param string $path + * @param string $style + * @param null|string $stdOut + * @param null|string $error + * + * @deprecated Remove in 4.0 + */ + 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(); + } + + /** + * Prints hook stat. + * + * @param OutputPrinter $printer + * @param HookStat $hookStat + * @param string $style + */ + private function printHookStat(OutputPrinter $printer, HookStat $hookStat, $style) + { + $printer->writeln( + sprintf(' {+%s}%s{-%s} {+comment}# %s{-comment}', + $style, $hookStat->getName(), $style, $this->relativizePaths($hookStat->getPath()) + ) + ); + + $pad = function ($line) { return ' ' . $line; }; + + if (null !== $hookStat->getStdOut()) { + $padText = function ($line) { return ' │ ' . $line; }; + $stdOutString = array_map($padText, explode("\n", $hookStat->getStdOut())); + $printer->writeln(implode("\n", $stdOutString)); + } + + if ($hookStat->getError()) { + $exceptionString = implode("\n", array_map($pad, explode("\n", $hookStat->getError()))); + $printer->writeln(sprintf('{+%s}%s{-%s}', $style, $exceptionString, $style)); + } + + $printer->writeln(); + } + + /** + * Prints hook stat. + * + * @param OutputPrinter $printer + * @param integer $number + * @param StepStatV2 $stat + * @param string $style + */ + private function printStepStat(OutputPrinter $printer, $number, StepStatV2 $stat, $style) + { + $maxLength = max(mb_strlen($stat->getScenarioText(), 'utf8'), mb_strlen($stat->getStepText(), 'utf8') + 2) + 1; + + $printer->writeln( + sprintf('%03d {+%s}%s{-%s}%s{+comment}# %s{-comment}', + $number, + $style, + $stat->getScenarioText(), + $style, + str_pad(' ', $maxLength - mb_strlen($stat->getScenarioText(), 'utf8')), + $this->relativizePaths($stat->getScenarioPath()) + ) + ); + + $printer->writeln( + sprintf(' {+%s}%s{-%s}%s{+comment}# %s{-comment}', + $style, + $stat->getStepText(), + $style, + str_pad(' ', $maxLength - mb_strlen($stat->getStepText(), 'utf8') - 2), + $this->relativizePaths($stat->getStepPath()) + ) + ); + + $pad = function ($line) { return ' ' . $line; }; + + if (null !== $stat->getStdOut()) { + $padText = function ($line) { return ' │ ' . $line; }; + $stdOutString = array_map($padText, explode("\n", $stat->getStdOut())); + $printer->writeln(implode("\n", $stdOutString)); + } + + if ($stat->getError()) { + $exceptionString = implode("\n", array_map($pad, explode("\n", $stat->getError()))); + $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 000000000..eb460ad34 --- /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 000000000..488fae6de --- /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 000000000..2d5babf83 --- /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 000000000..109dd25d6 --- /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 000000000..1a352c756 --- /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 000000000..8fbc03392 --- /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 000000000..ea0298e05 --- /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 000000000..9ea0b684a --- /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 000000000..378a99118 --- /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 000000000..46bcba3a3 --- /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 000000000..718afd3b9 --- /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 000000000..23702c747 --- /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 000000000..8d47da1ec --- /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 000000000..a104178d2 --- /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 000000000..ca1656f9a --- /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 000000000..0260c41b3 --- /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 000000000..5a0652766 --- /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 000000000..7999a2016 --- /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 000000000..7b03c4bf1 --- /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/Node/Printer/SuitePrinter.php b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/SuitePrinter.php new file mode 100644 index 000000000..58b8ef986 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Node/Printer/SuitePrinter.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\Output\Node\Printer; + +use Behat\Testwork\Output\Formatter; +use Behat\Testwork\Suite\Suite; + +/** + * Prints suite headers and footers. + * + * @author Wouter J + */ +interface SuitePrinter +{ + /** + * Prints suite header using provided formatter. + * + * @param Formatter $formatter + * @param Suite $suite + */ + public function printHeader(Formatter $formatter, Suite $suite); + + /** + * Prints suite footer using provided printer. + * + * @param Formatter $formatter + * @param Suite $suite + */ + public function printFooter(Formatter $formatter, Suite $suite); +} diff --git a/vendor/behat/behat/src/Behat/Behat/Output/Printer/ConsoleOutputFactory.php b/vendor/behat/behat/src/Behat/Behat/Output/Printer/ConsoleOutputFactory.php new file mode 100644 index 000000000..4764e1772 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Printer/ConsoleOutputFactory.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\Output\Printer; + +use Behat\Behat\Output\Printer\Formatter\ConsoleFormatter; +use Behat\Testwork\Output\Printer\Factory\ConsoleOutputFactory as BaseFactory; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; + +/** + * Extends default printer with default styles. + * + * @author Konstantin Kudryashov + */ +final class ConsoleOutputFactory extends BaseFactory +{ + /** + * {@inheritDoc} + */ + 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 000000000..9b403a68e --- /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/JUnitFormatterFactory.php b/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/JUnitFormatterFactory.php new file mode 100644 index 000000000..a9d289516 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/JUnitFormatterFactory.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\Output\ServiceContainer\Formatter; + +use Behat\Testwork\Exception\ServiceContainer\ExceptionExtension; +use Behat\Testwork\Output\ServiceContainer\Formatter\FormatterFactory; +use Behat\Testwork\Output\ServiceContainer\OutputExtension; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Behat junit formatter factory. + * + * @author Wouter J + */ +final class JUnitFormatterFactory implements FormatterFactory +{ + /* + * Available services + */ + const ROOT_LISTENER_ID = 'output.node.listener.junit'; + const RESULT_TO_STRING_CONVERTER_ID = 'output.node.printer.result_to_string'; + + /** + * {@inheritdoc} + */ + public function buildFormatter(ContainerBuilder $container) + { + $this->loadRootNodeListener($container); + $this->loadPrinterHelpers($container); + $this->loadCorePrinters($container); + $this->loadFormatter($container); + } + + /** + * {@inheritdoc} + */ + public function processFormatter(ContainerBuilder $container) + { + } + + /** + * Loads printer helpers. + * + * @param ContainerBuilder $container + */ + private function loadPrinterHelpers(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\Helper\ResultToStringConverter'); + $container->setDefinition(self::RESULT_TO_STRING_CONVERTER_ID, $definition); + } + + /** + * Loads the printers used to print the basic JUnit report. + * + * @param ContainerBuilder $container + */ + private function loadCorePrinters(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Node\Printer\JUnit\JUnitSuitePrinter', array( + new Reference('output.junit.statistics'), + )); + $container->setDefinition('output.node.printer.junit.suite', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\JUnit\JUnitFeaturePrinter', array( + new Reference('output.junit.statistics'), + )); + $container->setDefinition('output.node.printer.junit.feature', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\JUnit\JUnitScenarioPrinter', array( + new Reference(self::RESULT_TO_STRING_CONVERTER_ID), + new Reference('output.node.listener.junit.outline'), + )); + $container->setDefinition('output.node.printer.junit.scenario', $definition); + + $definition = new Definition('Behat\Behat\Output\Node\Printer\JUnit\JUnitStepPrinter', array( + new Reference(ExceptionExtension::PRESENTER_ID), + )); + $container->setDefinition('output.node.printer.junit.step', $definition); + + $definition = new Definition( + 'Behat\Behat\Output\Node\Printer\JUnit\JUnitSetupPrinter', array( + new Reference(ExceptionExtension::PRESENTER_ID), + ) + ); + $container->setDefinition('output.node.printer.junit.setup', $definition); + } + + /** + * Loads the node listeners required for JUnit printers to work. + * + * @param ContainerBuilder $container + */ + private function loadRootNodeListener(ContainerBuilder $container) + { + + $definition = new Definition('Behat\Behat\Output\Node\EventListener\JUnit\JUnitOutlineStoreListener', array( + new Reference('output.node.printer.junit.suite') + ) + ); + $container->setDefinition('output.node.listener.junit.outline', $definition); + + + $definition = new Definition('Behat\Testwork\Output\Node\EventListener\ChainEventListener', array( + array( + new Reference('output.node.listener.junit.outline'), + new Definition('Behat\Behat\Output\Node\EventListener\JUnit\JUnitFeatureElementListener', array( + new Reference('output.node.printer.junit.feature'), + new Reference('output.node.printer.junit.scenario'), + new Reference('output.node.printer.junit.step'), + new Reference('output.node.printer.junit.setup'), + )), + ), + )); + $container->setDefinition(self::ROOT_LISTENER_ID, $definition); + } + + /** + * Loads formatter itself. + * + * @param ContainerBuilder $container + */ + private function loadFormatter(ContainerBuilder $container) + { + $definition = new Definition('Behat\Behat\Output\Statistics\PhaseStatistics'); + $container->setDefinition('output.junit.statistics', $definition); + + $definition = new Definition('Behat\Testwork\Output\NodeEventListeningFormatter', array( + 'junit', + 'Outputs the failures in JUnit compatible files.', + 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\ScenarioStatsListener', array( + new Reference('output.junit.statistics') + )), + new Definition('Behat\Behat\Output\Node\EventListener\Statistics\StepStatsListener', array( + new Reference('output.junit.statistics'), + new Reference(ExceptionExtension::PRESENTER_ID) + )), + new Definition('Behat\Behat\Output\Node\EventListener\Statistics\HookStatsListener', array( + new Reference('output.junit.statistics'), + new Reference(ExceptionExtension::PRESENTER_ID) + )), + ), + )), + )); + $definition->addTag(OutputExtension::FORMATTER_TAG, array('priority' => 100)); + $container->setDefinition(OutputExtension::FORMATTER_TAG . '.junit', $definition); + } + + /** + * Creates output printer definition. + * + * @return Definition + */ + private function createOutputPrinterDefinition() + { + return new Definition('Behat\Testwork\Output\Printer\JUnitOutputPrinter', array( + new Definition('Behat\Testwork\Output\Printer\Factory\FilesystemOutputFactory'), + )); + } +} 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 000000000..261b509a8 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/PrettyFormatterFactory.php @@ -0,0 +1,469 @@ + + * + * 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\TotalStatistics'); + $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\Testwork\Output\Printer\StreamOutputPrinter', array( + new Definition('Behat\Behat\Output\Printer\ConsoleOutputFactory'), + )); + } + + /** + * 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 000000000..e19acdc05 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/ServiceContainer/Formatter/ProgressFormatterFactory.php @@ -0,0 +1,195 @@ + + * + * 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\TotalStatistics'); + $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\Testwork\Output\Printer\StreamOutputPrinter', array( + new Definition('Behat\Behat\Output\Printer\ConsoleOutputFactory'), + )); + } + + /** + * 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 000000000..e8afc312a --- /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/PhaseStatistics.php b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/PhaseStatistics.php new file mode 100644 index 000000000..c21e942c0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/PhaseStatistics.php @@ -0,0 +1,179 @@ + + * + * 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\Testwork\Counter\Timer; +use Behat\Testwork\Counter\Memory; + +/** + * A TotalStatistics decorator to get statistics per phase. + * + * This is useful to show the amount of failures + * in a single suite for instance. + * + * @author Wouter J + */ +final class PhaseStatistics implements Statistics +{ + /** + * @var TotalStatistics + */ + private $statistics; + + public function __construct() + { + $this->statistics = new TotalStatistics(); + } + + /** + * Resets the statistics. + */ + public function reset() + { + $this->statistics = new TotalStatistics(); + } + + /** + * Starts timer. + */ + public function startTimer() + { + $this->statistics->startTimer(); + } + + /** + * Stops timer. + */ + public function stopTimer() + { + $this->statistics->stopTimer(); + } + + /** + * Returns timer object. + * + * @return Timer + */ + public function getTimer() + { + return $this->statistics->getTimer(); + } + + /** + * Returns memory usage object. + * + * @return Memory + */ + public function getMemory() + { + return $this->statistics->getMemory(); + } + + /** + * Registers scenario stat. + * + * @param ScenarioStat $stat + */ + public function registerScenarioStat(ScenarioStat $stat) + { + $this->statistics->registerScenarioStat($stat); + } + + /** + * Registers step stat. + * + * @param StepStat $stat + */ + public function registerStepStat(StepStat $stat) + { + $this->statistics->registerStepStat($stat); + } + + /** + * Registers hook stat. + * + * @param HookStat $stat + */ + public function registerHookStat(HookStat $stat) + { + $this->statistics->registerHookStat($stat); + } + + /** + * Returns counters for different scenario result codes. + * + * @return array[] + */ + public function getScenarioStatCounts() + { + return $this->statistics->getScenarioStatCounts(); + } + + /** + * Returns skipped scenario stats. + * + * @return ScenarioStat[] + */ + public function getSkippedScenarios() + { + return $this->statistics->getSkippedScenarios(); + } + + /** + * Returns failed scenario stats. + * + * @return ScenarioStat[] + */ + public function getFailedScenarios() + { + return $this->statistics->getFailedScenarios(); + } + + /** + * Returns counters for different step result codes. + * + * @return array[] + */ + public function getStepStatCounts() + { + return $this->statistics->getStepStatCounts(); + } + + /** + * Returns failed step stats. + * + * @return StepStat[] + */ + public function getFailedSteps() + { + return $this->statistics->getFailedSteps(); + } + + /** + * Returns pending step stats. + * + * @return StepStat[] + */ + public function getPendingSteps() + { + return $this->statistics->getPendingSteps(); + } + + /** + * Returns failed hook stats. + * + * @return HookStat[] + */ + public function getFailedHookStats() + { + return $this->statistics->getFailedHookStats(); + } +} 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 000000000..0af5005d1 --- /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 000000000..4d20de9ec --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/Statistics.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\Output\Statistics; + +use Behat\Testwork\Counter\Memory; +use Behat\Testwork\Counter\Timer; + + +/** + * Collects and provided exercise statistics. + * + * @author Wouter J + */ +interface Statistics +{ + /** + * Starts timer. + */ + public function startTimer(); + + /** + * Stops timer. + */ + public function stopTimer(); + + /** + * Returns timer object. + * + * @return Timer + */ + public function getTimer(); + + /** + * Returns memory usage object. + * + * @return Memory + */ + public function getMemory(); + + /** + * Registers scenario stat. + * + * @param ScenarioStat $stat + */ + public function registerScenarioStat(ScenarioStat $stat); + + /** + * Registers step stat. + * + * @param StepStat $stat + */ + public function registerStepStat(StepStat $stat); + + /** + * Registers hook stat. + * + * @param HookStat $stat + */ + public function registerHookStat(HookStat $stat); + + /** + * Returns counters for different scenario result codes. + * + * @return array[] + */ + public function getScenarioStatCounts(); + + /** + * Returns skipped scenario stats. + * + * @return ScenarioStat[] + */ + public function getSkippedScenarios(); + + /** + * Returns failed scenario stats. + * + * @return ScenarioStat[] + */ + public function getFailedScenarios(); + + /** + * Returns counters for different step result codes. + * + * @return array[] + */ + public function getStepStatCounts(); + + /** + * Returns failed step stats. + * + * @return StepStat[] + */ + public function getFailedSteps(); + + /** + * Returns pending step stats. + * + * @return StepStat[] + */ + public function getPendingSteps(); + + /** + * Returns failed hook stats. + * + * @return HookStat[] + */ + public function getFailedHookStats(); +} 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 000000000..320d287d8 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/StepStat.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\Output\Statistics; + +/** + * Behat step stat. + * + * @author Konstantin Kudryashov + * + * @deprecated in favour of StepStatV2 and to be removed in 4.0 + */ +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/Output/Statistics/StepStatV2.php b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/StepStatV2.php new file mode 100644 index 000000000..ae13fc6bf --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/StepStatV2.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\Behat\Output\Statistics; + +/** + * Second iteration of Behat step stat, with a scenario information. + * + * @author Konstantin Kudryashov + */ +final class StepStatV2 extends StepStat +{ + /** + * @var string + */ + private $scenarioTitle; + /** + * @var string + */ + private $scenarioPath; + /** + * @var string + */ + private $stepText; + /** + * @var string + */ + private $stepPath; + /** + * @var integer + */ + private $resultCode; + /** + * @var null|string + */ + private $error; + /** + * @var null|string + */ + private $stdOut; + + /** + * Initializes step stat. + * + * @param string $scenarioTitle + * @param string $scenarioPath + * @param string $stepText + * @param string $stepPath + * @param integer $resultCode + * @param null|string $error + * @param null|string $stdOut + */ + public function __construct($scenarioTitle, $scenarioPath, $stepText, $stepPath, $resultCode, $error = null, $stdOut = null) + { + parent::__construct($stepText, $stepPath, $resultCode, $error, $stdOut); + + $this->scenarioTitle = $scenarioTitle; + $this->scenarioPath = $scenarioPath; + $this->stepText = $stepText; + $this->stepPath = $stepPath; + $this->resultCode = $resultCode; + $this->error = $error; + $this->stdOut = $stdOut; + } + + /** + * Returns associated scenario text. + * + * @return string + */ + public function getScenarioText() + { + return $this->scenarioTitle; + } + + /** + * Returns associated scenario path. + * + * @return string + */ + public function getScenarioPath() + { + return $this->scenarioPath; + } + + /** + * Returns step text. + * + * @return string + */ + public function getStepText() + { + return $this->stepText; + } + + /** + * Returns step path. + * + * @return string + */ + public function getStepPath() + { + return $this->stepPath; + } + + /** + * 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/Output/Statistics/TotalStatistics.php b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/TotalStatistics.php new file mode 100644 index 000000000..1b89e87a9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Output/Statistics/TotalStatistics.php @@ -0,0 +1,244 @@ + + * + * 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 TotalStatistics implements 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->resetAllCounters(); + + $this->timer = new Timer(); + $this->memory = new Memory(); + } + + public function resetAllCounters() + { + $this->scenarioCounters = $this->stepCounters = array( + TestResult::PASSED => 0, + TestResult::FAILED => 0, + StepResult::UNDEFINED => 0, + TestResult::PENDING => 0, + TestResult::SKIPPED => 0 + ); + } + + /** + * 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/Snippet/AggregateSnippet.php b/vendor/behat/behat/src/Behat/Behat/Snippet/AggregateSnippet.php new file mode 100644 index 000000000..cbadc0566 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Snippet/AggregateSnippet.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\Snippet; + +use Behat\Behat\Context\Snippet\ContextSnippet; +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 + ) + ); + } + + /** + * Returns the classes used in the snippet which should be imported. + * + * @return string[] + */ + public function getUsedClasses() + { + if (empty($this->snippets)) { + return array(); + } + + return array_unique( + call_user_func_array( + 'array_merge', + array_map( + function (Snippet $snippet) { + if (!$snippet instanceof ContextSnippet) { + return array(); + } + + return $snippet->getUsedClasses(); + }, + $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 000000000..041b8e6e5 --- /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 000000000..8ecdac5fb --- /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 000000000..5b01e2f13 --- /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 000000000..f3b23ae5b --- /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 000000000..ca7d73937 --- /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 000000000..7a5b36e74 --- /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 000000000..a0050af2d --- /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 000000000..992c3716d --- /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 000000000..b96e44578 --- /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 000000000..0724c3e40 --- /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 000000000..0305c4c2b --- /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 000000000..62d6e96e1 --- /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 000000000..58e3ddda2 --- /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 000000000..8d70b57d8 --- /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 000000000..93bd84ff9 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Cli/RerunController.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\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 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; + +/** + * 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(); + /** + * @var string + */ + private $basepath; + + /** + * Initializes controller. + * + * @param EventDispatcherInterface $eventDispatcher + * @param null|string $cachePath + * @param string $basepath + */ + public function __construct(EventDispatcherInterface $eventDispatcher, $cachePath, $basepath) + { + $this->eventDispatcher = $eventDispatcher; + $this->cachePath = null !== $cachePath ? rtrim($cachePath, DIRECTORY_SEPARATOR) : null; + $this->basepath = $basepath; + } + + /** + * 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()->getResultCode() !== TestResult::FAILED) { + return; + } + + $feature = $event->getFeature(); + $scenario = $event->getScenario(); + $suitename = $event->getSuite()->getName(); + + $this->lines[$suitename][] = $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(), json_encode($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') . + $this->basepath + ); + } + + /** + * 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 . '.rerun'; + } +} 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 000000000..6d31eb1c0 --- /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 000000000..c328bd1ae --- /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 000000000..ef299cefb --- /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 000000000..863aba38c --- /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 000000000..ba0c935b1 --- /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 000000000..40633ec7d --- /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 000000000..94fe072ec --- /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 000000000..4788d247f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Result/SkippedStepResult.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\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; + } + + /** + * Returns definition search result. + * + * @return SearchResult + */ + public function getSearchResult() + { + return $this->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 000000000..0a898c996 --- /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 000000000..1268cb798 --- /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/IsolatingScenarioTester.php b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/IsolatingScenarioTester.php new file mode 100644 index 000000000..f526b7034 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/IsolatingScenarioTester.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\Tester\Runtime; + +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\Environment\EnvironmentManager; +use Behat\Testwork\Tester\Result\IntegerTestResult; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Result\TestWithSetupResult; +use Behat\Testwork\Tester\Setup\SuccessfulSetup; +use Behat\Testwork\Tester\Setup\SuccessfulTeardown; + +/** + * Scenario tester that isolates the environment for each scenario. + * + * @author Konstantin Kudryashov + */ +final class IsolatingScenarioTester implements ScenarioTester +{ + /** + * @var ScenarioTester + */ + private $decoratedTester; + /** + * @var EnvironmentManager + */ + private $envManager; + + /** + * Initialises tester. + * + * @param ScenarioTester $decoratedTester + * @param EnvironmentManager $envManager + */ + public function __construct(ScenarioTester $decoratedTester, EnvironmentManager $envManager) + { + $this->decoratedTester = $decoratedTester; + $this->envManager = $envManager; + } + + /** + * {@inheritdoc} + */ + public function setUp(Environment $env, FeatureNode $feature, Scenario $scenario, $skip) + { + return new SuccessfulSetup(); + } + + /** + * {@inheritdoc} + */ + public function test(Environment $env, FeatureNode $feature, Scenario $scenario, $skip) + { + $isolatedEnvironment = $this->envManager->isolateEnvironment($env, $scenario); + + $setup = $this->decoratedTester->setUp($isolatedEnvironment, $feature, $scenario, $skip); + $localSkip = !$setup->isSuccessful() || $skip; + $testResult = $this->decoratedTester->test($isolatedEnvironment, $feature, $scenario, $localSkip); + $teardown = $this->decoratedTester->tearDown($isolatedEnvironment, $feature, $scenario, $localSkip, $testResult); + + $integerResult = new IntegerTestResult($testResult->getResultCode()); + + return new TestWithSetupResult($setup, $integerResult, $teardown); + } + + /** + * {@inheritdoc} + */ + public function tearDown(Environment $env, FeatureNode $feature, Scenario $scenario, $skip, TestResult $result) + { + return new SuccessfulTeardown(); + } +} 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 000000000..72d5c9dbc --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeBackgroundTester.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\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\IntegerTestResult; +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); + } + + if (!$background->hasSteps()) { + return new IntegerTestResult(TestResult::PASSED); + } + + $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 000000000..dcafc7ef2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/Runtime/RuntimeFeatureTester.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\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 + * + * TODO: Remove EnvironmentManager parameter in next major + */ + 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) { + $tester = $scenario instanceof OutlineNode ? $this->outlineTester : $this->scenarioTester; + + $setup = $tester->setUp($env, $feature, $scenario, $skip); + $localSkip = !$setup->isSuccessful() || $skip; + $testResult = $tester->test($env, $feature, $scenario, $localSkip); + $teardown = $tester->tearDown($env, $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 000000000..1c1c38b2c --- /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 000000000..7ab11a0be --- /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 000000000..7031eeca7 --- /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 000000000..2fd249489 --- /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 000000000..394ee9317 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Tester/ServiceContainer/TesterExtension.php @@ -0,0 +1,315 @@ + + * + * 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); + + // Proper isolation for scenarios + $definition = new Definition('Behat\Behat\Tester\Runtime\IsolatingScenarioTester', array( + new Reference(self::SCENARIO_TESTER_ID), + new Reference(EnvironmentExtension::MANAGER_ID) + ) + ); + $definition->addTag(self::SCENARIO_TESTER_WRAPPER_TAG, array('priority' => -999999)); + $container->setDefinition(self::SCENARIO_TESTER_WRAPPER_TAG . '.isolating', $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); + + // Proper isolation for examples + $definition = new Definition('Behat\Behat\Tester\Runtime\IsolatingScenarioTester', array( + new Reference(self::EXAMPLE_TESTER_ID), + new Reference(EnvironmentExtension::MANAGER_ID) + ) + ); + $definition->addTag(self::EXAMPLE_TESTER_WRAPPER_TAG, array('priority' => -999999)); + $container->setDefinition(self::EXAMPLE_TESTER_WRAPPER_TAG . '.isolating', $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, + $container->getParameter('paths.base') + )); + $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 000000000..543e133d2 --- /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 000000000..d5c995ceb --- /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 000000000..d6cde918d --- /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 000000000..5a5195553 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Call/RuntimeTransformation.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\Transformation\Call; + +use Behat\Behat\Transformation\Transformation; +use Behat\Testwork\Call\RuntimeCallee; + +/** + * Transformation that is created and executed in the runtime. + * + * @deprecated Will be removed in 4.0. Use specific transformations instead + * + * @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 000000000..8b57d0bfa --- /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 000000000..a32ac5cca --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Context/Annotation/TransformationAnnotationReader.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\Transformation\Context\Annotation; + +use Behat\Behat\Context\Annotation\AnnotationReader; +use Behat\Behat\Transformation\Transformation\PatternTransformation; +use Behat\Behat\Transformation\Transformation; +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|Transformation + */ + 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()); + + foreach ($this->simpleTransformations() as $transformation) { + if ($transformation::supportsPatternAndMethod($pattern, $method)) { + return new $transformation($pattern, $callable, $description); + } + } + + return new PatternTransformation($pattern, $callable, $description); + } + + /** + * Returns list of default transformations. + * + * @return array + */ + private function simpleTransformations() + { + $transformations = array(); + $transformations[] = 'Behat\Behat\Transformation\Transformation\RowBasedTableTransformation'; + $transformations[] = 'Behat\Behat\Transformation\Transformation\ColumnBasedTableTransformation'; + $transformations[] = 'Behat\Behat\Transformation\Transformation\TableRowTransformation'; + + if (PHP_VERSION_ID >= 70000) { + $transformations[] = 'Behat\Behat\Transformation\Transformation\TokenNameAndReturnTypeTransformation'; + $transformations[] = 'Behat\Behat\Transformation\Transformation\ReturnTypeTransformation'; + } + + $transformations[] = 'Behat\Behat\Transformation\Transformation\TokenNameTransformation'; + + return $transformations; + } +} 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 000000000..f5aef3e28 --- /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 000000000..40d0ab22d --- /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/RegexGenerator.php b/vendor/behat/behat/src/Behat/Behat/Transformation/RegexGenerator.php new file mode 100644 index 000000000..4a7000e4d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/RegexGenerator.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\Transformation; + +/** + * Regular expression generator. + * + * @author Konstantin Kudryashov + */ +interface RegexGenerator +{ + /** + * Generates regular expression using provided parameters. + * + * @param string $suiteName + * @param string $pattern + * @param string $language + * + * @return string + */ + public function generateRegex($suiteName, $pattern, $language); +} 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 000000000..f322ee926 --- /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/SimpleArgumentTransformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/SimpleArgumentTransformation.php new file mode 100644 index 000000000..77cdeefb2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/SimpleArgumentTransformation.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\Transformation; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Testwork\Call\CallCenter; +use ReflectionMethod; + +/** + * Represents a simple self-contained transformation capable of changing a single argument. + * + * @author Konstantin Kudryashov + */ +interface SimpleArgumentTransformation extends Transformation +{ + /** + * Checks if transformation supports given pattern. + * + * @param string $pattern + * @param ReflectionMethod $method + * + * @return bool + */ + static public function supportsPatternAndMethod($pattern, ReflectionMethod $method); + + /** + * Returns transformation priority. + * + * @return integer + */ + public function getPriority(); + + /** + * Checks if transformation 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 CallCenter $callCenter + * @param DefinitionCall $definitionCall + * @param integer|string $argumentIndex + * @param mixed $argumentValue + * + * @return mixed + */ + public function transformArgument(CallCenter $callCenter, DefinitionCall $definitionCall, $argumentIndex, $argumentValue); +} 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 000000000..e82190c20 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation.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\Transformation; + +use Behat\Testwork\Call\Callee; + +/** + * Step transformation interface. + * + * @author Konstantin Kudryashov + */ +interface Transformation extends Callee +{ + /** + * Returns transformation pattern exactly as it was defined. + * + * @deprecated Will be removed in 4.0. + * + * @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/Transformation/ColumnBasedTableTransformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/ColumnBasedTableTransformation.php new file mode 100644 index 000000000..1c8cc0ec3 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/ColumnBasedTableTransformation.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\Behat\Transformation\Transformation; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Transformation\Call\TransformationCall; +use Behat\Behat\Transformation\SimpleArgumentTransformation; +use Behat\Gherkin\Node\TableNode; +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\RuntimeCallee; +use ReflectionMethod; + +/** + * Column-based table transformation. + * + * @author Konstantin Kudryashov + */ +final class ColumnBasedTableTransformation extends RuntimeCallee implements SimpleArgumentTransformation +{ + const PATTERN_REGEX = '/^table\:(?:\*|[[:print:]]+)$/'; + + /** + * @var string + */ + private $pattern; + + /** + * {@inheritdoc} + */ + static public function supportsPatternAndMethod($pattern, ReflectionMethod $method) + { + return 1 === preg_match(self::PATTERN_REGEX, $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 supportsDefinitionAndArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + if (!$argumentValue instanceof TableNode) { + return false; + }; + + return $this->pattern === 'table:' . implode(',', $argumentValue->getRow(0)) + || $this->pattern === 'table:*'; + } + + /** + * {@inheritdoc} + */ + public function transformArgument(CallCenter $callCenter, DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + $call = new TransformationCall( + $definitionCall->getEnvironment(), + $definitionCall->getCallee(), + $this, + array($argumentValue) + ); + + $result = $callCenter->makeCall($call); + + if ($result->hasException()) { + throw $result->getException(); + } + + return $result->getReturn(); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 50; + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return 'ColumnTableTransform ' . $this->pattern; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/PatternTransformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/PatternTransformation.php new file mode 100644 index 000000000..505490151 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/PatternTransformation.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\Transformation\Transformation; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Transformation\Call\TransformationCall; +use Behat\Behat\Transformation\RegexGenerator; +use Behat\Behat\Transformation\Transformation; +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\RuntimeCallee; +use Exception; + +/** + * Pattern-based transformation. + * + * @author Konstantin Kudryashov + */ +final class PatternTransformation 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); + } + + /** + * Checks if transformer supports argument. + * + * @param RegexGenerator $regexGenerator + * @param DefinitionCall $definitionCall + * @param mixed $argumentValue + * + * @return bool + */ + public function supportsDefinitionAndArgument( + RegexGenerator $regexGenerator, + DefinitionCall $definitionCall, + $argumentValue + ) { + $regex = $regexGenerator->generateRegex( + $definitionCall->getEnvironment()->getSuite()->getName(), + $this->pattern, + $definitionCall->getFeature()->getLanguage() + ); + + return $this->match($regex, $argumentValue, $match); + } + + /** + * Transforms argument value using transformation and returns a new one. + * + * @param RegexGenerator $regexGenerator + * @param CallCenter $callCenter + * @param DefinitionCall $definitionCall + * @param mixed $argumentValue + * + * @return mixed + * + * @throws Exception If transformation throws exception + */ + public function transformArgument( + RegexGenerator $regexGenerator, + CallCenter $callCenter, + DefinitionCall $definitionCall, + $argumentValue + ) { + $regex = $regexGenerator->generateRegex( + $definitionCall->getEnvironment()->getSuite()->getName(), + $this->pattern, + $definitionCall->getFeature()->getLanguage() + ); + + $this->match($regex, $argumentValue, $arguments); + + $call = new TransformationCall( + $definitionCall->getEnvironment(), + $definitionCall->getCallee(), + $this, + $arguments + ); + + $result = $callCenter->makeCall($call); + + if ($result->hasException()) { + throw $result->getException(); + } + + return $result->getReturn(); + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return 'PatternTransform ' . $this->pattern; + } + + /** + * @param $regexPattern + * @param $argumentValue + * @param $match + * + * @return bool + */ + private function match($regexPattern, $argumentValue, &$match) + { + if (is_string($argumentValue) && preg_match($regexPattern, $argumentValue, $match)) { + // take arguments from capture groups if there are some + if (count($match) > 1) { + $match = array_slice($match, 1); + } + + return true; + } + + return false; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/ReturnTypeTransformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/ReturnTypeTransformation.php new file mode 100644 index 000000000..ecdc613a1 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/ReturnTypeTransformation.php @@ -0,0 +1,218 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Behat\Transformation\Transformation; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Transformation\Call\TransformationCall; +use Behat\Behat\Transformation\SimpleArgumentTransformation; +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\RuntimeCallee; +use Closure; +use ReflectionFunctionAbstract; +use ReflectionMethod; +use ReflectionParameter; + +/** + * By-type object transformation. + * + * @author Konstantin Kudryashov + */ +final class ReturnTypeTransformation extends RuntimeCallee implements SimpleArgumentTransformation +{ + + /** + * {@inheritdoc} + */ + static public function supportsPatternAndMethod($pattern, ReflectionMethod $method) + { + $returnClass = self::getReturnClass($method); + + if (null === $returnClass) { + return false; + } + + return '' === $pattern; + } + + /** + * Initializes transformation. + * + * @param string $pattern + * @param callable $callable + * @param null|string $description + */ + public function __construct($pattern, $callable, $description = null) + { + parent::__construct($callable, $description); + } + + /** + * {@inheritdoc} + */ + public function supportsDefinitionAndArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + $returnClass = self::getReturnClass($this->getReflection()); + + if (null === $returnClass) { + return false; + } + + $parameterClass = $this->getParameterClassNameByIndex($definitionCall, $argumentIndex); + + return $parameterClass === $returnClass; + } + + /** + * {@inheritdoc} + */ + public function transformArgument(CallCenter $callCenter, DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + $call = new TransformationCall( + $definitionCall->getEnvironment(), + $definitionCall->getCallee(), + $this, + array($argumentValue) + ); + + $result = $callCenter->makeCall($call); + + if ($result->hasException()) { + throw $result->getException(); + } + + return $result->getReturn(); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 80; + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return null; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return 'ReturnTypeTransform'; + } + + /** + * Extracts parameters from provided definition call. + * + * @param ReflectionFunctionAbstract $reflection + * + * @return null|string + */ + static private function getReturnClass(ReflectionFunctionAbstract $reflection) + { + $type = $reflection->getReturnType(); + + if (null === $type || $type->isBuiltin()) { + return null; + } + + return (string) $type; + } + + /** + * Attempts to get definition parameter using its index (parameter position or name). + * + * @param DefinitionCall $definitionCall + * @param string|integer $argumentIndex + * + * @return null|string + */ + private function getParameterClassNameByIndex(DefinitionCall $definitionCall, $argumentIndex) + { + $parameters = array_filter( + array_filter($this->getCallParameters($definitionCall), + $this->hasIndex($argumentIndex) + ), + $this->isClass() + ); + return count($parameters) ? current($parameters)->getClass()->getName() : null; + } + + /** + * Extracts parameters from provided definition call. + * + * @param DefinitionCall $definitionCall + * + * @return ReflectionParameter[] + */ + private function getCallParameters(DefinitionCall $definitionCall) + { + return $definitionCall->getCallee()->getReflection()->getParameters(); + } + + /** + * Returns appropriate closure for filtering parameter by index. + * + * @param string|integer $index + * + * @return Closure + */ + private function hasIndex($index) + { + return is_string($index) ? $this->hasName($index) : $this->hasPosition($index); + } + + /** + * Returns closure to filter parameter by name. + * + * @param string $index + * + * @return Closure + */ + private function hasName($index) + { + return function (ReflectionParameter $parameter) use ($index) { + return $index === $parameter->getName(); + }; + } + + /** + * Returns closure to filter parameter by position. + * + * @param integer $index + * + * @return Closure + */ + private function hasPosition($index) + { + return function (ReflectionParameter $parameter) use ($index) { + return $index === $parameter->getPosition(); + }; + } + + /** + * Returns closure to filter parameter by typehinted class. + * + * @return Closure + */ + private function isClass() + { + return function (ReflectionParameter $parameter) { + return $parameter->getClass(); + }; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/RowBasedTableTransformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/RowBasedTableTransformation.php new file mode 100644 index 000000000..61389834d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/RowBasedTableTransformation.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\Transformation\Transformation; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Transformation\Call\TransformationCall; +use Behat\Behat\Transformation\SimpleArgumentTransformation; +use Behat\Gherkin\Exception\NodeException; +use Behat\Gherkin\Node\TableNode; +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\RuntimeCallee; +use ReflectionMethod; + +/** + * Row-based table transformation. + * + * @author Konstantin Kudryashov + */ +final class RowBasedTableTransformation extends RuntimeCallee implements SimpleArgumentTransformation +{ + const PATTERN_REGEX = '/^rowtable\:[[:print:]]+$/'; + + /** + * @var string + */ + private $pattern; + + /** + * {@inheritdoc} + */ + static public function supportsPatternAndMethod($pattern, ReflectionMethod $method) + { + return 1 === preg_match(self::PATTERN_REGEX, $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 supportsDefinitionAndArgument(DefinitionCall $definitionCall, $argumentIndex, $value) + { + if (!$value instanceof TableNode) { + return false; + }; + + // What we're doing here is checking that we have a 2 column table. + // This bit checks we have two columns + try { + $value->getColumn(1); + } catch (NodeException $e) { + return false; + } + + // And here we check we don't have a 3rd column + try { + $value->getColumn(2); + } catch (NodeException $e) { + // Once we know the table could be a row table, we check against the pattern. + return $this->pattern === 'rowtable:' . implode(',', $value->getColumn(0)); + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function transformArgument(CallCenter $callCenter, DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + $call = new TransformationCall( + $definitionCall->getEnvironment(), + $definitionCall->getCallee(), + $this, + array($argumentValue) + ); + + $result = $callCenter->makeCall($call); + + if ($result->hasException()) { + throw $result->getException(); + } + + return $result->getReturn(); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 50; + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return 'RowTableTransform ' . $this->pattern; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/TableRowTransformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/TableRowTransformation.php new file mode 100644 index 000000000..571f1f0cd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/TableRowTransformation.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\Transformation\Transformation; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Transformation\Call\TransformationCall; +use Behat\Behat\Transformation\SimpleArgumentTransformation; +use Behat\Gherkin\Node\TableNode; +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\RuntimeCallee; +use ReflectionMethod; + +/** + * Table row transformation. + * + * @author Konstantin Kudryashov + */ +final class TableRowTransformation extends RuntimeCallee implements SimpleArgumentTransformation +{ + const PATTERN_REGEX = '/^row\:[[:print:]]+$/'; + + /** + * @var string + */ + private $pattern; + + /** + * {@inheritdoc} + */ + static public function supportsPatternAndMethod($pattern, ReflectionMethod $method) + { + return 1 === preg_match(self::PATTERN_REGEX, $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 supportsDefinitionAndArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + if (!$argumentValue instanceof TableNode) { + return false; + }; + + return $this->pattern === 'row:' . implode(',', $argumentValue->getRow(0)); + } + + /** + * {@inheritdoc} + */ + public function transformArgument(CallCenter $callCenter, DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + $rows = array(); + foreach ($argumentValue as $row) { + $call = new TransformationCall( + $definitionCall->getEnvironment(), + $definitionCall->getCallee(), + $this, + array($row) + ); + + $result = $callCenter->makeCall($call); + + if ($result->hasException()) { + throw $result->getException(); + } + + $rows[] = $result->getReturn(); + } + + return $rows; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 50; + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return 'TableRowTransform ' . $this->pattern; + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/TokenNameAndReturnTypeTransformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/TokenNameAndReturnTypeTransformation.php new file mode 100644 index 000000000..32f954d65 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/TokenNameAndReturnTypeTransformation.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\Transformation\Transformation; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Transformation\Call\TransformationCall; +use Behat\Behat\Transformation\SimpleArgumentTransformation; +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\RuntimeCallee; +use ReflectionMethod; + +/** + * Name and return type object transformation. + * + * @author Konstantin Kudryashov + */ +final class TokenNameAndReturnTypeTransformation extends RuntimeCallee implements SimpleArgumentTransformation +{ + /** + * @var TokenNameTransformation + */ + private $tokenTransformation; + /** + * @var ReturnTypeTransformation + */ + private $returnTransformation; + + /** + * {@inheritdoc} + */ + static public function supportsPatternAndMethod($pattern, ReflectionMethod $method) + { + return TokenNameTransformation::supportsPatternAndMethod($pattern, $method) + && ReturnTypeTransformation::supportsPatternAndMethod('', $method); + } + + /** + * Initializes transformation. + * + * @param string $pattern + * @param callable $callable + * @param null|string $description + */ + public function __construct($pattern, $callable, $description = null) + { + $this->tokenTransformation = new TokenNameTransformation($pattern, $callable, $description); + $this->returnTransformation = new ReturnTypeTransformation('', $callable, $description); + + parent::__construct($callable, $description); + } + + /** + * {@inheritdoc} + */ + public function supportsDefinitionAndArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + return $this->tokenTransformation->supportsDefinitionAndArgument($definitionCall, $argumentIndex, $argumentValue) + && $this->returnTransformation->supportsDefinitionAndArgument($definitionCall, $argumentIndex, $argumentValue); + } + + /** + * {@inheritdoc} + */ + public function transformArgument(CallCenter $callCenter, DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + $call = new TransformationCall( + $definitionCall->getEnvironment(), + $definitionCall->getCallee(), + $this, + array($argumentValue) + ); + + $result = $callCenter->makeCall($call); + + if ($result->hasException()) { + throw $result->getException(); + } + + return $result->getReturn(); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 100; + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return $this->tokenTransformation->getPattern(); + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return 'NamedReturnTypeTransform ' . $this->getPattern(); + } +} diff --git a/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/TokenNameTransformation.php b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/TokenNameTransformation.php new file mode 100644 index 000000000..cd4f4ab0b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformation/TokenNameTransformation.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\Transformation\Transformation; + +use Behat\Behat\Definition\Call\DefinitionCall; +use Behat\Behat\Transformation\Call\TransformationCall; +use Behat\Behat\Transformation\SimpleArgumentTransformation; +use Behat\Testwork\Call\CallCenter; +use Behat\Testwork\Call\RuntimeCallee; +use ReflectionMethod; + +/** + * Token name based transformation. + * + * @author Konstantin Kudryashov + */ +final class TokenNameTransformation extends RuntimeCallee implements SimpleArgumentTransformation +{ + const PATTERN_REGEX = '/^\:\w+$/'; + + /** + * @var string + */ + private $pattern; + + + /** + * {@inheritdoc} + */ + static public function supportsPatternAndMethod($pattern, ReflectionMethod $method) + { + return 1 === preg_match(self::PATTERN_REGEX, $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 supportsDefinitionAndArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + return ':' . $argumentIndex === $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function transformArgument(CallCenter $callCenter, DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + $call = new TransformationCall( + $definitionCall->getEnvironment(), + $definitionCall->getCallee(), + $this, + array($argumentValue) + ); + + $result = $callCenter->makeCall($call); + + if ($result->hasException()) { + throw $result->getException(); + } + + return $result->getReturn(); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 50; + } + + /** + * {@inheritdoc} + */ + public function getPattern() + { + return $this->pattern; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return 'TokenNameTransform ' . $this->pattern; + } +} 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 000000000..2fb0ff567 --- /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 000000000..4773960e0 --- /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 000000000..795f42fae --- /dev/null +++ b/vendor/behat/behat/src/Behat/Behat/Transformation/Transformer/RepositoryArgumentTransformer.php @@ -0,0 +1,198 @@ + + * + * 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\SimpleArgumentTransformation; +use Behat\Behat\Transformation\Transformation\PatternTransformation; +use Behat\Behat\Transformation\RegexGenerator; +use Behat\Behat\Transformation\Transformation; +use Behat\Behat\Transformation\TransformationRepository; +use Behat\Gherkin\Node\ArgumentInterface; +use Behat\Testwork\Call\CallCenter; +use Symfony\Component\Translation\TranslatorInterface; + +/** + * Argument transformer based on transformations repository. + * + * @author Konstantin Kudryashov + */ +final class RepositoryArgumentTransformer implements ArgumentTransformer, RegexGenerator +{ + /** + * @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 count($this->repository->getEnvironmentTransformations($definitionCall->getEnvironment())) > 0; + } + + /** + * {@inheritdoc} + */ + public function transformArgument(DefinitionCall $definitionCall, $argumentIndex, $argumentValue) + { + $environment = $definitionCall->getEnvironment(); + list($simpleTransformations, $normalTransformations) = $this->splitSimpleAndNormalTransformations( + $this->repository->getEnvironmentTransformations($environment) + ); + + $newValue = $this->applySimpleTransformations($simpleTransformations, $definitionCall, $argumentIndex, $argumentValue); + $newValue = $this->applyNormalTransformations($normalTransformations, $definitionCall, $argumentIndex, $newValue); + + return $newValue; + } + + /** + * {@inheritdoc} + */ + public function generateRegex($suiteName, $pattern, $language) + { + $translatedPattern = $this->translator->trans($pattern, array(), $suiteName, $language); + if ($pattern == $translatedPattern) { + return $this->patternTransformer->transformPatternToRegex($pattern); + } + + return $this->patternTransformer->transformPatternToRegex($translatedPattern); + } + + /** + * Apply simple argument transformations in priority order. + * + * @param SimpleArgumentTransformation[] $transformations + * @param DefinitionCall $definitionCall + * @param integer|string $index + * @param mixed $value + * + * @return mixed + */ + private function applySimpleTransformations(array $transformations, DefinitionCall $definitionCall, $index, $value) + { + usort($transformations, function (SimpleArgumentTransformation $t1, SimpleArgumentTransformation $t2) { + if ($t1->getPriority() == $t2->getPriority()) { + return 0; + } + + return ($t1->getPriority() > $t2->getPriority()) ? -1 : 1; + }); + + $newValue = $value; + foreach ($transformations as $transformation) { + $newValue = $this->transform($definitionCall, $transformation, $index, $newValue); + } + + return $newValue; + } + + /** + * Apply normal (non-simple) argument transformations. + * + * @param Transformation[] $transformations + * @param DefinitionCall $definitionCall + * @param integer|string $index + * @param mixed $value + * + * @return mixed + */ + private function applyNormalTransformations(array $transformations, DefinitionCall $definitionCall, $index, $value) + { + $newValue = $value; + foreach ($transformations as $transformation) { + $newValue = $this->transform($definitionCall, $transformation, $index, $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 ($transformation instanceof SimpleArgumentTransformation && + $transformation->supportsDefinitionAndArgument($definitionCall, $index, $value)) { + return $transformation->transformArgument($this->callCenter, $definitionCall, $index, $value); + } + + if ($transformation instanceof PatternTransformation && + $transformation->supportsDefinitionAndArgument($this, $definitionCall, $value)) { + return $transformation->transformArgument($this, $this->callCenter, $definitionCall, $value); + } + + return $value; + } + + /** + * Splits transformations into simple and normal ones. + * + * @param Transformation[] $transformations + * + * @return array + */ + private function splitSimpleAndNormalTransformations(array $transformations) + { + return array_reduce($transformations, function ($acc, $t) { + return array( + $t instanceof SimpleArgumentTransformation ? array_merge($acc[0], array($t)) : $acc[0], + !$t instanceof SimpleArgumentTransformation ? array_merge($acc[1], array($t)) : $acc[1], + ); + }, array(array(), array())); + } +} 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 000000000..439ad0968 --- /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 000000000..f4af2a5ba --- /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 000000000..ff604041b --- /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 000000000..865963195 --- /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 000000000..5ab612713 --- /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 000000000..fdcf310d5 --- /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 000000000..b83958bb2 --- /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 000000000..688c9393b --- /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 000000000..bc116ddd2 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/MixedArgumentOrganiser.php @@ -0,0 +1,429 @@ + + * + * 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; +use ReflectionClass; +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) + { + return $this->prepareArguments($function->getParameters(), $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) + + $this->prepareTypehintedArguments($parameters, $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 ($this->isParameterTypehintedInArgumentList($parameters, $val)) { + $typehintedArguments[] = $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); + } + + /** + * Check if a given value is typehinted in the argument list. + * + * @param ReflectionParameter[] $parameters + * @param mixed $value + * + * @return Boolean + */ + private function isParameterTypehintedInArgumentList(array $parameters, $value) + { + if (!is_object($value)) { + return false; + } + + foreach ($parameters as $parameter) { + if ($this->isValueMatchesTypehintedParameter($value, $parameter)) { + return true; + } + } + + return false; + } + + /** + * 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 typehinted arguments based on the given candidates. + * + * This method attempts to match up the best fitting arguments to each constructor argument. + * + * This case specifically fixes the issue where a constructor asks for a parent and child class, + * as separate arguments, but both arguments could satisfy the first argument, + * so they would both be passed in (overwriting each other). + * + * This will ensure that the children (exact class matches) are mapped first, and then other dependencies + * are mapped sequentially (to arguments which they are an `instanceof`). + * + * As such, this requires two passes of the $parameters array to ensure it is mapped as accurately as possible. + * + * @param ReflectionParameter[] $parameters Reflection Parameters (constructor argument requirements) + * @param mixed[] $typehintedArguments Resolved arguments + * + * @return mixed[] Ordered list of arguments, index is the constructor argument position, value is what will be injected + */ + private function prepareTypehintedArguments(array $parameters, array $typehintedArguments) + { + $arguments = array(); + + $candidates = $typehintedArguments; + + $this->applyPredicateToTypehintedArguments( + $parameters, + $candidates, + $arguments, + array($this, 'classMatchingPredicateForTypehintedArguments') + ); + + // This iteration maps up everything else, providing the argument is an instanceof the parameter. + $this->applyPredicateToTypehintedArguments( + $parameters, + $candidates, + $arguments, + array($this, 'isInstancePredicateForTypehintedArguments') + ); + + return $arguments; + } + + /** + * Filtered out superfluous parameters for matching up typehinted arguments. + * + * @param ReflectionParameter[] $parameters Constructor Arguments + * @return ReflectionParameter[] Filtered $parameters + */ + private function filterApplicableTypehintedParameters(array $parameters) + { + $filtered = array(); + + foreach ($parameters as $num => $parameter) { + if ($this->isArgumentDefined($num)) { + continue; + } + + $reflectionClass = $parameter->getClass(); + + if (!$reflectionClass) { + continue; + } + + $filtered[$num] = $parameter; + } + + return $filtered; + } + + /** + * Applies a predicate for each candidate when matching up typehinted arguments. + * This passes through to another loop of the candidates in @matchParameterToCandidateUsingPredicate, + * because this method is "too complex" with two loops... + * + * @param ReflectionParameter[] $parameters Reflection Parameters (constructor argument requirements) + * @param mixed[] &$candidates Resolved arguments + * @param mixed[] &$arguments Argument mapping + * @param callable $predicate Callable predicate to apply to each candidate + * @return void + */ + private function applyPredicateToTypehintedArguments( + array $parameters, + array &$candidates, + array &$arguments, + callable $predicate + ) { + $filtered = $this->filterApplicableTypehintedParameters($parameters); + + foreach ($filtered as $num => $parameter) { + $this->matchParameterToCandidateUsingPredicate($parameter, $candidates, $arguments, $predicate); + } + } + + /** + * Applies a predicate for each candidate when matching up typehinted arguments. + * This helps to avoid repetition when looping them, as multiple passes are needed over the parameters / candidates. + * + * @param ReflectionParameter $parameter Reflection Parameter (constructor argument requirements) + * @param mixed[] &$candidates Resolved arguments + * @param mixed[] &$arguments Argument mapping + * @param callable $predicate Callable predicate to apply to each candidate + * @return boolean Returns true if a candidate has been matched to the given parameter, otherwise false + */ + public function matchParameterToCandidateUsingPredicate( + ReflectionParameter $parameter, + array &$candidates, + array &$arguments, + callable $predicate + ) { + foreach ($candidates as $candidateIndex => $candidate) { + if (call_user_func_array($predicate, array($parameter->getClass(), $candidate))) { + $num = $parameter->getPosition(); + + $arguments[$num] = $candidate; + + $this->markArgumentDefined($num); + + unset($candidates[$candidateIndex]); + + return true; + } + } + + return false; + } + + /** + * Typehinted argument predicate to check if the argument and parameter classes match equally. + * + * @param ReflectionClass $reflectionClass Typehinted argument + * @param mixed $candidate Resolved argument + * @return boolean + */ + private function classMatchingPredicateForTypehintedArguments(ReflectionClass $reflectionClass, $candidate) + { + return $reflectionClass->getName() === get_class($candidate); + } + + /** + * Typehinted argument predicate to check if the argument is an instance of the parameter. + * + * @param ReflectionClass $reflectionClass Typehinted argument + * @param mixed $candidate Resolved argument + * @return boolean + */ + private function isInstancePredicateForTypehintedArguments(ReflectionClass $reflectionClass, $candidate) + { + return $reflectionClass->isInstance($candidate); + } + + /** + * 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; + } + + /** + * 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 000000000..2fb053585 --- /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 000000000..9aa5afeff --- /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 organisers for 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/Argument/Validator.php b/vendor/behat/behat/src/Behat/Testwork/Argument/Validator.php new file mode 100644 index 000000000..3d47e7e5a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Argument/Validator.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\Argument; + +use Behat\Testwork\Argument\Exception\UnknownParameterValueException; +use ReflectionFunctionAbstract; +use ReflectionMethod; +use ReflectionParameter; + +/** + * Validates function arguments. + * + * @author Konstantin Kudryashov + */ +final class Validator +{ + /** + * Validates that all arguments are in place, throws exception otherwise. + * + * @param ReflectionFunctionAbstract $function + * @param mixed[] $arguments + * + * @throws UnknownParameterValueException + */ + public function validateArguments(ReflectionFunctionAbstract $function, array $arguments) + { + foreach ($function->getParameters() as $num => $parameter) { + $this->validateArgument($parameter, $num, $arguments); + } + } + + /** + * Validates given argument. + * + * @param ReflectionParameter $parameter + * @param integer $parameterIndex + * @param array $givenArguments + */ + private function validateArgument(ReflectionParameter $parameter, $parameterIndex, array $givenArguments) + { + if ($parameter->isDefaultValueAvailable()) { + return; + } + + if (array_key_exists($parameterIndex, $givenArguments)) { + return; + } + + if (array_key_exists($parameter->getName(), $givenArguments)) { + return; + } + + throw new UnknownParameterValueException(sprintf( + 'Can not find a matching value for an argument `$%s` of the method `%s`.', + $parameter->getName(), + $this->getFunctionPath($parameter->getDeclaringFunction()) + )); + } + + /** + * 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()); + } +} 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 000000000..991eb412c --- /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 000000000..2c5f021cd --- /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 000000000..efa04de2a --- /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 000000000..448367b2d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/CallCenter.php @@ -0,0 +1,192 @@ + + * + * 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\Exception\FatalThrowableError; +use Behat\Testwork\Call\Filter\CallFilter; +use Behat\Testwork\Call\Filter\ResultFilter; +use Behat\Testwork\Call\Handler\CallHandler; +use Behat\Testwork\Call\Handler\ExceptionHandler; +use Exception; +use Throwable; + +/** + * 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(); + /** + * @var ExceptionHandler[] + */ + private $exceptionHandlers = 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; + } + + /** + * Registers result exception handler. + * + * @param ExceptionHandler $handler + */ + public function registerExceptionHandler(ExceptionHandler $handler) + { + $this->exceptionHandlers[] = $handler; + } + + /** + * Handles call and its result using registered filters and handlers. + * + * @param Call $call + * + * @return CallResult + */ + public function makeCall(Call $call) + { + try { + return $this->filterResult($this->handleCall($this->filterCall($call))); + } catch (Exception $exception) { + return new CallResult($call, null, $this->handleException($exception), null); + } catch (Throwable $exception) { + return new CallResult($call, null, $this->handleException($exception), null); + } + } + + /** + * 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; + } + + $call = $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; + } + + $result = $filter->filterResult($result); + } + + return $result; + } + + /** + * Handles exception using registered handlers and returns a handled one. + * + * @param Throwable $exception + * + * @return Throwable + */ + private function handleException($exception) + { + foreach ($this->exceptionHandlers as $handler) { + if (!$handler->supportsException($exception)) { + continue; + } + + $exception = $handler->handleException($exception); + } + + if ($exception instanceof Throwable) { + return new FatalThrowableError($exception); + } + + return $exception; + } +} 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 000000000..ca3c52837 --- /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 000000000..f79ea0c9e --- /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 000000000..c03e77649 --- /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 000000000..de56b4e07 --- /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 000000000..423abf38f --- /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 000000000..1e3db9758 --- /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 000000000..f8e670e88 --- /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/Exception/FatalThrowableError.php b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/FatalThrowableError.php new file mode 100644 index 000000000..52958b9cd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Exception/FatalThrowableError.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\Call\Exception; + +use ErrorException; +use ParseError; +use Throwable; +use TypeError; + +/** + * Fatal Throwable Error. + * + * @author Nicolas Grekas + */ +class FatalThrowableError extends ErrorException +{ + public function __construct(Throwable $e) + { + if ($e instanceof ParseError) { + $message = 'Parse error: '.$e->getMessage(); + $severity = E_PARSE; + } elseif ($e instanceof TypeError) { + $message = 'Type error: '.$e->getMessage(); + $severity = E_RECOVERABLE_ERROR; + } else { + $message = 'Fatal error: '.$e->getMessage(); + $severity = E_ERROR; + } + + parent::__construct( + $message, + $e->getCode(), + $severity, + $e->getFile(), + $e->getLine() + ); + + $this->setTrace($e->getTrace()); + } + + private function setTrace($trace) + { + $traceReflector = new \ReflectionProperty('Exception', 'trace'); + $traceReflector->setAccessible(true); + $traceReflector->setValue($this, $trace); + } +} 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 000000000..5426c160a --- /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 000000000..ac3ebe000 --- /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 000000000..e553d2a76 --- /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/Exception/ClassNotFoundHandler.php b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/Exception/ClassNotFoundHandler.php new file mode 100644 index 000000000..8d0f488fd --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/Exception/ClassNotFoundHandler.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\Testwork\Call\Handler\Exception; + +use Behat\Testwork\Call\Handler\ExceptionHandler; +use Error; + +/** + * Handles class not found exceptions. + * + * @see ExceptionHandler + * + * @author Konstantin Kudryashov + */ +abstract class ClassNotFoundHandler implements ExceptionHandler +{ + const PATTERN = "/^Class '([^']+)' not found$/"; + + /** + * {@inheritdoc} + */ + final public function supportsException($exception) + { + if (!$exception instanceof Error) { + return false; + } + + return null !== $this->extractNonExistentClass($exception); + } + + /** + * {@inheritdoc} + */ + final public function handleException($exception) + { + $this->handleNonExistentClass($this->extractNonExistentClass($exception)); + + return $exception; + } + + /** + * Override to handle non-existent class name. + * + * @param string $class + */ + abstract public function handleNonExistentClass($class); + + /** + * Extracts missing class name from the exception. + * + * @param Error $exception + * + * @return null|string + */ + private function extractNonExistentClass(Error $exception) + { + if (1 === preg_match(self::PATTERN, $exception->getMessage(), $matches)) { + return $matches[1]; + } + + return null; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Handler/Exception/MethodNotFoundHandler.php b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/Exception/MethodNotFoundHandler.php new file mode 100644 index 000000000..3ca680dae --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/Exception/MethodNotFoundHandler.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\Testwork\Call\Handler\Exception; + +use Behat\Testwork\Call\Handler\ExceptionHandler; +use Error; + +/** + * Handles method not found exceptions. + * + * @see ExceptionHandler + * + * @author Konstantin Kudryashov + */ +abstract class MethodNotFoundHandler implements ExceptionHandler +{ + const PATTERN = '/^Call to undefined method ([^:]+)::([^\)]+)\(\)$/'; + + /** + * {@inheritdoc} + */ + final public function supportsException($exception) + { + if (!$exception instanceof Error) { + return false; + } + + return null !== $this->extractNonExistentCallable($exception); + } + + /** + * {@inheritdoc} + */ + final public function handleException($exception) + { + $this->handleNonExistentMethod($this->extractNonExistentCallable($exception)); + + return $exception; + } + + /** + * Override to handle non-existent method. + * + * @param array $callable + */ + abstract public function handleNonExistentMethod(array $callable); + + /** + * Extract callable from exception. + * + * @param Error $exception + * + * @return null|array + */ + private function extractNonExistentCallable(Error $exception) + { + if (1 === preg_match(self::PATTERN, $exception->getMessage(), $matches)) { + return array($matches[1], $matches[2]); + } + + return null; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Call/Handler/ExceptionHandler.php b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/ExceptionHandler.php new file mode 100644 index 000000000..53a35f73d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/ExceptionHandler.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\Call\Handler; + +/** + * Handles exceptions. + * + * @see CallCenter + * + * @author Konstantin Kudryashov + */ +interface ExceptionHandler +{ + /** + * Checks if handler supports exception. + * + * @param \Throwable $exception + * + * @return bool + */ + public function supportsException($exception); + + /** + * Handles exception and returns new one if necessary. + * + * @param \Throwable $exception + * + * @return \Throwable + */ + public function handleException($exception); +} 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 000000000..62b3d1d6d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/Handler/RuntimeCallHandler.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\Call\Handler; + +use Behat\Testwork\Argument\Validator; +use Behat\Testwork\Call\Call; +use Behat\Testwork\Call\CallResult; +use Behat\Testwork\Call\Exception\CallErrorException; +use Exception; + +/** + * Handles calls in the current runtime. + * + * @author Konstantin Kudryashov + */ +final class RuntimeCallHandler implements CallHandler +{ + /** + * @var integer + */ + private $errorReportingLevel; + /** + * @var bool + */ + private $obStarted = false; + /** + * @var Validator + */ + private $validator; + + /** + * Initializes executor. + * + * @param integer $errorReportingLevel + */ + public function __construct($errorReportingLevel = E_ALL) + { + $this->errorReportingLevel = $errorReportingLevel; + $this->validator = new Validator(); + } + + /** + * {@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 ($this->errorLevelIsNotReportable($level)) { + return false; + } + + throw new CallErrorException($level, $message, $file, $line); + } + + /** + * Executes single call. + * + * @param Call $call + * + * @return CallResult + */ + private function executeCall(Call $call) + { + $reflection = $call->getCallee()->getReflection(); + $callable = $call->getBoundCallable(); + $arguments = $call->getArguments(); + $return = $exception = null; + + try { + $this->validator->validateArguments($reflection, $arguments); + $return = call_user_func_array($callable, $arguments); + } catch (Exception $caught) { + $exception = $caught; + } + + $stdOut = $this->getBufferedStdOut(); + + return new CallResult($call, $return, $exception, $stdOut); + } + + /** + * 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); + $this->obStarted = ob_start(); + } + + /** + * Stops error handler and stdout buffering. + */ + private function stopErrorAndOutputBuffering() + { + if ($this->obStarted) { + ob_end_clean(); + } + restore_error_handler(); + } + + /** + * Checks if provided error level is not reportable. + * + * @param integer $level + * + * @return Boolean + */ + private function errorLevelIsNotReportable($level) + { + return !(error_reporting() & $level); + } +} 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 000000000..c764629d2 --- /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 000000000..b9df7ea22 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Call/ServiceContainer/CallExtension.php @@ -0,0 +1,189 @@ + + * + * 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'; + const EXCEPTION_HANDLER_TAG = 'call.exception_handler'; + + /** + * @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); + $this->processExceptionHandlers($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)); + } + } + + /** + * Registers all exception handlers to the CallCenter. + * + * @param ContainerBuilder $container + */ + private function processExceptionHandlers(ContainerBuilder $container) + { + $references = $this->processor->findAndSortTaggedServices($container, CallExtension::EXCEPTION_HANDLER_TAG); + $definition = $container->getDefinition(CallExtension::CALL_CENTER_ID); + + foreach ($references as $reference) { + $definition->addMethodCall('registerExceptionHandler', 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 000000000..4189224e0 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Cli/Application.php @@ -0,0 +1,236 @@ + + * + * 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\Exception\ConfigurationLoadingException; +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) + { + putenv('COLUMNS=9999'); + + $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_OPTIONAL, + 'Increase verbosity of exceptions.' . PHP_EOL . + 'Use -vv or --verbose=2 to display backtraces in addition to 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('--debug', null, InputOption::VALUE_NONE, 'Provide debugging information about current environment.'), + new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display 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) + { + // xdebug's default nesting level of 100 is not enough + if (extension_loaded('xdebug') + && false === strpos(ini_get('disable_functions'), 'ini_set') + ) { + $oldValue = ini_get('xdebug.max_nesting_level'); + if ($oldValue === false || $oldValue < 256) { + ini_set('xdebug.max_nesting_level', 256); + } + } + + if ($input->hasParameterOption(array('--config-reference'))) { + $input = new ArrayInput(array('--config-reference' => true)); + } + + if ($path = $input->getParameterOption(array('--config', '-c'))) { + if (!is_file($path)) { + throw new ConfigurationLoadingException("The requested config file does not exist"); + } + + $this->configurationLoader->setConfigurationFilePath($path); + } + + $this->add($this->createCommand($input, $output)); + + return parent::doRun($input, $output); + } + + protected function getDefaultCommands() + { + $commands = parent::getDefaultCommands(); + + $commands[] = new DumpReferenceCommand($this->extensionManager); + $commands[] = new DebugCommand($this, $this->configurationLoader, $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(true); + + 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'; + } + + if ($input->hasParameterOption(array('--debug'))) { + return 'debug'; + } + + 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 000000000..ae53dfa99 --- /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 000000000..e604d6766 --- /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/DebugCommand.php b/vendor/behat/behat/src/Behat/Testwork/Cli/DebugCommand.php new file mode 100644 index 000000000..d888cb90b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Cli/DebugCommand.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\Cli; + +use Behat\Testwork\ServiceContainer\Configuration\ConfigurationLoader; +use Behat\Testwork\ServiceContainer\ExtensionManager; +use Symfony\Component\Console\Command\Command as BaseCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Provides debug information about the current environment. + * + * @author Konstantin Kudryashov + */ +final class DebugCommand extends BaseCommand +{ + /** + * @var Application + */ + private $application; + /** + * @var ConfigurationLoader + */ + private $configurationLoader; + /** + * @var ExtensionManager + */ + private $extensionManager; + + /** + * Initialises command. + * + * @param Application $application + * @param ConfigurationLoader $configurationLoader + * @param ExtensionManager $extensionManager + */ + public function __construct( + Application $application, + ConfigurationLoader $configurationLoader, + ExtensionManager $extensionManager + ) { + $this->application = $application; + $this->configurationLoader = $configurationLoader; + $this->extensionManager = $extensionManager; + + parent::__construct('debug'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln(sprintf('%s version %s', $this->application->getName(), $this->application->getVersion())); + + $output->writeln(''); + + $debug = $this->configurationLoader->debugInformation(); + $output->writeln('--- configuration'); + $output->writeln(sprintf(' environment variable (%s): %s', $debug['environment_variable_name'], $debug['environment_variable_content'])); + $output->writeln(sprintf(' configuration file: %s', $debug['configuration_file_path'])); + + $output->writeln(''); + + $debug = $this->extensionManager->debugInformation(); + $output->writeln('--- extensions'); + $output->writeln(sprintf(' extensions loaded: %s', count($debug['extensions_list']) ? implode(', ', $debug['extensions_list']) : 'none')); + + $output->writeln(''); + } +} 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 000000000..d6b57d442 --- /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 000000000..4b9fba847 --- /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 000000000..72238fdcc --- /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 000000000..f7d8605c1 --- /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 000000000..65025a33e --- /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 000000000..39d34f7fa --- /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 000000000..08500152c --- /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 000000000..b1dda505d --- /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 000000000..4c3bb92a4 --- /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 000000000..4b8579fed --- /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 000000000..6f517aed5 --- /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 000000000..07ed513be --- /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 000000000..f2b6b9820 --- /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 000000000..6b399cc99 --- /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 000000000..dcf66fde8 --- /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 000000000..e06f058c7 --- /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 000000000..3396b634f --- /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 000000000..24a639c9c --- /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 000000000..18c9aaeb4 --- /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 000000000..b2eec9f49 --- /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 000000000..b77de0610 --- /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 000000000..f820caf33 --- /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 000000000..97c8a7a03 --- /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 000000000..591e54ba3 --- /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 000000000..b68a4ec97 --- /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 000000000..1bec416ec --- /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 000000000..dc0a22cd0 --- /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 000000000..5892a0849 --- /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 000000000..31382172e --- /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 000000000..819be30d5 --- /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 000000000..66a82c64e --- /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 000000000..27e972863 --- /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 000000000..026592bdc --- /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 000000000..50191b463 --- /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 000000000..2ded66a28 --- /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 000000000..72376dac5 --- /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 000000000..10f34196e --- /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 000000000..84b2d07c0 --- /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 000000000..c1200f300 --- /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 000000000..bc86fb542 --- /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 000000000..fce59bbf6 --- /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 000000000..ac89715e5 --- /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 000000000..eab706186 --- /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 000000000..0b06299ef --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Exception/Stringer/PHPUnitExceptionStringer.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\Exception\Stringer; + +use Exception; + +/** + * 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 + || $exception instanceof \PHPUnit\Framework\Exception; + } + + /** + * {@inheritdoc} + */ + public function stringException(Exception $exception, $verbosity) + { + if (!class_exists('PHPUnit\\Framework\\TestFailure')) { + return trim(\PHPUnit_Framework_TestFailure::exceptionToString($exception)); + } + + // 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 000000000..5a5e59913 --- /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 000000000..a140b0053 --- /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 000000000..d08c498f3 --- /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 000000000..77f0a75a0 --- /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 000000000..4fdc537ca --- /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 000000000..0154d59f3 --- /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 000000000..e06fb4461 --- /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 000000000..38b7a0d1f --- /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 000000000..a8d392c18 --- /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 000000000..5242fa8db --- /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 000000000..237bc7615 --- /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 000000000..48ece6aba --- /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 000000000..19719ec9a --- /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 000000000..0dd7508f6 --- /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 000000000..527a11a1d --- /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 000000000..59b07c791 --- /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 000000000..30c5fd5ad --- /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 000000000..5c982cbe1 --- /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 000000000..d7014fd66 --- /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 000000000..6cc308f00 --- /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 000000000..fee6de4d4 --- /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 000000000..1277e824a --- /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 000000000..3ba4478f0 --- /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 000000000..5400be9e7 --- /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/Ordering/Cli/OrderController.php b/vendor/behat/behat/src/Behat/Testwork/Ordering/Cli/OrderController.php new file mode 100644 index 000000000..12edd91f1 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Ordering/Cli/OrderController.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\Ordering\Cli; + +use Behat\Testwork\Ordering\Exception\InvalidOrderException; +use Behat\Testwork\Ordering\OrderedExercise; +use Behat\Testwork\Ordering\Orderer\Orderer; +use Behat\Testwork\Cli\Controller; +use Symfony\Component\Console\Command\Command as SymfonyCommand; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * Preloads scenarios and then modifies the order when --order is passed + * + * @author Ciaran McNulty + */ +final class OrderController implements Controller +{ + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; + /** + * @var OrderedExercise + */ + private $exercise; + /** + * @var array + */ + private $orderers = array(); + + /** + * Initializes controller. + * + * @param EventDispatcherInterface $eventDispatcher + * @param OrderedExercise $exercise + */ + public function __construct(EventDispatcherInterface $eventDispatcher, OrderedExercise $exercise) + { + $this->eventDispatcher = $eventDispatcher; + $this->exercise = $exercise; + } + + /** + * Configures command to be executable by the controller. + * + * @param SymfonyCommand $command + */ + public function configure(SymfonyCommand $command) + { + $command->addOption('--order', null, InputOption::VALUE_REQUIRED, + 'Set an order in which to execute the specifications (this will result in slower feedback).' + ); + } + + /** + * Executes controller. + * + * @param InputInterface $input + * @param OutputInterface $output + * + * @return null|integer + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $orderer = $input->getOption('order'); + + if (!$orderer) { + return; + } + + if (!array_key_exists($orderer, $this->orderers)) { + throw new InvalidOrderException(sprintf("Order option '%s' was not recognised", $orderer)); + } + + $this->exercise->setOrderer($this->orderers[$orderer]); + } + + /** + * Register a new available controller + * + * @param Orderer $orderer + */ + public function registerOrderer(Orderer $orderer) + { + $this->orderers[$orderer->getName()] = $orderer; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Ordering/Exception/InvalidOrderException.php b/vendor/behat/behat/src/Behat/Testwork/Ordering/Exception/InvalidOrderException.php new file mode 100644 index 000000000..8d9cd32a7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Ordering/Exception/InvalidOrderException.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\Ordering\Exception; + +use Behat\Testwork\Exception\TestworkException; +use RuntimeException; + +/** + * Represents exception throw during attempt to prioritise execution with a non-existent algorithm + * + * @author Ciaran McNulty + */ +final class InvalidOrderException extends RuntimeException implements TestworkException +{} diff --git a/vendor/behat/behat/src/Behat/Testwork/Ordering/OrderedExercise.php b/vendor/behat/behat/src/Behat/Testwork/Ordering/OrderedExercise.php new file mode 100644 index 000000000..1cc3055a6 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Ordering/OrderedExercise.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\Testwork\Ordering; + +use Behat\Testwork\Ordering\Orderer\NoopOrderer; +use Behat\Testwork\Ordering\Orderer\Orderer; +use Behat\Testwork\Specification\SpecificationIterator; +use Behat\Testwork\Tester\Exercise; +use Behat\Testwork\Tester\Result\TestResult; +use Behat\Testwork\Tester\Setup\Setup; +use Behat\Testwork\Tester\Setup\Teardown; + +/** + * Exercise that is ordered according to a specified algorithm + * + * @author Ciaran McNulty + */ +final class OrderedExercise implements Exercise +{ + /** + * @var Orderer + */ + private $orderer; + + /** + * @var SpecificationIterator[] + */ + private $unordered; + + /** + * @var SpecificationIterator[] + */ + private $ordered; + + /** + * @var Exercise + */ + private $decoratedExercise; + + /** + * @param Exercise $decoratedExercise + */ + public function __construct(Exercise $decoratedExercise) + { + $this->orderer = new NoopOrderer(); + $this->decoratedExercise = $decoratedExercise; + } + + /** + * Sets up exercise for a test. + * + * @param SpecificationIterator[] $iterators + * @param Boolean $skip + * + * @return Setup + */ + public function setUp(array $iterators, $skip) + { + return $this->decoratedExercise->setUp($this->order($iterators), $skip); + } + + /** + * Tests suites specifications. + * + * @param SpecificationIterator[] $iterators + * @param Boolean $skip + * + * @return TestResult + */ + public function test(array $iterators, $skip) + { + return $this->decoratedExercise->test($this->order($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) + { + return $this->decoratedExercise->tearDown($this->order($iterators), $skip, $result); + } + + /** + * Replace the algorithm being used for prioritisation + * + * @param Orderer $orderer + */ + public function setOrderer(Orderer $orderer) + { + $this->orderer = $orderer; + } + + /** + * @param SpecificationIterator[] $iterators + * @return SpecificationIterator[] + */ + private function order(array $iterators) + { + if (!$this->ordered || $this->unordered != $iterators) { + $this->unordered = $iterators; + $this->ordered = $this->orderer->order($iterators); + } + + return $this->ordered; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/NoopOrderer.php b/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/NoopOrderer.php new file mode 100644 index 000000000..a2257f98f --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/NoopOrderer.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\Ordering\Orderer; + +use Behat\Testwork\Specification\SpecificationIterator; + +/** + * Null implementation of Orderer that does no ordering + * + * @author Ciaran McNulty + */ +final class NoopOrderer implements Orderer +{ + + /** + * @param SpecificationIterator[] $scenarioIterators + * @return SpecificationIterator[] + */ + public function order(array $scenarioIterators) + { + return $scenarioIterators; + } + + /** + * @return string + */ + public function getName() + { + return 'null'; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/Orderer.php b/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/Orderer.php new file mode 100644 index 000000000..1f29c528c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/Orderer.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\Testwork\Ordering\Orderer; + +use Behat\Testwork\Specification\SpecificationIterator; + +/** + * Algorithm for prioritising Specification execution + * + * @author Ciaran McNulty + */ +interface Orderer +{ + /** + * @param SpecificationIterator[] $scenarioIterators + * @return SpecificationIterator[] + */ + public function order(array $scenarioIterators); + + /** + * @return string + */ + public function getName(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/RandomOrderer.php b/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/RandomOrderer.php new file mode 100644 index 000000000..551e44796 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/RandomOrderer.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\Ordering\Orderer; + +use Behat\Testwork\Specification\SpecificationArrayIterator; + +/** + * Prioritises Suites and Features into random order + * + * @author Ciaran McNulty + */ +final class RandomOrderer implements Orderer +{ + /** + * @param SpecificationIterator[] $scenarioIterators + * @return SpecificationIterator[] + */ + public function order(array $scenarioIterators) + { + $orderedFeatures = $this->orderFeatures($scenarioIterators); + shuffle($orderedFeatures); + + return $orderedFeatures; + } + + /** + * @param array $scenarioIterators + * @return array + */ + private function orderFeatures(array $scenarioIterators) + { + $orderedSuites = array(); + + foreach ($scenarioIterators as $scenarioIterator) { + $orderedSpecifications = iterator_to_array($scenarioIterator); + shuffle($orderedSpecifications); + $orderedSuites[] = new SpecificationArrayIterator( + $scenarioIterator->getSuite(), + $orderedSpecifications + ); + } + + return $orderedSuites; + } + + /** + * @return string + */ + public function getName() + { + return 'random'; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/ReverseOrderer.php b/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/ReverseOrderer.php new file mode 100644 index 000000000..9a23a4dc7 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Ordering/Orderer/ReverseOrderer.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\Ordering\Orderer; + +use Behat\Testwork\Specification\SpecificationArrayIterator; +use Behat\Testwork\Specification\SpecificationIterator; + +/** + * Prioritises Suites and Features into reverse order + * + * @author Ciaran McNulty + */ +final class ReverseOrderer implements Orderer +{ + /** + * @param SpecificationIterator[] $scenarioIterators + * @return SpecificationIterator[] + */ + public function order(array $scenarioIterators) + { + $orderedFeatures = $this->orderFeatures($scenarioIterators); + $orderedSuites = $this->orderSuites($orderedFeatures); + + return $orderedSuites; + } + + /** + * @param array $scenarioIterators + * @return array + */ + private function orderFeatures(array $scenarioIterators) + { + $orderedSuites = array(); + + foreach ($scenarioIterators as $scenarioIterator) { + $orderedSpecifications = array_reverse(iterator_to_array($scenarioIterator)); + $orderedSuites[] = new SpecificationArrayIterator( + $scenarioIterator->getSuite(), + $orderedSpecifications + ); + } + + return $orderedSuites; + } + + /** + * @param $orderedSuites + * @return array + */ + private function orderSuites($orderedSuites) + { + return array_reverse($orderedSuites); + } + + /** + * @return string + */ + public function getName() + { + return 'reverse'; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Ordering/ServiceContainer/OrderingExtension.php b/vendor/behat/behat/src/Behat/Testwork/Ordering/ServiceContainer/OrderingExtension.php new file mode 100644 index 000000000..2a9d5a7fa --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Ordering/ServiceContainer/OrderingExtension.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\Testwork\Ordering\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\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 specification execution ordering. + * + * @author Ciaran McNulty + */ +final class OrderingExtension implements Extension +{ + const ORDERER_TAG = 'tester.orderer'; + + /** + * @var ServiceProcessor + */ + private $processor; + + /** + * Initializes extension. + * + * @param null|ServiceProcessor $processor + */ + public function __construct(ServiceProcessor $processor = null) + { + $this->processor = $processor ?: new ServiceProcessor(); + } + + /** + * You can modify the container here before it is dumped to PHP code. + * + * @param ContainerBuilder $container + * + * @api + */ + public function process(ContainerBuilder $container) + { + $definition = $container->getDefinition(CliExtension::CONTROLLER_TAG . '.order'); + $references = $this->processor->findAndSortTaggedServices($container, self::ORDERER_TAG); + + foreach ($references as $reference) { + $definition->addMethodCall('registerOrderer', array($reference)); + } + } + + /** + * Returns the extension config key. + * + * @return string + */ + public function getConfigKey() + { + return 'ordering'; + } + + /** + * 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) + { + $this->loadOrderController($container); + $this->loadOrderedExercise($container); + $this->loadDefaultOrderers($container); + } + + /** + * Loads order controller. + * + * @param ContainerBuilder $container + */ + private function loadOrderController(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Ordering\Cli\OrderController', array( + new Reference(EventDispatcherExtension::DISPATCHER_ID), + new Reference(TesterExtension::EXERCISE_WRAPPER_TAG . '.ordering') + )); + $definition->addTag(CliExtension::CONTROLLER_TAG, array('priority' => 250)); + $container->setDefinition(CliExtension::CONTROLLER_TAG . '.order', $definition); + } + + /** + * Loads exercise wrapper that enables ordering + * + * @param ContainerBuilder $container + */ + private function loadOrderedExercise(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Ordering\OrderedExercise', array( + new Reference(TesterExtension::EXERCISE_ID) + )); + $definition->addTag(TesterExtension::EXERCISE_WRAPPER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::EXERCISE_WRAPPER_TAG . '.ordering', $definition); + } + + /** + * Defines default orderers + * + * @param ContainerBuilder $container + */ + private function loadDefaultOrderers(ContainerBuilder $container) + { + $definition = new Definition('Behat\Testwork\Ordering\Orderer\ReverseOrderer'); + $definition->addTag(self::ORDERER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::EXERCISE_WRAPPER_TAG . '.ordering.reverse', $definition); + + + $definition = new Definition('Behat\Testwork\Ordering\Orderer\RandomOrderer'); + $definition->addTag(self::ORDERER_TAG, array('priority' => -9999)); + $container->setDefinition(TesterExtension::EXERCISE_WRAPPER_TAG . '.ordering.random', $definition); + } +} 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 000000000..ae886519b --- /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 000000000..edd773c81 --- /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 000000000..43b33718d --- /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 000000000..cba1a7d54 --- /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 000000000..283ed14ef --- /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 000000000..23a87c6d1 --- /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 000000000..0c76bac39 --- /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 000000000..6fbc078ff --- /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 000000000..0df21eb3a --- /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 000000000..3894d49fa --- /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 000000000..cdf776018 --- /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/Factory/ConsoleOutputFactory.php b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/Factory/ConsoleOutputFactory.php new file mode 100644 index 000000000..e1d22ee18 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/Factory/ConsoleOutputFactory.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\Testwork\Output\Printer\Factory; + +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; + +/** + * Creates an output stream for the console. + * + * @author Wouter J + * @author Konstantin Kudryashov + */ +class ConsoleOutputFactory extends OutputFactory +{ + /** + * Creates output formatter that is used to create a stream. + * + * @return OutputFormatter + */ + protected function createOutputFormatter() + { + return new OutputFormatter(); + } + + /** + * Configure output stream parameters. + * + * @param OutputInterface $output + */ + protected function configureOutputStream(OutputInterface $output) + { + $verbosity = $this->getOutputVerbosity() ? OutputInterface::VERBOSITY_VERBOSE : OutputInterface::VERBOSITY_NORMAL; + $output->setVerbosity($verbosity); + + if (null !== $this->isOutputDecorated()) { + $output->getFormatter()->setDecorated($this->isOutputDecorated()); + } + } + + /** + * Returns new output stream. + * + * Override this method & call flush() to write output in another stream + * + * @return resource + * + * @throws BadOutputPathException + */ + protected function createOutputStream() + { + if (null === $this->getOutputPath()) { + $stream = fopen('php://stdout', 'w'); + } elseif (!is_dir($this->getOutputPath())) { + $stream = fopen($this->getOutputPath(), 'w'); + } else { + throw new BadOutputPathException(sprintf( + 'Filename expected as `output_path` parameter, but got `%s`.', + $this->getOutputPath() + ), $this->getOutputPath()); + } + + return $stream; + } + + /** + * {@inheritdoc} + */ + public function createOutput($stream = null) + { + $stream = $stream ? : $this->createOutputStream(); + $format = $this->createOutputFormatter(); + + // set user-defined styles + foreach ($this->getOutputStyles() 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); + } + + $output = new StreamOutput( + $stream, + StreamOutput::VERBOSITY_NORMAL, + $this->isOutputDecorated(), + $format + ); + $this->configureOutputStream($output); + + return $output; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Printer/Factory/FilesystemOutputFactory.php b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/Factory/FilesystemOutputFactory.php new file mode 100644 index 000000000..af982028c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/Factory/FilesystemOutputFactory.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\Testwork\Output\Printer\Factory; + +use Behat\Testwork\Output\Exception\BadOutputPathException; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\StreamOutput; + +/** + * Creates an output stream for the filesystem. + * + * @author Wouter J + */ +class FilesystemOutputFactory extends OutputFactory +{ + private $fileName; + + public function setFileName($fileName) + { + $this->fileName = $fileName; + } + + /** + * Configure output stream parameters. + * + * @param OutputInterface $output + */ + protected function configureOutputStream(OutputInterface $output) + { + $verbosity = $this->getOutputVerbosity() ? OutputInterface::VERBOSITY_VERBOSE : OutputInterface::VERBOSITY_NORMAL; + $output->setVerbosity($verbosity); + } + + /** + * {@inheritDoc} + */ + public function createOutput($stream = null) + { + if (is_file($this->getOutputPath())) { + throw new BadOutputPathException( + 'Directory expected for the `output_path` option, but a filename was given.', + $this->getOutputPath() + ); + } elseif (!is_dir($this->getOutputPath())) { + mkdir($this->getOutputPath(), 0777, true); + } + + if (null === $this->fileName) { + throw new \LogicException('Unable to create file, no file name specified'); + } + + $filePath = $this->getOutputPath().'/'.$this->fileName; + + $stream = new StreamOutput( + fopen($filePath, 'w'), + StreamOutput::VERBOSITY_NORMAL, + false // a file is never decorated + ); + $this->configureOutputStream($stream); + + return $stream; + } +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Printer/Factory/OutputFactory.php b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/Factory/OutputFactory.php new file mode 100644 index 000000000..20f47d35a --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/Factory/OutputFactory.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Behat\Testwork\Output\Printer\Factory; + +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Wouter J + * @author Konstantin Kudryashov + */ +abstract class OutputFactory +{ + const VERBOSITY_NORMAL = 1; + const VERBOSITY_VERBOSE = 2; + const VERBOSITY_VERY_VERBOSE = 3; + const VERBOSITY_DEBUG = 4; + + /** + * @var null|string + */ + private $outputPath; + /** + * @var array + */ + private $outputStyles = array(); + /** + * @var null|Boolean + */ + private $outputDecorated = null; + /** + * @var integer + */ + private $verbosityLevel = 0; + + /** + * Sets output path. + * + * @param string $path + */ + public function setOutputPath($path) + { + $this->outputPath = $path; + } + + /** + * 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; + } + + /** + * 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; + } + + /** + * 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); + } + + /** + * Returns output verbosity level. + * + * @return integer + */ + public function getOutputVerbosity() + { + return $this->verbosityLevel; + } + + /** + * Returns a new output stream. + * + * @return OutputInterface + */ + abstract public function createOutput(); +} diff --git a/vendor/behat/behat/src/Behat/Testwork/Output/Printer/JUnitOutputPrinter.php b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/JUnitOutputPrinter.php new file mode 100644 index 000000000..7577e111c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/JUnitOutputPrinter.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\Testwork\Output\Printer; + +use Behat\Testwork\Output\Printer\Factory\FilesystemOutputFactory; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * A convenient wrapper around the ConsoleOutputPrinter to write valid JUnit + * reports. + * + * @author Wouter J + * @author James Watson + */ +final class JUnitOutputPrinter extends StreamOutputPrinter +{ + const XML_VERSION = '1.0'; + const XML_ENCODING = 'UTF-8'; + + /** + * @var \DOMDocument + */ + private $domDocument; + /** + * @var \DOMElement + */ + private $currentTestsuite; + /** + * @var \DOMElement + */ + private $currentTestcase; + /** + * @var \DOMElement + */ + private $testSuites; + + public function __construct(FilesystemOutputFactory $outputFactory) + { + parent::__construct($outputFactory); + } + + /** + * Creates a new JUnit file. + * + * The file will be initialized with an XML definition and the root element. + * + * @param string $name The filename (without extension) and default value of the name attribute + * @param array $testsuitesAttributes Attributes for the root element + */ + public function createNewFile($name, array $testsuitesAttributes = array()) + { + $this->setFileName(strtolower(trim(preg_replace('/[^[:alnum:]_]+/', '_', $name), '_'))); + + $this->domDocument = new \DOMDocument(self::XML_VERSION, self::XML_ENCODING); + $this->domDocument->formatOutput = true; + + $this->testSuites = $this->domDocument->createElement('testsuites'); + $this->domDocument->appendChild($this->testSuites); + $this->addAttributesToNode($this->testSuites, array_merge(array('name' => $name), $testsuitesAttributes)); + $this->flush(); + } + + /** + * Adds a new node. + * + * @param array $testsuiteAttributes + */ + public function addTestsuite(array $testsuiteAttributes = array()) + { + $this->currentTestsuite = $this->domDocument->createElement('testsuite'); + $this->testSuites->appendChild($this->currentTestsuite); + $this->addAttributesToNode($this->currentTestsuite, $testsuiteAttributes); + } + + + /** + * Adds a new node. + * + * @param array $testcaseAttributes + */ + public function addTestcase(array $testcaseAttributes = array()) + { + $this->currentTestcase = $this->domDocument->createElement('testcase'); + $this->currentTestsuite->appendChild($this->currentTestcase); + $this->addAttributesToNode($this->currentTestcase, $testcaseAttributes); + } + + /** + * Add a testcase child element. + * + * @param string $nodeName + * @param array $nodeAttributes + * @param string $nodeValue + */ + public function addTestcaseChild($nodeName, array $nodeAttributes = array(), $nodeValue = null) + { + $childNode = $this->domDocument->createElement($nodeName, $nodeValue); + $this->currentTestcase->appendChild($childNode); + $this->addAttributesToNode($childNode, $nodeAttributes); + } + + private function addAttributesToNode(\DOMElement $node, array $attributes) + { + foreach ($attributes as $name => $value){ + $node->setAttribute($name, $value); + } + } + + /** + * Sets file name. + * + * @param string $fileName + * @param string $extension The file extension, defaults to "xml" + */ + public function setFileName($fileName, $extension = 'xml') + { + if ('.'.$extension !== substr($fileName, strlen($extension) + 1)) { + $fileName .= '.'.$extension; + } + + $this->getOutputFactory()->setFileName($fileName); + $this->flush(); + } + + /** + * Generate XML from the DOMDocument and parse to the the writing stream + */ + public function flush() + { + if($this->domDocument instanceof \DOMDocument){ + $this->getWritingStream()->write( + $this->domDocument->saveXML(null, LIBXML_NOEMPTYTAG), + false, + OutputInterface::OUTPUT_RAW + ); + } + + parent::flush(); + } +} 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 000000000..91292d39c --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/OutputPrinter.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\Testwork\Output\Printer; + +/** + * Isolates all console/filesystem writing. + * + * @author Konstantin Kudryashov + */ +interface OutputPrinter +{ + /** + * @deprecated since 3.1, to be removed in 4.0 + */ + const VERBOSITY_NORMAL = 1; + /** + * @deprecated since 3.1, to be removed in 4.0 + */ + const VERBOSITY_VERBOSE = 2; + /** + * @deprecated since 3.1, to be removed in 4.0 + */ + const VERBOSITY_VERY_VERBOSE = 3; + /** + * @deprecated since 3.1, to be removed in 4.0 + */ + const VERBOSITY_DEBUG = 4; + + /** + * Sets output path. + * + * @param string $path + */ + public function setOutputPath($path); + + /** + * Returns output path. + * + * @return null|string + * + * @deprecated since 3.1, to be removed in 4.0 + */ + public function getOutputPath(); + + /** + * Sets output styles. + * + * @param array $styles + */ + public function setOutputStyles(array $styles); + + /** + * Returns output styles. + * + * @return array + * + * @deprecated since 3.1, to be removed in 4.0 + */ + public function getOutputStyles(); + + /** + * Forces output to be decorated. + * + * @param Boolean $decorated + */ + public function setOutputDecorated($decorated); + + /** + * Returns output decoration status. + * + * @return null|Boolean + * + * @deprecated since 3.1, to be removed in 4.0 + */ + public function isOutputDecorated(); + + /** + * Sets output verbosity level. + * + * @param integer $level + */ + public function setOutputVerbosity($level); + + /** + * Returns output verbosity level. + * + * @return integer + * + * @deprecated since 3.1, to be removed in 4.0 + */ + public function getOutputVerbosity(); + + /** + * Writes message(s) to output stream. + * + * @param string|array $messages message or array of messages + */ + public function write($messages); + + /** + * Writes newlined message(s) to output stream. + * + * @param string|array $messages message or array of messages + */ + public function writeln($messages = ''); + + /** + * Clear output stream, 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/Printer/StreamOutputPrinter.php b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/StreamOutputPrinter.php new file mode 100644 index 000000000..6b3fb4e49 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Output/Printer/StreamOutputPrinter.php @@ -0,0 +1,149 @@ + + * + * 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\Printer\Factory\OutputFactory; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Wouter J + * @author Konstantin Kudryashov + */ +class StreamOutputPrinter implements OutputPrinter +{ + /** + * @var OutputInterface + */ + private $output; + /** + * @var OutputFactory + */ + private $outputFactory; + + public function __construct(OutputFactory $outputFactory) + { + $this->outputFactory = $outputFactory; + } + + /** + * @return OutputFactory + */ + protected function getOutputFactory() + { + return $this->outputFactory; + } + + /** + * {@inheritdoc} + */ + public function setOutputPath($path) + { + $this->outputFactory->setOutputPath($path); + $this->flush(); + } + + /** + * {@inheritdoc} + */ + public function getOutputPath() + { + return $this->outputFactory->getOutputPath(); + } + + /** + * {@inheritdoc} + */ + public function setOutputStyles(array $styles) + { + $this->outputFactory->setOutputStyles($styles); + $this->flush(); + } + + /** + * {@inheritdoc} + */ + public function getOutputStyles() + { + return $this->outputFactory->getOutputStyles(); + } + + /** + * {@inheritdoc} + */ + public function setOutputDecorated($decorated) + { + $this->outputFactory->setOutputDecorated($decorated); + $this->flush(); + } + + /** + * {@inheritdoc} + */ + public function isOutputDecorated() + { + return $this->outputFactory->isOutputDecorated(); + } + + /** + * {@inheritdoc} + */ + public function setOutputVerbosity($level) + { + $this->outputFactory->setOutputVerbosity($level); + $this->flush(); + } + + /** + * {@inheritdoc} + */ + public function getOutputVerbosity() + { + return $this->outputFactory->getOutputVerbosity(); + } + + /** + * {@inheritdoc} + */ + public function write($messages) + { + $this->getWritingStream()->write($messages, false); + } + + /** + * {@inheritdoc} + */ + public function writeln($messages = '') + { + $this->getWritingStream()->write($messages, true); + } + + /** + * {@inheritdoc} + */ + public function flush() + { + $this->output = null; + } + + /** + * Returns output instance, prepared to write. + * + * @return OutputInterface + */ + final protected function getWritingStream() + { + if (null === $this->output) { + $this->output = $this->outputFactory->createOutput(); + } + + return $this->output; + } +} 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 000000000..c80b552c7 --- /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 000000000..f49babe97 --- /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 000000000..33521c10d --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/Configuration/ConfigurationLoader.php @@ -0,0 +1,282 @@ + + * + * 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; + /** + * @var array + */ + private $debugInformation = array( + 'environment_variable_name' => 'none', + 'environment_variable_content' => 'none', + 'configuration_file_path' => 'none' + ); + + /** + * 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) { + $this->debugInformation['configuration_file_path'] = $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; + } + + /** + * Returns array with configuration debug information. + * + * @return array + */ + public function debugInformation() + { + return $this->debugInformation; + } + + /** + * 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; + } + + $this->debugInformation['environment_variable_name'] = $this->environmentVariable; + + if ($envConfig = getenv($this->environmentVariable)) { + $config = @json_decode($envConfig, true); + + $this->debugInformation['environment_variable_content'] = $envConfig; + + 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 000000000..d713cbc9b --- /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 000000000..a72377762 --- /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 000000000..be1862046 --- /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 000000000..eb4e16db7 --- /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 000000000..b57aa66a4 --- /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 000000000..b5da8b4d2 --- /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 000000000..a7035c581 --- /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 000000000..9533dcaa3 --- /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 000000000..7e2d955dc --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/ServiceContainer/ExtensionManager.php @@ -0,0 +1,231 @@ + + * + * 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(); + private $debugInformation = array( + 'extensions_list' => 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); + + $this->debugInformation['extensions_list'][] = $extension->getConfigKey(); + + 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); + } + } + + /** + * Returns array with extensions debug information. + * + * @return array + */ + public function debugInformation() + { + return $this->debugInformation; + } + + /** + * 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 000000000..a57810e1f --- /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 000000000..bac556d05 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Specification/GroupedSpecificationIterator.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\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() + { + if (!isset($this->iterators[$this->position])) { + return; + } + + $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 000000000..372fbea32 --- /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 000000000..95cfc6a3a --- /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 000000000..03ca52de7 --- /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 000000000..c48292dc9 --- /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 000000000..5204bd503 --- /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 000000000..c96ad6c69 --- /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 000000000..dc8ac0ce6 --- /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 000000000..ea1a23aa6 --- /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 000000000..500588438 --- /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 000000000..73f366cfc --- /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 000000000..2027089b3 --- /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 000000000..d6b418b5d --- /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 000000000..95e02445a --- /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 000000000..5ceeb7e04 --- /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 000000000..36f6141c4 --- /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 000000000..876d6b600 --- /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 000000000..766cffe5b --- /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 array_key_exists($key, $this->settings); + } + + /** + * 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 000000000..79fbcda84 --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Suite/ServiceContainer/SuiteExtension.php @@ -0,0 +1,274 @@ + + * + * 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') + ->normalizeKeys(false) + ->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() + ->normalizeKeys(false) + ->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 000000000..616562434 --- /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 000000000..782f8fd7c --- /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 000000000..28d0af1ab --- /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 000000000..5ad98fdcb --- /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 000000000..7795cc9e8 --- /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 000000000..b3d2eac5b --- /dev/null +++ b/vendor/behat/behat/src/Behat/Testwork/Tester/Cli/ExerciseController.php @@ -0,0 +1,179 @@ + + * + * 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`. This might be because of incorrect paths configuration in your `suites`.', + $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 000000000..1e610be21 --- /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 000000000..2bede7cd5 --- /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 000000000..c429957ae --- /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 000000000..6a19c1efb --- /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 000000000..f30edcf19 --- /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 000000000..8dad2fc59 --- /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 000000000..555e75fa8 --- /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 000000000..fca891bec --- /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 000000000..0a43d8d7e --- /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 000000000..5ea9ad133 --- /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 000000000..9d557965d --- /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 000000000..5102f3747 --- /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 000000000..e9fa4f7d0 --- /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 000000000..2f831dd74 --- /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 000000000..b67838d28 --- /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 000000000..55bcfa9da --- /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 000000000..2130cd3f2 --- /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 000000000..7fdc74dbf --- /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 000000000..e904ebb35 --- /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 000000000..56686d04f --- /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 000000000..8a94d15db --- /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 000000000..fbb445b17 --- /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 000000000..9dc106a22 --- /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 000000000..f139f1a14 --- /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 000000000..676b8917d --- /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 000000000..39de237cf --- /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/gherkin/.gitignore b/vendor/behat/gherkin/.gitignore new file mode 100644 index 000000000..33b7c6582 --- /dev/null +++ b/vendor/behat/gherkin/.gitignore @@ -0,0 +1,4 @@ +*.tgz +vendor +composer.phar +composer.lock diff --git a/vendor/behat/gherkin/.travis.yml b/vendor/behat/gherkin/.travis.yml new file mode 100644 index 000000000..a348812c2 --- /dev/null +++ b/vendor/behat/gherkin/.travis.yml @@ -0,0 +1,33 @@ +language: php + +sudo: false + +cache: + directories: + - $HOME/.composer/cache/files + +php: [5.3, 5.6, 7.0, 7.1] + +matrix: + include: + - php: 5.6 + env: SYMFONY_VERSION='2.3.*' + - php: 5.6 + env: SYMFONY_VERSION='2.7.*' + - php: 5.6 + env: SYMFONY_VERSION='2.8.*' + - php: 7.1 + env: SYMFONY_VERSION='3.*' + +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 000000000..ddbfbc18c --- /dev/null +++ b/vendor/behat/gherkin/CHANGES.md @@ -0,0 +1,383 @@ +4.5.1 / 2017-08-30 +================== + + * Fix regression in `PathsFilter` + +4.5.0 / 2017-08-30 +================== + + * Sync i18n with Cucumber Gherkin + * Drop support for HHVM tests on Travis + * Add `TableNode::fromList()` method (thanks @TravisCarden) + * Add `ExampleNode::getOutlineTitle()` method (thanks @duxet) + * Use realpath, so the feature receives the cwd prefixed (thanks @glennunipro) + * Explicitly handle non-two-dimensional arrays in TableNode (thanks @TravisCarden) + * Fix to line/linefilter scenario runs which take relative paths to files (thanks @generalconsensus) + +4.4.5 / 2016-10-30 +================== + + * Fix partial paths matching in `PathsFilter` + +4.4.4 / 2016-09-18 +================== + + * Provide clearer exception for non-writeable cache directories + +4.4.3 / 2016-09-18 +================== + + * Ensure we reset tags between features + +4.4.2 / 2016-09-03 +================== + + * Sync 18n with gherkin 3 + +4.4.1 / 2015-12-30 +================== + + * Ensure keywords are trimmed when syncing translations + * Sync 18n with cucumber + +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 000000000..6869f76df --- /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/cucumber/blob/master/gherkin/gherkin-languages.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 000000000..14f15e8b4 --- /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 000000000..e7034df92 --- /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 000000000..379195645 --- /dev/null +++ b/vendor/behat/gherkin/bin/update_i18n @@ -0,0 +1,70 @@ +#!/usr/bin/env php + $keywords) { + $langMessages = array(); + + foreach ($keywords as $type => $words) { + if (!is_array($words)) { + $words = array($words); + } + + if ('scenarioOutline' === $type) { + $type = 'scenario_outline'; + } + + if (in_array($type, array('given', 'when', 'then', 'and', 'but'))) { + $formattedKeywords = array(); + + foreach ($words as $word) { + $formattedWord = trim($word); + + if ($formattedWord === $word) { + $formattedWord = $formattedWord.'<'; // Convert the keywords to the syntax used by Gherkin 2, which is expected by our Lexer. + } + + $formattedKeywords[] = $formattedWord; + } + + $words = $formattedKeywords; + } + + usort($words, function($type1, $type2) { + return mb_strlen($type2, 'utf8') - mb_strlen($type1, 'utf8'); + }); + + $langMessages[$type] = implode('|', $words); + } + + // ensure that the order of keys is consistent between updates + ksort($langMessages); + + $array[$lang] = $langMessages; +} + +// 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); +$arrayString = var_export($array, true); + +file_put_contents(__DIR__.'/../i18n.php', <<=5.3.1" + }, + + "require-dev": { + "symfony/yaml": "~2.3|~3", + "symfony/phpunit-bridge": "~2.7|~3", + "phpunit/phpunit": "~4.5|~5" + }, + + "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 000000000..f8e37409d --- /dev/null +++ b/vendor/behat/gherkin/i18n.php @@ -0,0 +1,1108 @@ + + array ( + 'and' => 'And|*', + 'background' => 'Background', + 'but' => 'But|*', + 'examples' => 'Scenarios|Examples', + 'feature' => 'Business Need|Feature|Ability', + 'given' => 'Given|*', + 'name' => 'English', + 'native' => 'English', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Scenario Template|Scenario Outline', + 'then' => 'Then|*', + 'when' => 'When|*', + ), + 'af' => + array ( + 'and' => 'En|*', + 'background' => 'Agtergrond', + 'but' => 'Maar|*', + 'examples' => 'Voorbeelde', + 'feature' => 'Besigheid Behoefte|Funksie|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' => 'عندما|متى|*', + ), + 'ast' => + array ( + 'and' => 'Ya|*|Y', + 'background' => 'Antecedentes', + 'but' => 'Peru|*', + 'examples' => 'Exemplos', + 'feature' => 'Carauterística', + 'given' => 'Dada|Daos|Daes|Dáu|*', + 'name' => 'Asturian', + 'native' => 'asturianu', + 'scenario' => 'Casu', + 'scenario_outline' => 'Esbozu del casu', + 'then' => 'Entós|*', + 'when' => 'Cuando|*', + ), + 'az' => + array ( + 'and' => 'Həm|Və|*', + 'background' => 'Kontekst|Keçmiş', + 'but' => 'Ancaq|Amma|*', + 'examples' => 'Nümunələr', + 'feature' => 'Özəllik', + 'given' => 'Tutaq ki|Verilir|*', + 'name' => 'Azerbaijani', + 'native' => 'Azərbaycanca', + 'scenario' => 'Ssenari', + 'scenario_outline' => 'Ssenarinin strukturu', + 'then' => 'O halda|*', + 'when' => 'Nə vaxt ki|Əgər|*', + ), + '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|Situasi|Keadaan', + 'scenario_outline' => 'Garis Panduan Senario|Kerangka Senario|Kerangka Situasi|Kerangka Keadaan', + 'then' => 'Kemudian|Maka|*', + 'when' => 'Apabila|*', + ), + 'bs' => + array ( + 'and' => '*|I|A', + 'background' => 'Pozadina', + 'but' => 'Ali|*', + 'examples' => 'Primjeri', + 'feature' => 'Karakteristika', + 'given' => 'Dato|*', + 'name' => 'Bosnian', + 'native' => 'Bosanski', + 'scenario' => 'Scenariju|Scenario', + 'scenario_outline' => 'Scenario-outline|Scenariju-obris', + 'then' => 'Zatim|*', + 'when' => 'Kada|*', + ), + 'ca' => + array ( + 'and' => '*|I', + 'background' => 'Antecedents|Rerefons', + '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' => 'Kontext|Pozadí', + 'but' => 'Ale|*', + 'examples' => 'Příklady', + 'feature' => 'Požadavek', + 'given' => 'Za předpokladu|Pokud|*', + 'name' => 'Czech', + 'native' => 'Česky', + 'scenario' => 'Scénář', + 'scenario_outline' => 'Osnova scénáře|Náčrt 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' => 'Όταν|*', + ), + 'em' => + array ( + 'and' => '😂<|*', + 'background' => '💤', + 'but' => '😔<|*', + 'examples' => '📓', + 'feature' => '📚', + 'given' => '😐<|*', + 'name' => 'Emoji', + '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|Kazo-skizo|Skizo', + 'then' => 'Do|*', + 'when' => 'Se|*', + ), + 'es' => + array ( + 'and' => '*|Y|E', + 'background' => 'Antecedentes', + 'but' => 'Pero|*', + 'examples' => 'Ejemplos', + 'feature' => 'Característica', + 'given' => 'Dados|Dadas|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 qu\'<|Et que|Et|*', + 'background' => 'Contexte', + 'but' => 'Mais qu\'<|Mais que|Mais|*', + 'examples' => 'Exemples', + 'feature' => 'Fonctionnalité', + 'given' => 'Etant donné qu\'<|Étant donné qu\'<|Etant donné que|Étant donné que|Etant données|Étant données|Etant donnée|Etant donnés|Étant donnée|Étant donnés|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|*', + ), + 'ga' => + array ( + 'and' => 'Agus<|*', + 'background' => 'Cúlra', + 'but' => 'Ach<|*', + 'examples' => 'Samplaí', + 'feature' => 'Gné', + 'given' => 'Cuir i gcás nach<|Cuir i gcás gur<|Cuir i gcás nár<|Cuir i gcás go<|*', + 'name' => 'Irish', + 'native' => 'Gaeilge', + 'scenario' => 'Cás', + 'scenario_outline' => 'Cás Achomair', + 'then' => 'Ansin<|*', + 'when' => 'Nuair nach<|Nuair nár<|Nuair ba<|Nuair a<|*', + ), + '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' => 'Dados|Dadas|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' => 'Scenariji|Primjeri', + 'feature' => 'Mogucnost|Mogućnost|Osobina', + 'given' => 'Zadani|Zadano|Zadan|*', + 'name' => 'Croatian', + 'native' => 'hrvatski', + 'scenario' => 'Scenarij', + 'scenario_outline' => 'Koncept|Skica', + 'then' => 'Onda|*', + 'when' => 'Kada|Kad|*', + ), + 'ht' => + array ( + 'and' => 'Epi|Ak|*|E', + 'background' => 'Kontèks|Istorik', + 'but' => 'Men|*', + 'examples' => 'Egzanp', + 'feature' => 'Karakteristik|Fonksyonalite|Mak', + 'given' => 'Sipoze ke|Sipoze Ke|Sipoze|*', + 'name' => 'Creole', + 'native' => 'kreyòl', + 'scenario' => 'Senaryo', + 'scenario_outline' => 'Senaryo deskripsyon|Senaryo Deskripsyon|Dyagram senaryo|Dyagram Senaryo|Plan senaryo|Plan 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' => 'Atburðarásir|Dæmi', + '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' => 'Data|Dato|Dati|Date|*', + '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' => 'Contone|Conto', + 'feature' => 'Fitur', + 'given' => 'Nalikaning|Nalika|*', + 'name' => 'Javanese', + 'native' => 'Basa Jawa', + 'scenario' => 'Skenario', + 'scenario_outline' => 'Konsep skenario', + 'then' => 'Banjur|Njuk|*', + 'when' => 'Menawa|Manawa|*', + ), + 'ka' => + array ( + 'and' => 'და<|*', + 'background' => 'კონტექსტი', + 'but' => 'მაგ­რამ<|*', + 'examples' => 'მაგალითები', + 'feature' => 'თვისება', + 'given' => 'მოცემული<|*', + 'name' => 'Georgian', + 'native' => 'ქართველი', + 'scenario' => 'სცენარის', + 'scenario_outline' => 'სცენარის ნიმუში', + 'then' => 'მაშინ<|*', + 'when' => 'როდესაც<|*', + ), + '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|*', + ), + 'mk-Cyrl' => + array ( + 'and' => '*|И', + 'background' => 'Контекст|Содржина', + 'but' => 'Но|*', + 'examples' => 'Сценарија|Примери', + 'feature' => 'Функционалност|Бизнис потреба|Можност', + 'given' => 'Дадена|Дадено|*', + 'name' => 'Macedonian', + 'native' => 'Македонски', + 'scenario' => 'На пример|Сценарио', + 'scenario_outline' => 'Преглед на сценарија|Концепт|Скица', + 'then' => 'Тогаш|*', + 'when' => 'Кога|*', + ), + 'mk-Latn' => + array ( + 'and' => '*|I', + 'background' => 'Sodrzhina|Kontekst', + 'but' => 'No|*', + 'examples' => 'Scenaria|Primeri', + 'feature' => 'Funkcionalnost|Biznis potreba|Mozhnost', + 'given' => 'Dadena|Dadeno|*', + 'name' => 'Macedonian (Latin)', + 'native' => 'Makedonski (Latinica)', + 'scenario' => 'Na primer|Scenario', + 'scenario_outline' => 'Pregled na scenarija|Koncept|Skica', + 'then' => 'Togash|*', + 'when' => 'Koga|*', + ), + 'mn' => + array ( + 'and' => 'Тэгээд|Мөн|*', + 'background' => 'Агуулга', + 'but' => 'Гэхдээ|Харин|*', + 'examples' => 'Тухайлбал', + 'feature' => 'Функционал|Функц', + 'given' => 'Өгөгдсөн нь|Анх|*', + 'name' => 'Mongolian', + 'native' => 'монгол', + 'scenario' => 'Сценар', + 'scenario_outline' => 'Сценарын төлөвлөгөө', + 'then' => 'Үүний дараа|Тэгэхэд|*', + 'when' => 'Хэрэв|*', + ), + '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' => 'Wanneer|Als|*', + ), + 'no' => + array ( + 'and' => 'Og|*', + 'background' => 'Bakgrunn', + 'but' => 'Men|*', + 'examples' => 'Eksempler', + 'feature' => 'Egenskap', + 'given' => 'Gitt|*', + 'name' => 'Norwegian', + 'native' => 'norsk', + 'scenario' => 'Scenario', + 'scenario_outline' => 'Abstrakt Scenario|Scenariomal', + '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' => 'Potrzeba biznesowa|Właściwość|Funkcja|Aspekt', + '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|Jeśli|Kiedy|Gdy|*', + ), + 'pt' => + array ( + 'and' => '*|E', + 'background' => 'Cenario de Fundo|Cenário de Fundo|Contexto|Fundo', + 'but' => 'Mas|*', + 'examples' => 'Exemplos|Cenários|Cenarios', + 'feature' => 'Funcionalidade|Característica|Caracteristica', + 'given' => 'Dados|Dadas|Dada|Dado|*', + 'name' => 'Portuguese', + 'native' => 'português', + 'scenario' => 'Cenário|Cenario', + 'scenario_outline' => 'Delineação do Cenário|Delineacao do Cenario|Esquema do Cenário|Esquema do Cenario', + 'then' => 'Entao|Então|*', + 'when' => 'Quando|*', + ), + 'ro' => + array ( + 'and' => 'Și|Si|Şi|*', + 'background' => 'Context', + 'but' => 'Dar|*', + 'examples' => 'Exemple', + 'feature' => 'Functionalitate|Funcționalitate|FuncÅ£ionalitate', + 'given' => 'Date fiind|Dati fiind|Dați fiind|DaÅ£i 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 taktiež|A zároveň|A tiež|*|A', + 'background' => 'Pozadie', + 'but' => 'Ale|*', + 'examples' => 'Príklady', + 'feature' => 'Požiadavka|VlastnosÅ¥|Funkcia', + 'given' => 'Za predpokladu|Pokiaľ|*', + 'name' => 'Slovak', + 'native' => 'Slovensky', + 'scenario' => 'Scenár', + 'scenario_outline' => 'Osnova Scenára|Náčrt Scenáru|Náčrt Scenára', + 'then' => 'Potom|Tak|*', + 'when' => 'Keď|Ak|*', + ), + 'sl' => + array ( + 'and' => 'Ter|In', + 'background' => 'Kontekst|Osnova|Ozadje', + 'but' => 'Vendar|Ampak|Toda', + 'examples' => 'Scenariji|Primeri', + 'feature' => 'Funkcionalnost|Značilnost|Funkcija|Možnosti|Moznosti|Lastnost', + 'given' => 'Privzeto|Zaradi|Podano|Dano', + 'name' => 'Slovenian', + 'native' => 'Slovenski', + 'scenario' => 'Scenarij|Primer', + 'scenario_outline' => 'Struktura scenarija|Oris scenarija|Koncept|Osnutek|Skica', + 'then' => 'Takrat|Potem|Nato', + 'when' => 'Kadar|Ko|Ce|Če', + ), + 'sr-Cyrl' => + array ( + 'and' => '*|И', + 'background' => 'Контекст|Позадина|Основа', + 'but' => 'Али|*', + 'examples' => 'Сценарији|Примери', + 'feature' => 'Функционалност|Могућност|Особина', + 'given' => 'За дате|За дато|За дати|*', + 'name' => 'Serbian', + 'native' => 'Српски', + 'scenario' => 'Сценарио|Пример', + 'scenario_outline' => 'Структура сценарија|Концепт|Скица', + 'then' => 'Онда|*', + 'when' => 'Када|Кад|*', + ), + 'sr-Latn' => + array ( + 'and' => '*|I', + 'background' => 'Kontekst|Pozadina|Osnova', + 'but' => 'Ali|*', + 'examples' => 'Scenariji|Primeri', + 'feature' => 'Funkcionalnost|Mogućnost|Mogucnost|Osobina', + 'given' => 'Za date|Za dato|Za dati|*', + 'name' => 'Serbian (Latin)', + 'native' => 'Srpski (Latinica)', + 'scenario' => 'Scenario|Primer', + 'scenario_outline' => 'Struktura scenarija|Koncept|Skica', + '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' => 'poQbogh malja\'|Qu\'meH \'ut|perbogh|Qap|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 000000000..35379fe54 --- /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 000000000..f983946e2 --- /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 000000000..24fc8d87a --- /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 000000000..87d4a472e --- /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 000000000..17a206ac7 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Cache/FileCache.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\Gherkin\Cache; + +use Behat\Gherkin\Exception\CacheException; +use Behat\Gherkin\Node\FeatureNode; +use Behat\Gherkin\Gherkin; + +/** + * 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. + * + * @throws CacheException + */ + public function __construct($path) + { + $this->path = rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'v'.Gherkin::VERSION; + + if (!is_dir($this->path)) { + @mkdir($this->path, 0777, true); + } + + if (!is_writeable($this->path)) { + throw new CacheException(sprintf('Cache path "%s" is not writeable. Check your filesystem permissions or disable Gherkin file cache.', $this->path)); + } + } + + /** + * 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 000000000..e404f3048 --- /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 000000000..f8b9214c3 --- /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 000000000..f377e30fe --- /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 000000000..476d81f56 --- /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 000000000..b7d7a4c6a --- /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 000000000..f835e726b --- /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 000000000..a3a3b0847 --- /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 000000000..8a0ebd566 --- /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 000000000..a7c43eccb --- /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 000000000..4a531a0dd --- /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 000000000..455e9ac35 --- /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 000000000..b8062bed5 --- /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 000000000..82ae0e582 --- /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 000000000..61126e569 --- /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 000000000..7f7c1dcaa --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Filter/PathsFilter.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\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( + function ($realpath) { + return rtrim($realpath, DIRECTORY_SEPARATOR) . + (is_dir($realpath) ? DIRECTORY_SEPARATOR : ''); + }, + array_filter( + 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 (0 === strpos(realpath($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 000000000..19e9377a9 --- /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 000000000..10bee8fad --- /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 000000000..fed6c1afd --- /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 000000000..e457cd873 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Gherkin.php @@ -0,0 +1,142 @@ + + * + * 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 +{ + const VERSION = '4.4-dev'; + + /** + * @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 000000000..35b9b821a --- /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 000000000..871f196f4 --- /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 000000000..2a5439677 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/CucumberKeywords.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\Gherkin\Keywords; + +use Symfony\Component\Yaml\Exception\ParseException; +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 or file path + */ + public function __construct($yaml) + { + // Handle filename explicitly for BC reasons, as Symfony Yaml 3.0 does not do it anymore + $file = null; + if (strpos($yaml, "\n") === false && is_file($yaml)) { + if (false === is_readable($yaml)) { + throw new ParseException(sprintf('Unable to parse "%s" as the file is not readable.', $yaml)); + } + + $file = $yaml; + $yaml = file_get_contents($file); + } + + try { + $content = Yaml::parse($yaml); + } catch (ParseException $e) { + if ($file) { + $e->setParsedFile($file); + } + + throw $e; + } + + parent::__construct($content); + } + + /** + * 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 000000000..fcd9769ba --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Keywords/KeywordsDumper.php @@ -0,0 +1,365 @@ + + * + * 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 + * @param bool $excludeAsterisk + * + * @return string|array String for short version and array of features for extended + */ + public function dump($language, $short = true, $excludeAsterisk = false) + { + $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, $excludeAsterisk)); + } + + $features = array(); + foreach ($keywords as $keyword) { + $keyword = call_user_func($this->keywordsDumper, array($keyword), $short); + $features[] = trim($languageComment . $this->dumpFeature($keyword, $short, $excludeAsterisk)); + } + + return $features; + } + + /** + * Dumps feature example. + * + * @param string $keyword Item keyword + * @param Boolean $short Dump short version? + * + * @return string + */ + protected function dumpFeature($keyword, $short = true, $excludeAsterisk = false) + { + $dump = <<keywords->getBackgroundKeywords()); + if ($short) { + $keywords = call_user_func($this->keywordsDumper, $keywords, $short); + $dump .= $this->dumpBackground($keywords, $short, $excludeAsterisk); + } else { + $keyword = call_user_func($this->keywordsDumper, array($keywords[0]), $short); + $dump .= $this->dumpBackground($keyword, $short, $excludeAsterisk); + } + + // Scenario + $keywords = explode('|', $this->keywords->getScenarioKeywords()); + if ($short) { + $keywords = call_user_func($this->keywordsDumper, $keywords, $short); + $dump .= $this->dumpScenario($keywords, $short, $excludeAsterisk); + } else { + foreach ($keywords as $keyword) { + $keyword = call_user_func($this->keywordsDumper, array($keyword), $short); + $dump .= $this->dumpScenario($keyword, $short, $excludeAsterisk); + } + } + + // Outline + $keywords = explode('|', $this->keywords->getOutlineKeywords()); + if ($short) { + $keywords = call_user_func($this->keywordsDumper, $keywords, $short); + $dump .= $this->dumpOutline($keywords, $short, $excludeAsterisk); + } else { + foreach ($keywords as $keyword) { + $keyword = call_user_func($this->keywordsDumper, array($keyword), $short); + $dump .= $this->dumpOutline($keyword, $short, $excludeAsterisk); + } + } + + return $dump; + } + + /** + * Dumps background example. + * + * @param string $keyword Item keyword + * @param Boolean $short Dump short version? + * + * @return string + */ + protected function dumpBackground($keyword, $short = true, $excludeAsterisk = false) + { + $dump = <<dumpStep( + $this->keywords->getGivenKeywords(), + 'there is agent A', + $short, + $excludeAsterisk + ); + + // And + $dump .= $this->dumpStep( + $this->keywords->getAndKeywords(), + 'there is agent B', + $short, + $excludeAsterisk + ); + + 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, $excludeAsterisk = false) + { + $dump = <<dumpStep( + $this->keywords->getGivenKeywords(), + 'there is agent J', + $short, + $excludeAsterisk + ); + + // And + $dump .= $this->dumpStep( + $this->keywords->getAndKeywords(), + 'there is agent K', + $short, + $excludeAsterisk + ); + + // When + $dump .= $this->dumpStep( + $this->keywords->getWhenKeywords(), + 'I erase agent K\'s memory', + $short, + $excludeAsterisk + ); + + // Then + $dump .= $this->dumpStep( + $this->keywords->getThenKeywords(), + 'there should be agent J', + $short, + $excludeAsterisk + ); + + // But + $dump .= $this->dumpStep( + $this->keywords->getButKeywords(), + 'there should not be agent K', + $short, + $excludeAsterisk + ); + + 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, $excludeAsterisk = false) + { + $dump = <<dumpStep( + $this->keywords->getGivenKeywords(), + 'there is agent ', + $short, + $excludeAsterisk + ); + + // And + $dump .= $this->dumpStep( + $this->keywords->getAndKeywords(), + 'there is agent ', + $short, + $excludeAsterisk + ); + + // When + $dump .= $this->dumpStep( + $this->keywords->getWhenKeywords(), + 'I erase agent \'s memory', + $short, + $excludeAsterisk + ); + + // Then + $dump .= $this->dumpStep( + $this->keywords->getThenKeywords(), + 'there should be agent ', + $short, + $excludeAsterisk + ); + + // But + $dump .= $this->dumpStep( + $this->keywords->getButKeywords(), + 'there should not be agent ', + $short, + $excludeAsterisk + ); + + $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 000000000..446d462c9 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Lexer.php @@ -0,0 +1,614 @@ + + * + * 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') + ? preg_quote(mb_substr($keyword, 0, -1, 'utf8'), '/') . '\s*' + : preg_quote($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] || '|' !== substr($line, -1)) { + 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) + { + // Consider "*" as a AND keyword so that it is normalized to the previous step type + if ('*' === $native) { + return 'And'; + } + + 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 000000000..20932c129 --- /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 000000000..3492d6e6a --- /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 000000000..dcde0e628 --- /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 000000000..f18f19ae2 --- /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 000000000..ae8bf992d --- /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 000000000..861332ccc --- /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 000000000..0c268fd3a --- /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 000000000..4457f1807 --- /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 000000000..fb1edb4b2 --- /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 000000000..d3366b9f6 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/ExampleNode.php @@ -0,0 +1,274 @@ + + * + * 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; + /** + * @var string + */ + private $outlineTitle; + + /** + * Initializes outline. + * + * @param string $title + * @param string[] $tags + * @param StepNode[] $outlineSteps + * @param string[] $tokens + * @param integer $line + * @param string|null $outlineTitle + */ + public function __construct($title, array $tags, $outlineSteps, array $tokens, $line, $outlineTitle = null) + { + $this->title = $title; + $this->tags = $tags; + $this->outlineSteps = $outlineSteps; + $this->tokens = $tokens; + $this->line = $line; + $this->outlineTitle = $outlineTitle; + } + + /** + * 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; + } + + /** + * Returns outline title. + * + * @return string + */ + public function getOutlineTitle() + { + return $this->outlineTitle; + } + + /** + * 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 000000000..805e659ef --- /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 000000000..641365996 --- /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 000000000..e6e412f38 --- /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 000000000..eabe61a0c --- /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 000000000..62f55181d --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/OutlineNode.php @@ -0,0 +1,218 @@ + + * + * 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), + $this->getTitle() + ); + } + + 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 000000000..f0e8948ee --- /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 000000000..fb298435d --- /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 000000000..88f793474 --- /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 000000000..58267e1e2 --- /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 000000000..2a5c73d9e --- /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 000000000..82eaef490 --- /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 000000000..23b794f02 --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Node/TableNode.php @@ -0,0 +1,342 @@ + + * + * 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 given table is invalid + */ + 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.'); + } + + if (!is_array($row)) { + throw new NodeException('Table is not two-dimensional.'); + } + + foreach ($row as $column => $string) { + if (!isset($this->maxLineLength[$column])) { + $this->maxLineLength[$column] = 0; + } + + if (!is_scalar($string)) { + throw new NodeException('Table is not two-dimensional.'); + } + + $this->maxLineLength[$column] = max($this->maxLineLength[$column], mb_strlen($string, 'utf8')); + } + } + } + + /** + * Creates a table from a given list. + * + * @param array $list One-dimensional array + * + * @return TableNode + * + * @throws NodeException If the given list is not a one-dimensional array + */ + public static function fromList(array $list) + { + if (count($list) !== count($list, COUNT_RECURSIVE)) { + throw new NodeException('List is not a one-dimensional array.'); + } + + array_walk($list, function (&$item) { + $item = array($item); + }); + return new self($list); + } + + /** + * 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 000000000..cce6bcafd --- /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 000000000..5cc85424b --- /dev/null +++ b/vendor/behat/gherkin/src/Behat/Gherkin/Parser.php @@ -0,0 +1,699 @@ + + * + * 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; + $this->tags = array(); + + 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 000000000..2f0b7c950 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Cache/FileCacheTest.php @@ -0,0 +1,75 @@ +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 . '/v' . Gherkin::VERSION . '/' . md5('broken_feature') . '.feature.cache'); + $this->cache->read('broken_feature'); + } + + public function testUnwriteableCacheDir() + { + $this->setExpectedException('Behat\Gherkin\Exception\CacheException'); + + new FileCache('/dev/null/gherkin-test'); + } + + 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 000000000..a0bb6c86f --- /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 000000000..994e6564a --- /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/Fixtures/full/file1 b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/Fixtures/full/file1 new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/Fixtures/full/file2 b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/Fixtures/full/file2 new file mode 100644 index 000000000..e69de29bb diff --git a/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/Fixtures/full_path/file1 b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/Fixtures/full_path/file1 new file mode 100644 index 000000000..e69de29bb 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 000000000..846a719de --- /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 000000000..fb8abe1ce --- /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 000000000..24914ecf1 --- /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 000000000..6a50e1eb0 --- /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 000000000..e106d734f --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Filter/PathsFilterTest.php @@ -0,0 +1,58 @@ +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)); + } + + public function testItDoesNotMatchPartialPaths() + { + $fixtures = __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR; + + $feature = new FeatureNode(null, null, array(), null, array(), null, null, $fixtures . 'full_path' . DIRECTORY_SEPARATOR . 'file1', 1); + + $filter = new PathsFilter(array($fixtures . 'full')); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $filter = new PathsFilter(array($fixtures . 'full' . DIRECTORY_SEPARATOR)); + $this->assertFalse($filter->isFeatureMatch($feature)); + + $filter = new PathsFilter(array($fixtures . 'full_path' . DIRECTORY_SEPARATOR)); + $this->assertTrue($filter->isFeatureMatch($feature)); + + $filter = new PathsFilter(array($fixtures . 'full_path')); + $this->assertTrue($filter->isFeatureMatch($feature)); + } + + public function testItDoesNotMatchIfFileWithSameNameButNotPathExistsInFolder() + { + $fixtures = __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR; + + $feature = new FeatureNode(null, null, array(), null, array(), null, null, $fixtures . 'full_path' . DIRECTORY_SEPARATOR . 'file1', 1); + + $filter = new PathsFilter(array($fixtures . 'full')); + $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 000000000..8e8af3e0d --- /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 000000000..5c6c9ab28 --- /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 000000000..e69de29bb 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 000000000..7627fe614 --- /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 000000000..a7b1a7b25 --- /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 000000000..f69277d74 --- /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 000000000..31089fd5d --- /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 000000000..014c8d38a --- /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 000000000..a8a2c5159 --- /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 000000000..2ae46cbc1 --- /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 000000000..d0d65dc27 --- /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 000000000..e13f36391 --- /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 000000000..43e7201d5 --- /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 000000000..43e7201d5 --- /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 000000000..35a144ba0 --- /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 000000000..c450a8b10 --- /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 000000000..55abe3b22 --- /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 000000000..091103c2f --- /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 000000000..6ac42d4ab --- /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: '前提', text: '50 を入力', line: 8 } + - { keyword_type: 'Given', type: 'かつ', text: '70 を入力', line: 9 } + - { keyword_type: 'When', type: 'もし', text: 'add ボタンを押した', line: 10 } + - { keyword_type: 'Then', 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 000000000..7e30cf54d --- /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 000000000..b41bc58d6 --- /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 000000000..d7aebc06c --- /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 000000000..6c73bba01 --- /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 000000000..c6e897725 --- /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 000000000..8c59ff132 --- /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 000000000..bc21a9a95 --- /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 000000000..9c0db4aa2 --- /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 000000000..1097d5d5f --- /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 000000000..358d86787 --- /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 000000000..b4d3005c7 --- /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 000000000..45fcd77cd --- /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 000000000..97966665f --- /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 000000000..486d9585c --- /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 000000000..fca7e2075 --- /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 000000000..3857fdf3d --- /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 000000000..84cb8ff64 --- /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 000000000..744184f16 --- /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 000000000..9a3ffb82c --- /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 000000000..d8ed4d3d4 --- /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 000000000..900d6c718 --- /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 000000000..e3e9cc7bd --- /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 000000000..61d7bef59 --- /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 000000000..02ca25cc9 --- /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 000000000..4db3b874e --- /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 000000000..8a560d71d --- /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 000000000..6c661c123 --- /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 000000000..7e17ff2ad --- /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 000000000..f17bef5e5 --- /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 000000000..4a743ea72 --- /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 000000000..e08fa7043 --- /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 000000000..4218a974a --- /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 000000000..b843852d9 --- /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 000000000..a93cb4d83 --- /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 000000000..95b9d5590 --- /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 000000000..bfc3e064e --- /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 000000000..f5526af42 --- /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 000000000..e587faada --- /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 000000000..9d317719e --- /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 000000000..601373f25 --- /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 000000000..eda57222a --- /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 000000000..36cbd054e --- /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 000000000..87cc7f2ee --- /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 000000000..7f024f6bb --- /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 000000000..45dd501a3 --- /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 000000000..92f4c78fc --- /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 000000000..21eaaab16 --- /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 000000000..ed08ba42b --- /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 000000000..4e04950b0 --- /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 000000000..ae3c7321b --- /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 000000000..398c60cf5 --- /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 000000000..9e5c0cb5e --- /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/ArrayKeywordsTest.php b/vendor/behat/gherkin/tests/Behat/Gherkin/Keywords/ArrayKeywordsTest.php new file mode 100644 index 000000000..e6c18dc94 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Keywords/ArrayKeywordsTest.php @@ -0,0 +1,48 @@ +getKeywordsArray()); + } + + protected function getKeywordsArray() + { + return array( + 'with_special_chars' => array( + 'and' => 'And/foo', + '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', + ), + ); + } + + protected function getSteps($keywords, $text, &$line, $keywordType) + { + $steps = array(); + foreach (explode('|', $keywords) as $keyword) { + if (false !== mb_strpos($keyword, '<')) { + $keyword = mb_substr($keyword, 0, -1); + } + + $steps[] = new StepNode($keyword, $text, array(), $line++, $keywordType); + } + + return $steps; + } +} 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 000000000..bf10cb391 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Keywords/CachedArrayKeywordsTest.php @@ -0,0 +1,37 @@ +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 000000000..fdfc65e29 --- /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, true); + $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" . json_encode($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 000000000..697d1d3d8 --- /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 000000000..de3270866 --- /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 000000000..8f5d2c17d --- /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 000000000..83b27398f --- /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 000000000..c6f46be54 --- /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 000000000..1e889b80f --- /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 000000000..1beed387e --- /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 000000000..d334415d6 --- /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 000000000..a2299551b --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/Node/TableNodeTest.php @@ -0,0 +1,269 @@ + array( + array('everzet', 'antono') + ), + 'Three-dimensional array' => array( + array(array(array('everzet', 'antono'))) + ) + ); + } + + /** + * @dataProvider constructorTestDataProvider + * @expectedException \Behat\Gherkin\Exception\NodeException + * @expectedExceptionMessage Table is not two-dimensional. + */ + public function testConstructorExpectsTwoDimensionalArrays($table) + { + new TableNode($table); + } + + public function testHashTable() + { + $table = new TableNode(array( + array('username', 'password'), + array('everzet', 'qwerty'), + array('antono', 'pa$sword') + )); + + $this->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()); + } + + public function testFromList() + { + $table = TableNode::fromList(array( + 'everzet', + 'antono' + )); + + $expected = new TableNode(array( + array('everzet'), + array('antono'), + )); + $this->assertEquals($expected, $table); + } + + /** + * @expectedException \Behat\Gherkin\Exception\NodeException + */ + public function testGetTableFromListWithMultidimensionalArrayArgument() + { + TableNode::fromList(array( + array(1, 2, 3), + array(4, 5, 6) + )); + } + +} 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 000000000..c416ec2e7 --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/ParserExceptionsTest.php @@ -0,0 +1,291 @@ + 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); + } + + /** + * @expectedException \Behat\Gherkin\Exception\ParserException + */ + public function testTableWithoutRightBorder() + { + $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 000000000..aff585cda --- /dev/null +++ b/vendor/behat/gherkin/tests/Behat/Gherkin/ParserTest.php @@ -0,0 +1,147 @@ +parseEtalon($fixtureName . '.yml'); + $features = $this->parseFixture($fixtureName . '.feature'); + + $this->assertInternalType('array', $features); + $this->assertEquals(1, count($features)); + $fixture = $features[0]; + + $this->assertEquals($etalon, $fixture); + } + + public function testParserResetsTagsBetweenFeatures() + { + $parser = $this->getGherkinParser(); + + $parser->parse(<<parse(<<assertFalse($feature2->hasTags()); + } + + 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/.gitignore b/vendor/behat/mink-extension/.gitignore new file mode 100644 index 000000000..e38971024 --- /dev/null +++ b/vendor/behat/mink-extension/.gitignore @@ -0,0 +1,4 @@ +*.tgz +*.phar +composer.lock +vendor diff --git a/vendor/behat/mink-extension/.travis.yml b/vendor/behat/mink-extension/.travis.yml new file mode 100644 index 000000000..f125a6126 --- /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 000000000..29864ddcb --- /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 000000000..5f90365c1 --- /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 11 translated languages: `cs`,`de`,`es`,`fr`,`ja`,`nl`,`pl`,`pt`,`ro`,`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 000000000..e0cbd4196 --- /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 000000000..e18f5dd50 --- /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 000000000..2e721d13d --- /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|~3.0" + }, + + "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 000000000..144dfec1c --- /dev/null +++ b/vendor/behat/mink-extension/doc/index.rst @@ -0,0 +1,349 @@ +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: + # Specify the path to the node_modules directory. + node_modules_path: /usr/local/lib/node_modules/ + +.. 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 000000000..b4e08efc6 --- /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 000000000..74ec33a23 --- /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 000000000..cf584e3a9 --- /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 000000000..ed7b3b11d --- /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 000000000..da25c71a3 --- /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 000000000..0cf6adb87 --- /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 000000000..a618fcb06 --- /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 000000000..8e045de0c --- /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 000000000..34ca2818f --- /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 000000000..8d4e91fc1 --- /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 000000000..ac20a3adc --- /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 000000000..8ba30ccf2 --- /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 000000000..6a8e41e61 --- /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 000000000..ac997ca18 --- /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/ro.xliff b/vendor/behat/mink-extension/i18n/ro.xliff new file mode 100644 index 000000000..52cbc766a --- /dev/null +++ b/vendor/behat/mink-extension/i18n/ro.xliff @@ -0,0 +1,191 @@ + + +
+ + + + + + + + + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + + + + + + + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" cu "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" with:$/]]> + (?:[^"]|\\")*)" cu:$/]]> + + + (?:[^"]|\\")*)" for "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" pentru "(?P(?:[^"]|\\")*)"$/]]> + + + + + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" from "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + [^"]*)" to "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" la "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" ar trebui să conțină "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" field should not contain "(?P(?:[^"]|\\")*)"$/]]> + (?:[^"]|\\")*)" nu ar trebui să conțină "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" checkbox should be checked$/]]> + (?:[^"]|\\")*)" ar trebui bifată$/]]> + + + (?:[^"]|\\")*)" (?:is|should be) checked$/]]> + (?:[^"]|\\")*)" este bifată$/]]> + + + (?:[^"]|\\")*)" should (?:be unchecked|not be checked)$/]]> + (?:[^"]|\\")*)" ar trebui să fie nebifată$/]]> + + + (?:[^"]|\\")*)" checkbox should not be checked$/]]> + (?:[^"]|\\")*)" ar trebui să nu fie bifată$/]]> + + + (?:[^"]|\\")*)" is (?:unchecked|not checked)$/]]> + (?:[^"]|\\")*)" este nebifată$/]]> + + + [^"]+)"$/]]> + [^"]+)"$/]]> + + + + + + + "(?:[^"]|\\")*")$/]]> + "(?:[^"]|\\")*")$/]]> + + + [^"]*)" element should contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" ar trebui să conțină "(?P(?:[^"]|\\")*)"$/]]> + + + [^"]*)" element should not contain "(?P(?:[^"]|\\")*)"$/]]> + [^"]*)" ar trebui să nu conțină "(?P(?:[^"]|\\")*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" în elementul "(?P[^"]*)"$/]]> + + + (?:[^"]|\\")*)" in the "(?P[^"]*)" element$/]]> + (?:[^"]|\\")*)" în elementul "(?P[^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + [^"]*)" element$/]]> + [^"]*)"$/]]> + + + \d+) "(?P[^"]*)" elements?$/]]> + \d+) element(e|а)? "(?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 000000000..00309d334 --- /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 000000000..8d06b23ab --- /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 000000000..d3c60b87e --- /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 000000000..99136cb34 --- /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 000000000..db8e96b38 --- /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 000000000..84b208ae0 --- /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 000000000..be72e219e --- /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 000000000..00922e7ec --- /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 000000000..484e6e70b --- /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 000000000..abdb7d5c1 --- /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 000000000..21bb10cbe --- /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 000000000..5ec5c1683 --- /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 000000000..a1fb5050d --- /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 000000000..f0e044522 --- /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 000000000..c16533b58 --- /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 000000000..bbb45abf4 --- /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 000000000..11aaa4f6b --- /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 000000000..a5bfa30f0 --- /dev/null +++ b/vendor/behat/mink-extension/src/Behat/MinkExtension/Context/MinkContext.php @@ -0,0 +1,571 @@ + + * + * 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 + * Example: Given I am on "/" + * Example: When I go to "/" + * Example: And I go to "/" + * + * @Given /^(?:|I )am on (?:|the )homepage$/ + * @When /^(?:|I )go to (?:|the )homepage$/ + */ + public function iAmOnHomepage() + { + $this->visitPath('/'); + } + + /** + * Opens specified page + * Example: Given I am on "http://batman.com" + * Example: And I am on "/articles/isBatmanBruceWayne" + * Example: When I go to "/articles/isBatmanBruceWayne" + * + * @Given /^(?:|I )am on "(?P[^"]+)"$/ + * @When /^(?:|I )go to "(?P[^"]+)"$/ + */ + public function visit($page) + { + $this->visitPath($page); + } + + /** + * Reloads current page + * Example: When I reload the page + * Example: And I reload the page + * + * @When /^(?:|I )reload the page$/ + */ + public function reload() + { + $this->getSession()->reload(); + } + + /** + * Moves backward one page in history + * Example: When I move backward one page + * + * @When /^(?:|I )move backward one page$/ + */ + public function back() + { + $this->getSession()->back(); + } + + /** + * Moves forward one page in history + * Example: And I move forward one page + * + * @When /^(?:|I )move forward one page$/ + */ + public function forward() + { + $this->getSession()->forward(); + } + + /** + * Presses button with specified id|name|title|alt|value + * Example: When I press "Log In" + * Example: And I press "Log In" + * + * @When /^(?:|I )press "(?P