Skip to content

OCPNETUI-56: Add Cypress test specs and runner scripts - #470

Open
lkladnit wants to merge 3 commits into
openshift:mainfrom
lkladnit:lkladnit/cypress-tests
Open

OCPNETUI-56: Add Cypress test specs and runner scripts#470
lkladnit wants to merge 3 commits into
openshift:mainfrom
lkladnit:lkladnit/cypress-tests

Conversation

@lkladnit

@lkladnit lkladnit commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Add E2E test specs for all networking resources:

  • NADs: bridge, localnet, OVN topologies
  • Network policies, routes, services, ingresses
  • User-defined networks (UDN + ClusterUDN)
  • Login and page navigation verification

Add test runner infrastructure:

  • setup.sh / cleanup.sh for test namespace lifecycle
  • test-cypress.sh with GUI (-g) and headless modes
  • research-flakiness.sh for repeated execution analysis
  • e2e.yml GitHub Actions workflow for CI
  • Migration and planning docs

PR 3 of 3 in the Cypress E2E series (1a: infra, 1b: views, 1c: tests).
Depends on #468 and #469.

Jira: OCPNETUI-56

Test plan

  • npm run test-e2e runs Cypress tests from ui-tests-cy/
  • ./test-cypress.sh executes setup, tests, and cleanup
  • e2e.yml workflow triggers on PR and manual dispatch

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added end-to-end coverage for Networking pages, including NetworkAttachmentDefinitions, UserDefinedNetworks, Services, Routes, Ingresses, and NetworkPolicies.
    • Added tests for creating, validating, filtering, and deleting networking resources through the console.
    • Added OpenShift console login and page-navigation test coverage.
  • Testing

    • Added automated pull-request E2E execution with screenshots, reports, and failure artifacts.
    • Added scripts for test setup, cleanup, interactive runs, and flakiness analysis.
  • Documentation

    • Added testing migration plans and implementation details.

lkladnit and others added 2 commits August 12, 2026 10:39
Set up Cypress test infrastructure for networking plugin E2E tests:
- cypress.config.js with esbuild preprocessor, timeouts, reporter
- Support files: login commands, navigation helpers, selectors
- Plugin config with dotenv and webpack preprocessor
- ESLint, tsconfig, reporter config for the test suite
- .env.example with required environment variables
- Package deps: esbuild-loader, dotenv, cypress-multi-reporters
- Minor fixes in integration-tests/ login and example spec

Jira: OCPNETUI-56
Co-authored-by: Cursor <cursoragent@cursor.com>
Add view helpers and constants for networking E2E tests:
- Views: NAD form helpers, UDN form helpers, common selectors, actions
- Constants: base test values, NAD config constants
- Types: NAD type definitions

These are the page object layer used by test specs (next PR).

Jira: OCPNETUI-56
Co-authored-by: Cursor <cursoragent@cursor.com>
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Aug 12, 2026
@openshift-ci-robot

openshift-ci-robot commented Aug 12, 2026

Copy link
Copy Markdown

@lkladnit: This pull request references OCPNETUI-56 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:

Summary

Add E2E test specs for all networking resources:

  • NADs: bridge, localnet, OVN topologies
  • Network policies, routes, services, ingresses
  • User-defined networks (UDN + ClusterUDN)
  • Login and page navigation verification

Add test runner infrastructure:

  • setup.sh / cleanup.sh for test namespace lifecycle
  • test-cypress.sh with GUI (-g) and headless modes
  • research-flakiness.sh for repeated execution analysis
  • e2e.yml GitHub Actions workflow for CI
  • Migration and planning docs

PR 3 of 3 in the Cypress E2E series (1a: infra, 1b: views, 1c: tests).
Depends on #468 and #469.

Jira: OCPNETUI-56

Test plan

  • npm run test-e2e runs Cypress tests from ui-tests-cy/
  • ./test-cypress.sh executes setup, tests, and cleanup
  • e2e.yml workflow triggers on PR and manual dispatch

Made with Cursor

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.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro Plus

Run ID: eb2a6214-7739-4b28-9fbc-94cb4a681149

Walkthrough

The pull request migrates networking E2E coverage to Cypress. It adds shared test support, networking specs, OpenShift namespace lifecycle scripts, CI execution, report collection, flakiness research, and migration documentation.

Changes

Cypress E2E migration

