-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Parse props in instMatchesObjectProps/instHasProperty for all instances #377
Conversation
Wow, quick turnaround! 👍 This definitely fixes what I would consider a bug. We do have to be careful though, because this could cause some unexpected failured by some people. For instance: Let's say I have a component:
Then, If I render some component:
At this point, am I right in assuming that prior to this change, I was kind of under the impression that it already worked this way... but if it didn't, this may blow up in some peoples' faces and cause unexpected test failures on update. |
I guess my example technically isn't true, since the branches between
Similarly: I might be okay with that considering the css selector maybe should sort of "opt in" to looking at only DOM nodes... but I'm really not sure here. Additional note. WIth this change, it seems like: |
Agreed! Awesome turn around!
I think this is a classic argument of correctness vs intuitiveness. Most developers using enzyme aren't going to look at docs until they absolutely need to. They'll just do what they assume should work. Thus the argument is that selectors should be intuitive. I would think we should maintain interactions like: @lelandrichardson are you sure your thoughts are fully right? I would assume some internal tests would break if that was the case... If not, In a different PR, we should have some simple tests to make sure the selectors all match up. |
This PR breaks a little bit of parity between const Root = ({ classProp }) => (
<div className={classProp}>
<MockLink to="/">First</MockLink>
<MockLink to="/second">Second</MockLink>
</div>
);
const wrapper = mount(
<Root classProp="yay" />
);
const wrapperr = shallow(
<Root classProp="yay" />
);
expect(wrapper.find({ classProp: 'yay' }).props()).to.eql(
wrapperr.find({ classProp: 'yay' }).props()
)
expect(wrapper.find({ className: 'yay' }).props()).to.eql(
wrapperr.find({ className: 'yay' }).props()
)
|
@nfcampos |
yes |
This isn't a bug with
This is the problem with putting too much trust into tests :) I'm pretty confident in the behavior i've assumed above, but we should definitely write some tests to make sure. Due to (mostly my) laziness, a lot of tests overly focus on traversing DOM nodes and not real composite components. Better tests could (should) certainly be written. |
So, to address the other broader issues. I think that
Is generally a good idea. I was surprised this change didn't break any existing tests. I'd like to keep the API easy to use and figure out how to make this a non-breaking change, but I think the current behavior is wrong. I think a big issue is that the test suite for edit: didn't see @lelandrichardson's comment above before posting that says essentially the same thing 👅
As your second comment suggets, Using If anything
|
@lelandrichardson I see. Then I guess this one shouldn't work... shallow(<div className='hey'><span>abc</span></div>).find({className: 'hey'}).length If the root node is not taken into account then that should return 0 instead of 1, no? |
@nfcampos that test will return
at the moment is pretty much the same as doing this:
Under the hood it isn't actually doing this, but it's not really far off. |
@lelandrichardson I see, makes sense, even if it is slightly surprising. |
I think special casing DOM nodes over composite components is probably not ideal, and at least should be documented if it's not already, but I think that's a different issue 😃 |
@nfcampos @aweary if you want to really understand the reason, it can be stated like this:
As a result, instead of making this an error case, we simply fall back to looking at I'm not sure if I consider this behavior wrong or less than ideal, but I do think that the fact that a large subset of our tests happen to test this case rather than the composite component case is the real problem. |
@lelandrichardson maybe we should open an issue to discuss expanding the test suite to cover composite components as that seems to be a superset of an issue we're seeing with this PR specifically. edit: #380 |
Here's where I'm at:
This is only a problem with mount. If we decide string-based selectors should look at composite nodes, it will work mostly as I originally intended for it to work, but will also likely break many existing tests. If we decide they should not look at composite nodes, string selectors will work more closely to how |
I think that string-based selections should behave like Making string-based selections act like |
const Foo = ({className}) => <div className={className}>abc</div>
mount(<Foo className='yay' />).find({className: 'yay'}) // 2 nodes That 2nd line returning 2 nodes is certainly never what anyone wants out of this API so that will always be surprising/frustrating. If we think it's worth it for that to return 2 so that you can find DOM nodes with |
In the case of |
My point with the API not being surprising/confusing is to avoid eg. this: const Foo = ({className}) => <div className={className}>abc</div>
const Bar = ({n}) => <div>
{[...Array(n-1)].map(() => <Foo className='yay' />)}
</div>
mount(<Bar n={2} />).find({className: 'yay'}).length // even though it returns 2 like I expected I only rendered one... |
@nfcampos I think looking at the output of <Bar n={2}>
<div>
<Foo className="yay">
<div className="yay">
abc
</div>
</Foo>
</div>
</Bar> If we special case string-based selectors then we'd expect |
@aweary but since the test passed you'd never even look at the output of |
I think the fact that it only returned props for DOM nodes is considered a bug
So just supporting composite components would just move the problem around. I can understand supporting methods that only check DOM nodes as some people might want to just assert values on the DOM. I'm not entirely sure it'd be useful to have a method that only checks composite props, but I think one big issue with that is it would likely break a lot of existing tests. Maybe we could discuss a different approach to allowing composite-only prop queries if there are use cases we want to support? Also, @lelandrichardson
I agree with that. If they're using syntax that they'd be using with |
@lelandrichardson summing up my position on your 3 points
|
@nfcampos @lelandrichardson @blainekasten I updated this PR so that the object syntax will query composite and DOM nodes, which the CSS selector queries will only match DOM nodes (the existing behavior). |
ping @nfcampos @lelandrichardson @blainekasten @ljharb Any more feedback on this? |
@aweary I'm still debating the right path on this. I'm going to try to get a minor release out tonight, and then the next release may be a breaking change with a couple that are queued up, and I might include this one in there (whether it's a breaking change or a bug fix is debatable, but it will definitely cause some tests to fail that currently pass... so we need to be conscious of that...) |
@aweary @lelandrichardson @nfcampos TLDR: How about
|
The linked issue is closed, and seems to be fixed in v3. Separately, mount has I'm going to close this, but can certainly reopen it if there's value and it can be rebased. |
Resolves #376
The current implementation just returns false if
isDOMComponent(inst)
is false. We can still check props on those instances by just passinginst
directly topropsOfNode
.