vue-test-utils returns null for document.querySelector

Tags: , ,



I am writing unit tests for a Vue.js component that displays some radiobuttons and emits an event with the radio button id whenever a button is checked:

ApplicationElement.vue:

<template>
  <div id="element">
    <label>
      <input
        type="radio"
        name="Element"
        id="element1"
        v-on:change="chooseElement"
      />
      Element1
    </label>
    <label>
      <input
        type="radio"
        name="Element"
        id="element2"
        v-on:change="chooseElement"
      />
      Element2
    </label>
    <label>
      <input
        type="radio"
        name="Element"
        id="element3"
        v-on:change="chooseElement"
      />
      Element3
    </label>
    <label>
      <input
        type="radio"
        name="Element"
        id="element4"
        v-on:change="chooseElement"
      />
      Element4
    </label>
  </div>
</template>

<script>
export default {
  methods: {
    chooseElement () {
      var chosenElement = document.querySelector('input[name="Element"]:checked').id
      this.$emit('passChosenElement', {category: chosenElement})
    }
  }
}
</script>

<style>
</style>

I wrote the following test for said component:

ApplicationElement.spec.js:

import { shallowMount, createLocalVue } from '@vue/test-utils'
import 'regenerator-runtime/runtime'
import ApplicationElement from '@/components/ApplicationElement.vue'

const localVue = createLocalVue()

describe('ApplicationElement tests', () => {
    it('should emit event with element1 parameter on corresponding radio button choice', async() => {
        const wrapper = shallowMount(ApplicationElement, {
            localVue,
            attachTo: document.body,
            propsData: {
                recursionNumber: 1
            }
        })
        await wrapper.find('input[type="radio"][id="element1"]').setChecked()
        expect(wrapper.emitted().passChosenElement[0]).toEqual([{element: 'element1'}])
        wrapper.destroy()
    })
})

The test fails with: “TypeError: Cannot read property ‘id’ of null” If I remove the document.querySelector line from the chooseElement method in the component and emit the right id by hand, the test succeeds.

How can I get document.querySelector to work with vue-test-utils?

Answer

I know, this question is already a bit older, but I finally found a solution here. You need to attach your component with attachTo (since May 2021) to an html element. The solution looks like this:

describe('ApplicationElement tests', () => {
  it('should emit event with element1 parameter on corresponding radio button choice', async() => {
      const elem = document.createElement('div')
      if (document.body) {
         document.body.appendChild(elem)
      }

      const wrapper = shallowMount(ApplicationElement, {
          localVue,
          attachTo: document.body,
          propsData: {
              recursionNumber: 1
          },
          attachTo: elem,
      })
      await wrapper.find('input[type="radio"][id="element1"]').setChecked()
      expect(wrapper.emitted().passChosenElement[0]).toEqual([{element: 'element1'}])
      wrapper.destroy()
  })
});
   

As you already did, it is important to call wrapper.destroy() after each test. Little refactoring tip: Put wrapper.destroy() into an afterEach callback function. Here you can find more about attachTo.



Source: stackoverflow