Skip to content

test: Add unit tests for multiple frontend components across openchoreo, openchoreo-ci and openchoreo-observerbility plugins#489

Merged
LakshanSS merged 15 commits intoopenchoreo:mainfrom
stefinie123:testing
Apr 3, 2026
Merged

test: Add unit tests for multiple frontend components across openchoreo, openchoreo-ci and openchoreo-observerbility plugins#489
LakshanSS merged 15 commits intoopenchoreo:mainfrom
stefinie123:testing

Conversation

@stefinie123
Copy link
Copy Markdown
Contributor

@stefinie123 stefinie123 commented Apr 3, 2026

Purpose

Add unit tests for frontend components and improve code coverage

Approach

This pull request introduces comprehensive frontend testing utilities and adds unit tests for several OpenChoreo CI plugin components. It provides new helper functions for mocking Backstage entities and the OpenChoreo API client, and documents best practices for testing Backstage plugins. The main themes are improved testability and developer experience for frontend plugin development.

Frontend testing utilities and documentation:

  • Added TESTING_GUIDE.md with guidelines and best practices for testing frontend Backstage plugins, including when to use renderInTestApp, EntityProvider, and mocking strategies.
  • Introduced mockComponentEntity and mockSystemEntity helpers in entityFixtures.ts for creating minimal Backstage entities in tests.
  • Added createMockOpenChoreoClient utility to generate a fully mocked OpenChoreo API client for use in tests, with all methods stubbed as jest.fn().
  • Exported new helpers from packages/test-utils for easy import in test files. [1] [2]
  • Updated dependencies to include @backstage/catalog-model for entity typing and made @openchoreo/test-utils available to plugins. [1] [2]

New Test Files Added

Traces (4 files, 38 tests)

  • ObservabilityTracesPage (10) — permission loading/denied, filters/actions/table rendering, total count, loading state, error with Retry, observability disabled info, environments/components error handling
  • TracesFilters (7) — search trace ID field, components/environment/time range selectors, disabled state, loading skeletons
  • TracesActions (5) — total count display, last updated text, refresh button click, disabled state
  • TracesTable (7) — table headers, trace data rendering, empty state, loading behavior, truncated IDs, row expansion, span error display
  • utils (16) — parseRfc3339Nano, nanosecondsToRfc3339Nano, formatDuration, formatTime, formatTimeFromString, calculateTimeRange

Incidents (6 files, 52 tests)

  • ObservabilityProjectIncidentsPage (11) — permission loading/denied, filters/actions/table rendering, observability disabled info, error with Retry, no environments alert, components error
  • IncidentsFilter (8) — search input, components (conditional), status multi-select, environment, time range, disabled state, loading skeleton
  • IncidentsActions (7) — total count, last updated, sort toggle (Newest/Oldest), refresh, disabled state
  • IncidentsTable (5) — table headers, incident rows, empty state, loading skeletons, no empty state during loading
  • IncidentRow (14) — timestamp, truncated ID, status chips (ACTIVE/ACKNOWLEDGED/RESOLVED), description, component name, View RCA button visibility, expand/collapse details, notes, Acknowledge/Resolve buttons, missing field fallbacks

RCA Reports (4 files, 28 tests)

  • RCAPage (11) — permission loading/denied, filters/actions/table rendering, report count, loading state, observability disabled info, RCA not configured info, error with Retry, environments error handling
  • RCAFilters (6) — search input, environment, status selector, time range, disabled state, loading skeleton
  • RCAActions (5) — total count, "No reports data" for undefined, refresh button, disabled state
  • RCATable (6) — report data rendering, pending report text, status badges, view/rerun buttons, empty state

Alerts (5 files, 50 tests)

  • ObservabilityAlertsPage (14) — permission loading/denied, filters/actions/table rendering, environment count, alert entries, total count, environment error, alerts error with Retry, observability disabled info, no environments alert, severity/search client-side filtering
  • AlertsFilter (6) — search input, severity selector, environment, time range, disabled state, typing in search
  • AlertsActions (7) — total count, last updated, sort toggle, refresh click, disabled state
  • AlertsTable (7) — table headers, alert rows, empty state, loading skeletons, spinner with existing data, severity chips
  • AlertRow (17) — timestamp, rule name, severity chips, source type, alert value, View incident button, expand/collapse details, metric/log query fields, notification channels, rule description, missing field fallbacks

Metrics (3 files, 39 tests)

  • ObservabilityMetricsPage (11) — permission loading/denied, filters/actions rendering, four metric cards, graph components, environment count, loading state, error with Retry, observability disabled info, namespace error handling
  • MetricsFilters (3) — environment selector, time range, disabled state
  • MetricsActions (4) — last updated text, refresh button, click handler, disabled state
  • utils (31) — formatAxisTime, formatMetricValue (CPU/memory/network/latency), parseTimeRange, transformMetricsData, getMetricConfigs, getLineOpacity, formatMetricName

Runtime Logs (6 files, 84 tests)

  • ObservabilityRuntimeLogsPage (13) — permission loading/denied, filter/table/actions rendering, environment count, log entries, total count, environment error, logs error, observability disabled info, no environments alert, Retry button logic
  • ObservabilityProjectRuntimeLogsPage (13) — permission loading/denied, filter/actions/table rendering, environments, components, project-level log entries, total count, environment/components/logs errors, observability disabled info, no environments alert
  • LogsFilter (10) — search input, environment, time range, log levels, components filter (conditional), selected fields filter, disabled state, typing in search
  • LogsActions (10) — total count, last updated, sort toggle, live mode toggle, refresh button, disabled state
  • LogsTable (10) — column headers, ComponentName header, log entries, empty state, loading skeletons, pagination indicators, selected field columns
  • LogEntry (12) — timestamp, log level chips (INFO/ERROR/WARN/DEBUG), log message, selected fields, component name, expand/collapse metadata, copy button, fallback values

Refactored Tests (8 page-level files)

All page-level tests refactored to follow Backstage recommended testing patterns:

  • Replaced mocked @backstage/core-components with real components via renderInTestApp
  • Replaced mocked useEntity with EntityProvider from @backstage/plugin-catalog-react
  • See TESTING_GUIDE.md for the testing approach

Summary by CodeRabbit

  • Documentation

    • Added a comprehensive frontend plugin testing guide with recommended render utilities, mock guidance, mapping table, and example test patterns.
  • New Features

    • Exposed reusable test utilities: mock catalog entity factories and a configurable mock client via the test-utils package.
  • Tests

    • Large expansion of unit and UI tests across plugins (components, hooks, pages, observability, CI, environments, secrets, access control, workflows).

…p Card component

- Eliminated auto deploy state and associated handlers from Environments component.
- Updated EnvironmentsContext and SetupCard to remove auto deploy props and logic.
- Refactored SetupCard to fetch auto deploy status directly and handle updates internally.
- Cleaned up EnvironmentsList to remove unused auto deploy props.

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
- Replace jest.mock('@backstage/core-plugin-api') with TestApiProvider from @backstage/test-utils for DI-based API mocking in tests
- Replace jest.mock('@backstage/plugin-catalog-react') with EntityProvider for entity context in tests
- Add shared frontend test utilities to @openchoreo/test-utils: createMockOpenChoreoClient(), mockComponentEntity(), mockSystemEntity()

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
…rol and Git Secret pages

- Introduced unit tests for AccessControlPage, MappingsTab, and RolesTab components to ensure proper rendering and functionality.
- Implemented tests for various user permission scenarios, including loading states, role visibility, and action handling.
- Added tests for EnvironmentActions and EnvironmentCard components to validate user interactions and permission checks.
- Enhanced test coverage for Environments components, including EnvironmentCardContent and SetupCard.

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
- Introduced unit tests for LogEntry, LogsActions, LogsFilter, LogsTable, ObservabilityProjectRuntimeLogsPage, and ObservabilityRuntimeLogsPage components to ensure proper rendering and functionality.
- Implemented tests for various user interactions, including filtering, sorting, and log entry display.
- Enhanced test coverage for log metadata display and error handling scenarios.

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
- Introduced unit tests for AlertRow, AlertsActions, AlertsFilter, AlertsTable, and ObservabilityAlertsPage components to ensure proper rendering and functionality.
- Added tests for IncidentRow, IncidentsActions, IncidentsFilter, IncidentsTable, and ObservabilityProjectIncidentsPage to validate user interactions and data display.
- Enhanced test coverage for various scenarios, including alert and incident details, filtering, sorting, and loading states.

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
- Introduced a comprehensive testing guide for frontend plugins, detailing recommended testing utilities and their usage.
- Included sections on rendering components with `renderInTestApp`, `EntityProvider`, and `TestApiProvider`.
- Provided guidelines on what to mock during testing and a quick reference table for component types and rendering methods.
- Added a structured test example to illustrate best practices.

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 30064cc1-7db6-4cc7-9aa8-5293971415d8

📥 Commits

Reviewing files that changed from the base of the PR and between cfc44d3 and 83343b7.

📒 Files selected for processing (3)
  • plugins/openchoreo/src/api/OpenChoreoClient.ts
  • plugins/openchoreo/src/api/OpenChoreoClientApi.ts
  • plugins/openchoreo/src/components/Environments/components/SetupCard.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/openchoreo/src/components/Environments/components/SetupCard.tsx

📝 Walkthrough

Walkthrough

Adds a testing guide and new frontend test utilities, introduces many Jest/RTL test suites across plugins, refactors tests to use Backstage providers (EntityProvider/TestApiProvider), adds entity fixtures and a mock OpenChoreo client, and moves auto‑deploy fetching/updating logic into SetupCard while removing auto‑deploy from Environments context and props.

Changes

