eddyerburgh/avoriaz

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 of mount 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.