Skip to content

CONSOLE-5279: Migrate secrets e2e tests from Cypress to Playwright#16522

Open
Cragsmann wants to merge 3 commits into
openshift:mainfrom
Cragsmann:CONSOLE-5279
Open

CONSOLE-5279: Migrate secrets e2e tests from Cypress to Playwright#16522
Cragsmann wants to merge 3 commits into
openshift:mainfrom
Cragsmann:CONSOLE-5279

Conversation

@Cragsmann
Copy link
Copy Markdown
Contributor

@Cragsmann Cragsmann commented Jun 1, 2026

Analysis / Root cause:
Migrate 5 Cypress secret test files (12 tests) to Playwright as part of the broader Playwright e2e migration effort.

Jira: https://redhat.atlassian.net/browse/CONSOLE-5279

Solution description:
Migrates 12 secrets tests across 5 spec files from Cypress to Playwright:

  • key-value.spec.ts (4 tests): binary/ascii/unicode file secrets, TLS secret editing
  • image-pull.spec.ts (3 tests): registry credentials CRUD, config file upload, password obfuscation
  • source.spec.ts (2 tests): basic auth and SSH auth secret CRUD
  • webhook.spec.ts (1 test): create, regenerate, and delete webhook secret
  • add-to-workload.spec.ts (2 tests): add secret as environment variables and as volume mount

New files:

  • e2e/pages/secret-page.ts — page object with methods for secret creation, editing, verification, and add-to-workload modal
  • e2e/fixtures/secrets/ — binary, ascii, and unicode test fixture files
  • e2e/tests/console/crud/secrets/ — 5 spec files

Extends KubernetesClient with createSecret, getSecret, and getDeployment methods.

Each test is self-contained with unique namespaces and automatic cleanup via cleanup.trackNamespace().

Screenshots / screen recording:

Test setup:
Requires a running OpenShift/OKD cluster with e2e/.env configured.

Test cases:
All 12 tests validated with 3 consecutive stability runs (0 failures):

npx playwright test e2e/tests/console/crud/secrets/ --project=console --retries=0 --workers=1
Cypress test Playwright test Assertions
creates binary file secret creates a binary file secret 2 → 2
creates ascii file secret creates an ascii file secret 2 → 2
creates unicode file secret creates a unicode file secret 2 → 2
edits a TLS secret edits a TLS secret 3 → 3
creates and edits registry credentials creates and edits registry credentials 4 → 4
uploads config file creates an upload config file 2 → 2
obfuscates password field obfuscates password fields 2 → 2
creates/edits basic auth secret creates, edits, and deletes basic source 4 → 4
creates SSH auth secret creates, edits, and deletes SSH source 4 → 4
creates/regenerates/deletes webhook creates, regenerates, and deletes webhook 3 → 3
adds secret as env vars adds secret as env vars 3 → 3
adds secret as volume adds secret as volume 3 → 3

Browser conformance:

  • Chrome

Additional info:
Part of the Cypress → Playwright migration effort tracked under CONSOLE-5279.

Reviewers and assignees:

Summary by CodeRabbit

  • Tests

    • Added extensive end-to-end coverage for secret workflows (create/edit, key/value and file secrets, image-pull/source/webhook secrets, and adding secrets to workloads) and for storage flows (PVC cloning, snapshots, volume-attributes, and storage class creation).
  • Chores

    • Improved test infrastructure and UI test helpers (page objects, fixtures, and Kubernetes resource helpers) and migrated storage tests to the updated E2E framework.

Cragsmann and others added 2 commits May 29, 2026 13:58
Migrate 4 Cypress storage test files to Playwright under
e2e/tests/console/storage/ and delete the original Cypress files.

- create-storage-class: 9 provisioner tests (all passing)
- clone: 2 PVC clone tests (skip on non-AWS clusters)
- snapshot: 2 VolumeSnapshot tests (skip on non-AWS clusters)
- volume-attributes-class: 1 VAC lifecycle test (skip on non-AWS)

Add KubernetesClient methods for cluster-scoped custom resources,
PVCs, and Deployments. Add ListPage and ModalPage page objects.
Fix ListPage filter selector to use data-test-id="item-filter"
(PF6 TextInput does not forward data-test to the DOM input).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrate 12 secrets tests across 5 spec files to Playwright:
- key-value.spec.ts (4 tests): binary/ascii/unicode file secrets, TLS edit
- image-pull.spec.ts (3 tests): registry credentials, config file upload, password obfuscation
- source.spec.ts (2 tests): basic auth and SSH auth secrets
- webhook.spec.ts (1 test): create, regenerate, and delete
- add-to-workload.spec.ts (2 tests): env vars and volume mount

Adds SecretPage page object and extends KubernetesClient with
createSecret, getSecret, and getDeployment methods.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jun 1, 2026
@openshift-ci-robot
Copy link
Copy Markdown
Contributor

openshift-ci-robot commented Jun 1, 2026

@Cragsmann: This pull request references CONSOLE-5279 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 story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Analysis / Root cause:
Migrate 5 Cypress secret test files (12 tests) to Playwright as part of the broader Playwright e2e migration effort.

Jira: https://redhat.atlassian.net/browse/CONSOLE-5279

