Skip to content

fix(RHOAIENG-57510): store raw input value in MultiSelection isCreatable option name#7198

Merged
openshift-merge-bot[bot] merged 2 commits intoopendatahub-io:mainfrom
dpanshug:rhoaieng-57510-fix-multiselection-creatable
Apr 15, 2026
Merged

fix(RHOAIENG-57510): store raw input value in MultiSelection isCreatable option name#7198
openshift-merge-bot[bot] merged 2 commits intoopendatahub-io:mainfrom
dpanshug:rhoaieng-57510-fix-multiselection-creatable

Conversation

@dpanshug
Copy link
Copy Markdown
Contributor

@dpanshug dpanshug commented Apr 13, 2026

https://redhat.atlassian.net/browse/RHOAIENG-57510

Description

The createOption was storing the createOptionMessage display text (e.g. Define new group: "foo") as the option name instead of the raw input value, causing the duplicate check to fail on subsequent lookups. Separate the display text into createOptionDisplayName, used only for dropdown rendering, and remove the now-unnecessary prefix-stripping workaround in GroupSettings.

@Griffin-Sullivan i have fixed directly the main component, rather than your proposed solution in JIRA. This benefits all current and future consumers of this component

Fix in Create subscription form

Screen.Recording.2026-04-13.at.2.56.15.PM.mov

Fix in User Management page

Screen.Recording.2026-04-13.at.2.51.43.PM.mov

How Has This Been Tested?

  1. Navigate to Subscriptions → Create subscription
  2. In the Groups multiselect, type a new group name (e.g., test) and select the create option
  3. Verify the dropdown shows Add group "test" and the selected chip shows test
  4. Remove the chip, then type test again
  5. Verify only one Add group "test" entry appears (no duplicates)

Test Impact

None

Request review criteria:

Self checklist (all need to be checked):

  • The developer has manually tested the changes and verified that the changes work
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has added tests or explained why testing cannot be added (unit or cypress tests for related changes)
  • The code follows our Best Practices (React coding standards, PatternFly usage, performance considerations)

If you have UI changes:

  • Included any necessary screenshots or gifs if it was a UI change.
  • Included tags to the UX team if it was a UI/UX change.

After the PR is posted & before it merges:

  • The developer has tested their solution on a cluster by using the image produced by the PR to main

Summary by CodeRabbit

  • Bug Fixes

    • Fixed create-option display so the rendered label shows correctly in multi-selection and corrected the create-option test identifier.
  • Refactor

    • Simplified group-creation messaging and normalized how the created group's name is stored.
  • Tests

    • Updated an end-to-end test to use the revised option label in the selection flow.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 7010592a-c3bf-4fa0-97a5-e6c7065f633c

📥 Commits

Reviewing files that changed from the base of the PR and between 3a742c5 and e481c85.

📒 Files selected for processing (3)
  • frontend/src/components/MultiSelection.tsx
  • frontend/src/pages/groupSettings/GroupSettings.tsx
  • packages/cypress/cypress/tests/mocked/connectionTypes/createConnectionType.cy.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/cypress/cypress/tests/mocked/connectionTypes/createConnectionType.cy.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/pages/groupSettings/GroupSettings.tsx
  • frontend/src/components/MultiSelection.tsx

📝 Walkthrough

Walkthrough

MultiSelection.tsx now always sets createOption.name to the trimmed input value and introduces a memoized createOptionDisplayName that uses createOptionMessage to render the visible label. The UI was updated to render createOptionDisplayName for create options and corrected a data-testid reference. GroupSettings.tsx removed the CREATE_PREFIX-based detection and now always uses opt.name when constructing GroupStatus.name. A Cypress test updated the multi-group selection label from "Option" to "New-category".

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Issues

CWE-20: Improper Input Validation — Removing the CREATE_PREFIX detection and storing only the trimmed input in createOption.name eliminates the prior in-band marker distinguishing newly created options from existing ones. This can cause silent misclassification of option origin, leading to incorrect persistence or bypassing creation-specific validation logic.

Missing state discriminator — The change decouples display formatting from the canonical option value without introducing explicit metadata (flag/type) to convey "created" vs "existing". Relying solely on opt.name risks inconsistent interpretation across components.

Actionable steps

  1. Reintroduce an explicit discriminator for created options: either restore a stable prefix/marker in the option value or, preferably, attach metadata (e.g., isNew: true or origin: 'created' | 'existing') to the option object propagated to GroupSettings.
  2. Add runtime validation in processGroup to assert expected structure/metadata before using opt.name as GroupStatus.name; fail-fast on missing discriminator.
  3. Add integration tests covering selection vs creation flows to ensure created groups are identified, stored with the intended canonical name, and existing groups are not misclassified.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: storing the raw input value (not the formatted display text) as the option name in MultiSelection's creatable feature.
Description check ✅ Passed The description includes the issue reference, clear explanation of the bug and fix, testing steps with expected outcomes, and all required self-checklist items marked complete.
Linked Issues check ✅ Passed PR correctly references RHOAIENG-57510 in both title and description with a valid issue link (redhat.atlassian.net/browse/RHOAIENG-57510).
Out of Scope Changes check ✅ Passed All changes directly address the stated bug: MultiSelection.tsx refactoring (core fix), GroupSettings.tsx workaround removal, and Cypress test alignment. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

Copy link
Copy Markdown
Contributor

@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)
frontend/src/components/MultiSelection.tsx (2)

137-161: Add regression coverage for the raw-name/display-label split.

This branch changes persisted selection semantics, not just dropdown text. Add a test for: create a new option, verify the chip stores the raw value, remove it, type the same value again, and verify only one create row is offered.

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

