Skip to content

fix(e2e): use scoped menuitem locator for Settings in profile dropdown [AI /e2e-fix]#4590

Open
zdrapela wants to merge 3 commits intoredhat-developer:release-1.8from
zdrapela:fix/e2e-guest-signin-settings-link
Open

fix(e2e): use scoped menuitem locator for Settings in profile dropdown [AI /e2e-fix]#4590
zdrapela wants to merge 3 commits intoredhat-developer:release-1.8from
zdrapela:fix/e2e-guest-signin-settings-link

Conversation

@zdrapela
Copy link
Copy Markdown
Member

@zdrapela zdrapela commented Apr 15, 2026

Summary

  • Root cause: goToSettingsPage() used clickLink("Settings") which resolves to locator('a').filter({ hasText: 'Settings' }).first() — a broad selector matching any <a> with "Settings" text. Under CI conditions, hidden elements match first and the dropdown menuitem times out.
  • Fix: Replace with getByRole("menuitem", { name: "Settings" }) to precisely target the dropdown menuitem, matching the fix already on main (PR fix(e2e): fix custom-theme test navigation and overlay issues #4436).

Test Results

  • Local verification: 5/5 passes
  • Code quality: tsc, eslint, prettier all pass

Related

@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Apr 15, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@zdrapela
Copy link
Copy Markdown
Member Author

/agentic_review

@zdrapela
Copy link
Copy Markdown
Member Author

/test ?

@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge bot commented Apr 15, 2026

Code Review by Qodo

🐞 Bugs (1)   📘 Rule violations (0)   📎 Requirement gaps (0)
🐞\ ≡ Correctness (1)

Grey Divider


Action required

1. Hardcoded Settings label 🐞
Description
UIhelper.goToSettingsPage() selects the profile dropdown item by the hardcoded accessible name
"Settings", so it cannot find/click the menuitem when tests run under non-English locales where the
Settings label is translated (e.g., fr uses "Paramètres"). This can break any suite that calls
goToSettingsPage() in the localization projects (e.g., custom-theme via ThemeVerifier).
Code

e2e-tests/playwright/utils/ui-helper.ts[R254-260]

+    // TODO: [RHDHBUGS-2552](https://redhat.atlassian.net/browse/RHDHBUGS-2552) - Strings not getting translated
+    // The profile dropdown renders Settings as a menuitem, not an <a> link
+    const settingsItem = this.page.getByRole("menuitem", {
+      name: "Settings",
+    });
+    await expect(settingsItem).toBeVisible();
+    await settingsItem.click();
Evidence
goToSettingsPage() now locates a menuitem by the literal name "Settings". However, other E2E tests
treat the profile dropdown Settings item as localized using
t["user-settings"][lang]["settingsLayout.title"], and the French translation for that key is
"Paramètres". The Playwright config defines a French localization project that runs
default-global-header and custom-theme, and ThemeVerifier.setTheme() calls goToSettingsPage(), so a
localized Settings label would cause this method to fail to locate the menuitem.

e2e-tests/playwright/utils/ui-helper.ts[251-261]
e2e-tests/playwright/e2e/default-global-header.spec.ts[116-132]
translations/core-plugins_v1.8_s3281-fr-C.json[309-317]
e2e-tests/playwright.config.ts[197-210]
e2e-tests/playwright/utils/custom-theme/theme-verifier.ts[13-24]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`UIhelper.goToSettingsPage()` hardcodes the menuitem accessible name as `"Settings"`. This conflicts with the repo’s localization support and other tests that use `t["user-settings"][lang]["settingsLayout.title"]` (e.g., fr: `"Paramètres"`), causing failures when running with `LOCALE!=en`.

### Issue Context
- Other tests already use the localized key for the Settings menu item.
- The Playwright config defines a French localization project that runs suites which indirectly call `goToSettingsPage()`.

### Fix Focus Areas
- e2e-tests/playwright/utils/ui-helper.ts[251-261]

### Suggested fix
- Replace the hardcoded `name: "Settings"` with the localized string used elsewhere, ideally with a safe fallback:
 - `const settingsLabel = t["user-settings"][lang]["settingsLayout.title"] ?? "Settings";`
 - Then use `name: settingsLabel` for the menuitem locator.
- Keep the new role-based approach (menuitem) to avoid hidden `<a>` matches.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Grey Divider

Previous review results

Review updated until commit d691a0a

Results up to commit 29c7f6b


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review Grey Divider Grey Divider

Qodo Logo

@zdrapela
Copy link
Copy Markdown
Member Author

/test e2e-ocp-helm-nightly

@github-actions
Copy link
Copy Markdown
Contributor

Image was built and published successfully. It is available at:

The goToSettingsPage() method used clickLink('Settings') which resolves to
locator('a').filter({ hasText: 'Settings' }).first() — a broad selector
that can match hidden <a> elements elsewhere in the page. Under CI
conditions (3 workers, slower rendering), the dropdown menuitem is found
but not visible in time, causing TimeoutError.

Replace with getByRole('menuitem', { name: 'Settings' }) which precisely
targets the profile dropdown menuitem. This matches the fix already on
main (PR redhat-developer#4436).

Assisted-by: OpenCode
@zdrapela zdrapela force-pushed the fix/e2e-guest-signin-settings-link branch from 29c7f6b to d691a0a Compare April 15, 2026 14:13
@zdrapela
Copy link
Copy Markdown
Member Author

/agentic_review

@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge bot commented Apr 15, 2026

Persistent review updated to latest commit d691a0a

@github-actions
Copy link
Copy Markdown
Contributor

Image was built and published successfully. It is available at:

@zdrapela
Copy link
Copy Markdown
Member Author

/test ?

@zdrapela zdrapela marked this pull request as ready for review April 15, 2026 15:07
@zdrapela
Copy link
Copy Markdown
Member Author

/test e2e-ocp-helm-nightly

@openshift-ci openshift-ci bot requested review from albarbaro and psrna April 15, 2026 15:07
@rhdh-qodo-merge
Copy link
Copy Markdown

rhdh-qodo-merge bot commented Apr 15, 2026

Code Review by Qodo

🐞 Bugs (2)   📘 Rule violations (0)   📎 Requirement gaps (0)
🐞\ ≡ Correctness (1) ☼ Reliability (1) ⭐ New (1)

Grey Divider


Action required

1. Hardcoded Settings label 🐞
Description
UIhelper.goToSettingsPage() selects the profile dropdown item by the hardcoded accessible name
"Settings", so it cannot find/click the menuitem when tests run under non-English locales where the
Settings label is translated (e.g., fr uses "Paramètres"). This can break any suite that calls
goToSettingsPage() in the localization projects (e.g., custom-theme via ThemeVerifier).
Code

e2e-tests/playwright/utils/ui-helper.ts[R254-260]

+    // TODO: [RHDHBUGS-2552](https://redhat.atlassian.net/browse/RHDHBUGS-2552) - Strings not getting translated
+    // The profile dropdown renders Settings as a menuitem, not an <a> link
+    const settingsItem = this.page.getByRole("menuitem", {
+      name: "Settings",
+    });
+    await expect(settingsItem).toBeVisible();
+    await settingsItem.click();
Evidence
goToSettingsPage() now locates a menuitem by the literal name "Settings". However, other E2E tests
treat the profile dropdown Settings item as localized using
t["user-settings"][lang]["settingsLayout.title"], and the French translation for that key is
"Paramètres". The Playwright config defines a French localization project that runs
default-global-header and custom-theme, and ThemeVerifier.setTheme() calls goToSettingsPage(), so a
localized Settings label would cause this method to fail to locate the menuitem.

e2e-tests/playwright/utils/ui-helper.ts[251-261]
e2e-tests/playwright/e2e/default-global-header.spec.ts[116-132]
translations/core-plugins_v1.8_s3281-fr-C.json[309-317]
e2e-tests/playwright.config.ts[197-210]
e2e-tests/playwright/utils/custom-theme/theme-verifier.ts[13-24]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`UIhelper.goToSettingsPage()` hardcodes the menuitem accessible name as `"Settings"`. This conflicts with the repo’s localization support and other tests that use `t["user-settings"][lang]["settingsLayout.title"]` (e.g., fr: `"Paramètres"`), causing failures when running with `LOCALE!=en`.

### Issue Context
- Other tests already use the localized key for the Settings menu item.
- The Playwright config defines a French localization project that runs suites which indirectly call `goToSettingsPage()`.

### Fix Focus Areas
- e2e-tests/playwright/utils/ui-helper.ts[251-261]

### Suggested fix
- Replace the hardcoded `name: "Settings"` with the localized string used elsewhere, ideally with a safe fallback:
 - `const settingsLabel = t["user-settings"][lang]["settingsLayout.title"] ?? "Settings";`
 - Then use `name: settingsLabel` for the menuitem locator.
- Keep the new role-based approach (menuitem) to avoid hidden `<a>` matches.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Missing settings page wait 🐞
Description
UIhelper.goToSettingsPage() clicks the Settings menuitem and returns without waiting for navigation
or a Settings-page element, so callers can run Settings-page interactions before the page is ready
and intermittently fail. This is observable in flows that call common.signOut() immediately after
goToSettingsPage().
Code

e2e-tests/playwright/utils/ui-helper.ts[R256-261]

+    const settingsItem = this.page.getByRole("menuitem", {
+      name: "Settings",
+    });
+    await expect(settingsItem).toBeVisible();
+    await settingsItem.click();
  }
Evidence
goToSettingsPage ends right after clicking the Settings menuitem, with no URL/element wait.
common.signOut then immediately clicks Settings page-specific selectors (user-settings-menu,
sign-out), and at least one test calls goToSettingsPage() followed directly by common.signOut()
without any intermediate assertion/wait, so the sign-out clicks can race navigation/rendering.

e2e-tests/playwright/utils/ui-helper.ts[251-261]
e2e-tests/playwright/utils/common.ts[51-55]
e2e-tests/playwright/e2e/guest-signin-happy-path.spec.ts[37-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`goToSettingsPage()` clicks the Settings dropdown item but does not wait for navigation or for any Settings-page-specific UI to appear. This allows subsequent steps (e.g., `Common.signOut()` clicking `user-settings-menu`) to run before the Settings page has finished loading, causing intermittent test failures.

### Issue Context
Multiple tests call `goToSettingsPage()` and then immediately interact with Settings page elements. At minimum, `guest-signin-happy-path.spec.ts` calls `goToSettingsPage()` followed by `common.signOut()` with no other wait.

### Fix Focus Areas
- e2e-tests/playwright/utils/ui-helper.ts[251-261]

### Suggested change
After clicking the Settings menu item, add an explicit wait that proves the Settings page is ready, e.g.:
- `await expect(this.page.getByTestId('user-settings-menu')).toBeVisible();` (best, because it’s page-specific), and/or
- `await this.page.waitForURL(/\/settings(\/|$)/);`

Optionally wrap click + wait in `Promise.all` to avoid missing fast navigations:
```ts
await Promise.all([
 this.page.waitForURL(/\/settings(\/|$)/),
 settingsItem.click(),
]);
await expect(this.page.getByTestId('user-settings-menu')).toBeVisible();
```

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@rhdh-qodo-merge
Copy link
Copy Markdown

Review Summary by Qodo

Fix Settings link selector in profile dropdown for CI stability

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Replace broad link selector with scoped menuitem locator in Settings navigation
• Use getByRole("menuitem") to precisely target dropdown Settings item
• Add visibility check before clicking to prevent timeout errors
• Aligns with existing fix on main branch (PR #4436)
Diagram
flowchart LR
  A["goToSettingsPage()"] -->|"Old: clickLink('Settings')"| B["Broad selector<br/>matches hidden elements"]
  B -->|"CI conditions"| C["TimeoutError"]
  A -->|"New: getByRole('menuitem')"| D["Scoped dropdown selector"]
  D -->|"+ visibility check"| E["Reliable click"]
Loading

Grey Divider

File Changes

1. e2e-tests/playwright/utils/ui-helper.ts 🐞 Bug fix +7/-5

Replace broad link selector with scoped menuitem locator

• Replace clickLink("Settings") with getByRole("menuitem", { name: "Settings" })
• Add explicit visibility check via expect(settingsItem).toBeVisible()
• Change from generic link selector to role-based menuitem selector
• Improves reliability under CI conditions with slower rendering

e2e-tests/playwright/utils/ui-helper.ts


Grey Divider

Qodo Logo

@zdrapela
Copy link
Copy Markdown
Member Author

zdrapela commented Apr 15, 2026

The hardcoded "Settings" is intentional and matches the current implementation on main. The TODO: [RHDHBUGS-2552](https://redhat.atlassian.net/browse/RHDHBUGS-2552) comment documents that the global header strings are not getting translated yet — until that product bug is fixed, using t["user-settings"][lang]["settingsLayout.title"] would not work correctly. Once RHDHBUGS-2552 is resolved, this should be updated to use the localized string.

@zdrapela
Copy link
Copy Markdown
Member Author

/retest

@zdrapela
Copy link
Copy Markdown
Member Author

/test e2e-ocp-helm

@github-actions
Copy link
Copy Markdown
Contributor

The container image build workflow finished with status: failure.

zdrapela added a commit to zdrapela/rhdh that referenced this pull request Apr 16, 2026
…lity

- Use scoped menuitem locator for Settings in profile dropdown (redhat-developer#4590)
- Fix bulk-import tests: optional chaining for env vars, nightly-only
  check, retry with filterAndVerifyAddedRepo, correct status text (redhat-developer#4583)
- Fix FAB sub-menu click stability with dispatchEvent and toBeVisible
  guard (redhat-developer#4591)

Assisted-by: OpenCode
zdrapela added a commit to zdrapela/rhdh that referenced this pull request Apr 16, 2026
…lity

- Use scoped menuitem locator for Settings in profile dropdown (redhat-developer#4590)
- Fix bulk-import tests: optional chaining for env vars, nightly-only
  check, retry with filterAndVerifyAddedRepo, correct status text (redhat-developer#4583)
- Fix FAB sub-menu click stability with dispatchEvent and toBeVisible
  guard (redhat-developer#4591)

Assisted-by: OpenCode
zdrapela added a commit to zdrapela/rhdh that referenced this pull request Apr 16, 2026
…lity

- Use scoped menuitem locator for Settings in profile dropdown (redhat-developer#4590)
- Fix bulk-import tests: optional chaining for env vars, nightly-only
  check, retry with filterAndVerifyAddedRepo, correct status text (redhat-developer#4583)
- Fix FAB sub-menu click stability with dispatchEvent and toBeVisible
  guard (redhat-developer#4591)

Assisted-by: OpenCode
zdrapela added a commit to zdrapela/rhdh that referenced this pull request Apr 16, 2026
…lity

- Use scoped menuitem locator for Settings in profile dropdown (redhat-developer#4590)
- Fix bulk-import tests: optional chaining for env vars, nightly-only
  check, retry with filterAndVerifyAddedRepo, correct status text (redhat-developer#4583)
- Fix FAB sub-menu click stability with dispatchEvent and toBeVisible
  guard (redhat-developer#4591)

Assisted-by: OpenCode
@github-actions
Copy link
Copy Markdown
Contributor

Image was built and published successfully. It is available at:

@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Apr 16, 2026

@zdrapela: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-ocp-helm-nightly d691a0a link false /test e2e-ocp-helm-nightly
ci/prow/e2e-ocp-helm e17ef49 link true /test e2e-ocp-helm

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant