Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the props of a child component of a wrapper object in Vue

I'm writing some tests using vue-test-util for a component I've made. I have boiled my code down to the actual problem.

The component is of the form:

<template>
  <inner-component>
</template>
<script>
export default {
  name: 'MyList'
}
</script>

and my inner component looks something like this:

<template>
  <div v-if="open">Some stuff</div>
</template>
<script>
export default {
  name: 'InnerComponent',
  props: {
    open: false,
  }
}
</script>

Now the test I'm writing is testing for the existence of the div in the inner-component when the open prop is set to true, but it is set to false by default. I need a way to set the prop of this child component before I test it.

My test:

import { createLocalVue, mount } from '@vue/test-utils'
import MyList from '@/components/MyList.vue'

describe('My Test', () => {
  const localVue = createLocalVue()
  const wrapper = mount(MyList)

  it('Tests', () => {
    // need to set the prop here
    expect(wrapper.find('div').exists()).toBeTruthy()
  }
}

I can use:

wrapper.vm.$children[0].$options.propsData.open = true

Which does appear to set the prop, but my tests still come up as receiving false.

I can change the component so the default is true and then my tests pass so I don't think it's the way I'm checking.

If anyone can spot why this isn't working or knows a better way to come at it, please let me know!

like image 841
Fergmux Avatar asked Sep 06 '25 03:09

Fergmux


1 Answers

According to the guide:

vm.$options

The instantiation options used for the current Vue instance.

So, $options is not what we write in props.

Use $props to set property for a child component:

wrapper.vm.$children[0].$props.open = true

But this way leads to the warning:

Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.

So, let's follow the advice and bind property of the child component with data of the parent component. Here I bind it with isOpen variable:

<template>
  <inner-component :open='isOpen'></inner-component>
</template>

<script>
import InnerComponent from '@/components/InnerComponent.vue'

export default {
  name: 'MyList',
  data() {
    return {
      isOpen: false
    }
  },
  components:{InnerComponent}
}
</script>

Then in your test, you can just change the value of isOpen when you want to change the value of open property in the child component:

    wrapper.setData({isOpen:true})
like image 105
Lana Avatar answered Sep 09 '25 21:09

Lana