vitest-dev / vitest

Next generation testing framework powered by Vite.
https://vitest.dev
MIT License
12.96k stars 1.16k forks source link

TypeError: window.matchMedia is not a function in Vitest #821

Closed matheusgomes062 closed 2 years ago

matheusgomes062 commented 2 years ago

Describe the bug

This is my first vue3 testing experience. In this project, I'm using Vitest mount testing and got an error "TypeError: window.matchMedia is not a function."

I read through Vitest documentation and also Jest (Just in case), then I found the "[official workaround]"(https://stackoverflow.com/questions/39830580/jest-test-fails-typeerror-window-matchmedia-is-not-a-function), but it does not work.

full error code:

 FAIL  test/component.test.ts [ test/component.test.ts ]
TypeError: window.matchMedia is not a function
 ❯ update node_modules/.pnpm/@vueuse+core@7.6.2_vue@3.2.31/node_modules/@vueuse/core/index.mjs:523:27
    521|       return;
    522|     if (!mediaQuery)
    523|       mediaQuery = window.matchMedia(query);
       |                           ^
    524|     matches.value = mediaQuery.matches;
    525|   };
 ❯ node_modules/.pnpm/@vueuse+core@7.6.2_vue@3.2.31/node_modules/@vueuse/core/index.mjs:527:5
 ❯ Object.tryOnMounted node_modules/.pnpm/@vueuse+shared@7.6.2_vue@3.2.31/node_modules/@vueuse/shared/index.mjs:870:5
 ❯ useMediaQuery node_modules/.pnpm/@vueuse+core@7.6.2_vue@3.2.31/node_modules/@vueuse/core/index.mjs:526:2
 ❯ usePreferredDark node_modules/.pnpm/@vueuse+core@7.6.2_vue@3.2.31/node_modules/@vueuse/core/index.mjs:897:10
 ❯ useColorMode node_modules/.pnpm/@vueuse+core@7.6.2_vue@3.2.31/node_modules/@vueuse/core/index.mjs:931:25
 ❯ Object.useDark node_modules/.pnpm/@vueuse+core@7.6.2_vue@3.2.31/node_modules/@vueuse/core/index.mjs:1087:16

Reproduction

You can use my repo to test it: https://github.com/matheusgomes062/mgodev the file path is /test/component.test.ts

System Info

Could not run the bash command, so here's my package.json:

{
  "private": true,
  "scripts": {
    "build": "vite-ssg build",
    "dev": "vite --port 3333 --open",
    "lint": "eslint \"**/*.{vue,ts,js}\"",
    "preview": "vite preview",
    "preview-https": "serve dist",
    "test": "vitest",
    "test:e2e": "cypress open",
    "test:unit": "vitest",
    "typecheck": "vue-tsc --noEmit"
  },
  "dependencies": {
    "@types/pug": "^2.0.6",
    "@vue/compiler-sfc": "^3.2.31",
    "@vueuse/core": "^7.6.2",
    "@vueuse/head": "^0.7.5",
    "nprogress": "^0.2.0",
    "pinia": "^2.0.11",
    "prism-theme-vars": "^0.2.2",
    "pug": "^3.0.2",
    "uniqid": "^5.4.0",
    "vite-plugin-style-import": "^2.0.0",
    "vue": "^3.2.31",
    "vue-demi": "^0.12.1",
    "vue-i18n": "^9.1.9",
    "vue-router": "^4.0.12"
  },
  "devDependencies": {
    "@antfu/eslint-config": "^0.16.1",
    "@iconify-json/carbon": "^1.1.1",
    "@iconify-json/el": "^1.1.0",
    "@iconify-json/fa": "^1.1.0",
    "@iconify-json/fa-regular": "^1.1.0",
    "@iconify-json/fa-solid": "^1.1.0",
    "@iconify-json/ic": "^1.1.0",
    "@iconify-json/mdi": "^1.1.0",
    "@intlify/vite-plugin-vue-i18n": "^3.3.0",
    "@types/jest": "^27.4.0",
    "@types/markdown-it-link-attributes": "^3.0.1",
    "@types/nprogress": "^0.2.0",
    "@types/uniqid": "^5.3.2",
    "@vitejs/plugin-vue": "^2.2.2",
    "@vue/test-utils": "^2.0.0-rc.18",
    "critters": "^0.0.16",
    "cross-env": "^7.0.3",
    "cypress": "^9.5.0",
    "eslint": "^8.9.0",
    "eslint-plugin-cypress": "^2.12.1",
    "https-localhost": "^4.7.1",
    "markdown-it-link-attributes": "^4.0.0",
    "markdown-it-prism": "^2.2.3",
    "pnpm": "^6.31.0",
    "typescript": "^4.5.5",
    "unplugin-auto-import": "^0.5.11",
    "unplugin-icons": "^0.13.2",
    "unplugin-vue-components": "^0.17.18",
    "vite": "^2.8.4",
    "vite-plugin-inspect": "^0.3.14",
    "vite-plugin-md": "^0.11.8",
    "vite-plugin-pages": "^0.20.2",
    "vite-plugin-pwa": "^0.11.13",
    "vite-plugin-vue-layouts": "^0.6.0",
    "vite-plugin-windicss": "^1.7.1",
    "vite-ssg": "^0.17.10",
    "vitest": "^0.3.6",
    "vue-tsc": "^0.31.4"
  }
}

I'm also using W10 and node v16.13.2

Used Package Manager

pnpm

Validations

matheusgomes062 commented 2 years ago

My mistake, it's working fine. All I needed to do was to create a setup.ts for testing files

image

and put this code:

Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: vi.fn().mockImplementation(query => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: vi.fn(), // deprecated
    removeListener: vi.fn(), // deprecated
    addEventListener: vi.fn(),
    removeEventListener: vi.fn(),
    dispatchEvent: vi.fn(),
  })),
})

Then, at vite.config.ts I changed the config for test. Like this:

test: {
    include: ['test/**/*.test.ts'],
    environment: 'jsdom',
    deps: {
      inline: ['@vue', '@vueuse', 'vue-demi', '@vue/composition-api'],
    },
    setupFiles: [resolve(__dirname, 'test/setup/setup.ts')],
    reporters: 'dot',
  },