Vue-test-utils: TypeError: Cannot read property '$options' of undefined

Created on 31 May 2018  ·  8Comments  ·  Source: vuejs/vue-test-utils

Version

1.0.0-beta.15

Reproduction link

https://github.com/feliupe/vuerror

Steps to reproduce

yarn && yarn test

What is expected?

The test to run with no error.

What is actually happening?

There two errors:

  • TypeError: Cannot read property '$options' of undefined
  • and TypeError: Cannot set property '_error' of undefined, that I think is related to the errorHandler and my not be related to the test failing.
    TypeError: Cannot read property '$options' of undefined

       6 |     it('Mock', () => {
       7 |         const wrapper = mount(Page)
    >  8 |         wrapper.vm.treeData = {}
       9 |         // wrapper.vm.$forceUpdate()
      10 |     })
      11 | })

      at updateChildComponent (node_modules/vue/dist/vue.js:2573:8)
      at prepatch (node_modules/vue/dist/vue.js:3510:5)
      at patchVnode (node_modules/vue/dist/vue.js:5425:7)
      at updateChildren (node_modules/vue/dist/vue.js:5340:9)
      at patchVnode (node_modules/vue/dist/vue.js:5436:29)
      at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.js:5566:9)
      at VueComponent.Vue._update (node_modules/vue/dist/vue.js:2428:19)
      at VueComponent.updateComponent (node_modules/vue/dist/vue.js:2542:10)
      at Watcher.get (node_modules/vue/dist/vue.js:2883:25)
      at Watcher.run (node_modules/vue/dist/vue.js:2960:22)
      at Watcher.update (node_modules/vue/dist/vue.js:2948:10)
      at Dep.notify (node_modules/vue/dist/vue.js:784:13)
      at Object.reactiveSetter [as treeData] (node_modules/vue/dist/vue.js:1006:11)
      at updateChildComponent (node_modules/vue/dist/vue.js:2599:18)
      at prepatch (node_modules/vue/dist/vue.js:3510:5)
      at patchVnode (node_modules/vue/dist/vue.js:5425:7)
      at updateChildren (node_modules/vue/dist/vue.js:5340:9)
      at patchVnode (node_modules/vue/dist/vue.js:5436:29)
      at updateChildren (node_modules/vue/dist/vue.js:5340:9)
      at patchVnode (node_modules/vue/dist/vue.js:5436:29)
      at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.js:5566:9)
      at VueComponent.Vue._update (node_modules/vue/dist/vue.js:2428:19)
      at VueComponent.updateComponent (node_modules/vue/dist/vue.js:2542:10)
      at Watcher.get (node_modules/vue/dist/vue.js:2883:25)
      at Watcher.run (node_modules/vue/dist/vue.js:2960:22)
      at Watcher.update (node_modules/vue/dist/vue.js:2948:10)
      at VueComponent.Vue.$forceUpdate (node_modules/vue/dist/vue.js:2449:19)
      at updateChildComponent (node_modules/vue/dist/vue.js:2615:8)
      at prepatch (node_modules/vue/dist/vue.js:3510:5)
      at patchVnode (node_modules/vue/dist/vue.js:5425:7)
      at VueComponent.patch [as __patch__] (node_modules/vue/dist/vue.js:5566:9)
      at VueComponent.Vue._update (node_modules/vue/dist/vue.js:2428:19)
      at VueComponent.updateComponent (node_modules/vue/dist/vue.js:2542:10)
      at Watcher.get (node_modules/vue/dist/vue.js:2883:25)
      at Watcher.run (node_modules/vue/dist/vue.js:2960:22)
      at Watcher.update (node_modules/vue/dist/vue.js:2948:10)
      at Dep.notify (node_modules/vue/dist/vue.js:784:13)
      at Object.reactiveSetter [as treeData] (node_modules/vue/dist/vue.js:1006:11)
      at VueComponent.proxySetter [as treeData] (node_modules/vue/dist/vue.js:3075:26)
      at Object.it (test/Test.spec.js:8:9)

  console.error node_modules/vue/dist/vue.js:667
    TypeError: Cannot set property '_error' of undefined
        at errorHandler (/home/feliupe/archii/vuerror/node_modules/@vue/test-utils/dist/vue-test-utils.js:5126:13)
        at handleError (/home/feliupe/archii/vuerror/node_modules/vue/dist/vue.js:565:25)
        at Array.<anonymous> (/home/feliupe/archii/vuerror/node_modules/vue/dist/vue.js:709:11)
        at nextTickHandler (/home/feliupe/archii/vuerror/node_modules/vue/dist/vue.js:654:16)
        at <anonymous>

