vuetify icon indicating copy to clipboard operation
vuetify copied to clipboard

[Documentation][3.0.0-beta.1] Unit testing

Open wildone opened this issue 4 years ago • 15 comments

Environment

Vuetify Version: 3.0.0-alpha.12 Vue Version: 3.2.13 Browsers: Chrome 98.0.4758.102 OS: Windows 10

Steps to reproduce

git clone https://github.com/governance-foundation/template-electron-vuex-vuetify.git cd template-electron-vuex-vuetify npm install npm run test:unit

Expected Behavior

unit test pass

Actual Behavior

 FAIL  src/components/__tests__/HelloWorld.spec.ts [ src/components/__tests__/HelloWorld.spec.ts ]
ReferenceError: CSS is not defined
 ❯ node_modules/vuetify/lib/util/globals.mjs:7:52
      5| export const SUPPORTS_INTERSECTION = IN_BROWSER && 'IntersectionObserver' in window;
      6| export const SUPPORTS_TOUCH = IN_BROWSER && ('ontouchstart' in window || window.navigator.maxTouchPoints > 0);
      7| export const SUPPORTS_FOCUS_VISIBLE = IN_BROWSER && CSS.supports('selector(:focus-visible)');
       |                                                    ^
      8| //# sourceMappingURL=globals.mjs.map
 ❯ async node_modules/vuetify/lib/util/index.mjs:19:31
 ❯ async node_modules/vuetify/lib/composables/tag.mjs:2:31
 ❯ async node_modules/vuetify/lib/components/VGrid/VContainer.mjs:7:31

Reproduction Link

https://github.com/governance-foundation/template-electron-vuex-vuetify

Other comments

I have globals set, and setup files mocking global.CSS.

wildone avatar Feb 20 '22 14:02 wildone

https://github.com/vuetifyjs/vuetify/blob/a582eea2df1e5747096c98d58b8b19a930f221f2/packages/vuetify/test/index.ts#L111

KaelWD avatar Feb 20 '22 14:02 KaelWD

https://github.com/vuetifyjs/vuetify/blob/a582eea2df1e5747096c98d58b8b19a930f221f2/packages/vuetify/test/index.ts#L111

Thank you I've added that to by beforeAll.

And now new error.

[Vuetify] Could not find defaults instance

It never ends :( Ive looked for a concrete way of loading it but nothing works so far.

wildone avatar Feb 21 '22 12:02 wildone

https://github.com/vuetifyjs/vuetify/blob/49ea21b108da925215ae6c337fa959a532116d66/packages/vuetify/src/components/VRating/tests/VRating.spec.ts#L10-L18

KaelWD avatar Feb 21 '22 13:02 KaelWD

Ok thank you, for your help @KaelWD got it working. I used this thread as a guide https://github.com/vuetifyjs/vuetify/issues/13936 as well.

import { describe, it, expect } from "vitest"
import { createVuetify } from "vuetify"
import * as components from "vuetify/components"
import * as directives from "vuetify/directives"

import { mount, shallowMount } from "@vue/test-utils"
import HelloWorld from "@/components/HelloWorld.vue"

describe("HelloWorld", () => {
  const vuetify = createVuetify({ components, directives })

  it("renders properly", () => {
    const wrapper = mount(HelloWorld, {
      global: {
        plugins: [vuetify],
      },
      props: { title: "Hello Vitest" },
    })
    expect(wrapper.text()).toContain("Hello Vitest")
  })
})

So the lesson is to declare vuetify in all your tests and use it to mount to the component.

wildone avatar Feb 21 '22 13:02 wildone

@wildone I tried your code and it's not working...

FAIL src/components/tests/HelloWorld.spec.js [ src/components/tests/HelloWorld.spec.js ] ReferenceError: CSS is not defined

Did I miss something? I have a repo to reproduce this issue: https://github.com/mpont91/vue3-vuetify-tests

If you can help me with a PR or anything I would appreciate. Thank you

mpont91 avatar Mar 08 '22 13:03 mpont91

I'm still trying to solve this problem.

Created vitest.config.js:

import { defineConfig } from 'vitest/config'

export default defineConfig({
    test: {
        setupFiles: 'vuetify.config.js'
    },
})

Created vuetify.config.js:

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

And now the test is failing with this error: TypeError: Unknown file extension ".css" for vue3-vuetify-tests/node_modules/vuetify/lib/components/VCode/VCode.css

You can reproduce the problem with my repo: https://github.com/mpont91/vue3-vuetify-tests

mpont91 avatar Mar 22 '22 14:03 mpont91

I don't know how, after much searching and clicking, I got to here and lo and behold this example works! Hallelujah and thankyou to @wildone https://github.com/governance-foundation/template-electron-vuex-vuetify

kpturner avatar Apr 12 '22 21:04 kpturner

I don't know how, after much searching and clicking, I got to here and lo and behold this example works! Hallelujah and thankyou to @wildone https://github.com/governance-foundation/template-electron-vuex-vuetify

Your link shows the following interesting results:

  • global setup (triggered before and after the tests run) can set global CSS support to false, but will not update with watch
  • beforeAll setup using a simplistic plugin entry (before test are triggered - including watch - to be able to rerun any changes on the fly)

To summarize your findings, which I had success with on multiple levels; the solution is indeed something which solves the OP's problem (CSS not defined) but also instance not defined meaning Vuetify has not been instantiated as plugin. The latter would be nice to figure out in a global/beforeAll solution (instead on each component mount).

davidzwa avatar Apr 13 '22 16:04 davidzwa

I've commented the plugin and the global approach in my vite config below, may it help anybody in need. Note: I have not removed anything after Vite setup (left it as untouched as possible), but of course this might include my setup choices like the optional vueJsx plugin. Note2: curious to understand the impact of the addition of ".css" to the resolve:extensions section.

import vueJsx from "@vitejs/plugin-vue-jsx";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vuetify from "@vuetify/vite-plugin";
import { fileURLToPath, URL } from "url";

// https://github.com/governance-foundation/template-electron-vuex-vuetify/blob/master/vite.config.ts
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
// Custom plugin entry
    {
      name: "vitest-plugin-beforeall",
      config: () => ({
        test: { setupFiles: ["./vitest/beforeAll.ts"] },
      }),
    },
    vue({
      // Allows for deconstructing props etc
      reactivityTransform: true,
    }),
    vueJsx(),
    // https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
    vuetify({
      autoImport: true,
    }),
  ],
  define: { "process.env": {} },
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("./src", import.meta.url)),
      // '@': path.resolve(__dirname, 'src'),
    },
    extensions: [
      ".js",
      ".json",
      ".jsx",
      ".mjs",
      ".ts",
      ".tsx",
      ".vue",
      ".css",
      ".scss",
    ],
  },
// Global setup functionality
  test: {
    globals: true,
    globalSetup: ["./vitest/setup.ts"],
    environment: "jsdom",
    deps: {
      inline: ["vuetify"],
    },
  },
  /* remove the need to specify .vue files https://vitejs.dev/config/#resolve-extensions
  resolve: {
    extensions: [
      '.js',
      '.json',
      '.jsx',
      '.mjs',
      '.ts',
      '.tsx',
      '.vue',
    ]
  },
  */
});

beforeAll.ts:

import { beforeAll } from "vitest";
(global as any).CSS = { supports: () => false };

beforeAll(() => {
  console.log("beforeAll");
  global.CSS = {
    supports: (str: string) => false,
    escape: (str: string) => str,
  };
  console.log("CSS.support:" + CSS.supports("selector(:focus-visible)"));
});

setup.ts:

export async function setup() {
  // global.CSS = {
  //   supports: (str: string) => false,
  //   escape: (str: string) => str,
  // };

  console.log("vitest globalSetup2.");
  // console.log("CSS.support:" + CSS.supports("selector(:focus-visible)"));
}

export async function teardown() {
  console.log("vitest globalTeardown");
}

davidzwa avatar Apr 13 '22 16:04 davidzwa

Not sure about

define: { "process.env": {} },

in the config. That seems to break the ability to reference VITE_.... environment variables on the client via import.meta.env

kpturner avatar Apr 17 '22 08:04 kpturner

same issue with vitest Unknown file extension ".css" for [email protected][email protected]/node_modules/vuetify/lib/components/VBtn/VBtn.css let me know if I can help with testing anything

tumulte avatar Apr 28 '22 20:04 tumulte

here’s a stackblitz for a better understanding of the bug : https://stackblitz.com/edit/vitejs-vite-e8jeuj (with npm run test)

tumulte avatar Apr 29 '22 20:04 tumulte

I'm still stuck on my last reply. When you create a project with default vue3 (with tests) and add the vuetify the first error you encounter when you run the tests is:

ReferenceError: CSS is not defined

To solve this you add:

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

Then you encounter this another error:

TypeError: Unknown file extension ".css" for vue3-vuetify-tests/node_modules/vuetify/lib/components/VCode/VCode.css

And I'm stuck here, don't know how to solve this. Don't understand the other people who commented on this issue how to solve it.

mpont91 avatar May 16 '22 11:05 mpont91

I finally managed to pass the tests. The last step is add this on vite.config.js

  test: {
    setupFiles: "vuetify.config.js",
    deps: {
      inline: ["vuetify"],
    },
    globals: true,
  }

And vuetify.config.js has the css support false:

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

I leave my repo reproducing the problem and the last commit solving it, so it can help someone. https://github.com/mpont91/vue3-vuetify-tests

mpont91 avatar May 17 '22 08:05 mpont91

Using Typescript there are some different configuration to put in the settings, the following errors happens here:

Error: [Vuetify] Could not find defaults instance
 ❯ Module.useDefaults node_modules/vuetify/src/composables/defaults.ts:25:23`

and:

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Error ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Error: ENOENT: no such file or directory, open 'xxxxx/dashboard-vue3/node_modules/vuetify/src/composables/defaults.ts'
❯ Object.openSync node:fs:585:3
❯ readFileSync node:fs:453:35
❯ xxxxx/dashboard-vue3/node_modules/vitest/dist/chunk-vite-node-externalize.42b0363f.js:10080:26
❯ printStack xxxxx/dashboard-vue3/node_modules/vitest/dist/chunk-vite-node-externalize.42b0363f.js:10165:32
❯ printError xxxxx/dashboard-vue3/node_modules/vitest/dist/chunk-vite-node-externalize.42b0363f.js:10078:3
❯ processTicksAndRejections node:internal/process/task_queues:96:5
❯ async DefaultReporter.printTaskErrorsxxxxx/dashboard-vue3/node_modules/vitest/dist/chunk-vite-node-externalize.42b0363f.js:8663:7
❯ async DefaultReporter.reportSummary xxxxx/dashboard-vue3/node_modules/vitest/dist/chunk-vite-node-externalize.42b0363f.js:8609:7
❯ async DefaultReporter.onFinished xxxxx/dashboard-vue3/node_modules/vitest/dist/chunk-vite-node-externalize.42b0363f.js:8500:5
❯ async DefaultReporter.onFinishedxxxxx/dashboard-vue3/node_modules/vitest/dist/chunk-vite-node-externalize.42b0363f.js:9290:5

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: {
 "code": "ENOENT",
 "errno": -2,
 "path": "/xxxxx/dashboard-vue3/node_modules/vuetify/src/composables/defaults.ts",
 "syscall": "open",
}

AntonyRafael avatar May 27 '22 20:05 AntonyRafael

I finally got it working as follows:

// vite.config.js
export default defineConfig(() => {
  return {
    test: {
      environment: 'jsdom',
      setupFiles: ['./test/setupVuetify.js', './test/setupPlugins.js'],
      deps: {
        inline: ['vuetify'],
      },
    },
  };
});
// test/setupVuetify.js
global.CSS = { supports: () => false };
// test/setupPlugins.js
import { config } from '@vue/test-utils';
import { createI18n } from 'vue-i18n';
import { createVuetify } from 'vuetify';

config.global.plugins = [createI18n(), createVuetify()];

gkubisa avatar Aug 23 '22 08:08 gkubisa

I have been struggling with this issue All of the above solution is for Vite. Can someone help me with Vue cli configuration for this issue. I am using cypress for e2e @KaelWD @gkubisa would appreciate your help.

rahil001 avatar Aug 25 '22 04:08 rahil001

Cypress uses a real browser so shouldn't have this problem.

KaelWD avatar Aug 25 '22 04:08 KaelWD

I created a repository solving this use case:

https://github.com/AntonyRafael/vuetify3beta-vite-ts-basic-tests

AntonyRafael avatar Aug 25 '22 11:08 AntonyRafael

@KaelWD when I am running yarn test:unit I am seeing below error saying CSS not defined. I am not using Vite but Vue cli

Screenshot 2022-08-25 at 7 07 19 PM

rahil001 avatar Aug 25 '22 13:08 rahil001

Cypress uses a real browser so shouldn't have this problem.

Sorry for the confusion but the issue was when running unit test

rahil001 avatar Aug 25 '22 13:08 rahil001

Yeah that's Mocha.

KaelWD avatar Aug 25 '22 13:08 KaelWD

Yeah that's Mocha.

What do you suggest ?

rahil001 avatar Aug 25 '22 13:08 rahil001

I don't know you'll have to read the mocha documentation to figure out a similar config.

KaelWD avatar Aug 25 '22 13:08 KaelWD

For some reason this is still happening on [email protected] while using [email protected].

P.S. Curious why it's mentioning node_modules/src when there is no src in the compiled vuetify... 🤷

TypeError: CSS.supports is not a function
 ❯ node_modules/vuetify/src/util/globals.ts:4:86

kendallroth avatar Sep 07 '22 14:09 kendallroth

What is typeof CSS?

there is no src

It's probably using sourcemaps

KaelWD avatar Sep 07 '22 14:09 KaelWD

Logging typeof CSS in the vitest setup file results in object, while checking for typeof CSS.supports results in undefined. If I add back the global.CSS = {supports: () => false}; workaround then it works again; however, removing it (as indicated in above fix) causes the same errors to return.

Update:

Was able to verify that node_modules/vuetify/dist/vuetify.js does contain the above fix:

const SUPPORTS_FOCUS_VISIBLE = IN_BROWSER && typeof CSS !== 'undefined' && CSS.supports('selector(:focus-visible)');

kendallroth avatar Sep 07 '22 16:09 kendallroth

I wonder if there is any relation to https://github.com/jsdom/jsdom/issues/2026, which indicates that some DOM libraries (jsdom in that case) do not support the supports property specifically? While I am using happy-dom environment (and not jsdom), I wonder if it might be something similar? Should the check be updated to also check that the CSS.supports function exists (rather than just CSS object itself)?

Update:

It does appear that happy-dom has added support; however, not sure about versions (https://github.com/capricorn86/happy-dom/issues/352)

Update 2

Cannot get this to work by patching the dist builds to also check whether CSS.supports is not undefined. Have tried updating the vuetify.js, vuetify.min.js, and vuetify.esm.js without any luck of even getting a log statement to fire (which means I'm doing something wrong clearly 🤦).

kendallroth avatar Sep 07 '22 16:09 kendallroth

I use vue-test-utils with jest 27 and TS 4.5

I did a simple test

import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'

describe('TodoList.vue', () => {
  const vuetify = createVuetify({ components, directives })
...

const wrapper = shallowMount(TodoList, {
      global: {
        plugins: [pinia, vuetify]
      }
})

But I got this error:

C:\Users\DanielRangel\Desktop\Test\test-ts-jest\test-ts-jest\node_modules\vuetify\lib\framework.mjs:2 import { createDefaults, DefaultsSymbol } from "./composables/defaults.mjs"; ^^^^^^

SyntaxError: Cannot use import statement outside a module

rangeldor avatar Sep 16 '22 22:09 rangeldor

@rangeldor I ended up having to use --experimental-vm-modules to fix that. node --experimental-vm-modules $(yarn bin jest)

jssuttles avatar Sep 22 '22 16:09 jssuttles