Vue-test-utils: Synchronous updates don't work on $slots

Created on 2 Oct 2017  路  2Comments  路  Source: vuejs/vue-test-utils

Version

1.0.0-beta

Steps to reproduce

Create a component that uses slots:

// SlotComponent.vue
<template>
  <div>
    <slot></slot>
  </div>
</template>

Use this component in some Parent.vue:

<template>
  <SlotComponent>
    <div :class="[{ 'is-on': on }, 'inner']"></div>
  </SlotComponent>
</template>

<script>
//...
export default {
  //...
  props: {
    on: {
      default: false,
      type: Boolean
    }
  },
  // ...
}
</script>

What is expected?

Setting props should synchronously update the template, but this test fails:

const parentWrapper = mount(Parent)
const innerEl = parentWrapper.find('.inner')

expect(innerEl.hasClass('is-on')).to.equal(false)

parentWrapper.setProps({
  on: true
})

expect(innerEl.hasClass('is-on')).to.equal(true)

What is actually happening?
nextTick is still required to update slot content.

Solution
Looks like Vue's vm._update function clones existing slots and does not update them unless the parent has updated. To fix this in our test we can trigger an update on our SlotComponent.vue:

parentWrapper.setProps({
  on: true
}) // calls parentWrapper.update

childWrapper = parentWrapper.find(SlotComponent)
childWrapper.update() // no nextTick required with this
bug

All 2 comments

Thanks for the amazing bug report, I was able to add a test with the code you provided 馃檪

In b714ce3, update now loops through child Vue instances and calls update on them

Amazing! Glad I could help and thanks for the quick response. I tested this fix and it seems to work for deeply nested slot content as well.

Was this page helpful?
0 / 5 - 0 ratings