I'm using vue test utils to test a component and got this error when trying to test text. Unable to call text on empty DOMWrapper.
Updated code. "RangeError: Maximum call stack size exceeded" in atable.spec.ts test.
atable.spec.ts
import ATable from "../components/ATable.vue"; import { IPatientResponse } from "@/types/patients"; import { shallowMount, RouterLinkStub } from "@vue/test-utils"; it("renders proper texts.", () => { const wrapper = shallowMount(ATable, { props: { patients: [ { id: 1, firstName: "arpit", lastName: "satyal", email: "arpited7@gmail.com", contact: "12345", address: "ktm", dob: "1998-07-29", allergies: ["Pet allergies"], }, ] as IPatientResponse[], }, stubs: { RouterLink: RouterLinkStub, }, scopedSlots: { bodyCell: ` <template slot-scope="{ column, record }" v-if="column.key === 'firstName'"> <router-link :to="{ name: 'PatientProfile', params: { id: record.id } }"> <div id="test-patient">{{ record.firstName }} {{ record.lastName }}</div> </router-link> </template>`, } }); const patientNameSelector = wrapper.find("#test-patient"); // see if the message renders expect(patientNameSelector.text()).toEqual("arpit satyal"); });
Table view Refactor the table component into its own component. It now receives props from the dashboard component.
<!-- eslint-disable vue/multi-word-component-names --> <template> <section> <a-table :columns="columns" :data-source="patients" :pagination="false"> <template #bodyCell="{ column, record }"> <template v-if="column.key === 'firstName'"> <router-link :to="{ name: 'PatientProfile', params: { id: record.id } }"> <span id="test-patient">{{ record.firstName }} {{ record.lastName }}</span> </router-link> </template> <template v-else-if="column.key === 'specialAttention'"> <span class="pointer"> <EyeOutlined v-if="record.specialAttention" @click="markAsSpecial(record, false)" class="iconStyle" /> <EyeInvisibleOutlined v-else @click="markAsSpecial(record, true)" class="iconStyle" /> </span> </template> <template v-else-if="column.key === 'action'"> <span class="pointer"> <router-link :to="{ name: 'UpdatePatient', params: { id: record.id } }"> <EditOutlined style="margin-right: 10px" class="iconStyle" /> </router-link> <a-divider type="vertical" /> <DeleteOutlined @click="deletePatient(record.id)" class="iconStyle" /> <a-divider type="vertical" /> </span> </template> </template> </a-table> </section> </template> <script lang="ts"> import { EditOutlined, DeleteOutlined, EyeInvisibleOutlined, EyeOutlined, } from "@ant-design/icons-vue"; import { defineComponent } from "@vue/runtime-core"; const columns = [ { title: "Name", dataIndex: "firstName", key: "firstName", align: "center", }, { title: "Contact", dataIndex: "contact", key: "contact", align: "center", }, { title: "Address", dataIndex: "address", key: "address", align: "center", }, { title: "DOB", key: "dob", dataIndex: "dob", align: "center", }, { title: "Special Attention", key: "specialAttention", align: "center", }, { title: "Actions", key: "action", align: "center", }, ]; export default defineComponent({ props: ["deletePatient", "markAsSpecial", "patients"], components: { EditOutlined, DeleteOutlined, EyeInvisibleOutlined, EyeOutlined, }, data() { return { columns, }; }, }); </script>
P粉6974089212023-11-01 13:16:58
You are testing the Dashboard component and trying to check that the ATable (
) component renders the slot content passed to it. This is wrong.
Considering the ATable component, what you should check when testing the Dashboard component is whether the ATable component just rendered. That's it.
// In Dashboard.spec.js it("renders ATable component.", () => { const ATableStub = { template: '<div>ATableStub</div>' } const wrapper = shallowMount(Dashboard, { stubs: { ATable: ATableStub }, data() { return { patients: [ { id: 1, firstName: "arpit", lastName: "satyal", email: "arpited7@gmail.com", contact: "12345", address: "ktm", dob: "1998-07-29", allergies: ["Pet allergies"], }, ] as IPatientResponse[], }; }, }); wrapper.findComponent(ATableStub).exists.toBe(true); }); });
You should leave testing the slot contents of ATable to test the ATable component, not the Dashboard component.
// In ATable.spec.js import { shallowMount, RouterLinkStub } from '@vue/test-utils' it("renders proper texts.", () => { const wrapper = shallowMount(ATable, { stubs: { RouterLink: RouterLinkStub }, scopedSlots: { bodyCell: ` <template slot-scope="{ column, record }" v-if="column.key === 'firstName'"> <router-link :to="{ name: 'PatientProfile', params: { id: record.id } }"> <div id="test-patient">{{ record.firstName }} {{ record.lastName }}</div> </router-link> </template>` }, data() { return { patients: [ { id: 1, firstName: "arpit", lastName: "satyal", email: "arpited7@gmail.com", contact: "12345", address: "ktm", dob: "1998-07-29", allergies: ["Pet allergies"], }, ] as IPatientResponse[], }; }, }); const patientNameSelector = wrapper.find("#test-patient"); // see if the message renders expect(patientNameSelector.text()).toEqual("arpit satyal"); }); });