Comments (31)
What do people think about adding it as an option to mount:
mount(Component, {
use: [plugin]
})
use
would take an array of plugins and use it in a scoped Vue instance.
from vue-test-utils.
It should work by using an extended constructor with empty options:
const FreshVue = Vue.extend()
FreshVue.use(plugin)
const testedVM = new FreshVue({ ... })
Let me know if there are practical issues with this.
from vue-test-utils.
from vue-test-utils.
@blocka I think people find very useful using global mixins, plugins and components. For me personally injecting $apollo
like you said seems more straight forward than a HOC. In my tests I can replace that with a mock very easily if I want to so I don't have to care too much about it's implementation.
After all I don't think you can stop people from using such a feature which is very widespread in Vue and used by many of vue developers.
from vue-test-utils.
What I thought about doing with Vuenit was to have an install method that exposed the scoped vue object before mounting the component:
mount(Component, {
install : function(ScopedVue){
ScopedVue.use('blahblah');
}
});
I don't know if that is the way to go, it means you don't have to account for the entire Vue api within the mount config.
from vue-test-utils.
@eddyerburgh alright, I get your point and yes it was a concern of mine as well. Probably better to omit some automagic by default.
As the approach with the CleanVue Instance is optional I think we should be good, as Vue.use(Vuex)
would still work for users who prefer it that way.
The API seems pretty clean so we should be good, agreed. :)
from vue-test-utils.
Are you referring to
Be able to Vue.use(plugin) without it polluting the global environment and leaking between tests. Some sort of isolated Vue constructor perhaps?
?
We could provide a wrapper that tracks the calls to global components, directives, filters and that can later be called again to uninstall everything. This is however limited to serialised tests. The isolated constructor is interesting, I wonder if we cannot get a hacky version working without touching core
from vue-test-utils.
@jackmellis it seems to work: https://jsfiddle.net/yyx990803/b5a1zh6u/
from vue-test-utils.
For 1 & 2, how about createLocalVue
, the verb reminding users that it's a function? Then the option could be called localVue
, making it clear that it expects the result of createLocalVue
. The "local" part serves to remind people not to use or pollute the global Vue.
from vue-test-utils.
@kazupon I'm happy to make a PR 👍
from vue-test-utils.
This has been solved by createLocalVue
from vue-test-utils.
You can see an example in the createLocalVue
code—https://github.com/vuejs/vue-test-utils/blob/dev/packages/test-utils/src/create-local-vue.js
You can omit the errorHandler
from vue-test-utils.
I like that, it's neat. Should we also account for configuration options?
from vue-test-utils.
Yeah I think if we go this route we'll need to add all of the global API to mount. Which will be a reasonable amount of work.
mount(Component, {
use: ['plugin'],
config: {
ignoredElements: ['my-custom-web-component', 'another-web-component']
}
})
Another option is to have a ScopedVue object (although with a better name!) -
import { ScopedVue } from 'vue-test-utils'
const scopedVue = new ScopedVue
scopedVue.use(plugin)
scopedVue.mixin('my-directive', function () {})
mount(Component, {
instance: scopedVue
})
from vue-test-utils.
I should also add that I found that an extended Vue object didn't work with mixins, directives, and components. So doing:
const Extended = Vue.extend(Component);
Extended.component('some-component', definition);
const vm = new Extended.$mount();
This did not use some-component
registered with the extended component, it would always go back to the base Vue object for globally-registered stuff.
from vue-test-utils.
@yyx990803 well in that case I stand corrected!
You can see the original discussion on this matter: https://forum.vuejs.org/t/vue-component-inheritence/9387
Perhaps the issue I had was that I was creating an extended vue, then registering a global component, then I was extending that extended vue again. I had assumed that it would go up the inheritence chain until it found what it was looking for, but maybe it just looks on the current class, then jumps straight to the base class?
from vue-test-utils.
The proposed API for options.use is problematic.
For example, Vuex must be installed before you can create a store, so this is not possible:
const store = new Vuex.Store({...})
mount(Component, { use: [Vuex] })
An alternative could be this pattern:
const CleanVue = Vue.extend()
CleanVue.use(Plugin)
mount(Component, { instance: CleanVue })
But there are also problems calling use on a vue.extend instance.
An extended instance doesn't have a version, which vuex relies on.
I'll look into this more over the next couple days
from vue-test-utils.
@yyx990803 I know that provide/inject did not exist at the time vuex was created, but if it used provide/inject, this would be less of a problem, as vuex can provide it's own mock provider, or creating a one is pretty trivial, and there would be no need to globally clobber ever vue instance.
from vue-test-utils.
@eddyerburgh that is one of several reasons I wrote mock-vuex, because Vuex has some test-unfriendly rules about instantiating and use
ing
from vue-test-utils.
@eddyerburgh so, why not inject the store
in the wrapper as well? That would make specs even cleaner and that's the approach I took for Revue.
mount(Component, {use: [Vuex], store: storeObject}
Or we make it even implicit, but that of course can be trcky if people wanne use a different store type.
from vue-test-utils.
@codebryo I don't think we should add options for specific plugins.
store
is already used by Vuez. ), right now a store passed to mount will be passed as component options - which means Vuex and Vue can both be tested. If we treat all option.store as Vuex, we make it impossible to test a Vuez store. Unless we also make an exception for that. But then another plugin might require a store option. I think it's a bad road to go down.
Although maybe we could add some kind of options specifically for vue-router and Vuex as they are official libraries. If we did we'd have to be explicit in the options that they are for Vuex and vue-router
mount(Component, {use: [Vuex], vuexStore , vueRouter }
Overall, I'm in favor of this API -
const CleanVue = Vue.extend()
CleanVue.use(Vuex)
const store = new Vuex.Store({...})
mount(Component, { instance: CleanVue, store })
It means we don't have to write code for specific plugins.
It also means we avoid adding options for everything you can pass to a Vue instance, like component, mixin, directive etc.
from vue-test-utils.
Oops, accidentally closed 😛
Ok great, I'll start working on it and get it added 👍
from vue-test-utils.
I've added a function that returns an extended Vue instance with some props that Vuex and Vue-router use (like version and config)
This way you can pass it to mount
using the instance
option, and mount will use the extended class as a base class.
So you can add components, mixins, and install components without polluting the global vue base class.
import { scopedVue, mount } from 'vue-test-utils'
const baseClass = scopedVued()
baseClass.use(Vuex)
const wrapper = mount(Component, {
instance: baseClass
})
wrapper.vm.$store // is defined
const freshWrapper = mount(Component)
wrapper.vm.$store // is undefined
Some things I'd like input on:
- I don't think
scopedVue
is very clear, can anyone think of a better name?extendedVue
,freshVue
,cleanVue
? - the option to pass a Vue class is named
instance
. I think this should be renamed, but am not sure what to. I would love some input. - Vuex can't be installed on two instances. It uses the same Vue class each install - https://github.com/vuejs/vuex/blob/dev/src/store.js#L6. I'm not sure how to resolve this
from vue-test-utils.
- Vuex can't be installed on two instances. It uses the same Vue class each install
I guess we should add an install option to allow overwriting previous Vue instance like forceInstall: true
in Vuex.
from vue-test-utils.
Just did this:
import { mount, createLocalVue } from 'vue-test-utils';
import Vuetify from 'vuetify';
const localVue = createLocalVue();
localVue.use(Vuetify);
describe('Question.spec.js', () => {
let cmp;
let template;
beforeEach(() => {
cmp = mount(Question, {
localVue,
propsData: {
question: {},
id: "/questions/6673",
store,
});
template = cmp.html();
});
And I get
TypeError: Cannot set property 'installed' of undefined
at Function.instance.use (node_modules/vue-test-utils/dist/vue-test-utils.js:1253:30)
at Object.<anonymous> (src/components/Question/Question.spec.js:8:10)
at Generator.next (<anonymous>)
at Promise (<anonymous>)
at Generator.next (<anonymous>)
at <anonymous>
from vue-test-utils.
Thanks for the bug report, can you please make a new issue?
I see you did. Thanks :)
from vue-test-utils.
from vue-test-utils.
@yyx990803 I tried in your fiddle what you suggested in this thread
const FreshVue = Vue.extend()
FreshVue.use(plugin)
const testedVM = new FreshVue({ ... })
but it seems to use the global Vue and it does not recognise $t
method (error in console)
from vue-test-utils.
Hi @lsimone . The solution to this issue was to add a createLocalVue
function. This needs to be used with a localVue
option.
You can see examples in the docs—https://vue-test-utils.vuejs.org/en/api/createLocalVue.html 😀
from vue-test-utils.
Thanks @eddyerburgh but how to do it without importing createLocalVue
from '@vue/test-utils'
?
the code I quoted doesn't work as expected in the fiddle I linked
from vue-test-utils.
ok, thanks @eddyerburgh I will try this way.
So the code suggested by Evan here is definitely not enough to avoid Vue.use polluting global Vue instance.
Do you think that cloning Vue would have a big impact on performance? (I am using it in server side rendering)
from vue-test-utils.
Related Issues (20)
- Computed value does not update when data updates
- isVisible() not seeing display: none using vitest with jsdom HOT 4
- Testing component with onBeforeRouteLeave hook raising "No active route record was found" warning HOT 1
- vue2 引入 element2. 页面存在table 表格 jest 测试报错 HOT 1
- *.svg?inline issues
- Errors in `setup()` are silent if `render()` throws an error HOT 6
- Check style changes on hover HOT 1
- setData on writable computed property does not seem to work as it does in VTU.1
- classes documentation
- Support Vue 2.7.16 HOT 2
- Vue test utils not updating template when testing composables
- TypeError: $setup.mergeProps is not a function
- Data property is already defined in Props. HOT 1
- Unable to use vitest spy within vue/nuxt 3 component methods. HOT 3
- `findComponent` doesn't find anything when using `@vue/compat` HOT 1
- Components with TS generic HOT 1
- event.keyCode is deprecated
- Change mocks mid-test
- While testing out mixins, the $refs cannot be modified and due to which the testing cannot occur.
- This import pattern causes imported component to be undefined in tests
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from vue-test-utils.