Skip to content

Testing Vue Components

To mount a vue components and get access to the setup function along with anything injected in plugins we can use the mountSuspended function.

ts
import { describe, expect, beforeEach, it, test } from "vitest"
import ArkForm from "..."
import Field from "..."

describe("description", () => {
    beforeEach(async () => {
        await mountSuspended(ArkForm, {
            // pass in props
            props: { name: formName },
        })
    })
    it("should do something", async () => {
        // ctx: after component mounts
    })

    it("something", async () => {
        // or we can access the component api
        const wrapper = await mountSuspended(ArkForm, {
            props: { name: formName },
        })

        wrapper.classes()
        wrapper.props()
        wrapper.exists()
        wrapper. // ...
    })


    it("should handle edge case", async () => {
        // test logic 3
    })
})

We can also pass in slots by rendering our component using the h render function.

ts
import { describe, expect, beforeEach, it, test } from "vitest"
import ArkForm from "..."
import Field from "..."

describe("description", () => {
    beforeEach(async () => {
        const wrapper = await mountSuspended(ArkForm, {
            props: { name: formName },
            slots: {
                // Mount with a child componment in the slot.
                default: h(Field, { name: "hello" }),
                namedSlot: // ..
            },

            // Make sure to expose the nested component within the wrapper context.
            global: { components: { Field } },
        })
    })
})

A great way to access component state while testing would be to abstract the component into a composable. Then the test and the template will share the same composable interface.

Here is an example. We mount two slots to the <arkform /> component. Then use the useLoginForm composable to assert state transformations.

ts
describe("description", () => {
    beforeEach(async () => {
        await mountSuspended(Arkform, {
            props: { name: "login" },
            slots: {
                default: [
                    h(Field, { name: "email", ark: ["string.email"] }),
                    h(Field, { name: "password", ark: ["string>=6"] }),
                ],
            },
            global: { components: { Field } },
        })
    })

    it("wrong email: fails to login", async () => {
        const { submit, formName, state } = useLoginForm()
        const { set, input } = $form(formName)

        set({
            email: "mail.com",
            password,
        })

        const out = await submit()

        expect(out.ok).toBe(false)
        expect(out.code).toBe(401)
    })
})