Combination of Vue 3 + Vuetify 3 + vue/test-utils, results in "Could not find injected Vuetify layout" error

Viewed 693

Does anyone know how to do component testing in @vue/test-utils v2 library, while using Vuetify 3 Beta version? I am also using Vue3 composition API to define my components. The documentation that i found here https://vuetifyjs.com/en/getting-started/unit-testing/#spec-tests is not working, since it is for Vuetify v2 and @vue/test-utils v1

This is my plugins/vuetify.js

import '@mdi/font/css/materialdesignicons.css';
import 'vuetify/styles';
import { createVuetify } from 'vuetify';

export default createVuetify();

This is my code in NavBar.spec.js

import { mount } from '@vue/test-utils';
import NavBar from '../NavBar.vue';
import Vuetify from '../../plugins/vuetify';

describe('NavBar', () => {
    it('No properties [correct]', () => {
        mount(NavBar, {
            props: {},
            global: {
                plugins: [Vuetify]
            }
        });
        // check if navbar renders
        cy.get('.main')
            .first();

    });
});

This is the error i receive: Could not find injected Vuetify layout

2 Answers

I have the same issue and I am using vitest.

Thanks for this GitHub issue

I solved it by adding global.plugin in each test file as below.

ToDoList.test.js

import { createVuetify } from "vuetify";
import { mount } from "@vue/test-utils";
import ToDoList from "./ToDoList.vue";

describe("ToDoList.vue", () => {
    const vuetify = createVuetify()

    it("renders", () => {
        const wrapper = mount(ToDoList, {
            props: {
                title: "testTitle",
                text: "testText",
            },
            global: {
                plugins: [vuetify],
            },
        });
    });
});

I also need to add some configuration in vite.config.js as below

vite.config.js

/// <reference types="vitest" />

import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vuetify from "vite-plugin-vuetify";

const path = require("path");

export default defineConfig({
    //...other config...
    test: {
        globals: true,
        environment: "jsdom",
        setupFiles: "vuetify.config.js",
        deps: {
            inline: ["vuetify"],
        },
    },
});

Finally, I create a vuetify.config.js file in the root directory referenced from the setupFiles properties of vite.config.js

vuetify.config.js

global.CSS = { supports: () => false };

I was having the same issue, someone answered a similar question saying they fixed the error by moving their component within the <v-app> tag.

If like me however your component was already within your top level <v-app> tag, other people online had success by adding

let el = document.createElement("div");
el.setAttribute("data-app", "true");
document.body.appendChild(el);

before your test, but this also didn't work for my setup.

(I found wrapping my component in a <v-app> tag got my tests to work, but you shouldn't have multiple of those on your page and you don't want to have to add extra code to every component just for your tests to pass.)

If that solution doesn't work for you either though, I eventually worked around it by mounting the VApp component itself and passing my component to it as the default slot content, like so:

import { h } from "vue";
import { VApp } from "vuetify/components";
import MyComponent from "./MyComponent.vue";

describe("Test", () => {
  it("should", () => {
    const wrapper = mount(VApp, {
      slots: {
        default: h(MyComponent),
      }
    })
  )}
)}

(thanks to this GitHub thread for the assist)

Hopefully this is just an issue as Vuetify 3 is still in beta, and once they formalise best testing practice we should be able to remove this custom fix.

Hope this helps!

Related