-
Notifications
You must be signed in to change notification settings - Fork 4k
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
chore(warnings): Fix warnings in Form and Modal #626
Conversation
Current coverage is 100% (diff: 100%)@@ master #626 diff @@
====================================
Files 119 119
Lines 1881 1884 +3
Methods 0 0
Messages 0 0
Branches 0 0
====================================
+ Hits 1881 1884 +3
Misses 0 0
Partials 0 0
|
Note, I added tests for |
const portalProps = _.pick(rest, _.keys(Portal.propTypes)) | ||
|
||
// Remove portal-handled props from 'rest' and pass them through to Portal | ||
const portalProps = _.reduce(rest, (memo, value, key) => { |
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.
Just a suggestion here. This adds another loop, but is a little clearer (at least to my eyes) and does not mutate any objects:
const unhandled = getUnhandledProps(Modal, this.props)
const portalPropKeys = _.keys(Portal.propTypes)
const portalProps = _.pick(unhandled, portalPropKeys)
const rest = _.omit(unhandled, portalPropKeys)
@@ -62,4 +63,23 @@ describe('Input', () => { | |||
}) | |||
}) | |||
}) | |||
|
|||
describe('onChange', () => { | |||
it('handles onChange', () => { |
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.
This should be covered by the conformance test for events. It runs every component through every event handler and asserts that it was called, and was called with the appropriate event shape as the first arg.
// React gives a warning if no onChange is given to a controlled input. We | ||
// handle the onChange on the wrapping element, so we don't actually need | ||
// onChange on the input itself but let's pass a noop to suppress the warning. | ||
onChange: _.noop, |
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.
Perhaps we instead add onChange
to the htmlInputPropNames
? This way, it is applied to the correct place and suppresses the warning only when it should be suppressed (user passed value/onChange). My concern is that we're swallowing the warning. If the user adds <Input value='' />
, they should see the warning but they won't with the current change here.
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, although adding it to the htmlInputPropNames
actually causes it to be called twice. I think we need to do a similar thing here as the portalProps
, where any prop we pass through to the input isn't included in the rest
. e.g.
// Currently:
const rest = getUnhandledProps(Input, props)
const inputProps = _.pick(props, htmlInputPropNames)
// Change to:
const unhandled = getUnhandledProps(Input, props)
const htmlInputProps = _.pick(unhandled, htmlInputPropNames)
const rest = _.omit(unhandled, htmlInputPropNames)
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 think that is true? Just make sure all the examples work/look how they should. SUI relies partially on the classNames and partially on the input props to do what it does for the Input component.
There are gonna be some exceptions for things like disabled
, which adds opacity to the input. It can't be both a class and an attribute or it is doubly transparent. Also, readOnly
I believe must be on the input to prevent entries, but not required as a className.
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.
Actually, this causes the handles events transparently
test to fail. I think that test tries to call the event (onChange
in this case) on the top-level component (the Input
in this case). Since the onChange
is now actually being passed as a prop to the htmlInput
, it's not being called when simulated on the Input
.
Thoughts on how to handle this? I agree it would be better to not suppress the warning, so ideally we can improve the test, assuming I'm understanding the issue correctly.
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.
Ugh, yep. That test is a little to naive. We could teach it where to put the handler (pass an argument somehow), but that would be pretty ugly I think.
I'll give this more thought and see what I can come up with.
@@ -104,6 +104,12 @@ describe('Modal', () => { | |||
shallow(<Modal open={false} />) | |||
.find('Portal') | |||
.should.have.prop('open', false) | |||
|
|||
// Does not pass this prop to the portal child |
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.
Suggest pulling this into it's own it()
block to keep assertions isolated.
272d869
to
6a1ea38
Compare
Regarding my comment about the "handles events transparently" above, I updated the test slightly to account for this situation. I think it makes sense but let me know if not. The idea behind the test (imho) is to ensure that if a user passes an event handler as a prop to the top-level component it is fired when that event takes place within that component. In this case, we're binding the event to a more appropriate sub-component that is the only element that will actually cause the event to be fired in an actual browser. So this test now is able to simulate a more real-world scenario. The only negative is that within other tests if you did Thoughts? |
@@ -295,7 +298,7 @@ export const isConformant = (Component, options = {}) => { | |||
// ^ was not called on "blur" | |||
const leftPad = ' '.repeat(constructorName.length + listenerName.length + 3) | |||
|
|||
handlerSpy.called.should.equal(true, | |||
handlerSpy.calledOnce.should.equal(true, | |||
`<${constructorName} ${listenerName}={${handlerName}} />\n` + | |||
`${leftPad} ^ was not called on "${eventName}".` + |
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.
Update required: "was not called on once"
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.
Fixed 👍
Test changes look good to me! I think if someone is writing tests for a component, they should be responsible for I added one last request to update the event assertion error to match the updated |
6a1ea38
to
1f3eebe
Compare
Looks good, will merge on pass |
Fixes warnings in two of the components referenced here: #599