Solution description:
Migrates 12 secrets tests across 5 spec files from Cypress to Playwright:

  • key-value.spec.ts (4 tests): binary/ascii/unicode file secrets, TLS secret editing
  • image-pull.spec.ts (3 tests): registry credentials CRUD, config file upload, password obfuscation
  • source.spec.ts (2 tests): basic auth and SSH auth secret CRUD
  • webhook.spec.ts (1 test): create, regenerate, and delete webhook secret
  • add-to-workload.spec.ts (2 tests): add secret as environment variables and as volume mount

New files:

  • e2e/pages/secret-page.ts — page object with methods for secret creation, editing, verification, and add-to-workload modal
  • e2e/fixtures/secrets/ — binary, ascii, and unicode test fixture files
  • e2e/tests/console/crud/secrets/ — 5 spec files

Extends KubernetesClient with createSecret, getSecret, and getDeployment methods.

Each test is self-contained with unique namespaces and automatic cleanup via cleanup.trackNamespace().

Screenshots / screen recording:

Test setup:
Requires a running OpenShift/OKD cluster with e2e/.env configured.

Test cases:
All 12 tests validated with 3 consecutive stability runs (0 failures):

npx playwright test e2e/tests/console/crud/secrets/ --project=console --retries=0 --workers=1
Cypress test Playwright test Assertions
creates binary file secret creates a binary file secret 2 → 2
creates ascii file secret creates an ascii file secret 2 → 2
creates unicode file secret creates a unicode file secret 2 → 2
edits a TLS secret edits a TLS secret 3 → 3
creates and edits registry credentials creates and edits registry credentials 4 → 4
uploads config file creates an upload config file 2 → 2
obfuscates password field obfuscates password fields 2 → 2
creates/edits basic auth secret creates, edits, and deletes basic source 4 → 4
creates SSH auth secret creates, edits, and deletes SSH source 4 → 4
creates/regenerates/deletes webhook creates, regenerates, and deletes webhook 3 → 3
adds secret as env vars adds secret as env vars 3 → 3
adds secret as volume adds secret as volume 3 → 3

Browser conformance:

  • Chrome

Additional info:
Part of the Cypress → Playwright migration effort tracked under CONSOLE-5279.

Reviewers and assignees:

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.

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 1, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 191a1f51-3355-49ac-a50d-d06b0ad662c0

📥 Commits

Reviewing files that changed from the base of the PR and between ca19bef and e4256c4.

📒 Files selected for processing (1)
  • frontend/e2e/clients/kubernetes-client.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/e2e/clients/kubernetes-client.ts

Walkthrough

Migrates Cypress tests to Playwright: adds Playwright page objects, fixtures and storage mocks, multiple Playwright e2e suites for secrets and storage, extends KubernetesClient with resource helpers, and removes legacy Cypress/integration-test fixtures and helpers.

Changes

Playwright E2E Migration

