I'm trying to call the close()
method in my Test
component, but it only gets fired when clicking outside the div
that the directive is on. What should I do in my test to make sure that that method gets fired? I'm using the v-click-outside
npm package in my component.
Component
<script>
import vClickOutside from 'v-click-outside';
export default {
name: 'Test',
directives: {
vClickOutside,
},
data: () => ({
isOpen: false,
}),
methods: {
close() {
this.isOpen = false;
},
};
</script>
<template>
<div
v-click-outside="close"
class="test-class"
>
<OtherComponent />
</div>
</template>
This is my test file.
const clickOutsidelDirective = jest.fn();
describe('Test.vue', () => {
const wrapper = shallowMount(Component, {
directives: {
clickOutside: clickOutsidelDirective,
},
});
wrapper.find('.test-class').trigger('click');
//not sure what i have to do to mock the close() function
//This doesn't get called
expect(clickOutsidelDirective).toHaveBeenCalled();
}
The directive is not setup properly in your component:
import vClickOutside from 'v-click-outside'
export default {
directives: {
// BEFORE: ❌
vClickOutside,
// AFTER: ✅
clickOutside: vClickOutside.directive
},
}
To verify that close()
is called when you click outside the component:
close
method with jest.spyOn
.div
for the test component, and attach the mounted wrapper to it.v-click-directive
adds its event listeners on the next macro-tick (using setTimeout
with no timeout), so the test also needs to wait a macro-tick for the directive to initialize.click
event on the wrapper, and await
the result. Then, assert that close()
was called.The test should look like this:
it('click directive', async () => {
1️⃣
const closeFn = jest.spyOn(HelloWorld.methods, 'close')
2️⃣
const div = document.createElement('div')
document.body.appendChild(div)
const wrapper = mount({
template: `<div><HelloWorld /></div>`,
components: {
HelloWorld
},
}, { attachTo: div })
try {
3️⃣
await new Promise(r => setTimeout(r))
4️⃣
await wrapper.trigger('click')
expect(closeFn).toHaveBeenCalled() ✅
} finally {
wrapper.destroy()
}
})