-
Notifications
You must be signed in to change notification settings - Fork 668
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
Design / Roadmap #1
Comments
The main question for me is should the test utils use a wrapper API, augmented API or simple API? Wrapper API const wrapper = mount(Component)
// Access vm
wrapper.vm.someMethod()
// Helper methods
wrapper.find('div') Augmented API const augmentedVm = mount(Component)
// Access vm
augmentedVm.someMethod()
// Helper methods
augmentedVm.$find('div') Simple API // Access vm
getMountedVm(Component)
// Helper methods
findElement('div', Component) avoriaz uses the wrapper API. Personally I think it's the best API for this library - it avoids possible collisions that can occur with the augmented API and produces readable and chainable code. What are people thoughts? |
@eddyerburgh I prefer wrapper. Simple API can be tedious to import all the methods. |
Thank @eddyerburgh 's great library! I have read avoriaz' doc and it is well done. Another field worth testing is the events a component emits. For example, a custom input component will likely emit an It is reasonable for a user to expect utility for testing custom event in the standard toolkit. |
@HerringtonDarkholme Good idea. What would the API look like for that? On another note. If we add a A container class could default to the first item: // Array
wrapper.find('div')[0].dispatch('click')
// Container
wrapper.find('div').dispatch('click') And throw an error message if no element is found: // Array
wrapper.find('div')[0].is('div') // throws Uncaught TypeError: Cannot read property 'is' of undefined
// Container
wrapper.find('div').is('div') // throws Error, no element matching tag div was found The downside to a container is it needs a custom API to access wrappers at different indices. // Array
wrapper.find('div')[1].is('div')
// Container
wrapper.find('div').at(1).is('div') @pearofducks suggested having two find methods:
What do people think? |
@eddyerburgh can't the returned wrapper behave like jQuery collections? They have methods but are somewhat array-like (can be accessed via indices and even have iteration methods). That said, |
@eddyerburgh call me old school, but I still feel that jQuery is the most convenient dom traversal library. For That means, any predicate or method is applied on all elements in the collection. If the user want one specific element to test they can simply use What do you think? |
@yyx990803 Yes, it could return an object with properties 0,1,2 etc. But you will get type errors if a wrapper doesn't exist at an index: wrapper.find('div')[3].find('p') // throws Uncaught TypeError: Cannot read property 'is' of undefined If we used a method like wrapper.find('div').at(3).find('p') // throws No div tag exists at index 3 It would be nice to throw as many custom error messages as possible. But I'm not sure if it justifies having a more complicated API. @HerringtonDarkholme I hadn't considered treating the wrapper like that, but it could definitely work. We should go with an API that's most natural for users. I think a lot of users will be familiar with the jQuery API, so maybe we should use a similar one as you suggest. |
I get the feeling I'm the only person who doesn't do a lot of DOM traversal in their Unit Tests! Most of my tests focus around the output of computed properties and methods using different data/prop values. I would leave checking the html layout of my page down to integration testing. Is this not how people test their Vue components? Personally this is where I feel the wrapper API adds one-too-many layers between the user and the code-under-test. Is there some way we could either integrate or separate these two areas? On top of the above list (which is all very sensible stuff) I would add the following to my wishlist:
I like the idea of just rendering to the virtual dom (but it still be explorable). But would this cause issues with components that do |
@jackmellis This is interesting. Add ability to mock/inject methods, vuex store & lifecycle hooks to my wishlist. |
@eddyerburgh yeah, I think a jQuery-like-object would be natural for most users, but you make a good point about @jackmellis good points - with the wrapper API you still have access to the actual |
I've made a draft API to get some ideas down - https://github.com/eddyerburgh/vue-test-utils-proposal/blob/master/API.md |
@eddyerburgh Great! I like the consistency of I have several questions:
|
@jackmellis I actually like to do unit tests with rendering. Tools like Jest that support a snapshot feature are great for checking the output. @eddyerburgh when mentioning jQuery, a thing that I felt was most useful and a big win for jquerys popularity is sizzle. What about leveraging sizzle for finding so people can so things like API: |
Regarding It's always hard to make the right call on this kind of things. For one, it would probably fit a lot of cases that it automatically updates but sometimes it's maybe desired to not update for some reason, then it would help to have it manually. So if the workflow would look like this:
I would prefer it as it leaves all control up to the user and while testing code, the more control you have over things the better. |
I want also to note that A |
Yes so wouldn't the updating of props require you to wait for the next tick anyway? To me this implies manually calling update is not necessary, as long as you somehow wait for the async updates to occurr. Otherwise, would you expect |
re: update: In avoriaz we force render the function by updating it with a re rendered vm. function update(vm) {
vm._update(vm._render());
} This might be a naive way of doing so. Perhaps someone with better knowledge of Vue core could advise. @codebryo Agreed, it would be great to use sizzle. I tried to implement with avoriaz, but couldn't think of a way to make it work with vNodes and components. Although I'm sure there is a way to use it. |
I noticed the async-ness issue. In Vue's own unit tests, I want to ensure the exact same behavior with user code, so we preserved the async-ness in tests. But for userland component testing, especially unit-testing, I think having to deal with the async-ness would be more of a annoyance. Vue used to have a global config option @codebryo can you give an example of a case where you don't want the component to update after changing props? |
#shallow - Default depth can be 1 but it should be configurable. |
@eddyerburgh I actually did not test sizzle with vNodes yet, but I am sure it should be doable somehow :D. Maybe it's a thing for later though. When the container supports all major things it's not so critical. @yyx990803 a crazy example I saw when reviewing a clients work: (Sorry I can't share the code)
Well, that code is arguable not great, but it was a case that heavily relied on the async update behavior. As that is probably a very special case and if everyone feels autoupdating of the html is the exptected behavior it's good as well :) |
Okay so the Vuenit library has some mocking utilities for Vuex and Vue-Router. I've spent some time extracting them into standalone packages so they can be library-agnostic. Can they be integrated into vue-test-utils? https://github.com/jackmellis/mock-vue-router |
@codebryo if that's not a common case it should be trivial to just temporarily turn async on during specific tests. @jackmellis that's great - although I'm wondering what's preventing your from injecting a real router/store created during the test? |
@yyx990803 In my experience, I've spent too much time trying to set up vuex and vue-router when setting up my component, when really i don't need 90% its functionality. The mock libraries came out of me writing many many tests that required too much setup to get working and thinking 'I wish I just had a dummy $router object available' |
having to write @HerringtonDarkholme About the Good job on the api draft 👍 Edit: What do you think of adding an expect(wrapped.find('.foo')).to.exist()
// or
wrappend.find('.foo').should.exist() You probably know https://github.com/nathanboktae/chai-dom/, that's where I got the idea from |
@posva Although a chai plugin should be a separate project in my opinion. // with vue-test-utils
wrapper.find('div').exists() // returns true
// with vue-test-utils-chai-plugin
expect(wrapped.find('.foo')).to.exist() |
@jackmellis I can't follow 100% on the store. Mocking is usually quite easy to do for the functions you wanne test ,and if you want to include certain functionality (like a vue component working with a Vuex store) it's nice that it works when needed. For the $router though I can see a lot of value in the generally mocked version. @posva @eddyerburgh Do you think when using the container and find methods, that something to generally trigger interactions would be helpful?
|
@eddyerburgh I have actually mistaken dispatch in this case for the Vue - Vuex communication (what does not make sense at this point) or the already deprecated // list to touch events on mobile
trigger('touch')
// trigger potential more complex events
trigger('keyPress', 'e') So considering dispatch is mostly in use to fire actions in the Vuex store it kind of feels weird to combine it with elements logic. |
@yyx990803 @eddyerburgh Glad to see this kicked off! I've been away for the US holiday weekend, but have (just a few :) thoughts to add: IMO, I don't think we should shy away from rendering to a real DOM, particularly since there are implementations like JSDOM that are pretty lightweight. My thinking is that if someone wants to traverse the DOM to test if it rendered correctly, or to stimulate a component by triggering events on specific nodes, then we should recommend rendering to a DOM. This gets us completely out of the business of querying/traversing DOM, and lets test writers use their preferred traversal and assertion libraries (e.g. chai-dom, chai-jquery, Sizzle, etc.). This would make the API much smaller; we could eliminate Conceptually, I believe the
A couple of specifics on the API:
One method that's missing is a manual way to force Vue's Going along with the above, I think that the Should there be a One thing that I think might be useful is to have a Mock/Spy Component ala Sinon. The idea is that you could pass this MockComponent to the component under test in a slot. It would have methods on it to tell you how many times it was instantiated (for testing |
Ahh, I didn't know /cc @wrseward it would be great to have some feedback from you and join forces with us :) |
Would love to see something to mock global event bus related things. |
I consider the event hub pattern to be an escape hatch for certain edge cases rather than a recommended pattern for general use. It brings the same, if not worse, problems that For that reason, I think we should not offer any API tailored to this pattern. What are the rest of you thinking about the event hub? |
I haven't ever found I need it (there's almost always an alternative solution). On the other hand, if there is a design pattern that is featured in the official documentation, and that is sometimes unavoidable, I think it would only be fair to consider providing a way to test it. In my opinion, this library, while not encouraging bad practices, should not punish people for using event buses and the like. The purpose is to make it easy to test vue apps in general, not to force a specific design pattern. Vue's impartiality on this (unlike, say, react) is what makes it so appealing to newcomers. |
It is currently mentioned in the migration guide only, but yes, it is being mentioned. My experience with reading and/or answering many questions on SO and our own forum is that people tend to use this pattern for the simplest problems because it seems to be an easy solution - people tend not to see the problems of reasoning about the apps event and data flow that event busses bring into their apps. For that reason I think we should discourage the use in the documentation, or at least write few warning words next to it. If e can do that, then support in the test tools would be fine with me. Otherwise, we would further encourage a pattern that, in my experience from working with the community, is already vastly over- or even abused. |
@LinusBorg Can you give some examples of event hub usage that could hurt or block rather than help? |
I don't think that this issue is the right place to go into too much detail. The general grievances i have with the event bus is that it requires a lot of mental overhead for any but the most simple scenarios (and the simple ones generally can be solved easily through normal props). The developer has to keep track of which events might change state where and when, because the application structure doesn't really tell you. The "when" is especially problematic because you essentially need to keep in mind when which component might be destroyed or re-created and could potentially miss an update from the event bus that it needs. All of this is based in the fact that it's, well, event-based and not state-based like the rest of the patterns we use in Vue. So of course the Event bus is not a problem (but not necessary either) if you use it to communicate between two not too distant components that are guaranteed to always exist together , at the same time. But it rarely stays with that, nd tends to become a mess. |
@yyx990803 @eddyerburgh I would be very happy to collaborate on this! Thank you 👍 I think there are some great ideas here and want some time read over everything before giving feedback |
One thing I'd love to see is utilities that allow the testing of single file components without Webpack. When writing unit tests Webpack definitely gets in the way of simple easy test scripts such as those using tape. To get things running with Avoriaz originally I had to spend a great deal of time writing a webpack file runner (similar to babel-node) that webpacks a file (or glob) and runs it in a node process. I'd really like to be able to avoid that. I'm not sure how much effort might be involved in supporting this. |
@chrisnicola yes this is an area I feel strongly about. In this day and age, passing testing code through webpack in order to test it in a node environment feels like a hack. This isn't limited to Vue but Single File Components makes it harder to overcome. I would suggest looking at require-extension-hooks. I would love it if the official docs could do away with karma/webpack advice, is the introduction of an official testing utility the right opportunity? |
@jackmellis @chrisnicola Seeing your comments inspired me to clean up some work I had done earlier to make unit testing a little better. While it's not what you're asking for, what I did was remove karma & phantomJS, and replace it with mocha-webpack and JSDOM. See issue vuejs-templates/webpack#875 and PR vuejs-templates/webpack#874. With this change, you still need webpack, but |
I think I ended up creating https://www.npmjs.com/package/wprun to support general running of test files through webpack. It still isn't my ideal solution however. I'm going to look at |
I recommend using Jest with jest-vue-preprocessor. Jest caches compiled components, runs faster than mocha-webpack and has better support. There are two problems with Jest
|
@eddyerburgh one other huge pitfall with jest is the inability to get a debugger in the code. This has been an issue for like 2ish years right now and it makes it very difficult for less experienced js developers to do unit testing. We recently switched out component testing from jest back to karma for this very reason. I think that the concept of testing outside of webpack is great, but I don't think it should be a focus of vue test utils. I think in leiu of that we should provide direct hookin to the vue-cli generators and setup tests for hacknews example so that others have real examples. |
This is fixed as of node 8.4
…On Tue, Aug 29, 2017 at 11:21 AM, Austin ***@***.***> wrote:
@eddyerburgh <https://github.com/eddyerburgh> one other huge pitfall with
jest is the inability to get a debugger in the code. This has been an issue
for like 2ish years right now and it makes it very difficult for less
experienced js developers to do unit testing. We recently switched out
component testing from jest back to karma for this very reason.
I think that the concept of testing outside of webpack is great, but I
don't think it should be a focus of vue test utils. I think in leiu of that
we should provide direct hookin to the vue-cli generators and setup tests
for hacknews example so that others have real examples.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#1 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AACounSNq0UIDSBdUPA4Yljox05V5Usmks5sdCyFgaJpZM4NooPe>
.
|
For reference my launch.json looks like this:
```
{
// Use IntelliSense to learn about possible Node.js debug attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit:
https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Jest Tests",
"program": "${workspaceRoot}/node_modules/.bin/jest",
"args": [
"-i"
],
"runtimeExecutable": "/path/to/node-8.4.0",
"internalConsoleOptions": "openOnSessionStart",
"outFiles": [
"${workspaceRoot}/dist/**/*"
]
}
]
}
```
…On Tue, Aug 29, 2017 at 11:22 AM, Avi Block ***@***.***> wrote:
This is fixed as of node 8.4
On Tue, Aug 29, 2017 at 11:21 AM, Austin ***@***.***> wrote:
> @eddyerburgh <https://github.com/eddyerburgh> one other huge pitfall
> with jest is the inability to get a debugger in the code. This has been an
> issue for like 2ish years right now and it makes it very difficult for less
> experienced js developers to do unit testing. We recently switched out
> component testing from jest back to karma for this very reason.
>
> I think that the concept of testing outside of webpack is great, but I
> don't think it should be a focus of vue test utils. I think in leiu of that
> we should provide direct hookin to the vue-cli generators and setup tests
> for hacknews example so that others have real examples.
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <#1 (comment)>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AACounSNq0UIDSBdUPA4Yljox05V5Usmks5sdCyFgaJpZM4NooPe>
> .
>
|
@blocka you are able to get a debugger in using webstorm (or rubymine) or with visual studio code, but that has been true for a while. I just tested out 8.4.0 on my node server (that uses jest for testing) and the debugger does not work out of the box. |
This statement is false |
Well, i think it really depends on perspective, my experience is that the people on my team who are migrating from backbone to vue had a highly difficult time with it. They had to learn several layers concepts to even debug the code, which resulted in less test coverage because testing to them was hard. The alternative after we moved back to karma was they threw in a debugger and could see the entire closure context and had access to all the normal vue tools, happiness increased and so did code coverage. Although I personally think jest is superior, in my experience it is not a good tool for beginner js programmers or programmers who are not coming from a more js heavy framework like react and that is why i think it is a pitfall. |
I'm not sure what this has to do with backbone. Personally, if not for jest I would probably not be testing my components at all. The fact that to get any testing done you need mocha, and karma, and sinon, and god knows what else...I just couldn't make sense out of it. Comes along jest, and bam! Just one tool, does all I need. So I found jest much simpler to use and set up. |
We should create another issue to discuss test frameworks. There are no plans currently to add test framework specific code to vue-test-utils. Right now, it's framework agnostic - and I think it should stay that way. |
Yeah I can't help but feel this got a bit off topic. We shouldn't really be forcing users to use one testing framework over another, we should just be ensuring there is a nice and easy way to test Vue components everywhere. So (grits teeth) those wanting to use karma can do so, but there should also be a well documented framework-agnostic way of being able to at least load a vue component from within node. |
@jackmellis, thank you, that is exactly right. I get Jest is great, regardless, I also have no intention of using it in my projects. I strongly disagree with the approach React and Angular have taken of "anointing" a particular testing framework. |
Since the beta is released, I'm closing this issue. We can continue discussing features in the issue tracker |
So, there is a plan to implement Array-like methods for WrapperArray( |
@saintplay not at the moment, if you want to make a feature request you can make a new issue. My opinion is we shouldn't add those methods. You can access the array of wrappers from a WrapperArray already: const wrapperArr = wrapper.findAll('div')
wrapperArr.wrappers.forEach(w => {
w.is('div') // true
}) |
Oh! I didn't notice that, is this in the documentation? @eddyerburgh That array will do the job |
Russian translation: improve types
Following the forum thread, using this issue to kick off work on an official unit testing utility lib. We are planning to built on top of @eddyerburgh 's Avoriaz, since it seems to be the most mature one currently, and Edd has kindly offered to work on it. Of course, we would also like to pull in ideas from other community solutions and make this a collaborative effort, so I'm pinging some community members that might also be interested in contributing here: @callumacrae, @asselin, @jackmellis, @codebryo, @BosNaufal.
I think the first step is outlining what feature set we are aiming for - here's some high level goals:
in the meanwhile, feel free to provide general feedback on some of the needs you've run into while unit testing Vue.
Also @vuejs/collaborators for any potential input.
The text was updated successfully, but these errors were encountered: