-
Notifications
You must be signed in to change notification settings - Fork 1k
Fixes #38842 - Replace FormControl with TextInput for InputFactory #10729
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #38842 - Replace FormControl with TextInput for InputFactory #10729
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR replaces the legacy FormControl component from patternfly-react with the modern TextInput component from @patternfly/react-core in the InputFactory component. The change modernizes the component while maintaining backwards compatibility for custom registered input components.
Key Changes:
- Replaced
FormControlwithTextInputas the default fallback component - Updated prop mapping to use PatternFly 4 conventions (
isDisabled,isRequired) - Migrated tests from snapshot-based to behavior-based testing with React Testing Library
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
InputFactory.js |
Replaced FormControl with TextInput, updated prop handling and onChange signature |
InputFactory.test.js |
Replaced snapshot tests with comprehensive behavior-based tests using React Testing Library |
InputFactory.test.js.snap |
Removed snapshot file as tests no longer use snapshots |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| isDisabled={disabled} | ||
| isRequired={required} | ||
| className={className} | ||
| onChange={(_event, value) => onChange(value)} |
Copilot
AI
Oct 21, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The onChange handler should check if onChange exists before calling it. While defaultProps defines onChange as noop, if a parent component explicitly passes undefined or null, this will throw a runtime error.
| onChange={(_event, value) => onChange(value)} | |
| onChange={(_event, value) => typeof onChange === 'function' && onChange(value)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a lint and tests fix, also
I've tried to make this backwards compatible, but please verify if it's enough.
Could you please share where its used?
| it('should render MemoryAllocationInput for type="memory"', () => { | ||
| render(<InputFactory type="memory" name="test" id="test-memory" />); | ||
| expect(screen.getByRole('spinbutton')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('should render CounterInput for type="counter"', () => { | ||
| render(<InputFactory type="counter" name="test" id="test-counter" />); | ||
| expect(screen.getByRole('spinbutton')).toBeInTheDocument(); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These test the same output
| it('should pass setError and setWarning to custom components', () => { | ||
| const setError = jest.fn(); | ||
| const setWarning = jest.fn(); | ||
|
|
||
| render( | ||
| <InputFactory | ||
| {...selectProps} | ||
| setError={setError} | ||
| setWarning={setWarning} | ||
| /> | ||
| ); | ||
|
|
||
| expect(screen.getByText('Grouped select')).toBeInTheDocument(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does it test it?
| type={type} | ||
| {...validations} | ||
| {...controlProps} | ||
| <TextInput |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got this error when rendering it: Text input: Text input requires either an id or aria-label to be specified Error Component Stack
|
This PR has a target version set to 3.17, so we'd likely want to cherry-pick it to 3.17-stable |
|
Thanks, I dont think we have to have it in 3.17 |
f682ebb to
283bfec
Compare
ofedoren
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @MariaAga, updated.
Could you please share where its used?
IIUC, currently the whole InputFactory is used only for FormField, which also seems to be used only in foreman_webhooks. I think potentially we can just drop both 🤷
Anyway, InputFactory's fallback (TextInput now) seems to be used in foreman_webhooks ForemanFormikField (https://github.com/theforeman/foreman_webhooks/blob/master/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/ForemanFormikField.js#L108), but the actual content will still be custom. I've checked if webhook forms still work with these changes and it seems so, but given how UI sometimes weird to me, I'd ask to re-test that.
283bfec to
badbc33
Compare
badbc33 to
64280f8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| onChange={(_event, val) => onChange(val)} | ||
| validated={validated} | ||
| ouiaId={`input-factory-text-input-${id}`} | ||
| aria-label={`text-input-${id}`} |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The aria-label will produce invalid values like "text-input-null" or "text-input-undefined" when id is null or undefined. Based on the FormField test snapshots, id can indeed be null.
Consider making aria-label conditional or providing a fallback:
aria-label={id ? `text-input-${id}` : 'text-input'}Alternatively, only include aria-label when id is provided, or use a more descriptive fallback based on the input's purpose.
| aria-label={`text-input-${id}`} | |
| aria-label={id ? `text-input-${id}` : 'text-input'} |
| className={className} | ||
| onChange={(_event, val) => onChange(val)} | ||
| validated={validated} | ||
| ouiaId={`input-factory-text-input-${id}`} |
Copilot
AI
Nov 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ouiaId will produce invalid values like "input-factory-text-input-null" or "input-factory-text-input-undefined" when id is null or undefined. Based on the FormField test snapshots, id can indeed be null.
Consider making ouiaId conditional:
ouiaId={id ? `input-factory-text-input-${id}` : undefined}OUIA IDs should be meaningful identifiers; having null or undefined in them defeats their purpose.
| ouiaId={`input-factory-text-input-${id}`} | |
| ouiaId={id ? `input-factory-text-input-${id}` : undefined} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
| "useKeyShortcuts": false, | ||
| } | ||
| } | ||
| id={null} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why these are null ? Don't we need to remove this file altogether ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are null, because they are not being provided via fixtures props. Some fixtures do provide them though, see below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The snap files are preventing testing. Please remove them. [/FormField.test.js.snap](https://github.com/theforeman/foreman/pull/10729/files#diff-78eb07ad74cba7f7b5be93c011a04c294006aa76157dd671f22fcd2794901981) is needed to be connected with the input
ofedoren
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The snap files are preventing testing.
How exactly? I've removed the snap which is directly related to the component I'm changing, since that snap is now covered by react-test lib tests.
I can't just remove snap for FormField component, since I don't almost change it nor re-writing into PF5 nor I change the test suite from snap-based into react-test-based. That's kinda out of scope for this PR.
| "useKeyShortcuts": false, | ||
| } | ||
| } | ||
| id={null} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are null, because they are not being provided via fixtures props. Some fixtures do provide them though, see below.
MariaAga
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont think its used anywhere, anyway I tested it with packit to make sure in webhooks that use InputFactory and report generate that also uses it for the date.
I replaced a place where text_f was used with react_form_input(nil, f, attr, options) and it works well on new and edit.
The only issue, that might be out of the scope of the PR as this was a bug before as well :
Warning: `value` prop on `input` should not be null. Consider using an empty string to clear the component or `undefined` for uncontrolled components.
|
Yeah, I'm afraid that bug is not related to this PR or should be dealt with in since here we pass what's provided and if |
MariaAga
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I opened https://issues.redhat.com/browse/SAT-40642 to track it
InputFactoryseems to be used byFormField(which is not commonly used and probably will have adjustments or removal) and byTags::ReactInputviareact_form_input.react_form_inputseems to cover any usages by either passing registered component name (such asautocomplete) or using a component directly instead of usingInputFactory(such astextarea).Given that I think we don't even need a fallback component, which previously was a simple
inputwrapped withFormControl. But to replace it, I went withTextInputsince it's quite general component, even though not as flexible asinputwithtype={type}.I've tried to make this backwards compatible, but please verify if it's enough. Also, tried to replace snap tests with normal ones, but not sure if they are enough as well.