Layer / File(s) Summary
Kubernetes client API wrappers
frontend/e2e/clients/kubernetes-client.ts
KubernetesClient gains methods for Secrets, cluster-scoped Custom Resources, PersistentVolumeClaims, and Deployments to support test operations.
Playwright page objects
frontend/e2e/pages/base-page.ts, frontend/e2e/pages/list-page.ts, frontend/e2e/pages/modal-page.ts, frontend/e2e/pages/secret-page.ts
Extended BasePage with tour dismissal; added ListPage (filter/rows/kebab helpers), ModalPage (modal interactions), and SecretPage (comprehensive secret CRUD, upload, workload wiring, helpers).
Fixtures and storage mocks
frontend/e2e/fixtures/secrets/*, frontend/e2e/mocks/storage.ts
Added ASCII and UTF-8 secret fixtures; new storage mock with Deployment, PVCs, VolumeSnapshotClass, JSON patch, provisionersMap, and getVACFixtures.
Secret CRUD Playwright tests
frontend/e2e/tests/console/crud/secrets/*
Added suites: add-to-workload, image-pull (credentials/config-file/obfuscation), key/value (binary/ASCII/Unicode/TLS), source (basic/SSH), webhook (create/regenerate/delete) with API verifications.
Storage Playwright tests
frontend/e2e/tests/console/storage/*
Added clone (PVC clone with optional storage-class), create-storage-class (provisioner parameter types), snapshot (create/restore), and volume-attributes-class (VAC lifecycle/modify/error handling) suites.
Removed legacy integration tests and mocks
frontend/packages/integration-tests/...
Deleted Cypress tests, old mocks, and view helpers previously under integration-tests; functionality moved to frontend/e2e Playwright suites and mocks.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • openshift/console#16454: Extends KubernetesClient with additional Secret and pod-related helper methods in parallel migration work.

Suggested labels

approved, lgtm, tide/merge-method-squash, component/shared, component/core, verified

Suggested reviewers

  • spadgett
  • logonoff
🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: migrating 5 Cypress secret test files to Playwright, directly reflected in the comprehensive changeset.
Description check ✅ Passed The description comprehensively covers analysis, solution details, test validation, browser conformance, and references the Jira issue, addressing all required template sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed PR uses Playwright tests (not Ginkgo); no Ginkgo test declarations found. All 17 test titles are static, descriptive strings without dynamic values.
Test Structure And Quality ✅ Passed Custom check requests Ginkgo test code review, but PR contains only Playwright e2e tests. Check is not applicable to non-Ginkgo test frameworks.
Microshift Test Compatibility ✅ Passed Custom check targets Ginkgo e2e tests; PR adds only Playwright tests (TypeScript/JavaScript frontend UI tests). No Ginkgo tests present, check not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed PR adds Playwright TypeScript e2e UI tests, not Ginkgo tests. SNO check applies only to Ginkgo e2e tests; these browser automation tests are not subject to multi-node assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed PR adds E2E test code (Playwright tests, page objects, fixtures) only. No deployment manifests, operators, or controllers with scheduling constraints are introduced.
Ote Binary Stdout Contract ✅ Passed PR contains no Go code; OTE Binary Stdout Contract check applies only to Go test binaries. All 26 modified files are TypeScript/JavaScript frontend tests (Playwright, Cypress).
Ipv6 And Disconnected Network Test Compatibility ✅ Passed This PR contains no Ginkgo e2e tests; it only adds Playwright TypeScript tests. The custom check applies only to Ginkgo tests, so it is not applicable.
No-Weak-Crypto ✅ Passed PR uses only Base64 encoding in test code. No weak crypto algorithms (MD5, SHA1, DES, RC4, etc.) or custom implementations detected. No production authentication code present.
Container-Privileges ✅ Passed No privileged containers, hostPID/hostNetwork/hostIPC, SYS_ADMIN capabilities, or allowPrivilegeEscalation configurations found in any K8s manifests or container specs across all PR changes.
No-Sensitive-Data-In-Logs ✅ Passed No logging of passwords, tokens, API keys, PII, session IDs, or sensitive data found in new test code, page objects, or kubernetes client methods.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@openshift-ci openshift-ci Bot requested review from TheRealJon and cajieh June 1, 2026 12:18
@openshift-ci openshift-ci Bot added the kind/cypress Related to Cypress e2e integration testing label Jun 1, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Jun 1, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Cragsmann
Once this PR has been reviewed and has the lgtm label, please assign spadgett for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Jun 1, 2026

@Cragsmann: 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/analyze ca19bef link true /test analyze
ci/prow/okd-scos-images ca19bef link true /test okd-scos-images
ci/prow/e2e-gcp-console ca19bef link true /test e2e-gcp-console
ci/prow/backend ca19bef link true /test backend
ci/prow/e2e-playwright ca19bef link false /test e2e-playwright
ci/prow/frontend ca19bef link true /test frontend
ci/prow/images ca19bef link true /test images

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.

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (7)
frontend/e2e/tests/console/storage/snapshot.spec.ts (1)

34-36: ⚡ Quick win

Improve error handling for VolumeSnapshotClass conflict detection.

The error handling uses string matching (String(e).includes('409')) to detect HTTP 409 Conflict responses. This is brittle because:

  • It will match "409" in any error message, not just status codes
  • Different client libraries may format errors differently

Consider checking for a structured error property instead.

♻️ Suggested improvement
 .catch((e) => {
-  if (!String(e).includes('409')) throw e;
+  if (e?.response?.statusCode !== 409 && e?.statusCode !== 409) throw e;
 });

Note: Adjust the property path based on the actual error structure returned by k8sClient.createClusterCustomResource().

Also applies to: 137-139

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/console/storage/snapshot.spec.ts` around lines 34 - 36,
Replace brittle string matching in the catch blocks that handle
VolumeSnapshotClass creation by checking a structured status/code property on
the thrown error (e.g., e.status, e.statusCode, e.response?.statusCode or
e.code) instead of String(e).includes('409'); specifically update the catch
after k8sClient.createClusterCustomResource() calls to test for a 409 numeric
status via optional chaining (and only swallow the error for 409), otherwise
rethrow the error so non-conflict failures propagate.
frontend/e2e/tests/console/storage/create-storage-class.spec.ts (1)

66-72: ⚡ Quick win

Consider adding cleanup fallback for cluster-scoped StorageClass resources.

The test deletes the StorageClass via UI action (lines 66-72), but if this fails, the cluster-scoped resource will be left behind and may interfere with subsequent test runs. Consider adding a cleanup step that uses k8sClient.deleteClusterCustomResource().catch(() => {}) after the UI deletion to ensure resources are cleaned up even if the UI flow fails.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/console/storage/create-storage-class.spec.ts` around lines
66 - 72, The UI deletion step may fail and leave the cluster-scoped StorageClass
behind; after the existing test.step that clicks the actions menu, triggers
'[data-test-action="Delete StorageClass"]' and uses
modal.shouldBeOpened()/submit()/shouldBeClosed(), add a fallback cleanup call to
k8sClient.deleteClusterCustomResource(...) (or the appropriate
deleteClusterCustomResource helper used in tests) and swallow errors with
.catch(() => {}) to ensure the StorageClass is removed if the UI flow fails;
place this fallback in a finally/after block following the modal interactions
and reference the same StorageClass identifier used by the test.
frontend/e2e/tests/console/storage/clone.spec.ts (1)

22-30: ⚡ Quick win

Consider using proper Kubernetes types instead of as any.

The as any type assertions bypass TypeScript's type checking. If the Kubernetes client methods accept specific resource types, consider defining or importing those types to improve type safety and catch potential errors at compile time.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/console/storage/clone.spec.ts` around lines 22 - 30, The
calls to k8sClient.createPVC and k8sClient.createDeployment use unsafe "as any"
casts; replace those with the proper Kubernetes resource types (e.g.,
V1PersistentVolumeClaim for PVC/PVCGP3 and V1Deployment for testerDeployment or
the specific types your k8sClient expects), import those types from
`@kubernetes/client-node` (or your k8s typings), and pass the objects typed
accordingly (ensure metadata.namespace is typed as string on the resource
metadata); update the calls to k8sClient.createPVC(ns, pvcObject) and
k8sClient.createDeployment(ns, deploymentObject) using the correct types instead
of "as any".
frontend/e2e/tests/console/storage/volume-attributes-class.spec.ts (1)

62-62: 💤 Low value

Consider using ListPage.navigateTo() for consistency.

This test uses page.goto() directly, while other storage tests in this cohort use listPage.navigateTo() (e.g., clone.spec.ts line 34, snapshot.spec.ts line 40). Using the page object method provides consistency and centralizes navigation logic.

♻️ Proposed fix
-    await page.goto(`/k8s/ns/${ns}/persistentvolumeclaims/~new/form`);
+    const listPage = new ListPage(page);
+    await listPage.navigateTo(`/k8s/ns/${ns}/persistentvolumeclaims/~new/form`);

However, note that ListPage is not instantiated above line 62, so you would need to add:

+    const listPage = new ListPage(page);
     const modal = new ModalPage(page);

Based on learnings: Page object patterns centralize navigation methods in base classes to provide consistent navigation behavior across test suites.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/console/storage/volume-attributes-class.spec.ts` at line
62, Replace the direct page.goto call with the page-object navigation method:
create/instantiate a ListPage (e.g., const listPage = new ListPage(page)) before
the navigation and call
listPage.navigateTo(`/k8s/ns/${ns}/persistentvolumeclaims/~new/form`) instead of
page.goto; also add the necessary import for ListPage at the top of the test
file so navigation logic is centralized and consistent with other storage tests
using ListPage.navigateTo().
frontend/e2e/tests/console/crud/secrets/add-to-workload.spec.ts (1)

19-43: ⚡ Quick win

Extract the duplicated Deployment/Secret setup into a shared helper or fixture.

The Deployment manifest (lines 19-37) and Secret manifest (lines 38-43) are duplicated verbatim in the second test (lines 74-98). A small factory (or a fixture under e2e/fixtures/) parameterized by name/namespace would remove the duplication and keep the two tests focused on their workload-attachment behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/console/crud/secrets/add-to-workload.spec.ts` around lines
19 - 43, Extract the duplicated Deployment/Secret creation into a reusable
helper (e.g., a factory function) and call it from both specs: create a helper
that accepts parameters (namespace, deployName, secretName) and internally calls
k8sClient.createDeployment and k8sClient.createSecret with the same manifests
currently inline, then replace the two verbatim blocks with a call to that
helper; reference the existing symbols k8sClient.createDeployment,
k8sClient.createSecret, deployName and secretName when implementing and invoking
the fixture so tests only assert workload-attachment behavior.
frontend/e2e/tests/console/crud/secrets/image-pull.spec.ts (1)

24-32: 💤 Low value

Assert the credential form count before iterating.

If the create-image-secret-form selector ever changes and count is 0, the loop silently fills nothing and the failure only surfaces later as a confusing dockerconfig assertion. A quick expect(count).toBe(2) (the two entries created by add-credentials-button) fails fast with a clear message.

🛡️ Suggested guard
       const forms = page.locator('[data-test-id="create-image-secret-form"]');
       const count = await forms.count();
+      expect(count).toBe(2);
       for (let i = 0; i < count; i++) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/console/crud/secrets/image-pull.spec.ts` around lines 24 -
32, Before iterating the forms locator, add a precondition assertion to fail
fast when no credential forms are present: call an assertion like
expect(count).toBe(2) (or the expected number created by the
add-credentials-button) right after computing count so the test fails with a
clear message if the '[data-test-id="create-image-secret-form"]' selector
returns 0 or an unexpected number; this change should be made near the code
using the forms locator and the count variable in the image-pull.spec.ts test.
frontend/e2e/tests/console/crud/secrets/key-value.spec.ts (1)

54-114: ⚡ Quick win

Consider a table-driven test for the ASCII and Unicode file secrets.

The creates an ascii file secret (54-83) and creates a unicode file secret (85-114) tests are structurally identical apart from the fixture filename and content. Parameterizing over a { name, fixture } table would remove the duplication and make adding further encodings trivial.

As per coding guidelines: "Tests should follow a table-driven testing convention similar to Go where applicable".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/console/crud/secrets/key-value.spec.ts` around lines 54 -
114, Combine the two nearly identical tests into a single table-driven test that
iterates over cases (e.g., [{name: 'ascii', fixture: 'asciisecret.txt'}, {name:
'unicode', fixture: 'unicodesecret.utf8'}]); for each case create a unique
namespace and secretName, read fixture content (like unicodeContent/asciiContent
currently), perform the same steps using SecretPage methods
(clickCreateSecretDropdownButton, fillName, page.getByTestId('secret-key').fill,
secretPage.uploadFile, expect file-input-textarea, expect
file-input-binary-alert hidden, secretPage.save) and then verify via
k8sClient.getSecret and Buffer.from(...).toString('utf-8'); ensure you preserve
cleanup.trackNamespace(ns) and use the case-specific fixture filename and
expected content when asserting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/e2e/mocks/storage.ts`:
- Around line 172-185: VAC_LOW_IOPS and VAC_HIGH_IOPS in the storage mocks use
identical parameters so tests that switch a PVC between them don't exercise a
parameter change; update the VAC_HIGH_IOPS mock (symbol: VAC_HIGH_IOPS) to use
distinctly higher IOPS/throughput values than VAC_LOW_IOPS (e.g., increase the
iops and throughput parameters and keep type 'gp3') so assertions comparing
before/after VAC changes actually detect a difference.
- Around line 1-33: The testerDeployment uses volumeDevices (block device) but
the PVC fixture lacks spec.volumeMode and defaults to Filesystem; update the PVC
fixture to include spec.volumeMode: 'Block' so it matches testerDeployment, or
alternatively change testerDeployment to use volumeMounts if a filesystem volume
was intended; locate the PVC fixture used by the tests and add spec.volumeMode:
'Block' (or switch volumeDevices -> volumeMounts in testerDeployment) to keep
volumeMode and mount type consistent.

In `@frontend/e2e/pages/modal-page.ts`:
- Around line 19-21: The method submitShouldBeEnabled currently only waits for
visibility on this.submitButton; change it to assert enabled state by importing
expect from '`@playwright/test`' and use expect(this.submitButton).toBeEnabled()
(optionally after waiting for visible) inside submitShouldBeEnabled so a
visible-but-disabled button fails the test. Ensure you update imports to include
expect and keep the waitFor call if needed for timing.

In `@frontend/e2e/tests/console/storage/create-storage-class.spec.ts`:
- Line 78: The function signature for fillParameter uses an inline type import
import('`@playwright/test`').Page; replace that with a top-level type-only
import—add "import type { Page } from '`@playwright/test`'" at the top of the file
and update the fillParameter signature to use Page (i.e., fillParameter(page:
Page, parameter: Parameter)): Promise<void>; keep Parameter as-is if it's a
runtime type or also use import type if it's a type-only import.

---

Nitpick comments:
In `@frontend/e2e/tests/console/crud/secrets/add-to-workload.spec.ts`:
- Around line 19-43: Extract the duplicated Deployment/Secret creation into a
reusable helper (e.g., a factory function) and call it from both specs: create a
helper that accepts parameters (namespace, deployName, secretName) and
internally calls k8sClient.createDeployment and k8sClient.createSecret with the
same manifests currently inline, then replace the two verbatim blocks with a
call to that helper; reference the existing symbols k8sClient.createDeployment,
k8sClient.createSecret, deployName and secretName when implementing and invoking
the fixture so tests only assert workload-attachment behavior.

In `@frontend/e2e/tests/console/crud/secrets/image-pull.spec.ts`:
- Around line 24-32: Before iterating the forms locator, add a precondition
assertion to fail fast when no credential forms are present: call an assertion
like expect(count).toBe(2) (or the expected number created by the
add-credentials-button) right after computing count so the test fails with a
clear message if the '[data-test-id="create-image-secret-form"]' selector
returns 0 or an unexpected number; this change should be made near the code
using the forms locator and the count variable in the image-pull.spec.ts test.

In `@frontend/e2e/tests/console/crud/secrets/key-value.spec.ts`:
- Around line 54-114: Combine the two nearly identical tests into a single
table-driven test that iterates over cases (e.g., [{name: 'ascii', fixture:
'asciisecret.txt'}, {name: 'unicode', fixture: 'unicodesecret.utf8'}]); for each
case create a unique namespace and secretName, read fixture content (like
unicodeContent/asciiContent currently), perform the same steps using SecretPage
methods (clickCreateSecretDropdownButton, fillName,
page.getByTestId('secret-key').fill, secretPage.uploadFile, expect
file-input-textarea, expect file-input-binary-alert hidden, secretPage.save) and
then verify via k8sClient.getSecret and Buffer.from(...).toString('utf-8');
ensure you preserve cleanup.trackNamespace(ns) and use the case-specific fixture
filename and expected content when asserting.

In `@frontend/e2e/tests/console/storage/clone.spec.ts`:
- Around line 22-30: The calls to k8sClient.createPVC and
k8sClient.createDeployment use unsafe "as any" casts; replace those with the
proper Kubernetes resource types (e.g., V1PersistentVolumeClaim for PVC/PVCGP3
and V1Deployment for testerDeployment or the specific types your k8sClient
expects), import those types from `@kubernetes/client-node` (or your k8s typings),
and pass the objects typed accordingly (ensure metadata.namespace is typed as
string on the resource metadata); update the calls to k8sClient.createPVC(ns,
pvcObject) and k8sClient.createDeployment(ns, deploymentObject) using the
correct types instead of "as any".

In `@frontend/e2e/tests/console/storage/create-storage-class.spec.ts`:
- Around line 66-72: The UI deletion step may fail and leave the cluster-scoped
StorageClass behind; after the existing test.step that clicks the actions menu,
triggers '[data-test-action="Delete StorageClass"]' and uses
modal.shouldBeOpened()/submit()/shouldBeClosed(), add a fallback cleanup call to
k8sClient.deleteClusterCustomResource(...) (or the appropriate
deleteClusterCustomResource helper used in tests) and swallow errors with
.catch(() => {}) to ensure the StorageClass is removed if the UI flow fails;
place this fallback in a finally/after block following the modal interactions
and reference the same StorageClass identifier used by the test.

In `@frontend/e2e/tests/console/storage/snapshot.spec.ts`:
- Around line 34-36: Replace brittle string matching in the catch blocks that
handle VolumeSnapshotClass creation by checking a structured status/code
property on the thrown error (e.g., e.status, e.statusCode,
e.response?.statusCode or e.code) instead of String(e).includes('409');
specifically update the catch after k8sClient.createClusterCustomResource()
calls to test for a 409 numeric status via optional chaining (and only swallow
the error for 409), otherwise rethrow the error so non-conflict failures
propagate.

In `@frontend/e2e/tests/console/storage/volume-attributes-class.spec.ts`:
- Line 62: Replace the direct page.goto call with the page-object navigation
method: create/instantiate a ListPage (e.g., const listPage = new
ListPage(page)) before the navigation and call
listPage.navigateTo(`/k8s/ns/${ns}/persistentvolumeclaims/~new/form`) instead of
page.goto; also add the necessary import for ListPage at the top of the test
file so navigation logic is centralized and consistent with other storage tests
using ListPage.navigateTo().
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 07944aa3-94ac-4d21-82f8-b3805af13633

📥 Commits

Reviewing files that changed from the base of the PR and between 377ea54 and ca19bef.

⛔ Files ignored due to path filters (1)
  • frontend/e2e/fixtures/secrets/binarysecret.bin is excluded by !**/*.bin
