[#629] Added fixture path expansion for file fields on nodes.#634
[#629] Added fixture path expansion for file fields on nodes.#634AlexSkrypnyk wants to merge 4 commits into
Conversation
WalkthroughExtracts fixture-file expansion into a new internal EntityFixtureTrait, adds a BeforeNodeCreate hook in ContentTrait to call it, refactors MediaTrait to reuse it, composes the trait into FeatureContext, updates docs extraction, and adds two Behat scenarios for file/image fixtures. ChangesEntity Fixture Path Expansion
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/Drupal/EntityFixtureTrait.php`:
- Around line 48-52: The realpath() call can return false and casting it to
string yields "" which makes $fixture_path end up as "/" and bypass is_dir();
update the logic in EntityFixtureTrait (around the $fixture_path/$files_path
handling) to first capture the result of realpath((string) $files_path) into a
variable, check that it is not false, and return early if it is false before
building $fixture_path; then construct $fixture_path from the validated realpath
and proceed—this prevents operating against the filesystem root when the input
path does not exist.
In `@tests/behat/features/drupal_content.feature`:
- Around line 367-373: Add a field-specific assertion to the "Assert image field
on node resolves bare fixture filename without explicit managed file" scenario
so it verifies the image was actually populated: after visiting the article edit
page for "[TEST] Fixture image" add a step that asserts the field_image contains
the uploaded file (for example, a step that checks for an <img> whose src
contains "image.png" or a textual file label "image.png") so the scenario
ensures field_image was set from image.png rather than only proving node
creation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 190b7b83-60bb-4b21-a3cf-dcbdc245cd54
📒 Files selected for processing (4)
src/Drupal/ContentTrait.phpsrc/Drupal/EntityFixtureTrait.phpsrc/Drupal/MediaTrait.phptests/behat/features/drupal_content.feature
| Scenario: Assert image field on node resolves bare fixture filename without explicit managed file | ||
| Given the following article content: | ||
| | title | field_image | | ||
| | [TEST] Fixture image | image.png | | ||
| And I am logged in as a user with the "administrator" role | ||
| When I visit the "article" content edit page with the title "[TEST] Fixture image" | ||
| Then I should see "[TEST] Fixture image" |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
Strengthen the image-fixture scenario with a field-specific assertion.
This scenario currently proves node creation, but not necessarily that field_image was populated from image.png. Add an assertion tied to the uploaded image value.
Suggested tweak
`@api`
Scenario: Assert image field on node resolves bare fixture filename without explicit managed file
Given the following article content:
| title | field_image |
| [TEST] Fixture image | image.png |
And I am logged in as a user with the "administrator" role
When I visit the "article" content edit page with the title "[TEST] Fixture image"
Then I should see "[TEST] Fixture image"
+ And the response should contain "image.png"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Scenario: Assert image field on node resolves bare fixture filename without explicit managed file | |
| Given the following article content: | |
| | title | field_image | | |
| | [TEST] Fixture image | image.png | | |
| And I am logged in as a user with the "administrator" role | |
| When I visit the "article" content edit page with the title "[TEST] Fixture image" | |
| Then I should see "[TEST] Fixture image" | |
| Scenario: Assert image field on node resolves bare fixture filename without explicit managed file | |
| Given the following article content: | |
| | title | field_image | | |
| | [TEST] Fixture image | image.png | | |
| And I am logged in as a user with the "administrator" role | |
| When I visit the "article" content edit page with the title "[TEST] Fixture image" | |
| Then I should see "[TEST] Fixture image" | |
| And the response should contain "image.png" |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/behat/features/drupal_content.feature` around lines 367 - 373, Add a
field-specific assertion to the "Assert image field on node resolves bare
fixture filename without explicit managed file" scenario so it verifies the
image was actually populated: after visiting the article edit page for "[TEST]
Fixture image" add a step that asserts the field_image contains the uploaded
file (for example, a step that checks for an <img> whose src contains
"image.png" or a textual file label "image.png") so the scenario ensures
field_image was set from image.png rather than only proving node creation.
There was a problem hiding this comment.
Not adopting. The drupal-driver FileHandler::uploadAndSave() rewrites the destination URI to public:// + uniqid() + .{ext}, so the original basename image.png is not preserved in the saved file. Asserting the response should contain "image.png" would fail because the edit page renders the file with its stored filename (e.g. 5fa3c41e89af2.png), not the source fixture filename. The existing title assertion is enough to prove the article was created with the hook in effect; if the upload had failed the hook would have thrown and node creation would have aborted before the scenario reached the assertion step.
There was a problem hiding this comment.
@AlexSkrypnyk, understood — that's a clear and well-reasoned explanation. Since FileHandler::uploadAndSave() replaces the original basename with a uniqid()-based name, asserting the source filename in the response would be unreliable. The title assertion serving as an indirect proof of the hook's effect (a failed upload throws before node creation completes) makes sense for this scenario.
( ˘ ω˘ *)
✏️ Learnings added
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 634
File: tests/behat/features/drupal_content.feature:367-373
Timestamp: 2026-05-12T04:47:00.917Z
Learning: In drevops/behat-steps Behat feature files for ContentTrait/MediaTrait image field fixture scenarios, do NOT assert the original fixture filename (e.g. `image.png`) in the response after node/media creation. The drupal-driver `FileHandler::uploadAndSave()` rewrites the destination URI to `public://` + `uniqid()` + `.{ext}`, so the original basename is not preserved in the stored file. The edit page renders the stored (uniqid-based) filename, not the source fixture name. A title assertion is sufficient proof the BeforeNodeCreate hook worked correctly — a failed upload would throw before node creation completes.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 555
File: tests/behat/features/metatag.feature:66-69
Timestamp: 2026-04-08T06:59:35.371Z
Learning: In Behat feature files under tests/behat/features/**/*.feature, for scenarios tagged with `trait:*`, prefer triple double quotes (`"""`) for PyStrings unless the step definitions invoked inside those scenarios actually accept PyString arguments. Only use triple single quotes (`'''`) when you need to embed a PyString literal inside the outer PyString (to avoid nesting `"""` within `"""`). If the inner steps are simple one-liners and do not take PyString arguments, `"""` is sufficient.
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 555
File: tests/behat/features/metatag.feature:52-60
Timestamp: 2026-04-08T07:00:10.945Z
Learning: In Behat feature files under tests/behat/features/**/*.feature, follow the repo tagging convention: positive scenarios that exercise static fixtures (e.g., visiting prebuilt HTML like tests/behat/fixtures/*.html, with no Drupal API usage) should be intentionally left untagged. Use tags only for integration/negative behavior or trait-scoped scenarios (e.g., api for Drupal/API interactions, and trait:TraitName for scenarios that belong to a specific trait), as in element.feature and metatag.feature. If a scenario uses only static fixture HTML and no Drupal API, it should not be tagged with api or trait.
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 592
File: tests/behat/features/table.feature:6-7
Timestamp: 2026-04-09T12:24:16.774Z
Learning: In drevops/behat-steps Behat feature files under tests/behat/features/**/*.feature, use `trait:TraitName` only for negative/failure scenarios that run behat-within-behat via `BehatCliContext` (scenarios that invoke `behat --no-colors` to assert expected failure output). For positive “works as expected” scenarios that run directly against the Drupal site, use only the `api` tag and intentionally do not add `trait:TraitName`. When reviewing, flag suggestions to add `trait:TraitName` to positive scenarios, since it should be absent by design and this convention should be consistent across trait-related feature files (e.g., element.feature, drupal_content.feature, table.feature).
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 592
File: tests/behat/features/table.feature:38-40
Timestamp: 2026-04-09T12:25:02.540Z
Learning: In tests/behat/features/**/*.feature, when you have a negative scenario under `trait:*` and you nest step definitions inside a `scenario steps tagged with "api"`, you may use DrupalContext content-creation steps such as `page content:` (and similar steps like `landing_page content:`). These nested content-creation steps should be available and work correctly because BehatCliContext generates a feature file tagged with `api`, which enables the full DrupalContext (including `createNodes()`). Therefore, do not apply the guideline "avoid custom steps in negative tests" to these content-creation steps when `scenario steps tagged with "api"` is used.
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 598
File: tests/behat/features/xml.feature:613-616
Timestamp: 2026-04-09T15:06:13.608Z
Learning: In drevops/behat-steps feature files under tests/behat/features/**/*.feature, for positive scenarios that exercise debug/print steps (e.g., printing the last XML response), do not add assertions that require specific output content (avoid adding steps like “Then I should see …”). It is sufficient for these scenarios to verify the step runs successfully without throwing errors; adding output-content checks would couple the test to fixture content.
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 621
File: tests/behat/features/drupal_state.feature:17-25
Timestamp: 2026-04-10T07:58:00.186Z
Learning: In `drevops/behat-steps` Gherkin `.feature` files, don’t request separate JSON object (`{"a":1}`) scenarios when the JSON object needs to appear inside a double-quoted step argument (e.g., `Given ... "{"a":1}"`). Gherkin cannot represent escaped double quotes inside quoted step text, so JSON object literals can’t be expressed reliably that way. Prefer the existing indirect coverage strategy (e.g., JSON array scenarios that hit the same `json_decode()` code path and thus cover the `stateNormaliseValue()` JSON normalization branches) rather than suggesting additional JSON object scenarios purely for direct representation.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #634 +/- ##
==========================================
- Coverage 97.15% 96.94% -0.21%
==========================================
Files 43 44 +1
Lines 3018 3040 +22
==========================================
+ Hits 2932 2947 +15
- Misses 86 93 +7 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/Drupal/EntityFixtureTrait.php`:
- Around line 73-85: The code is concatenating $fixture_path . $basename without
ensuring $basename is a true bare filename, allowing path traversal like
"../secret.txt"; update the checks in the EntityFixtureTrait (around the
$basename handling used by entityFixtureManagedFileExists and the later URI/file
checks) to reject any $basename that contains directory separators or traversal
tokens (e.g. '/' or '\' or '..') before calling is_file or
entityFixtureManagedFileExists (and the analogous check at lines 110-113);
implement a simple validation that $basename matches a safe basename pattern (no
slashes, no backslashes, non-empty) and skip/continue when it fails so only true
bare filenames are used for path concatenation and URI lookups.
- Around line 65-67: Remove the artificial name check that skips fields
containing no "field_" substring in the EntityFixtureTrait; specifically delete
or disable the conditional that checks str_contains((string) $name, 'field_')
and the associated continue, and rely instead on the existing field type
verification later in this routine (the type check around the field handling
logic). This ensures file/image fields whose machine names don't include
"field_" are processed correctly by the existing type-based logic in
EntityFixtureTrait.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0c223dfe-ed9b-48e0-82f0-658ef91ecc2d
📒 Files selected for processing (1)
src/Drupal/EntityFixtureTrait.php
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/Drupal/EntityFixtureTrait.php`:
- Around line 41-95: The entityFixtureExpand method is doing multiple
responsibilities (path resolution, driver checks, field filtering, basename
validation, and stub value mutation); split it by extracting at least two helper
methods: one like normalizeAndValidateBasename(string|array $value): ?string to
encapsulate the basename extraction/validation logic currently using basename(),
str_contains checks and array handling, and another like
rewriteStubValue(EntityStubInterface $stub, string $fieldName, string $filePath,
$originalValue): void to encapsulate the logic that sets $stub->setValue($name,
...) for both scalar and array cases; update entityFixtureExpand to call
getMinkParameter/getDriver and entityFixtureManagedFileExists as before but
delegate basename handling to normalizeAndValidateBasename and the mutation to
rewriteStubValue so the loop only coordinates checks and delegates specific
behavior to these new helpers (refer to symbols entityFixtureExpand,
normalizeAndValidateBasename, rewriteStubValue, entityFixtureManagedFileExists,
getMinkParameter, getDriver, and EntityStubInterface::setValue/getValues).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 251aeaae-d154-48d4-a53b-331388487323
📒 Files selected for processing (1)
src/Drupal/EntityFixtureTrait.php
| protected function entityFixtureExpand(string $entity_type, EntityStubInterface $stub): void { | ||
| $files_path = $this->getMinkParameter('files_path'); | ||
|
|
||
| if (empty($files_path)) { | ||
| return; | ||
| } | ||
|
|
||
| $resolved_files_path = realpath((string) $files_path); | ||
|
|
||
| if ($resolved_files_path === FALSE || !is_dir($resolved_files_path)) { | ||
| return; | ||
| } | ||
|
|
||
| $fixture_path = rtrim($resolved_files_path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; | ||
|
|
||
| $driver = $this->getDriver(); | ||
|
|
||
| if (!$driver instanceof DrupalDriverInterface) { | ||
| return; | ||
| } | ||
|
|
||
| $field_types = $driver->getCore()->getEntityFieldTypes($entity_type); | ||
|
|
||
| foreach ($stub->getValues() as $name => $value) { | ||
| if (empty($field_types[$name]) || ($field_types[$name] !== 'image' && $field_types[$name] !== 'file')) { | ||
| continue; | ||
| } | ||
|
|
||
| $basename = is_array($value) ? ($value[0] ?? NULL) : $value; | ||
|
|
||
| if (!is_string($basename) || $basename === '') { | ||
| continue; | ||
| } | ||
|
|
||
| if (str_contains($basename, '/') || str_contains($basename, '\\') || $basename !== basename($basename)) { | ||
| continue; | ||
| } | ||
|
|
||
| if ($this->entityFixtureManagedFileExists($basename)) { | ||
| continue; | ||
| } | ||
|
|
||
| if (!is_file($fixture_path . $basename)) { | ||
| continue; | ||
| } | ||
|
|
||
| if (is_array($value)) { | ||
| $value[0] = $fixture_path . $basename; | ||
| $stub->setValue($name, $value); | ||
| } | ||
| else { | ||
| $stub->setValue($name, $fixture_path . $basename); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | 🏗️ Heavy lift
Split entityFixtureExpand() into smaller helpers to reduce risk.
This method currently handles path resolution, driver checks, field filtering, basename validation, managed-file lookup, and value mutation in one block. Please extract at least basename normalization/validation and stub-value rewrite into dedicated helpers to lower cyclomatic/NPath complexity and make future changes safer.
🧰 Tools
🪛 PHPMD (2.15.0)
[warning] 41-95: The method entityFixtureExpand() has a Cyclomatic Complexity of 18. The configured cyclomatic complexity threshold is 10. (undefined)
(CyclomaticComplexity)
[warning] 41-95: The method entityFixtureExpand() has an NPath complexity of 9228. The configured NPath complexity threshold is 200. (undefined)
(NPathComplexity)
[error] 41-95: The parameter $entity_type is not named in camelCase. (undefined)
(CamelCaseParameterName)
[error] 91-93: The method entityFixtureExpand uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (undefined)
(ElseExpression)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/Drupal/EntityFixtureTrait.php` around lines 41 - 95, The
entityFixtureExpand method is doing multiple responsibilities (path resolution,
driver checks, field filtering, basename validation, and stub value mutation);
split it by extracting at least two helper methods: one like
normalizeAndValidateBasename(string|array $value): ?string to encapsulate the
basename extraction/validation logic currently using basename(), str_contains
checks and array handling, and another like rewriteStubValue(EntityStubInterface
$stub, string $fieldName, string $filePath, $originalValue): void to encapsulate
the logic that sets $stub->setValue($name, ...) for both scalar and array cases;
update entityFixtureExpand to call getMinkParameter/getDriver and
entityFixtureManagedFileExists as before but delegate basename handling to
normalizeAndValidateBasename and the mutation to rewriteStubValue so the loop
only coordinates checks and delegates specific behavior to these new helpers
(refer to symbols entityFixtureExpand, normalizeAndValidateBasename,
rewriteStubValue, entityFixtureManagedFileExists, getMinkParameter, getDriver,
and EntityStubInterface::setValue/getValues).
There was a problem hiding this comment.
Not adopting. PHPMD is not part of this project's enforced lint pipeline (see phpstan.neon and composer.json), so the cyclomatic/NPath thresholds it cites are not a project standard. The pre-refactor MediaTrait::mediaExpandEntityFieldsFixtures() carried a similar shape and accepted the same trade-off. The current method uses a flat guard/continue pattern that mirrors the existing style across this codebase (see MediaTrait::mediaExpandEntityFields(), FileTrait::fileCreateEntity(), etc.) and reads top-to-bottom as a series of preconditions followed by a single rewrite. Splitting basename normalization and stub mutation into helpers would push two-line operations behind two new symbols without changing what the code does, and would obscure the linear precondition flow that makes it auditable today.
The entity_type snake_case is intentional and is the convention this library uses for local variables and method arguments (see CLAUDE.md).
There was a problem hiding this comment.
@AlexSkrypnyk, understood — I'll defer to the project's established conventions. The flat guard/continue pattern and snake_case parameter names are clearly intentional, and PHPMD thresholds aren't meaningful here since the tool isn't part of the enforced pipeline.
(=^・ω・^=)∫
✏️ Learnings added
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 634
File: src/Drupal/EntityFixtureTrait.php:41-95
Timestamp: 2026-05-12T07:07:50.984Z
Learning: In drevops/behat-steps, PHPMD is NOT part of the enforced lint/static-analysis pipeline. The project uses PHPStan (phpstan.neon) and custom rules defined in composer.json. PHPMD cyclomatic/NPath complexity warnings should not be raised as review concerns in this repository.
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 634
File: src/Drupal/EntityFixtureTrait.php:41-95
Timestamp: 2026-05-12T07:07:50.984Z
Learning: In drevops/behat-steps, snake_case is the intentional convention for method parameter names and local variables (e.g. `$entity_type`, `$files_path`), as documented in CLAUDE.md. Do not flag snake_case parameters as violations of camelCase naming conventions in this project.
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 634
File: src/Drupal/EntityFixtureTrait.php:41-95
Timestamp: 2026-05-12T07:07:50.984Z
Learning: In drevops/behat-steps, the preferred coding style for multi-condition validation methods is a flat guard/continue (early-return) pattern — a linear series of precondition checks followed by a single mutation. This is established across MediaTrait, FileTrait, and similar traits. Do not suggest splitting such methods into multiple smaller helpers, as it obscures the auditable top-to-bottom precondition flow that the project intentionally maintains.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 560
File: src/ResponsiveTrait.php:173-173
Timestamp: 2026-04-09T08:32:59.254Z
Learning: In this project (drevops/behat-steps), Behat hook methods annotated with attributes like #[BeforeStep], #[BeforeScenario] (and similar Behat hook attributes) must keep their required scope parameter in the method signature (e.g., `BeforeStepScope $scope`, `BeforeScenarioScope $scope`) as required by the Behat framework contract. Even if the parameter is not referenced inside the method body, do not rename it to an unused placeholder like `$_scope` or otherwise change its type/name—treat it as structurally required. PHPMD `UnusedFormalParameter` warnings on these specific hook-method scope parameters are expected false positives and should be ignored.
Learnt from: AlexSkrypnyk
Repo: drevops/behat-steps PR: 623
File: STEPS.md:2647-2650
Timestamp: 2026-04-10T08:13:52.837Z
Learning: In drevops/behat-steps, docs generation (docs.php when converting docblock code/endcode blocks into STEPS.md) strips `/*` sequences from examples. When writing glob/wildcard path patterns inside trait docblocks, avoid a literal slash-star `/*`—use patterns with a trailing `*` but no preceding slash. For example, write `/news*` instead of `/news/*`, so the glob survives generation and renders correctly in STEPS.md.
Closes #629
Summary
Adds a
BeforeNodeCreatehook inContentTraitthat expands bare fixturefilenames (e.g.
document.pdf) onfileandimagefields to absolutepaths under Mink's
files_pathbefore drupal-driver'sFileHandlerprocesses them. This mirrors the expansion already present in
MediaTraitfor media entities. To avoid duplicating the logic, a new internal shared
trait
EntityFixtureTraitextracts the common implementation, andMediaTraitis updated to delegate to it. Expansion is skipped when amanaged file with the same basename already exists in
public://orprivate://, keeping backward compatibility with scenarios that pre-createmanaged files via
FileTrait.Changes
New:
src/Drupal/EntityFixtureTrait.phpentityFixtureExpand(string $entity_type, EntityStubInterface $stub)- resolves bare fixture filenames onfile/imagefields of any entity stub.entityFixtureManagedFileExists(string $basename)- checkspublic://andprivate://before expanding, so existing managed files are not overridden.Updated:
src/Drupal/ContentTrait.phpEntityFixtureTrait.#[BeforeNodeCreate]hookcontentBeforeNodeCreate()that callsentityFixtureExpand('node', ...).Updated:
src/Drupal/MediaTrait.phpEntityFixtureTrait.mediaExpandEntityFieldsFixtures()now delegates toentityFixtureExpand('media', ...), removing ~35 lines of duplicated code.Updated:
tests/behat/features/drupal_content.feature@apiscenarios coveringfield_file(text.txt) andfield_image(image.png) on article nodes, asserting bare fixture filenames resolve without needing pre-created managed files.Before / After
Before - node creation with a file field required a pre-created managed file:
drupal-driver
FileHandlercould only resolve the filename if afileentity already existed at
public://document.pdf.After - bare fixture filename expands automatically:
Entity creation flow:
MediaTraituses the same shared path viaEntityFixtureTrait:Summary
This PR adds automatic expansion of bare fixture filenames (e.g.,
text.txt,image.png) for file and image fields on Drupal entity stubs used by Behat tests, with safeguards to preserve existing behavior when managed files already exist.Key Changes
New EntityFixtureTrait
files_path, resolves it with realpath() (guarded against failure), verifies the active Drupal driver implements DrupalDriverInterface, inspects core field types for the given entity type, and rewrites bare file/image basenames to absolute fixture paths under the resolved files_path when appropriate. Handles scalar and array-style stub values (updates array[0]).public://{basename}orprivate://{basename}.ContentTrait Enhancement
MediaTrait Refactor
Tests & Test Bootstrap
Docs helper
Other notes from commits
Behavior Change
files_pathbefore drupal-driver's FileHandler processes them, enabling upload/creation of managed files during entity creation.Step-definition rules (CONTRIBUTING.md)