18

I try to bootstrap a simple app based on the following Vue3, Vite, Vitest

I also installed the vue 3 compatible version of vue test utils to test vue components.

I have an error trying to replicate the basic example in the docs :

import { mount } from "@vue/test-utils";
import { expect, test } from 'vitest'


// The component to test
const MessageComponent = {
  template: "<p>{{ msg }}</p>",
  props: ["msg"],
};

test("displays message", () => {
  const wrapper = mount(MessageComponent, {
    props: {
      msg: "Hello world",
    },
  });

  // Assert the rendered text of the component
  expect(wrapper.text()).toContain("Hello world");
});

 FAIL  src/tests/hello-world.test.ts > displays message
ReferenceError: document is not defined
 ❯ Proxy.mount node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js:7840:14
    7838|     addToDoNotStubComponents(component);
    7839|     registerStub({ source: originalComponent, stub: component });
    7840|     var el = document.createElement('div');
       |              ^
    7841|     if (options === null || options === void 0 ? void 0 : options.attachTo) {
    7842|         var to = void 0;
Re-running tests... [ src/tests/hello-world.test.ts ]

My package.json

{
  "name": "vite-vue3-poc",
  "version": "0.0.0",
  "scripts": {
    "serve": "vite preview",
    "build": "vite build",
    "coverage": "vitest --coverage",
    "dev": "vite",
    "preview": "vite preview",
    "test": "vitest"
  },
  "dependencies": {
    "@mdi/font": "5.9.55",
    "prettier": "^2.5.1",
    "roboto-fontface": "*",
    "vue": "^3.2.25",
    "vuetify": "^3.0.0-alpha.0",
    "webfontloader": "^1.0.0"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^2.0.0",
    "@vue/cli-plugin-babel": "5.0.0-beta.7",
    "@vue/cli-service": "5.0.0-beta.7",
    "@vue/test-utils": "^2.0.0-rc.18",
    "@vuetify/vite-plugin": "^1.0.0-alpha.3",
    "sass": "^1.38.0",
    "sass-loader": "^10.0.0",
    "vite": "^2.7.2",
    "vitest": "^0.1.23",
    "vue-cli-plugin-vuetify": "~2.4.5",
    "vuetify-loader": "^2.0.0-alpha.0"
  }
}

vite.config.js

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

import path from "path";
/// <reference types="vitest" />

// Configure Vitest (https://vitest.dev/config)

// https://vitejs.dev/config/
export default defineConfig({
  test: {
    /* for example, use global to avoid globals imports (describe, test, expect): */
    // globals: true,
  },
  plugins: [
    vue(),

    // https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
    vuetify({
      autoImport: true,
    }),
  ],
  define: { "process.env": {} },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
    },
  },
});

Pierre_T
  • 1,094
  • 12
  • 29
  • 2
    The problem is specific to testing framework you're using, vitest, not anything else. You're not in a good situation when using low-profile libs that don't have extensive support from the community. Since it seems to use Jest internally, this is likely solved from Jest side by enforcing Jest's `jsdom` environment. – Estus Flask Jan 19 '22 at 12:13
  • Thx. This helped me finding a way (see below) – Pierre_T Jan 19 '22 at 13:20

4 Answers4

20

Finally fixed it by manually installing jsdom and declaring it in vite.config.ts

export default defineConfig({
  test: {

    globals: true,
    environment: "jsdom",
  },
...
}
Pierre_T
  • 1,094
  • 12
  • 29
8

Like others have pointed out, you need to set environment: 'jsdom' in vitest.config.ts. Alternatively, you could set environment: 'happy-dom'.

In the example provided by the Vitest documentation, they used to use happy-dom instead of jsdom. From what I gather, happy-dom is a faster alternative to jsdom. I'm using happy-dom in my project, and I'm happy with it! :)

EDIT: I changed my wording to reflect the fact that the Vitest example used to use happy-dom. As of this writing, it uses jsdom.

liammulh
  • 81
  • 3
5

This config helped me

Your vite.config.ts

import { fileURLToPath, URL } from "node:url"
import { defineConfig } from "vite"
import type { UserConfig as VitestUserConfigInterface } from "vitest/config"
import vue from "@vitejs/plugin-vue"

const vitestConfig: VitestUserConfigInterface = {
  test: {
    globals: true,
    environment: "jsdom",
  },
}

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
    },
  },
  test: vitestConfig.test,
})
Raphael Deiana
  • 750
  • 4
  • 20
Atomic town
  • 51
  • 1
  • 2
3

No need to install jsdom manually. By setting environment: "jsdom" in the test property, Vitest automatically asks you if you want to install it.