drupal/drupal-extension
Drupal extension for Behat
v6.1.0
16M downloads/mo
#1661 most downloaded on Packagist
jhedstrom/drupalextension
What this package is like to depend on
Last release 2 months ago
22 Jun 2026
Release timing varies
gaps range from 2 weeks to 1.4 years
Rarely documented
notes for 8 of 69 stable releases
Nothing withdrawn
no release was ever pulled
14 years old
72 releases · first in 2012
12 releases in the last 12 months
see the full history below
Release timeline
72 releases · Jul 2012 to Jun 2026Releases
latest 60 of 72-
v6.1.022 Jun 2026Release notes
Open source →What's new since v6.0.0
Breaking changes
- [#874] Removed the 'field_parser: legacy' parser. @AlexSkrypnyk (#880)
Thefield_parserconfiguration node and itslegacyvalue (which opted back into the pre-6.0 inline field syntax) are gone, soEntityFieldParseris now always active and accepts no configuration. Anyfield_parserkey left inbehat.ymlnow triggers a hard configuration error on load. To migrate, delete thefield_parserentry from yourDrupal\DrupalExtensionconfig and convert any feature files still written in the legacy field syntax to the current syntax (see the field-syntax mapping table inUPGRADING.md). - [#876] Removed the 'region_map' configuration key. @AlexSkrypnyk (#879)
Theregion_mapkey, superseded by the identically structuredregionskey in 6.0.0, has been removed, and abehat.ymlthat still uses it now fails to load with an "Unrecognized option" error. To migrate, renameregion_map:toregions:in yourDrupal\DrupalExtensionconfiguration; the nested structure is unchanged, so only the key name needs updating. - [#875] Removed flat message selector keys. @AlexSkrypnyk (#878)
The four flat keys underselectors:-message_selector,error_message_selector,success_message_selector, andwarning_message_selector- are no longer accepted, and the nestedselectors.messages:map (keyeddefault,error,success,warning) is now the only supported form. A missing selector now raises aRuntimeExceptionnaming the exact path to configure, e.g.Drupal\DrupalExtension.selectors.messages.error. To migrate, move each flat key into the nested map under its corresponding type. - [#873] Removed the legacy '<?name>' random token syntax. @AlexSkrypnyk (#877)
The<?name>random-token form has been removed, leaving the typed[?name:type,args]syntax as the only oneRandomContextunderstands. As a side effectRandomContextno longer implementsParametersAwareInterfaceorDeprecationInterface, so subclasses that relied on those members are affected. To migrate, replace every<?name>token in your feature files with the[?name]/[?name:type,args]form documented indocs/writing-tests.md.
Highlights
- [#597] Added HTTP Basic authentication support for sites behind webserver-level basic auth. @AlexSkrypnyk (#870)
You can now test Drupal sites sitting behind Apache/Nginx HTTP Basic auth, which previously failed becausefastLogout()reset the session and discarded theAuthorizationheader, returning a401before the login form ever loaded. Credentials are read from a newbasic_auth: {username, password}config node (or thebase_urluserinfo) and re-applied automatically after every session reset, so the whole login flow stays authenticated. - [#536] Added best-practice docs and a tested example for module-shipped Behat contexts. @AlexSkrypnyk (#869)
A new "Shipping contexts in a module" guide documents where to place context classes, how to namespace them (Drupal\Tests\{module}\Behat\Context\), and how to wire PSR-4 autoloading for standalone Behat runs - filling the gap left when sub-context auto-discovery was removed. It is backed by a workingExampleContextin thebehat_testfixture module that CI exercises under--strict, so the recommended pattern is proven rather than theoretical. - [#813] Added '@AfterScenario' cleanup of files attached through the UI. @AlexSkrypnyk (#868)
Files uploaded via theI attach the filestep are now tracked and their managed-file entities deleted after each scenario, so re-uploading the same filename is no longer silently renamed by Drupal (e.g.image.pngbecomesimage_0.png) and breaking path-based assertions. Tag a scenario or feature with@no-file-cleanupto opt out; the hook is a no-op on blackbox and other non-in-process drivers. - [#672] Added email attachment assertion steps to 'MailContext'. @AlexSkrypnyk (#867)
Four newThensteps let you assert that a sent email carries specific attachment(s), optionally filtered by recipient and/or subject, and theWhen I send the following (e)mail:step gains anattachmentstable column so tests can send mails with attachments in the first place. This makes it possible to verify attachment delivery end to end without writing custom step code. - [#734] Added steps to run a failing drush command and assert its output. @AlexSkrypnyk (#866)
NewI run the failing drush commandsteps run a Drush command expected to exit non-zero and capture its output so the existingthe drush output should contain/matchsteps can assert on it, failing the step if the command unexpectedly succeeds. This closes the gap where a non-zero exit previously aborted the scenario before you could inspect the error output. - [#115] Added 'MappingContext' resolving '{{ Key }}' tokens from 'mappings' config. @AlexSkrypnyk (#865)
A newMappingContextreplaces{{ Key }}tokens in any step argument or table cell with values defined under a newmappingskey inbehat.yml, letting you centralise shared test data (URLs, labels, IDs) in one place instead of repeating literals across feature files. Keys must be globally unique - duplicates are rejected at config load - and an unknown key fails the step immediately rather than passing through unresolved.
All changes
- [#874] Removed the 'field_parser: legacy' parser. @AlexSkrypnyk (#880)
Deletes thefield_parserconfig node, thelegacyvalue, and the backingLegacyEntityFieldParserclass, leavingEntityFieldParseras the sole parser with no configuration. Anyfield_parserkey inbehat.ymlnow produces a hard configuration error on load. - [#876] Removed the 'region_map' configuration key. @AlexSkrypnyk (#879)
Drops theregion_mapkey from the config schema in favour of the identically structuredregionskey, so a staleregion_mapnow fails to load with an "Unrecognized option" error. Rename the key toregionsto upgrade. - [#875] Removed flat message selector keys. @AlexSkrypnyk (#878)
Removes the flatmessage_selector,error_message_selector,success_message_selector, andwarning_message_selectorkeys, so selectors must now live under the nestedselectors.messages:map. An unconfigured selector throws aRuntimeExceptionthat names the exact nested path to add. - [#873] Removed the legacy '<?name>' random token syntax. @AlexSkrypnyk (#877)
Removes the<?name>token form and the legacy parsing path fromRandomContext, leaving the typed[?name:type,args]syntax as the only supported form. As a resultRandomContextno longer implementsParametersAwareInterfaceorDeprecationInterface, and the per-run[Deprecation]notices it printed are gone. - Switched back to stable DrupalDriver. @AlexSkrypnyk (#872)
Restores thedrupal/drupal-driverrequirement to a stable version range, replacing the temporarydev-masterpin used while driver-side APIs needed by recent features were still unreleased. Consumers get a stable, tagged driver constraint again. - Updated information about maintainers. @AlexSkrypnyk (#871)
Refreshes the project's maintainer information. A documentation-only change with no effect on the extension's behaviour. - [#597] Added HTTP Basic authentication support for sites behind webserver-level basic auth. @AlexSkrypnyk (#870)
Adds first-class HTTP Basic auth: credentials from a newbasic_authconfig node (or thebase_urluserinfo) are applied to the Mink session and re-applied automatically after each reset, so logging into a site behind Apache/Nginx basic auth no longer fails with a401. JavaScript/Selenium drivers, which cannot set request headers, fall back to thebase_urluserinfo and degrade to a silent no-op where unsupported. - [#536] Added best-practice docs and a tested example for module-shipped Behat contexts. @AlexSkrypnyk (#869)
Adds a "Shipping contexts in a module" guide covering directory layout, namespacing, and PSR-4 autoloading for standalone Behat runs, plus a workingExampleContextand helper trait in thebehat_testfixture module that CI exercises under--strict. This documents the recommended replacement for the removed sub-context auto-discovery. - [#813] Added '@AfterScenario' cleanup of files attached through the UI. @AlexSkrypnyk (#868)
Tracks files uploaded via theI attach the filestep and deletes their managed-file entities after each scenario, preventing Drupal from renaming a re-uploaded file (e.g.image.pngtoimage_0.png) and breaking path-based assertions. Opt out per scenario or feature with@no-file-cleanup; the hook is a no-op on blackbox and other non-in-process drivers. - [#672] Added email attachment assertion steps to 'MailContext'. @AlexSkrypnyk (#867)
Adds fourThensteps that assert a sent email carries specific attachment(s), with optional recipient and subject filters, and extendsWhen I send the following (e)mail:with anattachmentstable column so such mails can be sent in tests. Lets you verify attachment delivery without writing custom step definitions. - [#734] Added steps to run a failing drush command and assert its output. @AlexSkrypnyk (#866)
AddsI run the failing drush commandsteps that execute a Drush command expected to exit non-zero, capture its output for the existingthe drush output should contain/matchassertions, and fail if the command unexpectedly exits 0. Previously a non-zero exit aborted the scenario before its error output could be checked. - [#115] Added 'MappingContext' resolving '{{ Key }}' tokens from 'mappings' config. @AlexSkrypnyk (#865)
Adds a driver-freeMappingContextthat substitutes{{ Key }}tokens in step arguments and table cells with values defined under a newmappingskey inbehat.yml. Keys must be globally unique (duplicates are rejected at config load) and an unknown key fails the step rather than passing through unresolved. - [#860] Added a test for 'color_field' field support. @AlexSkrypnyk (#863)
Adds end-to-end coverage for the contribcolor_fieldmodule'scolor_field_type, driving a Gherkin table cell through the entity-field parser, the driver'sColorFieldTypeHandler(fromdrupal/drupal-driverv3.1.0), Drupal storage, and rendered output. It exercises both the bare-hex shorthand and thecolor/opacityform, covering the extension-level path a user actually drives. - [#861] Documented bracketed test markers as a compound-mode trigger in 'UPGRADING.md'. @AlexSkrypnyk (#862)
Documents a non-obvious upgrade footgun: in the modern parser a compound column value beginning with[(such as a[TEST]or[DEV]marker) is read as the start of a[name:value]token and causes a parse error. The new guidance shows that wrapping the value in double quotes makes the bracket literal, and explains why an unrelated column can tip a whole cell into compound mode. - Fixed PHPStan always-true comparison errors in docs generator and field parser. @AlexSkrypnyk (#864)
Resolves three PHPStan always-true comparison errors that were failingahoy lint, by dropping a provably-redundant condition inscripts/docs.phpand reading the stop character inEntityFieldParser::parseScalarList()viasubstr()instead of offset indexing. Both changes are behavior-preserving, with no PHPStan config, baseline, or ignore annotations added.
Full Changelog: v6.0.0...v6.1.0
- [#874] Removed the 'field_parser: legacy' parser. @AlexSkrypnyk (#880)
-
v6.0.029 May 2026Release notes
Open source →What's new since v6.0.0-rc2
- Prepared v6 stable release: pinned 'drupal/drupal-driver' to stable v3 and tidied release docs. @AlexSkrypnyk (#859)
Full Changelog: v6.0.0-rc2...v6.0.0
Migration
For migration instructions, see
UPGRADING.md.Implemented across pre-stable v6
This combines the release notes from every pre-stable v6 release -
v6.0.0-alpha1,v6.0.0-rc1, andv6.0.0-rc2. The complete set is what ships inv6.0.0stable. Each section lists the items first introduced in that specific pre-release.v6.0.0-alpha1
Version 6.0 enforces a consistent set of step-definition conventions across all bundled contexts. The conventions are documented in
CONTRIBUTING.mdand validated byscripts/docs.php; CI fails on any violation.See
UPGRADING.mdfor detailed migration instructions covering all breaking changes, and the table below for a summary of highlights and breaking changes.Highlights
- Updated 'drupal/drupal-driver' to 3.x and migrated to capability-based API. @AlexSkrypnyk (#803)
The monolithicDriverInterfaceis replaced with capability interfaces (AuthenticationCapabilityInterface,MailCapabilityInterface,ConfigCapabilityInterface,ContentCapabilityInterface,CacheCapabilityInterface,CronCapabilityInterface,LanguageCapabilityInterface,RoleCapabilityInterface,UserCapabilityInterface) and every CRUD method is renamed to a verb-noun form. Migration: bumpdrupal/drupal-driverto^3.0, rename driver calls (createNode→nodeCreate,runCron→cronRun,clearCache→cacheClear,startCollectingMail→mailStartCollecting,getMail→mailGet,sendMail→mailSend, etc.), and add capability-interface guards before invoking driver methods in subclasses. - [#469] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk (#844)
RandomContextships six built-in generators (string,name,machine_name,int,email,uuid) selectable via[?name:type,args], with subclasses able to register custom types by overriding a single method. Equivalent literals share a scenario-scoped cache key, so[?title],[?title:string], and[?title:string,10]all produce the same value within one scenario. - [#258] Added BigPipe NOJS cookie bypass to 'DrupalContext'. @AlexSkrypnyk (#821)
Tagging a scenario with@bigpipesets thebig_pipe_nojscookie on non-JS Mink drivers (BrowserKit, Goutte) so Drupal renders pages fully server-side instead of leaving placeholders that only the BigPipe JS would replace. This makes authenticated-user assertions like "I should see Log out" reliable on BigPipe-enabled sites without switching to a real browser. - [#732] Added 'login_field' configuration to submit a custom user property as the login value. @AlexSkrypnyk (#820)
Sites that authenticate by email rather than username (viamail_login,email_registration, or similar contrib) can now setlogin_field: mail(or any other user property) underDrupal\DrupalExtension, and the auth manager submits that property value to the username field instead of the hardcodedname. The default remainsname, so existing setups are unaffected. - [#766] Added modern entity-field parser with 'field_parser' configuration flag. @AlexSkrypnyk (#818)
The newEntityFieldParserintroduces double-quote escaping, named-column compound syntax (country:"BE", locality:"Brussel"), structuredParseExceptionerrors with file/line context, and aggregated multi-error reporting. Bare-is now treated as literal text in scalar mode, so entity reference titles like"My article - Part 2"no longer require escaping. - Added 'suppress_deprecations' configuration and 'BEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONS' environment variable. @AlexSkrypnyk (#836)
Both thesuppress_deprecationsconfig key and theBEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONSenv var silence the extension's[Deprecation]notices to STDERR, with the env var winning over config. This lets teams roll forward through migrations without their CI failing on deprecation noise from extension-detected legacy patterns. - [#647] Added 'BEHAT_DRUPALEXTENSION_DISABLE_CLEANUP' env var to skip scenario teardown. @AlexSkrypnyk (#845)
SettingBEHAT_DRUPALEXTENSION_DISABLE_CLEANUP=1(ortrue/yes/on) skips theAfterScenarioteardown of entities, users, and roles, and intentionally leaves the last logged-in session open so a failing scenario's database state and browser session can be inspected directly. Intended for ad-hoc local debugging - leave it off in CI. - [#479] Added verbose diagnostic output to AJAX timeout exception. @AlexSkrypnyk (#838)
iWaitForAjaxToFinish()now captures the current URL,jQuery.activecount, animated-element count, and each activeDrupal.ajax.instancesentry (selector, event, URL) at the moment of timeout and embeds them in a structured multi-line error message. Replaces the previous single-line "Unable to complete AJAX request." message that gave no clue why the browser was busy.
Breaking changes
- Updated 'drupal/drupal-driver' to 3.x and migrated to capability-based API. @AlexSkrypnyk (#803)
The monolithicDriverInterfaceis replaced with capability interfaces (AuthenticationCapabilityInterface,MailCapabilityInterface,ConfigCapabilityInterface,ContentCapabilityInterface,CacheCapabilityInterface,CronCapabilityInterface,LanguageCapabilityInterface,RoleCapabilityInterface,UserCapabilityInterface) and every CRUD method is renamed to a verb-noun form. Migration: bumpdrupal/drupal-driverto^3.0, rename driver calls (createNode→nodeCreate,runCron→cronRun,clearCache→cacheClear,startCollectingMail→mailStartCollecting,getMail→mailGet,sendMail→mailSend, etc.), and add capability-interface guards before invoking driver methods in subclasses. - [#469] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk (#844)
The legacy<?name>random-token form still works in 6.0 but emits a[Deprecation]notice once per literal. Migration: replace<?name>with[?name](equivalent default) or one of the typed forms ([?slug:machine_name],[?age:int,18,99],[?email:email],[?id:uuid]); the legacy form is scheduled for removal in 6.1. - Renamed 'assert' action steps and tightened validator. @AlexSkrypnyk (#837)
Action methods that previously usedassertXxxnames are renamed to action-style names (e.g.assertCron→iRunCron,assertAuthenticatedByRole→iAmLoggedInAsUserWithRole,assertDrushCommand→iRunDrush), and three negative-message steps move from@Givento@Thenwith matching method renames. Migration: see the rename table inMIGRATION.mdand search-and-replace overridden method names in your subclasses; step text is unchanged for most steps but the three re-classified steps now require@Thensemantics. - [#824] Converted 'BatchContext' into 'BatchTrait' on 'DrupalContext'. @AlexSkrypnyk (#835)
BatchContextis deleted; itsiWaitForTheBatchJobToFinishandthereIsAnItemInTheSystemQueuesteps are now provided byDrupalContextviaBatchTrait. Migration: removeDrupal\DrupalExtension\Context\BatchContextfrom thecontexts:list in yourbehat.yml- the steps are loaded automatically withDrupalContext. - Moved driver and mail manager classes under 'Drupal\DrupalExtension\Manager' namespace. @AlexSkrypnyk (#833)
Drupal\DrupalDriverManager→Drupal\DrupalExtension\Manager\DriverManager(theDrupalprefix drops),Drupal\DrupalDriverManagerInterface→Drupal\DrupalExtension\Manager\DriverManagerInterface,Drupal\DrupalMailManager→Drupal\DrupalExtension\Manager\DrupalMailManager,Drupal\DrupalMailManagerInterface→Drupal\DrupalExtension\Manager\DrupalMailManagerInterface. Migration: updateusestatements and any FQCN references; the user and authentication managers retain their existing namespaces. - Moved 'ParametersAwareInterface' to root namespace alongside 'ParametersTrait'. @AlexSkrypnyk (#832)
The interface moved fromDrupal\DrupalExtension\Context\ParametersAwareInterfacetoDrupal\DrupalExtension\ParametersAwareInterface. Migration: updateusestatements to import from the root namespace; signatures (setParameters,getParameter) are unchanged. - [#825] Extracted Drupal AJAX handling into 'DrupalAjaxTrait'. @AlexSkrypnyk (#830)
The three Drupal-specific AJAX methods (iWaitForAjaxToFinish,beforeJavascriptStep,afterJavascriptStep) move fromMinkContextintoDrupalAjaxTrait.MinkContextcomposes the trait so existing consumers see no behavior change, but downstream subclasses that overrode these methods inline must now override the trait methods or composeDrupalAjaxTraitdirectly. - Moved 'ajax_timeout' to 'Drupal\DrupalExtension' and renamed parameters interface. @AlexSkrypnyk (#829)
ajax_timeoutconfiguration moves fromDrupal\MinkExtensiontoDrupal\DrupalExtension, and the parameters API drops itsDrupalprefix:DrupalParametersAwareInterface→ParametersAwareInterface,DrupalParametersTrait→ParametersTrait,setDrupalParameters→setParameters,getDrupalParameter→getParameter,$drupalParameters→$parameters. Migration: relocateajax_timeoutinbehat.ymland rename interface/trait/method/property references in subclasses. - [#822] Rebased MessageContext on RawMinkContext and moved message selectors to Drupal\MinkExtension. @AlexSkrypnyk (#827)
MessageContextnow extendsRawMinkContextinstead ofRawDrupalContext, so it can be registered in any Mink suite without booting the Drupal driver; subclasses that depended onRawDrupalContexthelpers must composeParametersTraitthemselves or change their base. The four message selectors (message_selector,error_message_selector,success_message_selector,warning_message_selector) move fromDrupal\DrupalExtension.selectors:toDrupal\MinkExtension.selectors:; the legacy location still works in 6.0 with a one-shot deprecation notice and is removed in 6.1. - [#258] Added BigPipe NOJS cookie bypass to 'DrupalContext'. @AlexSkrypnyk (#821)
This is additive (opt-in via@bigpipetag) but ships as part ofDrupalContext, so subclasses that override the existingBeforeScenario/BeforeStephook methods without calling parent will silently disable the bypass. Migration: if you override these hooks, callparent::or useBigPipeTraitexplicitly so the cookie management still runs. - Replaced Sphinx documentation with Markdown-based docs in 'docs/'. @AlexSkrypnyk (#819)
The Read the Docs / Sphinx tree underdoc/is removed and replaced with Markdown underdocs/. Migration: update bookmarks and any internal links pointing atdoc/*.rstto the newdocs/*.mdpaths; the Read the Docs site is no longer maintained. - [#766] Added modern entity-field parser with 'field_parser' configuration flag. @AlexSkrypnyk (#818)
The default field-value parser is nowEntityFieldParser, which uses double-quote escaping and detects compound mode bykey:"value"form rather than-separator spacing. Migration: setfield_parser: legacyunderDrupal\DrupalExtensioninbehat.ymlto keep the 5.x behavior (emits a one-shot deprecation notice); the legacy parser is removed in 6.1. Cells containing-no longer require escaping under the modern parser. - Renamed 'classifier()' calls to 'getFieldClassifier()' to match drupal-driver API. @AlexSkrypnyk (#817)
The drupal-driverCoreInterface::classifier()accessor was renamed togetFieldClassifier(). Migration: replace direct calls of$driver->getCore()->classifier()with$driver->getCore()->getFieldClassifier(); no backwards-compatibility shim is provided. - [#337] Replaced 'stdClass' entity stubs with typed 'EntityStub' from driver. @AlexSkrypnyk (#814)
Hook scopes (BeforeNodeCreateScope,AfterNodeCreateScope, etc.) and step methods now exposeEntityStubInterfaceinstead of\stdClass, andEntityScope::getEntity()is renamed togetStub(). Migration: replace ad-hoc property reads with$stub->getValue('title')and writes with$stub->setValue(...); replace(object) [...]constructions withnew EntityStub($entity_type, $bundle, $values); replace$saved->nid/$saved->tidwith$stub->getId(); renamegetEntity()calls togetStub(). - [#806] Removed 'store' parameter from 'DrupalMailManager' and 'DrupalMailManagerInterface'. @AlexSkrypnyk (#812)
getMail()andclearMail()no longer accept a$storeargument because the v3 driver only exposes a single implicit collector. Migration: drop the$storeargument from any direct calls and from any subclass overrides that implementDrupalMailManagerInterface; tracked counts inRawMailContextare now a scalarintrather than an array keyed by store. - [#752] Replaced generic exceptions with typed Mink exceptions across bundled contexts. @AlexSkrypnyk (#811)
Roughly 30\Exceptionthrows across the bundled contexts are replaced withBehat\Mink\Exception\ElementNotFoundException(lookups),Behat\Mink\Exception\ExpectationException(assertion mismatches), or\RuntimeException(configuration errors). Migration: any tests or hooks that catch\Exceptionfrom these steps continue to work, but code that asserts on specific exception classes or messages must update to the typed classes; Mink exceptions append URL and page-snippet context via__toString(). - Enforced step-definition conventions for v6 across all bundled contexts. @AlexSkrypnyk (#810)
Roughly 50@Thenmethods are renamed to<concern>Assert<action>form, around 29 step texts are updated to satisfy the new conventions (e.g.Given users:→Given the following users:,Then drush output should contain X→Then the drush output should contain X,Then I log out→When I log out), and several methods are re-categorised from@Thento@Whenfor side-effect steps. Migration: search-and-replace step text in your feature files using the table inMIGRATION.md; rename overridden method names in your subclasses. - Removed deprecated APIs in preparation for 6.0.0. @AlexSkrypnyk (#809)
Subcontext auto-discovery (subcontexts.pathsconfig,.behat.incloading,DrupalSubContextInterface,DrupalSubContextBase), the annotation-based hook reader (Annotation\Reader),RawDrupalContext::loggedInWithRole(), and theAnnotatedDefinitionProposalshim are all removed. Migration: rewrite subcontexts as regular Behat contexts using PHP attributes; remove anysubcontexts:block frombehat.yml; replaceloggedInWithRole()calls with the standard authenticated-user flow. - [#823] Rebased 'RandomContext' on bare Behat context interface. @AlexSkrypnyk (#834)
RandomContextno longer extendsRawDrupalContext; it implementsBehat\Behat\Context\Contextdirectly and instantiates aRandomlazily. Migration: subclassers that relied on inherited Drupal/Mink helpers must compose those traits themselves or change their base class; documented inMIGRATION.mdunder "RandomContext base class".
All changes
- [#356] Strengthened 'author' property test to assert author is applied. @AlexSkrypnyk (#847)
The existing scenario for theauthorproperty inGiven the following :type content:was rewritten as a direct test that creates an article withauthor = Joe User, visits/admin/content, and assertsJoe Userappears in the article's author column. Previously the scenario only verified the syntax did not error. - [#647] Added 'BEHAT_DRUPALEXTENSION_DISABLE_CLEANUP' env var to skip scenario teardown. @AlexSkrypnyk (#845)
SettingBEHAT_DRUPALEXTENSION_DISABLE_CLEANUP=1(ortrue/yes/on) skips theAfterScenarioteardown of entities, users, and roles, and intentionally leaves the last logged-in session open so a failing scenario's database state and browser session can be inspected directly. Intended for ad-hoc local debugging - leave it off in CI. - [#735] Added test coverage and docs for options in 'I run drush :command :arguments' step. @AlexSkrypnyk (#846)
The existingI run drush :command :argumentsstep already supported flags because the arguments string is appended verbatim to the shell command, but this was undocumented. The docblock now shows a combined positional-argument-plus-flag example, and a new scenario exercisesconfig:get "system.site uuid --format=string"end to end. - [#469] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk (#844)
RandomContextships six built-in generators (string,name,machine_name,int,email,uuid) selectable via[?name:type,args], with subclasses able to register custom types by overriding a single method. Equivalent literals share a scenario-scoped cache key, so[?title],[?title:string], and[?title:string,10]all produce the same value within one scenario. - [#733] Added test coverage and docs for configurable login and logout URLs. @AlexSkrypnyk (#843)
Three new PHPUnit tests pin thevisit()argument so a regression that hardcoded/userback intoDrupalAuthenticationManagerwould now fail loudly, and thelogout_confirm_urlentry was added to the documentedtext:example so all three login/logout URL keys are visible together. - [#415] Added test coverage for URI-only link field values. @AlexSkrypnyk (#841)
Five new Behat scenarios exercise URI-only link field values - bare URIs, comma-separated lists, the nameduri:compound column, and a mixed scenario - covering the upstreamLinkHandlerfix in drupal-driver that wraps a bare string as['uri' => $value]. - Fixed chrome port and AJAX assertion after Pygmy and Lagoon stack migration. @AlexSkrypnyk (#840)
The Selenium VNC port mapping was changed from a fixed7900:7900host binding to a Docker-assigned ephemeral port to avoid conflicts, and the AJAX timeout assertion inFeatureContextno longer hardcodeshttp://blackboxso it works against the new in-process PHP server (http://cli:8888).CONTRIBUTING.mdnow documents how to read the dynamic VNC URL fromahoy info. - [#730] Migrated local stack to Pygmy and Lagoon images. @AlexSkrypnyk (#839)
The Wodby + Traefik local stack is replaced with Lagoon container images fronted by Pygmy, matching the layout used bydrevops/behat-steps. The blackbox nginx container is dropped in favour of an in-process PHP server started byBlackboxServerContextinside theclicontainer, thedrupal_httpsprofile is removed, and provisioning steps move into a singlescripts/provision.shshared byahoyand CI. - [#479] Added verbose diagnostic output to AJAX timeout exception. @AlexSkrypnyk (#838)
iWaitForAjaxToFinish()now captures the current URL,jQuery.activecount, animated-element count, and each activeDrupal.ajax.instancesentry (selector, event, URL) at the moment of timeout and embeds them in a structured multi-line error message. Replaces the previous single-line "Unable to complete AJAX request." message that gave no clue why the browser was busy. - Renamed 'assert' action steps and tightened validator. @AlexSkrypnyk (#837)
Action methods that previously usedassertXxxnames are renamed to action-style names (e.g.assertCron→iRunCron,assertAuthenticatedByRole→iAmLoggedInAsUserWithRole,assertDrushCommand→iRunDrush), and three negative-message steps move from@Givento@Thenwith matching method renames. The validator now hard-fails when@Given/@Whenstep text containsshouldor method names containAssert. - Added 'suppress_deprecations' configuration and 'BEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONS' environment variable. @AlexSkrypnyk (#836)
Both thesuppress_deprecationsconfig key and theBEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONSenv var silence the extension's[Deprecation]notices to STDERR, with the env var winning over config. This lets teams roll forward through migrations without their CI failing on deprecation noise from extension-detected legacy patterns. - [#824] Converted 'BatchContext' into 'BatchTrait' on 'DrupalContext'. @AlexSkrypnyk (#835)
BatchContextis deleted; itsiWaitForTheBatchJobToFinishandthereIsAnItemInTheSystemQueuesteps are now provided byDrupalContextviaBatchTrait. Both steps depend on\Drupal::calls, so hosting them on the API-driver-onlyDrupalContextkeeps them behind a bootstrapped Drupal kernel and prevents silent failures under Blackbox or Drush drivers. - Moved driver and mail manager classes under 'Drupal\DrupalExtension\Manager' namespace. @AlexSkrypnyk (#833)
Drupal\DrupalDriverManager→Drupal\DrupalExtension\Manager\DriverManager(theDrupalprefix drops because driver routing is generic infrastructure), and the mail manager and its interface move alongside the user/auth managers under the same namespace. The deadpsr-0autoload entry incomposer.jsonis removed. - [#823] Rebased 'RandomContext' on bare Behat context interface. @AlexSkrypnyk (#834)
RandomContextno longer extendsRawDrupalContext; it implementsBehat\Behat\Context\Contextdirectly and instantiates aRandomlazily, so the context can be registered in any Behat suite regardless of whether the Drupal extension is loaded. New PHPUnit tests cover the standalone shape and the token substitution contract. - Moved 'ParametersAwareInterface' to root namespace alongside 'ParametersTrait'. @AlexSkrypnyk (#832)
The interface moved fromDrupal\DrupalExtension\Context\ParametersAwareInterfacetoDrupal\DrupalExtension\ParametersAwareInterfaceso it sits next to its companionParametersTraitandRegionTrait.setParameters/getParametersignatures are unchanged - only the FQN moves. - [#826] Documented 'ParametersTrait' and 'RegionTrait' as Mink-only consumption points. @AlexSkrypnyk (#831)
The two traits work on anyRawMinkContextconsumer without requiring a Drupal driver bootstrap; the trait docblocks and a new "Mink-only contexts" section indocs/contexts.mdmake the pattern explicit. The bundledMinkContext,MarkupContext, andMessageContextalready follow this pattern. - [#825] Extracted Drupal AJAX handling into 'DrupalAjaxTrait'. @AlexSkrypnyk (#830)
The three Drupal-specific AJAX methods (iWaitForAjaxToFinish,beforeJavascriptStep,afterJavascriptStep) move fromMinkContextintoDrupalAjaxTrait;MinkContextcomposes the trait so existing consumers see no behavior change. The trait can now be reused in custom Mink-based contexts without inheriting fromMinkContext. - Moved 'ajax_timeout' to 'Drupal\DrupalExtension' and renamed parameters interface. @AlexSkrypnyk (#829)
ajax_timeoutconfiguration moves fromDrupal\MinkExtensiontoDrupal\DrupalExtensionso all custom config lives under one extension, and the parameters API drops itsDrupalprefix throughout: interface, trait, methods, and property name. TheDrupal\MinkExtensionextension now only registers the BrowserKit driver factory. - Moved 'ClassGenerator' out of 'Context/ContextClass/' into a top-level 'Generator/' namespace. @AlexSkrypnyk (#828)
ClassGenerator(Behat'sbehat --initscaffolder for Drupal context classes) moves fromDrupal\DrupalExtension\Context\ContextClasstoDrupal\DrupalExtension\Generator, away from the actual step-defining contexts. The class is only instantiated by Behat's DI from inside the extension, so no downstream user code is affected. New PHPUnit tests cover both namespaced and rootless context-class generation. - [#822] Rebased MessageContext on RawMinkContext and moved message selectors to Drupal\MinkExtension. @AlexSkrypnyk (#827)
MessageContextnow extendsRawMinkContextinstead ofRawDrupalContext, so blackbox-only suites no longer pay the cost of booting the Drupal driver stack. The four message selectors move fromDrupal\DrupalExtension.selectors:to a newDrupal\MinkExtension.selectors:map; the legacy location keeps working in 6.0 with a one-shot deprecation notice. - [#258] Added BigPipe NOJS cookie bypass to 'DrupalContext'. @AlexSkrypnyk (#821)
Tagging a scenario with@bigpipesets thebig_pipe_nojscookie on non-JS Mink drivers so Drupal renders pages fully server-side instead of leaving placeholders that only the BigPipe JS would replace. The cookie is re-applied on every step because login redirects drop session cookies, and the trait is a no-op when the active driver supports JavaScript. - [#732] Added 'login_field' configuration to submit a custom user property as the login value. @AlexSkrypnyk (#820)
Sites that authenticate by email rather than username (viamail_login,email_registration, or similar contrib) can now setlogin_field: mail(or any other user property) underDrupal\DrupalExtension, and the auth manager submits that property value to the username field instead of the hardcodedname. The default remainsname, so existing setups are unaffected. - Replaced Sphinx documentation with Markdown-based docs in 'docs/'. @AlexSkrypnyk (#819)
The Read the Docs / Sphinx tree underdoc/is removed and replaced with plain Markdown underdocs/covering installation, configuration, drivers, contexts, hooks, and writing tests. The Read the Docs badge and links inREADME.mdare also dropped. - [#766] Added modern entity-field parser with 'field_parser' configuration flag. @AlexSkrypnyk (#818)
The newEntityFieldParserintroduces double-quote escaping, named-column compound syntax (country:"BE", locality:"Brussel"), structuredParseExceptionerrors with file/line context, and aggregated multi-error reporting. Bare-is now treated as literal text in scalar mode, so entity reference titles like"My article - Part 2"no longer require escaping. - [#766] Extracted field parsing into 'ParserInterface' and 'LegacyEntityFieldsParser'. @AlexSkrypnyk (#816)
This is a pure refactor that lifts the cell-level field-value parsing out ofRawDrupalContext::parseEntityFields()into a newLegacyEntityFieldsParserimplementing a newParserInterface. Behavior is unchanged in this PR; the contract is introduced first so the new modern parser (#818) can land against a stable interface. - Renamed 'classifier()' calls to 'getFieldClassifier()' to match drupal-driver API. @AlexSkrypnyk (#817)
The drupal-driverCoreInterface::classifier()accessor was renamed togetFieldClassifier()upstream, and this PR updates the single call site inparseEntityFields()and the four mock setups inRawDrupalContextTest. No backwards-compatibility shim is provided. - Removed PHPSpec-based unit testing from the project. @AlexSkrypnyk (#815)
The 22 PHPSpec spec files, thetest-phpspecahoy command, and thephpspec/phpspecComposer dev dependency are all removed; PHPUnit and Behat already cover the same ground. CI now runs one fewer parallel step. - [#337] Replaced 'stdClass' entity stubs with typed 'EntityStub' from driver. @AlexSkrypnyk (
Note truncated.
Release notes
Open source →Breaking changes
-
[ #874 ] Removed the 'field_parser: legacy' parser. @AlexSkrypnyk ( #880 ) The field_parser configuration node and its legacy value (which opted back into the pre-6.0 inline field syntax) are gone, so EntityFieldParser is now always active and accepts no configuration. Any field_parser key left in behat.yml now triggers a hard configuration error on load. To migrate, delete the field_parser entry from your Drupal\DrupalExtension config and convert any feature files still written in the legacy field syntax to the current syntax (see the field-syntax mapping table in UPGRADING.md ).
-
[ #876 ] Removed the 'region_map' configuration key. @AlexSkrypnyk ( #879 ) The region_map key, superseded by the identically structured regions key in 6.0.0, has been removed, and a behat.yml that still uses it now fails to load with an "Unrecognized option" error. To migrate, rename region_map: to regions: in your Drupal\DrupalExtension configuration; the nested structure is unchanged, so only the key name needs updating.
-
[ #875 ] Removed flat message selector keys. @AlexSkrypnyk ( #878 ) The four flat keys under selectors: - message_selector , error_message_selector , success_message_selector , and warning_message_selector - are no longer accepted, and the nested selectors.messages: map (keyed default , error , success , warning ) is now the only supported form. A missing selector now raises a RuntimeException naming the exact path to configure, e.g. Drupal\DrupalExtension.selectors.messages.error . To migrate, move each flat key into the nested map under its corresponding type.
-
[ #873 ] Removed the legacy '<?name>' random token syntax. @AlexSkrypnyk ( #877 ) The <?name> random-token form has been removed, leaving the typed [?name:type,args] syntax as the only one RandomContext understands. As a side effect RandomContext no longer implements ParametersAwareInterface or DeprecationInterface , so subclasses that relied on those members are affected. To migrate, replace every <?name> token in your feature files with the [?name] / [?name:type,args] form documented in docs/writing-tests.md .
Highlights
-
[ #597 ] Added HTTP Basic authentication support for sites behind webserver-level basic auth. @AlexSkrypnyk ( #870 ) You can now test Drupal sites sitting behind Apache/Nginx HTTP Basic auth, which previously failed because fastLogout() reset the session and discarded the Authorization header, returning a 401 before the login form ever loaded. Credentials are read from a new basic_auth: {username, password} config node (or the base_url userinfo) and re-applied automatically after every session reset, so the whole login flow stays authenticated.
-
[ #536 ] Added best-practice docs and a tested example for module-shipped Behat contexts. @AlexSkrypnyk ( #869 ) A new "Shipping contexts in a module" guide documents where to place context classes, how to namespace them ( Drupal\Tests{module}\Behat\Context\ ), and how to wire PSR-4 autoloading for standalone Behat runs - filling the gap left when sub-context auto-discovery was removed. It is backed by a working ExampleContext in the behat_test fixture module that CI exercises under --strict , so the recommended pattern is proven rather than theoretical.
-
[ #813 ] Added '@AfterScenario' cleanup of files attached through the UI. @AlexSkrypnyk ( #868 ) Files uploaded via the I attach the file step are now tracked and their managed-file entities deleted after each scenario, so re-uploading the same filename is no longer silently renamed by Drupal (e.g. image.png becomes image_0.png ) and breaking path-based assertions. Tag a scenario or feature with @no-file-cleanup to opt out; the hook is a no-op on blackbox and other non-in-process drivers.
-
[ #672 ] Added email attachment assertion steps to 'MailContext'. @AlexSkrypnyk ( #867 ) Four new Then steps let you assert that a sent email carries specific attachment(s), optionally filtered by recipient and/or subject, and the When I send the following (e)mail: step gains an attachments table column so tests can send mails with attachments in the first place. This makes it possible to verify attachment delivery end to end without writing custom step code.
-
[ #734 ] Added steps to run a failing drush command and assert its output. @AlexSkrypnyk ( #866 ) New I run the failing drush command steps run a Drush command expected to exit non-zero and capture its output so the existing the drush output should contain/match steps can assert on it, failing the step if the command unexpectedly succeeds. This closes the gap where a non-zero exit previously aborted the scenario before you could inspect the error output.
-
[ #115 ] Added 'MappingContext' resolving '{{ Key }}' tokens from 'mappings' config. @AlexSkrypnyk ( #865 ) A new MappingContext replaces {{ Key }} tokens in any step argument or table cell with values defined under a new mappings key in behat.yml , letting you centralise shared test data (URLs, labels, IDs) in one place instead of repeating literals across feature files. Keys must be globally unique - duplicates are rejected at config load - and an unknown key fails the step immediately rather than passing through unresolved.
All changes
-
[ #874 ] Removed the 'field_parser: legacy' parser. @AlexSkrypnyk ( #880 ) Deletes the field_parser config node, the legacy value, and the backing LegacyEntityFieldParser class, leaving EntityFieldParser as the sole parser with no configuration. Any field_parser key in behat.yml now produces a hard configuration error on load.
-
[ #876 ] Removed the 'region_map' configuration key. @AlexSkrypnyk ( #879 ) Drops the region_map key from the config schema in favour of the identically structured regions key, so a stale region_map now fails to load with an "Unrecognized option" error. Rename the key to regions to upgrade.
-
[ #875 ] Removed flat message selector keys. @AlexSkrypnyk ( #878 ) Removes the flat message_selector , error_message_selector , success_message_selector , and warning_message_selector keys, so selectors must now live under the nested selectors.messages: map. An unconfigured selector throws a RuntimeException that names the exact nested path to add.
-
[ #873 ] Removed the legacy '<?name>' random token syntax. @AlexSkrypnyk ( #877 ) Removes the <?name> token form and the legacy parsing path from RandomContext , leaving the typed [?name:type,args] syntax as the only supported form. As a result RandomContext no longer implements ParametersAwareInterface or DeprecationInterface , and the per-run [Deprecation] notices it printed are gone.
-
Switched back to stable DrupalDriver. @AlexSkrypnyk ( #872 ) Restores the drupal/drupal-driver requirement to a stable version range, replacing the temporary dev-master pin used while driver-side APIs needed by recent features were still unreleased. Consumers get a stable, tagged driver constraint again.
-
Updated information about maintainers. @AlexSkrypnyk ( #871 ) Refreshes the project's maintainer information. A documentation-only change with no effect on the extension's behaviour.
-
[ #597 ] Added HTTP Basic authentication support for sites behind webserver-level basic auth. @AlexSkrypnyk ( #870 ) Adds first-class HTTP Basic auth: credentials from a new basic_auth config node (or the base_url userinfo) are applied to the Mink session and re-applied automatically after each reset, so logging into a site behind Apache/Nginx basic auth no longer fails with a 401 . JavaScript/Selenium drivers, which cannot set request headers, fall back to the base_url userinfo and degrade to a silent no-op where unsupported.
-
[ #536 ] Added best-practice docs and a tested example for module-shipped Behat contexts. @AlexSkrypnyk ( #869 ) Adds a "Shipping contexts in a module" guide covering directory layout, namespacing, and PSR-4 autoloading for standalone Behat runs, plus a working ExampleContext and helper trait in the behat_test fixture module that CI exercises under --strict . This documents the recommended replacement for the removed sub-context auto-discovery.
-
[ #813 ] Added '@AfterScenario' cleanup of files attached through the UI. @AlexSkrypnyk ( #868 ) Tracks files uploaded via the I attach the file step and deletes their managed-file entities after each scenario, preventing Drupal from renaming a re-uploaded file (e.g. image.png to image_0.png ) and breaking path-based assertions. Opt out per scenario or feature with @no-file-cleanup ; the hook is a no-op on blackbox and other non-in-process drivers.
-
[ #672 ] Added email attachment assertion steps to 'MailContext'. @AlexSkrypnyk ( #867 ) Adds four Then steps that assert a sent email carries specific attachment(s), with optional recipient and subject filters, and extends When I send the following (e)mail: with an attachments table column so such mails can be sent in tests. Lets you verify attachment delivery without writing custom step definitions.
-
[ #734 ] Added steps to run a failing drush command and assert its output. @AlexSkrypnyk ( #866 ) Adds I run the failing drush command steps that execute a Drush command expected to exit non-zero, capture its output for the existing the drush output should contain/match assertions, and fail if the command unexpectedly exits 0. Previously a non-zero exit aborted the scenario before its error output could be checked.
-
[ #115 ] Added 'MappingContext' resolving '{{ Key }}' tokens from 'mappings' config. @AlexSkrypnyk ( #865 ) Adds a driver-free MappingContext that substitutes {{ Key }} tokens in step arguments and table cells with values defined under a new mappings key in behat.yml . Keys must be globally unique (dupl...
Read more
Contributors
AlexSkrypnyk
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
All reactions
-
v6.0.0-rc219 May 2026 pre-releaseRelease notes
Open source →What's new since v6.0.0-rc1
- [#857] Allowed literal '"' inside unquoted scalar values. @AlexSkrypnyk (#858)
Full Changelog: v6.0.0-rc1...v6.0.0-rc2
Release notes
Open source →- Prepared v6 stable release: pinned 'drupal/drupal-driver' to stable v3 and tidied release docs. @AlexSkrypnyk ( #859 )
Full Changelog : v6.0.0-rc2...v6.0.0
@AlexSkrypnyk
-
v6.0.0-rc118 May 2026 pre-releaseRelease notes
Open source →What's new since v6.0.0-alpha1
- Bumped 'drupal/drupal-driver' to 3.0.0-rc1 and tightened 'minimum-stability' to RC. @AlexSkrypnyk (#856)
- [#854] Made 'Before/AfterEntityCreate' hooks fire for every entity create path. @AlexSkrypnyk (#855)
- [#194] Added 'Given the following :type entities:' step for generic entity creation. @AlexSkrypnyk (#853)
- Allowed bundle fields defined in hooks to be recognised. @AlexSkrypnyk (#852)
Full Changelog: v6.0.0-alpha1...v6.0.0-rc1
Release notes
Open source →- [ #857 ] Allowed literal '"' inside unquoted scalar values. @AlexSkrypnyk ( #858 )
Full Changelog : v6.0.0-rc1...v6.0.0-rc2
@AlexSkrypnyk
Contributors
AlexSkrypnyk
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
All reactions
-
v6.0.0-alpha104 May 2026 pre-releaseRelease notes
Open source →What's new since v5.4.0
Version 6.0 enforces a consistent set of step-definition conventions across all bundled contexts. The conventions are documented in
CONTRIBUTING.mdand validated byscripts/docs.php; CI fails on any violation.See
UPGRADING.mdfor detailed migration instructions covering all breaking changes, and the table below for a summary of highlights and breaking changes.Highlights
- Updated 'drupal/drupal-driver' to 3.x and migrated to capability-based API. @AlexSkrypnyk (#803)
The monolithicDriverInterfaceis replaced with capability interfaces (AuthenticationCapabilityInterface,MailCapabilityInterface,ConfigCapabilityInterface,ContentCapabilityInterface,CacheCapabilityInterface,CronCapabilityInterface,LanguageCapabilityInterface,RoleCapabilityInterface,UserCapabilityInterface) and every CRUD method is renamed to a verb-noun form. Migration: bumpdrupal/drupal-driverto^3.0, rename driver calls (createNode→nodeCreate,runCron→cronRun,clearCache→cacheClear,startCollectingMail→mailStartCollecting,getMail→mailGet,sendMail→mailSend, etc.), and add capability-interface guards before invoking driver methods in subclasses. - [#469] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk (#844)
RandomContextships six built-in generators (string,name,machine_name,int,email,uuid) selectable via[?name:type,args], with subclasses able to register custom types by overriding a single method. Equivalent literals share a scenario-scoped cache key, so[?title],[?title:string], and[?title:string,10]all produce the same value within one scenario. - [#258] Added BigPipe NOJS cookie bypass to 'DrupalContext'. @AlexSkrypnyk (#821)
Tagging a scenario with@bigpipesets thebig_pipe_nojscookie on non-JS Mink drivers (BrowserKit, Goutte) so Drupal renders pages fully server-side instead of leaving placeholders that only the BigPipe JS would replace. This makes authenticated-user assertions like "I should see Log out" reliable on BigPipe-enabled sites without switching to a real browser. - [#732] Added 'login_field' configuration to submit a custom user property as the login value. @AlexSkrypnyk (#820)
Sites that authenticate by email rather than username (viamail_login,email_registration, or similar contrib) can now setlogin_field: mail(or any other user property) underDrupal\DrupalExtension, and the auth manager submits that property value to the username field instead of the hardcodedname. The default remainsname, so existing setups are unaffected. - [#766] Added modern entity-field parser with 'field_parser' configuration flag. @AlexSkrypnyk (#818)
The newEntityFieldParserintroduces double-quote escaping, named-column compound syntax (country:"BE", locality:"Brussel"), structuredParseExceptionerrors with file/line context, and aggregated multi-error reporting. Bare-is now treated as literal text in scalar mode, so entity reference titles like"My article - Part 2"no longer require escaping. - Added 'suppress_deprecations' configuration and 'BEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONS' environment variable. @AlexSkrypnyk (#836)
Both thesuppress_deprecationsconfig key and theBEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONSenv var silence the extension's[Deprecation]notices to STDERR, with the env var winning over config. This lets teams roll forward through migrations without their CI failing on deprecation noise from extension-detected legacy patterns. - [#647] Added 'BEHAT_DRUPALEXTENSION_DISABLE_CLEANUP' env var to skip scenario teardown. @AlexSkrypnyk (#845)
SettingBEHAT_DRUPALEXTENSION_DISABLE_CLEANUP=1(ortrue/yes/on) skips theAfterScenarioteardown of entities, users, and roles, and intentionally leaves the last logged-in session open so a failing scenario's database state and browser session can be inspected directly. Intended for ad-hoc local debugging - leave it off in CI. - [#479] Added verbose diagnostic output to AJAX timeout exception. @AlexSkrypnyk (#838)
iWaitForAjaxToFinish()now captures the current URL,jQuery.activecount, animated-element count, and each activeDrupal.ajax.instancesentry (selector, event, URL) at the moment of timeout and embeds them in a structured multi-line error message. Replaces the previous single-line "Unable to complete AJAX request." message that gave no clue why the browser was busy.
Breaking changes
- Updated 'drupal/drupal-driver' to 3.x and migrated to capability-based API. @AlexSkrypnyk (#803)
The monolithicDriverInterfaceis replaced with capability interfaces (AuthenticationCapabilityInterface,MailCapabilityInterface,ConfigCapabilityInterface,ContentCapabilityInterface,CacheCapabilityInterface,CronCapabilityInterface,LanguageCapabilityInterface,RoleCapabilityInterface,UserCapabilityInterface) and every CRUD method is renamed to a verb-noun form. Migration: bumpdrupal/drupal-driverto^3.0, rename driver calls (createNode→nodeCreate,runCron→cronRun,clearCache→cacheClear,startCollectingMail→mailStartCollecting,getMail→mailGet,sendMail→mailSend, etc.), and add capability-interface guards before invoking driver methods in subclasses. - [#469] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk (#844)
The legacy<?name>random-token form still works in 6.0 but emits a[Deprecation]notice once per literal. Migration: replace<?name>with[?name](equivalent default) or one of the typed forms ([?slug:machine_name],[?age:int,18,99],[?email:email],[?id:uuid]); the legacy form is scheduled for removal in 6.1. - Renamed 'assert' action steps and tightened validator. @AlexSkrypnyk (#837)
Action methods that previously usedassertXxxnames are renamed to action-style names (e.g.assertCron→iRunCron,assertAuthenticatedByRole→iAmLoggedInAsUserWithRole,assertDrushCommand→iRunDrush), and three negative-message steps move from@Givento@Thenwith matching method renames. Migration: see the rename table inMIGRATION.mdand search-and-replace overridden method names in your subclasses; step text is unchanged for most steps but the three re-classified steps now require@Thensemantics. - [#824] Converted 'BatchContext' into 'BatchTrait' on 'DrupalContext'. @AlexSkrypnyk (#835)
BatchContextis deleted; itsiWaitForTheBatchJobToFinishandthereIsAnItemInTheSystemQueuesteps are now provided byDrupalContextviaBatchTrait. Migration: removeDrupal\DrupalExtension\Context\BatchContextfrom thecontexts:list in yourbehat.yml- the steps are loaded automatically withDrupalContext. - Moved driver and mail manager classes under 'Drupal\DrupalExtension\Manager' namespace. @AlexSkrypnyk (#833)
Drupal\DrupalDriverManager→Drupal\DrupalExtension\Manager\DriverManager(theDrupalprefix drops),Drupal\DrupalDriverManagerInterface→Drupal\DrupalExtension\Manager\DriverManagerInterface,Drupal\DrupalMailManager→Drupal\DrupalExtension\Manager\DrupalMailManager,Drupal\DrupalMailManagerInterface→Drupal\DrupalExtension\Manager\DrupalMailManagerInterface. Migration: updateusestatements and any FQCN references; the user and authentication managers retain their existing namespaces. - Moved 'ParametersAwareInterface' to root namespace alongside 'ParametersTrait'. @AlexSkrypnyk (#832)
The interface moved fromDrupal\DrupalExtension\Context\ParametersAwareInterfacetoDrupal\DrupalExtension\ParametersAwareInterface. Migration: updateusestatements to import from the root namespace; signatures (setParameters,getParameter) are unchanged. - [#825] Extracted Drupal AJAX handling into 'DrupalAjaxTrait'. @AlexSkrypnyk (#830)
The three Drupal-specific AJAX methods (iWaitForAjaxToFinish,beforeJavascriptStep,afterJavascriptStep) move fromMinkContextintoDrupalAjaxTrait.MinkContextcomposes the trait so existing consumers see no behavior change, but downstream subclasses that overrode these methods inline must now override the trait methods or composeDrupalAjaxTraitdirectly. - Moved 'ajax_timeout' to 'Drupal\DrupalExtension' and renamed parameters interface. @AlexSkrypnyk (#829)
ajax_timeoutconfiguration moves fromDrupal\MinkExtensiontoDrupal\DrupalExtension, and the parameters API drops itsDrupalprefix:DrupalParametersAwareInterface→ParametersAwareInterface,DrupalParametersTrait→ParametersTrait,setDrupalParameters→setParameters,getDrupalParameter→getParameter,$drupalParameters→$parameters. Migration: relocateajax_timeoutinbehat.ymland rename interface/trait/method/property references in subclasses. - [#822] Rebased MessageContext on RawMinkContext and moved message selectors to Drupal\MinkExtension. @AlexSkrypnyk (#827)
MessageContextnow extendsRawMinkContextinstead ofRawDrupalContext, so it can be registered in any Mink suite without booting the Drupal driver; subclasses that depended onRawDrupalContexthelpers must composeParametersTraitthemselves or change their base. The four message selectors (message_selector,error_message_selector,success_message_selector,warning_message_selector) move fromDrupal\DrupalExtension.selectors:toDrupal\MinkExtension.selectors:; the legacy location still works in 6.0 with a one-shot deprecation notice and is removed in 6.1. - [#258] Added BigPipe NOJS cookie bypass to 'DrupalContext'. @AlexSkrypnyk (#821)
This is additive (opt-in via@bigpipetag) but ships as part ofDrupalContext, so subclasses that override the existingBeforeScenario/BeforeStephook methods without calling parent will silently disable the bypass. Migration: if you override these hooks, callparent::or useBigPipeTraitexplicitly so the cookie management still runs. - Replaced Sphinx documentation with Markdown-based docs in 'docs/'. @AlexSkrypnyk (#819)
The Read the Docs / Sphinx tree underdoc/is removed and replaced with Markdown underdocs/. Migration: update bookmarks and any internal links pointing atdoc/*.rstto the newdocs/*.mdpaths; the Read the Docs site is no longer maintained. - [#766] Added modern entity-field parser with 'field_parser' configuration flag. @AlexSkrypnyk (#818)
The default field-value parser is nowEntityFieldParser, which uses double-quote escaping and detects compound mode bykey:"value"form rather than-separator spacing. Migration: setfield_parser: legacyunderDrupal\DrupalExtensioninbehat.ymlto keep the 5.x behavior (emits a one-shot deprecation notice); the legacy parser is removed in 6.1. Cells containing-no longer require escaping under the modern parser. - Renamed 'classifier()' calls to 'getFieldClassifier()' to match drupal-driver API. @AlexSkrypnyk (#817)
The drupal-driverCoreInterface::classifier()accessor was renamed togetFieldClassifier(). Migration: replace direct calls of$driver->getCore()->classifier()with$driver->getCore()->getFieldClassifier(); no backwards-compatibility shim is provided. - [#337] Replaced 'stdClass' entity stubs with typed 'EntityStub' from driver. @AlexSkrypnyk (#814)
Hook scopes (BeforeNodeCreateScope,AfterNodeCreateScope, etc.) and step methods now exposeEntityStubInterfaceinstead of\stdClass, andEntityScope::getEntity()is renamed togetStub(). Migration: replace ad-hoc property reads with$stub->getValue('title')and writes with$stub->setValue(...); replace(object) [...]constructions withnew EntityStub($entity_type, $bundle, $values); replace$saved->nid/$saved->tidwith$stub->getId(); renamegetEntity()calls togetStub(). - [#806] Removed 'store' parameter from 'DrupalMailManager' and 'DrupalMailManagerInterface'. @AlexSkrypnyk (#812)
getMail()andclearMail()no longer accept a$storeargument because the v3 driver only exposes a single implicit collector. Migration: drop the$storeargument from any direct calls and from any subclass overrides that implementDrupalMailManagerInterface; tracked counts inRawMailContextare now a scalarintrather than an array keyed by store. - [#752] Replaced generic exceptions with typed Mink exceptions across bundled contexts. @AlexSkrypnyk (#811)
Roughly 30\Exceptionthrows across the bundled contexts are replaced withBehat\Mink\Exception\ElementNotFoundException(lookups),Behat\Mink\Exception\ExpectationException(assertion mismatches), or\RuntimeException(configuration errors). Migration: any tests or hooks that catch\Exceptionfrom these steps continue to work, but code that asserts on specific exception classes or messages must update to the typed classes; Mink exceptions append URL and page-snippet context via__toString(). - Enforced step-definition conventions for v6 across all bundled contexts. @AlexSkrypnyk (#810)
Roughly 50@Thenmethods are renamed to<concern>Assert<action>form, around 29 step texts are updated to satisfy the new conventions (e.g.Given users:→Given the following users:,Then drush output should contain X→Then the drush output should contain X,Then I log out→When I log out), and several methods are re-categorised from@Thento@Whenfor side-effect steps. Migration: search-and-replace step text in your feature files using the table inMIGRATION.md; rename overridden method names in your subclasses. - Removed deprecated APIs in preparation for 6.0.0. @AlexSkrypnyk (#809)
Subcontext auto-discovery (subcontexts.pathsconfig,.behat.incloading,DrupalSubContextInterface,DrupalSubContextBase), the annotation-based hook reader (Annotation\Reader),RawDrupalContext::loggedInWithRole(), and theAnnotatedDefinitionProposalshim are all removed. Migration: rewrite subcontexts as regular Behat contexts using PHP attributes; remove anysubcontexts:block frombehat.yml; replaceloggedInWithRole()calls with the standard authenticated-user flow. - [#823] Rebased 'RandomContext' on bare Behat context interface. @AlexSkrypnyk (#834)
RandomContextno longer extendsRawDrupalContext; it implementsBehat\Behat\Context\Contextdirectly and instantiates aRandomlazily. Migration: subclassers that relied on inherited Drupal/Mink helpers must compose those traits themselves or change their base class; documented inMIGRATION.mdunder "RandomContext base class".
All changes
- [#356] Strengthened 'author' property test to assert author is applied. @AlexSkrypnyk (#847)
The existing scenario for theauthorproperty inGiven the following :type content:was rewritten as a direct test that creates an article withauthor = Joe User, visits/admin/content, and assertsJoe Userappears in the article's author column. Previously the scenario only verified the syntax did not error. - [#647] Added 'BEHAT_DRUPALEXTENSION_DISABLE_CLEANUP' env var to skip scenario teardown. @AlexSkrypnyk (#845)
SettingBEHAT_DRUPALEXTENSION_DISABLE_CLEANUP=1(ortrue/yes/on) skips theAfterScenarioteardown of entities, users, and roles, and intentionally leaves the last logged-in session open so a failing scenario's database state and browser session can be inspected directly. Intended for ad-hoc local debugging - leave it off in CI. - [#735] Added test coverage and docs for options in 'I run drush :command :arguments' step. @AlexSkrypnyk (#846)
The existingI run drush :command :argumentsstep already supported flags because the arguments string is appended verbatim to the shell command, but this was undocumented. The docblock now shows a combined positional-argument-plus-flag example, and a new scenario exercisesconfig:get "system.site uuid --format=string"end to end. - [#469] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk (#844)
RandomContextships six built-in generators (string,name,machine_name,int,email,uuid) selectable via[?name:type,args], with subclasses able to register custom types by overriding a single method. Equivalent literals share a scenario-scoped cache key, so[?title],[?title:string], and[?title:string,10]all produce the same value within one scenario. - [#733] Added test coverage and docs for configurable login and logout URLs. @AlexSkrypnyk (#843)
Three new PHPUnit tests pin thevisit()argument so a regression that hardcoded/userback intoDrupalAuthenticationManagerwould now fail loudly, and thelogout_confirm_urlentry was added to the documentedtext:example so all three login/logout URL keys are visible together. - [#415] Added test coverage for URI-only link field values. @AlexSkrypnyk (#841)
Five new Behat scenarios exercise URI-only link field values - bare URIs, comma-separated lists, the nameduri:compound column, and a mixed scenario - covering the upstreamLinkHandlerfix in drupal-driver that wraps a bare string as['uri' => $value]. - Fixed chrome port and AJAX assertion after Pygmy and Lagoon stack migration. @AlexSkrypnyk (#840)
The Selenium VNC port mapping was changed from a fixed7900:7900host binding to a Docker-assigned ephemeral port to avoid conflicts, and the AJAX timeout assertion inFeatureContextno longer hardcodeshttp://blackboxso it works against the new in-process PHP server (http://cli:8888).CONTRIBUTING.mdnow documents how to read the dynamic VNC URL fromahoy info. - [#730] Migrated local stack to Pygmy and Lagoon images. @AlexSkrypnyk (#839)
The Wodby + Traefik local stack is replaced with Lagoon container images fronted by Pygmy, matching the layout used bydrevops/behat-steps. The blackbox nginx container is dropped in favour of an in-process PHP server started byBlackboxServerContextinside theclicontainer, thedrupal_httpsprofile is removed, and provisioning steps move into a singlescripts/provision.shshared byahoyand CI. - [#479] Added verbose diagnostic output to AJAX timeout exception. @AlexSkrypnyk (#838)
iWaitForAjaxToFinish()now captures the current URL,jQuery.activecount, animated-element count, and each activeDrupal.ajax.instancesentry (selector, event, URL) at the moment of timeout and embeds them in a structured multi-line error message. Replaces the previous single-line "Unable to complete AJAX request." message that gave no clue why the browser was busy. - Renamed 'assert' action steps and tightened validator. @AlexSkrypnyk (#837)
Action methods that previously usedassertXxxnames are renamed to action-style names (e.g.assertCron→iRunCron,assertAuthenticatedByRole→iAmLoggedInAsUserWithRole,assertDrushCommand→iRunDrush), and three negative-message steps move from@Givento@Thenwith matching method renames. The validator now hard-fails when@Given/@Whenstep text containsshouldor method names containAssert. - Added 'suppress_deprecations' configuration and 'BEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONS' environment variable. @AlexSkrypnyk (#836)
Both thesuppress_deprecationsconfig key and theBEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONSenv var silence the extension's[Deprecation]notices to STDERR, with the env var winning over config. This lets teams roll forward through migrations without their CI failing on deprecation noise from extension-detected legacy patterns. - [#824] Converted 'BatchContext' into 'BatchTrait' on 'DrupalContext'. @AlexSkrypnyk (#835)
BatchContextis deleted; itsiWaitForTheBatchJobToFinishandthereIsAnItemInTheSystemQueuesteps are now provided byDrupalContextviaBatchTrait. Both steps depend on\Drupal::calls, so hosting them on the API-driver-onlyDrupalContextkeeps them behind a bootstrapped Drupal kernel and prevents silent failures under Blackbox or Drush drivers. - Moved driver and mail manager classes under 'Drupal\DrupalExtension\Manager' namespace. @AlexSkrypnyk (#833)
Drupal\DrupalDriverManager→Drupal\DrupalExtension\Manager\DriverManager(theDrupalprefix drops because driver routing is generic infrastructure), and the mail manager and its interface move alongside the user/auth managers under the same namespace. The deadpsr-0autoload entry incomposer.jsonis removed. - [#823] Rebased 'RandomContext' on bare Behat context interface. @AlexSkrypnyk (#834)
RandomContextno longer extendsRawDrupalContext; it implementsBehat\Behat\Context\Contextdirectly and instantiates aRandomlazily, so the context can be registered in any Behat suite regardless of whether the Drupal extension is loaded. New PHPUnit tests cover the standalone shape and the token substitution contract. - Moved 'ParametersAwareInterface' to root namespace alongside 'ParametersTrait'. @AlexSkrypnyk (#832)
The interface moved fromDrupal\DrupalExtension\Context\ParametersAwareInterfacetoDrupal\DrupalExtension\ParametersAwareInterfaceso it sits next to its companionParametersTraitandRegionTrait.setParameters/getParametersignatures are unchanged - only the FQN moves. - [#826] Documented 'ParametersTrait' and 'RegionTrait' as Mink-only consumption points. @AlexSkrypnyk (#831)
The two traits work on anyRawMinkContextconsumer without requiring a Drupal driver bootstrap; the trait docblocks and a new "Mink-only contexts" section indocs/contexts.mdmake the pattern explicit. The bundledMinkContext,MarkupContext, andMessageContextalready follow this pattern. - [#825] Extracted Drupal AJAX handling into 'DrupalAjaxTrait'. @AlexSkrypnyk (#830)
The three Drupal-specific AJAX methods (iWaitForAjaxToFinish,beforeJavascriptStep,afterJavascriptStep) move fromMinkContextintoDrupalAjaxTrait;MinkContextcomposes the trait so existing consumers see no behavior change. The trait can now be reused in custom Mink-based contexts without inheriting fromMinkContext. - Moved 'ajax_timeout' to 'Drupal\DrupalExtension' and renamed parameters interface. @AlexSkrypnyk (#829)
ajax_timeoutconfiguration moves fromDrupal\MinkExtensiontoDrupal\DrupalExtensionso all custom config lives under one extension, and the parameters API drops itsDrupalprefix throughout: interface, trait, methods, and property name. TheDrupal\MinkExtensionextension now only registers the BrowserKit driver factory. - Moved 'ClassGenerator' out of 'Context/ContextClass/' into a top-level 'Generator/' namespace. @AlexSkrypnyk (#828)
ClassGenerator(Behat'sbehat --initscaffolder for Drupal context classes) moves fromDrupal\DrupalExtension\Context\ContextClasstoDrupal\DrupalExtension\Generator, away from the actual step-defining contexts. The class is only instantiated by Behat's DI from inside the extension, so no downstream user code is affected. New PHPUnit tests cover both namespaced and rootless context-class generation. - [#822] Rebased MessageContext on RawMinkContext and moved message selectors to Drupal\MinkExtension. @AlexSkrypnyk (#827)
MessageContextnow extendsRawMinkContextinstead ofRawDrupalContext, so blackbox-only suites no longer pay the cost of booting the Drupal driver stack. The four message selectors move fromDrupal\DrupalExtension.selectors:to a newDrupal\MinkExtension.selectors:map; the legacy location keeps working in 6.0 with a one-shot deprecation notice. - [#258] Added BigPipe NOJS cookie bypass to 'DrupalContext'. @AlexSkrypnyk (#821)
Tagging a scenario with@bigpipesets thebig_pipe_nojscookie on non-JS Mink drivers so Drupal renders pages fully server-side instead of leaving placeholders that only the BigPipe JS would replace. The cookie is re-applied on every step because login redirects drop session cookies, and the trait is a no-op when the active driver supports JavaScript. - [#732] Added 'login_field' configuration to submit a custom user property as the login value. @AlexSkrypnyk (#820)
Sites that authenticate by email rather than username (viamail_login,email_registration, or similar contrib) can now setlogin_field: mail(or any other user property) underDrupal\DrupalExtension, and the auth manager submits that property value to the username field instead of the hardcodedname. The default remainsname, so existing setups are unaffected. - Replaced Sphinx documentation with Markdown-based docs in 'docs/'. @AlexSkrypnyk (#819)
The Read the Docs / Sphinx tree underdoc/is removed and replaced with plain Markdown underdocs/covering installation, configuration, drivers, contexts, hooks, and writing tests. The Read the Docs badge and links inREADME.mdare also dropped. - [#766] Added modern entity-field parser with 'field_parser' configuration flag. @AlexSkrypnyk (#818)
The newEntityFieldParserintroduces double-quote escaping, named-column compound syntax (country:"BE", locality:"Brussel"), structuredParseExceptionerrors with file/line context, and aggregated multi-error reporting. Bare-is now treated as literal text in scalar mode, so entity reference titles like"My article - Part 2"no longer require escaping. - [#766] Extracted field parsing into 'ParserInterface' and 'LegacyEntityFieldsParser'. @AlexSkrypnyk (#816)
This is a pure refactor that lifts the cell-level field-value parsing out ofRawDrupalContext::parseEntityFields()into a newLegacyEntityFieldsParserimplementing a newParserInterface. Behavior is unchanged in this PR; the contract is introduced first so the new modern parser (#818) can land against a stable interface. - Renamed 'classifier()' calls to 'getFieldClassifier()' to match drupal-driver API. @AlexSkrypnyk (#817)
The drupal-driverCoreInterface::classifier()accessor was renamed togetFieldClassifier()upstream, and this PR updates the single call site inparseEntityFields()and the four mock setups inRawDrupalContextTest. No backwards-compatibility shim is provided. - Removed PHPSpec-based unit testing from the project. @AlexSkrypnyk (#815)
The 22 PHPSpec spec files, thetest-phpspecahoy command, and thephpspec/phpspecComposer dev dependency are all removed; PHPUnit and Behat already cover the same ground. CI now runs one fewer parallel step. - [#337] Replaced 'stdClass' entity stubs with typed 'EntityStub' from driver. @AlexSkrypnyk (#814)
Hook scopes and step methods now exposeEntityStubInterfaceinstead of\stdClass, four parallel creation paths collapse into a singleentityCreate()entry point, and the fourcleanNodes()/cleanTerms()/cleanUsers()/cleanLanguages()AfterScenario hooks become a singlecleanEntities()reverse-walk.(object) [...]constructions becomenew EntityStub($type, $bundle, $values)and ad-hoc property access becomesgetValue()/setValue(). - [#806] Removed 'store' parameter from 'DrupalMailManager' and 'DrupalMailManagerInterface'. @AlexSkrypnyk (
Note truncated.
Release notes
Open source →Version 6.0 enforces a consistent set of step-definition conventions across all bundled contexts. The conventions are documented in CONTRIBUTING.md and validated by scripts/docs.php ; CI fails on any violation.
See UPGRADING.md for detailed migration instructions covering all breaking changes, and the table below for a summary of highlights and breaking changes.
Highlights
-
Updated 'drupal/drupal-driver' to 3.x and migrated to capability-based API. @AlexSkrypnyk ( #803 ) The monolithic DriverInterface is replaced with capability interfaces ( AuthenticationCapabilityInterface , MailCapabilityInterface , ConfigCapabilityInterface , ContentCapabilityInterface , CacheCapabilityInterface , CronCapabilityInterface , LanguageCapabilityInterface , RoleCapabilityInterface , UserCapabilityInterface ) and every CRUD method is renamed to a verb-noun form. Migration: bump drupal/drupal-driver to ^3.0 , rename driver calls ( createNode → nodeCreate , runCron → cronRun , clearCache → cacheClear , startCollectingMail → mailStartCollecting , getMail → mailGet , sendMail → mailSend , etc.), and add capability-interface guards before invoking driver methods in subclasses.
-
[ #469 ] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk ( #844 ) RandomContext ships six built-in generators ( string , name , machine_name , int , email , uuid ) selectable via [?name:type,args] , with subclasses able to register custom types by overriding a single method. Equivalent literals share a scenario-scoped cache key, so [?title] , [?title:string] , and [?title:string,10] all produce the same value within one scenario.
-
[ #258 ] Added BigPipe NOJS cookie bypass to 'DrupalContext'. @AlexSkrypnyk ( #821 ) Tagging a scenario with @bigpipe sets the big_pipe_nojs cookie on non-JS Mink drivers (BrowserKit, Goutte) so Drupal renders pages fully server-side instead of leaving placeholders that only the BigPipe JS would replace. This makes authenticated-user assertions like "I should see Log out" reliable on BigPipe-enabled sites without switching to a real browser.
-
[ #732 ] Added 'login_field' configuration to submit a custom user property as the login value. @AlexSkrypnyk ( #820 ) Sites that authenticate by email rather than username (via mail_login , email_registration , or similar contrib) can now set login_field: mail (or any other user property) under Drupal\DrupalExtension , and the auth manager submits that property value to the username field instead of the hardcoded name . The default remains name , so existing setups are unaffected.
-
[ #766 ] Added modern entity-field parser with 'field_parser' configuration flag. @AlexSkrypnyk ( #818 ) The new EntityFieldParser introduces double-quote escaping, named-column compound syntax ( country:"BE", locality:"Brussel" ), structured ParseException errors with file/line context, and aggregated multi-error reporting. Bare - is now treated as literal text in scalar mode, so entity reference titles like "My article - Part 2" no longer require escaping.
-
Added 'suppress_deprecations' configuration and 'BEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONS' environment variable. @AlexSkrypnyk ( #836 ) Both the suppress_deprecations config key and the BEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONS env var silence the extension's [Deprecation] notices to STDERR, with the env var winning over config. This lets teams roll forward through migrations without their CI failing on deprecation noise from extension-detected legacy patterns.
-
[ #647 ] Added 'BEHAT_DRUPALEXTENSION_DISABLE_CLEANUP' env var to skip scenario teardown. @AlexSkrypnyk ( #845 ) Setting BEHAT_DRUPALEXTENSION_DISABLE_CLEANUP=1 (or true / yes / on ) skips the AfterScenario teardown of entities, users, and roles, and intentionally leaves the last logged-in session open so a failing scenario's database state and browser session can be inspected directly. Intended for ad-hoc local debugging - leave it off in CI.
-
[ #479 ] Added verbose diagnostic output to AJAX timeout exception. @AlexSkrypnyk ( #838 ) iWaitForAjaxToFinish() now captures the current URL, jQuery.active count, animated-element count, and each active Drupal.ajax.instances entry (selector, event, URL) at the moment of timeout and embeds them in a structured multi-line error message. Replaces the previous single-line "Unable to complete AJAX request." message that gave no clue why the browser was busy.
Breaking changes
-
Updated 'drupal/drupal-driver' to 3.x and migrated to capability-based API. @AlexSkrypnyk ( #803 ) The monolithic DriverInterface is replaced with capability interfaces ( AuthenticationCapabilityInterface , MailCapabilityInterface , ConfigCapabilityInterface , ContentCapabilityInterface , CacheCapabilityInterface , CronCapabilityInterface , LanguageCapabilityInterface , RoleCapabilityInterface , UserCapabilityInterface ) and every CRUD method is renamed to a verb-noun form. Migration: bump drupal/drupal-driver to ^3.0 , rename driver calls ( createNode → nodeCreate , runCron → cronRun , clearCache → cacheClear , startCollectingMail → mailStartCollecting , getMail → mailGet , sendMail → mailSend , etc.), and add capability-interface guards before invoking driver methods in subclasses.
-
[ #469 ] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk ( #844 ) The legacy <?name> random-token form still works in 6.0 but emits a [Deprecation] notice once per literal. Migration: replace <?name> with [?name] (equivalent default) or one of the typed forms ( [?slug:machine_name] , [?age:int,18,99] , [?email:email] , [?id:uuid] ); the legacy form is scheduled for removal in 6.1.
-
Renamed 'assert' action steps and tightened validator. @AlexSkrypnyk ( #837 ) Action methods that previously used assertXxx names are renamed to action-style names (e.g. assertCron → iRunCron , assertAuthenticatedByRole → iAmLoggedInAsUserWithRole , assertDrushCommand → iRunDrush ), and three negative-message steps move from @Given to @Then with matching method renames. Migration: see the rename table in MIGRATION.md and search-and-replace overridden method names in your subclasses; step text is unchanged for most steps but the three re-classified steps now require @Then semantics.
-
[ #824 ] Converted 'BatchContext' into 'BatchTrait' on 'DrupalContext'. @AlexSkrypnyk ( #835 ) BatchContext is deleted; its iWaitForTheBatchJobToFinish and thereIsAnItemInTheSystemQueue steps are now provided by DrupalContext via BatchTrait . Migration: remove Drupal\DrupalExtension\Context\BatchContext from the contexts: list in your behat.yml - the steps are loaded automatically with DrupalContext .
-
Moved driver and mail manager classes under 'Drupal\DrupalExtension\Manager' namespace. @AlexSkrypnyk ( #833 ) Drupal\DrupalDriverManager → Drupal\DrupalExtension\Manager\DriverManager (the Drupal prefix drops), Drupal\DrupalDriverManagerInterface → Drupal\DrupalExtension\Manager\DriverManagerInterface , Drupal\DrupalMailManager → Drupal\DrupalExtension\Manager\DrupalMailManager , Drupal\DrupalMailManagerInterface → Drupal\DrupalExtension\Manager\DrupalMailManagerInterface . Migration: update use statements and any FQCN references; the user and authentication managers retain their existing namespaces.
-
Moved 'ParametersAwareInterface' to root namespace alongside 'ParametersTrait'. @AlexSkrypnyk ( #832 ) The interface moved from Drupal\DrupalExtension\Context\ParametersAwareInterface to Drupal\DrupalExtension\ParametersAwareInterface . Migration: update use statements to import from the root namespace; signatures ( setParameters , getParameter ) are unchanged.
-
[ #825 ] Extracted Drupal AJAX handling into 'DrupalAjaxTrait'. @AlexSkrypnyk ( #830 ) The three Drupal-specific AJAX methods ( iWaitForAjaxToFinish , beforeJavascriptStep , afterJavascriptStep ) move from MinkContext into DrupalAjaxTrait . MinkContext composes the trait so existing consumers see no behavior change, but downstream subclasses that overrode these methods inline must now override the trait methods or compose DrupalAjaxTrait directly.
-
Moved 'ajax_timeout' to 'Drupal\DrupalExtension' and renamed parameters interface. @AlexSkrypnyk ( #829 ) ajax_timeout configuration moves from Drupal\MinkExtension to Drupal\DrupalExtension , and the parameters API drops its Drupal prefix: DrupalParametersAwareInterface → ParametersAwareInterface , DrupalParametersTrait → ParametersTrait , setDrupalParameters → setParameters , getDrupalParameter → getParameter , $drupalParameters → $parameters . Migration: relocate ajax_timeout in behat.yml and rename interface/trait/method/property references in subclasses.
-
[ #822 ] Rebased MessageContext on RawMinkContext and moved message selectors to Drupal\MinkExtension. @AlexSkrypnyk ( #827 ) MessageContext now extends RawMinkContext instead of RawDrupalContext , so it can be registered in any Mink s...
Read more
Contributors
AlexSkrypnyk
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
All reactions
- Updated 'drupal/drupal-driver' to 3.x and migrated to capability-based API. @AlexSkrypnyk (#803)
-
v5.4.016 Apr 2026Release notes
Open source →What's new since v5.3.3
Important
This is the last
5.xrelease with DrupalDriver2.xsupport. Only critical bug fixes will be worked on as patches for2.4, if required.
We are working on6.x, which will use the updated DrupalDriver API.- [#662] Added drag-and-drop step definition for MinkContext. @AlexSkrypnyk (#800)
- Changed default Drush binary to 'vendor/bin/drush' with automatic path resolution. @AlexSkrypnyk (#799)
- Added configurable 'login_wait' to fix post-login race condition on JS-heavy sites. @AlexSkrypnyk (#798)
Full Changelog: v5.3.3...v5.4.0
Release notes
Open source →Version 6.0 enforces a consistent set of step-definition conventions across all bundled contexts. The conventions are documented in CONTRIBUTING.md and validated by scripts/docs.php ; CI fails on any violation.
See UPGRADING.md for detailed migration instructions covering all breaking changes, and the table below for a summary of highlights and breaking changes.
Highlights
-
Updated 'drupal/drupal-driver' to 3.x and migrated to capability-based API. @AlexSkrypnyk ( #803 ) The monolithic DriverInterface is replaced with capability interfaces ( AuthenticationCapabilityInterface , MailCapabilityInterface , ConfigCapabilityInterface , ContentCapabilityInterface , CacheCapabilityInterface , CronCapabilityInterface , LanguageCapabilityInterface , RoleCapabilityInterface , UserCapabilityInterface ) and every CRUD method is renamed to a verb-noun form. Migration: bump drupal/drupal-driver to ^3.0 , rename driver calls ( createNode → nodeCreate , runCron → cronRun , clearCache → cacheClear , startCollectingMail → mailStartCollecting , getMail → mailGet , sendMail → mailSend , etc.), and add capability-interface guards before invoking driver methods in subclasses.
-
[ #469 ] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk ( #844 ) RandomContext ships six built-in generators ( string , name , machine_name , int , email , uuid ) selectable via [?name:type,args] , with subclasses able to register custom types by overriding a single method. Equivalent literals share a scenario-scoped cache key, so [?title] , [?title:string] , and [?title:string,10] all produce the same value within one scenario.
-
[ #258 ] Added BigPipe NOJS cookie bypass to 'DrupalContext'. @AlexSkrypnyk ( #821 ) Tagging a scenario with @bigpipe sets the big_pipe_nojs cookie on non-JS Mink drivers (BrowserKit, Goutte) so Drupal renders pages fully server-side instead of leaving placeholders that only the BigPipe JS would replace. This makes authenticated-user assertions like "I should see Log out" reliable on BigPipe-enabled sites without switching to a real browser.
-
[ #732 ] Added 'login_field' configuration to submit a custom user property as the login value. @AlexSkrypnyk ( #820 ) Sites that authenticate by email rather than username (via mail_login , email_registration , or similar contrib) can now set login_field: mail (or any other user property) under Drupal\DrupalExtension , and the auth manager submits that property value to the username field instead of the hardcoded name . The default remains name , so existing setups are unaffected.
-
[ #766 ] Added modern entity-field parser with 'field_parser' configuration flag. @AlexSkrypnyk ( #818 ) The new EntityFieldParser introduces double-quote escaping, named-column compound syntax ( country:"BE", locality:"Brussel" ), structured ParseException errors with file/line context, and aggregated multi-error reporting. Bare - is now treated as literal text in scalar mode, so entity reference titles like "My article - Part 2" no longer require escaping.
-
Added 'suppress_deprecations' configuration and 'BEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONS' environment variable. @AlexSkrypnyk ( #836 ) Both the suppress_deprecations config key and the BEHAT_DRUPALEXTENSION_SUPPRESS_DEPRECATIONS env var silence the extension's [Deprecation] notices to STDERR, with the env var winning over config. This lets teams roll forward through migrations without their CI failing on deprecation noise from extension-detected legacy patterns.
-
[ #647 ] Added 'BEHAT_DRUPALEXTENSION_DISABLE_CLEANUP' env var to skip scenario teardown. @AlexSkrypnyk ( #845 ) Setting BEHAT_DRUPALEXTENSION_DISABLE_CLEANUP=1 (or true / yes / on ) skips the AfterScenario teardown of entities, users, and roles, and intentionally leaves the last logged-in session open so a failing scenario's database state and browser session can be inspected directly. Intended for ad-hoc local debugging - leave it off in CI.
-
[ #479 ] Added verbose diagnostic output to AJAX timeout exception. @AlexSkrypnyk ( #838 ) iWaitForAjaxToFinish() now captures the current URL, jQuery.active count, animated-element count, and each active Drupal.ajax.instances entry (selector, event, URL) at the moment of timeout and embeds them in a structured multi-line error message. Replaces the previous single-line "Unable to complete AJAX request." message that gave no clue why the browser was busy.
Breaking changes
-
Updated 'drupal/drupal-driver' to 3.x and migrated to capability-based API. @AlexSkrypnyk ( #803 ) The monolithic DriverInterface is replaced with capability interfaces ( AuthenticationCapabilityInterface , MailCapabilityInterface , ConfigCapabilityInterface , ContentCapabilityInterface , CacheCapabilityInterface , CronCapabilityInterface , LanguageCapabilityInterface , RoleCapabilityInterface , UserCapabilityInterface ) and every CRUD method is renamed to a verb-noun form. Migration: bump drupal/drupal-driver to ^3.0 , rename driver calls ( createNode → nodeCreate , runCron → cronRun , clearCache → cacheClear , startCollectingMail → mailStartCollecting , getMail → mailGet , sendMail → mailSend , etc.), and add capability-interface guards before invoking driver methods in subclasses.
-
[ #469 ] Added typed random tokens with '[?name:type,args]' syntax and deprecated '<?name>' form. @AlexSkrypnyk ( #844 ) The legacy <?name> random-token form still works in 6.0 but emits a [Deprecation] notice once per literal. Migration: replace <?name> with [?name] (equivalent default) or one of the typed forms ( [?slug:machine_name] , [?age:int,18,99] , [?email:email] , [?id:uuid] ); the legacy form is scheduled for removal in 6.1.
-
Renamed 'assert' action steps and tightened validator. @AlexSkrypnyk ( #837 ) Action methods that previously used assertXxx names are renamed to action-style names (e.g. assertCron → iRunCron , assertAuthenticatedByRole → iAmLoggedInAsUserWithRole , assertDrushCommand → iRunDrush ), and three negative-message steps move from @Given to @Then with matching method renames. Migration: see the rename table in MIGRATION.md and search-and-replace overridden method names in your subclasses; step text is unchanged for most steps but the three re-classified steps now require @Then semantics.
-
[ #824 ] Converted 'BatchContext' into 'BatchTrait' on 'DrupalContext'. @AlexSkrypnyk ( #835 ) BatchContext is deleted; its iWaitForTheBatchJobToFinish and thereIsAnItemInTheSystemQueue steps are now provided by DrupalContext via BatchTrait . Migration: remove Drupal\DrupalExtension\Context\BatchContext from the contexts: list in your behat.yml - the steps are loaded automatically with DrupalContext .
-
Moved driver and mail manager classes under 'Drupal\DrupalExtension\Manager' namespace. @AlexSkrypnyk ( #833 ) Drupal\DrupalDriverManager → Drupal\DrupalExtension\Manager\DriverManager (the Drupal prefix drops), Drupal\DrupalDriverManagerInterface → Drupal\DrupalExtension\Manager\DriverManagerInterface , Drupal\DrupalMailManager → Drupal\DrupalExtension\Manager\DrupalMailManager , Drupal\DrupalMailManagerInterface → Drupal\DrupalExtension\Manager\DrupalMailManagerInterface . Migration: update use statements and any FQCN references; the user and authentication managers retain their existing namespaces.
-
Moved 'ParametersAwareInterface' to root namespace alongside 'ParametersTrait'. @AlexSkrypnyk ( #832 ) The interface moved from Drupal\DrupalExtension\Context\ParametersAwareInterface to Drupal\DrupalExtension\ParametersAwareInterface . Migration: update use statements to import from the root namespace; signatures ( setParameters , getParameter ) are unchanged.
-
[ #825 ] Extracted Drupal AJAX handling into 'DrupalAjaxTrait'. @AlexSkrypnyk ( #830 ) The three Drupal-specific AJAX methods ( iWaitForAjaxToFinish , beforeJavascriptStep , afterJavascriptStep ) move from MinkContext into DrupalAjaxTrait . MinkContext composes the trait so existing consumers see no behavior change, but downstream subclasses that overrode these methods inline must now override the trait methods or compose DrupalAjaxTrait directly.
-
Moved 'ajax_timeout' to 'Drupal\DrupalExtension' and renamed parameters interface. @AlexSkrypnyk ( #829 ) ajax_timeout configuration moves from Drupal\MinkExtension to Drupal\DrupalExtension , and the parameters API drops its Drupal prefix: DrupalParametersAwareInterface → ParametersAwareInterface , DrupalParametersTrait → ParametersTrait , setDrupalParameters → setParameters , getDrupalParameter → getParameter , $drupalParameters → $parameters . Migration: relocate ajax_timeout in behat.yml and rename interface/trait/method/property references in subclasses.
-
[ #822 ] Rebased MessageContext on RawMinkContext and moved message selectors to Drupal\MinkExtension. @AlexSkrypnyk ( #827 ) MessageContext now extends RawMinkContext instead of RawDrupalContext , so it can be registered in any Mink suite without booting the Drupal driver; subclasses that depended on RawDrupalContext helpers must compose ParametersTrait themselves or change their base. The four message selectors ( message_selector , error_message_selector , success_message_selector , warning_message_selector ) move from Drupal\DrupalExtension.selectors: to Drupal\MinkExtension.selectors: ; the legacy location still works in 6.0 with a one-shot deprecation notice and is removed in 6.1.
-
[ #258 ] Added BigPipe NOJS cookie bypass to 'DrupalContext'. @AlexSkrypnyk ( #821 ) This is additive (opt-in via @bigpipe tag) but ships as part of ...
Read more
Contributors
AlexSkrypnyk
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
All reactions
-
v5.3.315 Apr 2026Release notes
Open source →What's new since v5.3.2
- Fixed 'setBasicConfig()' storing all values as strings instead of native PHP types. @idimopoulos @AlexSkrypnyk (#796)
- Updated Behat Screenshot config to remove deprecated option. @AlexSkrypnyk (#797)
- Add Slack community badge to README @AlexSkrypnyk (#793)
Full Changelog: v5.3.2...v5.3.3
Release notes
Open source →Important
This is the last 5.x release with DrupalDriver 2.x support. Only critical bug fixes will be worked on as patches for 2.4 , if required. We are working on 6.x , which will use the updated DrupalDriver API.
-
[ #662 ] Added drag-and-drop step definition for MinkContext. @AlexSkrypnyk ( #800 )
-
Changed default Drush binary to 'vendor/bin/drush' with automatic path resolution. @AlexSkrypnyk ( #799 )
-
Added configurable 'login_wait' to fix post-login race condition on JS-heavy sites. @AlexSkrypnyk ( #798 )
Full Changelog : v5.3.3...v5.4.0
@AlexSkrypnyk
Contributors
AlexSkrypnyk
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
All reactions
-
v5.3.218 Mar 2026Release notes
Open source →What's new since v5.3.1
- [#791] Fixed 'author' property triggering validation error in node creation. @AlexSkrypnyk (#792)
- Added tests for attribute/annotation inheritance and changelog warning. @AlexSkrypnyk (#790)
Full Changelog: v5.3.1...v5.3.2
Release notes
Open source →-
Fixed 'setBasicConfig()' storing all values as strings instead of native PHP types. @idimopoulos @AlexSkrypnyk ( #796 )
-
Updated Behat Screenshot config to remove deprecated option. @AlexSkrypnyk ( #797 )
-
Add Slack community badge to README @AlexSkrypnyk ( #793 )
Full Changelog : v5.3.2...v5.3.3
@AlexSkrypnyk @idimopoulos
Contributors
AlexSkrypnyk and idimopoulos
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
All reactions
-
v5.3.117 Mar 2026Release notes
Open source →What's new since v5.3.0
- Moved Drupal configuration from provisioning scripts to deploy hooks. @AlexSkrypnyk (#789)
- [#787] Fixed computed base fields failing in parseEntityFields() @AlexSkrypnyk (#788)
Full Changelog: v5.3.0...v5.3.1
Release notes
Open source →-
[ #791 ] Fixed 'author' property triggering validation error in node creation. @AlexSkrypnyk ( #792 )
-
Added tests for attribute/annotation inheritance and changelog warning. @AlexSkrypnyk ( #790 )
Full Changelog : v5.3.1...v5.3.2
@AlexSkrypnyk
Contributors
AlexSkrypnyk
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
All reactions
-
v5.3.017 Mar 2026Release notes
Open source →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.) insrc/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
RedundantStepExceptionfor 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 protectedThe
setConfig()method visibility was changed frompublictoprotected.
If your project callsConfigContext::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 aparentfield 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\RuntimeExceptionis 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.ymlprovidedA new
behat.dist.ymlfile is included with all configuration values
pre-filled, serving as a reference for available options and their defaults.
New features
Custom
DocumentElementA custom
DocumentElementclass 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
ConfigContextwas 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
Release notes
Open source →-
Moved Drupal configuration from provisioning scripts to deploy hooks. @AlexSkrypnyk ( #789 )
-
[ #787 ] Fixed computed base fields failing in parseEntityFields() @AlexSkrypnyk ( #788 )
Full Changelog : v5.3.0...v5.3.1
@AlexSkrypnyk
Contributors
AlexSkrypnyk
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
All reactions
-
v5.2.108 Mar 2026Release notes
Open source →-
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.yml with 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 ScenarioTagTrait and RawDrupalContext magic 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 ( #7 ...
Read more
Contributors
AlexSkrypnyk
Assets 2 Loading
Uh oh!
There was an error while loading. Please reload this page .
All reactions
Previous 1 2 3 4 5 6 Next
Previous Next
You can’t perform that action at this time.
-
-
v5.2.003 Mar 2026Nothing published for this version
-
v5.1.021 Oct 2024Nothing published for this version
-
v5.0.013 Dec 2023Nothing published for this version
-
v4.2.126 Apr 2022Nothing published for this version
-
v4.1.001 Jun 2020Nothing published for this version
-
v4.0.108 Oct 2019Nothing published for this version
-
v4.0.027 Sep 2019Nothing published for this version
-
v3.4.106 Dec 2017Nothing published for this version
-
v3.4.017 Nov 2017Nothing published for this version
-
v3.3.113 Sep 2017Nothing published for this version
-
v3.3.015 Jun 2017Nothing published for this version
-
v3.2.308 Jun 2017Nothing published for this version
-
v3.2.230 Jun 2016Nothing published for this version
-
v3.2.116 Jun 2016Nothing published for this version
-
v3.2.009 Jun 2016Nothing published for this version
-
v3.1.522 Dec 2015Nothing published for this version
-
v3.1.421 Dec 2015Nothing published for this version
-
v3.1.330 Nov 2015Nothing published for this version
-
v3.1.216 Sep 2015Nothing published for this version
-
v3.1.102 Sep 2015Nothing published for this version
-
3.1.026 Aug 2015Nothing published for this version
-
v3.0.1316 Sep 2015Nothing published for this version
-
v3.0.1225 Aug 2015Nothing published for this version
-
v3.0.1101 Jun 2015Nothing published for this version
-
v3.0.1006 May 2015Nothing published for this version
-
v3.0.901 Apr 2015Nothing published for this version
-
v3.0.825 Mar 2015Nothing published for this version
-
v3.0.714 Feb 2015Nothing published for this version
-
v3.0.602 Feb 2015Nothing published for this version
-
v3.0.530 Dec 2014Nothing published for this version
-
3.0.423 Dec 2014Nothing published for this version
-
v3.0.324 Nov 2014Nothing published for this version
-
v3.0.211 Nov 2014Nothing published for this version
-
v3.0.105 Nov 2014Nothing published for this version
-
v3.0.003 Nov 2014Nothing published for this version
-
v1.0.930 Dec 2014Nothing published for this version
-
v1.0.823 Dec 2014Nothing published for this version
-
v1.0.707 Nov 2014Nothing published for this version
-
v1.0.607 Nov 2014Nothing published for this version
-
v1.0.521 Oct 2014Nothing published for this version
-
v1.0.419 Oct 2014Nothing published for this version
-
v1.0.315 Oct 2014Nothing published for this version
-
v1.0.221 Jun 2014Nothing published for this version
-
v1.0.116 May 2014Nothing published for this version
-
v1.0.006 May 2014Nothing published for this version
-
v0.1.601 May 2014Nothing published for this version
-
v0.1.518 Dec 2013Nothing published for this version
-
v0.1.404 Dec 2013Nothing published for this version
-
v0.1.324 Oct 2013Nothing published for this version