OBSINTA-1290: Incident Tests Stability#887
OBSINTA-1290: Incident Tests Stability#887DavidRajnoha wants to merge 6 commits intoopenshift:mainfrom
Conversation
Three layered defenses against Chrome/Node.js OOM (exit 137) and infinite hangs in findIncidentWithAlert's retry loop: 1. cy.reload() at start of each search iteration — releases browser DOM from previous iteration, preventing browser-side accumulation. 2. _quietSearch/_qLog() pattern — suppresses Cypress command logging (and DOM snapshot serialization, ~1-5 MB each) during search. Without this, ~40 commands * 15+ iterations = 600+ snapshots OOM. 3. Hard timeout safety net (35 min) — Date.now()-based kill switch that fires if cy.waitUntil's timeout breaks due to cy.reload() interfering with the Cypress command queue. Also adds warmUpForPlugin() page object method for plugin loading race condition (used by subsequent commit). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the simple waitUntil loop with the OOM-protected findIncidentWithAlert — it uses cy.reload(), _quietSearch, and hard timeout to safely poll for up to 30 minutes without OOM. The previous approach accumulated Cypress command snapshots and browser DOM across 15+ retry cycles, causing exit 137 in CI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The monitoring-console-plugin registers the Incidents tab extension asynchronously after Cypress session restoration. Without warm-up, the tab may not be registered before beforeEach() tries to navigate, causing flaky failures in reg/02-05 specs. Uses warmUpForPlugin() (added in previous commit) which polls for the Incidents tab via jQuery check for up to 3 minutes — replacing the fragile goTo() that relied on the 80s default command timeout. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove 3 cy.pause() debug calls from the tooltip boundary test (02.reg_ui_tooltip_boundary_times) that block automated runs. The @xfail tag is already excluded by CI test commands (--@xfail). - Add missing silenced-and-firing-mixed-severity fixture referenced by 02.incidents-mocking-example.cy.ts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@DavidRajnoha: This pull request references OBSINTA-1290 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
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 openshift-eng/jira-lifecycle-plugin repository. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: DavidRajnoha The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
@DavidRajnoha: This pull request references OBSINTA-1290 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
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 openshift-eng/jira-lifecycle-plugin repository. |
WalkthroughAdded plugin warm-up and search-timeout management to Cypress incidents tests and the incidents-page view; replaced a maxMinutes wait with explicit interval-based polling, muted Cypress DOM logging during searches for OOM-safe traversal, removed manual pauses, and added a new mixed-severity incident fixture. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 10✅ Passed checks (10 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/cypress/views/incidents-page.ts (1)
403-431:⚠️ Potential issue | 🟠 MajorIndex incidents by bar group, not by flattened path order.
These helpers still treat
incidentsChartBarsVisiblePaths()as “one entry per incident”, but multi-severity incidents render multiple visible paths. That meansselectIncidentByBarIndex()can click the wrong incident, anddeselectIncidentByBar()always clicks the first visible path rather than the currently selected bar. Downstream,traverseAllIncidentsBars()can skip incidents, revisit the same one, or fail once it searches past index 0.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/cypress/views/incidents-page.ts` around lines 403 - 431, selectIncidentByBarIndex and deselectIncidentByBar are indexing into the flattened nodes returned by incidentsChartBarsVisiblePaths() but the chart renders multi-severity incidents as multiple <path>s per logical bar; change both helpers to operate on bar groups instead of flattened paths: use a grouped selector (e.g., incidentsChartBars() or find the parent/bar container around paths) to get one element per incident, validate index against that group length, and click the appropriate clickable child inside the chosen group (first path or specific selector). For deselectIncidentByBar, locate the currently selected bar group (e.g., filter by a selected class/attribute) or accept an index parameter and click that group's clickable child instead of always clicking $paths.eq(0). Also update traverseAllIncidentsBars to iterate over the bar groups (the same grouped selector) so it visits each logical incident once.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.ts`:
- Around line 53-55: The waitUntil call uses interval: 2 * intervalMs but
timeout: 30 * intervalMs, which shortens the effective search window by one
poll; update the timeout to include one full polling interval (e.g., set timeout
to 30 * intervalMs + (2 * intervalMs) or otherwise add the interval value) so
that cy.waitUntil(..., { interval: 2 * intervalMs, timeout: 30 * intervalMs + (2
* intervalMs) }) ensures incidentsPage.findIncidentWithAlert(currentAlertName)
is polled across the full intended 30-minute window.
In `@web/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.ts`:
- Around line 42-46: The before() hook currently calls cy.beforeBlockCOO(MCP,
MP, ...) and incidentsPage.resetSearchTimeout() but omits the plugin warm-up;
add a call to incidentsPage.warmUpForPlugin() in this before() hook (run it
before navigating or before resetSearchTimeout) so the Incidents tab is warmed
before session restore/navigation and avoids the async plugin-registration race;
update the before() in 03-04.reg_e2e_firing_alerts.cy.ts to invoke
incidentsPage.warmUpForPlugin() alongside cy.beforeBlockCOO(...) and
incidentsPage.resetSearchTimeout().
In `@web/cypress/views/incidents-page.ts`:
- Around line 639-641: The module-level flags _findIncidentSearchStart and
_quietSearch are only cleared in the hard-timeout and success (.then) branches;
ensure you call the existing reset helper (resetSearchTimeout) from all
failure/cleanup paths as well (including any .catch/.finally or Cypress failure
callbacks inside the search chain) so that when a Cypress command fails the
module state is cleared and subsequent tests don't inherit quiet mode or a stale
start timestamp; update the failure branches referenced around the search flow
(including the block covering lines 842-875) to invoke resetSearchTimeout where
appropriate.
---
Outside diff comments:
In `@web/cypress/views/incidents-page.ts`:
- Around line 403-431: selectIncidentByBarIndex and deselectIncidentByBar are
indexing into the flattened nodes returned by incidentsChartBarsVisiblePaths()
but the chart renders multi-severity incidents as multiple <path>s per logical
bar; change both helpers to operate on bar groups instead of flattened paths:
use a grouped selector (e.g., incidentsChartBars() or find the parent/bar
container around paths) to get one element per incident, validate index against
that group length, and click the appropriate clickable child inside the chosen
group (first path or specific selector). For deselectIncidentByBar, locate the
currently selected bar group (e.g., filter by a selected class/attribute) or
accept an index parameter and click that group's clickable child instead of
always clicking $paths.eq(0). Also update traverseAllIncidentsBars to iterate
over the bar groups (the same grouped selector) so it visits each logical
incident once.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 325d507e-5629-49b5-9b0c-1758c8e7bbc0
📒 Files selected for processing (9)
web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.tsweb/cypress/e2e/incidents/regression/02.reg_ui_charts_comprehensive.cy.tsweb/cypress/e2e/incidents/regression/02.reg_ui_tooltip_boundary_times.cy.tsweb/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.tsweb/cypress/e2e/incidents/regression/03.reg_api_calls.cy.tsweb/cypress/e2e/incidents/regression/04.reg_redux_effects.cy.tsweb/cypress/e2e/incidents/regression/05.reg_stress_testing_ui.cy.tsweb/cypress/fixtures/incident-scenarios/silenced-and-firing-mixed-severity.yamlweb/cypress/views/incidents-page.ts
💤 Files with no reviewable changes (1)
- web/cypress/e2e/incidents/regression/02.reg_ui_tooltip_boundary_times.cy.ts
- waitUntil timeout: add one extra interval to avoid off-by-one where the last poll fires 2 min before timeout expires - 03-04.reg_e2e_firing_alerts: add missing warmUpForPlugin() call that all other regression specs already have - incidents-page.ts: extract _resetSearchState() helper and use it on both success and error paths so _quietSearch and _findIncidentSearchStart don't leak across specs on failure Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
03ddbe2 to
580dc96
Compare
|
@DavidRajnoha: This pull request references OBSINTA-1290 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
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 openshift-eng/jira-lifecycle-plugin repository. |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
web/cypress/views/incidents-page.ts (1)
847-890:⚠️ Potential issue | 🟠 MajorReset the search state on every terminal path.
This still only clears
_findIncidentSearchStarton hard timeout or atrueresult. A normalfalseresult leaves the old start time alive, so later independentfindIncidentWithAlert()calls inherit a shortened 35-minute budget. If any Cypress command in this chain fails before the final.then(...),_quietSearchleaks too._resetSearchState()needs to run whenever the search ends, not only on success.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/cypress/views/incidents-page.ts` around lines 847 - 890, The search state reset is only invoked on hard timeout or when a match is found, causing _findIncidentSearchStart and _quietSearch to leak on normal false results or on errors; update findIncidentWithAlert to ensure _resetSearchState() always runs when the search finishes (success, false, or error) and that _quietSearch is restored to false for non-success paths. Concretely, add a terminal cleanup handler on the Cypress chain (e.g., a .finally or a concluding .then/.catch pair) that calls _resetSearchState() and sets _quietSearch = false when found === false or on errors, and also call _resetSearchState() only once for the successful path, referencing the existing function name findIncidentWithAlert plus symbols _resetSearchState and _quietSearch to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/cypress/views/incidents-page.ts`:
- Around line 419-442: In selectIncidentByBarIndex and deselectIncidentByBar,
stop clicking the unconditional .first() path inside a bar group; instead locate
the visible segment first by filtering for visible/non-zero-opacity paths (the
same visible-segment filter used elsewhere) on
incidentsChartBarsGroups().eq(index) before calling .first() and .click({ force:
true, ..._qLog() }) so you target the actual displayed segment rather than a
hidden placeholder.
---
Duplicate comments:
In `@web/cypress/views/incidents-page.ts`:
- Around line 847-890: The search state reset is only invoked on hard timeout or
when a match is found, causing _findIncidentSearchStart and _quietSearch to leak
on normal false results or on errors; update findIncidentWithAlert to ensure
_resetSearchState() always runs when the search finishes (success, false, or
error) and that _quietSearch is restored to false for non-success paths.
Concretely, add a terminal cleanup handler on the Cypress chain (e.g., a
.finally or a concluding .then/.catch pair) that calls _resetSearchState() and
sets _quietSearch = false when found === false or on errors, and also call
_resetSearchState() only once for the successful path, referencing the existing
function name findIncidentWithAlert plus symbols _resetSearchState and
_quietSearch to locate the change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 22eef24d-65bd-42b6-9e63-d65990bb9270
📒 Files selected for processing (4)
web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.tsweb/cypress/e2e/incidents/01.incidents.cy.tsweb/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.tsweb/cypress/views/incidents-page.ts
✅ Files skipped from review due to trivial changes (1)
- web/cypress/e2e/incidents/regression/03-04.reg_e2e_firing_alerts.cy.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- web/cypress/e2e/incidents/00.coo_incidents_e2e.cy.ts
|
/test e2e-incidents |
- selectIncidentByBarIndex/deselectIncidentByBar: use incidentsChartBarsGroups() (one element per incident) instead of incidentsChartBarsVisiblePaths() (flattened paths). Fixes incorrect incident selection/deselection with multi-severity incidents. - findIncidentWithAlert: count bar groups instead of flattened paths - deselectIncidentByBar: accept index parameter to deselect the correct incident instead of always clicking the first bar - 01.incidents.cy.ts: add warmUpForPlugin() to before() hook — same plugin loading race fix as reg/02-05 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
580dc96 to
d9f37d2
Compare
|
@DavidRajnoha: This pull request references OBSINTA-1290 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set. DetailsIn response to this:
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 openshift-eng/jira-lifecycle-plugin repository. |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
web/cypress/views/incidents-page.ts (1)
875-898:⚠️ Potential issue | 🟠 MajorSearch state still is not cleaned up on command failures.
This still only resets via the hard-timeout branch or the final success
.then(...). If any Cypress command inprepareIncidentsPageForSearch()ortraverseAllIncidentsBars()fails first, that tail callback never runs, so later searches inherit_quietSearchand a stale_findIncidentSearchStart.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/cypress/views/incidents-page.ts` around lines 875 - 898, The search state (_quietSearch and _findIncidentSearchStart) must be cleaned on both success and failure: wrap the cy.get(...).then(...) promise chain that calls prepareIncidentsPageForSearch() and traverseAllIncidentsBars(...) with an error handler so failures also call _resetSearchState() (and set _quietSearch = false if appropriate) before rethrowing the error; in practice add a .catch / second-argument .then error callback after the chain that calls _resetSearchState() and resets _quietSearch/_findIncidentSearchStart and then rethrows so the original test failure still surfaces.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@web/cypress/views/incidents-page.ts`:
- Around line 90-100: The DOM existence probe runs before the queued
cy.wait(500, _qLog()) resolves, so move the probe to run after the wait: inside
the .then(($body) => { ... }) return cy.wait(500, _qLog()).then(() => { const
exists =
$body.find('g[role="presentation"][data-test*="incidents-chart-bar-"]').length >
0; if (exists) { return
cy.get('g[role="presentation"][data-test*="incidents-chart-bar-"]', _qLog()) ...
} else { return [] } }); this ensures the check for the selector executes after
the delay and uses the same $body reference.
---
Duplicate comments:
In `@web/cypress/views/incidents-page.ts`:
- Around line 875-898: The search state (_quietSearch and
_findIncidentSearchStart) must be cleaned on both success and failure: wrap the
cy.get(...).then(...) promise chain that calls prepareIncidentsPageForSearch()
and traverseAllIncidentsBars(...) with an error handler so failures also call
_resetSearchState() (and set _quietSearch = false if appropriate) before
rethrowing the error; in practice add a .catch / second-argument .then error
callback after the chain that calls _resetSearchState() and resets
_quietSearch/_findIncidentSearchStart and then rethrows so the original test
failure still surfaces.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: 1c4eca30-99ea-489d-9013-012288f9179c
📒 Files selected for processing (2)
web/cypress/e2e/incidents/01.incidents.cy.tsweb/cypress/views/incidents-page.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- web/cypress/e2e/incidents/01.incidents.cy.ts
| return cy.get('body', _qLog()).then(($body) => { | ||
| // There is a delay between the element being rendered and the paths being visible. | ||
| // The case when no paths are visible is valid, so we can not use should or conditional | ||
| // testing semantics. | ||
| cy.wait(500); | ||
| // The case when no paths are visible is valid, so we can not use should | ||
| // or conditional testing semantics. | ||
| cy.wait(500, _qLog()); | ||
| // We need to use the $body as both cases when the element is there or not are valid. | ||
| const exists = | ||
| $body.find('g[role="presentation"][data-test*="incidents-chart-bar-"]').length > 0; | ||
| if (exists) { | ||
| return cy | ||
| .get('g[role="presentation"][data-test*="incidents-chart-bar-"]') | ||
| .get('g[role="presentation"][data-test*="incidents-chart-bar-"]', _qLog()) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n web/cypress/views/incidents-page.ts | head -120 | tail -50Repository: openshift/monitoring-plugin
Length of output: 3067
🏁 Script executed:
rg -n "findIncidentWithAlert|_resetSearchState" web/cypress/views/incidents-page.ts -A 5 -B 2Repository: openshift/monitoring-plugin
Length of output: 2516
🏁 Script executed:
sed -n '855,920p' web/cypress/views/incidents-page.tsRepository: openshift/monitoring-plugin
Length of output: 2624
🏁 Script executed:
rg -n "prepareIncidentsPageForSearch" web/cypress/views/incidents-page.ts -A 20 -B 2Repository: openshift/monitoring-plugin
Length of output: 2231
🏁 Script executed:
rg -n "traverseAllIncidentsBars" web/cypress/views/incidents-page.ts -A 5 -B 2 | head -30Repository: openshift/monitoring-plugin
Length of output: 661
Move the DOM existence probe to execute after the queued wait.
On line 94, cy.wait(500) is queued inside the .then() callback, but the synchronous $body.find() check on line 96 executes immediately—before the wait resolves. This means if the bar groups appear during that 500 ms window, the check still takes the empty-path branch and returns [], negating the delay you intended.
Restructure to ensure the wait completes before the DOM probe:
Suggested fix
incidentsChartBarsVisiblePaths: () => {
- return cy.get('body', _qLog()).then(($body) => {
+ return cy.wait(500, _qLog()).then(() => cy.get('body', _qLog()).then(($body) => {
// There is a delay between the element being rendered and the paths being visible.
// The case when no paths are visible is valid, so we can not use should
// or conditional testing semantics.
- cy.wait(500, _qLog());
// We need to use the $body as both cases when the element is there or not are valid.
const exists =
$body.find('g[role="presentation"][data-test*="incidents-chart-bar-"]').length > 0;
if (exists) {
return cy
.get('g[role="presentation"][data-test*="incidents-chart-bar-"]', _qLog())
.find('path[role="presentation"]')
.filter((index, element) => {
const fillOpacity =
Cypress.$(element).css('fill-opacity') || Cypress.$(element).attr('fill-opacity');
return parseFloat(fillOpacity || '0') > 0;
});
} else {
if (!_quietSearch) cy.log('Chart bars were not found. Test continues.');
return cy.wrap([], _qLog());
}
- });
+ }));
},📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| return cy.get('body', _qLog()).then(($body) => { | |
| // There is a delay between the element being rendered and the paths being visible. | |
| // The case when no paths are visible is valid, so we can not use should or conditional | |
| // testing semantics. | |
| cy.wait(500); | |
| // The case when no paths are visible is valid, so we can not use should | |
| // or conditional testing semantics. | |
| cy.wait(500, _qLog()); | |
| // We need to use the $body as both cases when the element is there or not are valid. | |
| const exists = | |
| $body.find('g[role="presentation"][data-test*="incidents-chart-bar-"]').length > 0; | |
| if (exists) { | |
| return cy | |
| .get('g[role="presentation"][data-test*="incidents-chart-bar-"]') | |
| .get('g[role="presentation"][data-test*="incidents-chart-bar-"]', _qLog()) | |
| incidentsChartBarsVisiblePaths: () => { | |
| return cy.wait(500, _qLog()).then(() => cy.get('body', _qLog()).then(($body) => { | |
| // There is a delay between the element being rendered and the paths being visible. | |
| // The case when no paths are visible is valid, so we can not use should | |
| // or conditional testing semantics. | |
| // We need to use the $body as both cases when the element is there or not are valid. | |
| const exists = | |
| $body.find('g[role="presentation"][data-test*="incidents-chart-bar-"]').length > 0; | |
| if (exists) { | |
| return cy | |
| .get('g[role="presentation"][data-test*="incidents-chart-bar-"]', _qLog()) | |
| .find('path[role="presentation"]') | |
| .filter((index, element) => { | |
| const fillOpacity = | |
| Cypress.$(element).css('fill-opacity') || Cypress.$(element).attr('fill-opacity'); | |
| return parseFloat(fillOpacity || '0') > 0; | |
| }); | |
| } else { | |
| if (!_quietSearch) cy.log('Chart bars were not found. Test continues.'); | |
| return cy.wrap([], _qLog()); | |
| } | |
| })); | |
| }, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@web/cypress/views/incidents-page.ts` around lines 90 - 100, The DOM existence
probe runs before the queued cy.wait(500, _qLog()) resolves, so move the probe
to run after the wait: inside the .then(($body) => { ... }) return cy.wait(500,
_qLog()).then(() => { const exists =
$body.find('g[role="presentation"][data-test*="incidents-chart-bar-"]').length >
0; if (exists) { return
cy.get('g[role="presentation"][data-test*="incidents-chart-bar-"]', _qLog()) ...
} else { return [] } }); this ensures the check for the selector executes after
the delay and uses the same $body reference.
Testsuite stability improvement generated by POC agentic loop. Looking for coderabbit feedback.
OOM prevention in search loop:
cy.reload()to free browser DOM,_quietSearchto suppressCypress snapshot accumulation, and a 35-min hard timeout safety net against infinite hangs
Plugin warm-up:
warmUpForPlugin()polls for the Incidents tab up to 3 min, fixing flakyreg/02–05 specs caused by async plugin registration after session restoration
Test hygiene: remove
cy.pause()debug calls, add missing fixtureSummary by CodeRabbit