Skip to content

Instantly share code, notes, and snippets.

@mturley
Last active April 14, 2026 15:27
Show Gist options
  • Select an option

  • Save mturley/347e8174fd97cbe479f1c209ba3df575 to your computer and use it in GitHub Desktop.

Select an option

Save mturley/347e8174fd97cbe479f1c209ba3df575 to your computer and use it in GitHub Desktop.

Green Scrum: Cypress Mock Test Conversion Report

Prompt

This report is the output from this prompt:

Look at the cypress mock tests (not the e2e tests) in the upstream model-registry repo and the ones in odh-dashboard related to the model registry, model catalog and MCP catalog features (green scrum's areas). We have a lot of very heavy cypress tests that take forever to run and are flaky. Think hard and analyze which tests would be better off being rewritten as unit tests or component tests (using jest, react-testing-library, etc) and which ones benefit from being cypress tests. A lot of them are just testing local UI functionality and not really integration across the app, and those may be more efficient and reliable without the overhead of cypress. Make a plan prioritized in multiple phases, starting with low hanging fruit and progressing with a balance of effort and benefit. The plan should be broken down into PRs that are each focused and small enough to be reviewed by a human, we want to avoid large bloated PRs. Write up your findings in a report at /tmp/green-cypress-mock-conversion-report.md.

It is up to date as of April 14, 2026.

Executive Summary

The green scrum areas (Model Registry, Model Catalog, MCP Catalog) have ~470 Cypress mock tests across 26 test files spanning two repos: the upstream kubeflow/model-registry (synced to odh-dashboard/packages/model-registry/upstream/) and ODH Dashboard's own mock tests. Many of these tests exercise isolated UI behavior (form validation, rendering conditions, modal logic, empty states) that would be faster, more reliable, and cheaper to run as Jest + React Testing Library tests.

Key finding: ~40% of mock tests (~190 tests across 12 files) are strong candidates for conversion. These tests don't use Cypress's strengths (routing, browser history, cross-page state) and would benefit from the faster feedback loop and deterministic execution of Jest/RTL.

Existing infrastructure is ready: Both repos already have Jest + RTL configured, mock data factories in __mocks__/ directories, and established patterns. The upstream repo has only 3 unit test files today — there's massive room for growth with minimal setup cost.


Scope

This report covers mock/mocked Cypress tests only — not e2e tests that run against live clusters. The e2e tests serve a fundamentally different purpose (validating real K8s resources, RBAC, database operations) and should remain as-is.

Repos and Test Locations

Repo Test Location Mock Test Files Approx Tests
Upstream (kubeflow/model-registry) clients/ui/frontend/src/__tests__/cypress/cypress/tests/mocked/ 22 files ~470
ODH Dashboard packages/cypress/cypress/tests/mocked/ 4 files ~31

The upstream tests are synced to odh-dashboard/packages/model-registry/upstream/ and run as part of the ODH Dashboard CI. Changes should be made in the upstream repo first.


Assessment Criteria

Tests were evaluated on these dimensions:

Factor Favors Jest/RTL Favors Cypress
Routing No route changes Multi-page navigation, browser back
State scope Single component/page Cross-page state sync
API interaction Rendering mock data Asserting request params/URLs
User interaction Clicks, typing, toggles Drag-and-drop, complex gestures
DOM scope Component-level rendering Full page with header/sidebar/breadcrumb
Flakiness risk Low (synchronous JSDOM) Higher (async browser automation)

File-by-File Assessment

Tier 1: Strong Conversion Candidates (High confidence, low effort)

These tests exercise isolated component behavior with no routing or cross-page state.

# File Tests What It Tests Why Convert
1 modelRegistry/modelDetailsCard.cy.ts 8 Card rendering, expand/collapse, property CRUD, form validation Pure component logic. Validation rules, expand/collapse state, PATCH body assertions all work better in RTL.
2 modelRegistry/modelTransferJobs.cy.ts 16 Transfer jobs table, status labels, modals, error/empty states Isolated table + modal component. No routing. Status label rendering and modal open/close are trivial in RTL.
3 modelRegistry/modelRegistrySettings.cy.ts 7 Settings page, create/delete modals, form validation Form validation (name confirmation for delete), modal logic. No multi-page flow.
4 modelRegistry/modelVersionsCard.cy.ts 6 Versions card, empty states, link rendering Conditional rendering based on data. No actual navigation tested.
5 modelCatalog/modelCatalogAllModelsView.cy.ts 6 Category sections, "show more", empty/error states Pure rendering logic. Category grouping and empty states are ideal for RTL.
6 modelCatalog/tensorTypeComparisonCard.cy.ts 23 Variant comparison card, edge cases, loading/error states Isolated card component. 23 tests for rendering conditions — perfect RTL target.
7 modelCatalog/modelCatalogCard.cy.ts 21 Card rendering with toggle-driven content, metrics display Toggle ON/OFF rendering, metric formatting. No routing needed.
8 mcpCatalog/mcpCatalog.cy.ts 5 Catalog landing page, card display, empty/error states Page rendering, description truncation. Minimal interaction.
9 mocked/mcpCatalog/mcpCatalogFeatureFlag.cy.ts (ODH) 3 Feature flag gating (nav item show/hide, 404) Config-driven rendering. Simple RTL with mocked config.
10 mocked/mcpCatalog/mcpDeploymentsDelete.cy.ts (ODH) 3 Delete confirmation modal, cancel, error state Modal interaction pattern — well-suited for RTL.

Subtotal: 10 files, ~98 tests

Tier 2: Partial Conversion Candidates (Split recommended)

These files contain a mix of component-level tests (convertible) and integration-level tests (keep in Cypress). The recommendation is to extract the component-level tests into Jest and slim down the Cypress file.

# File Total Tests Convert Keep Split Rationale
11 modelRegistry/modelVersionDetails.cy.ts 52 ~30 ~22 Property CRUD, label validation, expand/collapse → Jest. Storage location flows with error retry, navigation → Cypress.
12 modelRegistry/registerAndStoreFields.cy.ts 31 ~15 ~16 Form validation, toggle logic, credential validation → Jest. Background polling, namespace access checks with navigation → Cypress.
13 modelRegistry/modelRegistry.cy.ts 25 ~12 ~13 Table rendering, sorting, filtering → Jest. Session storage persistence, registry selector across refreshes → Cypress.
14 modelCatalog/modelCatalog.cy.ts 31 ~10 ~21 Filter sidebar rendering, empty states → Jest. Performance toggle with URL state, cross-filter interactions → Cypress.
15 modelCatalog/modelCatalogTabs.cy.ts 33 ~15 ~18 Column visibility logic, ARIA attributes, conditional tab display → Jest. Tab state persistence, server-side filtering, pagination → Cypress.
16 modelCatalogSettings/modelCatalogSettings.cy.ts 53 ~25 ~28 Form field validation, source type switching, preview panel → Jest. Full CRUD flows, navigation, enable/disable toggle with API → Cypress.
17 mcpCatalog/mcpServerDetails.cy.ts 44 ~20 ~24 Tool rendering, parameter display, pagination → Jest. Tab navigation, breadcrumb, browser back → Cypress.
18 kubeflowStandalone/navBar.cy.ts 7 ~3 ~4 Username display, empty state → Jest. Namespace persistence across navigation → Cypress.
19 mocked/mcpCatalog/mcpDeployments.cy.ts (ODH) 12 ~6 ~6 Row rendering, status labels, empty/error states → Jest. Deploy modal with API, edit modal save → Cypress.
20 mocked/modelRegistry/registerAndStore.cy.ts (ODH) 13 ~7 ~6 Toggle behavior, access warnings, no-projects state → Jest. Project selection with access check API flow → Cypress.

Subtotal: 10 files, ~301 total tests → ~143 convertible, ~158 keep in Cypress

Tier 3: Keep in Cypress (Integration value is high)

These tests exercise multi-page flows, browser history, or cross-page state that genuinely benefit from Cypress.

# File Tests Why Keep
21 modelRegistry/modelVersionArchive.cy.ts 12 Multi-page archive/restore flows with breadcrumb navigation, browser back button.
22 modelRegistry/registeredModelArchive.cy.ts 18 Multi-page archive list → details → restore with state transitions and routing.
23 modelRegistry/modelVersions.cy.ts 4 Browser back button behavior, multi-page navigation between table and details.
24 modelCatalog/modelCatalogDetails.cy.ts 11 Cross-tab filter state persistence, cy.go('back') navigation state sync.
25 modelCatalog/modelCatalogPerformanceFiltersAlert.cy.ts 13 Cross-page state: filter changes on details page trigger alert on catalog page.
26 modelCatalog/modelCatalogPerformanceFiltersApi.cy.ts 24 Asserts actual API request URL parameters based on toggle/filter state.

Subtotal: 6 files, ~82 tests — all stay in Cypress


Phased Implementation Plan

Phase 1: Low-Hanging Fruit — Isolated Components (4 PRs)

These are the simplest conversions with the highest reliability gain. Each PR is focused on one component or closely related set of components.

PR 1.1: Model Details Card + Versions Card (upstream)

  • Convert modelDetailsCard.cy.ts (8 tests) → ModelDetailsCard.test.tsx
  • Convert modelVersionsCard.cy.ts (6 tests) → ModelVersionsCard.test.tsx
  • ~14 tests, tightly related components on the same page
  • Effort: Small — straightforward rendering + expand/collapse + form validation
  • Delete the Cypress files after conversion

PR 1.2: Transfer Jobs Table (upstream)

  • Convert modelTransferJobs.cy.ts (16 tests) → component tests
  • Status label rendering, modal open/close, error states, empty state
  • Effort: Small — isolated table component with modal
  • Delete the Cypress file after conversion

PR 1.3: Catalog Cards (upstream)

  • Convert modelCatalogCard.cy.ts (21 tests) → ModelCatalogCard.test.tsx
  • Convert tensorTypeComparisonCard.cy.ts (23 tests) → TensorTypeComparisonCard.test.tsx
  • Convert modelCatalogAllModelsView.cy.ts (6 tests) → AllModelsView.test.tsx
  • ~50 tests, all card/section rendering with conditional logic
  • Effort: Medium — more tests but all follow the same pattern
  • Delete the Cypress files after conversion

PR 1.4: Settings & Feature Flags (split: upstream + ODH)

  • Convert modelRegistrySettings.cy.ts (7 tests) → component tests (upstream)
  • Convert mcpCatalog.cy.ts (5 tests) → component tests (upstream)
  • Convert mcpCatalogFeatureFlag.cy.ts (3 tests) → component tests (ODH)
  • Convert mcpDeploymentsDelete.cy.ts (3 tests) → component tests (ODH)
  • ~18 tests across settings pages and feature flag gating
  • Effort: Small — modal logic, form validation, config-driven rendering
  • Delete the Cypress files after conversion

Phase 1 Total: ~98 tests converted, 10 Cypress files removed, 4 PRs


Phase 2: Extract Component Tests from Mixed Files (6 PRs)

Each PR takes one large Cypress file, extracts the component-level tests into Jest, and slims down the Cypress file to only integration tests.

PR 2.1: Model Version Details — Component Extraction (upstream)

  • Source: modelVersionDetails.cy.ts (52 tests)
  • Extract: Property CRUD, label editing/validation, expand/collapse, detail card rendering (~30 tests)
  • Keep in Cypress: Storage location flows, error retry, navigation (~22 tests)
  • Effort: Medium — need to identify component boundaries for test splitting

PR 2.2: Register & Store Fields — Form Validation Extraction (upstream)

  • Source: registerAndStoreFields.cy.ts (31 tests)
  • Extract: Form field validation, toggle logic, credential validation rules (~15 tests)
  • Keep in Cypress: Namespace access flow with polling, form submission with navigation (~16 tests)
  • Effort: Medium — form validation logic is well-isolated

PR 2.3: Model Registry Main Page — Table Tests Extraction (upstream)

  • Source: modelRegistry.cy.ts (25 tests)
  • Extract: Table rendering, sorting behavior, filtering, empty states (~12 tests)
  • Keep in Cypress: Session storage persistence, registry selector, register flow (~13 tests)
  • Effort: Medium

PR 2.4: Model Catalog Settings — Form Extraction (upstream)

  • Source: modelCatalogSettings.cy.ts (53 tests)
  • Extract: Form validation, source type switching, preview panel, model visibility (~25 tests)
  • Keep in Cypress: Full CRUD lifecycle, navigation, enable/disable toggle (~28 tests)
  • Effort: Medium-Large — largest file, many describe blocks to sort through

PR 2.5: MCP Server Details — Tool Rendering Extraction (upstream)

  • Source: mcpServerDetails.cy.ts (44 tests)
  • Extract: Tool display, parameter rendering, pagination, expandable details (~20 tests)
  • Keep in Cypress: Tab navigation, breadcrumb, browser back, error page routing (~24 tests)
  • Effort: Medium

PR 2.6: ODH-Specific Mock Tests — Component Extraction (ODH)

  • Sources: mcpDeployments.cy.ts (12 tests), registerAndStore.cy.ts (13 tests)
  • Extract: Row rendering, status labels, toggle behavior, warning states (~13 tests)
  • Keep in Cypress: Deploy/edit modals with API calls, project access check flow (~12 tests)
  • Effort: Small-Medium

Phase 2 Total: ~115 tests extracted to Jest, 6 Cypress files slimmed, 6 PRs


Phase 3: Catalog & Tab Tests (2 PRs)

These are the remaining partial-conversion files that require more careful analysis of state boundaries.

PR 3.1: Model Catalog Main Page — Filter Extraction (upstream)

  • Source: modelCatalog.cy.ts (31 tests)
  • Extract: Filter sidebar rendering, checkbox logic, empty states (~10 tests)
  • Keep in Cypress: Performance toggle with URL state, cross-filter interactions (~21 tests)
  • Effort: Medium — filter state management crosses component boundaries

PR 3.2: Model Catalog Tabs — Column & ARIA Extraction (upstream)

  • Source: modelCatalogTabs.cy.ts (33 tests)
  • Extract: Column visibility logic, ARIA attributes, conditional tab display (~15 tests)
  • Keep in Cypress: Tab state persistence, server-side filtering, pagination (~18 tests)
  • Effort: Medium — tab state management is complex

Phase 3 Total: ~25 tests extracted, 2 Cypress files slimmed, 2 PRs


Summary

Phase PRs Tests Converted Cypress Files Removed Cypress Files Slimmed
Phase 1 4 ~98 10 0
Phase 2 6 ~115 0 6
Phase 3 2 ~25 0 2
Total 12 ~238 10 8

After all phases: ~238 tests moved to Jest/RTL, 10 Cypress files deleted entirely, 8 Cypress files reduced in scope. The remaining ~232 Cypress mock tests are the ones that genuinely benefit from browser-level integration testing.


Implementation Notes

Test Infrastructure (Already Available)

Upstream repo (kubeflow/model-registry/clients/ui/frontend/):

  • Jest + RTL configured in jest.config.js
  • Mock data factories in src/__mocks__/ (e.g., mockModelVersion, mockRegisteredModel, mockCatalogModel)
  • Only 3 existing test files — patterns established but coverage is minimal
  • The Cypress mock data factories can often be reused directly in Jest tests

ODH Dashboard:

  • @odh-dashboard/jest-config shared package with custom hook testing utilities
  • @odh-dashboard/internal/__mocks__ centralized mock factory package
  • Well-established patterns across other packages

Mock Data Reuse

Many Cypress tests use mock factories from cypress/support/ that mirror the structures in src/__mocks__/. When converting:

  1. Check if an equivalent mock factory already exists in src/__mocks__/
  2. If not, create one there (not in the test file) so it's reusable
  3. The Cypress mock data (e.g., mockModelVersion({...})) typically maps 1:1

What NOT to Convert

  • E2e tests — these test real cluster integration and should remain
  • Tests asserting URL query parameters — Cypress's cy.intercept URL inspection is hard to replicate
  • Tests using cy.go('back') — JSDOM doesn't have real browser history
  • Tests verifying sessionStorage/localStorage persistence across page loads — RTL doesn't simulate page loads
  • Archive/restore multi-page flows — the value is in the cross-page state transitions

PR Hygiene

  • Each PR should add the Jest tests AND delete (or slim) the corresponding Cypress tests in the same PR
  • Include before/after CI timing data in PR description if available
  • Tag the PR with relevant area labels for reviewer routing
  • For upstream PRs: never reference RHOAIENG Jira issues
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment