diff --git a/.gherkin-lintignore b/.gherkin-lintignore new file mode 100644 index 00000000..20b8ca6d --- /dev/null +++ b/.gherkin-lintignore @@ -0,0 +1 @@ +features/i18n/*/*.feature diff --git a/.gherkin-lintrc b/.gherkin-lintrc new file mode 100644 index 00000000..50ae29b5 --- /dev/null +++ b/.gherkin-lintrc @@ -0,0 +1,36 @@ +{ + "no-files-without-scenarios" : "on", + "no-unnamed-features": "on", + "no-unnamed-scenarios": "on", + "no-dupe-scenario-names": "on", + "no-dupe-feature-names": "on", + "no-partially-commented-tag-lines": "on", + "indentation": [ + "on", { + "Feature": 0, + "Background": 2, + "Scenario": 2, + "Examples": 4, + "example": 6, + "Step": 4 + } + ], + "no-trailing-spaces": "on", + "new-line-at-eof": ["on", "yes"], + "no-multiple-empty-lines": "on", + "no-empty-file": "on", + "no-scenario-outlines-without-examples": "on", + "name-length": [ + "on", { + "Feature": 100, + "Scenario": 120, + "Step": "off" + } + ], + "no-restricted-tags": ["on", {"tags": ["@watch", "@wip"]}], + "use-and": "on", + "no-duplicate-tags": "on", + "no-superfluous-tags": "on", + "no-homogenous-tags": "off", + "one-space-between-tags": "on" +} diff --git a/.gitignore b/.gitignore index 4d3f649c..4dd0756a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ composer.lock vendor /drupal* behat.yml +/package-lock.json /node_modules +/.docksal diff --git a/.travis.yml b/.travis.yml index b989be53..89c4d520 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,37 +1,24 @@ language: php php: - - 5.5 - - 5.6 - 7.0 - 7.1 + - 7.2 env: global: - - PATH=$PATH:/home/travis/.composer/vendor/bin + - PATH=$PATH:/home/travis/.config/composer/vendor/bin - TRAVIS_NODE_VERSION="4.0.0" matrix: - - DRUPAL_VERSION=6 - DRUPAL_VERSION=7 - DRUPAL_VERSION=8 -matrix: - exclude: - - php: 5.5 - env: DRUPAL_VERSION=8 - - php: 5.6 - env: DRUPAL_VERSION=6 - - php: 7.0 - env: DRUPAL_VERSION=6 - - php: 7.1 - env: DRUPAL_VERSION=6 - allow_failures: - - php: 7.1 - env: DRUPAL_VERSION=7 - # Enable Travis containers. sudo: false +services: + - mysql + install: - composer self-update # For Drupal 8 install the behat drush endpoint. @@ -39,7 +26,7 @@ install: # @see https://github.com/jhedstrom/drupalextension/issues/413 # @todo Re-enable behat drush endpoint testing. # @see https://github.com/jhedstrom/drupalextension/issues/458 - - test ${DRUPAL_VERSION} -ne 8 || composer require --prefer-source drush/drush:~9.0 symfony/dependency-injection:3.4.4 + - test ${DRUPAL_VERSION} -ne 8 || COMPOSER_MEMORY_LIMIT=-1 travis_retry composer require drush/drush:~9.0 symfony/dependency-injection:3.4.4 - composer install # Install drush globally. - (test ${DRUPAL_VERSION} -ne 8 && composer global require drush/drush:~8.0 drupal/drupal-driver) || composer global require drush/drush:~9.0 @@ -51,8 +38,6 @@ install: - npm install before_script: - # Set NODE_PATH for zombie driver. - - export NODE_PATH="`pwd`/node_modules" # Define the module path according to the Drupal version being tested. - test ${DRUPAL_VERSION} -ne 8 || export MODULE_PATH="drupal/modules" - test ${DRUPAL_VERSION} -eq 8 || export MODULE_PATH="drupal/sites/all/modules" && mkdir -p ${MODULE_PATH} @@ -75,7 +60,7 @@ before_script: - drush cc drush # @todo Re-enable behat drush endpoint testing. # @see https://github.com/jhedstrom/drupalextension/issues/458 - - test ${DRUPAL_VERSION} -eq 6 || test ${DRUPAL_VERSION} -eq 8 || (test ${DRUPAL_VERSION} -eq 7 && drush help behat) + # - test ${DRUPAL_VERSION} -eq 6 || test ${DRUPAL_VERSION} -eq 8 || (test ${DRUPAL_VERSION} -eq 7 && drush help behat) # Only revert features on Drupal 7. - test \! ${DRUPAL_VERSION} -eq 7 || drush --yes fr behat_test # Disable the page cache on Drupal 8. @@ -90,6 +75,7 @@ before_script: script: - composer test + - npm test - vendor/bin/behat -fprogress --strict - vendor/bin/behat -fprogress --profile=drupal${DRUPAL_VERSION} --strict # Do not test the Drush profile unless Drupal 7 was installed. diff --git a/CHANGELOG.md b/CHANGELOG.md index 8975a4fb..78d753cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,42 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [4.0.1] 2019-10-08 +### Fixed + * [#552](https://github.com/jhedstrom/drupalextension/issue/552) Remove hard-coded symfony/event-dispatcher requirement. +### Changed + * [#553](https://github.com/jhedstrom/drupalextension/pull/553) Remove testing on PHP 5.6 and Drupal 6 +## [4.0.0] 2019-09-27 +## [4.0.0 rc1] 2019-07-24 +### Changed + * [#528](https://github.com/jhedstrom/drupalextension/pull/528) Show a more helpful failure when running `@javascript` + scenarios with incorrect configuration. + * [#545](https://github.com/jhedstrom/drupalextension/issue/545) Remove Zombie JS testing on Travis. + * [#518](https://github.com/jhedstrom/drupalextension/issue/518) Subcontexts are deprecated and will be removed in v4.1.0. +### Added + * [#527](https://github.com/jhedstrom/drupalextension/pull/527) Provide a step to check that a button is not in a region. + * [#543](https://github.com/jhedstrom/drupalextension/issue/543) Run gherkin-lint against feature files on Travis. + * [#544](https://github.com/jhedstrom/drupalextension/issue/544) Added a 'Contributing' section to the README. +### Fixed + * [#542](https://github.com/jhedstrom/drupalextension/pull/542) Fix issue with certain symfony 4 components being pulled in. + * [#537](https://github.com/jhedstrom/drupalextension/pull/537) Remove usage of deprecated `SnippetAcceptingContext`. + +## [4.0.0 beta2] 2018-12-19 +### Added + * [#514](https://github.com/jhedstrom/drupalextension/pull/514) Add a note about the need to remove the entries in behat.yml to use BEHAT_PARAMS. + * [#504](https://github.com/jhedstrom/drupalextension/issues/504) Added Gherkin linting. + * [#507](https://github.com/jhedstrom/drupalextension/pull/511) Test Drupal 7 on PHP 7. + * [#516](https://github.com/jhedstrom/drupalextension/pull/516) Warn users when message table is not correctly formatted. +### Changed + * [#510](https://github.com/jhedstrom/drupalextension/pull/510) Provide TagTrait to replace ScenarioTagTrait. + * [#512](https://github.com/jhedstrom/drupalextension/pull/512) Start testing on PHP 7.2. + * [#521](https://github.com/jhedstrom/drupalextension/pull/521) Updated tests to work with DrupalDriver string field handlers change. +### Fixed + * [#522](https://github.com/jhedstrom/drupalextension/pull/522) Composer path changed on travis. + * [#520](https://github.com/jhedstrom/drupalextension/pull/520) Removes patch applied to Features module that was committed. + * [#502](https://github.com/jhedstrom/drupalextension/pull/502) RawDrupalContext::loggedIn() can return false positive. + * [#507](https://github.com/jhedstrom/drupalextension/issues/507) PHP coding standards update. + * [#499](https://github.com/jhedstrom/drupalextension/pull/499) Fix config context backup strategy. ## [4.0.0 beta1] 2018-04-17 ### Added * [#479](https://github.com/jhedstrom/drupalextension/issues/479): Provide more verbose exception when AJAX fails. @@ -77,7 +113,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). * [#437](https://github.com/jhedstrom/drupalextension/pull/437): Radio button selector fix. * [#439](https://github.com/jhedstrom/drupalextension/pull/439): Symfony 3 compatibility follow-up fix. -[Unreleased]: https://github.com/jhedstrom/drupalextension/compare/v4.0.0beta1...HEAD +[Unreleased]: https://github.com/jhedstrom/drupalextension/compare/v4.0.1...HEAD +[4.0.1]: https://github.com/jhedstrom/drupalextension/compare/v4.0.0...v4.0.1 +[4.0.0]: https://github.com/jhedstrom/drupalextension/compare/v4.0.0rc1...v4.0.0 +[4.0.0 rc1]: https://github.com/jhedstrom/drupalextension/compare/v4.0.0beta2...v4.0.0rc1 +[4.0.0 beta2]: https://github.com/jhedstrom/drupalextension/compare/v4.0.0beta1...v4.0.0beta2 [4.0.0 beta1]: https://github.com/jhedstrom/drupalextension/compare/v4.0.0alpha4...v4.0.0beta1 [4.0.0 alpha4]:https://github.com/jhedstrom/drupalextension/compare/v4.0.0alpha3...v4.0.0alpha4 [4.0.0 alpha3]:https://github.com/jhedstrom/drupalextension/compare/v4.0.0alpha2...v4.0.0alpha3 diff --git a/README.md b/README.md index 6e9c1934..d44ddeb1 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ the [Full documentation](https://behat-drupal-extension.readthedocs.org) contexts: - Drupal\DrupalExtension\Context\DrupalContext extensions: - Behat\MinkExtension: + Drupal\MinkExtension: goutte: ~ base_url: http://example.org/ # Replace with your site's URL Drupal\DrupalExtension: @@ -98,6 +98,11 @@ the [Full documentation](https://behat-drupal-extension.readthedocs.org) See [CHANGELOG](CHANGELOG.md). +## Contributing + +Features and bug fixes are welcome! First-time contributors can jump in with the +issues tagged [good first issue](https://github.com/jhedstrom/drupalextension/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). + ### Backwards incompatible changes Starting with 3.3.0 Behat Drupal Extension depends on Behat 3.2.0 which diff --git a/behat.yml.dist b/behat.yml.dist index 000eaeb6..d12d882d 100644 --- a/behat.yml.dist +++ b/behat.yml.dist @@ -13,9 +13,7 @@ default: extensions: Drupal\MinkExtension: goutte: ~ - zombie: ~ base_url: http://127.0.0.1:8888/blackbox - javascript_session: zombie Drupal\DrupalExtension: blackbox: ~ region_map: @@ -44,7 +42,7 @@ drupal6: filters: tags: "@d6" extensions: - Behat\MinkExtension: + Drupal\MinkExtension: base_url: http://127.0.0.1:8888 Drupal\DrupalExtension: api_driver: "drupal" @@ -67,7 +65,7 @@ drupal7: filters: tags: "@d7" extensions: - Behat\MinkExtension: + Drupal\MinkExtension: base_url: http://127.0.0.1:8888 Drupal\DrupalExtension: api_driver: "drupal" @@ -92,7 +90,7 @@ drush: filters: tags: "@drushTest" extensions: - Behat\MinkExtension: + Drupal\MinkExtension: base_url: http://127.0.0.1:8888 Drupal\DrupalExtension: api_driver: "drush" @@ -119,7 +117,7 @@ drupal8: filters: tags: "@d8&&~@d8wip" extensions: - Behat\MinkExtension: + Drupal\MinkExtension: base_url: http://127.0.0.1:8888 Drupal\DrupalExtension: api_driver: "drupal" diff --git a/composer.json b/composer.json index fb603de5..7ca95fee 100644 --- a/composer.json +++ b/composer.json @@ -28,14 +28,14 @@ "behat/mink-goutte-driver": "~1.0", "behat/mink-selenium2-driver": "~1.1", "drupal/drupal-driver": "dev-186-backend-auth", + "symfony/browser-kit": "^3.4", "symfony/dependency-injection": "~3.0", - "symfony/event-dispatcher": "~3.0" + "symfony/translation": "^3.4" }, "require-dev": { "phpspec/phpspec": "~2.0 || ~4.0", - "behat/mink-zombie-driver": "^1.2", "jakub-onderka/php-parallel-lint": "^0.9.2", - "drupal/coder": "^8.2" + "drupal/coder": "~8.2.12" }, "scripts": { "test": [ @@ -43,6 +43,7 @@ "parallel-lint src spec features fixtures", "phpcs --standard=./phpcs-ruleset.xml -p", "phpcs --standard=./phpcs-drupal-ruleset.xml -p", + "npm test", "phpspec run -f pretty --no-interaction" ] }, @@ -56,7 +57,7 @@ }, "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "4.1.x-dev" } } } diff --git a/doc/_static/snippets/FeatureContext.php.inc b/doc/_static/snippets/FeatureContext.php.inc index 66d61362..838c51eb 100644 --- a/doc/_static/snippets/FeatureContext.php.inc +++ b/doc/_static/snippets/FeatureContext.php.inc @@ -2,14 +2,13 @@ use Behat\Behat\Tester\Exception\PendingException; use Drupal\DrupalExtension\Context\RawDrupalContext; -use Behat\Behat\Context\SnippetAcceptingContext; use Behat\Gherkin\Node\PyStringNode; use Behat\Gherkin\Node\TableNode; /** * Defines application features from the specific context. */ -class FeatureContext extends RawDrupalContext implements SnippetAcceptingContext { +class FeatureContext extends RawDrupalContext { /** * Initializes context. diff --git a/doc/blackbox.rst b/doc/blackbox.rst index f6a3477a..8da54136 100644 --- a/doc/blackbox.rst +++ b/doc/blackbox.rst @@ -89,6 +89,8 @@ customized the label visible to users, you can change that text as follows: Drupal\DrupalExtension: text: + login_url: "/user" + logout_url: "/user/logout" log_out: "Sign out" log_in: "Sign in" password_field: "Enter your password" diff --git a/doc/environment.rst b/doc/environment.rst index 81e5a523..86ce948d 100644 --- a/doc/environment.rst +++ b/doc/environment.rst @@ -11,7 +11,7 @@ If you intend to run your tests on different environments these settings should not be committed to ``behat.yml``. Instead they should be exported in an environment variable. Before running tests Behat will check the ``BEHAT_PARAMS`` environment variable and add these settings to the ones that are present in -``behat.yml``. This variable should contain a JSON object with your settings. +``behat.yml``. This variable should contain a JSON object with your settings. Example JSON object: @@ -19,7 +19,7 @@ Example JSON object: { "extensions": { - "Behat\\MinkExtension": { + "Drupal\\MinkExtension": { "base_url": "http://myproject.localhost" }, "Drupal\\DrupalExtension": { @@ -36,7 +36,49 @@ object into a single line and surround with single quotes: .. code-block:: bash - $ export BEHAT_PARAMS='{"extensions":{"Behat\\MinkExtension":{"base_url":"http://myproject.localhost"},"Drupal\\DrupalExtension":{"drupal":{"drupal_root":"/var/www/myproject"}}}}' + $ export BEHAT_PARAMS='{"extensions":{"Drupal\\MinkExtension":{"base_url":"http://myproject.localhost"},"Drupal\\DrupalExtension":{"drupal":{"drupal_root":"/var/www/myproject"}}}}' + +You must also remove (or comment out) the entries that you use in behat.yml for the values in BEHAT_PARAMS to take affect. + +.. code-block:: yml + + default: + suites: + default: + contexts: + - FeatureContext + - Drupal\DrupalExtension\Context\DrupalContext + - Drupal\DrupalExtension\Context\MinkContext + - Drupal\DrupalExtension\Context\MessageContext + - Drupal\DrupalExtension\Context\DrushContext + extensions: + Drupal\MinkExtension: + goutte: ~ + selenium2: ~ + # Must comment out for BEHAT_PARAMS to be effective. + # base_url: http://seven.l + Drupal\DrupalExtension: + # Anything used in BEHAT_PARAMS must be removed or commented. + # drupal: + # drupal_root: /var/www + # drush: + # alias: '@site' + blackbox: ~ + + # You can use profiles if you wish to allow users to run tests locally. + # Usage: + # bin/behat --profile=local + local: + extensions: + Drupal\MinkExtension: + base_url: 'localhost' + Drupal\DrupalExtension: + drush: + alias: '@self' + drupal: + drupal_root: '../web' + + There is also a `Drush extension `_ that can help you generate these environment variables. diff --git a/features/api.feature b/features/api.feature index db239b58..6c4c84f4 100644 --- a/features/api.feature +++ b/features/api.feature @@ -1,5 +1,5 @@ @api -Feature: DrupalContext +Feature: DrupalContext general testing In order to prove the Drupal context is working properly As a developer I need to use the step definitions of this context @@ -13,33 +13,19 @@ Feature: DrupalContext Then I should see the text "Member for" @drushTest @d7 - Scenario: Target links within table rows + Scenario: Target links within table rows for Drush and Drupal 7 Given I am logged in as a user with the "administrator" role When I am at "admin/structure/types" And I click "manage fields" in the "Article" row Then I should be on "admin/structure/types/manage/article/fields" And I should see text matching "Add new field" - @d8 - Scenario: Target links within table rows - Given I am logged in as a user with the "administrator" role - When I am at "admin/structure/types" - And I click "Manage fields" in the "Article" row - Then I should be on "admin/structure/types/manage/article/fields" - And I should see text matching "Add field" - @drushTest @d7 - Scenario: Find a heading in a region + Scenario: Find a heading in a region for Drupal 7 Given I am not logged in When I am on the homepage Then I should see the heading "User login" in the "left sidebar" region - @d8 - Scenario: Find a heading in a region - Given I am not logged in - When I am on the homepage - Then I should see the heading "Search" in the "left sidebar" region - @drushTest @d7 @d8 Scenario: Clear cache Given the cache has been cleared @@ -104,7 +90,7 @@ Feature: DrupalContext Then I should see the link "Joe User" @d7 - Scenario: Create users with roles + Scenario: Create users with roles for Drupal 7 Given users: | name | mail | roles | | Joe User | joe@example.com | administrator | @@ -114,17 +100,6 @@ Feature: DrupalContext Then I should see the text "administrator" in the "Joe User" row And I should not see the text "administrator" in the "Jane User" row - @d8 - Scenario: Create users with roles - Given users: - | name | mail | roles | - | Joe User | joe@example.com | administrator | - | Jane User | jane@example.com | | - And I am logged in as a user with the "administrator" role - When I visit "admin/people" - Then I should see the text "Administrator" in the "Joe User" row - And I should not see the text "administrator" in the "Jane User" row - @d7 @d8 Scenario: Login as a user created during this scenario Given users: @@ -140,7 +115,7 @@ Feature: DrupalContext Then I should see the heading "My tag" @d7 - Scenario: Create many terms + Scenario: Create many terms for Drupal 7 Given "tags" terms: | name | | Tag one | @@ -151,7 +126,7 @@ Feature: DrupalContext And I should see "Tag two" @d8 - Scenario: Create many terms + Scenario: Create many terms for Drupal 8 Given "tags" terms: | name | | Tag one | @@ -162,7 +137,7 @@ Feature: DrupalContext And I should see "Tag two" @d7 - Scenario: Create terms using vocabulary title rather than machine name. + Scenario: Create terms using vocabulary title rather than machine name for Drupal 7. Given "Tags" terms: | name | | Tag one | @@ -173,7 +148,7 @@ Feature: DrupalContext And I should see "Tag two" @d8 - Scenario: Create terms using vocabulary title rather than machine name. + Scenario: Create terms using vocabulary title rather than machine name for Drupal 8. Given "Tags" terms: | name | | Tag one | @@ -248,7 +223,7 @@ Feature: DrupalContext Then I should see the link "Joe User" @d7 - Scenario: Term hooks are functioning + Scenario: Term hooks are functioning for Drupal 7 Given "tags" terms: | Label | | Tag one | @@ -259,7 +234,7 @@ Feature: DrupalContext And I should see "Tag two" @d8 - Scenario: Term hooks are functioning + Scenario: Term hooks are functioning for Drupal 8 Given "tags" terms: | Label | | Tag one | diff --git a/features/api_background.feature b/features/api_background.feature index 3d911995..4d232987 100644 --- a/features/api_background.feature +++ b/features/api_background.feature @@ -1,5 +1,5 @@ @d6 @d7 @d8 @api -Feature: DrupalContext +Feature: DrupalContext with background steps Test DrupalContext in combination with Backgrounds Background: @@ -8,12 +8,12 @@ Feature: DrupalContext | Tag one | | Tag two | - Given users: + And users: | name | | User one | | User two | - Given "article" content: + And "article" content: | title | | Node one | | Node two | diff --git a/features/blackbox.feature b/features/blackbox.feature index 62c6b729..06246470 100644 --- a/features/blackbox.feature +++ b/features/blackbox.feature @@ -41,6 +41,10 @@ Feature: Test DrupalContext Given I am on the homepage Then I should see the "Search" button in the "navigation" + Scenario: Button not in region + Given I am on the homepage + Then I should not see the "Search" button in the "right header" region + Scenario: Find an element in a region Given I am on the homepage Then I should see the "h1" element in the "left header" @@ -68,21 +72,21 @@ Feature: Test DrupalContext And I should see the "div" element with the "class" attribute set to "class3" in the "left header" region Scenario: Error messages - Given I am on "user.html" - When I press "Log in" - Then I should see the error message "Password field is required" - And I should not see the error message "Sorry, unrecognized username or password" - And I should see the following error messages: - | error messages | - | Username or email field is required. | - | Password field is required | - And I should not see the following error messages: - | error messages | - | Sorry, unrecognized username or password | - | Unable to send e-mail. Contact the site administrator if the problem persists | - - @javascript - Scenario: Zombie driver is functional - Given I am on the homepage - When I click "Download & Extend" - Then I should see the link "Distributions" + Given I am on "user.html" + When I press "Log in" + Then I should see the error message "Password field is required" + And I should not see the error message "Sorry, unrecognized username or password" + And I should see the following error messages: + | error messages | + | Username or email field is required. | + | Password field is required | + And I should not see the following error messages: + | error messages | + | Sorry, unrecognized username or password | + | Unable to send e-mail. Contact the site administrator if the problem persists | + + @scenariotag + Scenario: Check tags on feature and scenario + Then the "scenariotag" tag should be present + And the "blackbox" tag should be present + But the "nonexisting" tag should not be present diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php index 4546c897..cf4bd443 100644 --- a/features/bootstrap/FeatureContext.php +++ b/features/bootstrap/FeatureContext.php @@ -5,6 +5,7 @@ use Drupal\DrupalExtension\Context\RawDrupalContext; use Drupal\DrupalExtension\Hook\Scope\BeforeNodeCreateScope; use Drupal\DrupalExtension\Hook\Scope\EntityScope; +use Drupal\DrupalExtension\TagTrait; use Symfony\Component\Process\PhpExecutableFinder; use Symfony\Component\Process\Process; @@ -16,6 +17,9 @@ * conflicts. */ class FeatureContext extends RawDrupalContext { + + use TagTrait; + /** * Hook into node creation to test `@beforeNodeCreate` * @@ -456,6 +460,36 @@ public function itShouldFail($success) } } + /** + * Checks if the current scenario or feature has the given tag. + * + * @Then the :tag tag should be present + * + * @param string $tag + * The tag to check. + */ + public function shouldHaveTag($tag) + { + if (!$this->hasTag($tag)) { + throw new \Exception("Expected tag $tag was not found in the scenario or feature."); + } + } + + /** + * Checks if the current scenario or feature does not have the given tag. + * + * @Then the :tag tag should not be present + * + * @param string $tag + * The tag to check. + */ + public function shouldNotHaveTag($tag) + { + if ($this->hasTag($tag)) { + throw new \Exception("Expected tag $tag was found in the scenario or feature."); + } + } + private function getExitCode() { return $this->process->getExitCode(); diff --git a/features/d6.feature b/features/d6.feature index b79e7e1e..5ca7933e 100644 --- a/features/d6.feature +++ b/features/d6.feature @@ -3,27 +3,23 @@ Feature: Environment check Scenario: Frontpage Given I am not logged in - And I am on the homepage + And I am on the homepage Then I should see "User login" Scenario: assertAnonymousUser Given I am an anonymous user - @api Scenario: assertAuthenticatedByRole Given I am logged in as a user with the "authenticated" role - @api Scenario: assertAuthenticatedByRoleWithGivenFields Given I am logged in as a user with the "authenticated" role and I have the following fields: | name | test | - @api Scenario: createNode Given I am viewing a story with the title "test" Then I should see "test" - @api Scenario: createNodes Given article content: | title | author | status | created | @@ -31,12 +27,10 @@ Feature: Environment check When I am viewing a content with the title "My title" Then I should see "My title" - @api Scenario: createTerm Given I am viewing a tags term with the name "example tag" Then I should see "example tag" - @api Scenario: createUsers Given I am logged in as a user with the "administer users" permission And users: @@ -45,9 +39,8 @@ Feature: Environment check | user bar | baz@bar.com | When I visit "admin/user/user" Then I should see "user foo" - And I should see "user bar" + And I should see "user bar" - @api Scenario: create node with terms. Given tags terms: | name | diff --git a/features/d8.feature b/features/d8.feature index 6cefd974..96d94bb5 100644 --- a/features/d8.feature +++ b/features/d8.feature @@ -1,22 +1,22 @@ @d8 @api -Feature: DrupalContext +Feature: DrupalContext for Drupal 8 In order to prove the Drupal context is working properly for Drupal 8 As a developer I need to use the step definitions of this context - Scenario: Create and log in as a user + Scenario: Create and log in as a user for Drupal 8 Given I am logged in as a user with the "authenticated user" role When I click "My account" Then I should see the text "Member for" - Scenario: Target links within table rows + Scenario: Target links within table rows for Drupal 8 Given I am logged in as a user with the "administrator" role When I am at "admin/structure/types" And I click "Manage fields" in the "Article" row Then I should be on "admin/structure/types/manage/article/fields" And I should see the link "Add field" - Scenario: Create users with roles + Scenario: Create users with roles for Drupal 8 Given users: | name | mail | roles | | Joe User | joe@example.com | Administrator | @@ -26,7 +26,7 @@ Feature: DrupalContext Then I should see the text "Administrator" in the "Joe User" row And I should not see the text "administrator" in the "Jane Doe" row - Scenario: Find a heading in a region + Scenario: Find a heading in a region for Drupal 8 Given I am not logged in When I am on the homepage Then I should see the heading "Search" in the "left sidebar" region diff --git a/features/drush.feature b/features/drush.feature index ccc79cff..f64eed98 100644 --- a/features/drush.feature +++ b/features/drush.feature @@ -7,20 +7,22 @@ Feature: Drush-specific steps Scenario: drush command with text matching: drush output correct status Given I run drush "st" Then drush output should contain "Drupal version" - Then drush output should contain "Site URI" - Then drush output should match "/.*Site\sURI\s+:.*/" - Then drush output should contain "Database driver" - Then drush output should contain "Successful" - Then drush output should not contain "NonExistantWord" + And drush output should contain "Site URI" + And drush output should match "/.*Site\sURI\s+:.*/" + And drush output should contain "Database driver" + And drush output should contain "Successful" + And drush output should not contain "NonExistantWord" Scenario: drush command with arguments: re-enable toolbar Given I run drush "en" "toolbar -y" - And I run drush "en" "toolbar -y" + And I run drush "en" "toolbar -y" Then drush output should contain "toolbar is already enabled." - Scenario: Create and view a node with fields using the Drush driver - Given I am viewing an "Article": - | title | My article with fields! | - | body | A placeholder | - Then I should see the heading "My article with fields!" - And I should see the text "A placeholder" +# @todo Re-enable behat drush endpoint testing. +# @see https://github.com/jhedstrom/drupalextension/issues/458 +# Scenario: Create and view a node with fields using the Drush driver +# Given I am viewing an "Article": +# | title | My article with fields! | +# | body | A placeholder | +# Then I should see the heading "My article with fields!" +# And I should see the text "A placeholder" diff --git a/features/field_handlers.feature b/features/field_handlers.feature index da8448cf..b0f4b539 100644 --- a/features/field_handlers.feature +++ b/features/field_handlers.feature @@ -19,7 +19,7 @@ Feature: FieldHandlers | field_post_reference | Page one, Page two | | field_post_date | 2015-02-08 17:45:00 | | field_post_links | Link 1 - http://example.com, Link 2 - http://example.com | - | field_post_select | One, Two | + | field_post_select | Select value one, Select value two | | field_post_address | country: BE - locality: Brussel - thoroughfare: Louisalaan 1 - postal_code: 1000 | Then I should see "Post title" And I should see "PLACEHOLDER BODY" @@ -28,8 +28,9 @@ Feature: FieldHandlers And I should see "Sunday, February 8, 2015" And I should see the link "Link 1" And I should see the link "Link 2" - And I should see "One" - And I should see "Two" + And I should see "Select value one" + And I should see "Select value two" + And I should not see "Select value three" And I should see "Belgium" And I should see "Brussel" And I should see "1000" @@ -52,15 +53,15 @@ Feature: FieldHandlers | reference | Page one, Page two | | date | 2015-02-08 17:45:00 | | links | Link 1 - http://example.com, Link 2 - http://example.com | - | select | One, Two | + | select | Select value one, Select value two | | address | country: BE - locality: Brussel - thoroughfare: Louisalaan 1 - postal_code: 1000 | Then I should see "Page one" And I should see "Page two" And I should see "Sunday, February 8, 2015" And I should see the link "Link 1" And I should see the link "Link 2" - And I should see "One" - And I should see "Two" + And I should see "Select value one" + And I should see "Select value two" And I should see "Belgium" And I should see "Brussel" And I should see "1000" @@ -134,7 +135,7 @@ Feature: FieldHandlers But I should not see the link "Tag three" And I should see "Page one" And I should see "Page two" - But I should not see "Page three" + And I should not see "Page three" And I should see "Belgium" And I should see "Brussel" And I should see "1000" diff --git a/features/i18n/es/blackbox.feature b/features/i18n/es/blackbox.feature index b265f4b4..b73006a6 100644 --- a/features/i18n/es/blackbox.feature +++ b/features/i18n/es/blackbox.feature @@ -98,9 +98,3 @@ Característica: Test DrupalContext | error messages | | Sorry, unrecognized username or password | | Unable to send e-mail. Contact the site administrator if the problem persists | - - @javascript - Escenario: El driver Zombie funciona adecuadamente - Dado estoy en la página de inicio - Cuando hago click en "Download & Extend" - Entonces debo ver el enlace "Distributions" diff --git a/features/mail.feature b/features/mail.feature index 4890ee30..53c1f24b 100644 --- a/features/mail.feature +++ b/features/mail.feature @@ -49,7 +49,6 @@ Feature: MailContext | subject | | test 1 | - Scenario: No mail is sent Then no mail has been sent diff --git a/features/messages.feature b/features/messages.feature index 802bbd7d..b7cfd1e4 100644 --- a/features/messages.feature +++ b/features/messages.feature @@ -7,13 +7,5 @@ Feature: Ensure that messages are working properly on local installs Given I am on "/user/login" When I fill in "a fake user" for "Username" And I fill in "a fake password" for "Password" - When I press "Log in" - Then I should see the error message "Unrecognized username or password" - - @javascript - Scenario: JS messages - Given I am on "/user/login" - When I fill in "a fake user" for "Username" - And I fill in "a fake password" for "Password" - When I press "Log in" + And I press "Log in" Then I should see the error message "Unrecognized username or password" diff --git a/features/subcontexts/find.feature b/features/subcontexts/find.feature index 91af75f0..3e71042b 100644 --- a/features/subcontexts/find.feature +++ b/features/subcontexts/find.feature @@ -43,7 +43,7 @@ Feature: Ability to find Drupal sub-contexts default: contexts: [Drupal\DrupalExtension\Context\DrupalContext] extensions: - Behat\MinkExtension: + Drupal\MinkExtension: goutte: ~ selenium2: ~ base_url: http://drupal.org @@ -54,15 +54,15 @@ Feature: Ability to find Drupal sub-contexts """ Scenario: Step-definitions in sub-contexts are available - When I run "behat --no-colors -dl" - Then the output should contain: + When I run "behat --no-colors -dl" + Then the output should contain: """ Then /^I should have a subcontext definition$/ """ - Scenario: Subcontext can be instantiated - When I run "behat --no-colors" - Then the output should contain: - """ - TODO: write pending definition - """ + Scenario: Subcontext can be instantiated + When I run "behat --no-colors" + Then the output should contain: + """ + TODO: write pending definition + """ diff --git a/fixtures/drupal7/modules/behat_test/behat_test.features.field_base.inc b/fixtures/drupal7/modules/behat_test/behat_test.features.field_base.inc index 1e39d628..23ab188f 100644 --- a/fixtures/drupal7/modules/behat_test/behat_test.features.field_base.inc +++ b/fixtures/drupal7/modules/behat_test/behat_test.features.field_base.inc @@ -193,9 +193,9 @@ function behat_test_field_default_field_bases() { 'module' => 'list', 'settings' => array( 'allowed_values' => array( - 1 => 'One', - 2 => 'Two', - 3 => 'Three', + 1 => 'Select value one', + 2 => 'Select value two', + 3 => 'Select value three', ), 'allowed_values_function' => '', ), diff --git a/fixtures/drupal8/modules/behat_test/config/install/field.storage.node.field_post_select.yml b/fixtures/drupal8/modules/behat_test/config/install/field.storage.node.field_post_select.yml index 415c6e13..35f51e7b 100644 --- a/fixtures/drupal8/modules/behat_test/config/install/field.storage.node.field_post_select.yml +++ b/fixtures/drupal8/modules/behat_test/config/install/field.storage.node.field_post_select.yml @@ -12,17 +12,17 @@ settings: allowed_values: - value: '1' - label: One + label: Select value one - value: '2' - label: Two + label: Select value two - value: '3' - label: Three + label: Select value three allowed_values_function: '' module: options locked: false -cardinality: 1 +cardinality: -1 translatable: true indexes: { } persist_with_no_fields: false diff --git a/package.json b/package.json index 20df6400..f875eb3d 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,9 @@ { "devDependencies": { - "zombie": "^2.5" + "gherkin-lint": "^2.12.0" + }, + "scripts": { + "gherkin-lint": "gherkin-lint features", + "test": "npm run gherkin-lint" } } diff --git a/src/Drupal/DrupalExtension/Context/ConfigContext.php b/src/Drupal/DrupalExtension/Context/ConfigContext.php index e858fee7..e302093e 100644 --- a/src/Drupal/DrupalExtension/Context/ConfigContext.php +++ b/src/Drupal/DrupalExtension/Context/ConfigContext.php @@ -107,6 +107,13 @@ public function setConfig($name, $key, $value) { $backup = $this->getDriver()->configGet($name, $key); $this->getDriver()->configSet($name, $key, $value); - $this->config[$name][$key] = $backup; + if (!array_key_exists($name, $this->config)) { + $this->config[$name][$key] = $backup; + return; + } + + if (!array_key_exists($key, $this->config[$name])) { + $this->config[$name][$key] = $backup; + } } } diff --git a/src/Drupal/DrupalExtension/Context/ContextClass/ClassGenerator.php b/src/Drupal/DrupalExtension/Context/ContextClass/ClassGenerator.php index 50f5611e..b61e3734 100644 --- a/src/Drupal/DrupalExtension/Context/ContextClass/ClassGenerator.php +++ b/src/Drupal/DrupalExtension/Context/ContextClass/ClassGenerator.php @@ -18,7 +18,6 @@ class ClassGenerator implements BehatClassGenerator parameters['subcontexts']['paths'])) { + if (!empty($this->parameters['subcontexts']['paths'])) { + @trigger_error( + 'The `subcontexts.paths` parameter is deprecated in Drupal Behat Extension 4.0.0 and will be removed in 4.1.0. Normal Behat contexts should be used instead and loaded via behat.yml.', + E_USER_DEPRECATED + ); + } $paths = array_merge($paths, $this->parameters['subcontexts']['paths']); } @@ -173,7 +180,8 @@ private function findSubContextClasses() $classes = get_declared_classes(); foreach ($classes as $class) { $reflect = new \ReflectionClass($class); - if (!$reflect->isAbstract() && $reflect->implementsInterface('Drupal\DrupalExtension\Context\DrupalSubContextInterface')) { + if (!$reflect->isAbstract() && $reflect->implementsInterface(DrupalSubContextInterface::class)) { + @trigger_error('Sub-contexts are deprecated in Drupal Behat Extension 4.0.0 and will be removed in 4.1.0. Class ' . $class . ' is a subcontext. This logic should be moved to a normal Behat context and loaded via behat.yml.', E_USER_DEPRECATED); $class_names[] = $class; } } diff --git a/src/Drupal/DrupalExtension/Context/MarkupContext.php b/src/Drupal/DrupalExtension/Context/MarkupContext.php index 08179f7b..fb6afc2c 100644 --- a/src/Drupal/DrupalExtension/Context/MarkupContext.php +++ b/src/Drupal/DrupalExtension/Context/MarkupContext.php @@ -58,6 +58,30 @@ public function assertRegionButton($button, $region) } } + /** + * Asserts that a button does not exists in a region. + * + * @Then I should not see the button :button in the :region( region) + * @Then I should not see the :button button in the :region( region) + * + * @param $button + * string The id|name|title|alt|value of the button + * @param $region + * string The region in which the button should not be found + * + * @throws \Exception + * If region is not found or the button is found within the region. + */ + public function assertNotRegionButton($button, $region) + { + $regionObj = $this->getRegion($region); + + $buttonObj = $regionObj->findButton($button); + if (!empty($buttonObj)) { + throw new \Exception(sprintf("The button '%s' was found in the region '%s' on the page %s but should not", $button, $region, $this->getSession()->getCurrentUrl())); + } + } + /** * @Then I( should) see the :tag element in the :region( region) */ diff --git a/src/Drupal/DrupalExtension/Context/MessageContext.php b/src/Drupal/DrupalExtension/Context/MessageContext.php index 9b10c75a..1d41cff8 100644 --- a/src/Drupal/DrupalExtension/Context/MessageContext.php +++ b/src/Drupal/DrupalExtension/Context/MessageContext.php @@ -41,14 +41,17 @@ public function assertErrorVisible($message) /** * Checks if the current page contains the given set of error messages * - * @param $messages - * array An array of texts to be checked + * @param array $messages + * An array of texts to be checked. The first row should consist of the + * string "Error messages". * * @Then I should see the following error message(s): */ public function assertMultipleErrors(TableNode $messages) { + $this->assertValidMessageTable($messages, 'error messages'); foreach ($messages->getHash() as $key => $value) { + $value = array_change_key_case($value); $message = trim($value['error messages']); $this->assertErrorVisible($message); } @@ -74,14 +77,17 @@ public function assertNotErrorVisible($message) /** * Checks if the current page does not contain the given set error messages * - * @param $messages - * array An array of texts to be checked + * @param array $messages + * An array of texts to be checked. The first row should consist of the + * string "Error messages". * * @Then I should not see the following error messages: */ public function assertNotMultipleErrors(TableNode $messages) { + $this->assertValidMessageTable($messages, 'error messages'); foreach ($messages->getHash() as $key => $value) { + $value = array_change_key_case($value); $message = trim($value['error messages']); $this->assertNotErrorVisible($message); } @@ -108,14 +114,17 @@ public function assertSuccessMessage($message) /** * Checks if the current page contains the given set of success messages * - * @param $message - * array An array of texts to be checked + * @param array $message + * An array of texts to be checked. The first row should consist of the + * string "Success messages". * * @Then I should see the following success messages: */ public function assertMultipleSuccessMessage(TableNode $messages) { + $this->assertValidMessageTable($messages, 'success messages'); foreach ($messages->getHash() as $key => $value) { + $value = array_change_key_case($value); $message = trim($value['success messages']); $this->assertSuccessMessage($message); } @@ -141,14 +150,17 @@ public function assertNotSuccessMessage($message) /** * Checks if the current page does not contain the given set of success messages * - * @param $message - * array An array of texts to be checked + * @param array $message + * An array of texts to be checked. The first row should consist of the + * string "Success messages". * * @Then I should not see the following success messages: */ public function assertNotMultipleSuccessMessage(TableNode $messages) { + $this->assertValidMessageTable($messages, 'success messages'); foreach ($messages->getHash() as $key => $value) { + $value = array_change_key_case($value); $message = trim($value['success messages']); $this->assertNotSuccessMessage($message); } @@ -175,14 +187,17 @@ public function assertWarningMessage($message) /** * Checks if the current page contains the given set of warning messages * - * @param $message - * array An array of texts to be checked + * @param array $message + * An array of texts to be checked. The first row should consist of the + * string "Warning messages". * * @Then I should see the following warning messages: */ public function assertMultipleWarningMessage(TableNode $messages) { + $this->assertValidMessageTable($messages, 'warning messages'); foreach ($messages->getHash() as $key => $value) { + $value = array_change_key_case($value); $message = trim($value['warning messages']); $this->assertWarningMessage($message); } @@ -208,14 +223,17 @@ public function assertNotWarningMessage($message) /** * Checks if the current page does not contain the given set of warning messages * - * @param $message - * array An array of texts to be checked + * @param array $message + * An array of texts to be checked. The first row should consist of the + * string "Warning messages". * * @Then I should not see the following warning messages: */ public function assertNotMultipleWarningMessage(TableNode $messages) { + $this->assertValidMessageTable($messages, 'warning messages'); foreach ($messages->getHash() as $key => $value) { + $value = array_change_key_case($value); $message = trim($value['warning messages']); $this->assertNotWarningMessage($message); } @@ -256,6 +274,35 @@ public function assertNotMessage($message) ); } + /** + * Checks whether the given list of messages is valid. + * + * This checks whether the list has only one column and has the correct + * header. + * + * @param \Behat\Gherkin\Node\TableNode $messages + * The list of messages. + * @param string $expected_header + * The header that should be present in the list. + */ + protected function assertValidMessageTable(TableNode $messages, $expected_header) + { + // Check that the table only contains a single column. + $header_row = $messages->getRow(0); + + $column_count = count($header_row); + if ($column_count != 1) { + throw new \RuntimeException("The list of $expected_header should only contain 1 column. It has $column_count columns."); + } + + // Check that the correct header is used. + $actual_header = reset($header_row); + if (strtolower(trim($actual_header)) !== $expected_header) { + $capitalized_header = ucfirst($expected_header); + throw new \RuntimeException("The list of $expected_header should have the header '$capitalized_header'."); + } + } + /** * Internal callback to check for a specific message in a given context. * diff --git a/src/Drupal/DrupalExtension/Context/MinkContext.php b/src/Drupal/DrupalExtension/Context/MinkContext.php index 69b15725..dc7200de 100644 --- a/src/Drupal/DrupalExtension/Context/MinkContext.php +++ b/src/Drupal/DrupalExtension/Context/MinkContext.php @@ -5,7 +5,7 @@ use Behat\Behat\Context\TranslatableContext; use Behat\Mink\Exception\UnsupportedDriverActionException; use Behat\MinkExtension\Context\MinkContext as MinkExtension; -use Drupal\DrupalExtension\ScenarioTagTrait; +use Drupal\DrupalExtension\TagTrait; /** * Extensions to the Mink Extension. @@ -13,7 +13,7 @@ class MinkContext extends MinkExtension implements TranslatableContext { - use ScenarioTagTrait; + use TagTrait; /** * Returns list of definition translation resources paths. @@ -95,8 +95,11 @@ public function assertEnterField($field, $value) public function beforeJavascriptStep($event) { /** @var \Behat\Behat\Hook\Scope\BeforeStepScope $event */ - $tags = $this->getCurrentScenarioTags($event); - if (!in_array('javascript', $tags)) { + // Make sure the feature is registered in case this hook fires before + // ::registerFeature() which is also a @BeforeStep. Behat doesn't + // support ordering hooks. + $this->registerFeature($event); + if (!$this->hasTag('javascript')) { return; } $text = $event->getStep()->getText(); @@ -113,8 +116,7 @@ public function beforeJavascriptStep($event) public function afterJavascriptStep($event) { /** @var \Behat\Behat\Hook\Scope\BeforeStepScope $event */ - $tags = $this->getCurrentScenarioTags($event); - if (!in_array('javascript', $tags)) { + if (!$this->hasTag('javascript')) { return; } $text = $event->getStep()->getText(); @@ -150,8 +152,12 @@ function isAjaxing(instance) { ); }()); JS; - $result = $this->getSession()->wait(1000 * $this->getMinkParameter('ajax_timeout'), $condition); + $ajax_timeout = $this->getMinkParameter('ajax_timeout'); + $result = $this->getSession()->wait(1000 * $ajax_timeout, $condition); if (!$result) { + if ($ajax_timeout === null) { + throw new \Exception('No AJAX timeout has been defined. Please verify that "Drupal\MinkExtension" is configured in behat.yml (and not "Behat\MinkExtension").'); + } if ($event) { /** @var \Behat\Behat\Hook\Scope\BeforeStepScope $event */ $event_data = ' ' . json_encode([ diff --git a/src/Drupal/DrupalExtension/Context/RawDrupalContext.php b/src/Drupal/DrupalExtension/Context/RawDrupalContext.php index 3d2593e4..b8b9ae18 100644 --- a/src/Drupal/DrupalExtension/Context/RawDrupalContext.php +++ b/src/Drupal/DrupalExtension/Context/RawDrupalContext.php @@ -404,17 +404,17 @@ public function parseEntityFields($entity_type, \stdClass $entity) // Reset the multicolumn field if the field name does not contain a column. if (strpos($field, ':') === false) { $multicolumn_field = ''; - } // Start tracking a new multicolumn field if the field name contains a ':' - // which is preceded by at least 1 character. - elseif (strpos($field, ':', 1) !== false) { + } elseif (strpos($field, ':', 1) !== false) { + // Start tracking a new multicolumn field if the field name contains a ':' + // which is preceded by at least 1 character. list($multicolumn_field, $multicolumn_column) = explode(':', $field); - } // If a field name starts with a ':' but we are not yet tracking a - // multicolumn field we don't know to which field this belongs. - elseif (empty($multicolumn_field)) { + } elseif (empty($multicolumn_field)) { + // If a field name starts with a ':' but we are not yet tracking a + // multicolumn field we don't know to which field this belongs. throw new \Exception('Field name missing for ' . $field); - } // Update the column name if the field name starts with a ':' and we are - // already tracking a multicolumn field. - else { + } else { + // Update the column name if the field name starts with a ':' and we are + // already tracking a multicolumn field. $multicolumn_column = substr($field, 1); } diff --git a/src/Drupal/DrupalExtension/FeatureTrait.php b/src/Drupal/DrupalExtension/FeatureTrait.php new file mode 100644 index 00000000..13b500ec --- /dev/null +++ b/src/Drupal/DrupalExtension/FeatureTrait.php @@ -0,0 +1,46 @@ +currentFeature = $scope->getFeature(); + } + + /** + * @return \Behat\Gherkin\Node\FeatureNode + */ + protected function getFeature() + { + return $this->currentFeature; + } +} diff --git a/src/Drupal/DrupalExtension/Manager/DrupalAuthenticationManager.php b/src/Drupal/DrupalExtension/Manager/DrupalAuthenticationManager.php index fd28f86b..abe85676 100644 --- a/src/Drupal/DrupalExtension/Manager/DrupalAuthenticationManager.php +++ b/src/Drupal/DrupalExtension/Manager/DrupalAuthenticationManager.php @@ -60,7 +60,7 @@ public function logIn(\stdClass $user) // Ensure we aren't already logged in. $this->fastLogout(); - $this->getSession()->visit($this->locatePath('/user')); + $this->getSession()->visit($this->locatePath($this->getDrupalText('login_url'))); $element = $this->getSession()->getPage(); $element->fillField($this->getDrupalText('username_field'), $user->name); $element->fillField($this->getDrupalText('password_field'), $user->pass); @@ -93,7 +93,7 @@ public function logIn(\stdClass $user) */ public function logout() { - $this->getSession()->visit($this->locatePath('/user/logout')); + $this->getSession()->visit($this->locatePath($this->getDrupalText('logout_url'))); $this->userManager->setCurrentUser(false); // Log the user out on the backend if possible. @@ -127,8 +127,9 @@ public function loggedIn() } // Some themes do not add that class to the body, so lets check if the - // login form is displayed on /user/login. - $session->visit($this->locatePath('/user/login')); + // login form is displayed on the page with the login form (defaults to + // /user/login) + $session->visit($this->locatePath($this->getDrupalText('login_url'))); if ($page->has('css', $this->getDrupalSelector('login_form_selector'))) { $this->fastLogout(); return false; diff --git a/src/Drupal/DrupalExtension/ScenarioTagTrait.php b/src/Drupal/DrupalExtension/ScenarioTagTrait.php index a54b0f05..5420c9b0 100644 --- a/src/Drupal/DrupalExtension/ScenarioTagTrait.php +++ b/src/Drupal/DrupalExtension/ScenarioTagTrait.php @@ -14,7 +14,7 @@ * * The solution is documented in this issue: https://github.com/Behat/Behat/issues/703#issuecomment-86687563 * - * @package Drupal\DrupalExtension + * @deprecated Use \Drupal\DrupalExtension\TagTrait instead. */ trait ScenarioTagTrait { diff --git a/src/Drupal/DrupalExtension/ScenarioTrait.php b/src/Drupal/DrupalExtension/ScenarioTrait.php new file mode 100644 index 00000000..4979e45b --- /dev/null +++ b/src/Drupal/DrupalExtension/ScenarioTrait.php @@ -0,0 +1,43 @@ +currentScenario = $scope->getScenario(); + } + + /** + * @return \Behat\Gherkin\Node\ScenarioInterface + */ + protected function getScenario() + { + return $this->currentScenario; + } +} diff --git a/src/Drupal/DrupalExtension/ServiceContainer/DrupalExtension.php b/src/Drupal/DrupalExtension/ServiceContainer/DrupalExtension.php index f711e782..98e78ca6 100644 --- a/src/Drupal/DrupalExtension/ServiceContainer/DrupalExtension.php +++ b/src/Drupal/DrupalExtension/ServiceContainer/DrupalExtension.php @@ -116,6 +116,8 @@ public function configure(ArrayNodeDefinition $builder) arrayNode('text')-> info( 'Text strings, such as Log out or the Username field can be altered via behat.yml if they vary from the default values.' . PHP_EOL + . ' login_url: "/user"' . PHP_EOL + . ' logout_url: "/user/logout"' . PHP_EOL . ' log_out: "Sign out"' . PHP_EOL . ' log_in: "Sign in"' . PHP_EOL . ' password_field: "Enter your password"' . PHP_EOL @@ -123,6 +125,12 @@ public function configure(ArrayNodeDefinition $builder) )-> addDefaultsIfNotSet()-> children()-> + scalarNode('login_url')-> + defaultValue('/user')-> + end()-> + scalarNode('logout_url')-> + defaultValue('/user/logout')-> + end()-> scalarNode('log_in')-> defaultValue('Log in')-> end()-> @@ -145,7 +153,7 @@ public function configure(ArrayNodeDefinition $builder) scalarNode('success_message_selector')->end()-> scalarNode('warning_message_selector')->end()-> scalarNode('login_form_selector')-> - defaultValue('form#user-login')-> + defaultValue('form#user-login,form#user-login-form')-> end()-> scalarNode('logged_in_selector')-> defaultValue('body.logged-in,body.user-logged-in')-> diff --git a/src/Drupal/DrupalExtension/TagTrait.php b/src/Drupal/DrupalExtension/TagTrait.php new file mode 100644 index 00000000..b703459d --- /dev/null +++ b/src/Drupal/DrupalExtension/TagTrait.php @@ -0,0 +1,35 @@ +getFeature()->getTags(); + $scenarioTags = $this->getScenario()->getTags(); + return array_unique(array_merge($featureTags, $scenarioTags)); + } + + /** + * Checks whether the current scenario or feature has the given tag. + * + * @param string $tag + * + * @return bool + */ + protected function hasTag($tag) + { + return in_array($tag, $this->getTags()); + } +}