Import Password component in unit test

UI Components for Vue
Post Reply
Softyware
Posts: 1
Joined: 05 Aug 2021, 16:29

22 Nov 2021, 09:19

Hi,

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>
This component just has an input that should contain a lowercase letter. It emits the status of error to the parent component.
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");
    });
});
Now the tricky part: I add the Password component and do nothing with it. I added the import in main.ts so it's globally imported. Here's the code of the component:

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>
Everything is unchanged except in the template, there is a <Password /> tag.
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");
    });
});
And now there's an error:

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)
I don't understand why I get the error for this component, it seems to work smoothly for all other components such as Dropdown.

Thanks for your help!
And congratulations for this amazing lib, I really enjoy working with it, apart for unit test :P

Post Reply

Return to “PrimeVue”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 4 guests