📒 Files selected for processing (26)
  • frontend/e2e/clients/kubernetes-client.ts
  • frontend/e2e/fixtures/secrets/asciisecret.txt
  • frontend/e2e/fixtures/secrets/unicodesecret.utf8
  • frontend/e2e/mocks/storage.ts
  • frontend/e2e/pages/base-page.ts
  • frontend/e2e/pages/list-page.ts
  • frontend/e2e/pages/modal-page.ts
  • frontend/e2e/pages/secret-page.ts
  • frontend/e2e/tests/console/crud/secrets/add-to-workload.spec.ts
  • frontend/e2e/tests/console/crud/secrets/image-pull.spec.ts
  • frontend/e2e/tests/console/crud/secrets/key-value.spec.ts
  • frontend/e2e/tests/console/crud/secrets/source.spec.ts
  • frontend/e2e/tests/console/crud/secrets/webhook.spec.ts
  • frontend/e2e/tests/console/storage/clone.spec.ts
  • frontend/e2e/tests/console/storage/create-storage-class.spec.ts
  • frontend/e2e/tests/console/storage/snapshot.spec.ts
  • frontend/e2e/tests/console/storage/volume-attributes-class.spec.ts
  • frontend/packages/integration-tests/mocks/snapshot.ts
  • frontend/packages/integration-tests/mocks/storage-class.ts
  • frontend/packages/integration-tests/mocks/volume-attributes-class.ts
  • frontend/packages/integration-tests/tests/storage/clone.cy.ts
  • frontend/packages/integration-tests/tests/storage/create-storage-class.cy.ts
  • frontend/packages/integration-tests/tests/storage/snapshot.cy.ts
  • frontend/packages/integration-tests/tests/storage/volume-attributes-class.cy.ts
  • frontend/packages/integration-tests/views/storage/create-storage-class.ts
  • frontend/packages/integration-tests/views/storage/snapshot.ts
