v5.3.0
Highlights
- Converted standard Behat annotations to PHP 8 attributes.
- Added comprehensive test coverage for all step definitions using positive and negative tests.
- Added a documentation generator for step definitions to allow humans and AI agents to easily discover available steps and their usage.
- Removed Drupal 6 and 7 driver support, including all related code and fixtures.
Behavioural changes
Behat annotations converted to PHP 8 attributes
All standard Behat annotations (@Given, @When, @Then, @BeforeScenario,
@AfterScenario, etc.) in src/ have been converted to PHP 8 attributes. The
old annotation syntax is still supported by Behat, so this is not a breaking
change for consumers.
Warning
If you extend any of the bundled context classes and override step or hook
methods, you must switch your overrides from docblock annotations (@Given,
@When, @Then, @BeforeScenario, etc.) to PHP 8 attributes (#[Given],
#[When], #[Then], #[BeforeScenario], etc.). Behat resolves both the
parent attribute and the child annotation independently, which causes a
RedundantStepException for step definitions and duplicate execution for
hooks. To safely override a method, either re-declare the step/hook using
only the PHP 8 attribute on the child (and remove it from the parent by not
registering the parent context), or override the method without any
annotation or attribute to inherit the parent's definition.
ConfigContext::setConfig() is now protected
The setConfig() method visibility was changed from public to protected.
If your project calls ConfigContext::setConfig() from outside the class, you
will need to adjust your code.
Role-based login always creates a fresh user
The loggedInWithRole() method now always creates a new user instead of reusing
a previously created user with the same role. This prevents stale login state
from leaking between scenarios.
Link assertion separated from click action
The link existence assertion has been separated from the click action. Previously,
clicking a non-existent link would throw a generic element-not-found exception.
Now the assertion and click are distinct operations with clearer error messages.
Parent term resolution in termCreate()
termCreate() now resolves parent terms by name. When creating a taxonomy term
with a parent field value, the extension will look up the parent term by name
and use its term ID. Validation ensures the parent term exists before creation.
Entity field validation in parseEntityFields()
parseEntityFields() now validates that all fields specified in a Behat table
row actually exist on the entity type. Previously, non-existent fields were
silently ignored. Now a \RuntimeException is thrown listing the invalid fields.
Table header validation in assertValidMessageTable()
The error message when a message table has invalid headers has been improved to
show the expected headers and what was actually provided.
Double-quote escaping in entity reference values
Entity reference values containing commas can now be wrapped in double quotes to
prevent the compound separator from splitting them. For example:
"Term with, comma" will be treated as a single value.
Configuration changes
behat.dist.yml provided
A new behat.dist.yml file is included with all configuration values
pre-filled, serving as a reference for available options and their defaults.
New features
Custom DocumentElement
A custom DocumentElement class has been added to remove the DrupalFinder
dependency from extension boot. This simplifies the extension initialisation
and reduces external dependencies.
Steps documentation generator
A new documentation generator (scripts/docs.php) produces a summary of all
available step definitions. Output can be posted to CI as a summary.
Removed
Drupal 6 and 7 driver support dropped
All Drupal 6 and 7 driver support has been removed, including:
- D6/D7-specific driver code and conditionals (#768)
- Remaining D6/D7 support remnants, fixtures, and references (#760)
Deprecated APIs removed
ScenarioTagTrait— removed entirely, useTagTraitinstead.RawDrupalContextmagic property accessors — removed. Use the explicit
getter/setter methods (getUserManager(),getAuthenticationManager(), etc.).
Bug fixes
AJAX wait no longer crashes on unstarted session
iWaitForAjaxToFinish() now checks $this->getSession()->isStarted() before
attempting to evaluate JavaScript. Previously, calling this step before a session
was started (e.g. in API-only scenarios) would throw an uncaught driver
exception.
Stale config cache in cleanConfig()
cleanConfig() was comparing the current configuration against a stale cached
value instead of the original backup, causing it to miss changes made during
a scenario. The cache is now properly invalidated before comparison.
Config backup using original value
ConfigContext was backing up the overridden value instead of the original when
a config key was set multiple times in a scenario. It now correctly stores only
the first (original) value.
Stale login state between scenarios
Login state could leak between scenarios when a user created in one scenario was
reused in the next. Session cleanup now ensures a clean authentication state at
the start of each scenario.
Infrastructure and testing
- Switched coding standards to Drupal (#757).
- Added comprehensive test coverage for all Context classes (#740).
- Added tests for Managers (#753).
- Added more negative test coverage (#756).
- Updated testing harness to support negative coverage (#755).
- Increased coverage for Mink extension service container (#751).
- Increased coverage for
DrupalDriverManager(#748). - Fixed coverage merge (#750).
- Added posting of the coverage as comments to the PR (#741).
- Updated stack to support Ahoy command wrapper and added coverage support (#739).
- Added examples to tests and updated docs generator to post summary to CI (#744).
- Added instructions for AI agents (#743).
- Renamed blackbox fixtures to generic names and updated region mappings (#747).
- Merged
FeatureContextTraitintoFeatureContext(#746). - Replaced regex annotation with turnip in
BatchContext::iWaitForTheBatchJobToFinish()(#745). - Simplified code (#781).
- Reformatted configuration trees to use hierarchical indentation and added formatter fences (#771).
- Added test for fresh
REQUEST_TIMEduring cron and bumped drupal-driver to ^2.4.2 (#762).
What's new since v5.2.1
- Simplified code. @AlexSkrypnyk (#781)
- [#693] Converted standard Behat annotations to PHP 8 attributes. @AlexSkrypnyk (#780)
- [#500] Made ConfigContext::setConfig() protected @AlexSkrypnyk (#779)
- [#599] Fixed 'iWaitForAjaxToFinish()' crashing on unstarted session. @AlexSkrypnyk (#778)
- [#534] Fixed stale config cache in cleanConfig() breaking change detection @AlexSkrypnyk (#777)
- [#238] Added table header validation tests and improved error message in 'assertValidMessageTable()'. @AlexSkrypnyk (#776)
- [#501] Fixed config backup using overridden value instead of original @AlexSkrypnyk (#775)
- Fix stale login state leaking between scenarios @AlexSkrypnyk (#774)
- [#770] Added
behat.dist.ymlwith all configuration values pre-filled. @AlexSkrypnyk (#773) - [#314] Added parent term resolution in termCreate() with validation and tests. @AlexSkrypnyk (#772)
- Reformatted configuration trees to use hierarchical indentation and added formatter fences. @AlexSkrypnyk (#771)
- [#607] Removed Drupal 6 and 7 driver support. @AlexSkrypnyk (#768)
- [#642] Added double-quote escaping to prevent compound separator splitting entity reference values. @AlexSkrypnyk (#767)
- [#360] Added validation for non-existent entity fields in parseEntityFields(). @AlexSkrypnyk (#765)
- [#658] Added custom DocumentElement to remove DrupalFinder dependency from extension boot. @AlexSkrypnyk (#764)
- [#670] Always create fresh user in role-based login steps @AlexSkrypnyk (#763)
- [#179] Added test for fresh REQUEST_TIME during cron and bumped drupal-driver to ^2.4.2. @AlexSkrypnyk (#762)
- [#676] Separated link assertion from click action in . @AlexSkrypnyk (#761)
- [#616] Removed Drupal 6 and 7 support remnants. @AlexSkrypnyk (#760)
- Removed deprecated
ScenarioTagTraitandRawDrupalContextmagic property accessors. @AlexSkrypnyk (#758) - [#729] Switched coding standards to Drupal. @AlexSkrypnyk (#757)
- [#738] Added more negative test coverage. @AlexSkrypnyk (#756)
- Updated testing harness to support negative coverage. @AlexSkrypnyk (#755)
- Added tests for Managers. @AlexSkrypnyk (#753)
- Increased coverage for Mink extension service container. @AlexSkrypnyk (#751)
- Fixed coverage merge. @AlexSkrypnyk (#750)
- Increased coverage for DrupalDriverManager. @AlexSkrypnyk (#748)
- Renamed blackbox fixtures to generic names and updated region mappings. @AlexSkrypnyk (#747)
- Merged FeatureContextTrait into FeatureContext @AlexSkrypnyk (#746)
- Replaced regex annotation with turnip in
BatchContext::iWaitForTheBatchJobToFinish(). @AlexSkrypnyk (#745) - Added examples to tests and updated docs generator to post summary to CI. @AlexSkrypnyk (#744)
- Added instructions for AI agents. @AlexSkrypnyk (#743)
- Added steps documentation generator. @AlexSkrypnyk (#742)
- [#738] Added posting of the coverage as comments to the PR. @AlexSkrypnyk (#741)
- Added comprehensive test coverage for all Context classes @AlexSkrypnyk (#740)
- [#738] Updated stack to support Ahoy command wrapper and added coverage support. @AlexSkrypnyk (#739)
Full Changelog: v5.2.1...v5.3.0