Layer / File(s) Summary
Test architecture and runtime configuration
ui-tests-cy/PLAN.md, ui-tests-cy/MIGRATION.md, .env.example, package.json, ui-tests-cy/*config*, integration-tests/...
Defines the Cypress migration structure, environment settings, TypeScript and lint configuration, reporters, package commands, and updated environment access.
Cluster lifecycle and test execution
setup.sh, cleanup.sh, test-cypress.sh
Creates or reconciles test namespaces, runs Cypress in GUI or headless mode, captures results, and removes OpenShift networking resources.
Cypress support and reusable workflows
ui-tests-cy/support/*, ui-tests-cy/utils/*, ui-tests-cy/views/*
Adds authentication, navigation, selectors, resource commands, shared constants, NAD workflows, and UDN workflows.
Networking specs, CI execution, and flakiness evidence
ui-tests-cy/tests/*, .github/workflows/e2e.yml, research-flakiness.sh
Adds login, navigation, NAD, UDN, Service, Route, Ingress, and NetworkPolicy tests. The workflow runs the suite and uploads screenshots. The research script repeats runs and records failure evidence.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant test_cypress.sh
  participant setup.sh
  participant Cypress
  participant OpenShift
  participant cleanup.sh
  GitHubActions->>test_cypress.sh: run headless E2E tests
  test_cypress.sh->>setup.sh: prepare test namespaces
  setup.sh->>OpenShift: create or reconcile namespaces
  test_cypress.sh->>Cypress: execute networking specs
  Cypress->>OpenShift: create and inspect networking resources
  test_cypress.sh->>cleanup.sh: clean resources after success
  cleanup.sh->>OpenShift: delete test resources
Loading
🚥 Pre-merge checks | ✅ 15
✅ Passed checks (15 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 All added Cypress describe/it titles are literal, stable strings; dynamic namespaces and resource names appear only in test bodies, not titles.
Test Structure And Quality ✅ Passed The PR adds Cypress .cy.ts tests using describe/it and cy.*; the diff and dependencies contain no Ginkgo or Gomega test code, so this check is inapplicable.
Microshift Test Compatibility ✅ Passed The PR adds Cypress TypeScript specs (*.cy.ts) run by Cypress, not Ginkgo tests; the introduced code has no Ginkgo markers or listed MicroShift-incompatible OpenShift API references.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The PR adds Cypress .cy.ts specs, not Ginkgo tests. The changed specs and helpers contain no node-count, scheduling, failover, topology, or multi-endpoint assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed The PR diff adds only E2E workflow, scripts, tests, and documentation; it adds no deployment manifests, operator/controller code, or topology-related scheduling constraints.
Ote Binary Stdout Contract ✅ Passed The PR diff contains only shell, Cypress TypeScript, YAML, and documentation files; the repository has no Go, Ginkgo, or OTE binary entrypoints to emit invalid stdout.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The PR adds Cypress TypeScript specs (*.cy.ts) and no Go/Ginkgo files or Ginkgo declarations, so this Ginkgo-specific check is not applicable.
No-Weak-Crypto ✅ Passed The PR-range scan found no MD5, SHA1, DES, RC4, Blowfish, ECB, crypto APIs, custom crypto, or secret comparisons; login code only enters the password in the UI.
Container-Privileges ✅ Passed The PR diff adds no privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, allowPrivilegeEscalation, or root container/Kubernetes settings; the workflow uses a standard ubuntu-latest runner.
No-Sensitive-Data-In-Logs ✅ Passed No added log prints credentials; shell tracing does not expand the password, and Cypress sends it to the masked #inputPassword field. CI receives it from GitHub Secrets.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the Cypress test specifications and runner scripts, which are the main changes in the pull request.
✨ 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.

@openshift-ci

openshift-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: lkladnit

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

The pull request process is described 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 openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 16

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (7)
ui-tests-cy/support/commands.ts-38-44 (1)

38-44: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Re-query the filter after .clear().

Cypress marks chaining commands after .clear() as unsafe, even though .clear() yields the same subject. Split the chain before .type(projectName).

🤖 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 `@ui-tests-cy/support/commands.ts` around lines 38 - 44, Split the Cypress
command chain after .clear() in the filter interaction, then re-query the same
filter selector before calling .type(projectName). Preserve the existing
first-match selection, timeout, clearing behavior, and projectName input.

Source: Linters/SAST tools

ui-tests-cy/views/nad.ts-29-30 (1)

29-30: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Split each .clear().type() chain.

Start a new cy.get() before .type() for each affected input, including lines 29–30, 35–37, and 53–56. This prevents failures when the form replaces the input after .clear().

🤖 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 `@ui-tests-cy/views/nad.ts` around lines 29 - 30, Split each affected
clear-and-type chain in the NAD form test into separate Cypress commands: keep
cy.get(...).clear() and begin a new cy.get(...) before .type(). Apply this
consistently to the inputs in the indicated sections, including the fields using
name and description.

Source: Linters/SAST tools

ui-tests-cy/utils/types/nad.ts-2-10 (1)

2-10: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reorder the NadData fields alphabetically: bridge, description, exclude, macSpoof, mtu, name, subnet, type, vlan. The perfectionist/sort-object-types rule reports five errors.

🤖 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 `@ui-tests-cy/utils/types/nad.ts` around lines 2 - 10, Reorder the fields in
the NadData type alphabetically as bridge, description, exclude, macSpoof, mtu,
name, subnet, type, vlan to satisfy the perfectionist/sort-object-types rule.

Source: Linters/SAST tools

ui-tests-cy/tests/setup/visit-pages.cy.ts-3-35 (1)

3-35: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Add a login setup to visit-pages.cy.ts. support/index.ts has no setup hook, and login.cy.ts is a separate spec. testIsolation: false does not share state across specs, so direct runs can execute cy.clickNavLink without a console page.

🤖 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 `@ui-tests-cy/tests/setup/visit-pages.cy.ts` around lines 3 - 35, Add a
login/setup hook within the “Visit networking pages” spec in visit-pages.cy.ts,
using the existing login helper or flow from login.cy.ts so direct runs
establish a console page before any cy.clickNavLink calls. Do not rely on
support/index.ts or state shared by another spec; ensure the setup runs before
the networking page tests.
package.json-16-23 (1)

16-23: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Reorder script keys to pass the repository lint check.

The static analysis report requires lint before ts-node, cypress-generate before cypress-merge, and cypress-merge before test-e2e-open. Reorder the keys without changing command behavior.

The static analysis hint reports these perfectionist/sort-objects errors.

🤖 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 `@package.json` around lines 16 - 23, Reorder the package scripts to satisfy
the repository’s object-sorting rules: place lint before ts-node,
cypress-generate before cypress-merge, and cypress-merge before test-e2e-open.
Keep every script command unchanged.

Source: Linters/SAST tools

ui-tests-cy/MIGRATION.md-17-17 (1)

17-17: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the plan path in the migration log.

Line 17 references ui/PLAN.md, but the added file is ui-tests-cy/PLAN.md. Update the entry so readers can locate the plan.

Proposed fix
-- Plan saved to `ui/PLAN.md`
+- Plan saved to `ui-tests-cy/PLAN.md`

The reviewed files establish ui-tests-cy/PLAN.md as the plan location.

🤖 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 `@ui-tests-cy/MIGRATION.md` at line 17, Update the plan reference in the
migration log to point to ui-tests-cy/PLAN.md instead of ui/PLAN.md, matching
the location of the added plan file.
.env.example-5-5 (1)

5-5: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Parse HIDE_XHR as a boolean before passing it to Cypress.

dotenv provides "false" as a string. The truthiness check in ui-tests-cy/support/index.ts:10 therefore remains enabled. Convert "true" and "false" to booleans, or document that only true is supported.

🤖 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 @.env.example at line 5, Update the HIDE_XHR configuration handling used by
Cypress support initialization so the dotenv string "false" becomes boolean
false rather than a truthy value. Parse both "true" and "false" explicitly
before passing the setting to Cypress, while preserving the existing behavior
for enabled HIDE_XHR.
🧹 Nitpick comments (1)
ui-tests-cy/utils/types/nad.ts (1)

1-11: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Define NadData as a discriminated union for createNAD.

NadData currently allows {} and arbitrary type values. createNAD always passes name and description to .type(). The Bridge and Localnet branches also require bridge, and the Localnet branch requires mtu. An unsupported or missing type skips every switch case and still submits. Require the common and branch-specific fields. Constrain type to 'Bridge' | 'OVN' | 'Localnet'. Keep subnet and exclude optional as a pair because NAD_LOCALNET omits both.

🤖 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 `@ui-tests-cy/utils/types/nad.ts` around lines 1 - 11, Redefine NadData as a
discriminated union keyed by type, requiring name and description in every
variant, restricting type to 'Bridge' | 'OVN' | 'Localnet', and requiring bridge
for Bridge and Localnet plus mtu for Localnet. Keep subnet and exclude optional
together so the NAD_LOCALNET variant can omit them, and remove the permissive
empty/object and arbitrary-type cases.
🤖 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 @.github/workflows/e2e.yml:
- Line 27: Update the GitHub Actions references for checkout, setup-node, and
upload-artifact to use their full immutable commit SHAs instead of version tags,
while retaining an adjacent comment identifying each action’s version.
- Around line 12-27: Update the e2e job configuration to add an explicit
permissions block granting only contents: read, and configure the Checkout step
to set persist-credentials to false. Keep the existing checkout action and job
behavior unchanged.
- Around line 29-33: Update the Node.js version configured in the “Setup
Node.js” workflow step to a Cypress 15-supported version, such as 20.1.0, 22, or
24+, while preserving the existing npm cache configuration.

In `@cleanup.sh`:
- Line 20: Update the cleanup command to delete only the test-owned
NodeNetworkConfigurationPolicy resource, using its specific name or a dedicated
test label selector instead of the --all flag. Preserve the existing
ignore-not-found and non-blocking wait behavior.

In `@package.json`:
- Around line 18-20: Make test-e2e the canonical headless runner for the
migrated Cypress suite by aligning the relevant package.json scripts, then
update ui-tests-cy/PLAN.md:174 to invoke that same command; ensure all affected
sites use the migrated cypress suite rather than integration-tests.
- Around line 16-17: Use ui-tests-cy as the single Cypress project root: update
package.json lines 16-17 to lint ui-tests-cy, package.json lines 20-21 to run
Cypress commands from ui-tests-cy, and revise the architecture paths in
ui-tests-cy/PLAN.md lines 74-105 plus the final file tree in lines 194-233 to
match the checked-in root.
- Line 64: Update the dotenv dependency declaration in package.json from the
caret range to the exact version 17.4.2, preserving the lockfile’s resolved
version and metadata.

In `@test-cypress.sh`:
- Around line 3-4: Preserve failure propagation across the test runner: in
test-cypress.sh lines 3-4, keep errexit enabled except for the Cypress pipeline
that needs captured exit codes, then run post-reporting and exit with
test_exit_code at lines 30-37; update setup.sh lines 13-42 to return nonzero
when any required namespace operation fails; update cleanup.sh lines 12-21 to
return nonzero for cleanup failures other than missing resources.
- Around line 25-30: Update the Cypress invocation in both the interactive and
headless branches of test-cypress.sh to target the configured ui-tests-cy
project, including artifact creation and the working directory or project
argument. Ensure Cypress uses ui-tests-cy’s cypress.config.js, test patterns,
support file, and artifact paths in both modes.

In `@ui-tests-cy/cypress.config.js`:
- Around line 3-18: Fix asynchronous Cypress environment access across
ui-tests-cy/cypress.config.js lines 3-18, integration-tests/support/login.ts
lines 11-27, and integration-tests/tests/example-page.cy.ts line 4: configure
PLUGIN_TEMPLATE_PULL_SPEC under Cypress expose (or pass it with --expose) so
Cypress.expose() returns its value; in the login flow, resolve
cy.env('BRIDGE_KUBEADMIN_PASSWORD') inside .then(...) before using it or
deriving loginUsername. Update the cited example-page site only as needed to
consume the configured exposed value.

In `@ui-tests-cy/support/commands.ts`:
- Around line 14-22: Update both cy.exec calls in the resource deletion command
to remove failOnNonZeroExit: false, while retaining --ignore-not-found=true and
the existing timeout settings so genuine authentication, API, and deletion
failures fail the test.

In `@ui-tests-cy/support/index.ts`:
- Around line 6-8: Remove the global uncaught:exception handler registered via
Cypress.on, or narrow it to return false only for a documented exact known error
while allowing all other application exceptions to fail the UI tests.

In `@ui-tests-cy/support/login.ts`:
- Line 43: Update the cy.type call for originPwd in the login flow to pass the
option that disables command logging, ensuring the password does not appear in
Cypress’s Command Log while preserving the existing password entry behavior.

In `@ui-tests-cy/tests/all.cy.ts`:
- Around line 1-10: Restrict Cypress spec discovery so the aggregator all.cy.ts
does not execute alongside its imported leaf specs. Update the Cypress
specPattern/configuration to target tests/all.cy.ts only, or remove the
all.cy.ts aggregator while preserving direct leaf-spec execution; ensure each
test runs exactly once without --spec.

In `@ui-tests-cy/tests/networking/nad-localnet.cy.ts`:
- Around line 10-13: Make the it('delete NAD') test self-contained by creating
NAD_LOCALNET within the test before calling deleteNAD. Preserve the existing
deletion target and ensure the test no longer relies on state from preceding
tests or test execution order.

In `@ui-tests-cy/tests/networking/routes.cy.ts`:
- Around line 8-11: Update the service setup around the cy.exec call to fail
closed: validate TEST_NS, stop interpolating it into a shell command, and pass
it as an argument to a Node task that performs the oc lookup/creation. Remove
the || fallback and failOnNonZeroExit: false so authentication, API, lookup, and
creation errors propagate instead of being treated as a missing service.

---

Minor comments:
In @.env.example:
- Line 5: Update the HIDE_XHR configuration handling used by Cypress support
initialization so the dotenv string "false" becomes boolean false rather than a
truthy value. Parse both "true" and "false" explicitly before passing the
setting to Cypress, while preserving the existing behavior for enabled HIDE_XHR.

In `@package.json`:
- Around line 16-23: Reorder the package scripts to satisfy the repository’s
object-sorting rules: place lint before ts-node, cypress-generate before
cypress-merge, and cypress-merge before test-e2e-open. Keep every script command
unchanged.

In `@ui-tests-cy/MIGRATION.md`:
- Line 17: Update the plan reference in the migration log to point to
ui-tests-cy/PLAN.md instead of ui/PLAN.md, matching the location of the added
plan file.

In `@ui-tests-cy/support/commands.ts`:
- Around line 38-44: Split the Cypress command chain after .clear() in the
filter interaction, then re-query the same filter selector before calling
.type(projectName). Preserve the existing first-match selection, timeout,
clearing behavior, and projectName input.

In `@ui-tests-cy/tests/setup/visit-pages.cy.ts`:
- Around line 3-35: Add a login/setup hook within the “Visit networking pages”
spec in visit-pages.cy.ts, using the existing login helper or flow from
login.cy.ts so direct runs establish a console page before any cy.clickNavLink
calls. Do not rely on support/index.ts or state shared by another spec; ensure
the setup runs before the networking page tests.

In `@ui-tests-cy/utils/types/nad.ts`:
- Around line 2-10: Reorder the fields in the NadData type alphabetically as
bridge, description, exclude, macSpoof, mtu, name, subnet, type, vlan to satisfy
the perfectionist/sort-object-types rule.

In `@ui-tests-cy/views/nad.ts`:
- Around line 29-30: Split each affected clear-and-type chain in the NAD form
test into separate Cypress commands: keep cy.get(...).clear() and begin a new
cy.get(...) before .type(). Apply this consistently to the inputs in the
indicated sections, including the fields using name and description.

---

Nitpick comments:
In `@ui-tests-cy/utils/types/nad.ts`:
- Around line 1-11: Redefine NadData as a discriminated union keyed by type,
requiring name and description in every variant, restricting type to 'Bridge' |
'OVN' | 'Localnet', and requiring bridge for Bridge and Localnet plus mtu for
Localnet. Keep subnet and exclude optional together so the NAD_LOCALNET variant
can omit them, and remove the permissive empty/object and arbitrary-type cases.
🪄 Autofix

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: Pro Plus

Run ID: 82e1a448-2a7e-40e8-b370-29474c6989fd

📥 Commits

Reviewing files that changed from the base of the PR and between 3378840 and 7b83d74.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (40)
  • .env.example
  • .github/workflows/e2e.yml
  • .gitignore
  • cleanup.sh
  • integration-tests/support/login.ts
  • integration-tests/tests/example-page.cy.ts
  • package.json
  • research-flakiness.sh
  • setup.sh
  • test-cypress.sh
  • ui-tests-cy/.eslintrc
  • ui-tests-cy/MIGRATION.md
  • ui-tests-cy/PLAN.md
  • ui-tests-cy/cypress.config.js
  • ui-tests-cy/plugins/index.ts
  • ui-tests-cy/reporter-config.json
  • ui-tests-cy/support/commands.ts
  • ui-tests-cy/support/index.ts
  • ui-tests-cy/support/login.ts
  • ui-tests-cy/support/nav.ts
  • ui-tests-cy/support/selectors.ts
  • ui-tests-cy/tests/all.cy.ts
  • ui-tests-cy/tests/networking/ingresses.cy.ts
  • ui-tests-cy/tests/networking/nad-bridge.cy.ts
  • ui-tests-cy/tests/networking/nad-localnet.cy.ts
  • ui-tests-cy/tests/networking/nad-ovn.cy.ts
  • ui-tests-cy/tests/networking/net-policies.cy.ts
  • ui-tests-cy/tests/networking/routes.cy.ts
  • ui-tests-cy/tests/networking/services.cy.ts
  • ui-tests-cy/tests/networking/udn.cy.ts
  • ui-tests-cy/tests/setup/login.cy.ts
  • ui-tests-cy/tests/setup/visit-pages.cy.ts
  • ui-tests-cy/tsconfig.json
  • ui-tests-cy/utils/const/base.ts
  • ui-tests-cy/utils/const/nad.ts
  • ui-tests-cy/utils/types/nad.ts
  • ui-tests-cy/views/actions.ts
  • ui-tests-cy/views/nad.ts
  • ui-tests-cy/views/selector-common.ts
  • ui-tests-cy/views/udn.ts

Comment thread .github/workflows/e2e.yml
Comment thread .github/workflows/e2e.yml

steps:
- name: Checkout
uses: actions/checkout@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Pin every GitHub Action to a full commit SHA.

actions/checkout@v4, actions/setup-node@v4, and actions/upload-artifact@v4 use mutable tags. Replace each tag with a full commit SHA and retain an adjacent version comment.

As per path instructions, “Pin actions by full SHA, not tag.”

Also applies to: 30-30, 43-43

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 26-27: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 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 @.github/workflows/e2e.yml at line 27, Update the GitHub Actions references
for checkout, setup-node, and upload-artifact to use their full immutable commit
SHAs instead of version tags, while retaining an adjacent comment identifying
each action’s version.

Source: Path instructions

Comment thread .github/workflows/e2e.yml
Comment thread cleanup.sh Outdated
Comment thread package.json Outdated
Comment on lines +16 to +17
"lint": "eslint ./src ./integration-tests ./cypress",
"lint-fix": "eslint ./src ./integration-tests ./cypress --fix",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use one Cypress project-root path.

The supplied runtime configuration is under ui-tests-cy/, but the package scripts and plan document cypress/. Align the commands and documentation before merge.

  • package.json#L16-L17: lint ui-tests-cy instead of ./cypress.
  • package.json#L20-L21: run the Cypress commands from ui-tests-cy.
  • ui-tests-cy/PLAN.md#L74-L105: update the architecture paths to the checked-in project root.
  • ui-tests-cy/PLAN.md#L194-L233: update the final file tree to the checked-in project root.

The supplied review context identifies ui-tests-cy as the new Cypress project root.

🧰 Tools
🪛 ESLint

[error] 16-16: Expected "lint" to come before "ts-node"

(perfectionist/sort-objects)

📍 Affects 2 files
  • package.json#L16-L17 (this comment)
  • package.json#L20-L21
  • ui-tests-cy/PLAN.md#L74-L105
  • ui-tests-cy/PLAN.md#L194-L233
🤖 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 `@package.json` around lines 16 - 17, Use ui-tests-cy as the single Cypress
project root: update package.json lines 16-17 to lint ui-tests-cy, package.json
lines 20-21 to run Cypress commands from ui-tests-cy, and revise the
architecture paths in ui-tests-cy/PLAN.md lines 74-105 plus the final file tree
in lines 194-233 to match the checked-in root.

Comment thread ui-tests-cy/support/index.ts Outdated
Comment thread ui-tests-cy/support/login.ts Outdated
Comment thread ui-tests-cy/tests/all.cy.ts
Comment on lines +10 to +13
it('delete NAD', () => {
cy.visitNAD();
deleteNAD(NAD_LOCALNET.name);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
file=$(git ls-files | rg '(^|/)ui-tests-cy/tests/networking/nad-localnet\.cy\.ts$' | head -n1)
printf '%s\n' "FILE=$file"
test -n "$file"
wc -l "$file"
cat -n "$file"
printf '%s\n' '--- related NAD symbols and hooks ---'
rg -n --glob '*.{ts,js}' 'NAD_LOCALNET|createNAD|deleteNAD|visitNAD|beforeEach|afterEach' ui-tests-cy

Repository: openshift/networking-console-plugin

Length of output: 1988


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- NAD view helpers ---'
cat -n ui-tests-cy/views/nad.ts
printf '%s\n' '--- NAD fixture ---'
cat -n ui-tests-cy/utils/const/nad.ts
printf '%s\n' '--- suite wrapper and navigation ---'
cat -n ui-tests-cy/utils/const/base.ts
cat -n ui-tests-cy/support/nav.ts
printf '%s\n' '--- Cypress configuration and test scripts ---'
rg -n --glob 'package.json' --glob '*config*' --glob '*.ts' 'testIsolation|experimentalSessionAndOrigin|cypress run|ui-tests-cy' .

Repository: openshift/networking-console-plugin

Length of output: 6883


🏁 Script executed:

#!/bin/bash
set -e
python3 - <<'PY'
from pathlib import Path
import re

test = Path("ui-tests-cy/tests/networking/nad-localnet.cy.ts").read_text()
config = Path("ui-tests-cy/cypress.config.js").read_text()

create_tests = re.findall(r"\bit\(\s*(['\"])(.*?)\1\s*,\s*\(\)\s*=>\s*\{(.*?)\n\s*\}\s*\)", test, re.S)
delete_body = next((body for _, title, body in create_tests if title == "delete NAD"), None)

print("delete_test_found:", delete_body is not None)
print("delete_test_calls_createNAD:", bool(delete_body and re.search(r"\bcreateNAD\s*\(", delete_body)))
print("delete_test_calls_deleteNAD:", bool(delete_body and re.search(r"\bdeleteNAD\s*\(", delete_body)))
print("testIsolation_false:", bool(re.search(r"\btestIsolation\s*:\s*false\b", config)))
print("create_and_delete_are_separate_tests:", len([title for _, title, _ in create_tests if "NAD" in title]) >= 2)
PY

Repository: openshift/networking-console-plugin

Length of output: 335


Make the delete test independent.

it('delete NAD') does not create NAD_LOCALNET. With testIsolation: false, it depends on the preceding test and fails when run alone or after creation fails. Combine creation and deletion, or create the NAD within the delete test.

🤖 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 `@ui-tests-cy/tests/networking/nad-localnet.cy.ts` around lines 10 - 13, Make
the it('delete NAD') test self-contained by creating NAD_LOCALNET within the
test before calling deleteNAD. Preserve the existing deletion target and ensure
the test no longer relies on state from preceding tests or test execution order.

Comment on lines +8 to +11
cy.exec(
`oc get service ${EXAMPLE} -n ${TEST_NS} 2>/dev/null || oc create service clusterip ${EXAMPLE} --tcp=80:80 -n ${TEST_NS}`,
{ failOnNonZeroExit: false },
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- target file ---'
cat -n ui-tests-cy/tests/networking/routes.cy.ts
printf '%s\n' '--- related Cypress and oc.exec usages ---'
rg -n --glob '!node_modules' --glob '!dist' --glob '!build' \
  'Cypress\.env|cy\.exec|oc get service|clusterip|TEST_NS|EXAMPLE' \
  ui-tests-cy
printf '%s\n' '--- repository files near Cypress configuration ---'
git ls-files ui-tests-cy | sed -n '1,160p'

Repository: openshift/networking-console-plugin

Length of output: 6158


🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- Cypress configuration and plugin setup ---'
cat -n ui-tests-cy/cypress.config.js
cat -n ui-tests-cy/plugins/index.ts
printf '%s\n' '--- command helpers ---'
cat -n ui-tests-cy/support/commands.ts
printf '%s\n' '--- namespace and test constants ---'
cat -n ui-tests-cy/utils/const/base.ts
printf '%s\n' '--- package versions and test scripts ---'
rg -n --glob 'package.json' --glob 'package-lock.json' --glob 'yarn.lock' \
  '"cypress"|"test:e2e"|"ui-tests-cy"' .
printf '%s\n' '--- all Cypress exec call sites ---'
rg -n -A5 -B3 --glob '*.ts' --glob '*.js' 'cy\.exec\(' ui-tests-cy

Repository: openshift/networking-console-plugin

Length of output: 7125


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
import subprocess

template = (
    "oc get service {example} -n {namespace} 2>/dev/null || "
    "oc create service clusterip {example} --tcp=80:80 -n {namespace}"
)
for namespace in ("cy-test-ns", "safe; printf INJECTED"):
    command = template.format(example="example", namespace=namespace)
    # Use a harmless command prefix to demonstrate shell parsing without invoking
    # `oc` or any repository code.
    probe = command.replace("oc ", "printf OC_ >/dev/null; ", 2)
    result = subprocess.run(
        ["/bin/sh", "-c", probe],
        text=True,
        capture_output=True,
        check=False,
    )
    print(f"namespace={namespace!r}")
    print(f"command={command!r}")
    print(f"returncode={result.returncode}")
    print(f"stdout={result.stdout!r}")
    print(f"stderr={result.stderr!r}")
PY

Repository: openshift/networking-console-plugin

Length of output: 713


🌐 Web query:

Cypress 15 cy.exec failOnNonZeroExit false documentation command shell behavior

💡 Result:

In Cypress, the cy.exec command is used to execute system commands [1]. The option failOnNonZeroExit, which defaults to true, determines whether the Cypress test fails if the executed command returns a non-zero exit code [1][2]. When you set failOnNonZeroExit: false, Cypress will not automatically fail the test if the command exits with a non-zero code [1][2]. Instead, the command promise will resolve, and you can inspect the result object—which includes the exitCode, stdout, and stderr—to perform your own assertions [1][2]. Example usage: cy.exec('your-command', { failOnNonZeroExit: false }).then((result) => { expect(result.exitCode).to.eq(1); expect(result.stderr).to.contain('expected error message'); }); Regarding command shell behavior: Cypress executes commands via a child process. Historically and in current implementations, cy.exec relies on the underlying shell to interpret commands [3]. On Windows, this behavior can be environment-dependent; if the system shell (such as cmd.exe or a shell defined by environment variables) is not explicitly handled or available, commands requiring shell features—like pipes (|), redirections (>), or environment variable expansion—may fail if they are executed without a shell context [4][3]. Cypress generally attempts to resolve a suitable shell for execution, but complexities can arise depending on the host operating system and available shell environments [4][3]. Note that cy.exec requires the command to eventually exit; commands that do not exit (e.g., long-running servers) will timeout and cause the test to fail [1][5][2].

Citations:


Make service setup fail closed.

Do not suppress oc errors or set failOnNonZeroExit: false. The || treats authentication and API errors as “service missing,” then Cypress continues if creation also fails. Validate TEST_NS and pass it as an argument to a Node task instead of interpolating it into the shell command. The current interpolation permits shell command injection.

🧰 Tools
🪛 OpenGrep (1.26.0)

[ERROR] 8-11: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🤖 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 `@ui-tests-cy/tests/networking/routes.cy.ts` around lines 8 - 11, Update the
service setup around the cy.exec call to fail closed: validate TEST_NS, stop
interpolating it into a shell command, and pass it as an argument to a Node task
that performs the oc lookup/creation. Remove the || fallback and
failOnNonZeroExit: false so authentication, API, lookup, and creation errors
propagate instead of being treated as a missing service.

@lkladnit
lkladnit force-pushed the lkladnit/cypress-tests branch 2 times, most recently from ac9fd8b to 406078e Compare August 13, 2026 09:45
@lkladnit lkladnit changed the title OCPNETUI-56: Add Cypress test specs and runner scripts WIP: OCPNETUI-56: Add Cypress test specs and runner scripts Aug 13, 2026
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 13, 2026
@lkladnit
lkladnit force-pushed the lkladnit/cypress-tests branch 2 times, most recently from 9bc19ab to 696798c Compare August 13, 2026 11:34
@lkladnit
lkladnit force-pushed the lkladnit/cypress-tests branch from 696798c to 79921b9 Compare August 13, 2026 12:47
@lkladnit lkladnit changed the title WIP: OCPNETUI-56: Add Cypress test specs and runner scripts OCPNETUI-56: Add Cypress test specs and runner scripts Aug 13, 2026
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 13, 2026
@pcbailey pcbailey added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 13, 2026
@lkladnit lkladnit removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 17, 2026
Add E2E test specs for all networking resources:
- NADs: bridge, localnet, OVN topologies
- Network policies, routes, services, ingresses
- User-defined networks (UDN + ClusterUDN)
- Login and page navigation verification

Add test runner infrastructure:
- setup.sh / cleanup.sh for test namespace lifecycle
- test-cypress.sh with GUI (-g) and headless modes
- research-flakiness.sh for repeated execution analysis
- e2e.yml GitHub Actions workflow for CI
- Migration and planning docs

Depends on: cypress-infra (1a) + cypress-views (1b)

Jira: OCPNETUI-56
Co-authored-by: Cursor <cursoragent@cursor.com>
@lkladnit
lkladnit force-pushed the lkladnit/cypress-tests branch from 79921b9 to a1e0829 Compare August 18, 2026 08:10
@openshift-ci

openshift-ci Bot commented Aug 18, 2026

Copy link
Copy Markdown

@lkladnit: all tests passed!

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.

@rszwajko
rszwajko self-requested a review August 18, 2026 11:23
Comment thread .github/workflows/e2e.yml

steps:
- name: Checkout
uses: actions/checkout@v4

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.

it may be a follow-up but we should update all the actions - the current is v7

Comment thread .github/workflows/e2e.yml
cache: npm

- name: Install dependencies
run: npm ci

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.

in this install path we rely on post-install scripts which is insecure.
Alternative way is to disable post-install and install cypress explicitly:

npm clean-install --ignore-scripts --no-audit
npx cypress install

}
});
cy.get(
'input[data-test="dropdown-text-filter"], input[placeholder*="name"], input[aria-label*="filter"]',

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.

note that most likely we are using data test IDs not compatible with PatternFly.
check my comment for a similar PR for kubevirt plugin.

Comment thread .github/workflows/e2e.yml
timeout-minutes: 30

env:
BRIDGE_BASE_ADDRESS: ${{ secrets.CONSOLE_URL }}

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.

the tests seem to be run via dev mode - in case of networking plugin it may be easier to build an image and update the env var in cluster network operator.

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.

for hot cluster it makes sense. however still we should be using a cluster network operator compatible with our plugin. Do we have some way of checking that?

@rszwajko
rszwajko requested a review from sjd78 August 19, 2026 14:16
Comment thread .github/workflows/e2e.yml
timeout-minutes: 30

env:
BRIDGE_BASE_ADDRESS: ${{ secrets.CONSOLE_URL }}

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.

for hot cluster it makes sense. however still we should be using a cluster network operator compatible with our plugin. Do we have some way of checking that?

Comment thread .github/workflows/e2e.yml

env:
BRIDGE_BASE_ADDRESS: ${{ secrets.CONSOLE_URL }}
BRIDGE_KUBEADMIN_PASSWORD: ${{ secrets.KUBEADMIN_PASSWORD }}

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.

this should not be needed.
CC: @sjd78

Comment thread .github/workflows/e2e.yml
BRIDGE_BASE_ADDRESS: ${{ secrets.CONSOLE_URL }}
BRIDGE_KUBEADMIN_PASSWORD: ${{ secrets.KUBEADMIN_PASSWORD }}
BRIDGE_E2E_BROWSER_NAME: electron
TEST_NS: ${{ secrets.TEST_NS || 'cy-test-ns' }}

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.

why we use secrets to store a namspace name?

Comment thread .github/workflows/e2e.yml
runs-on: ubuntu-latest
timeout-minutes: 30

env:

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.

HIDE_XHR needs to be set to true for public env

args.push('-n', namespace);
}
args.push(kind, name, '--wait=true', '--timeout=300s');
cy.exec(args.join(' '), { failOnNonZeroExit: false, timeout: 5 * MINUTE });

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.

exec is deprecated and unsafe - we should switch to task

}

Cypress.Commands.add('deleteResource', (kind: string, name: string, namespace?: string) => {
const args = ['oc', 'delete', '--ignore-not-found=true'];

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.

not sure if oc is available on that env - maybe we should use JS client as the kubevirt plugin?

Comment thread .gitignore
integration-tests/.DS_Store
yarn-error.log
.DS_Store
cypress/gui-test-screenshots/

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.

the path cypress does not exist

screenshotOnRunFailure: true,
screenshotsFolder: './gui-test-screenshots/screenshots/',
trashAssetsBeforeRuns: true,
video: true,

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.

do we need video?

Comment thread .github/workflows/e2e.yml
run: npm run test-e2e

- name: Upload test artifacts
if: always()

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.

maybe it's enough to upload screenshots on failure?

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants