I am facing a challenge in testing a VueJS component as I am new to both Vue and Vitest. Despite my efforts, I have not been able to find a solution through online searches.
The component in question receives props and has two named slots.
The onmounted()
function checks if the text within one of these slots vertically fits a set threshold in pixels. If it does not fit, a CSS class is added to the parent <div>
and a button is displayed.
However, during testing, I noticed that the height of the elements always returns as 0
. It seems that the rendering engine in vitest does not expose or compute element.clientHeight
.
This issue results in the button, which I need to test its functionality, never being rendered.
I attempted to modify the variable controlling the button's visibility from the test using
wrapper.vm.isButtonVisible = true
(where isButtonVisible
is a ref
), but unfortunately, it did not work. This could be due to the script being defined under <script setup>
.
It appears that functions and refs within the component are not accessible from my test suite. Here is a simplified version of the component and the relevant test:
<template>
<div ref="textWrapper" class="detail-summary__text" :class="{'truncated': isButtonVisible}">
<div ref="textContainer" class="detail-summary__inner-text">
<slot name="default"></slot>
</div>
</div>
<div class="detail-summary__button">
<button
v-if="isButtonVisible"
@click="toggleModal"
>Show more</button>
</div>
</template>
<script setup lang="ts">
const textContainer: Ref<DomElement> = ref(null);
const textWrapper: Ref<DomElement> = ref(null);
const textModal: Ref<DomElement> = ref(null);
const isButtonVisible: Ref<boolean> = ref(false);
const isModalOpen: Ref<boolean> = ref(false);
onMounted(() => {
checkContainerHeight();
});
function checkContainerHeight():void {
let textInnerHeight = textHeight.value;
let textWrapperHeight = textHeight.value;
if (textWrapper.value != null && textWrapper.value.clientHeight != null) {
textWrapperHeight = textWrapper.value.clientHeight;
}
if (textContainer.value != null && textContainer.value.clientHeight != null) {
textInnerHeight = textContainer.value.clientHeight;
if (textInnerHeight > textWrapperHeight) {
makeButtonVisible();
}
}
}
function makeButtonVisible(): void {
isButtonVisible.value = true;
}
function toggleModal(): void {
isModalOpen.value = !isModalOpen.value;
}
</script>
I also tried moving isButtonVisible.value = true;
to a separate function and calling it in the test, but there were no errors. Yet, wrapper.html()
did not show the button, indicating that functions cannot be accessed either.
Edit (adding a sample test)
In the test, I attempted:
it.only('should show the see more button', async () => {
// when
const wrapper = await mount(DetailSummary, {
props: {
[...]
},
slots: {
default: 'text here',
},
stubs: [...],
shallow: true,
});
// then
wrapper.vm.makeButtonVisible() // I see the console that I added to the function
console.log(wrapper.html()); // The snapshot still doesn't show the button
const e = wrapper.findComponent({ name: 'DetailSummary' });
e.vm.makeButtonVisible(); // If I add a console in the function, I see it to be called, even if the linter says that that method does not exist
console.log(wrapper.html()); // The snapshot still doesn't show the button
});
If anyone can suggest how to proceed or direct me to relevant documentation/examples, I would greatly appreciate it.