I tried to create the minimum setup to reproduce the problem. Almost any statement you remove from this code will make the test pass. Like removing <message/> for example.

You may ask, why this setup of components, with a Tree and Message wrapped in a Layout: it's a representation of what I have in my project.

May also help to know that the error disappears if you remove wrapper.vm.treeData = {} and also happens if you uncomment wrapper.vm.$forceUpdate().

Most helpful comment

Thanks for the bug report.

This is the same issue filed here—#653.

This is a problem with how we have implemented synchronous updating. There's a PR open to fix this by adding an async option to Vue—https://github.com/vuejs/vue/pull/8240.

For the moment, the workaround is to set the sync mounting option to false and use Vue.nextTick to await DOM updates:

test('use Vue.nextTick', (done) => {
  const wrapper = mount(TestComponent, { sync: false })
  wrapper.trigger('click')
  Vue.nextTick(() => {
    expect(wrapper.text()).toBe('updated')
    done()
  })
})

All 8 comments

Thanks for the bug report.

This is the same issue filed here—#653.

This is a problem with how we have implemented synchronous updating. There's a PR open to fix this by adding an async option to Vue—https://github.com/vuejs/vue/pull/8240.

For the moment, the workaround is to set the sync mounting option to false and use Vue.nextTick to await DOM updates:

test('use Vue.nextTick', (done) => {
  const wrapper = mount(TestComponent, { sync: false })
  wrapper.trigger('click')
  Vue.nextTick(() => {
    expect(wrapper.text()).toBe('updated')
    done()
  })
})

I ran into this issue myself. However, I couldn't get Edd Yerburgh solution to work for me. I was working with a form submit trigger event.

I ended up using the flushPromises method from https://www.npmjs.com/package/flush-promises.~~

test('use Vue.nextTick', async () => {
  const wrapper = mount(TestComponent, { sync: false })
  wrapper.trigger('submit')
  await flushPromises()
  expect(wrapper.text()).toBe('updated')
})

Update

My above example actually didn't work as expected. Here is what I changed.

test('use Vue.nextTick', async () => {
  const wrapper = mount(TestComponent, { sync: false })
  wrapper.trigger('submit')
  await wrapper.vm.$nextTick()
  expect(wrapper.text()).toBe('updated')
})

@nathanjisaac thanks men this is huge serve !

I've updated to @vue/test-utils 1.0.0-beta.29 and vue 2.5.22 and I've the same issue.

I pulled out a minimal reproduction on https://github.com/rndmerle/repro-vue-test-utils-sync.git
Just yarn && yarn test

The test would pass if you change either one of those:

  • comment out one of the two it()
  • comment out the content of the forEach (in setup method)
  • switch the watcher to immediate:false and uncomment the created() content

I can't find anything further down, my brain is boiling.

Thanks for the reproduction @rndmerle, this is caused by sync mode, which is being deprecated. See this issue for more details—https://github.com/vuejs/vue-test-utils/issues/1137

Yea but I thought https://github.com/vuejs/vue-test-utils/pull/1062 would solve that somehow. I misunderstood something I guess.
Thanks for the details.

We were hoping #1062 would be a medium-term solution, but there are lots of edge cases we didn't anticipate.

It's clearer now thanks ;)

Was this page helpful?
0 / 5 - 0 ratings