undefined is not a function (evaluating 'this.element.querySelectorAll(selector)')
Closed this issue · 11 comments
Hi, I encounter such error as the title says and my test fails.
avoriaz version: 4.2.0
My test is very simple:
describe('Welcome Page', () => {
it('Should render welcome text', () => {
const wrapper = mount(Welcome)
expect(wrapper.contains('.welcome__header')).to.equal(true)
})
})
And the component is simple as well:
<template>
<section class="login-form text-align">
<section class="welcome-text">
<p class="welcome__header">
{{ $t('welcome.header') }}
</p>
<p>
{{ $t('welcome.text') }}
</p>
</section>
<section class="welcome-buttons">
<el-button
type="primary"
class="login__button welcome__btn"
native-type="button"
@click="handleSample">
{{ $t('welcome.loadSample') }}
</el-button>
<el-button
type="primary"
class="login__button welcome__btn"
native-type="button"
@click="$router.push({ name: 'Login' })">
{{ $t('welcome.auth') }}
</el-button>
</section>
</section>
</template>
<script>
export default {
name: 'welcome',
methods: {
handleSample () {}
}
}
</script>
What am I doing wrong?
P.S. Also how can I use $router
, $t
& $store
inside of my component? (As I have warns & errors because of that) Thanks.
Are you using JSDOM to add a document in your tests?
To add $router, $t and $store, you can use options.globals
:
const wrapper = mount(Component, {
globals: {
$router: {}, $t: {}, $store: {}
}
})
@eddyerburgh
Thanks for your fast reply! No, I am not using JSDOM.
Ok, that's probably the problem. You need to run the tests in a browser, or you need to run JSDOM to create a virtual document. You can do that with a setup file that runs browser-env (which runs JSDOM under the hood) before your tests, like this - https://github.com/eddyerburgh/avoriaz-tape-example/blob/master/test/helpers/.setup.js#L6
Is it the same stuff for Mocha/Chai?
Now I get something like this - TypeError: undefined is not an object (evaluating 'store.registerModule')
Sounds like you're installing Vuex before your tests (using Vue.use(Vuex)).
You'll need to debug your code and find where the error is. You can add globals using the globals
option. Anything that's undefined but used in the component will need to be added with this option:
const wrapper = mount(Component, {
globals: {
$router: {}, $t: {}, $store: {}
}
})
I am adding router instance as $router
property as well as others, however I still get the same output that these are undefined :(
Btw, I am not running any Vue.use
in test.
Ah - you might be getting stung by this - #80
Make sure you don't accidentally Vue.use(Router) before you run your tests. If you require/import a file that contains a Vue.use(Router), this will run the function and make it impossible to overwrite $router on the Vue instance.
Still no luck :(
Unit testing seems overcomplicated to configurate
Yeah it can be complicated
The main things to note:
- You need to run the tests in a Document environment. (use JSDOM to run in node)
- You need to stub properties on the vue instance in components if they expect them. Using
shallow
instead ofmount
means you only stub dependencies in one component. - You shouldn't run any code that installs plugins on Vue in your unit tests. It's easy to do this without realizing. When you require('./some-file'), node executes the code in the file. This might lead to unexpected installs.
Try using one of the example projects and building on top of that.