1

I have a component:

<template>
  <div class="toggle">
    <div v-show="toggle">
      {{ text }}
      <slot :toggle="toggleSlots" name="first"></slot>
    </div>
    <div v-if="!toggle">
      <slot :toggle="toggleSlots" name="second"></slot>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const toggle = ref(true);

const text = ref('hi');

function toggleSlots() {
  toggle.value = !toggle.value;
}

setTimeout(() => {
  text.value = 'hii';
}, 1000);

</script>

And a Jest test:

import { mount } from '@vue/test-utils';
import AppToggle from './toggle.vue';

describe('Toggle', () => {
  it('should toggle the slots', async () => {
    const wrapper = mount(AppToggle);

    expect(wrapper.vm.toggle).toBeTruthy(); // vm.toggle is undefined

    wrapper.vm.toggleSlots(); // vm.toggleSlots is undefined

    expect(wrapper.vm.toggle).toBeFalsy();
  });
});

When I wrote the component using the options API, the test passed. If I use the composition API, all variables or functions I define are not defined on wrapper.vm.

I found other examples where they did the same thing but it does not work for me somehow.

2
  • is vm itself undefined as well or does it have any values? Commented Dec 17, 2022 at 10:30
  • vm itself is defined and does have other keys/values Commented Dec 19, 2022 at 16:13

1 Answer 1

1

Components using are closed by default - i.e. the public instance of the component, which is retrieved via template refs or $parent chains, will not expose any of the bindings declared inside .

To explicitly expose properties in a component, use the defineExpose compiler macro.

<script setup>
import { ref } from 'vue'

const a = 1
const b = ref(2)

defineExpose({
  a,
  b
})
</script>

Source: https://vuejs.org/api/sfc-script-setup.html#defineexpose

I added

defineExpose({ toggle, toggleSlots });

at the end of my script and now the test passes.

Sign up to request clarification or add additional context in comments.

4 Comments

I would not advise this method. If you do this throughout your application, you are going to have a lot of naming conflicts.
@JoshuaTrimm how?
Your configuration isn't correct. You don't want to allow the other parts of the application to have access by using the defineExpose function just to get your tests to pass.
@JoshuaTrimm I agree. In my case I was migrating an existing component with tests to the composition API, and the tests were already checking the variables. I wanted to find out whether this was also possible with the composition API, rather than rewriting an old test. How does this result in having a lot of naming conflicts though?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.