-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
fix(Search): fix event passed to onChange
when clearing input (#12133)
#12140
fix(Search): fix event passed to onChange
when clearing input (#12133)
#12140
Conversation
…on-design-system#12133) * fix(Search): when clearing, pass a pseudo input change event instead of the mouse click event with which the internal event handler is called.
DCO Assistant Lite bot All contributors have signed the DCO. |
✅ Deploy Preview for carbon-components-react ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify site settings. |
I have read the DCO document and I hereby sign the DCO. |
✅ Deploy Preview for carbon-elements ready!
To edit notification comments on pull requests, go to your Netlify site settings. |
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 for noticing this and putting up a PR! This is a quite old snippet of code - 5+ years at this point. I think the original intent of this code was probably to replace the existing event.target.value
with an empty string.
function clearInput(event) {
if (!value) {
inputRef.current.value = '';
onChange(event);
} else {
- const clearedEvt = Object.assign({}, event.target, {
+ const clearedEvt = Object.assign({}, event, {
target: {
value: '',
},
});
onChange(clearedEvt);
}
onClear();
setHasContent(false);
focus(inputRef);
}
This would be the smallest change to rectify the root issue and I think the least likely to introduce a breaking change. I'd prefer not to change the signature and call structure if possible, or at least as little as possible, as these could inadvertently break folks who have relied on this since v8/v9.
let wrapper; | ||
|
||
// const container = () => wrapper.find(`.${prefix}--search`); | ||
const button = () => wrapper.find('button'); | ||
const input = () => wrapper.find('input'); | ||
// const label = () => wrapper.find('label'); | ||
|
||
const render = (props) => { | ||
if (wrapper) { | ||
return wrapper.setProps(props); | ||
} | ||
|
||
wrapper = mount(<Search labelText="testlabel" {...props} />); | ||
|
||
return wrapper; | ||
}; | ||
|
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.
Should this be in a beforeEach
or beforeAll
?
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.
It could be a beforeAll
, but that would only be doing the same thing as this but with less clarity: the functions would need to be declared as let
variables and then assigned in the before
routine.
This code solves for an issue that I see a lot with front-end tests and which I see with the tests in this suite: if you render the element under test in a beforeEach
routine, then it makes any other setup in nested contexts very difficult. You end up with multiple renders of the element.
In fact, I believe that some of the tests in this suite are finding the wrong element rendered.
If you move the mounting or rendering into each test/it
, then you avoid this issue.
To avoid duplicating the possibly complex mount/render declaration, I have adopted this paradigm which works quite well in my experience.
Each nested context/describe can build on the props:
- default: props reset
- with size large: props.large = true
- with size small: props.small = true
- with onChange: props.onChange = jest.fn();
- etc.
Each test simply becomes
render(props);
expect(...);
@tay1orjones The actual culprit is the first if (!value) {
inputRef.current.value = '';
onChange(event);
} This clears the input's value, but it sends the
Additionally, the else {
const clearedEvt = Object.assign({}, event.target, {
target: {
value: '',
},
});
onChange(clearedEvt);
}
In both cases from this Alternatively, this could be: if (!value) {
inputRef.current.value = '';
}
const inputTarget = Object.assign({}, inputRef.current, { value: '' });
const clearedEvt = { target: inputTarget, type: 'change' }; |
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.
That makes sense, thanks!
the mouse click event with which the internal event handler is called.
Closes #12133
When the close button is clicked, the internal event handler is called with the mouse click event.
Previously, the
onChange
prop was called with this event or a modified version. However, that event callback normally expects an input change event.This fixes the issue by creating and sending a pseudo input change event to the
onChange
prop.Changelog
Changed
Search
:onChange
is called with proper data shape when clearing inputTesting / Reviewing