8000 [#367] Updated `BlockTrait`. by skipper-vp · Pull Request #376 · drevops/behat-steps · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[#367] Updated BlockTrait. #376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 4, 2025
Merged

Conversation

skipper-vp
Copy link
Contributor
@skipper-vp skipper-vp commented May 1, 2025

Updated BlockTrait.

Summary by CodeRabbit

  • Documentation
    • Enhanced migration and step definition guides for block operations with clearer mappings and streamlined phrasing.
  • Style
    • Refined step definitions and test assertions for block features to use simpler, more consistent language.
  • Tests
    • Expanded and updated feature files with unified step formats, added negative test scenarios, and improved scenario structure for block management.
  • New Features
    • Improved block management with enhanced creation, configuration, visibility, enable/disable controls, and cleanup steps for better test reliability.
  • Chores
    • Scoped feature tags to individual scenarios for clearer test categorization.

Copy link
coderabbitai bot commented May 1, 2025

"""

Walkthrough

The changes enhance the block-related Behat testing framework by refining method names, parameter orders, and step definitions for clarity and consistency. The BlockTrait was refactored to rename and restructure block lifecycle methods, including creation, configuration, visibility management, enabling/disabling, and assertions, with improved cleanup handling that respects scenario tags. Migration documentation was extended with a new section mapping v2 to v3 step definitions for blocks. Step definition documentation was updated to use singular phrasing, clearer keywords, and standardized language. Behat feature files were expanded and refactored to adopt the new steps, add negative test cases, and improve test coverage. Minor adjustments were made to scenario tags in unrelated feature files. No core logic or control flow changes were introduced.

Changes

File(s) Change Summary
MIGRATION.md Added a new section for BlockTrait mapping v2 to v3 step definitions, detailing updated step keywords, phrasing, and parameter names for block creation, configuration, visibility conditions, enabling/disabling, and existence assertions.
src/BlockTrait.php Refactored BlockTrait: renamed methods (e.g., blockPlaceBlockInRegionblockCreateInstance), reordered parameters, consolidated configuration logic into public methods, improved cleanup with blockAfterScenario method honoring skip tags, standardized exception messages, and updated doc comments and step annotations. No changes to underlying logic.
steps.md Revised Gherkin step definitions for BlockTrait to use singular phrasing, consistent keywords (@Given, @Then), simplified language, and standardized parameter naming. Removed or consolidated steps related to visibility conditions and enabling/disabling. No code or logic changes.
tests/behat/features/block.feature Expanded and refactored block feature scenarios: added Background step to ensure block absence, updated steps to new phrasing and keywords, added idempotency checks, introduced comprehensive negative test scenarios for error handling, and updated visibility condition and block move steps accordingly. No logic changes.
tests/behat/features/content_block.feature Added new positive and negative scenarios for content block management, standardized step phrasing and ordering, removed global feature-level @api tag in favor of scenario-level tags, and improved test coverage for creation, editing, deletion, and error handling. No changes to scenario logic.
tests/behat/features/wait.feature Changed feature-level tags @api and @javascript to scenario-level tags to more precisely scope test contexts without altering test logic.
src/ContentBlockTrait.php Improved robustness in contentBlockAfterScenario cleanup by wrapping entity deletion in try-catch for EntityStorageException to prevent teardown failures, and changed static array cleanup to per-entity unset. Added import for EntityStorageException. No signature changes.

Sequence Diagram(s)

sequenceDiagram
    participant Tester
    participant Behat
    participant BlockTrait

    Tester->>Behat: Run feature with block steps
    Behat->>BlockTrait: Call block step method (with updated parameter names/order)
    BlockTrait-->>Behat: Perform block operation (create/configure/assert/visibility)
    Behat-->>Tester: Report result
Loading

Poem

🐇
Blocks hop in line with names anew,
Steps crisp and clear, like morning dew.
Cleanup dances, tidy and bright,
Tests run smooth from day to night.
Phrases trimmed, no fluff in sight—
A rabbit’s cheer for code done right!
🎉


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
codecov bot commented May 1, 2025

Codecov Report

Attention: Patch coverage is 87.30159% with 8 lines in your changes missing coverage. Please review.

Project coverage is 81.28%. Comparing base (eb49928) to head (e675bda).
Report is 1 commits behind head on 3.x.

Files with missing lines Patch % Lines
src/BlockTrait.php 88.13% 7 Missing ⚠️
src/ContentBlockTrait.php 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              3.x     #376      +/-   ##
==========================================
- Coverage   81.29%   81.28%   -0.02%     
==========================================
  Files          32       32              
  Lines        1893     1881      -12     
==========================================
- Hits         1539     1529      -10     
+ Misses        354      352       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@skipper-vp skipper-vp requested a review from AlexSkrypnyk May 1, 2025 03:39
@AlexSkrypnyk AlexSkrypnyk force-pushed the feature/367-update-BlockTrait branch from 6046b33 to 350bde4 Compare May 4, 2025 07:37
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🔭 Outside diff range comments (1)
src/BlockTrait.php (1)

133-136: ⚠️ Potential issue

Boolean cast treats '0' as TRUE – visibility & status flags will be wrong

Casting a non-empty string to bool in PHP always yields true, therefore
'0', 'false', and any other non-empty string set in the TableNode will
be interpreted as true.
Blocks configured with label_display = 0 or status = 0 will still be saved
as visible and enabled.

-        case 'label_display':
-          $settings['label_display'] = (bool) $value;
+        case 'label_display':
+          // Accept 0/1, true/false, yes/no, etc.
+          $settings['label_display'] = filter_var($value, FILTER_VALIDATE_BOOLEAN);
...
-        case 'status':
-          $block->setStatus((bool) $value);
+        case 'status':
+          $block->setStatus(filter_var($value, FILTER_VALIDATE_BOOLEAN));

Also applies to: 142-144

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between 6046b33 and 350bde4.

📒 Files selected for processing (5)
  • MIGRATION.md (1 hunks)
  • src/BlockTrait.php (3 hunks)
  • steps.md (2 hunks)
  • tests/behat/features/block.feature (1 hunks)
  • tests/behat/features/content_block.feature (1 hunks)
🔇 Additional comments (15)
tests/behat/features/content_block.feature (1)

47-48: Improved step definition phrasing for better consistency and readability

The step definition updates follow a more direct "[subject] should [state]" pattern instead of "I should see..." which improves readability and maintains consistency with other assertion steps throughout the test suite.

MIGRATION.md (1)

7-19: Well-structured migration guide for BlockTrait step definitions

The migration mappings for BlockTrait follow a consistent pattern that improves clarity and readability:

  1. Changing from "When" to "Given" for setup actions
  2. Removing redundant "with label" phrasing
  3. Adding definite articles and standardizing parameter order
  4. Clarifying region specifications

This addition helps users migrate their existing tests from v2 to v3 of the library.

tests/behat/features/block.feature (7)

6-7: Improved test isolation with Background section

Adding a Background section ensures each scenario starts with a clean state where the test block doesn't exist, improving test isolation and preventing potential interference between scenarios.


11-17: Updated step definitions with clearer, more consistent phrasing

Block creation and verification steps now use more declarative and consistent phrasing, making the test more readable while maintaining the same functionality.


21-23: Added explicit cache clearing for better test reliability

The addition of explicit cache clearing steps after disabling the block ensures that the change is properly reflected when testing, improving test reliability.


26-28: Consistent pattern for enabling blocks and cache clearing

The same pattern of explicit cache clearing is applied after enabling the block, ensuring consistency in the test approach.


39-41: Clearer visibility condition configuration

The step for configuring block visibility conditions now uses more descriptive phrasing that clearly indicates what is being configured.


48-50: Explicit condition removal and cache clearing

The step for removing visibility conditions is clearer, and including cache clearing ensures the change is immediately reflected in testing.


62-65: Improved block configuration and assertion steps

The steps for configuring blocks and verifying their placement in regions use more consistent phrasing that clearly indicates the block's expected state and location.

steps.md (6)

5-5: Updated trait description for clarity

The BlockTrait description has been updated to be more concise and clear about its purpose.


35-43: Updated block creation step definition and example

The documentation for block creation now uses "Given" instead of "When" and has clearer parameter naming with "the instance of :admin_label block exists" rather than "I create a block of type :label".


48-55: Improved block configuration step documentation

The block configuration step now uses clearer phrasing that focuses on the block's state rather than the action of configuring it.


87-93: Clearer documentation for visibility condition configuration

The visibility condition configuration step now has more explicit parameter naming and consistent phrasing.


107-111: Standardized block existence assertion steps

The block existence assertion steps now follow a consistent "[subject] should [state]" pattern, making them more readable and aligned with other assertion steps.


125-130: Improved region-specific block assertion documentation

The documentation for region-specific block assertions now clearly specifies "in the :region region" for improved readability.

Comment on lines 263 to 273
$this->blockConfigureVisibilityCondition($condition, $label, new TableNode([]));
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

blockRemoveVisibilityCondition() doesn’t actually remove the condition

Passing an empty configuration only resets the condition to its defaults.
Use the dedicated unsetVisibilityConfig() helper (available since Drupal 8.8)
or explicit unset() to remove it completely:

-    $this->blockConfigureVisibilityCondition($label, $condition, new TableNode([]));
+    $this->blockAssertExists($label);
+    $block = $this->blockLoadByLabel($label);
+    $block->unsetVisibilityConfig($condition);
+    $block->save();

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 60 to 104
* @Given the instance of :admin_label block exists with the following configuration:
*/
public function blockPlaceBlockInRegion(string $label, TableNode $fields): void {
public function blockCreateInstance(string $admin_label, TableNode $fields): void {
$block = NULL;
$block_id = NULL;

/** @var \Drupal\Core\Block\BlockManagerInterface $block_manager */
$block_manager = \Drupal::service('plugin.manager.block');
$definitions = $block_manager->getDefinitions();
$default_theme = \Drupal::config('system.theme')->get('default');
$block = NULL;
foreach ($definitions as $plugin_id => $definition) {
if ((string) $definition['admin_label'] === $label) {
if ((string) $definition['admin_label'] === $admin_label) {
$default_theme = \Drupal::config('system.theme')->get('default');
$block = \Drupal::entityTypeManager()->getStorage('block')->create([
'plugin' => $plugin_id,
'theme' => $default_theme,
]);

$suggestion = $block->getPlugin()->getMachineNameSuggestion();
$block_id = \Drupal::service('block.repository')->getUniqueMachineName($suggestion, $block->getTheme());

$block->set('id', $block_id);

// Set temporary label to pass to the block configuration step.
$settings = $block->get('settings');
$settings['label'] = $admin_label;
$block->set('settings', $settings);

$block->save();

break;
}
}

if (!$block instanceof Block) {
throw new \Exception(sprintf('Could not create block of type "%s"', $label));
throw new \Exception(sprintf('Could not create block with admin label "%s"', $admin_label));
}
$this->blockConfigureBlockInstance($block, $fields);
static::$blockInstances[] = $block;
}

/**
* Clean up all blocks created during the scenario.
*
* This method automatically runs after each scenario to ensure clean
* test state.
* Add the tag @behat-steps-skip:AfterScenario to your scenario to
* prevent automatic cleanup of blocks.
*
* @AfterScenario
*/
public function blockAfterScenario(AfterScenarioScope $scope): void {
if ($scope->getScenario()->hasTag('behat-steps-skip:' . __FUNCTION__)) {
return;
}
$this->blockConfigure($admin_label, $fields);

foreach (static::$blockInstances as $block) {
$block->delete();
}
static::$blockInstances = [];
static::$blockInstances[] = $block;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Potential duplicate “admin label” ambiguity & premature save

  1. settings.label is not unique; blockLoadByLabel() may return a
    previously-created block with the same label, causing
    $this->blockConfigure() to target the wrong entity.

    Consider storing the freshly-created block’s ID in a context variable
    (or injecting the entity directly) instead of re-loading by label.

  2. The initial save() happens before the real configuration is applied,
    creating two revision writes where one would suffice.

-        $block->save();
-        ...
-        $this->blockConfigure($admin_label, $fields);
+        // Apply full configuration before the first save to avoid a second write.
+        $this->blockConfigure($admin_label, $fields);
+        $block->save();

Committable suggestion skipped: line range outside the PR's diff.

@AlexSkrypnyk AlexSkrypnyk force-pushed the feature/367-update-BlockTrait branch from 350bde4 to eee26a3 Compare May 4, 2025 07:42
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (5)
src/BlockTrait.php (5)

232-235: ⚠️ Potential issue

Parameter order still reversed – step will inject wrong values

The step uses the placeholder order :label … :condition, yet the method expects
(string $condition, string $label, …).
Behat will pass label to $condition and condition to $label, breaking
the call (most likely an exception from blockLoadByLabel()).

This was pointed out in a previous review but remains unfixed.


260-263: ⚠️ Potential issue

Same ordering bug for blockRemoveVisibilityCondition()

@Given the block :label has the :condition condition removed
public function blockRemoveVisibilityCondition(string $condition, string $label)

The injected arguments will be swapped, resulting in an attempt to remove a
condition named block-label from a block called condition-id.


160-163: 🧹 Nitpick (assertive)

PSR-12 formatting & consistency

public function blockRemove(string $label):void is still missing the required
space before the return type – "): void".


82-89: 🧹 Nitpick (assertive)

Avoid double save() – write once, not twice

The block is saved immediately after creation and again after
blockConfigure(). This generates two config-entity revisions and extra I/O
for no benefit.

-        $block->save();
-        ...
-        $this->blockConfigure($admin_label, $fields);
+        // Apply full configuration first to avoid an extra write.
+        $this->blockConfigure($admin_label, $fields);
+        $block->save();

381-389: 🛠️ Refactor suggestion

end($blocks) returns non-deterministic element

Picking the last array element relies on PHP’s internal hash order, giving
unpredictable results when multiple blocks share a label. Sort by ID (or throw
when duplicates exist) for deterministic behaviour.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between 350bde4 and eee26a3.

📒 Files selected for processing (4)
  • MIGRATION.md (1 hunks)
  • src/BlockTrait.php (3 hunks)
  • steps.md (2 hunks)
  • tests/behat/features/block.feature (1 hunks)
🔇 Additional comments (1)
MIGRATION.md (1)

7-19: Documentation looks great 👍

The v2→v3 mapping table is clear and comprehensive.

Comment on lines 64 to 69
$block_id = NULL;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Unused variable $block_id

$block_id is assigned but never referenced afterwards.
If you only need the generated ID on the entity itself, drop the separate
variable.

Comment on lines +32 to +35
Given the block "[TEST] User Account Menu" does not exist
And the block "[TEST] User Account Menu" does not exist

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Redundant pre-condition

Given the block "[TEST] User Account Menu" does not exist is executed twice in
a row. The second occurrence is redundant and can be removed for clearer
scenarios.

Comment on lines +90 to 93
Given the block "My block" has the following "request_path" condition configuration:
| pages | /node/1\r\n/about |
| negate | 0 |

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Literal \r\n sequence may confuse readers

In the example table the value /node/1\r\n/about shows the escaped CR/LF
sequence literally. Consider using a multi-line cell or an explicit bullet
list to illustrate multiple paths.

@AlexSkrypnyk AlexSkrypnyk force-pushed the feature/367-update-BlockTrait branch from eee26a3 to 3cb4dce Compare May 4, 2025 08:08
@AlexSkrypnyk AlexSkrypnyk changed the title [#367]: Updated BlockTrait. [#367] Updated BlockTrait. May 4, 2025
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🔭 Outside diff range comments (1)
tests/behat/features/content_block.feature (1)

6-24: 🧹 Nitpick (assertive)

Consider moving repeated login & pre-conditions into a Background for clarity

All four scenarios begin with identical steps:

Given I am logged in as a user with the "administrator" role
And the content block type "basic" should exist
And the following "basic" content blocks do not exist: …

Extracting these into a single Background: section removes duplication,
shortens the scenarios and makes the actual intent of each scenario pop out
immediately.

Diff sketch (outside the shown lines):

Background:
  Given I am logged in as a user with the "administrator" role
  And the content block type "basic" should exist
  And the following "basic" content blocks do not exist:
    | … |

Each scenario can then start with the creation step.

♻️ Duplicate comments (6)
tests/behat/features/block.feature (1)

33-35: Redundant pre-condition – duplicate “does not exist” step

Given the block "[TEST] User Account Menu" does not exist is executed twice
in a row. The second invocation is redundant and can safely be removed.

src/BlockTrait.php (4)

261-263: ⚠️ Potential issue

Incorrect argument order re-opens the earlier bug

The first argument of blockConfigureVisibilityCondition() must be $label, but the call here passes $condition first.
This will silently create/overwrite a different visibility config on the wrong block.

-    $this->blockConfigureVisibilityCondition($condition, $label, new TableNode([]));
+    $this->blockConfigureVisibilityCondition($label, $condition, new TableNode([]));

(You may also want to replace the “empty table” trick with an explicit removal API; see next comment.)


388-391: 🧹 Nitpick (assertive)

Block selection is still nondeterministic

krsort() followed by end() returns the oldest entity after an
implementation-defined hash sort.
If multiple blocks share the label you may test a different one each run.

Consider:

-    krsort($blocks);
-    return empty($blocks) ? NULL : end($blocks);
+    uasort($blocks, fn(Block $a, Block $b) => $b->id() <=> $a->id()); // newest first
+    return reset($blocks) ?: NULL;

or throw when duplicates exist.


62-88: 🛠️ Refactor suggestion

Avoid the double write: save only after full configuration

$block->save() is called before the real configuration is applied, causing
two entity revisions and extra database I/O.

-        $block->save();
-
-        break;
+        break;
       }
@@
-    $this->blockConfigure($admin_label, $fields);
-
-    static::$blockInstances[] = $block;
+    $this->blockConfigure($admin_label, $fields);
+    $block->save();
+
+    static::$blockInstances[] = $block;

245-263: 🛠️ Refactor suggestion

Use the dedicated removal API instead of “configure with an empty table”

Resetting the condition to its defaults does not remove the visibility
restriction. Drupal ≥8.8 exposes unsetVisibilityConfig() for this purpose.

-  public function blockRemoveVisibilityCondition(string $label, string $condition): void {
-    $this->blockConfigureVisibilityCondition($label, $condition, new TableNode([]));
+  public function blockRemoveVisibilityCondition(string $label, string $condition): void {
+    $this->blockAssertExists($label);
+    $block = $this->blockLoadByLabel($label);
+
+    if ($block->getVisibilityConfig()[$condition] ?? FALSE) {
+      $block->unsetVisibilityConfig($condition);
+      $block->save();
+    }
   }
steps.md (1)

90-93: Literal “\r\n” may confuse readers (unchanged)

The example cell shows the escaped CR/LF sequence verbatim:
/node/1\r\n/about.

Readers may interpret this as two characters rather than a line break. Use a
multi-line cell instead:

| pages | 
"""
/node/1
/about
"""
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between eee26a3 and 3cb4dce.

📒 Files selected for processing (5)
  • MIGRATION.md (1 hunks)
  • src/BlockTrait.php (3 hunks)
  • steps.md (2 hunks)
  • tests/behat/features/block.feature (1 hunks)
  • tests/behat/features/content_block.feature (5 hunks)
🔇 Additional comments (2)
tests/behat/features/content_block.feature (1)

17-19: Verify the availability of the step “I go to …”

The PathTrait examples (and the migration table) still refer to the step
When I visit :path. If the library does not register an alias for
I go to, these steps will be undefined at runtime.

Please confirm that I go to is wired up, or revert to the canonical
When I visit "/admin/content/block" / When I visit "/" wording.

tests/behat/features/block.feature (1)

19-21: Same “I go to …” alias question applies here

The scenario uses When I go to "/". Please double-check that this alias
is registered; otherwise the step will be undefined. If not, replace with
When I visit "/" to match existing PathTrait definitions.

@AlexSkrypnyk AlexSkrypnyk force-pushed the feature/367-update-BlockTrait branch 2 times, most recently from 4012d49 to 6d925cf Compare May 4, 2025 08:16
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🔭 Outside diff range comments (2)
tests/behat/features/content_block.feature (2)

8-10: 🧹 Nitpick (assertive)

Consider extracting repeated login & pre-conditions into a Background block

Each scenario starts with
Given I am logged in as a user with the "administrator" role
and
And the content block type "basic" should exist.

Moving these two ubiquitous pre-conditions into a single Background: section would make the scenarios shorter, remove duplication, and surface only the behaviour that differs per scenario.

Example:

Background:
  Given I am logged in as a user with the "administrator" role
  And the content block type "basic" should exist

This keeps all scenarios readable while still exercising the same paths.

Also applies to: 26-28, 40-43


14-16: 🧹 Nitpick (assertive)

Keep table headers in a consistent order

The column order for the “basic” block tables changes from info | status | body (lines 14-16) to info | body | status (line 42).
Mixing header order makes scenarios harder to read and increases the chance of copying the wrong format when tests are extended.

Align the later table with the earlier one:

-  | info               | body                | status |
+  | info               | status | body |

(or vice-versa, provided you pick one convention and stick to it throughout the suite).

Also applies to: 42-43

♻️ Duplicate comments (7)
MIGRATION.md (1)

16-17: 🧹 Nitpick (assertive)

“When” → “Then” still incorrect in v2 mapping

These two rows keep the v2 step keyword as When, but the original v2 steps were actually assertions (Then).
The mismatch was raised in a previous review and is still unresolved.

-| `When block with label :label should exist in the region :region`
-| `When block with label :label should not exist in the region :region`
+| `Then block with label :label should exist in the region :region`
+| `Then block with label :label should not exist in the region :region`

Keeping the correct keyword prevents users from blindly copy-pasting an inaccurate mapping and wondering why their scenarios read strangely.

steps.md (1)

90-93: 🧹 Nitpick (assertive)

Literal “\r\n” in example table may confuse readers

In the example value the carriage-return / line-feed escape sequence is rendered literally:

| pages  | /node/1\r\n/about |

Most readers will not expect to paste an escaped CR-LF sequence.
Consider showing it as a real multi-line cell (or bullet list) instead:

-| pages  | /node/1\r\n/about |
+| pages  | /node/1
+/about  |

or add a short note that multiple lines are allowed. This tiny adjustment improves copy-pasting accuracy.

src/BlockTrait.php (4)

261-263: ⚠️ Potential issue

Parameter order still swapped – step will fail

blockRemoveVisibilityCondition() calls blockConfigureVisibilityCondition() with the parameters in reverse order, reproducing the bug flagged in the previous review.

-    $this->blockConfigureVisibilityCondition($condition, $label, new TableNode([]));
+    $this->blockConfigureVisibilityCondition($label, $condition, new TableNode([]));

Without this fix Behat will inject label as condition and vice-versa, yielding “Unknown visibility condition” errors.


245-263: 🛠️ Refactor suggestion

Condition is reset, not removed – use unsetVisibilityConfig()

Passing an empty config merely resets the condition to its defaults; the visibility entry still exists.
Drupal ≥ 8.8 exposes unsetVisibilityConfig($id) for true removal.

-    $this->blockConfigureVisibilityCondition($label, $condition, new TableNode([]));
+    $this->blockAssertExists($label);
+    $block = $this->blockLoadByLabel($label);
+    $block->unsetVisibilityConfig($condition);
+    $block->save();

This guarantees the condition is gone, not silently set to default values.


81-87: 🛠️ Refactor suggestion

Avoid the double–write: configure the block before the first save

blockCreateInstance() persistently saves the entity (line 86) before handing it over to blockConfigure(), which then loads the same block again and saves once more.
This produces two revision writes where one would suffice, slowing down test runs and polluting the revision table.

A leaner flow is:

  1. Apply the configuration contained in $fields directly on the freshly-created $block.
  2. Call $block->save() only once after all properties are in place.
  3. Drop the subsequent blockConfigure() call (or refactor it to accept a Block argument so it can act in-memory).
-        $block->set('settings', $settings);
-        $block->save();
-
-        break;
+        $block->set('settings', $settings);
+
+        // Apply additional fields before the first (and only) save.
+        $this->applyBlockFieldConfiguration($block, $fields); // helper you’d introduce
+        $block->save();
+
+        break;

Doing so eliminates an unnecessary service round-trip and keeps revision history clean.


380-391: 🧹 Nitpick (assertive)

Non-deterministic block selection when duplicates exist

krsort($blocks); end($blocks); relies on PHP array keys (entity IDs) and still picks the last element after a descending sort.
If multiple blocks share the same label, the chosen entity changes with every new ID, leading to flaky tests.

Recommended approaches:

-    krsort($blocks);
-    return empty($blocks) ? NULL : end($blocks);
+    // Sort by numeric ID for repeatable order and always take the *first*.
+    uasort($blocks, static fn($a, $b) => $a->id() <=> $b->id());
+    return reset($blocks) ?: NULL;

Better yet, detect duplicates and throw to force unique labels in fixtures.

tests/behat/features/block.feature (1)

32-35: Duplicate “block does not exist” step – already flagged previously

The step is executed twice intentionally, but it was highlighted in a past review as redundant. If the goal is to prove idempotency you could add an inline comment or wrap it in a Scenario Outline to avoid confusion.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between 4012d49 and 6d925cf.

📒 Files selected for processing (5)
  • MIGRATION.md (1 hunks)
  • src/BlockTrait.php (3 hunks)
  • steps.md (2 hunks)
  • tests/behat/features/block.feature (1 hunks)
  • tests/behat/features/content_block.feature (5 hunks)
🔇 Additional comments (1)
tests/behat/features/block.feature (1)

19-20: Mixing “I go to” and “I visit” steps may hide coverage gaps

The file switches between

When I go to "/"
When I visit "/"

If both phrases map to the same underlying step this is harmless, but if they differ (e.g. one clears cache or waits for AJAX) the test intent becomes ambiguous. Standardise on one phrasing or add a comment explaining why both are required.

Also applies to: 180-184

Comment on lines 44 to +93
| label | [TEST] Content Block |
| label_display | 1 |
| region | content |
| status | 1 |
Then I should see the block with label "[TEST] Content Block"
And I should see the block with label "[TEST] Content Block" in the region "content"
Then the block "[TEST] Content Block" should exist
F438 Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Redundant status setting between content block and block instance

status is set to 1 in both the content-entity creation table (lines 40-42) and again inside the block-instance configuration table (lines 44-47).
Unless the underlying step definitions require both values, dropping the duplicate in the instance configuration reduces noise.

-  | region        | content              |
-  | status        | 1                    |
+  | region        | content              |

Comment on lines 221 to +230
| label | [TEST] User Account Menu |
| label_display | 1 |
| region | content |
| status | 1 |
Then I should see the block with label "[TEST] User Account Menu" in the region "content"
When I configure the block with the label "[TEST] User Account Menu" with:
Then the block "[TEST] User Account Menu" should exist in the "content" region

Given the block "[TEST] User Account Menu" has the following configuration:
| region | header |
Then I should see the block with label "[TEST] User Account Menu" in the region "header"
And I should not see the block with label "[TEST] User Account Menu" in the region "content"
Then the block "[TEST] User Account Menu" should exist in the "header" region
And the block "[TEST] User Account Menu" should not exist in the "content" region
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Possible missing cache clear after block move

After updating the block’s region configuration (line 227), the scenario immediately asserts the new placement (line 225-231). Depending on Drupal caching, the move may not be visible until caches are cleared. Consider adding the existing And the cache has been cleared step used elsewhere to avoid intermittent failures on slow CI runners.

Comment on lines +36 to +40
@trait:BlockTrait @api
Scenario: Assert "block should exist" fails for non-existing block
Given some behat configuration
And scenario steps:
"""
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Tag consistency – use @trait:BlockTrait everywhere or drop it

Most negative-test scenarios are tagged with @trait:BlockTrait @api, yet the positive scenarios (e.g. lines 9-31, 170-190, 219-231) only have @api. Using a consistent tag makes it trivial to run all BlockTrait tests via behat --tags=trait:BlockTrait.

Recommendation: add @trait:BlockTrait to the positive scenarios (or remove it from the negatives) so the suite can be filtered predictably.

@AlexSkrypnyk AlexSkrypnyk force-pushed the feature/367-update-BlockTrait branch from 6d925cf to 700fe3b Compare May 4, 2025 08:25
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (6)
tests/behat/features/content_block.feature (1)

43-47: 🧹 Nitpick (assertive)

Consider removing redundant status setting.

The status field is set to 1 in both the content block entity creation table (line 42) and again in the block instance configuration table (line 47). Unless both settings are required by the underlying implementation, removing the duplicate in the instance configuration would reduce noise.

  | label         | [TEST] Content Block |
  | label_display | 1                    |
  | region        | content              |
- | status        | 1                    |
tests/behat/features/block.feature (2)

227-230: Still no cache clear after a region change

We previously pointed out that immediately asserting a new placement after changing the region configuration can be flaky on some CI runners due to cached render arrays. You have not added the And the cache has been cleared step here, so the same intermittent-failure risk remains.


9-10: 🧹 Nitpick (assertive)

Add @trait:BlockTrait tag for consistency

The positive scenario is still tagged only with @api, while every negative scenario carries @trait:BlockTrait @api. Keeping the tag set uniform makes it trivial to run all trait-specific tests via behat --tags=trait:BlockTrait.

src/BlockTrait.php (3)

261-263: ⚠️ Potential issue

blockRemoveVisibilityCondition() still only resets, it doesn’t remove

Passing an empty TableNode calls setVisibilityConfig() with an empty array, which merely resets the condition to its defaults.
Use unsetVisibilityConfig() (Drupal 8.8+) or unset() to delete it outright, as previously suggested.


298-304: 🧹 Nitpick (assertive)

Doc-comment still contradicts behaviour

blockAssertNotExists() throws when the block does exist, but the @throws annotation claims it throws “When no block … is found”. Please update the comment to match reality.


80-88: 🛠️ Refactor suggestion

Avoid the double-save – configure before persisting

The block entity is saved once here (line 86) with only a temporary label and then saved again inside blockConfigure().
This produces an unnecessary write and two revisions.

-        $block->save();
-
-    ...
-    $this->blockConfigure($admin_label, $fields);
+        // Apply the full configuration before the first save to avoid a
+        // second write.
+        $this->blockConfigure($admin_label, $fields);
+        $block->save();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between 6d925cf and 700fe3b.

📒 Files selected for processing (6)
  • MIGRATION.md (1 hunks)
  • src/BlockTrait.php (3 hunks)
  • steps.md (2 hunks)
  • tests/behat/features/block.feature (1 hunks)
  • tests/behat/features/content_block.feature (5 hunks)
  • tests/behat/features/wait.feature 10000 (2 hunks)
🔇 Additional comments (10)
tests/behat/features/wait.feature (1)

6-6: Improved scenario tagging approach.

Moving tags from the feature level to individual scenarios creates more precise test execution contexts. This change allows the first scenario to run with just the @api tag while the second scenario retains both @api and @javascript tags as it tests AJAX functionality.

Also applies to: 17-17

MIGRATION.md (2)

7-19: Complete and well-structured BlockTrait migration mapping.

The new migration mapping for BlockTrait provides a clear path from v2 to v3 step definitions. The changes appropriately:

  1. Rename steps from "When" to "Given" or "Then" to better reflect their purpose
  2. Standardize phrasing by adding articles ("the") and simplifying terminology
  3. Clearly indicate which steps have been removed (visibility condition checks)

This mapping will help users transition their existing tests to the new standardized format.


16-17: Thanks for fixing the step keyword in the migration table.

The rows correctly show "Then" steps in both the original v2 and new v3 columns, addressing the previous review comment about using the correct assertion step keyword.

tests/behat/features/content_block.feature (3)

6-6: Improved tag granularity by moving @api to scenario level.

Tags are now properly applied at the scenario level rather than the feature level, improving execution context specificity for each test scenario.

Also applies to: 24-24, 38-38, 54-54, 64-64, 84-84


40-49: Standardized block instance creation and verification syntax.

Steps now use consistent phrasing with "Given the instance of..." and "Then the block... should exist" patterns, aligning with the updated BlockTrait interface. This improves readability and maintains consistency across the codebase.


75-79: Consistent block creation syntax in updated scenario.

Step definition now uses the standardized "Given the instance of... block exists with the following configuration" syntax, matching the other scenarios and maintaining consistent phrasing throughout the test suite.

steps.md (4)

5-5: Clearer BlockTrait description.

The updated description "Create, configure, and test block" is more concise and accurately reflects the trait's purpose.


35-43: Standardized step definitions with improved semantics.

The BlockTrait step definitions have been thoughtfully standardized with:

  1. More appropriate step keywords (@Given for setup and @Then for assertions)
  2. Consistent singular phrasing ("the block" instead of "block with label")
  3. Clearer parameter naming
  4. Addition of articles for improved readability
  5. Simplified, more direct language

These changes make the documentation more consistent and the step definitions more intuitive to use.

Also applies to: 48-55, 60-64, 69-73, 78-82, 87-93, 98-102, 107-111, 116-120, 125-129, 134-138


90-92: Clear example for condition configuration.

The example showing visibility condition configuration with paths is now clearer. The /node/1\r\n/about format might be better presented as a bullet list in future updates for even greater clarity, but it's sufficient as is.


101-101: Concrete condition value in example.

The example now uses a concrete condition value "request_path" instead of a placeholder, making it copyable for users - addressing a previous review comment.

Comment on lines +388 to 401
krsort($blocks);

return reset($blocks);
return empty($blocks) ? NULL : end($blocks);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

blockLoadByLabel() selection is still non-deterministic

krsort() + end() relies on PHP array-key order.
If several blocks share the same label you might pick an arbitrary one.
Load by id (ascending) or throw on duplicates instead of relying on hash order.

@AlexSkrypnyk AlexSkrypnyk force-pushed the feature/367-update-BlockTrait branch from 700fe3b to fdfd7be Compare May 4, 2025 08:41
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (6)
MIGRATION.md (1)

16-17: Step keyword corrected from "When" to "Then" as per previous feedback.

The block existence verification steps are now correctly categorized as assertions (Then) in the migration mapping, which aligns with their actual purpose and fixes the previously identified inconsistency.

tests/behat/features/content_block.feature (1)

89-92: 🧹 Nitpick (assertive)

Block instance configuration contains redundant status setting.

The status field appears to be set to 1 in both the content block entity (line 87) and again in the block instance configuration (line 92). Consider removing the duplicate setting in the instance configuration to reduce noise.

  | label         | [TEST] Content Block |
  | label_display | 1                    |
  | region        | content              |
- | status        | 1                    |
steps.md (1)

90-93: 🧹 Nitpick (assertive)

Example uses literal \r\n which may confuse users.

The example shows \r\n literally in the paths value, which might confuse readers about how to format multiple paths. Consider using a clearer demonstration of multiple paths, such as a bulleted list or explicit note.

tests/behat/features/block.feature (1)

9-10: Tag consistency – positive scenarios still miss @trait:BlockTrait

Earlier feedback (see past comments) recommended tagging every BlockTrait-related scenario with @trait:BlockTrait so that the whole trait can be executed via behat --tags=trait:BlockTrait.
The positive scenario starting here is still missing the tag, whereas the negative scenarios further below have it.

Adding the tag (or removing it from the negatives) will make the suite easier to filter.

src/BlockTrait.php (2)

374-390: Block selection is still non-deterministic

Using krsort() + end() relies on PHP’s hash order; if multiple blocks share the same label you may pick an arbitrary one.
Earlier reviews already flagged this – consider ordering by entity ID or throwing on duplicates for predictable behaviour.


261-263: ⚠️ Potential issue

Visibility condition is reset, not removed

Passing an empty TableNode merely resets the condition to defaults; it does not remove it.
Drupal ≥ 8.8 provides unsetVisibilityConfig() for this purpose.

-  public function blockRemoveVisibilityCondition(string $label, string $condition): void {
-    $this->blockConfigureVisibilityCondition($label, $condition, new TableNode([]));
+  public function blockRemoveVisibilityCondition(string $label, string $condition): void {
+    $this->blockAssertExists($label);
+    $block = $this->blockLoadByLabel($label);
+
+    $block->unsetVisibilityConfig($condition);
+    $block->save();
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between 700fe3b and fdfd7be.

📒 Files selected for processing (6)
  • MIGRATION.md (1 hunks)
  • src/BlockTrait.php (3 hunks)
  • steps.md (2 hunks)
  • tests/behat/features/block.feature (1 hunks)
  • tests/behat/features/content_block.feature (6 hunks)
  • tests/behat/features/wait.feature (2 hunks)
🔇 Additional comments (21)
tests/behat/features/wait.feature (2)

6-6: Tag scope narrowed appropriately.

The @api tag has been applied directly to this scenario instead of at the feature level, providing more precise control over test execution requirements.


17-17: Tags correctly specify required driver capabilities.

The @api @javascript tags ensure this AJAX-related scenario explicitly indicates its JavaScript dependency, making it clear that this test requires a JavaScript-capable driver.

MIGRATION.md (1)

7-19: Complete BlockTrait migration map added.

The migration table for BlockTrait provides a clear mapping between v2 and v3 step definitions, which is essential for users upgrading their test suites. The changes consistently apply the new naming conventions and step categorizations.

Key improvements:

  • Steps properly categorized as Given or Then based on their purpose
  • Use of definite articles ("the") for improved readability
  • Parameter naming standardization (:label:admin_label where appropriate)
  • Clear indication of removed steps
tests/behat/features/content_block.feature (9)

6-15: New scenario added to verify content block type existence.

This scenario properly tests the content block type verification functionality with appropriate tagging. It creates a test block and verifies the block type exists.


16-28: Added negative test for content block type validation.

This is a well-structured test that verifies the proper error message when attempting to check a non-existent content block type. Good practice to include negative test cases.


47-54: Added test to verify non-existent content blocks don't cause failures.

This scenario confirms that the step for checking non-existence of content blocks works correctly when the blocks already don't exist, which is an important edge case to test.


69-82: Added negative test for editing non-existent content block.

This scenario confirms that attempting to edit a non-existent content block produces the expected error message, providing thorough test coverage for error handling.


85-94: Updated block creation syntax.

The step has been updated from "When I create a block..." to "Given the instance of... block exists..." which aligns with the new naming conventions in BlockTrait. The surrounding assertions use the new syntax as well.


99-115: Added test for handling non-existent blocks in instance creation.

This scenario properly tests the error case when attempting to create a block instance with a non-existent block, verifying that the correct error message is displayed.


127-134: Updated block creation syntax in content update scenario.

The step for creating a block instance has been updated to use the new "Given the instance of... block exists" syntax, maintaining consistency with the new naming conventions.


150-163: Added comprehensive test for block deletion workflow.

This scenario provides a complete test of the content block lifecycle, creating, verifying, deleting, and confirming deletion of a block. This is good practice to ensure the entire workflow functions correctly.


164-171: Added test for deleting non-existent content block.

This scenario confirms that attempting to delete a content block that doesn't exist doesn't cause failures, which is important for robustness in test suites.

steps.md (8)

5-5: BlockTrait description simplified.

The description has been made more concise while still accurately describing the trait's functionality.


35-43: Updated block creation step definition.

The step has been renamed from @When I create a block of type :label with: to @Given the instance of :admin_label block exists with the following configuration:, which better reflects its purpose as a setup step rather than an action.


48-56: Updated block configuration step definition.

The step has been renamed from @When I configure the block with the label :label with: to @Given the block :label has the following configuration:, which is more consistent with the new naming pattern.


60-66: Added step to specify block non-existence.

A new step @Given the block :label does not exist has been added, which provides a direct way to ensure a block doesn't exist before running tests.


69-84: Renamed block enable/disable steps.

The enable/disable steps have been renamed to use more direct phrasing: @Given the block :label is enabled and @Given the block :label is disabled, which is clearer than the previous versions.


87-94: Updated block condition configuration step.

The condition configuration step has been updated to use clearer phrasing and includes a proper example with request_path condition.


98-103: Updated block condition removal step.

The step for removing conditions has been updated to use consistent phrasing with other steps, and the example now uses a concrete condition type ("request_path") instead of the placeholder.


107-140: Updated block existence verification steps.

The verification steps have been updated to use assertion phrasing (@Then the block :label should exist), which better reflects their purpose as assertions rather than actions.

tests/behat/features/block.feature (1)

32-34: Idempotency check acknowledged

Nice touch adding the explicit comment explaining why the step is repeated.
Running the “block does not exist” step twice is a neat way to verify idempotency and no further action is required.

Comment on lines 19 to 21
When I go to "/"
Then I should see "[TEST] User Account Menu"

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Mixed “go to” vs “visit” step keywords

Most scenarios were migrated to the new wording When I go to "/", yet lines 180-185 still use the old When I visit "/".
If the old step definition was removed (as suggested by the PR description), these scenarios will break.
Please harmonise the wording to avoid dangling step definitions or runtime errors.

Also applies to: 180-185

< CEB7 /div>

@AlexSkrypnyk AlexSkrypnyk force-pushed the feature/367-update-BlockTrait branch 2 times, most recently from 451823d to c1a2264 Compare May 4, 2025 08:50
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (10)
MIGRATION.md (1)

16-17: Doc rows correctly show original step keywords.

The migration table properly shows that the v2 assertion steps were originally When steps despite being assertions. This matches the historical implementation and will help users accurately identify which steps to replace when migrating.

tests/behat/features/content_block.feature (1)

83-98: 🧹 Nitpick (assertive)

Redundant status setting between content block and block instance.

The status is set to 1 in both the content-entity creation table (line 87) and again inside the block-instance configuration table (line 92). Unless both values are required by the underlying implementation, this creates unnecessary duplication.

Consider removing the redundant status setting from the block instance configuration:

  | label_display | 1                    |
  | region        | content              |
- | status        | 1                    |
steps.md (1)

87-93: 🧹 Nitpick (assertive)

Consider improving the readability of the multi-line example value.

The example uses \r\n to represent newlines in the pages field, which may be confusing to readers who aren't familiar with this notation. This could be represented more clearly.

Consider using a more readable format for representing multiple values:

-| pages  | /node/1\r\n/about |
+| pages  | /node/1           |
+|        | /about            |

Or alternatively:

-| pages  | /node/1\r\n/about |
+| pages  | [multiple paths]: |
+|        | - /node/1         |
+|        | - /about          |
src/BlockTrait.php (4)

261-263: blockRemoveVisibilityCondition() does not actually remove the condition

Passing an empty configuration only resets the condition; the condition object
still exists and will be evaluated with default settings.

Use unsetVisibilityConfig() (available since Drupal 8.8) or explicit unset():

-  public function blockRemoveVisibilityCondition(string $label, string $condition): void {
-    $this->blockConfigureVisibilityCondition($label, $condition, new TableNode([]));
+  public function blockRemoveVisibilityCondition(string $label, string $condition): void {
+    $this->blockAssertExists($label);
+    $block = $this->blockLoadByLabel($label);
+    $block->unsetVisibilityConfig($condition);
+    $block->save();
   }

388-390: Selection remains non-deterministic when duplicate labels exist

krsort() + end() relies on PHP’s array-key order; if several blocks share
the same visible label you may randomly pick different ones between runs.
Consider ordering by id (ascending) or throwing on duplicates instead.


161-165: 🛠️ Refactor suggestion

Keep the static registry in sync after explicit removals

blockRemove() deletes matching entities but never removes them from static::$blockInstances.
If the same label was registered earlier, blockAfterScenario() will attempt a second delete and explode.

   while ($block = $this->blockLoadByLabel($label)) {
     $block->delete();
   }
+
+  // Purge the registry so teardown stays idempotent.
+  static::$blockInstances = array_filter(
+    static::$blockInstances,
+    fn(Block $b) => $b->get('settings')['label'] !== $label
+  );

42-47: 🛠️ Refactor suggestion

Make teardown resilient to blocks deleted inside scenarios

blockAfterScenario() unconditionally calls $block->delete().
If a scenario already removed the entity (e.g. via Given the block … does not exist), the second delete triggers an EntityStorageException, failing the suite during @afterScenario.

-    foreach (static::$blockInstances as $block) {
-      $block->delete();
-    }
+    foreach (static::$blockInstances as $key => $block) {
+      try {
+        $block->delete();
+      }
+      // Ignore “already deleted” errors so teardown is idempotent.
+      catch (\Drupal\Core\Entity\EntityStorageException $e) {
+        // no-op
+      }
+      unset(static::$blockInstances[$key]);
+    }
tests/behat/features/block.feature (3)

32-35: Redundant “block does not exist” step executed twice

Lines 33–34 repeat the same pre-condition and add noise to the scenario without
providing extra safety. Deleting the second line keeps the intent clear.


19-20: Mixed “visit” vs “go to” wording may leave dangling step definitions

New wording elsewhere uses When I go to "/", but these lines still rely on
When I visit "/". If the old step definition was removed (per migration
guide) these steps will break at runtime. Harmonise the vocabulary.

Also applies to: 183-184


227-231: Possible missing cache clear after moving the block

After changing the region configuration (line 227) the scenario immediately
asserts the new placement. Depending on Drupal caching, the move might not be
visible until caches are cleared, causing flakes on slow CI runners. Consider
adding And the cache has been cleared before the assertions.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between fdfd7be and c1a2264.

📒 Files selected for processing (6)
  • MIGRATION.md (1 hunks)
  • src/BlockTrait.php (3 hunks)
  • steps.md (2 hunks)
  • tests/behat/features/block.feature (1 hunks)
  • tests/behat/features/content_block.feature (6 hunks)
  • tests/behat/features/wait.feature (2 hunks)
🔇 Additional comments (14)
tests/behat/features/wait.feature (1)

6-6: Improved test organization with scenario-level tagging.

The changes add specific Behat tags (@api and @javascript) to individual scenarios rather than at the feature level. This provides more granular control over which scenarios require API access or JavaScript capabilities.

Also applies to: 17-17

MIGRATION.md (1)

7-19: Well-structured BlockTrait migration documentation.

The new BlockTrait migration mapping clearly documents how v2 step definitions map to v3 equivalents. The changes reflect a shift to more semantic and consistent step definitions:

  • Verb changes from "When" to "Given" for setup steps
  • Improved phrasing with "the block" instead of "block with label"
  • Standardized organization of parameters
  • Clearly marked removed steps

This addition provides essential guidance for users migrating from v2 to v3.

tests/behat/features/content_block.feature (7)

6-14: Added comprehensive test for content block type validation.

This new scenario provides proper coverage for verifying that content block types exist, including testing for a basic content block type and checking the admin UI to confirm visibility.


16-28: Added negative test scenario for non-existent block types.

This scenario verifies the error handling when attempting to validate non-existent content block types, ensuring the proper error message is displayed. This complements the positive test case and ensures robust error handling.


47-54: Added idempotency test for "blocks do not exist" operation.

This scenario verifies that the "Given the following content blocks do not exist" step does not fail when the blocks already don't exist. This ensures the step is safe to use in setups without knowledge of current state.


69-82: Added test for failure handling with non-existent content blocks.

This scenario ensures that attempting to edit a non-existent content block produces the expected error message, providing test coverage for error handling in this edge case.


99-115: Added failure test for invalid block instances.

This scenario properly tests that attempting to create a block instance with a non-existent block admin label fails with the appropriate error message.


150-163: Added complete block lifecycle test.

This scenario provides end-to-end testing of the creation and deletion of content blocks, verifying UI state along the way. This is an important test for ensuring the complete lifecycle of content blocks functions correctly.


164-171: Added safety check for deleting non-existent blocks.

This scenario ensures that attempting to delete non-existent content blocks doesn't fail, which is important for idempotent operations in test setups.

steps.md (5)

5-5: Updated BlockTrait description.

The description has been simplified and clarified to better reflect the functionality provided by the trait.


35-43: Improved block creation step definition syntax.

The step definition has been changed from @When I create a block of type :label with: to @Given the instance of :admin_label block exists with the following configuration:. This makes the intent clearer and shifts from an action-focused to a state-focused approach, which is better for test setup.


48-56: Improved block configuration step definition 3D11 .

The step definition has been changed from @When I configure the block with the label :label with: to @Given the block :label has the following configuration:. This makes the intent clearer and shifts to a state-focused approach.


98-103: Improved block condition removal step.

The step definition has been changed from @When I remove the visibility condition :condition from the block with label :label to @Given the block :label has the :condition condition removed. The example now correctly demonstrates a concrete condition name ("request_path") rather than a placeholder.


107-140: Standardized block assertion step definitions.

The assertion steps have been standardized to follow a consistent pattern:

  • @Then the block :label should exist
  • @Then the block :label should not exist
  • @Then the block :label should exist in the :region region
  • @Then the block :label should not exist in the :region region

This consistency makes the steps more intuitive and easier to remember.

@AlexSkrypnyk AlexSkrypnyk force-pushed the feature/367-update-BlockTrait branch from c1a2264 to e675bda Compare May 4, 2025 08:58
Copy link
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (9)
MIGRATION.md (1)

16-17: Correctly addressed previous review feedback

The mapping now correctly shows that these block existence checks are "Then" steps in v3, properly reflecting their purpose as assertions rather than actions.

tests/behat/features/content_block.feature (1)

86-92: 🧹 Nitpick (assertive)

Redundant status setting between content block and block instance

The status field is set to 1 in both the content block creation table and the block instance configuration table. Unless both settings are required by the underlying implementation, one could be removed to reduce redundancy.

   | info               | body                | status |
   | [TEST] Basic Block | [TEST] Body content | 1      |
 And the instance of "[TEST] Basic Block" block exists with the following configuration:
   | label         | [TEST] Content Block |
   | label_display | 1                    |
   | region        | content              |
-  | status        | 1                    |
+  | status        | TRUE                 |

Alternatively, if both status fields are serving different purposes, consider adding a code comment to clarify the distinction.

steps.md (1)

90-92: 🧹 Nitpick (assertive)

Literal \r\n sequence may confuse readers

The example still shows the escaped CR/LF sequence literally (/node/1\r\n/about).
Consider using a multi-line cell or bullet list so the rendered Markdown is clearer to readers and avoids copy/paste surprises.

tests/behat/features/block.feature (3)

19-21: Step wording diverges from the new “go to” convention

Most scenarios were migrated to When I go to "/", yet these still use When I visit "/".
If the legacy step definition was removed during the refactor, these steps will break at runtime.


9-11: 🧹 Nitpick (assertive)

Tag consistency – add @trait:BlockTrait to positive scenario

Negative scenarios carry the tag, but this main happy-path scenario does not.
Keeping tags consistent makes it trivial to run all BlockTrait tests:
behat --tags=trait:BlockTrait.


227-231: 🧹 Nitpick (assertive)

Possible missing cache clear after changing region

Immediately asserting the new placement after updating the region configuration can intermittently fail on some CI runners due to cached render arrays.
Consider inserting And the cache has been cleared before the assertions, mirroring the pattern used elsewhere in the file.

src/BlockTrait.php (3)

271-273: 🛠️ Refactor suggestion

⚠️ Potential issue

blockRemoveVisibilityCondition() does not actually remove the condition

Passing an empty configuration only resets to defaults. Use unsetVisibilityConfig() (Drupal ≥ 8.8) or explicit unset() so the condition is removed:

-    $this->blockConfigureVisibilityCondition($label, $condition, new TableNode([]));
+    $this->blockAssertExists($label);
+    $block = $this->blockLoadByLabel($label);
+
+    if (method_exists($block, 'unsetVisibilityConfig')) {
+      $block->unsetVisibilityConfig($condition);
+    }
+    else {
+      $block->setVisibilityConfig($condition, []);
+    }
+
+    $block->save();

86-92: 🛠️ Refactor suggestion

⚠️ Potential issue

Avoid double-save when creating a block

blockCreateInstance() saves the entity (line 91) and then blockConfigure() saves it again (line 151).
This creates an extra revision and doubles the I/O cost.

-        // Temporary label…
-        $block->set('settings', $settings);
-
-        $block->save();
+        // Temporary label…
+        $block->set('settings', $settings);

blockConfigure() will persist the entity once the full configuration is applied.


398-400: 🧹 Nitpick (assertive)

Non-deterministic selection when multiple blocks share a label

krsort() + end() depends on PHP’s internal hash order. If two blocks have the same label, a random one may be picked between runs.
Sort deterministically (e.g. by id) or throw when duplicates are found.

-    krsort($blocks);
-    return empty($blocks) ? NULL : end($blocks);
+    if (count($blocks) > 1) {
+      usort($blocks, fn(Block $a, Block $b) => $a->id() <=> $b->id());
+    }
+    return $blocks ? reset($blocks) : NULL;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Lite

📥 Commits

Reviewing files that changed from the base of the PR and between c1a2264 and e675bda.

📒 Files selected for processing (7)
  • MIGRATION.md (1 hunks)
  • src/BlockTrait.php (3 hunks)
  • src/ContentBlockTrait.php (2 hunks)
  • steps.md (2 hunks)
  • tests/behat/features/block.feature (1 hunks)
  • tests/behat/features/content_block.feature (6 hunks)
  • tests/behat/features/wait.feature (2 hunks)
🔇 Additional comments (4)
tests/behat/features/wait.feature (1)

6-6: Good improvement to tag granularity

Moving from feature-level tags to scenario-level tags provides better test isolation and more precise control over which scenarios require JavaScript capabilities.

Also applies to: 17-17

MIGRATION.md (1)

7-19: Well-structured migration documentation for BlockTrait

This comprehensive migration map clearly guides users from v2 to v3 step definitions, with consistent naming conventions and appropriate step types (Given/Then) that match their actual purpose.

src/ContentBlockTrait.php (1)

10-11: Improved robustness in entity cleanup

Good enhancement to the cleanup process by adding exception handling and individual entity removal from the tracking array. This prevents test teardown failures when entities can't be deleted or have already been removed, making tests more reliable.

Also applies to: 39-47

tests/behat/features/content_block.feature (1)

6-171: Excellent expansion of test coverage

The addition of both positive and negative test scenarios greatly improves test coverage. The new scenarios systematically validate correct behavior as well as proper error handling for edge cases.

Comment on lines +383 to 388
* @return \Drupal\block\Entity\Block|null
* The loaded block entity or NULL if not found.
*
* @throws \Exception
* When no block with the specified label is found.
*/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Doc-block contradicts implementation

The @throws annotation claims an exception is thrown “when no block is found”, yet the method now returns null instead.
Update the comment (or restore the exception) to keep documentation accurate.

@AlexSkrypnyk AlexSkrypnyk merged commit 6852df3 into 3.x May 4, 2025
5 checks passed
@AlexSkrypnyk AlexSkrypnyk deleted the feature/367-update-BlockTrait branch May 4, 2025 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0