In `@frontend/src/components/MultiSelection.tsx` around lines 137 - 161, The test
suite needs a regression test for the raw-name vs display-label creation flow:
write a test that mounts the MultiSelection component (using the same props that
enable isCreatable and supply createOptionMessage), type a new value into
inputValue to trigger createOption, confirm selecting it adds a chip whose
stored value equals the raw input (not the display label), remove that chip,
type the exact same raw value again and assert that only one create row is
offered (i.e., createOption is present once and no duplicate rows exist). Use
component identifiers tied to the MultiSelection props/state (inputValue,
isCreatable, createOption, createOptionMessage, and allValues) to drive
interactions and assertions.

154-161: Remove React.useMemo around createOptionDisplayName and compute the string inline.

Deriving a short display string from current props is trivial enough that memoization adds overhead without benefit. React 19's official guidance and compiler-based optimization handle expensive derivations automatically; manual memoization here violates the coding guideline: "avoid unnecessary useCallback/useMemo/useRef — React is performant by default."

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

In `@frontend/src/components/MultiSelection.tsx` around lines 154 - 161, Remove
the React.useMemo wrapper around createOptionDisplayName and compute the display
string inline (use the values createOption and createOptionMessage directly
where createOptionDisplayName is referenced); replace the memoized constant
createOptionDisplayName with a simple conditional expression that returns
undefined if !createOption, otherwise returns typeof createOptionMessage ===
'string' ? createOptionMessage : createOptionMessage(createOption.name), and
remove the dependency array since memoization is being eliminated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/pages/groupSettings/GroupSettings.tsx`:
- Around line 45-48: The processGroup function is writing opt.name back
unchanged which preserves legacy creatable labels like 'Define new group:
"foo"'; update processGroup (SelectionOptions -> GroupStatus) to normalize
opt.name before returning: detect the legacy pattern (e.g. /^Define new
group:\s*"?(.+?)"?$/) and extract the inner label to use as name, otherwise fall
back to opt.name (or opt.label if appropriate), keeping id as String(opt.id) and
enabled from opt.selected; this ensures old persisted display labels are cleaned
on write while still handling normal options.

---

Nitpick comments:
In `@frontend/src/components/MultiSelection.tsx`:
- Around line 137-161: The test suite needs a regression test for the raw-name
vs display-label creation flow: write a test that mounts the MultiSelection
component (using the same props that enable isCreatable and supply
createOptionMessage), type a new value into inputValue to trigger createOption,
confirm selecting it adds a chip whose stored value equals the raw input (not
the display label), remove that chip, type the exact same raw value again and
assert that only one create row is offered (i.e., createOption is present once
and no duplicate rows exist). Use component identifiers tied to the
MultiSelection props/state (inputValue, isCreatable, createOption,
createOptionMessage, and allValues) to drive interactions and assertions.
- Around line 154-161: Remove the React.useMemo wrapper around
createOptionDisplayName and compute the display string inline (use the values
createOption and createOptionMessage directly where createOptionDisplayName is
referenced); replace the memoized constant createOptionDisplayName with a simple
conditional expression that returns undefined if !createOption, otherwise
returns typeof createOptionMessage === 'string' ? createOptionMessage :
createOptionMessage(createOption.name), and remove the dependency array since
memoization is being eliminated.
🪄 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: Repository YAML (base), Central YAML (inherited), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: bcd2de3d-adcb-415a-a821-bf1912473125

📥 Commits

Reviewing files that changed from the base of the PR and between 00510fe and 3a742c5.

📒 Files selected for processing (2)
  • frontend/src/components/MultiSelection.tsx
  • frontend/src/pages/groupSettings/GroupSettings.tsx

Comment thread frontend/src/pages/groupSettings/GroupSettings.tsx
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 13, 2026

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 63.64%. Comparing base (596b3ea) to head (e481c85).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
frontend/src/components/MultiSelection.tsx 83.33% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #7198      +/-   ##
==========================================
- Coverage   64.81%   63.64%   -1.18%     
==========================================
  Files        2441     2502      +61     
  Lines       75996    77594    +1598     
  Branches    19158    19717     +559     
==========================================
+ Hits        49257    49382     +125     
- Misses      26739    28212    +1473     
Files with missing lines Coverage Δ
frontend/src/pages/groupSettings/GroupSettings.tsx 96.55% <100.00%> (-0.23%) ⬇️
frontend/src/components/MultiSelection.tsx 79.39% <83.33%> (+0.38%) ⬆️

... and 71 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 596b3ea...e481c85. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…ble option name

The createOption was storing the createOptionMessage display text
(e.g. `Define new group: "foo"`) as the option name instead of the
raw input value, causing the duplicate check to fail on subsequent
lookups. Separate the display text into createOptionDisplayName, used
only for dropdown rendering, and remove the now-unnecessary
prefix-stripping workaround in GroupSettings.

Also fixes a typo where `Option.name` referenced the global
constructor instead of `createOption.name`.
The previous code had a typo (Option.name instead of createOption.name)
that made the create option data-testid always resolve to "Option".
Update the test selector to match the corrected test ID.

Also remove unnecessary useMemo around createOptionDisplayName.
@dpanshug dpanshug force-pushed the rhoaieng-57510-fix-multiselection-creatable branch from 2bc14de to e481c85 Compare April 15, 2026 07:57
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Apr 15, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: Griffin-Sullivan

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

The pull request process is described here

Details Needs approval from an approver in each of these files:

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

@openshift-merge-bot openshift-merge-bot Bot merged commit abd09cb into opendatahub-io:main Apr 15, 2026
53 checks passed
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.

2 participants