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.
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.
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.
| 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.
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) |
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
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
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
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
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
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
| 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.
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-configshared package with custom hook testing utilities@odh-dashboard/internal/__mocks__centralized mock factory package- Well-established patterns across other packages
Many Cypress tests use mock factories from cypress/support/ that mirror the structures in src/__mocks__/. When converting:
- Check if an equivalent mock factory already exists in
src/__mocks__/ - If not, create one there (not in the test file) so it's reusable
- The Cypress mock data (e.g.,
mockModelVersion({...})) typically maps 1:1
- E2e tests — these test real cluster integration and should remain
- Tests asserting URL query parameters — Cypress's
cy.interceptURL inspection is hard to replicate - Tests using
cy.go('back')— JSDOM doesn't have real browser history - Tests verifying
sessionStorage/localStoragepersistence across page loads — RTL doesn't simulate page loads - Archive/restore multi-page flows — the value is in the cross-page state transitions
- 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