I'm working on a component that includes Password component. I would like to write unit test for it, but I get an error that I don't understand when I try to unit test the component.
We're using Primevue 3.3.5 with TS and Jest.
Here is the code without Password component that works great:
Code: Select all
<template>
<InputText v-model="letter" class="p-mr-2 p-ml-2 p-d-inline letter-input" :class="{'p-invalid' : error }" size="1" />
</template>
<script lang="ts">
import { defineComponent, watch } from "vue";
import * as yup from 'yup';
import { useField, useForm, useValidateForm } from 'vee-validate';
export default defineComponent({
name: "Letters",
props: {
modelValue: String,
submitTrigger: Boolean,
},
emits: ["update:modelValue", "error"],
setup(props, { emit }) {
const schema = yup.object({
letter: yup.string().min(1).max(1).matches(/^[a-z]*$/, 'letter must be a lowercase letter'),
});
const { meta } = useForm({
validationSchema: schema,
initialValues: {letter: ''}
});
const { errorMessage: error, value: letter } = useField('letter', schema);
const validate = useValidateForm();
watch(() => meta.value, () => {
console.log(error.value)
emit("update:modelValue", letter.value);
emit("error", error.value ? error.value : "");
});
watch(() => props.submitTrigger, () => {
validate().then(() => {
emit("error", error.value ? error.value : "");
});
});
return {
letter,
error,
};
},
})
</script>
<style scoped>
.letter-input {
text-align: center;
}
</style>
Here's the unit test associated (very basic):
Code: Select all
import { mount, shallowMount } from "@vue/test-utils";
import InputText from 'primevue/inputtext';
import OneLetter from "@/components/OneLetter.vue";
describe("Letters.vue", () => {
let one_letter_component = shallowMount(OneLetter, {
global: {
components: {
'InputText': InputText,
}
}
});
beforeEach(() => {
one_letter_component = mount(OneLetter, {
global: {
components: {
'InputText': InputText,
}
}
});
});
it("initialize with empty letter", () => {
expect(one_letter_component.vm.letter).toEqual("");
});
it("set value letter on a one-letter input", async () => {
await one_letter_component.find(".letter-input").setValue("a");
expect(one_letter_component.vm.letter).toEqual("a");
});
});
Code: Select all
<template>
<InputText v-model="letter" class="p-mr-2 p-ml-2 p-d-inline letter-input" :class="{'p-invalid' : error }" size="1" />
<Password />
</template>
<script lang="ts">
import { defineComponent, watch } from "vue";
import * as yup from 'yup';
import { useField, useForm, useValidateForm } from 'vee-validate';
export default defineComponent({
name: "Letters",
props: {
modelValue: String,
submitTrigger: Boolean,
},
emits: ["update:modelValue", "error"],
setup(props, { emit }) {
const schema = yup.object({
letter: yup.string().min(1).max(1).matches(/^[a-z]*$/, 'letter must be a lowercase letter'),
});
const { meta } = useForm({
validationSchema: schema,
initialValues: {letter: ''}
});
const { errorMessage: error, value: letter } = useField('letter', schema);
const validate = useValidateForm();
watch(() => meta.value, () => {
console.log(error.value)
emit("update:modelValue", letter.value);
emit("error", error.value ? error.value : "");
});
watch(() => props.submitTrigger, () => {
validate().then(() => {
emit("error", error.value ? error.value : "");
});
});
return {
letter,
error,
};
},
})
</script>
<style scoped>
.letter-input {
text-align: center;
}
</style>
To use this component in test, I need to add the Password component to the global component list when mounting the component, so here's the code of the test with just the addition of Password:
Code: Select all
import { mount, shallowMount } from "@vue/test-utils";
import InputText from 'primevue/inputtext';
import Password from "primevue/password";
import OneLetter from "@/components/OneLetter.vue";
describe("Letters.vue", () => {
let one_letter_component = shallowMount(OneLetter, {
global: {
components: {
'InputText': InputText,
'Password': Password,
}
}
});
beforeEach(() => {
one_letter_component = mount(OneLetter, {
global: {
components: {
'InputText': InputText,
'Password': Password,
}
}
});
});
it("initialize with empty letter", () => {
expect(one_letter_component.vm.letter).toEqual("");
});
it("set value letter on a one-letter input", async () => {
await one_letter_component.find(".letter-input").setValue("a");
expect(one_letter_component.vm.letter).toEqual("a");
});
});
Code: Select all
FAIL tests/unit/one_letter.spec.ts
- Console
console.warn node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-core@3.2.20/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6482
[Vue warn]: Unhandled error during execution of mounted hook
at <Password>
at <Letters ref="VTU_COMPONENT" >
at <VTUROOT>
- OneLetters.vue > initialize with empty letter
TypeError: Cannot read property 'config' of undefined
14 | });
15 | beforeEach(() => {
> 16 | one_letter_component = mount(OneLetter, {
| ^
17 | global: {
18 | components: {
19 | 'InputText': InputText,
at Proxy.promptText (node_modules/primevue/password/password.cjs.js:282:55)
at ReactiveEffect.run (node_modules/.pnpm/registry.npmmirror.com+@vue+reactivity@3.2.20/node_modules/@vue/reactivity/dist/reactivity.cjs.js:164:29)
at ComputedRefImpl.get value [as value] (node_modules/.pnpm/registry.npmmirror.com+@vue+reactivity@3.2.20/node_modules/@vue/reactivity/dist/reactivity.cjs.js:1075:39)
at Object.get [as promptText] (node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-core@3.2.20/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:2122:30)
at Object.get (node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-core@3.2.20/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5894:27)
at Proxy.mounted (node_modules/primevue/password/password.cjs.js:84:30)
at callWithErrorHandling (node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-core@3.2.20/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6599:22)
at callWithAsyncErrorHandling (node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-core@3.2.20/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6608:21)
at Array.hook.__weh.hook.__weh (node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-core@3.2.20/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:1948:29)
at flushPostFlushCbs (node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-core@3.2.20/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6794:47)
at render (node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-core@3.2.20/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4767:9)
at mount (node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-core@3.2.20/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:3146:25)
at Object.app.mount (node_modules/.pnpm/registry.npmmirror.com+@vue+runtime-dom@3.2.20/node_modules/@vue/runtime-dom/dist/runtime-dom.cjs.js:1521:23)
at mount (node_modules/.pnpm/registry.npmmirror.com+@vue+test-utils@2.0.0-rc.16_vue@3.2.20/node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js:7860:18)
at Object.<anonymous> (tests/unit/one_letter.spec.ts:16:32)
- OneLetters.vue > set value letter on a one-letter input
TypeError: Cannot set property 'hasOwnProperty' of undefined
14 | });
15 | beforeEach(() => {
> 16 | one_letter_component = mount(OneLetter, {
| ^
17 | global: {
18 | components: {
19 | 'InputText': InputText,
at mount (node_modules/.pnpm/registry.npmmirror.com+@vue+test-utils@2.0.0-rc.16_vue@3.2.20/node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js:7866:27)
at Object.<anonymous> (tests/unit/one_letter.spec.ts:16:32)
- OneLetters.vue > set value letter on a one-letter input
wrapper.setValue() cannot be called on INPUT-TEXT-STUB
27 | });
28 | it("set value letter on a one-letter input", async () => {
> 29 | await one_letter_component.find(".letter-input").setValue("a");
| ^
30 |
31 | expect(one_letter_component.vm.letter).toEqual("a");
32 | });
at DOMWrapper.Object.<anonymous>.DOMWrapper.setValue (node_modules/.pnpm/registry.npmmirror.com+@vue+test-utils@2.0.0-rc.16_vue@3.2.20/node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js:7389:19)
at Object.<anonymous> (tests/unit/one_letter.spec.ts:29:58)
Thanks for your help!
And congratulations for this amazing lib, I really enjoy working with it, apart for unit test