💤 Files with no reviewable changes (9)
  • frontend/packages/integration-tests/tests/storage/create-storage-class.cy.ts
  • frontend/packages/integration-tests/views/storage/create-storage-class.ts
  • frontend/packages/integration-tests/tests/storage/clone.cy.ts
  • frontend/packages/integration-tests/views/storage/snapshot.ts
  • frontend/packages/integration-tests/mocks/volume-attributes-class.ts
  • frontend/packages/integration-tests/tests/storage/volume-attributes-class.cy.ts
  • frontend/packages/integration-tests/mocks/snapshot.ts
  • frontend/packages/integration-tests/mocks/storage-class.ts
  • frontend/packages/integration-tests/tests/storage/snapshot.cy.ts

Comment on lines +1 to +33
export const testerDeployment = {
apiVersion: 'apps/v1',
kind: 'Deployment',
metadata: {
name: 'busybox-deployment',
labels: { app: 'busybox' },
},
spec: {
replicas: 1,
strategy: { type: 'RollingUpdate' },
selector: { matchLabels: { app: 'busybox' } },
template: {
metadata: { labels: { app: 'busybox' } },
spec: {
volumes: [
{
name: 'testpvc',
persistentVolumeClaim: { claimName: 'testpvc' },
},
],
containers: [
{
name: 'busybox',
image: 'busybox',
imagePullPolicy: 'IfNotPresent',
volumeDevices: [{ name: 'testpvc', devicePath: '/data' }],
command: ['sh', '-c', 'echo Container 1 is Running ; sleep 3600'],
},
],
},
},
},
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP 'testerDeployment|volumeMode|volumeDevices' --type=ts -C2

Repository: openshift/console

Length of output: 28032


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the PVC fixture in the referenced mock file
nl -ba frontend/e2e/mocks/storage.ts | sed -n '1,120p'

# Check whether other e2e storage mocks/tests set Block volumeMode
rg -n "volumeMode:\s*['\"]Block['\"]|volumeMode:\s*Block|spec:\s*\{[^}]*volumeMode" frontend/e2e -S

Repository: openshift/console

Length of output: 104


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== frontend/e2e/mocks/storage.ts (first 120 lines) =="
cat -n frontend/e2e/mocks/storage.ts | sed -n '1,120p'

echo
echo "== volumeMode occurrences in e2e mocks/tests (storage) =="
rg -n "volumeMode\s*:\s*['\"]?Block['\"]?|volumeMode\s*:\s*['\"]?Filesystem['\"]?|volumeDevices|devicePath" frontend/e2e -S

Repository: openshift/console

Length of output: 4874


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== volumeDevices usage in e2e storage tests =="
rg -n "volumeDevices|devicePath" frontend/e2e/tests/console/storage -S

echo
echo "== volumeMode usage in e2e storage tests =="
rg -n "volumeMode\s*:\s*['\"]?(Block|Filesystem)['\"]?" frontend/e2e/tests/console/storage -S

echo
echo "== volumeMode usage in e2e mocks (broader, but limited to e2e folder) =="
rg -n "volumeMode\s*:\s*['\"]?(Block|Filesystem)['\"]?" frontend/e2e/mocks -S

Repository: openshift/console

Length of output: 108


🏁 Script executed:

#!/bin/bash
set -uo pipefail

echo "== volumeDevices usage in e2e storage tests =="
rg -n "volumeDevices|devicePath" frontend/e2e/tests/console/storage -S || true

echo
echo "== volumeMode usage in e2e storage tests =="
rg -n "volumeMode\s*:\s*['\"]?(Block|Filesystem)['\"]?" frontend/e2e/tests/console/storage -S || true

echo
echo "== volumeMode usage in e2e mocks (limited to e2e) =="
rg -n "volumeMode\s*:\s*['\"]?(Block|Filesystem)['\"]?" frontend/e2e/mocks -S || true

Repository: openshift/console

Length of output: 207


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show where testerDeployment/PVC are used in the storage e2e tests
rg -n "testerDeployment|createDeployment\(|createPVC\(|\bPVC\b" frontend/e2e/tests/console/storage -S

echo
echo "== snapshot.spec.ts (relevant sections) =="
sed -n '1,260p' frontend/e2e/tests/console/storage/snapshot.spec.ts

echo
echo "== clone.spec.ts (relevant sections) =="
sed -n '1,220p' frontend/e2e/tests/console/storage/clone.spec.ts

Repository: openshift/console

Length of output: 18799


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== testerDeployment usage across e2e =="
rg -n "testerDeployment" frontend/e2e -S

Repository: openshift/console

Length of output: 1402


Align PVC spec.volumeMode with testerDeployment’s volumeDevices usage.
In frontend/e2e/mocks/storage.ts, testerDeployment mounts testpvc via volumeDevices (block-mode), but the PVC fixture omits spec.volumeMode (defaults to Filesystem). This mismatch can prevent the Deployment pod from scheduling/attaching even though the clone/snapshot tests only wait for the PVC to become Bound. Set PVC.spec.volumeMode: 'Block' for this test (or switch testerDeployment to volumeMounts if the intent is filesystem).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/mocks/storage.ts` around lines 1 - 33, The testerDeployment uses
volumeDevices (block device) but the PVC fixture lacks spec.volumeMode and
defaults to Filesystem; update the PVC fixture to include spec.volumeMode:
'Block' so it matches testerDeployment, or alternatively change testerDeployment
to use volumeMounts if a filesystem volume was intended; locate the PVC fixture
used by the tests and add spec.volumeMode: 'Block' (or switch volumeDevices ->
volumeMounts in testerDeployment) to keep volumeMode and mount type consistent.

Comment on lines +172 to +185
VAC_LOW_IOPS: {
apiVersion: 'storage.k8s.io/v1',
kind: 'VolumeAttributesClass',
metadata: { name: names.TEST_VAC_LOW_IOPS },
driverName: 'ebs.csi.aws.com',
parameters: { iops: '3000', throughput: '125', type: 'gp3' },
},
VAC_HIGH_IOPS: {
apiVersion: 'storage.k8s.io/v1',
kind: 'VolumeAttributesClass',
metadata: { name: names.TEST_VAC_HIGH_IOPS },
driverName: 'ebs.csi.aws.com',
parameters: { iops: '3000', throughput: '125', type: 'gp3' },
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

VAC_LOW_IOPS and VAC_HIGH_IOPS have identical parameters.

Both define iops: '3000', throughput: '125', type: 'gp3'. Any test that modifies a PVC from the low to the high VAC won't actually exercise a parameter change, so the assertion becomes a no-op. Differentiate the high-IOPS values.

Proposed fix
     VAC_HIGH_IOPS: {
       apiVersion: 'storage.k8s.io/v1',
       kind: 'VolumeAttributesClass',
       metadata: { name: names.TEST_VAC_HIGH_IOPS },
       driverName: 'ebs.csi.aws.com',
-      parameters: { iops: '3000', throughput: '125', type: 'gp3' },
+      parameters: { iops: '6000', throughput: '250', type: 'gp3' },
     },
📝 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.

Suggested change
VAC_LOW_IOPS: {
apiVersion: 'storage.k8s.io/v1',
kind: 'VolumeAttributesClass',
metadata: { name: names.TEST_VAC_LOW_IOPS },
driverName: 'ebs.csi.aws.com',
parameters: { iops: '3000', throughput: '125', type: 'gp3' },
},
VAC_HIGH_IOPS: {
apiVersion: 'storage.k8s.io/v1',
kind: 'VolumeAttributesClass',
metadata: { name: names.TEST_VAC_HIGH_IOPS },
driverName: 'ebs.csi.aws.com',
parameters: { iops: '3000', throughput: '125', type: 'gp3' },
},
VAC_LOW_IOPS: {
apiVersion: 'storage.k8s.io/v1',
kind: 'VolumeAttributesClass',
metadata: { name: names.TEST_VAC_LOW_IOPS },
driverName: 'ebs.csi.aws.com',
parameters: { iops: '3000', throughput: '125', type: 'gp3' },
},
VAC_HIGH_IOPS: {
apiVersion: 'storage.k8s.io/v1',
kind: 'VolumeAttributesClass',
metadata: { name: names.TEST_VAC_HIGH_IOPS },
driverName: 'ebs.csi.aws.com',
parameters: { iops: '6000', throughput: '250', type: 'gp3' },
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/mocks/storage.ts` around lines 172 - 185, VAC_LOW_IOPS and
VAC_HIGH_IOPS in the storage mocks use identical parameters so tests that switch
a PVC between them don't exercise a parameter change; update the VAC_HIGH_IOPS
mock (symbol: VAC_HIGH_IOPS) to use distinctly higher IOPS/throughput values
than VAC_LOW_IOPS (e.g., increase the iops and throughput parameters and keep
type 'gp3') so assertions comparing before/after VAC changes actually detect a
difference.

Comment on lines +19 to +21
async submitShouldBeEnabled(): Promise<void> {
await this.submitButton.waitFor({ state: 'visible', timeout: 10_000 });
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

submitShouldBeEnabled checks visibility, not enablement.

The name promises an enabled-state assertion but it only waits for the button to be visible; a visible-but-disabled submit would pass and hide a real regression.

Proposed fix
-  async submitShouldBeEnabled(): Promise<void> {
-    await this.submitButton.waitFor({ state: 'visible', timeout: 10_000 });
-  }
+  async submitShouldBeEnabled(): Promise<void> {
+    await this.submitButton.waitFor({ state: 'visible', timeout: 10_000 });
+    await expect(this.submitButton).toBeEnabled();
+  }

Requires importing expect from @playwright/test.

📝 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.

Suggested change
async submitShouldBeEnabled(): Promise<void> {
await this.submitButton.waitFor({ state: 'visible', timeout: 10_000 });
}
async submitShouldBeEnabled(): Promise<void> {
await this.submitButton.waitFor({ state: 'visible', timeout: 10_000 });
await expect(this.submitButton).toBeEnabled();
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/pages/modal-page.ts` around lines 19 - 21, The method
submitShouldBeEnabled currently only waits for visibility on this.submitButton;
change it to assert enabled state by importing expect from '`@playwright/test`'
and use expect(this.submitButton).toBeEnabled() (optionally after waiting for
visible) inside submitShouldBeEnabled so a visible-but-disabled button fails the
test. Ensure you update imports to include expect and keep the waitFor call if
needed for timing.

},
);

async function fillParameter(page: import('@playwright/test').Page, parameter: Parameter): Promise<void> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use import type syntax for type-only imports.

The inline type import import('@playwright/test').Page should be moved to the top-level imports using the import type syntax for better clarity and to follow TypeScript best practices.

♻️ Proposed fix

At the top of the file:

+import type { Page } from '`@playwright/test`';
 import kebabCase from 'lodash/kebabCase.js';
 import { test, expect } from '../../../fixtures';

Then update the function signature:

-async function fillParameter(page: import('`@playwright/test`').Page, parameter: Parameter): Promise<void> {
+async function fillParameter(page: Page, parameter: Parameter): Promise<void> {

As per coding guidelines: "Use import type syntax for type-only imports"

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/e2e/tests/console/storage/create-storage-class.spec.ts` at line 78,
The function signature for fillParameter uses an inline type import
import('`@playwright/test`').Page; replace that with a top-level type-only
import—add "import type { Page } from '`@playwright/test`'" at the top of the file
and update the fillParameter signature to use Page (i.e., fillParameter(page:
Page, parameter: Parameter)): Promise<void>; keep Parameter as-is if it's a
runtime type or also use import type if it's a type-only import.

Resolve conflict in kubernetes-client.ts by keeping both our
createSecret/getSecret methods and upstream's patchSecret method.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. kind/cypress Related to Cypress e2e integration testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants