Skip to content

ACM-33855 wizard review page filter to just show differences#6259

Merged
jeswanke merged 18 commits into
stolostron:mainfrom
jeswanke:ACM-33855-Wizard-Review-Page-Filter-to-just-show-differences-2
Jun 10, 2026
Merged

ACM-33855 wizard review page filter to just show differences#6259
jeswanke merged 18 commits into
stolostron:mainfrom
jeswanke:ACM-33855-Wizard-Review-Page-Filter-to-just-show-differences-2

Conversation

@jeswanke

@jeswanke jeswanke commented May 26, 2026

Copy link
Copy Markdown
Contributor

📝 Summary

demo is here:
https://redhat-internal.slack.com/archives/C02684L8JMV/p1780001491259069

coding details are here:
https://docs.google.com/document/d/1uhesSDfaXbi4vwQO8hz56MTRd--UGpt6R84JH8gEZgM/edit?tab=t.0

Ticket Summary (Title):
wizard review page filter to just show differences

Ticket Link:
https://redhat.atlassian.net/browse/ACM-33855

Type of Change:

  • 🐞 Bug Fix
  • ✨ Feature
  • 🔧 Refactor
  • 💸 Tech Debt
  • 🧪 Test-related
  • 📄 Docs

✅ Checklist

General

  • PR title follows the convention (e.g. ACM-12340 Fix bug with...)
  • Code builds and runs locally without errors
  • No console logs, commented-out code, or unnecessary files
  • All commits are meaningful and well-labeled
  • All new display strings are externalized for localization (English only)
  • (Nice to have) JSDoc comments added for new functions and interfaces

If Feature

  • UI/UX reviewed (if applicable)
  • All acceptance criteria met
  • Unit test coverage added or updated
  • Relevant documentation or comments included

If Bugfix

  • Root cause and fix summary are documented in the ticket (for future reference / errata)
  • Fix tested thoroughly and resolves the issue
  • Test(s) added to prevent regression

🗒️ Notes for Reviewers

Summary by CodeRabbit

  • New Features

    • Persisted "Show changes only" filter in review with new localized label
    • Side-by-side diff editor with previous/next navigation, improved copy/paste and "paste-all" behavior
    • Wizard exposes a resettable default-data snapshot; editors receive default resources to detect/reset changes
  • Style

    • Updated editor/diff visuals and review list styling for clearer change indicators and layout
  • Tests

    • Expanded and updated editor, diff, process, and mock tests to cover new flows and decorations

Signed-off-by: John Swanke <jswanke@redhat.com>
@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown

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

Walkthrough

Adds default-data snapshot support and default-array input registration to the wizard, implements a persisted "show changes only" review filter with path/value comparison, introduces getItemValue YAML-path resolver, and refactors SyncEditor to support diff view, diff navigation, model refresh, decoration changes, and improved Monaco test mocks.

Changes

Form Wizard: Default snapshot & review

Layer / File(s) Summary
Wizard core and default-data context
frontend/packages/react-form-wizard/src/Wizard.tsx, frontend/packages/react-form-wizard/src/contexts/DefaultDataContext.tsx, frontend/packages/react-form-wizard/src/contexts/DataContext.tsx
Adds defaultDataSnapshot, dataRef, rewrites update(newData, resetDefaultSnapshot?), provides DefaultDataContext and DefaultArrayInputRegisterProvider.
Review find/list & navigation
frontend/packages/react-form-wizard/src/review/ReviewStep.tsx, .../ReviewStepFilterList.tsx, .../ReviewStepNavigation.tsx
Implements persisted showChangesOnly state, threads defaultItem into the find-list model, filters rows identical to defaults, and delegates YAML-path membership to getItemValue.
Review UI strings and styles
frontend/packages/react-form-wizard/src/contexts/StringContext.tsx, .../ReviewStepToolbar.tsx, .../ReviewStep.css
Adds reviewShowChangesOnlyLabel, toolbar checkbox for "Show changes", and CSS for changes-only find-list/difference rows.
Default array-input register & types
frontend/packages/react-form-wizard/src/review/ReviewStepContexts.tsx
Adds ArrayInstanceDiffType, defaultValue node field, and DefaultArrayInputRegisterProvider that rebuilds register when default snapshot changes.
Input helpers
frontend/packages/react-form-wizard/src/inputs/Input.ts
Adds getArrayInputLabel and uses it for array-input review labels.
YAML path helpers & utils API
frontend/packages/react-form-wizard/src/review/utils.ts
Adds getItemValue(item, yamlPath), removes simplifyLabels, and narrows horizontalTermWidthModifierForInputRun input type.
Exports and route wiring
frontend/packages/react-form-wizard/src/index.ts, many frontend/src/routes/* files
Exports DefaultDataContext; updates many route components to call useDefaultItem() and pass defaultResources to SyncEditor, forwarding resetDefaultSnapshot through update() callbacks.
Wizard strings mapping
frontend/src/lib/wizardStrings.ts
Wires new reviewShowChangesOnlyLabel and review array instance labels into translations.

SyncEditor, decorations, and Monaco mocks

Layer / File(s) Summary
SyncEditor diff component and toolbar
frontend/src/components/SyncEditor/SyncEditorDiff.tsx, .../SyncEditorToolbar.tsx
Adds SyncEditorDiff with imperative handle and diff navigator, and SyncEditorToolbar with show-changes toggle and diff navigation controls.
SyncEditor core behavior
frontend/src/components/SyncEditor/SyncEditor.tsx
Refactors to support activeEditor switching (main vs diff), paste-all detection with one-time resetDefaultSnapshot, model-refresh helpers, diff-aware processing, and expanded onEditorChange(editorResources, resetDefaultSnapshot?).
Decorations and process utilities
frontend/src/components/SyncEditor/decorate.ts, frontend/src/components/SyncEditor/process.ts
Introduces LINE_DECORATION_CLASS_NAMES, getModelDecorations, changes line-decoration classes (e.g., insertLineDecoration), and adds normalize(original, current) utility for resource diffs.
Monaco test mocks and jest mapping
frontend/__mocks__/@monaco-editor/react.tsx, frontend/__mocks__/react-monaco-editor.tsx, frontend/jest.config.ts
Improves Monaco and React-Monaco mocks with container DOM, geometry, selection/edit behaviors, adds Diff mock, and maps @monaco-editor/react to the local mock in Jest config.
Tests and CSS adjustments
frontend/src/components/SyncEditor/*.{test,ts,tsx}, frontend/src/components/SyncEditor/SyncEditor.css
Updates and expands tests for SyncEditor/SyncEditorDiff, adjusts expected decorator shapes, and updates CSS for diff visuals and toolbar layout.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

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

Inline comments:
In `@frontend/packages/react-form-wizard/src/review/ReviewStepFilterList.tsx`:
- Around line 70-88: The current reviewValuesEqualAtPath uses JSON.stringify
fallback which is key-order sensitive; replace that fallback with a
deterministic deep equality for arrays and plain objects: implement object
comparison by checking both are objects (or arrays), compare array lengths and
recursively compare elements, and for objects compare sorted keys (or iterate
keys from Object.keys(a).sort()), ensure same key set and recursively compare
values via reviewValuesEqualAtPath; keep existing short-circuits for
booleans/null/undefined and the Object.is check. Use the function name
reviewValuesEqualAtPath to locate and replace the JSON.stringify-based
comparison with this order-insensitive deep-equal logic.

In `@frontend/packages/react-form-wizard/src/review/utils.ts`:
- Around line 179-194: getItemValue currently strips the ";id=..." discriminator
from yamlPath before selecting an array element, causing wrong matches; fix by
extracting and preserving the id discriminator (e.g., with /;id=([^;]+)$/) into
a variable like idDiscriminator before you call clean/normalized/kindHead, then
when Array.isArray(item) inside getItemValue use that idDiscriminator in the
find callback: if idDiscriminator exists, prefer matching the resource by its
unique id field (check common places like resource.id or resource.metadata?.id)
and fall back to the kindHead match only when no discriminator is present. This
preserves per-resource selection while keeping the rest of the path logic
intact.

In `@frontend/src/components/SyncEditor/SyncEditor.tsx`:
- Around line 235-236: The detection for full-document paste in SyncEditor.tsx
is too broad (only checks endLineNumber) and can misfire on partial
replacements; update the if condition that currently checks
selection?.startColumn and selection?.endLineNumber to require the selection to
start at line 1 column 1 and end at the document's last line and its max column.
Concretely, change the condition around the autoCreateNs branch (where
resetDefaultSnapshotOnNextReportRef is set) to verify selection.startLineNumber
=== 1 && selection.startColumn === 1 && selection.endLineNumber ===
model.getLineCount() && selection.endColumn ===
model.getLineMaxColumn(selection.endLineNumber) so only true full-range
selections trigger the reset.
- Around line 701-705: The decorate call is using editorHasFocus which is false
in diff mode even when the modified diff pane is focused; change the argument to
use a combined focus state (e.g., const combinedFocus = editorHasFocus ||
(isDiffMode && modifiedEditorHasFocus)) and pass combinedFocus into
decorate(...) instead of editorHasFocus so decorations/scroll behavior treat the
focused diff pane as focused; update any related callers that compute focus for
diff/modified panes accordingly (refer to decorate, editorHasFocus, isDiffMode,
and modifiedEditorHasFocus).
- Around line 377-390: The blur listener created via
activeEditor.onDidBlurEditorWidget is not disposed, causing listener
accumulation; capture the returned disposable (from
activeEditor.onDidBlurEditorWidget(...)) and store it in a variable, then call
disposable.dispose() in the effect cleanup (and/or before re-assigning when
activeEditor changes) so the subscription is removed; update the useEffect that
registers the listener around activeEditor and ensure setClickedOnFilteredLine
and setEditorHasFocus logic remains inside the disposed callback.

In `@frontend/src/components/SyncEditor/SyncEditorToolbar.tsx`:
- Line 90: The title fallback in SyncEditorToolbar uses a hardcoded string
'YAML' instead of the translation function; update the JSX so the fallback uses
the i18n translator (e.g., t('YAML') or an existing key) when editorTitle is
falsy, ensuring you import/use the same t function used elsewhere in the
component and preserve the current prop name editorTitle and className
"sy-c-code-editor__title".

In `@frontend/src/lib/wizardStrings.ts`:
- Line 44: The new label reviewShowChangesOnlyLabel currently uses a hardcoded
English string t('Show changes'); replace it with a hierarchical translation key
(e.g., 'wizard.review.showChanges') in frontend/src/lib/wizardStrings.ts by
calling t('wizard.review.showChanges') for reviewShowChangesOnlyLabel, then add
the corresponding entry and translations to the locale files (e.g., en.json)
under the same 'wizard.review.showChanges' key so no user-facing English text
remains in code.

In `@frontend/src/wizards/Argo/ArgoWizard.tsx`:
- Around line 286-289: The title rendering incorrectly checks resources
truthiness which causes an empty array to display the Edit title; instead use
the computed editMode variable consistently. Update the title logic that
currently inspects resources (around where the UI renders the heading) to check
if editMode === EditMode.Edit (and otherwise EditMode.Create) and remove/replace
any direct resources-based checks; ensure any other UI branches (e.g.,
defaultData assignment using defaultData = resources and related conditional
rendering) also rely on editMode so create vs edit state is unified.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: fb6a59f5-fcb2-449f-9737-4689bdc4c7f6

📥 Commits

Reviewing files that changed from the base of the PR and between 6226584 and 1033b44.

⛔ Files ignored due to path filters (1)
  • frontend/public/locales/en/translation.json is excluded by !frontend/public/locales/**
📒 Files selected for processing (35)
  • frontend/packages/react-form-wizard/src/Wizard.tsx
  • frontend/packages/react-form-wizard/src/contexts/DataContext.tsx
  • frontend/packages/react-form-wizard/src/contexts/DefaultDataContext.tsx
  • frontend/packages/react-form-wizard/src/contexts/StringContext.tsx
  • frontend/packages/react-form-wizard/src/index.ts
  • frontend/packages/react-form-wizard/src/inputs/Input.ts
  • frontend/packages/react-form-wizard/src/review/ReviewStep.css
  • frontend/packages/react-form-wizard/src/review/ReviewStep.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStepFilterList.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStepNavigation.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStepToolbar.tsx
  • frontend/packages/react-form-wizard/src/review/utils.ts
  • frontend/src/components/SyncEditor/SyncEditor.css
  • frontend/src/components/SyncEditor/SyncEditor.test.tsx
  • frontend/src/components/SyncEditor/SyncEditor.tsx
  • frontend/src/components/SyncEditor/SyncEditorDiff.tsx
  • frontend/src/components/SyncEditor/SyncEditorToolbar.tsx
  • frontend/src/components/SyncEditor/decorate.test.ts
  • frontend/src/components/SyncEditor/decorate.ts
  • frontend/src/components/SyncEditor/process.ts
  • frontend/src/lib/wizardStrings.ts
  • frontend/src/routes/Applications/CreateArgoApplication/CreatePullApplicationSet.tsx
  • frontend/src/routes/Applications/CreateArgoApplication/CreatePushApplicationSet.tsx
  • frontend/src/routes/Applications/CreateArgoApplication/EditArgoApplicationSet.tsx
  • frontend/src/routes/Governance/policies/CreatePolicy.tsx
  • frontend/src/routes/Governance/policies/CreatePolicyAutomation.tsx
  • frontend/src/routes/Governance/policies/EditPolicy.tsx
  • frontend/src/routes/Governance/policies/EditPolicyAutomation.tsx
  • frontend/src/routes/Governance/policy-sets/CreatePolicySet.tsx
  • frontend/src/routes/Governance/policy-sets/EditPolicySet.tsx
  • frontend/src/routes/Infrastructure/Clusters/ManagedClusters/ImportCluster/ImportCluster.tsx
  • frontend/src/routes/Infrastructure/Clusters/Placements/CreatePlacement/CreatePlacement.tsx
  • frontend/src/routes/Infrastructure/Clusters/Placements/CreatePlacement/EditPlacement.tsx
  • frontend/src/wizards/Argo/ArgoWizard.tsx
  • frontend/src/wizards/Argo/CreateArgoResources.tsx

Comment thread frontend/packages/react-form-wizard/src/review/utils.ts
Comment thread frontend/src/components/SyncEditor/SyncEditor.tsx Outdated
Comment thread frontend/src/components/SyncEditor/SyncEditor.tsx
Comment thread frontend/src/components/SyncEditor/SyncEditor.tsx
Comment thread frontend/src/components/SyncEditor/SyncEditorToolbar.tsx
Comment thread frontend/src/lib/wizardStrings.ts Outdated
Comment thread frontend/src/wizards/Argo/ArgoWizard.tsx
Signed-off-by: John Swanke <jswanke@redhat.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@frontend/src/components/SyncEditor/SyncEditor.tsx`:
- Around line 870-873: The container's compare-mode class is currently applied
using only showChanges; change the className logic on the element that uses
pageRef (the div with className `sync-editor__container`) to add
`sync-editor__container--show-changes` only when the full diff-eligibility
condition is true (i.e., showChanges && defaultResources !== undefined && !mock)
so the compare-only styling matches the actual diff rendering conditions
(references: pageRef, showChanges, defaultResources, mock, and
`sync-editor__container`).
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9a49706a-61e1-449e-89e8-d495d83802c2

📥 Commits

Reviewing files that changed from the base of the PR and between 1033b44 and a56da33.

📒 Files selected for processing (3)
  • frontend/src/components/SyncEditor/SyncEditor.css
  • frontend/src/components/SyncEditor/SyncEditor.tsx
  • frontend/src/components/SyncEditor/decorate.ts

Comment thread frontend/src/components/SyncEditor/SyncEditor.tsx
jeswanke added 5 commits May 26, 2026 16:21
Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@frontend/__mocks__/`@monaco-editor/react.tsx:
- Line 303: The mock for useMonaco returns a tuple but the real
`@monaco-editor/react` exports useMonaco() that returns monaco_editor | null;
update the mock for useMonaco (the exported symbol useMonaco) to return a single
value (null or a mocked monaco instance) with the correct type
(monaco.editor.IStandaloneCodeEditor | typeof monaco | null as appropriate)
instead of [null, () => undefined], so change the exported implementation to
return null (or a typed mock) matching the library's return shape and update any
related type annotations to ensure compatibility.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8a24ee9f-a041-40cf-8ebc-ee5c3fcda88d

📥 Commits

Reviewing files that changed from the base of the PR and between a56da33 and ca1810a.

⛔ Files ignored due to path filters (1)
  • frontend/public/locales/en/translation.json is excluded by !frontend/public/locales/**
📒 Files selected for processing (8)
  • frontend/__mocks__/@monaco-editor/react.tsx
  • frontend/__mocks__/react-monaco-editor.tsx
  • frontend/jest.config.ts
  • frontend/packages/react-form-wizard/src/review/ReviewStepFilterList.tsx
  • frontend/src/components/SyncEditor/SyncEditor.test.tsx
  • frontend/src/components/SyncEditor/SyncEditor.tsx
  • frontend/src/components/SyncEditor/decorate.test.ts
  • frontend/src/lib/wizardStrings.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • frontend/src/lib/wizardStrings.ts
  • frontend/packages/react-form-wizard/src/review/ReviewStepFilterList.tsx
  • frontend/src/components/SyncEditor/SyncEditor.tsx

export const Editor = MonacoEditor
export const DiffEditor = MonacoEditor
export const loader = { config: () => undefined }
export const useMonaco = () => [null, () => undefined] as const

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Confirm library typing for v4.6.0
curl -s https://unpkg.com/@monaco-editor/react@4.6.0/dist/index.d.ts | rg -n 'useMonaco'

# 2) Check local usage expectations
rg -nP '\buseMonaco\s*\(' frontend -C2

Repository: stolostron/console

Length of output: 355


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search repo-wide for any usage patterns of `useMonaco(`
rg -nP '\buseMonaco\s*\(' . -C2

Repository: stolostron/console

Length of output: 44


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Find any mention/imports of useMonaco
rg -nP '\buseMonaco\b' . -S -g'*.{ts,tsx,js,jsx}'

# 2) Look for destructuring patterns that would indicate tuple usage
rg -nP '\[\s*[^]]*\]\s*=\s*useMonaco\s*\(' . -S -g'*.{ts,tsx,js,jsx}'
rg -nP '\(\s*[^)]*\)\s*=\s*useMonaco\s*\(' . -S -g'*.{ts,tsx,js,jsx}'
rg -nP '\{[^}]*\}\s*=\s*useMonaco\s*\(' . -S -g'*.{ts,tsx,js,jsx}'

Repository: stolostron/console

Length of output: 176


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Repo-wide (all files) search for any mention of `useMonaco`
rg -nP '\buseMonaco\b' . -S

Repository: stolostron/console

Length of output: 176


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -nP '\buseMonaco\b' frontend/__mocks__/@monaco-editor/react.tsx

Repository: stolostron/console

Length of output: 130


Fix useMonaco mock to match @monaco-editor/react’s return type

frontend/__mocks__/@monaco-editor/react.tsx currently returns a tuple ([null, () => undefined]), but @monaco-editor/react defines useMonaco() as returning monaco_editor | null directly. Aligning the mock avoids type/behavior mismatches.

Proposed fix
-export const useMonaco = () => [null, () => undefined] as const
+export const useMonaco = () => null
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/__mocks__/`@monaco-editor/react.tsx at line 303, The mock for
useMonaco returns a tuple but the real `@monaco-editor/react` exports useMonaco()
that returns monaco_editor | null; update the mock for useMonaco (the exported
symbol useMonaco) to return a single value (null or a mocked monaco instance)
with the correct type (monaco.editor.IStandaloneCodeEditor | typeof monaco |
null as appropriate) instead of [null, () => undefined], so change the exported
implementation to return null (or a typed mock) matching the library's return
shape and update any related type annotations to ensure compatibility.

jeswanke added 2 commits May 28, 2026 10:43
Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@frontend/__mocks__/`@monaco-editor/react.tsx:
- Around line 203-206: There is a duplicate property definition for
onDidChangeModelContent in the mock module: the simple stub
onDidChangeModelContent: () => mockDisposable() is shadowed by a later
callback-storing implementation; remove the earlier stub so only the
callback-storing version remains (locate the two occurrences of
onDidChangeModelContent in the `@monaco-editor/react` mock and delete the first
stub that returns mockDisposable, keeping the richer implementation that
registers and stores callbacks).

In `@frontend/src/components/SyncEditor/process.test.ts`:
- Around line 118-131: The CachedValuesType.path and related test overrides are
too narrow: change CachedValuesType.path from string to string | (string |
number)[] and widen cached value types (e.g., cacheFiltered and any filter
cached `value`) to accept non-string shapes (string | number | (string |
number)[] or unknown) to match MappingType.value (string | (string|number)[]);
update the test helper processUserDefaults override types accordingly so its
cachedSecrets/cacheFiltered entries accept path: string | (string|number)[] and
non-string values, and ensure any usages of MappingType.$p are compatible with
the revised CachedValuesType.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 94497880-1f7e-4714-9347-3b90897e24ec

📥 Commits

Reviewing files that changed from the base of the PR and between ca1810a and 58cc857.

📒 Files selected for processing (4)
  • frontend/__mocks__/@monaco-editor/react.tsx
  • frontend/src/components/SyncEditor/SyncEditor.test.tsx
  • frontend/src/components/SyncEditor/process.test.js
  • frontend/src/components/SyncEditor/process.test.ts
💤 Files with no reviewable changes (1)
  • frontend/src/components/SyncEditor/process.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/SyncEditor/SyncEditor.test.tsx

Comment thread frontend/__mocks__/@monaco-editor/react.tsx Outdated
Comment thread frontend/src/components/SyncEditor/process.test.ts Outdated
jeswanke added 2 commits May 28, 2026 11:36
Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>
@jeswanke jeswanke requested review from KevinFCormier and fxiang1 May 28, 2026 20:51
@fxiang1

fxiang1 commented May 29, 2026

Copy link
Copy Markdown
Contributor

Looks great John! I will put on hold in case Kevin has anything.

/lgtm
/hold

@openshift-ci openshift-ci Bot added the lgtm label May 29, 2026
@KevinFCormier KevinFCormier changed the title Acm 33855 wizard review page filter to just show differences ACM-33855 wizard review page filter to just show differences Jun 1, 2026
Signed-off-by: John Swanke <jswanke@redhat.com>
@openshift-ci openshift-ci Bot removed the lgtm label Jun 5, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

Inline comments:
In `@frontend/packages/react-form-wizard/src/review/ReviewStepContexts.tsx`:
- Around line 229-240: Add a regression test that verifies
DefaultArrayInputRegisterProvider rebuilds when defaultDataSnapshot is reset:
mount the provider with an initial snapshot and steps (using
stepRegister.getSteps()/buildDefaultArrayInputRegisterFromStepTrees), let it
capture (observe lastCapturedSnapshotRef behavior indirectly), then call
update(..., true) to reset defaultDataSnapshot and update the step tree via
sr.setStepTree (or bump stepRegister.version) to reflect the new snapshot;
finally assert the provider’s register (or ReviewStepFilterList output /
rowMatchesChangesOnlyFilter behavior) reflects the new snapshot’s ARRAY_INPUT
subtrees rather than the stale ones. Ensure the test references
DefaultArrayInputRegisterProvider, buildDefaultArrayInputRegisterFromStepTrees,
stepRegister (sr.setStepTree / version), and ReviewStepFilterList /
rowMatchesChangesOnlyFilter so it fails if rebuild doesn’t occur.

In `@frontend/src/components/SyncEditor/SyncEditorDiff.test.tsx`:
- Around line 114-115: Tests in this suite use fireEvent.change for simulating
typing, which violates the guideline; import userEvent from
'`@testing-library/user-event`' and replace fireEvent.change(input, { target: {
value: '...' } }) with the equivalent user-facing calls (e.g., await
userEvent.clear(input) then await userEvent.type(input, 'apiVersion: v1\nkind:
Pod\n') or await userEvent.paste(input, '...') as appropriate), and update the
test functions to be async where needed; apply the same replacements for the
other occurrences around the suite (the lines referenced near 124-127 and
145-146) and remove the fireEvent usage.
- Around line 59-193: Add a jest-axe accessibility assertion to this test suite
by rendering the component via renderSyncEditorDiff and calling await
axe(container) then expect(...).toHaveNoViolations(); e.g., add a test (or
extend an existing one such as the "mounts the diff editor..." case) that
obtains the rendered container from renderSyncEditorDiff, awaits axe(container)
and asserts toHaveNoViolations(); ensure you reference the axe import and use
await so the accessibility check runs after the diff editor is mounted.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: caac5b08-ab52-474d-b903-1a1baf7862e4

📥 Commits

Reviewing files that changed from the base of the PR and between 58cc857 and 3962987.

⛔ Files ignored due to path filters (1)
  • frontend/public/locales/en/translation.json is excluded by !frontend/public/locales/**
📒 Files selected for processing (13)
  • frontend/__mocks__/@monaco-editor/react.tsx
  • frontend/packages/react-form-wizard/src/Wizard.tsx
  • frontend/packages/react-form-wizard/src/contexts/StringContext.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStep.css
  • frontend/packages/react-form-wizard/src/review/ReviewStep.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStepContexts.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStepFilterList.tsx
  • frontend/packages/react-form-wizard/src/review/utils.ts
  • frontend/src/components/SyncEditor/SyncEditor.css
  • frontend/src/components/SyncEditor/SyncEditor.test.tsx
  • frontend/src/components/SyncEditor/SyncEditorDiff.test.tsx
  • frontend/src/components/SyncEditor/process.test.ts
  • frontend/src/lib/wizardStrings.ts
💤 Files with no reviewable changes (1)
  • frontend/packages/react-form-wizard/src/review/utils.ts
✅ Files skipped from review due to trivial changes (1)
  • frontend/packages/react-form-wizard/src/contexts/StringContext.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
  • frontend/src/lib/wizardStrings.ts
  • frontend/packages/react-form-wizard/src/review/ReviewStep.tsx
  • frontend/src/components/SyncEditor/SyncEditor.css
  • frontend/packages/react-form-wizard/src/Wizard.tsx
  • frontend/src/components/SyncEditor/process.test.ts
  • frontend/mocks/@monaco-editor/react.tsx
  • frontend/packages/react-form-wizard/src/review/ReviewStepFilterList.tsx

Comment on lines +59 to +193
describe('SyncEditorDiff', () => {
beforeEach(() => {
jest.clearAllMocks()
mockUseResizeObserver.mockImplementation((_target, callback) => {
mockResizeCallback.mockImplementation(callback)
return {} as ResizeObserver
})
})

it('renders nothing when showChanges is false', () => {
renderSyncEditorDiff({ showChanges: false })
expect(screen.queryByRole('textbox', { name: /monaco-diff/i })).not.toBeInTheDocument()
})

it('renders nothing when defaultResources is undefined', () => {
renderSyncEditorDiff({ defaultResources: undefined })
expect(screen.queryByRole('textbox', { name: /monaco-diff/i })).not.toBeInTheDocument()
})

it('renders nothing when mock mode is enabled', () => {
renderSyncEditorDiff({ mock: true })
expect(screen.queryByRole('textbox', { name: /monaco-diff/i })).not.toBeInTheDocument()
})

it('mounts the diff editor and exposes imperative handle accessors', async () => {
const ref = createRef<SyncEditorDiffHandle>()
const { onDiffEditorInstanceChange, onActiveInstancesChange } = renderSyncEditorDiff({}, ref)

await waitFor(() => expect(screen.getByRole('textbox', { name: /monaco-diff/i })).toBeInTheDocument())

expect(onActiveInstancesChange).toHaveBeenCalled()
expect(onDiffEditorInstanceChange).toHaveBeenCalled()
expect(ref.current?.getDiffEditor()).not.toBeNull()
expect(ref.current?.getOriginalEditor()).not.toBeNull()
expect(ref.current?.getModifiedEditor()).not.toBeNull()
expect(ref.current?.getDiffEditorMonaco()).not.toBeNull()
})

it('invokes diff navigator previous and next from the imperative handle', async () => {
const ref = createRef<SyncEditorDiffHandle>()
renderSyncEditorDiff({}, ref)
await waitFor(() => expect(screen.getByRole('textbox', { name: /monaco-diff/i })).toBeInTheDocument())

expect(() => ref.current?.previous()).not.toThrow()
expect(() => ref.current?.next()).not.toThrow()

await act(async () => {
await new Promise((resolve) => requestAnimationFrame(resolve))
})
})

it('notifies onChange when the modified pane content changes', async () => {
const { onChange } = renderSyncEditorDiff()
const input = await waitFor(() => screen.getByRole('textbox', { name: /monaco-diff/i }))

fireEvent.change(input, { target: { value: 'apiVersion: v1\nkind: Pod\n' } })

await waitFor(() => expect(onChange).toHaveBeenCalled())
expect(onChange.mock.calls[0][0]).toContain('kind: Pod')
})

it('notifies focus changes when the diff editor gains and loses focus', async () => {
const { onDiffEditorFocusChange } = renderSyncEditorDiff()
const input = await waitFor(() => screen.getByRole('textbox', { name: /monaco-diff/i }))

fireEvent.focus(input)
expect(onDiffEditorFocusChange).toHaveBeenCalledWith(true)

fireEvent.blur(input)
await act(async () => {
await new Promise((resolve) => requestAnimationFrame(resolve))
})
expect(onDiffEditorFocusChange).toHaveBeenCalledWith(false)
})

it('does not report blur when focus moves to a diff toolbar control', async () => {
const { onDiffEditorFocusChange } = renderSyncEditorDiff()
const input = await waitFor(() => screen.getByRole('textbox', { name: /monaco-diff/i }))

fireEvent.focus(input)
onDiffEditorFocusChange.mockClear()

const toolbarButton = document.createElement('button')
toolbarButton.id = 'diff-prev-button'
document.body.appendChild(toolbarButton)
toolbarButton.focus()
fireEvent.blur(input)

await act(async () => {
await new Promise((resolve) => requestAnimationFrame(resolve))
})

expect(onDiffEditorFocusChange).not.toHaveBeenCalledWith(false)
toolbarButton.remove()
})

it('cleans up and notifies instance change when diff view is hidden', async () => {
const { onDiffEditorInstanceChange, onDiffEditorFocusChange, rerender, props } = renderSyncEditorDiff()

await waitFor(() => expect(screen.getByRole('textbox', { name: /monaco-diff/i })).toBeInTheDocument())
onDiffEditorInstanceChange.mockClear()
onDiffEditorFocusChange.mockClear()

rerender(<SyncEditorDiff {...props} showChanges={false} />)

expect(screen.queryByRole('textbox', { name: /monaco-diff/i })).not.toBeInTheDocument()
expect(onDiffEditorInstanceChange).toHaveBeenCalled()
expect(onDiffEditorFocusChange).toHaveBeenCalledWith(false)
})

it('applies layout when the resize observer fires', async () => {
renderSyncEditorDiff()
await waitFor(() => expect(screen.getByRole('textbox', { name: /monaco-diff/i })).toBeInTheDocument())

const host = document.querySelector('.sync-editor__diff-host') as HTMLDivElement
jest.spyOn(host, 'getBoundingClientRect').mockReturnValue({
width: 900,
height: 400,
x: 0,
y: 0,
top: 0,
left: 0,
right: 900,
bottom: 400,
toJSON: () => ({}),
})

await act(async () => {
mockResizeCallback()
await new Promise((resolve) => requestAnimationFrame(resolve))
})

expect(mockUseResizeObserver).toHaveBeenCalled()
})
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add a jest-axe accessibility assertion for SyncEditorDiff tests.

This component test suite is missing the required accessibility check.

As per coding guidelines: "Every component test must include an accessibility test with jest-axe: expect(await axe(container)).toHaveNoViolations()".

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

In `@frontend/src/components/SyncEditor/SyncEditorDiff.test.tsx` around lines 59 -
193, Add a jest-axe accessibility assertion to this test suite by rendering the
component via renderSyncEditorDiff and calling await axe(container) then
expect(...).toHaveNoViolations(); e.g., add a test (or extend an existing one
such as the "mounts the diff editor..." case) that obtains the rendered
container from renderSyncEditorDiff, awaits axe(container) and asserts
toHaveNoViolations(); ensure you reference the axe import and use await so the
accessibility check runs after the diff editor is mounted.

Comment on lines +114 to +115
fireEvent.change(input, { target: { value: 'apiVersion: v1\nkind: Pod\n' } })

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Replace fireEvent interactions with userEvent in this suite.

These interaction paths are implemented with fireEvent, which conflicts with the frontend test guideline and can under-represent real user behavior.

As per coding guidelines: "Use @testing-library/user-event for user interactions in tests — not fireEvent".

Also applies to: 124-127, 145-146

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

In `@frontend/src/components/SyncEditor/SyncEditorDiff.test.tsx` around lines 114
- 115, Tests in this suite use fireEvent.change for simulating typing, which
violates the guideline; import userEvent from '`@testing-library/user-event`' and
replace fireEvent.change(input, { target: { value: '...' } }) with the
equivalent user-facing calls (e.g., await userEvent.clear(input) then await
userEvent.type(input, 'apiVersion: v1\nkind: Pod\n') or await
userEvent.paste(input, '...') as appropriate), and update the test functions to
be async where needed; apply the same replacements for the other occurrences
around the suite (the lines referenced near 124-127 and 145-146) and remove the
fireEvent usage.

jeswanke added 2 commits June 5, 2026 16:30
…-33855-Wizard-Review-Page-Filter-to-just-show-differences-2

Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>
@jeswanke

jeswanke commented Jun 6, 2026

Copy link
Copy Markdown
Contributor Author

/hold

@fxiang1

fxiang1 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm label Jun 8, 2026

@KevinFCormier KevinFCormier left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for the updates @jeswanke. Much better. Couple things:

  1. Can you please take a look at the Sonar issues... there are a bunch of minor things that could be cleaned up.
  2. If you can fix the green background behind changes - sometimes when the form is narrow, the text extends past the green box.
Image

Signed-off-by: John Swanke <jswanke@redhat.com>
@openshift-ci openshift-ci Bot removed the lgtm label Jun 9, 2026
jeswanke added 2 commits June 9, 2026 14:56
Signed-off-by: John Swanke <jswanke@redhat.com>
Signed-off-by: John Swanke <jswanke@redhat.com>
@sonarqubecloud

sonarqubecloud Bot commented Jun 9, 2026

Copy link
Copy Markdown

@jeswanke jeswanke requested a review from KevinFCormier June 9, 2026 20:42
@openshift-ci

openshift-ci Bot commented Jun 9, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: fxiang1, jeswanke, KevinFCormier

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

The pull request process is described here

Details Needs approval from an approver in each of these files:
  • OWNERS [KevinFCormier,fxiang1,jeswanke]

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

@jeswanke jeswanke merged commit 2201615 into stolostron:main Jun 10, 2026
16 of 17 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jun 17, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants