More intuitive API.
There is an open PR to add this API:
wrapper = shallowMount(ComponentWithChild)
expect(wrapper.find("child-component").exists()).toBe(true)
Which lets users do find("tag") rather than find({ name }) or find(Component).
There is some objection (see #692 and it's previous PR, #681 ). Here is my thoughts why I like this better than the existing APIs:
name API: ({ name: ... }) doesn't feel very intuitive. We allow querySelector like syntax for find, ({ name }) doesn't conform to this. Also, name is not always the same as the tag, and has nothing to do with what is actually rendered, which is what find is used to assert.
component API: find(Component) is okay, but I don't really like having to import every component I want to find to every test. It's just a bunch of boilerplate. It's easy enough to make shallowMount and mount global, in the same way describe is, but this is not an option for components.
The least amount of typing and reduced boilerplate is find({ name }), but I don't like this that much. If the name is different for the component (it shouldn't be, but it happens) I have to go and find the .vue file, and check the name. Then if someone else looks at the test, they will likely have the same thought (we are looking for ({ name: foo-component }), but actually this component only renders <bar-component>).
We can still continue to allow for { name: 'foo' } to be used, as well. I am not proposing to remove and existing feature, simply extend it.
I don't want to drag this out for too long, if people have too strong an opinion we can just drop it. That's my thoughts.
I think this is an intuitive way of finding a component, although I'd like to hear what other people think.
I have a new use case for this. When I stub an external dependency (at work we are using something called vue-flatpickr which wraps a javascript datepicker):
const wrapper = shallowMount(Foo, {
stubs: {
flatpickr: true
}
})
I cannot use { name: 'flatPickr' } to select the component (I guess the name is something else, no way to know). I could go and look into node_modules and see the correct name, but I don't want to look at some external dependency just to be able to assert it was rendered. For now we did
const wrapper = shallowMount(Foo, {
stubs: {
flatpickr: "<div id='flat' />"
}
})
and find("#flat"), which is more than I would like to type. I could use name by doing something like
const stub = name => ({ name, render: h => h("div" })
or something. We proposed this in an issue a while ago as a helper function, but it would nicer to use something like find('flatpickr-stub') which vue-test-utils makes for us.
This would also be useful for components like RouterLink that aren't exported by the library that adds them. Currently we include a RouterLinkStub to select a RouterLink, but I don't think this is intuitive:
import { RouterLinkStub } from '@vue/test-utils'
const wrapper = mount(TestComponent, {
stubs: {
RouterLink: RouterLinkStub
}
})
wrapper.find(RouterLinkStub)
If we selected by tag, you could do this:
const wrapper = mount(TestComponent)
wrapper.find('router-link')
Since the case you mentioned exists in only using mount(),
I think using CSS Selector is appropriate.
RouterLinkStub is another good use case.
@38elements I don't think using a css selector (in the case of RouterLink, it would be find("a")) is appropriate. You then need to know that the component uses <a href> internally - which means you are testing the internals of another component. It is no longer a contained unit test.
If <router-link> changes and uses <div> instead of <a> in a future version, then you test would fail. The objective of stubbing dependencies is so they can change their internals without impacting the public API.
@38elements I don't think using a css selector (in the case of RouterLink, it would be find("a")) is appropriate. You then need to know that the component uses
<a href>internally - which means you are testing the internals of another component. It is no longer a contained unit test.
If
<router-link>changes and uses<div>instead of<a>in a future version, then you test would fail. The objective of stubbing dependencies is so they can change their internals without impacting the public API.
Passing test is not purpose.
This is your subjective opinion and not reasonable.
The RouterLink example is the same with shallowMount or mount
I see.
I misunderstood.
I thought about the inner component which is not exported in other component.
It seems that the case only exists in only using the component provided by only plugin.
I do not think the libraries is many.
I do not think the example is very useful in using shallowMount().
I do not think it's a sufficient reason for adding this feature.
I think using stub is sufficient.
The PR for this has quite a few conflicts. I can update it, but it might be good to make a decision, be it to include this feature (then I'll need to add more tests) or to not include it, and close the PR, instead of just letting the PR sit forever.
I think we should implement this, and deprecate constructors as selectors.
There are a few benefits:
findI think existing the tag name is existing the component name.
It seems that only few people are interested about this feature.
I think searching by tag name is definitely more intuitive.
One thing I think we need to establish is which find APIs remain and which don't. Using constructors as selectors is the find(Foo) API, so we are left with
find({ name: 'foo' })find("my-component")This should simplify find a lot. The current PR regarding this issue has some groundwork, but if we are removing the constructor option, some existing code can be removed, and finding by tagName should be as simple as:
tagName for all children (we have a function that does something similar alreadywrapper.htmlThere is no constructor option in wrapper page.
https://vue-test-utils.vuejs.org/api/wrapper/
Passing a component matches against the constructor, for example wrapper.find(Foo).
@38elements the big benefit of using tag is to fix the problem of extended child components that will be introduced by this PR—https://github.com/vuejs/vue-test-utils/pull/840.
We shouldn't remove any code in the initial PR, but we could add warnings that the consturctor selector will be deprecated in 1.0.0.
@eddyerburgh
There is the name selector.
I think using name selector is resolved.
There is no constructor option in below selector page.
https://vue-test-utils.vuejs.org/api/#selectors
I think there is no term called "constructor option" in Vue Test Utils.
When I say constructor selector, I mean component selector.
I commented to this.
https://github.com/vuejs/vue-test-utils/issues/695#issuecomment-408577791
@eddyerburgh
If many people need this feature, I think this feature is necessary.
Since you are a maintainer of Vue Test Utils, you can add feature to Vue Test Utils without my agreement.
I'd like to work on this, once we decide it is going to be included!
Yes please start working on it. I'd like to release it at the same time as I merge #840
I am very sorry.
I lost interest this issue.
Would you please ignore my opinion in this issue.
I'm closing this because this feature would be too complex to implement. We'll continue with the current selector API instead
Most helpful comment
I think this is an intuitive way of finding a component, although I'd like to hear what other people think.