Skip to content

[#1090] Treated the 'anonymous' role as a logout in 'I am logged in as a user with the role(s) :roles'. - #1094

Merged
AlexSkrypnyk merged 3 commits into
mainfrom
feature/1090-anonymous-role-logout
Oct 23, 2026
Merged

AlexSkrypnyk merged 3 commits into
mainfrom
feature/1090-anonymous-role-logout

Conversation

@AlexSkrypnyk

@AlexSkrypnyk AlexSkrypnyk commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Closes #1090

Summary

Given I am logged in as a user with the role "anonymous" now logs the current user out, the same way Given I am an anonymous user does. anonymous user and any capitalization of either work too, so a Scenario Outline can list anonymous in its Examples table beside the real roles.

On 4.0.0-rc2 that row failed at the login step with Drupal's Anonymous or authenticated role ID must not be assigned manually. (InvalidArgumentException), because UserTrait::userLoginWithRoles() created an account and tried to assign anonymous to it. Given I am an anonymous user takes no argument, so an Examples row couldn't pick it, and every access-matrix outline had to be split up or the step overridden in FeatureContext.

When anonymous sits beside other roles ("anonymous, editor"), or shows up in the ... and I have the following fields: step or a roles column of Given the following users exist:, the step fails with The role "anonymous" cannot be assigned to a user. (\RuntimeException). It fails before any account is saved or any role is assigned, on both the Drupal and Drush backends. The step text and every other role stay as they were.

Before / After

Given I am logged in as a user with the role "<role>"   (Examples row: anonymous)

BEFORE
  userLoginWithRoles("anonymous")
    └─ userCreateAndLogin()
         ├─ authCreateUser()          account saved
         └─ userAssignRoles()
              └─ addUserRole("anonymous")
                   └─ InvalidArgumentException   ✗ row fails

AFTER
  userLoginWithRoles("anonymous")
    ├─ userIsAnonymousRole()  ──yes──▶ authLogout(TRUE)   ✓ anonymous session
    └─ no ──▶ userCreateAndLogin()
                ├─ userParseRoles()   "anonymous, editor" ──▶ RuntimeException
                │                     (before the account is saved)
                ├─ authCreateUser()
                └─ userAssignRoles()  ──▶ addUserRole() per parsed role

Changes

Step and helpers (src/Steps/Drupal/UserTrait.php)

  • userLoginWithRoles() calls authLogout(TRUE) and returns when userIsAnonymousRole() holds; otherwise it creates and logs in a user as before.
  • userIsAnonymousRole() (new, public) is TRUE when the list holds exactly 1 role, anonymous or anonymous user, in any case.
  • userParseRoles() (new, public) turns a role list into the roles an account can be assigned: it drops authenticated and empty entries, and throws on anonymous.
  • userAssignRoles() assigns the parsed roles, so a list naming anonymous assigns none of them. userCreate() and userCreateAndLogin() parse the list before saving the account.

Tests

  • tests/phpunit/src/Unit/Steps/Drupal/UserTraitTest.php (new) covers userIsAnonymousRole(), userParseRoles() and userAssignRoles(), including anonymous before and after another role.
  • tests/behat/features/drupal_user.feature adds the access-matrix outline from the issue (administrator, authenticated, anonymous, anonymous user, Anonymous). It also adds an outline that logs in as administrator, switches to each anonymous spelling and asserts that user/login stays on /user/login. A logged-in user gets redirected to their profile there, so this tells a real logout apart from a non-admin account. 2 @test-trait scenarios cover the mixed list and a roles column of anonymous user.

Docs

  • MIGRATION.md describes the anonymous role as logging out again in the 3.14 step table and the OverrideTrait method table.
  • STEPS.md, HELPERS.md and docs/content/drupal-steps/user.md are regenerated with ahoy update-docs.

Summary

  • UserTrait now treats anonymous and anonymous user as a request to log out when either is the only role specified, regardless of capitalization.
  • Role parsing now rejects anonymous roles in mixed lists. User creation and role assignment validate the roles before saving or assigning them.
  • Added PHPUnit and Behat coverage for anonymous login behavior, role parsing, mixed-role failures, and access-matrix scenarios.
  • Updated the helper index, migration guide, and step documentation.

Step-definition review

No step-definition rule violations were identified in the inspected definitions. The change adds helper methods and tests; it does not add a step definition.

@AlexSkrypnyk AlexSkrypnyk added this to the 4.0 milestone Oct 23, 2026
@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: ASSERTIVE
  • Plan: Team
  • Run ID: 454eac2b-d6f3-4a5d-ae7f-777c78849c84
📥 Commits

Reviewing files that changed from the base of the PR and between 5c625ca and 03a1ee1.

📒 Files selected for processing: 7
  • HELPERS.md
  • MIGRATION.md
  • STEPS.md
  • docs/content/drupal-steps/user.md
  • src/Steps/Drupal/UserTrait.php
  • tests/behat/features/drupal_user.feature
  • tests/phpunit/src/Unit/Steps/Drupal/UserTraitTest.php

Included review availability: This review used your included allowance. 0 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour.

Walkthrough

The Drupal user trait now detects anonymous-only role lists, logs out instead of creating an account for those requests, and rejects anonymous roles when they appear with other roles or during account creation. Tests and documentation cover the updated role handling.

Changes

Anonymous role handling

Layer / File(s) Summary
Role parsing and account validation
src/Steps/Drupal/UserTrait.php, tests/phpunit/src/Unit/Steps/Drupal/UserTraitTest.php, HELPERS.md
The trait adds role parsing and anonymous-role detection. It excludes authenticated roles, rejects anonymous roles during assignment or account creation, and tests parsing, assignment, and rejection behavior. The helper index and documentation list the new methods.
Anonymous-role login behavior
src/Steps/Drupal/UserTrait.php, tests/behat/features/drupal_user.feature, STEPS.md, docs/content/drupal-steps/user.md, MIGRATION.md
The login step logs out when the role list contains only anonymous or anonymous user. Behat scenarios cover access results and invalid mixed roles. Step examples and migration guidance describe the behavior.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant BehatStep
  participant UserTrait
  BehatStep->>UserTrait: userLoginWithRoles(roles)
  UserTrait->>UserTrait: userIsAnonymousRole(roles)
  alt role list contains only anonymous
    UserTrait->>UserTrait: userLogoutSession()
  else other role list
    UserTrait->>UserTrait: userCreateAndLogin(roles)
  end
Loading
Merge Risk: ⚪ Minimal · up to 03a1e

The anonymous-role behavior is ready to merge with normal checks. A future test could more directly guard against saving an account before rejecting the role.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 73.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 2 files. (5 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly describes the primary change: treating the "anonymous" role as a logout in the specified user-login step. It is specific and relevant to the changeset.
Linked Issues check Passed Issue #1090 requires the role step to treat exactly anonymous or anonymous user as an anonymous session, including case variants, and to reject mixed lists. userLoginWithRoles() calls `authLogou…
Out of Scope Changes check Passed The changes stay within issue #1090. The parser and assignment changes prevent invalid anonymous roles in user creation paths. The PHPUnit tests, Behat scenarios, and documentation support the request…
Full details: Linked Issues check

Explanation

Issue #1090 requires the role step to treat exactly anonymous or anonymous user as an anonymous session, including case variants, and to reject mixed lists. userLoginWithRoles() calls authLogout(TRUE) and returns when userIsAnonymousRole() matches. userIsAnonymousRole() handles both names case-insensitively. userParseRoles() rejects anonymous roles before account creation or role assignment. PHPUnit and Behat coverage tests these cases. The migration and step documentation also describe the behavior.

Full details: Out of Scope Changes check

Explanation

The changes stay within issue #1090. The parser and assignment changes prevent invalid anonymous roles in user creation paths. The PHPUnit tests, Behat scenarios, and documentation support the requested role and logout behavior. No unrelated product behavior is demonstrated.

Full details: Docstring Coverage

Explanation

Docstring coverage is 73.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 15 functions across 2 files. (5 skipped: 5 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A rabbit checked the role list twice,
“Anonymous means logout,” said it nice.
Empty commas hop away,
Authenticated roles don’t stay,
And mixed roles earn a parsing slice.

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

@codecov

codecov Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.23%. Comparing base (5c625ca) to head (03a1ee1).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1094      +/-   ##
==========================================
+ Coverage   99.22%   99.23%   +0.01%     
==========================================
  Files         180      180              
  Lines        9570     9583      +13     
==========================================
+ Hits         9496     9510      +14     
+ Misses         74       73       -1     

☔ View full report in Codecov by Harness.
📢 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.

@AlexSkrypnyk AlexSkrypnyk added the Needs review Pull request needs a review from assigned developers label Oct 23, 2026
@AlexSkrypnyk
AlexSkrypnyk merged commit 274ba66 into main Oct 23, 2026
23 checks passed
@AlexSkrypnyk
AlexSkrypnyk deleted the feature/1090-anonymous-role-logout branch October 23, 2026 02:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A1 Needs review Pull request needs a review from assigned developers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Treat the 'anonymous' role as a logout in 'I am logged in as a user with the role(s) :roles'

1 participant