I am updating my project from Vue 2/Nuxt 2 to Vue 3/Nuxt 3. As i've been doing this my tests have broken and i'm trying to resolve them but every way I try to shallowMount my component returns an empty object or undefined.
The component:
<template>
<footer data-test="form">
<div class="footer-top">
<div class="email-text-container">
<h2 id="heading__mailing-list-form" class="email-title">{{ email.title }}</h2>
<h3 class="email-subtext">
{{ email.subtext }}
</h3>
</div>
<FooterForm />
</div>
</footer>
</template>
<script setup>
import { ref, computed } from "vue";
import { fetchEntriesByContentType } from "../composables/contentful-service";
import FooterForm from "./form/FooterForm.vue";
const props = defineProps({
siteName: String
})
const footer = ref({})
try {
const data = await fetchEntriesByContentType({
contentType: "footer",
title: "Global Footer"
})
if (!data || data.length < 1) {
throw `error fetching footer data`;
} else {
footer.value = data[0].fields
}
} catch (error) {
if (process.env.ROLLBAR_ENABLED === true) {
Vue.rollbar.error(error);
}
throw new Error(error);
}
const email = computed(() => {
return {
title: footer?.value.emailTitle,
subtext: footer?.value.emailSubtext,
}
})
</script>
The previous test (Vue 2/Nuxt 2):
import { shallowMount } from "@vue/test-utils";
import GlobalFooter from "./GlobalFooter";
import FooterForm from "./form/FooterForm";
import "@testing-library/jest-dom";
import { mockFooterData } from '../assets/data/footer-mock-data';
const mockedFooterData = {
emailTitle: "email title",
emailSubtext: "email subtext",
};
describe("GlobalFooter", () => {
it("Should render EloquaForm component", () => {
const wrapper = shallowMount(GlobalFooter, {
propsData: {
siteName: '/test/',
}
});
expect(wrapper.findComponent(FooterForm).exists()).toBe(true);
});
});
If I run this test with the updated component written in Vue 3/Nuxt 3 then I get the error: [Vue warn]: Component <Anonymous>: setup function returned a promise, but no <Suspense> boundary was found in the parent component tree. A component with async setup() must be nested in a <Suspense> in order to be rendered.
I read up online about testing async components with the new Vue composition API and I have been trying some different methods, this seems to be the most common suggestion but it doesn't find the child FooterForm component and everything seems to be empty
The new test (Vue 3/Nuxt 3):
import { shallowMount, flushPromises } from "@vue/test-utils";
import { defineComponent } from 'vue';
import GlobalFooter from "./GlobalFooter";
import FooterForm from "./form/FooterForm";
import "@testing-library/jest-dom";
import { mockFooterData } from '../assets/data/footer-mock-data';
const mockedFooterData = {
propsData: {
emailTitle: "email title",
emailSubtext: "email subtext"
}
};
async function mountWithSuspense (component, options) {
const wrapper = defineComponent({
components: { component },
props: Object.keys(options.props ?? {}),
template: `<suspense><GlobalFooter v-bind="$props" /></suspense>`
})
const result = shallowMount(wrapper, options)
await flushPromises()
return result
}
test('Should render EloquaForm component', async () => {
const wrapper = await mountWithSuspense(GlobalFooter, mockedFooterData)
expect(wrapper.findComponent(FooterForm).exists()).toBe(true);
})