Cohort / File(s) Summary
Testing guide
TESTING_GUIDE.md
New Backstage-focused testing guide describing render helpers (renderInTestApp, EntityProvider, TestApiProvider), mocking guidance, and example test scaffolding.
Test utils — package & exports
packages/test-utils/package.json, packages/test-utils/src/index.ts
Added @backstage/catalog-model dependency; exported new frontend testing utilities from package entrypoint.
Test utils — fixtures & mock client
packages/test-utils/src/frontend/entityFixtures.ts, .../mockOpenChoreoClient.ts, .../frontend/index.ts
Added mockComponentEntity and mockSystemEntity factories; added createMockOpenChoreoClient and MockOpenChoreoClient type; re-exported via frontend barrel.
Workspace devDeps
plugins/openchoreo-ci/package.json, plugins/openchoreo/package.json
Added local workspace devDependency @openchoreo/test-utils to plugins for test utilities.
Extensive test additions — CI plugin
plugins/openchoreo-ci/src/components/..., plugins/openchoreo-ci/src/utils/*.test.ts
Many new Jest/RTL test suites for CI plugin components, dialogs, tabs, pages, and schema utilities.
Extensive test additions — Observability
plugins/openchoreo-observability/src/components/...
Large set of new tests covering Alerts, Incidents, Metrics, RCA, RuntimeLogs, Traces, and related utilities.
Plugin test refactors (Entity/API providers)
plugins/openchoreo/src/.../*.test.tsx
Refactored tests to use EntityProvider, mockComponentEntity/mockSystemEntity, and TestApiProvider instead of mocking useEntity/useApi; removed several local style mocks.
Environments — context & providers
plugins/openchoreo/src/components/Environments/EnvironmentsContext.tsx, .../Environments.tsx, .../EnvironmentsList.tsx
Removed auto‑deploy fields from Environments context/provider and provider value; removed auto‑deploy state usage from Environments component and list.
SetupCard — internalized auto‑deploy
plugins/openchoreo/src/components/Environments/components/SetupCard.tsx, .../types.ts
Moved auto‑deploy fetching and update handling inside SetupCard (uses useEntity, openChoreo client, useAutoDeployUpdate, and notifications); removed auto‑deploy props from SetupCard types.
OpenChoreo API type update
plugins/openchoreo/src/api/OpenChoreoClient.ts, .../OpenChoreoClientApi.ts
Extended getComponentDetails return type to include optional autoDeploy?: boolean.
Numerous new tests across plugins
plugins/**/src/**/**/*.test.tsx
Added ~50+ Jest/RTL test files covering UI states, interactions, utilities, and edge cases; many include focused Jest module mocks and deterministic stubs.
Specific component edits (tests & behavior)
plugins/openchoreo/src/components/...
Multiple tests updated to rely on entity fixtures/provider; some components (SetupCard) gained internal logic and prop signature changes; Environments consumer components adjusted accordingly.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • kaviththiranga
  • sameerajayasoma
  • jhivandb

Poem

"🐇 I hopped through mocks and fixtures bright,
With entities stitched snug and tight.
Tests popped up, a bustling chore,
Assertions hummed and ran galore.
Hooray — the rabbit fixed the night!"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: adding unit tests for frontend components across multiple OpenChoreo plugins.
Description check ✅ Passed The pull request description is comprehensive and well-structured, covering Purpose, Approach, organized test file summaries by domain, and refactored tests. It aligns with the changeset and explains the testing utilities, documentation, and new test coverage added.

✏️ 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.

…s tests

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
…s, and RunMetadata components

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
Copy link
Copy Markdown

@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: 9

🧹 Nitpick comments (13)
plugins/openchoreo-observability/src/components/Metrics/utils.test.ts (1)

11-11: Remove redundant comment.

The // ---- Tests ---- comment is unnecessary since the .test.ts file extension already indicates this is a test file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/openchoreo-observability/src/components/Metrics/utils.test.ts` at
line 11, Remove the redundant "// ---- Tests ----" comment in the test file;
open plugins/openchoreo-observability/src/components/Metrics/utils.test.ts and
delete that single-line comment (it provides no value because the .test.ts
extension already indicates a test file), leaving the rest of the file and any
test functions (e.g., any describe/it or test blocks in utils.test.ts)
untouched.
plugins/openchoreo-observability/src/components/RuntimeLogs/LogsTable.test.tsx (1)

106-117: Deduplicate overlapping loading-empty-state tests.

The cases “shows loading skeletons when loading with no logs” and “does not show empty state when loading” assert the same outcome. Keeping one will simplify maintenance.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/RuntimeLogs/LogsTable.test.tsx`
around lines 106 - 117, Remove the duplicated test that asserts the same
behavior for loading with no logs: keep a single test (either "shows loading
skeletons when loading with no logs" or "does not show empty state when
loading") that calls renderTable({ logs: [], loading: true }) and asserts
expect(screen.queryByText('No logs found')).not.toBeInTheDocument();; delete the
other redundant it(...) block to avoid overlap in LogsTable.test.tsx and rely on
renderTable and screen.queryByText('No logs found') to verify the behavior.
plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityRuntimeLogsPage.test.tsx (1)

68-79: Consider using mockComponentEntity from @openchoreo/test-utils for consistency.

Similar to the project-level page test, the inline entity could use the shared fixture:

import { mockComponentEntity } from '@openchoreo/test-utils';

const defaultEntity = mockComponentEntity({
  name: 'api-service',
  annotations: {
    'openchoreo.io/namespace': 'dev-ns',
    'openchoreo.io/component': 'api-service',
  },
});

This is optional since the current implementation works correctly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityRuntimeLogsPage.test.tsx`
around lines 68 - 79, Replace the inline defaultEntity object in
ObservabilityRuntimeLogsPage.test.tsx with the shared fixture
mockComponentEntity from `@openchoreo/test-utils`: add an import for
mockComponentEntity and construct defaultEntity via mockComponentEntity({ name:
'api-service', annotations: { 'openchoreo.io/namespace': 'dev-ns',
'openchoreo.io/component': 'api-service' } }); update any usages of the original
defaultEntity accordingly (search for defaultEntity in the test file) so the
test uses the shared fixture instead of the handcrafted object.
plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.test.tsx (1)

71-81: Consider using mockSystemEntity from @openchoreo/test-utils for consistency.

The inline defaultEntity works correctly, but using the shared fixture would align with the new test utilities introduced in this PR:

import { mockSystemEntity } from '@openchoreo/test-utils';

const defaultEntity = mockSystemEntity({
  name: 'my-project',
  annotations: { 'openchoreo.io/namespace': 'dev-ns' },
});

This is optional since the current implementation is functionally correct.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.test.tsx`
around lines 71 - 81, Replace the inline test fixture defaultEntity with the
shared mock from test utils: import mockSystemEntity from
'@openchoreo/test-utils', then initialize defaultEntity by calling
mockSystemEntity({ name: 'my-project', annotations: { 'openchoreo.io/namespace':
'dev-ns' } }) so tests use the common fixture; update the import list
accordingly and keep the variable name defaultEntity used by the tests (function
under test: ObservabilityProjectRuntimeLogsPage test setup).
plugins/openchoreo-observability/src/components/Traces/TracesFilters.test.tsx (1)

90-108: Prefer behavior-first queries over MUI class selectors.

Line 93, Line 101, and Line 107 assert via .Mui-* classes, which is brittle across MUI changes. Prefer role/label/accessible-state assertions against specific controls.

Refactor sketch
-  const selects = document.querySelectorAll('.Mui-disabled');
-  expect(selects.length).toBeGreaterThan(0);
+  expect(screen.getByPlaceholderText('Enter Trace ID to search')).toBeDisabled();

-  expect(document.querySelector('.MuiSkeleton-root')).toBeInTheDocument();
+  // Prefer querying a known loading placeholder/text/test-id exposed by the component.
+  // Example: expect(screen.getByTestId('components-loading-skeleton')).toBeInTheDocument();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/Traces/TracesFilters.test.tsx`
around lines 90 - 108, The tests currently rely on MUI implementation classes
(e.g., '.Mui-disabled' and '.MuiSkeleton-root') which is brittle; update the
three tests ("disables controls when disabled", "shows skeleton while components
are loading", "shows skeleton while environments are loading") to use accessible
queries from renderFilters instead of class selectors: for the disabled test,
select the specific controls rendered by renderFilters (e.g., the select inputs
via getByRole('combobox') or getByLabelText('<label text>')) and assert they are
disabled with toBeDisabled(); for the skeleton tests, query for the Skeleton by
role (e.g., getByRole('progressbar') or an aria-label/testid exposed by the
Skeleton) and assert it is in the document using getByRole/getByLabelText rather
than document.querySelector('.MuiSkeleton-root').
plugins/openchoreo-observability/src/components/Incidents/IncidentsFilter.test.tsx (1)

52-58: Consider using getByLabelText or getByRole for more robust selector queries.

The getAllByText('Components').length >= 1 pattern works but is less idiomatic. If the filter renders a label, using getByLabelText('Components') or querying by role would be more resilient to UI changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/Incidents/IncidentsFilter.test.tsx`
around lines 52 - 58, The test "renders components selector when components
exist" uses screen.getAllByText('Components').length which is brittle; update
the assertion to use an accessible query such as
screen.getByLabelText('Components') or screen.getByRole (e.g.,
getByRole('combobox', { name: 'Components' })) so the test targets the labeled
control, and adjust the expect to assert presence (toBeInTheDocument()) — change
this in the test that calls renderFilters() in IncidentsFilter.test.tsx.
plugins/openchoreo-observability/src/components/Incidents/IncidentsTable.test.tsx (1)

71-77: Skeleton count assertion is tightly coupled to implementation.

Asserting exactly 30 skeletons (5 rows × 6 cells) will break if the loading skeleton layout changes. Consider a looser assertion or documenting the expectation.

💡 Alternative: Assert skeletons exist without exact count
   it('shows loading skeletons when loading', () => {
     renderTable({ loading: true, incidents: [] });

-    // 5 skeleton rows × 6 cells each
-    const skeletons = document.querySelectorAll('.MuiSkeleton-root');
-    expect(skeletons.length).toBe(30);
+    // Verify loading state renders skeletons
+    const skeletons = document.querySelectorAll('.MuiSkeleton-root');
+    expect(skeletons.length).toBeGreaterThan(0);
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/Incidents/IncidentsTable.test.tsx`
around lines 71 - 77, The test "shows loading skeletons when loading" currently
asserts an exact count of 30 .MuiSkeleton-root nodes which is brittle; update
the assertion in IncidentsTable.test.tsx (the test using renderTable and
querying '.MuiSkeleton-root') to be looser—e.g., assert that at least one
skeleton exists or that skeletons.length > 0 (or use a semantic query like
getAllByRole/getAllByLabelText) instead of expecting exactly 30—so layout
changes won’t break the test while still verifying loading state is rendered.
plugins/openchoreo-ci/src/components/WorkflowConfigPage/EditWorkflowConfigs/ChangesPreview.test.tsx (1)

43-53: Consider strengthening the modified-change assertion.

The test only verifies /1 →/ but doesn't assert the new value 3 appears. This could miss regressions where the new value isn't rendered correctly.

💡 Suggestion to verify both old and new values
     expect(screen.getByText(/replicas/)).toBeInTheDocument();
     // The modified line contains "1 → 3"
-    expect(screen.getByText(/1 →/)).toBeInTheDocument();
+    expect(screen.getByText(/1 → 3/)).toBeInTheDocument();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-ci/src/components/WorkflowConfigPage/EditWorkflowConfigs/ChangesPreview.test.tsx`
around lines 43 - 53, The test in ChangesPreview.test.tsx currently only asserts
the old value pattern (/1 →/) and may miss missing new values; update the test
for the 'renders modified change with old → new values' case to assert the new
value is present as well by checking for the full "1 → 3" rendering (or separate
assertions that both the old value "1" and new value "3" appear) when rendering
the ChangesPreview component with the Change { type: 'modified', path:
'replicas', oldValue: 1, newValue: 3 } so the expectation verifies both values
show up.
packages/test-utils/src/frontend/mockOpenChoreoClient.ts (2)

112-119: Consider stricter typing for overrides parameter.

The overrides parameter accepts Record<string, jest.Mock>, allowing any key. A typo in a method name would silently be ignored. Consider using the same union type for better type safety:

🔧 Proposed type improvement
 export function createMockOpenChoreoClient(
-  overrides: Partial<Record<string, jest.Mock>> = {},
+  overrides: Partial<Record<(typeof methodNames)[number], jest.Mock>> = {},
 ): MockOpenChoreoClient {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/test-utils/src/frontend/mockOpenChoreoClient.ts` around lines 112 -
119, The overrides parameter is too loose (Record<string, jest.Mock>) so typos
in method names are ignored; change its type to a Partial keyed by the actual
client methods (e.g., Partial<Record<keyof MockOpenChoreoClient, jest.Mock>> or
Partial<{ [K in keyof MockOpenChoreoClient]: jest.Mock }>) and update the loop
to iterate over methodNames while preserving proper typing so assignments like
mock[name] = overrides[name] are type-checked against MockOpenChoreoClient and
the compiler will catch misspelled method keys; keep the function signature
createMockOpenChoreoClient, the methodNames usage, and return type
MockOpenChoreoClient.

5-7: Consider adding automated verification for method list sync.

The comment about keeping the list in sync is good documentation. The method list is currently complete and in sync with OpenChoreoClientApi (all 76 methods match). For long-term maintainability and to prevent future drift, consider adding a test that imports the OpenChoreoClientApi interface and validates that the mock's method list remains in sync.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/test-utils/src/frontend/mockOpenChoreoClient.ts` around lines 5 - 7,
Add an automated test that imports the OpenChoreoClientApi type and the mock
exported from mockOpenChoreoClient.ts and verifies the mock exposes the same
method names as the interface; implement the test by extracting the interface's
keys (e.g., via a helper type or by importing the real client implementation's
prototype) and comparing as a set to Object.keys(mockOpenChoreoClient) to assert
equality, failing the build if any method is missing or extra.
plugins/openchoreo/src/components/GitSecrets/CreateSecretDialog.test.tsx (1)

94-116: Prefer semantic field queries over index/DOM selectors.

These cases are tightly coupled to the dialog’s DOM order via getAllByRole('textbox')[n] and document.querySelector('input[type="password"]'). A small layout or MUI markup change will break the suite without any behavior regression. Query the inputs by label instead; the same pattern is repeated throughout this file.

Example cleanup
- const inputs = screen.getAllByRole('textbox');
- await user.type(inputs[0], 'my-secret');
- const passwordInput = document.querySelector(
-   'input[type="password"]',
- ) as HTMLInputElement;
- await user.type(passwordInput, 'my-token');
+ await user.type(screen.getByLabelText(/secret name/i), 'my-secret');
+ await user.type(
+   screen.getByLabelText(/password|access token/i),
+   'my-token',
+ );

Also applies to: 127-152, 165-166, 180-189, 218-245, 274-279

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/openchoreo/src/components/GitSecrets/CreateSecretDialog.test.tsx`
around lines 94 - 116, The tests in CreateSecretDialog.test.tsx rely on fragile
DOM indexing and selectors (e.g., using getAllByRole('textbox')[0] and
document.querySelector('input[type="password"]') in the "enables Create button
when name and token are filled" test and several others) which couples them to
markup order; replace those with semantic queries that target fields by label or
accessible name (e.g., screen.getByLabelText('Secret Name'),
screen.getByLabelText('Password') or screen.getByRole('textbox', { name: /Secret
Name/i }) ), updating usages of inputs, passwordInput, and any other indexed
lookups in renderDialog-related tests so each field is located by its
label/accessibility name rather than index/selector; apply the same pattern to
the other affected ranges mentioned.
plugins/openchoreo-observability/src/components/Alerts/ObservabilityAlertsPage.test.tsx (1)

149-159: Avoid asserting Progress internals here.

This case depends on a child component exposing data-testid="progress", which is not part of the page contract and can change on a Backstage upgrade. Mock Progress in this file like the other page suites do, or assert on a stable page-level signal instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/Alerts/ObservabilityAlertsPage.test.tsx`
around lines 149 - 159, The test asserts a child component internals by querying
data-testid="progress" from Progress; instead, modify the test to avoid relying
on Progress implementation by either mocking Progress in this test file (similar
to other page suites) or asserting a stable page-level signal (e.g., check for a
loading message or a container element rendered by renderPage). Specifically,
add a mock for the Progress component (or module) used by
ObservabilityAlertsPage at the top of the test file and update the test to
assert the mocked output (or assert a page-level text like "Loading…" or a
loading container) instead of screen.getByTestId('progress'); keep
mockUseAlertsPermission and renderPage usage the same.
plugins/openchoreo/src/components/DeleteEntity/hooks/useDeleteEntityMenuItems.test.tsx (1)

40-42: Isolate mock client instances per test to prevent cross-test coupling

mockClient and mockAlertApi are shared singletons, while tests override method behavior (mockResolvedValue/mockRejectedValue). Because jest.clearAllMocks() does not reset implementations, behavior can leak between tests as this suite grows.

Proposed refactor
-const mockClient = createMockOpenChoreoClient();
-const mockAlertApi = { post: jest.fn() };
+let mockClient: ReturnType<typeof createMockOpenChoreoClient>;
+let mockAlertApi: { post: jest.Mock };

 describe('useDeleteEntityMenuItems', () => {
   beforeEach(() => {
-    jest.clearAllMocks();
+    jest.clearAllMocks();
+    mockClient = createMockOpenChoreoClient();
+    mockAlertApi = { post: jest.fn() };
     // Reset isMarkedForDeletion since clearAllMocks doesn't reset mockReturnValue
     const { isMarkedForDeletion } = require('../utils');
     isMarkedForDeletion.mockReturnValue(false);
   });

Also applies to: 113-118

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo/src/components/DeleteEntity/hooks/useDeleteEntityMenuItems.test.tsx`
around lines 40 - 42, The test suite shares single-instance mocks (mockClient,
mockAlertApi created via createMockOpenChoreoClient and jest.fn()) which allows
overridden implementations to leak between tests; change to recreate these mocks
per test (e.g., declare mockClient and mockAlertApi as variables and reassign
new instances in a beforeEach or inside each test), or call jest.resetAllMocks()
and recreate implementations before each test, ensuring any
mockResolvedValue/mockRejectedValue calls only affect the current test and
referencing the symbols mockClient, mockAlertApi, and createMockOpenChoreoClient
to locate where to adjust.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/openchoreo-observability/src/components/Alerts/AlertRow.test.tsx`:
- Around line 199-203: The test is clicking the last "View incident" button
which is brittle; instead scope the query to the expanded details container and
find the "View incident" button inside it (e.g., use
within(expandedDetailsContainer).getByRole('button', { name: /View incident/i })
or within(...).getByText('View incident')) and then call user.click on that
scoped button; locate the expanded container using the same selector the test
uses to expand rows (e.g., the element found earlier in the test or a
test-id/aria attribute for the expanded row) so you replace
viewIncidentButtons[...] with a scoped query and click the single matched
button.

In `@plugins/openchoreo-observability/src/components/Alerts/AlertsTable.test.tsx`:
- Around line 72-83: The second test ("shows loading skeletons when loading with
no alerts") is a duplicate that only repeats the empty-state assertion; update
it to actually assert skeleton rendering or remove it. Locate the two it blocks
in AlertsTable.test.tsx (the tests that call renderTable({ alerts: [], loading:
true })) and either delete the duplicate test, or change its assertions to check
for the loading skeleton elements produced by AlertsTable when loading (e.g.,
look for the component's skeleton/test-id, a "skeleton" CSS class, or an
accessible loading role/element) instead of asserting "No alerts found".

In
`@plugins/openchoreo-observability/src/components/Metrics/MetricsFilters.test.tsx`:
- Around line 67-73: The test in MetricsFilters.test.tsx uses a global CSS
selector '.Mui-disabled' which is brittle; update the test that calls
renderFilters({ disabled: true }) to instead query the specific controls (e.g.,
the environment select and the time range select) by their accessible labels
(using the same label text used in the component) and assert each returned
element is disabled (e.g., using .disabled or toBeDisabled). Locate the test
case 'disables controls when disabled' and replace the
document.querySelectorAll('.Mui-disabled') assertion with explicit queries for
the environment and time range controls and individual disabled assertions.

In `@plugins/openchoreo-observability/src/components/Traces/TracesTable.test.tsx`:
- Around line 114-124: The test sets
mockTraceSpans.getError.mockReturnValue('Network error') which persists across
tests (jest.clearAllMocks only clears calls, not return values); update the test
suite to avoid pollution by either using
mockTraceSpans.getError.mockReturnValueOnce('Network error') inside the 'shows
span error when expanded with error' test, or reset the mock return value in a
shared hook (e.g., add mockTraceSpans.getError.mockReset() or
jest.resetAllMocks()/jest.restoreAllMocks() in a beforeEach/afterEach) so
subsequent tests don't see the lingering return value.

In
`@plugins/openchoreo/src/components/DeleteEntity/hooks/useDeleteEntityMenuItems.test.tsx`:
- Around line 222-232: After awaiting the deletion call, make the subsequent
side-effect assertions wait-aware to avoid flakiness: change the direct
assertions on mockAlertApi.post and mockNavigate so they run inside a waitFor
(or use await waitFor(() => expect(...))). Specifically, wrap the expectations
for mockAlertApi.post (message 'Component "my-service" has been marked for
deletion' and severity 'success') and mockNavigate('/catalog') in waitFor so
they only assert after effects triggered by useDeleteEntityMenuItems complete;
reference mockClient.deleteComponent, mockAlertApi.post, mockNavigate and
waitFor in your fix.

In
`@plugins/openchoreo/src/components/Environments/components/EnvironmentCard.test.tsx`:
- Around line 7-13: The first jest.mock of '@openchoreo/backstage-design-system'
is redundant because it's overwritten by the later mock that also defines
StatusBadge; remove the earlier mock block (the one that only returns Card with
data-testid="ds-card") so only the later mock (which provides both Card and
StatusBadge) remains; ensure the remaining mock still exports Card and
StatusBadge as expected for EnvironmentCard.test.tsx.

In `@plugins/openchoreo/src/components/Environments/components/SetupCard.tsx`:
- Around line 40-58: The toggle is being set using checked={autoDeploy ?? false}
which makes it interactive before the current entity's value is loaded; add a
per-entity "loaded" flag (e.g., autoDeployLoaded or isAutoDeployLoaded) and only
enable the switch once the fetchComponentData resolves successfully for that
specific entity; in fetchComponentData record the current entity (or use an
incrementing requestId/AbortController) so that stale responses are ignored and
only setAutoDeploy and setAutoDeployLoaded when the response matches the
outstanding request; apply the same guard/loaded flag and stale-response check
to the other fetch/update logic referenced around the 115-120 area so the
control stays disabled until the initial read for the current entity completes.

In `@plugins/openchoreo/src/components/GitSecrets/GitSecretsPage.test.tsx`:
- Around line 129-134: The test "renders namespace selector with sorted
namespaces" only checks that the Namespace selector renders (via renderContent
and screen.getByLabelText('Namespace')) but doesn't verify ordering; update the
test in GitSecretsPage.test.tsx to either assert the actual option order (e.g.,
use screen.getByLabelText('Namespace') to locate the select, then
getAllByRole('option') or querySelectorAll('option') and compare their
textContent to the expected sorted array) or change the test name to reflect
that it only checks rendering (e.g., "renders namespace selector"); modify the
assertions accordingly in the same test block that calls renderContent().

In `@plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx`:
- Around line 75-106: The tests claim the list is refreshed after mutations but
never assert it; update the tests for useGitSecrets to explicitly verify
mockClient.listGitSecrets is called after createSecret and deleteSecret by
checking call counts or last call (e.g., after invoking
result.current.createSecret(...) and awaiting, assert mockClient.listGitSecrets
was called again), and do the same in the deleteSecret test—locate the test
blocks that call result.current.createSecret and result.current.deleteSecret and
add assertions verifying mockClient.listGitSecrets was invoked to confirm the
refetch behavior.

---

Nitpick comments:
In `@packages/test-utils/src/frontend/mockOpenChoreoClient.ts`:
- Around line 112-119: The overrides parameter is too loose (Record<string,
jest.Mock>) so typos in method names are ignored; change its type to a Partial
keyed by the actual client methods (e.g., Partial<Record<keyof
MockOpenChoreoClient, jest.Mock>> or Partial<{ [K in keyof
MockOpenChoreoClient]: jest.Mock }>) and update the loop to iterate over
methodNames while preserving proper typing so assignments like mock[name] =
overrides[name] are type-checked against MockOpenChoreoClient and the compiler
will catch misspelled method keys; keep the function signature
createMockOpenChoreoClient, the methodNames usage, and return type
MockOpenChoreoClient.
- Around line 5-7: Add an automated test that imports the OpenChoreoClientApi
type and the mock exported from mockOpenChoreoClient.ts and verifies the mock
exposes the same method names as the interface; implement the test by extracting
the interface's keys (e.g., via a helper type or by importing the real client
implementation's prototype) and comparing as a set to
Object.keys(mockOpenChoreoClient) to assert equality, failing the build if any
method is missing or extra.

In
`@plugins/openchoreo-ci/src/components/WorkflowConfigPage/EditWorkflowConfigs/ChangesPreview.test.tsx`:
- Around line 43-53: The test in ChangesPreview.test.tsx currently only asserts
the old value pattern (/1 →/) and may miss missing new values; update the test
for the 'renders modified change with old → new values' case to assert the new
value is present as well by checking for the full "1 → 3" rendering (or separate
assertions that both the old value "1" and new value "3" appear) when rendering
the ChangesPreview component with the Change { type: 'modified', path:
'replicas', oldValue: 1, newValue: 3 } so the expectation verifies both values
show up.

In
`@plugins/openchoreo-observability/src/components/Alerts/ObservabilityAlertsPage.test.tsx`:
- Around line 149-159: The test asserts a child component internals by querying
data-testid="progress" from Progress; instead, modify the test to avoid relying
on Progress implementation by either mocking Progress in this test file (similar
to other page suites) or asserting a stable page-level signal (e.g., check for a
loading message or a container element rendered by renderPage). Specifically,
add a mock for the Progress component (or module) used by
ObservabilityAlertsPage at the top of the test file and update the test to
assert the mocked output (or assert a page-level text like "Loading…" or a
loading container) instead of screen.getByTestId('progress'); keep
mockUseAlertsPermission and renderPage usage the same.

In
`@plugins/openchoreo-observability/src/components/Incidents/IncidentsFilter.test.tsx`:
- Around line 52-58: The test "renders components selector when components
exist" uses screen.getAllByText('Components').length which is brittle; update
the assertion to use an accessible query such as
screen.getByLabelText('Components') or screen.getByRole (e.g.,
getByRole('combobox', { name: 'Components' })) so the test targets the labeled
control, and adjust the expect to assert presence (toBeInTheDocument()) — change
this in the test that calls renderFilters() in IncidentsFilter.test.tsx.

In
`@plugins/openchoreo-observability/src/components/Incidents/IncidentsTable.test.tsx`:
- Around line 71-77: The test "shows loading skeletons when loading" currently
asserts an exact count of 30 .MuiSkeleton-root nodes which is brittle; update
the assertion in IncidentsTable.test.tsx (the test using renderTable and
querying '.MuiSkeleton-root') to be looser—e.g., assert that at least one
skeleton exists or that skeletons.length > 0 (or use a semantic query like
getAllByRole/getAllByLabelText) instead of expecting exactly 30—so layout
changes won’t break the test while still verifying loading state is rendered.

In `@plugins/openchoreo-observability/src/components/Metrics/utils.test.ts`:
- Line 11: Remove the redundant "// ---- Tests ----" comment in the test file;
open plugins/openchoreo-observability/src/components/Metrics/utils.test.ts and
delete that single-line comment (it provides no value because the .test.ts
extension already indicates a test file), leaving the rest of the file and any
test functions (e.g., any describe/it or test blocks in utils.test.ts)
untouched.

In
`@plugins/openchoreo-observability/src/components/RuntimeLogs/LogsTable.test.tsx`:
- Around line 106-117: Remove the duplicated test that asserts the same behavior
for loading with no logs: keep a single test (either "shows loading skeletons
when loading with no logs" or "does not show empty state when loading") that
calls renderTable({ logs: [], loading: true }) and asserts
expect(screen.queryByText('No logs found')).not.toBeInTheDocument();; delete the
other redundant it(...) block to avoid overlap in LogsTable.test.tsx and rely on
renderTable and screen.queryByText('No logs found') to verify the behavior.

In
`@plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.test.tsx`:
- Around line 71-81: Replace the inline test fixture defaultEntity with the
shared mock from test utils: import mockSystemEntity from
'@openchoreo/test-utils', then initialize defaultEntity by calling
mockSystemEntity({ name: 'my-project', annotations: { 'openchoreo.io/namespace':
'dev-ns' } }) so tests use the common fixture; update the import list
accordingly and keep the variable name defaultEntity used by the tests (function
under test: ObservabilityProjectRuntimeLogsPage test setup).

In
`@plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityRuntimeLogsPage.test.tsx`:
- Around line 68-79: Replace the inline defaultEntity object in
ObservabilityRuntimeLogsPage.test.tsx with the shared fixture
mockComponentEntity from `@openchoreo/test-utils`: add an import for
mockComponentEntity and construct defaultEntity via mockComponentEntity({ name:
'api-service', annotations: { 'openchoreo.io/namespace': 'dev-ns',
'openchoreo.io/component': 'api-service' } }); update any usages of the original
defaultEntity accordingly (search for defaultEntity in the test file) so the
test uses the shared fixture instead of the handcrafted object.

In
`@plugins/openchoreo-observability/src/components/Traces/TracesFilters.test.tsx`:
- Around line 90-108: The tests currently rely on MUI implementation classes
(e.g., '.Mui-disabled' and '.MuiSkeleton-root') which is brittle; update the
three tests ("disables controls when disabled", "shows skeleton while components
are loading", "shows skeleton while environments are loading") to use accessible
queries from renderFilters instead of class selectors: for the disabled test,
select the specific controls rendered by renderFilters (e.g., the select inputs
via getByRole('combobox') or getByLabelText('<label text>')) and assert they are
disabled with toBeDisabled(); for the skeleton tests, query for the Skeleton by
role (e.g., getByRole('progressbar') or an aria-label/testid exposed by the
Skeleton) and assert it is in the document using getByRole/getByLabelText rather
than document.querySelector('.MuiSkeleton-root').

In
`@plugins/openchoreo/src/components/DeleteEntity/hooks/useDeleteEntityMenuItems.test.tsx`:
- Around line 40-42: The test suite shares single-instance mocks (mockClient,
mockAlertApi created via createMockOpenChoreoClient and jest.fn()) which allows
overridden implementations to leak between tests; change to recreate these mocks
per test (e.g., declare mockClient and mockAlertApi as variables and reassign
new instances in a beforeEach or inside each test), or call jest.resetAllMocks()
and recreate implementations before each test, ensuring any
mockResolvedValue/mockRejectedValue calls only affect the current test and
referencing the symbols mockClient, mockAlertApi, and createMockOpenChoreoClient
to locate where to adjust.

In `@plugins/openchoreo/src/components/GitSecrets/CreateSecretDialog.test.tsx`:
- Around line 94-116: The tests in CreateSecretDialog.test.tsx rely on fragile
DOM indexing and selectors (e.g., using getAllByRole('textbox')[0] and
document.querySelector('input[type="password"]') in the "enables Create button
when name and token are filled" test and several others) which couples them to
markup order; replace those with semantic queries that target fields by label or
accessible name (e.g., screen.getByLabelText('Secret Name'),
screen.getByLabelText('Password') or screen.getByRole('textbox', { name: /Secret
Name/i }) ), updating usages of inputs, passwordInput, and any other indexed
lookups in renderDialog-related tests so each field is located by its
label/accessibility name rather than index/selector; apply the same pattern to
the other affected ranges mentioned.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: a4ed90fa-f8db-4037-a56f-aace7fa58da4

📥 Commits

Reviewing files that changed from the base of the PR and between 077a91d and 5799d19.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (70)
  • TESTING_GUIDE.md
  • packages/test-utils/package.json
  • packages/test-utils/src/frontend/entityFixtures.ts
  • packages/test-utils/src/frontend/index.ts
  • packages/test-utils/src/frontend/mockOpenChoreoClient.ts
  • packages/test-utils/src/index.ts
  • plugins/openchoreo-ci/package.json
  • plugins/openchoreo-ci/src/components/BuildStatusChip/BuildStatusChip.test.tsx
  • plugins/openchoreo-ci/src/components/BuildWithCommitDialog/BuildWithCommitDialog.test.tsx
  • plugins/openchoreo-ci/src/components/OverviewTab/OverviewTab.test.tsx
  • plugins/openchoreo-ci/src/components/RunMetadataContent/RunMetadataContent.test.tsx
  • plugins/openchoreo-ci/src/components/RunsTab/RunsTab.test.tsx
  • plugins/openchoreo-ci/src/components/WorkflowConfigPage/EditWorkflowConfigs/ChangesPreview.test.tsx
  • plugins/openchoreo-ci/src/components/WorkflowDetailsRenderer/WorkflowDetailsRenderer.test.tsx
  • plugins/openchoreo-ci/src/components/WorkflowRunDetailsPage/WorkflowRunDetailsPage.test.tsx
  • plugins/openchoreo-ci/src/components/Workflows/Workflows.test.tsx
  • plugins/openchoreo-ci/src/utils/schemaExtensions.test.ts
  • plugins/openchoreo-observability/src/components/Alerts/AlertRow.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertsActions.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertsFilter.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertsTable.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/ObservabilityAlertsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentRow.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentsActions.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentsFilter.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentsTable.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/ObservabilityProjectIncidentsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/MetricsActions.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/MetricsFilters.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/ObservabilityMetricsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/utils.test.ts
  • plugins/openchoreo-observability/src/components/RCA/RCAActions.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCAFilters.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCAPage.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCATable.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogEntry.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogsActions.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogsFilter.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogsTable.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityRuntimeLogsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/ObservabilityTracesPage.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/TracesActions.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/TracesFilters.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/TracesTable.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/utils.test.ts
  • plugins/openchoreo/package.json
  • plugins/openchoreo/src/components/AccessControl/AccessControlPage.test.tsx
  • plugins/openchoreo/src/components/AccessControl/MappingsTab/MappingsTab.test.tsx
  • plugins/openchoreo/src/components/AccessControl/RolesTab/ClusterRolesContent.test.tsx
  • plugins/openchoreo/src/components/AccessControl/RolesTab/RolesTab.test.tsx
  • plugins/openchoreo/src/components/DeleteEntity/hooks/useDeleteEntityMenuItems.test.tsx
  • plugins/openchoreo/src/components/Environments/Environments.test.tsx
  • plugins/openchoreo/src/components/Environments/Environments.tsx
  • plugins/openchoreo/src/components/Environments/EnvironmentsContext.tsx
  • plugins/openchoreo/src/components/Environments/EnvironmentsList.test.tsx
  • plugins/openchoreo/src/components/Environments/EnvironmentsList.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentActions.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentCard.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentCardContent.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupCard.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupCard.tsx
  • plugins/openchoreo/src/components/Environments/types.ts
  • plugins/openchoreo/src/components/GitSecrets/CreateSecretDialog.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/GitSecretsPage.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/SecretsTable.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx
  • plugins/openchoreo/src/components/Projects/OverviewCards/DeploymentPipelineCard.test.tsx
  • plugins/openchoreo/src/components/Projects/ProjectComponentsCard/ProjectComponentsCard.test.tsx
  • plugins/openchoreo/src/components/Workflows/OverviewCard/WorkflowsOverviewCard.test.tsx
💤 Files with no reviewable changes (3)
  • plugins/openchoreo/src/components/Environments/EnvironmentsList.tsx
  • plugins/openchoreo/src/components/Environments/types.ts
  • plugins/openchoreo/src/components/Environments/EnvironmentsContext.tsx

Copy link
Copy Markdown

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

🧹 Nitpick comments (3)
plugins/openchoreo/src/components/Environments/EnvironmentsList.test.tsx (1)

353-389: Minor: Test numbering is inconsistent (skips #11).

The test comments jump from // 10. to // 12., skipping // 11.. This may indicate a removed test or a numbering oversight. Consider renumbering for consistency, or adding a comment explaining the gap if test #11 was intentionally removed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/openchoreo/src/components/Environments/EnvironmentsList.test.tsx`
around lines 353 - 389, The test comments are misnumbered (jumping from "// 10."
to "// 12."); update the inline comment before the onRefresh test to "// 11."
(or renumber the surrounding test comments consistently) so the sequence around
the tests for onOpenOverrides and onRefresh in EnvironmentsList.test.tsx reads
consecutively; locate the tests using symbols like onOpenOverrides, onRefresh,
capturedEnvironmentCardProps, and mockHandleRefreshEnvironment to find and edit
the comment.
plugins/openchoreo-ci/src/components/RunMetadataContent/RunMetadataContent.test.tsx (2)

7-10: Align mocked hook state with the real useWorkflowRun shape.

All mocked returns omit refetch, so tests are less strict about the hook contract. Consider using a shared state factory that always includes refetch and only overrides per test case.

♻️ Suggested patch
 const mockUseWorkflowRun = jest.fn();
+const makeWorkflowRunState = (overrides: Record<string, unknown> = {}) => ({
+  workflowRun: null,
+  loading: false,
+  error: null,
+  refetch: jest.fn(),
+  ...overrides,
+});

 // ...
-    mockUseWorkflowRun.mockReturnValue({
-      workflowRun: null,
-      loading: true,
-      error: null,
-    });
+    mockUseWorkflowRun.mockReturnValue(
+      makeWorkflowRunState({ loading: true }),
+    );

Also applies to: 53-58, 66-70, 80-84, 96-103, 113-121, 131-138, 150-157, 167-177, 185-189

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-ci/src/components/RunMetadataContent/RunMetadataContent.test.tsx`
around lines 7 - 10, The mock for the useWorkflowRun hook (mockUseWorkflowRun)
returns objects that omit the refetch method; update the tests to provide a
shared mock state factory (e.g., createMockWorkflowRunState) that always
includes a refetch noop and any other required properties, then have
mockUseWorkflowRun(name) return createMockWorkflowRunState(overrides) so each
test can override fields but refetch is always present; update calls in
RunMetadataContent.test.tsx (all occurrences of mockUseWorkflowRun returns
mentioned in the review) to use this factory to match the real useWorkflowRun
shape.

18-20: Add one assertion path for extracted Git metadata.

extractGitFieldValues is always mocked to {}, so the Git-field rendering path is never validated in this suite.

♻️ Suggested patch
-jest.mock('../../utils/schemaExtensions', () => ({
-  extractGitFieldValues: (_params: any, _mapping: any) => ({}),
-}));
+const mockExtractGitFieldValues = jest.fn();
+jest.mock('../../utils/schemaExtensions', () => ({
+  extractGitFieldValues: (...args: any[]) => mockExtractGitFieldValues(...args),
+}));

 beforeEach(() => {
   jest.clearAllMocks();
+  mockExtractGitFieldValues.mockReturnValue({});
 });

+it('renders git fields when extracted values are available', () => {
+  mockUseWorkflowRun.mockReturnValue({
+    workflowRun: { ...baseBuild },
+    loading: false,
+    error: null,
+  });
+  mockExtractGitFieldValues.mockReturnValue({
+    repoUrl: 'https://github.com/openchoreo/backstage-plugins',
+    branch: 'main',
+  });
+
+  renderContent();
+
+  expect(screen.getByText('https://github.com/openchoreo/backstage-plugins')).toBeInTheDocument();
+  expect(screen.getByText('main')).toBeInTheDocument();
+});

Also applies to: 95-110, 184-194

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-ci/src/components/RunMetadataContent/RunMetadataContent.test.tsx`
around lines 18 - 20, The suite currently always mocks extractGitFieldValues to
return {} so the Git-field rendering path in RunMetadataContent is never
exercised; update the tests in RunMetadataContent.test.tsx to add a case where
extractGitFieldValues returns a non-empty mapping (e.g., a sample git metadata
object) and assert that the component renders the expected Git fields.
Concretely, change the mock behavior for extractGitFieldValues (use
jest.mock/spy or mockReturnValueOnce on the mocked module) within the specific
test that should validate Git metadata, mount/render RunMetadataContent, and add
expectations for the rendered Git keys/values to verify the Git-field rendering
path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@plugins/openchoreo-ci/src/components/RunMetadataContent/RunMetadataContent.test.tsx`:
- Around line 7-10: The mock for the useWorkflowRun hook (mockUseWorkflowRun)
returns objects that omit the refetch method; update the tests to provide a
shared mock state factory (e.g., createMockWorkflowRunState) that always
includes a refetch noop and any other required properties, then have
mockUseWorkflowRun(name) return createMockWorkflowRunState(overrides) so each
test can override fields but refetch is always present; update calls in
RunMetadataContent.test.tsx (all occurrences of mockUseWorkflowRun returns
mentioned in the review) to use this factory to match the real useWorkflowRun
shape.
- Around line 18-20: The suite currently always mocks extractGitFieldValues to
return {} so the Git-field rendering path in RunMetadataContent is never
exercised; update the tests in RunMetadataContent.test.tsx to add a case where
extractGitFieldValues returns a non-empty mapping (e.g., a sample git metadata
object) and assert that the component renders the expected Git fields.
Concretely, change the mock behavior for extractGitFieldValues (use
jest.mock/spy or mockReturnValueOnce on the mocked module) within the specific
test that should validate Git metadata, mount/render RunMetadataContent, and add
expectations for the rendered Git keys/values to verify the Git-field rendering
path.

In `@plugins/openchoreo/src/components/Environments/EnvironmentsList.test.tsx`:
- Around line 353-389: The test comments are misnumbered (jumping from "// 10."
to "// 12."); update the inline comment before the onRefresh test to "// 11."
(or renumber the surrounding test comments consistently) so the sequence around
the tests for onOpenOverrides and onRefresh in EnvironmentsList.test.tsx reads
consecutively; locate the tests using symbols like onOpenOverrides, onRefresh,
capturedEnvironmentCardProps, and mockHandleRefreshEnvironment to find and edit
the comment.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dbea2ab3-4b48-4654-85f3-2c175455761d

📥 Commits

Reviewing files that changed from the base of the PR and between 5799d19 and ed91d10.

📒 Files selected for processing (8)
  • plugins/openchoreo-ci/src/components/RunMetadataContent/RunMetadataContent.test.tsx
  • plugins/openchoreo-ci/src/components/RunsTab/RunsTab.test.tsx
  • plugins/openchoreo-ci/src/components/WorkflowRunDetailsPage/WorkflowRunDetailsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/MetricsActions.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCAActions.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/TracesActions.test.tsx
  • plugins/openchoreo/src/components/Environments/EnvironmentsList.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx
✅ Files skipped from review due to trivial changes (3)
  • plugins/openchoreo-observability/src/components/Metrics/MetricsActions.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/TracesActions.test.tsx
  • plugins/openchoreo-ci/src/components/RunsTab/RunsTab.test.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • plugins/openchoreo-observability/src/components/RCA/RCAActions.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx
  • plugins/openchoreo-ci/src/components/WorkflowRunDetailsPage/WorkflowRunDetailsPage.test.tsx

… components

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
…s, and Alerts components

- Improved assertions in useDeleteEntityMenuItems tests to ensure proper alert and navigation behavior.
- Removed unnecessary mocks in EnvironmentCard tests for cleaner code.
- Simplified namespace selector test in GitSecretsPage for clarity.
- Verified list refresh behavior in useGitSecrets tests after create and delete actions.
- Updated AlertRow tests to improve button interaction verification.
- Enhanced AlertsTable tests to check for loading skeletons instead of empty state.
- Refined MetricsFilters tests to ensure proper control disabling checks.

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
Copy link
Copy Markdown

@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: 7

♻️ Duplicate comments (1)
plugins/openchoreo/src/components/Environments/components/SetupCard.tsx (1)

46-60: ⚠️ Potential issue | 🟠 Major

Clear stale autoDeploy state when a new read starts.

Line 48 only resets autoDeployLoaded. If the previous entity had autoDeploy=true and the next getComponentDetails() call rejects or returns an object without autoDeploy, the old value survives and becomes interactive again once Line 60 flips autoDeployLoaded back to true. Reset autoDeploy at fetch start and in the fallback path so each entity starts from a neutral state.

Possible fix
   useEffect(() => {
     let cancelled = false;
+    setAutoDeploy(undefined);
     setAutoDeployLoaded(false);

     const fetchComponentData = async () => {
       try {
         const componentData = await client.getComponentDetails(entity);
-        if (!cancelled && componentData && 'autoDeploy' in componentData) {
-          setAutoDeploy((componentData as any).autoDeploy);
+        if (!cancelled) {
+          setAutoDeploy(
+            componentData && 'autoDeploy' in componentData
+              ? (componentData as any).autoDeploy
+              : undefined,
+          );
         }
       } catch {
-        // Silently fail - autoDeploy will remain undefined
+        if (!cancelled) {
+          setAutoDeploy(undefined);
+        }
       } finally {
         if (!cancelled) {
           setAutoDeployLoaded(true);
         }
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/openchoreo/src/components/Environments/components/SetupCard.tsx`
around lines 46 - 60, The effect's fetchComponentData may leave a stale
autoDeploy value from a previous entity; in the useEffect before calling
client.getComponentDetails (inside fetchComponentData) call
setAutoDeploy(undefined) to clear previous state, and also in the catch/fallback
path ensure setAutoDeploy(undefined) is invoked when componentData is absent or
when an error occurs; update the logic around fetchComponentData,
setAutoDeployLoaded, and the client.getComponentDetails handling so each new
entity starts with autoDeploy cleared.
🧹 Nitpick comments (8)
plugins/openchoreo-observability/src/components/RCA/RCAActions.test.tsx (1)

50-54: Strengthen disabled-path behavior test with a click assertion.

You already assert disabled state; consider also asserting onRefresh is not called on attempted click to guard regressions.

✅ Suggested test hardening
 it('disables Refresh button when disabled', async () => {
-  render(<RCAActions totalCount={0} disabled onRefresh={jest.fn()} />);
-
-  expect(screen.getByRole('button', { name: /refresh/i })).toBeDisabled();
+  const user = userEvent.setup();
+  const onRefresh = jest.fn();
+  render(<RCAActions totalCount={0} disabled onRefresh={onRefresh} />);
+
+  const refreshButton = screen.getByRole('button', { name: /refresh/i });
+  expect(refreshButton).toBeDisabled();
+  await user.click(refreshButton);
+  expect(onRefresh).not.toHaveBeenCalled();
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/openchoreo-observability/src/components/RCA/RCAActions.test.tsx`
around lines 50 - 54, Update the test in RCAActions.test.tsx for the "disables
Refresh button when disabled" case to also verify the click handler is not
invoked: keep rendering <RCAActions totalCount={0} disabled
onRefresh={onRefreshMock} /> (use a jest.fn() named e.g. onRefreshMock),
simulate a user click on the Refresh button (via userEvent.click or
fireEvent.click) and assert onRefreshMock was not called; reference the
RCAActions component and the test case name so the change is applied to the
existing disabled-path test.
plugins/openchoreo-ci/src/utils/schemaExtensions.test.ts (1)

75-79: Consider testing all unsafe path segments for consistency.

The getNestedValue tests cover all three unsafe keys (__proto__, constructor, prototype), but setNestedValue only tests __proto__. While the underlying validatePathParts function handles all three, adding explicit tests would improve consistency and documentation of the security boundary.

♻️ Optional: Add tests for other unsafe segments
   it('throws on unsafe path segment', () => {
     expect(() => setNestedValue({}, '__proto__.polluted', true)).toThrow(
       'Unsafe path segment',
     );
   });
+
+  it('throws on constructor path segment', () => {
+    expect(() => setNestedValue({}, 'a.constructor.b', true)).toThrow(
+      'Unsafe path segment',
+    );
+  });
+
+  it('throws on prototype path segment', () => {
+    expect(() => setNestedValue({}, 'prototype.polluted', true)).toThrow(
+      'Unsafe path segment',
+    );
+  });
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/openchoreo-ci/src/utils/schemaExtensions.test.ts` around lines 75 -
79, Add explicit tests to verify setNestedValue rejects all unsafe path segments
(not just "__proto__"); specifically add test cases calling setNestedValue({},
'constructor.polluted', true) and setNestedValue({}, 'prototype.polluted', true)
and assert they throw the same 'Unsafe path segment' error. Reference
setNestedValue and the underlying validatePathParts to locate where to add these
tests so behavior matches the existing getNestedValue coverage.
plugins/openchoreo-observability/src/components/RCA/RCAFilters.test.tsx (2)

77-82: Consider strengthening the disabled state assertion.

The current test confirms something is disabled but doesn't verify which controls or how many. Consider checking specific controls like the search input, or verifying the expected count of disabled elements.

💡 Example: verify specific control is disabled
   it('disables controls when disabled', () => {
     renderFilters({ disabled: true });
 
-    const selects = document.querySelectorAll('.Mui-disabled');
-    expect(selects.length).toBeGreaterThan(0);
+    // Verify search input is disabled
+    expect(screen.getByPlaceholderText('Search RCA reports...')).toBeDisabled();
+    
+    // Verify MUI selects are disabled
+    const disabledControls = document.querySelectorAll('.Mui-disabled');
+    expect(disabledControls.length).toBeGreaterThanOrEqual(3); // Environment, Status, Time Range
   });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/openchoreo-observability/src/components/RCA/RCAFilters.test.tsx`
around lines 77 - 82, The test currently only asserts that some element has the
Mui-disabled class; update it to assert specific controls are disabled after
calling renderFilters({ disabled: true }) by selecting them explicitly (e.g.,
query the search input by role "textbox" or placeholder and assert
input.disabled or aria-disabled, query filter dropdowns by role "combobox" and
assert they are disabled, and optionally assert the exact count of disabled
controls). Target identifiers: the test helper renderFilters, the search input
element (role/placeholder), and any dropdowns/buttons used in RCAFilters so the
assertions verify the exact controls and expected disabled count.

59-75: Consider more specific queries for selector labels.

The getAllByText(...).length >= 1 pattern is weak—it passes if the text appears anywhere in the document. For MUI Select components, consider using getByRole or getByLabelText for more precise targeting.

💡 Example using getByRole for the combobox
   it('renders environment selector', () => {
     renderFilters();
 
-    expect(screen.getAllByText('Environment').length).toBeGreaterThanOrEqual(1);
+    expect(screen.getByRole('combobox', { name: /environment/i })).toBeInTheDocument();
   });

If MUI's Select doesn't expose the accessible name reliably, the current approach is acceptable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/openchoreo-observability/src/components/RCA/RCAFilters.test.tsx`
around lines 59 - 75, The tests in RCAFilters.test.tsx use
getAllByText(...).length checks which are too broad; update the three assertions
in the 'renders environment selector', 'renders status selector', and 'renders
time range selector' tests to use more specific queries (e.g.,
getByRole('combobox', { name: /Environment/i }) or getByLabelText('Environment')
for the Environment selector, and analogous queries for 'Status' and 'Time
Range'), replacing the length checks with direct existence assertions (e.g.,
expect(...).toBeInTheDocument()) and fall back to the existing getAllByText
approach only if MUI Select does not expose a reliable accessible name; keep the
tests using renderFilters() and the same test names.
plugins/openchoreo-observability/src/components/Incidents/IncidentRow.test.tsx (1)

101-105: Consider using a more precise assertion.

getAllByText(...).length).toBeGreaterThanOrEqual(1) works but is less precise than getByRole or getByText. If there's only one "View RCA" button expected, a direct assertion is clearer.

💡 Optional: More precise assertion
 it('shows View RCA button when incidentTriggerAiRca is true', () => {
   renderRow();

-  expect(screen.getAllByText('View RCA').length).toBeGreaterThanOrEqual(1);
+  expect(screen.getByRole('button', { name: /View RCA/i })).toBeInTheDocument();
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/Incidents/IncidentRow.test.tsx`
around lines 101 - 105, The test "shows View RCA button when
incidentTriggerAiRca is true" uses expect(screen.getAllByText('View
RCA').length).toBeGreaterThanOrEqual(1) which is imprecise; update the assertion
to assert the single expected element directly (e.g., use screen.getByText('View
RCA') or screen.getByRole(...) for a button) after calling renderRow(), so the
test verifies the exact presence of the "View RCA" button (reference the test
name and renderRow() and the 'View RCA' text to locate the code to change).
plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx (1)

28-29: Prefer condition-based waiting over no-op act for async effects.

Using await act(async () => {}); (e.g., Line 28) is brittle and can hide timing issues. waitFor with a concrete assertion is more stable for hook-side async state transitions.

Suggested pattern update
-import { renderHook, act } from '@testing-library/react';
+import { renderHook, act, waitFor } from '@testing-library/react';

 it('fetches secrets on mount', async () => {
   renderHook(() => useGitSecrets('test-ns'));

-  await act(async () => {});
-
-  expect(mockClient.listGitSecrets).toHaveBeenCalledWith('test-ns');
+  await waitFor(() => {
+    expect(mockClient.listGitSecrets).toHaveBeenCalledWith('test-ns');
+  });
 });

Also applies to: 42-43, 62-63, 84-95, 121-125, 143-144, 149-150, 159-160

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx`
around lines 28 - 29, Replace the no-op `await act(async () => {});` calls in
useGitSecrets.test.tsx with condition-based waiting using `waitFor` (from
`@testing-library/react`) and concrete assertions on the hook's state or mocked
calls; specifically update usages where `act` is used to flush async effects for
the `useGitSecrets` tests (multiple occurrences) to await `waitFor(() =>
expect(...).to... )` that checks the expected state change or that a mock
function was called, ensuring each test asserts a concrete condition rather than
relying on an empty act to resolve async behavior.
plugins/openchoreo-observability/src/components/RuntimeLogs/LogEntry.test.tsx (2)

158-176: Add one test for ComponentName column fallback when metadata is missing.

You verify fallback in expanded metadata, but not in the row column path (LogEntryField.ComponentName) when log.metadata is undefined. Adding that case would close this regression gap.

Proposed test addition
+  it('falls back to componentName prop in ComponentName column when metadata is missing', () => {
+    renderLogEntry({
+      log: { ...sampleLog, metadata: undefined },
+      componentName: 'fallback-component',
+      selectedFields: [...allFields, LogEntryField.ComponentName],
+    });
+
+    expect(screen.getByText('fallback-component')).toBeInTheDocument();
+  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/RuntimeLogs/LogEntry.test.tsx`
around lines 158 - 176, Add a test in LogEntry.test.tsx that verifies the
row-level ComponentName column falls back to the prop when log.metadata is
undefined: render using renderLogEntry with log: { ...sampleLog, metadata:
undefined } and props environmentName, projectName, componentName, then assert
that screen.getByText for LogEntryField.ComponentName's visible cell shows the
provided componentName (e.g., 'fallback-component') without expanding the row;
reference renderLogEntry, sampleLog and LogEntryField.ComponentName to locate
the column renderer to test.

119-125: Use a stable query for the clickable row instead of index-based text targeting.

The test uses getAllByText('Server started on port 8080')[0] twice to interact with the collapsible log entry. If the component renders the same text in multiple places (e.g., log message cell and detail view), the index will become unreliable. Use a role-based query scoped to the row (e.g., within(screen.getByRole('row')).getByText(...)) or add a data-testid to the clickable TableRow element for a stable, intent-clear selector.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@plugins/openchoreo-observability/src/components/RuntimeLogs/LogEntry.test.tsx`
around lines 119 - 125, The test in LogEntry.test.tsx is using index-based
selection via getAllByText('Server started on port 8080')[0], which is brittle;
update the test to target the clickable row deterministically by either querying
the row role and scoping the text lookup (e.g., use screen.getByRole('row',
{name: ...}) or within(screen.getByRole('row', ...)).getByText(...)) or add a
stable data-testid to the clickable TableRow and use getByTestId to perform the
clicks and assertions; update both the expand and collapse interactions to use
the new stable selector so they no longer rely on array indexing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@plugins/openchoreo-observability/src/components/Alerts/ObservabilityAlertsPage.test.tsx`:
- Around line 117-136: The mocks for mockUseComponentAlerts in
ObservabilityAlertsPage.test.tsx are missing the totalCount property from the
hook contract; update every mockReturnValue call for mockUseComponentAlerts to
include totalCount (e.g., totalCount: 2 for the two-alert mock, and appropriate
counts for other variants) alongside alerts, loading, error, fetchAlerts, and
refresh so tests validate the count wiring (refer to mockUseComponentAlerts and
the test cases in ObservabilityAlertsPage.test.tsx).

In
`@plugins/openchoreo-observability/src/components/Incidents/IncidentRow.test.tsx`:
- Around line 51-57: The test in IncidentRow.test.tsx uses new
Date(...).toLocaleString() which is locale/timezone dependent and causes flaky
failures; update the assertion in the 'renders incident timestamp' test (where
renderRow() is called and screen.getByText(...) is used) to compare a stable,
deterministic string or a tolerant match: either format the date with
Intl.DateTimeFormat with an explicit locale and timeZone (e.g., 'en-US' or
'en-GB' and 'UTC') to produce a fixed expected string, or replace getByText(...)
with a regex/partial text match that only asserts the stable parts of the
timestamp (e.g., year-month-day or hour:minute) to avoid exact locale-specific
formatting.

In
`@plugins/openchoreo-observability/src/components/Incidents/ObservabilityProjectIncidentsPage.test.tsx`:
- Around line 118-120: The test mock for useUpdateIncident is incomplete: update
the mockUseUpdateIncident.mockReturnValue to return the full shape used by the
component (include updateIncident, updating and error) so tests reflect the hook
behavior; for example return { updateIncident: jest.fn(), updating: false,
error: null } (or appropriate initial values) so components and table
interactions that read updating/error behave correctly.
- Around line 110-116: The mocked return values for mockUseProjectIncidents are
missing the totalCount property required by the hook contract; update every
mockReturnValue call for mockUseProjectIncidents (including the instances around
the given diff and at the other occurrences referenced) to include totalCount: 0
(or an appropriate number per test) alongside incidents, loading, error,
fetchIncidents, and refresh so the test shape matches useProjectIncidents and
count-related UI logic is exercised correctly.

In
`@plugins/openchoreo/src/components/Environments/components/SetupCard.test.tsx`:
- Around line 111-172: Tests are asserting/clicking the Auto Deploy switch
before the mocked getComponentDetails has settled, causing false positives;
update each affected test (e.g., those using renderSetupCard,
mockClient.getComponentDetails) to wait for the post-load state by awaiting the
resolved UI instead of just asserting not.toBeChecked — for example wait for an
element that only appears after load (or use await screen.findByRole('checkbox',
{ name: /auto deploy/i }) or waitFor(() =>
expect(mockClient.getComponentDetails).toHaveBeenCalled())) so the switch is
enabled and reflects the fetched value before clicking or asserting success
(apply same change to the other test block referenced at lines ~231-244).

In `@plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx`:
- Around line 154-162: Add a positive forbidden-path test: update
useGitSecrets.test.tsx to add a new it block that mocks
mockClient.listGitSecrets to reject with an error object that simulates a 403
(e.g., an Error with response.status = 403 or a custom error type your hook
checks), render the hook via renderHook(() => useGitSecrets('test-ns')), await
the effect with act, and assert result.current.isForbidden === true; reference
the existing test structure and mocks (mockClient.listGitSecrets and
useGitSecrets) to mirror setup and teardown so the new test covers the forbidden
branch.

In
`@plugins/openchoreo/src/components/Workflows/OverviewCard/WorkflowsOverviewCard.test.tsx`:
- Around line 164-169: The test uses a non-existent latestBuild.commit field;
update the fixture in WorkflowsOverviewCard.test.tsx to match the real
useWorkflowsSummary ModelsBuild shape (remove the fake commit property or rename
it to the actual field name used by ModelsBuild, e.g., commitSha/revision) and
update the assertion that checks truncation to target that real field (or remove
the truncation assertion if that data is never provided by the hook). Ensure
changes reference the latestBuild fixture and the assertion around the
truncation behavior tied to useWorkflowsSummary.

---

Duplicate comments:
In `@plugins/openchoreo/src/components/Environments/components/SetupCard.tsx`:
- Around line 46-60: The effect's fetchComponentData may leave a stale
autoDeploy value from a previous entity; in the useEffect before calling
client.getComponentDetails (inside fetchComponentData) call
setAutoDeploy(undefined) to clear previous state, and also in the catch/fallback
path ensure setAutoDeploy(undefined) is invoked when componentData is absent or
when an error occurs; update the logic around fetchComponentData,
setAutoDeployLoaded, and the client.getComponentDetails handling so each new
entity starts with autoDeploy cleared.

---

Nitpick comments:
In `@plugins/openchoreo-ci/src/utils/schemaExtensions.test.ts`:
- Around line 75-79: Add explicit tests to verify setNestedValue rejects all
unsafe path segments (not just "__proto__"); specifically add test cases calling
setNestedValue({}, 'constructor.polluted', true) and setNestedValue({},
'prototype.polluted', true) and assert they throw the same 'Unsafe path segment'
error. Reference setNestedValue and the underlying validatePathParts to locate
where to add these tests so behavior matches the existing getNestedValue
coverage.

In
`@plugins/openchoreo-observability/src/components/Incidents/IncidentRow.test.tsx`:
- Around line 101-105: The test "shows View RCA button when incidentTriggerAiRca
is true" uses expect(screen.getAllByText('View
RCA').length).toBeGreaterThanOrEqual(1) which is imprecise; update the assertion
to assert the single expected element directly (e.g., use screen.getByText('View
RCA') or screen.getByRole(...) for a button) after calling renderRow(), so the
test verifies the exact presence of the "View RCA" button (reference the test
name and renderRow() and the 'View RCA' text to locate the code to change).

In `@plugins/openchoreo-observability/src/components/RCA/RCAActions.test.tsx`:
- Around line 50-54: Update the test in RCAActions.test.tsx for the "disables
Refresh button when disabled" case to also verify the click handler is not
invoked: keep rendering <RCAActions totalCount={0} disabled
onRefresh={onRefreshMock} /> (use a jest.fn() named e.g. onRefreshMock),
simulate a user click on the Refresh button (via userEvent.click or
fireEvent.click) and assert onRefreshMock was not called; reference the
RCAActions component and the test case name so the change is applied to the
existing disabled-path test.

In `@plugins/openchoreo-observability/src/components/RCA/RCAFilters.test.tsx`:
- Around line 77-82: The test currently only asserts that some element has the
Mui-disabled class; update it to assert specific controls are disabled after
calling renderFilters({ disabled: true }) by selecting them explicitly (e.g.,
query the search input by role "textbox" or placeholder and assert
input.disabled or aria-disabled, query filter dropdowns by role "combobox" and
assert they are disabled, and optionally assert the exact count of disabled
controls). Target identifiers: the test helper renderFilters, the search input
element (role/placeholder), and any dropdowns/buttons used in RCAFilters so the
assertions verify the exact controls and expected disabled count.
- Around line 59-75: The tests in RCAFilters.test.tsx use
getAllByText(...).length checks which are too broad; update the three assertions
in the 'renders environment selector', 'renders status selector', and 'renders
time range selector' tests to use more specific queries (e.g.,
getByRole('combobox', { name: /Environment/i }) or getByLabelText('Environment')
for the Environment selector, and analogous queries for 'Status' and 'Time
Range'), replacing the length checks with direct existence assertions (e.g.,
expect(...).toBeInTheDocument()) and fall back to the existing getAllByText
approach only if MUI Select does not expose a reliable accessible name; keep the
tests using renderFilters() and the same test names.

In
`@plugins/openchoreo-observability/src/components/RuntimeLogs/LogEntry.test.tsx`:
- Around line 158-176: Add a test in LogEntry.test.tsx that verifies the
row-level ComponentName column falls back to the prop when log.metadata is
undefined: render using renderLogEntry with log: { ...sampleLog, metadata:
undefined } and props environmentName, projectName, componentName, then assert
that screen.getByText for LogEntryField.ComponentName's visible cell shows the
provided componentName (e.g., 'fallback-component') without expanding the row;
reference renderLogEntry, sampleLog and LogEntryField.ComponentName to locate
the column renderer to test.
- Around line 119-125: The test in LogEntry.test.tsx is using index-based
selection via getAllByText('Server started on port 8080')[0], which is brittle;
update the test to target the clickable row deterministically by either querying
the row role and scoping the text lookup (e.g., use screen.getByRole('row',
{name: ...}) or within(screen.getByRole('row', ...)).getByText(...)) or add a
stable data-testid to the clickable TableRow and use getByTestId to perform the
clicks and assertions; update both the expand and collapse interactions to use
the new stable selector so they no longer rely on array indexing.

In `@plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx`:
- Around line 28-29: Replace the no-op `await act(async () => {});` calls in
useGitSecrets.test.tsx with condition-based waiting using `waitFor` (from
`@testing-library/react`) and concrete assertions on the hook's state or mocked
calls; specifically update usages where `act` is used to flush async effects for
the `useGitSecrets` tests (multiple occurrences) to await `waitFor(() =>
expect(...).to... )` that checks the expected state change or that a mock
function was called, ensuring each test asserts a concrete condition rather than
relying on an empty act to resolve async behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: f2170664-133c-4968-ab1a-4ed000f8b5a6

📥 Commits

Reviewing files that changed from the base of the PR and between ed91d10 and af831f6.

📒 Files selected for processing (49)
  • TESTING_GUIDE.md
  • plugins/openchoreo-ci/src/components/BuildWithCommitDialog/BuildWithCommitDialog.test.tsx
  • plugins/openchoreo-ci/src/components/OverviewTab/OverviewTab.test.tsx
  • plugins/openchoreo-ci/src/components/RunsTab/RunsTab.test.tsx
  • plugins/openchoreo-ci/src/components/WorkflowConfigPage/EditWorkflowConfigs/ChangesPreview.test.tsx
  • plugins/openchoreo-ci/src/components/WorkflowDetailsRenderer/WorkflowDetailsRenderer.test.tsx
  • plugins/openchoreo-ci/src/utils/schemaExtensions.test.ts
  • plugins/openchoreo-observability/src/components/Alerts/AlertRow.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertsActions.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertsFilter.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertsTable.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/ObservabilityAlertsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentRow.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentsActions.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentsFilter.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentsTable.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/ObservabilityProjectIncidentsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/MetricsActions.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/MetricsFilters.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/ObservabilityMetricsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/utils.test.ts
  • plugins/openchoreo-observability/src/components/RCA/RCAActions.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCAFilters.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCAPage.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCATable.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogEntry.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogsActions.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogsFilter.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogsTable.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/ObservabilityTracesPage.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/TracesActions.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/TracesFilters.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/TracesTable.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/utils.test.ts
  • plugins/openchoreo/src/components/AccessControl/MappingsTab/MappingsTab.test.tsx
  • plugins/openchoreo/src/components/AccessControl/RolesTab/ClusterRolesContent.test.tsx
  • plugins/openchoreo/src/components/AccessControl/RolesTab/RolesTab.test.tsx
  • plugins/openchoreo/src/components/DeleteEntity/hooks/useDeleteEntityMenuItems.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentActions.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentCard.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentCardContent.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupCard.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupCard.tsx
  • plugins/openchoreo/src/components/GitSecrets/CreateSecretDialog.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/GitSecretsPage.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/SecretsTable.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx
  • plugins/openchoreo/src/components/Workflows/OverviewCard/WorkflowsOverviewCard.test.tsx
✅ Files skipped from review due to trivial changes (19)
  • plugins/openchoreo-observability/src/components/Traces/TracesActions.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertsFilter.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertsActions.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/TracesFilters.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogsFilter.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentsFilter.test.tsx
  • TESTING_GUIDE.md
  • plugins/openchoreo-observability/src/components/Traces/utils.test.ts
  • plugins/openchoreo-observability/src/components/Traces/TracesTable.test.tsx
  • plugins/openchoreo-ci/src/components/BuildWithCommitDialog/BuildWithCommitDialog.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertsTable.test.tsx
  • plugins/openchoreo/src/components/AccessControl/MappingsTab/MappingsTab.test.tsx
  • plugins/openchoreo-ci/src/components/WorkflowConfigPage/EditWorkflowConfigs/ChangesPreview.test.tsx
  • plugins/openchoreo/src/components/DeleteEntity/hooks/useDeleteEntityMenuItems.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/utils.test.ts
  • plugins/openchoreo/src/components/Environments/components/EnvironmentCardContent.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentActions.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/ObservabilityTracesPage.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/SecretsTable.test.tsx
🚧 Files skipped from review as they are similar to previous changes (17)
  • plugins/openchoreo-observability/src/components/Metrics/MetricsFilters.test.tsx
  • plugins/openchoreo/src/components/AccessControl/RolesTab/RolesTab.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentsActions.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCATable.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCAPage.test.tsx
  • plugins/openchoreo-ci/src/components/OverviewTab/OverviewTab.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/CreateSecretDialog.test.tsx
  • plugins/openchoreo/src/components/GitSecrets/GitSecretsPage.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogsTable.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/IncidentsTable.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/MetricsActions.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/AlertRow.test.tsx
  • plugins/openchoreo-ci/src/components/WorkflowDetailsRenderer/WorkflowDetailsRenderer.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/LogsActions.test.tsx
  • plugins/openchoreo/src/components/AccessControl/RolesTab/ClusterRolesContent.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentCard.test.tsx

- Introduced a new test case to verify that the isForbidden state is set to true when a 403 error is encountered.
- Enhanced the existing test suite for useGitSecrets to improve error handling coverage.

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
- Replaced static method names array with a dynamic Proxy-based approach for creating a fully-mocked OpenChoreoClientApi.
- This change ensures that any method accessed on the mock is automatically a jest.fn(), keeping the mock up-to-date with the interface without manual updates.

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
Copy link
Copy Markdown

@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: 1

🧹 Nitpick comments (2)
packages/test-utils/src/frontend/mockOpenChoreoClient.ts (2)

24-24: Consider constraining the type to OpenChoreoClientApi for compile-time safety.

The current Record<string, jest.Mock> type allows tests to access any property name, including typos like mockClient.getEnvironmentss, without TypeScript errors. The Proxy silently creates a mock, so tests pass but may not exercise real API methods.

A type-safe alternative:

import type { OpenChoreoClientApi } from '@openchoreo/backstage-plugin';

export type MockOpenChoreoClient = {
  [K in keyof OpenChoreoClientApi]: jest.Mock;
};

This preserves the Proxy's dynamic behavior at runtime while catching typos at compile time.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/test-utils/src/frontend/mockOpenChoreoClient.ts` at line 24, The
MockOpenChoreoClient type is too permissive; change MockOpenChoreoClient to be
keyed by the OpenChoreoClientApi interface so TypeScript enforces valid method
names. Import OpenChoreoClientApi from '@openchoreo/backstage-plugin' and
redefine MockOpenChoreoClient as a mapped type over keyof OpenChoreoClientApi
producing jest.Mock for each key (maintaining the Proxy-based runtime behavior),
and update any places that reference MockOpenChoreoClient accordingly.

36-43: Guard against well-known properties to prevent thenable/Promise confusion.

The Proxy returns jest.fn() for any accessed property, including then. This causes the mock to be mistaken for a thenable:

const mockClient = createMockOpenChoreoClient();
await mockClient; // Hangs or fails - mockClient.then() is called as a thenable
Promise.resolve(mockClient); // Wraps incorrectly

Add guards for properties that should return undefined:

Proposed fix
+const PASSTHROUGH_PROPS = new Set([
+  'then',
+  'toJSON',
+  'asymmetricMatch',
+  '$$typeof',
+  'nodeType',
+  'tagName',
+]);
+
 return new Proxy(mocks, {
-  get(target, prop: string) {
+  get(target, prop) {
+    if (typeof prop === 'symbol' || PASSTHROUGH_PROPS.has(prop)) {
+      return undefined;
+    }
     if (!(prop in target)) {
       target[prop] = jest.fn();
     }
     return target[prop];
   },
 }) as MockOpenChoreoClient;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/test-utils/src/frontend/mockOpenChoreoClient.ts` around lines 36 -
43, The Proxy get trap in createMockOpenChoreoClient currently creates jest.fn()
for any property (target, prop), which makes the mock behave like a thenable
when accessing "then" or other well-known properties; update the get trap in
packages/test-utils/src/frontend/mockOpenChoreoClient.ts to explicitly guard and
return undefined for well-known keys (at minimum "then", "catch", "finally",
Symbol.toStringTag, Symbol.iterator/Symbol.asyncIterator, and "constructor")
before creating jest.fn(), so that accessing those props does not treat the mock
as a Promise/thenable while preserving the existing behavior for other mocked
methods on the mocks object.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/openchoreo/src/components/Environments/components/SetupCard.tsx`:
- Around line 45-69: Update the getComponentDetails return type in the
OpenChoreoClientApi interface to include autoDeploy?: boolean so the method
signature matches the backend schema and test mocks; locate the
getComponentDetails declaration and add the optional autoDeploy property to the
returned Promise shape (e.g., include autoDeploy?: boolean alongside uid?,
deletionTimestamp?, parameters?) so places checking 'autoDeploy' in
componentData (and tests) are type-safe.

---

Nitpick comments:
In `@packages/test-utils/src/frontend/mockOpenChoreoClient.ts`:
- Line 24: The MockOpenChoreoClient type is too permissive; change
MockOpenChoreoClient to be keyed by the OpenChoreoClientApi interface so
TypeScript enforces valid method names. Import OpenChoreoClientApi from
'@openchoreo/backstage-plugin' and redefine MockOpenChoreoClient as a mapped
type over keyof OpenChoreoClientApi producing jest.Mock for each key
(maintaining the Proxy-based runtime behavior), and update any places that
reference MockOpenChoreoClient accordingly.
- Around line 36-43: The Proxy get trap in createMockOpenChoreoClient currently
creates jest.fn() for any property (target, prop), which makes the mock behave
like a thenable when accessing "then" or other well-known properties; update the
get trap in packages/test-utils/src/frontend/mockOpenChoreoClient.ts to
explicitly guard and return undefined for well-known keys (at minimum "then",
"catch", "finally", Symbol.toStringTag, Symbol.iterator/Symbol.asyncIterator,
and "constructor") before creating jest.fn(), so that accessing those props does
not treat the mock as a Promise/thenable while preserving the existing behavior
for other mocked methods on the mocks object.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: d1f18d54-5b3f-4e1f-b1a1-a7c8e5aad9f5

📥 Commits

Reviewing files that changed from the base of the PR and between af831f6 and cfc44d3.

📒 Files selected for processing (4)
  • packages/test-utils/src/frontend/mockOpenChoreoClient.ts
  • plugins/openchoreo/src/components/Environments/components/SetupCard.tsx
  • plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx
  • plugins/openchoreo/src/components/Workflows/OverviewCard/useWorkflowsSummary.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/openchoreo/src/components/GitSecrets/hooks/useGitSecrets.test.tsx

…lientApi

- Introduced an optional autoDeploy property in both OpenChoreoClient and OpenChoreoClientApi interfaces.
- Updated SetupCard component to utilize the new autoDeploy property for improved state management.

Signed-off-by: Stefinie Fernando <minolispencer@gmail.com>
@LakshanSS LakshanSS merged commit 0930ac9 into openchoreo:main Apr 3, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants