[Documentation][3.0.0-beta.1] Unit testing
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.
https://github.com/vuetifyjs/vuetify/blob/a582eea2df1e5747096c98d58b8b19a930f221f2/packages/vuetify/test/index.ts#L111
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.
https://github.com/vuetifyjs/vuetify/blob/49ea21b108da925215ae6c337fa959a532116d66/packages/vuetify/src/components/VRating/tests/VRating.spec.ts#L10-L18
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 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
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
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
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).
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");
}
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
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
here’s a stackblitz for a better understanding of the bug : https://stackblitz.com/edit/vitejs-vite-e8jeuj (with npm run test)
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.
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
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",
}
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()];
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.
Cypress uses a real browser so shouldn't have this problem.
I created a repository solving this use case:
https://github.com/AntonyRafael/vuetify3beta-vite-ts-basic-tests
@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
Cypress uses a real browser so shouldn't have this problem.
Sorry for the confusion but the issue was when running unit test
Yeah that's Mocha.
Yeah that's Mocha.
What do you suggest ?
I don't know you'll have to read the mocha documentation to figure out a similar config.
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
What is typeof CSS?
there is no src
It's probably using sourcemaps
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)');
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 🤦).
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 I ended up having to use --experimental-vm-modules to fix that.
node --experimental-vm-modules $(yarn bin jest)