vitest icon indicating copy to clipboard operation
vitest copied to clipboard

Mock module does not work when imported in vue sfc files in typescript

Open leifmarcus opened this issue 3 years ago • 7 comments
trafficstars

Describe the bug

When importing the library plyr inside a Vue 3 SFC and mock it inside a test file, it will not be mocked. Instead the actual library is used inside the vue file.

Reproduction

Considering having a component as follows

<template>
  <div></div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import Plyr from 'plyr';

export default defineComponent({
  name: 'TestComponent',
  setup() {
    console.log(Plyr);
    return {};
  },
});
</script>

within the test the plyr library is mocked:

import { mount } from '@vue/test-utils';
import { vi } from 'vitest';
import TestComponent from './TestComponent.vue';

const onFunction = vi.fn();

vi.mock('plyr', () => {
  const plyrLib = vi.fn(() => ({
    on: onFunction,
  }));

  return {
    default: plyrLib,
  };
});

describe('TestComponent', () => {
  it('should register events', () => {
    mount(TestComponent);
    expect(onFunction).toHaveBeenCalled();
  });
});

When running the test, the actual Plyr class will be logged instead of the mocked library.

System Info

System:
    OS: macOS 12.4
    CPU: (10) x64 Apple M1 Pro
    Memory: 176.62 MB / 32.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 14.15.4 - ~/.nvm/versions/node/v14.15.4/bin/node
    npm: 6.14.10 - ~/.nvm/versions/node/v14.15.4/bin/npm
  Browsers:
    Chrome: 102.0.5005.115
    Chrome Canary: 105.0.5118.3
    Firefox: 101.0
    Safari: 15.5
  npmPackages:
    @vitejs/plugin-legacy: ^1.8.1 => 1.8.2 
    @vitejs/plugin-vue: ^2.3.3 => 2.3.3 
    vite: ^2.9.12 => 2.9.12 
    vitest: ^0.14.2 => 0.14.2

Used Package Manager

npm

Validations

leifmarcus avatar Jun 14 '22 10:06 leifmarcus

I had a similar issue and the comment below solved my problem. https://github.com/vitest-dev/vitest/issues/1450#issuecomment-1151357294

At the top of my test file, I now have:

const doSomething = vi.fn()
vi.resetModules()

import ...

vi.mock('@/helpers/functions', () => {
  return {
    doSomething,
  }
})

OneFourFree avatar Jun 14 '22 17:06 OneFourFree

Hello @OneFourFree, thank you for the response. I did already test your solution before I added this issue (I should have mention that in my description).

In my case this approach does not help. The plyr library is still not mocked. I think it might be related to imports from node_modules, that cannot be mocked?

UPDATE

I also added an example test on stackblitz. You get an error there that window.matchMedia is not defined, but this is not the problem I'm pointing at. If the mocking would work, the error would not appear.

leifmarcus avatar Jun 15 '22 06:06 leifmarcus

As I was investigating this issue a bit further I found, that other libraries can be mocked for instance like @vueuse/.. without any problems.

I also found, that when creating a file that has export { default } from 'plyr' and import that file in my component, then the mocking works as expected. I then mock the export of this file instead of mocking 'plyr' directly

leifmarcus avatar Jun 17 '22 09:06 leifmarcus

The next thing I tried was to directly mock the selected file inside the plyr bundle. So what worked for now is to import the library inside the component as before

// inside component
import Plyr from 'plyr';

and use mocking like

// vitest requests the module version of the plyr and if
// the correct file is mocked, the mocking will work.
vi.mock('plyr/dist/plyr.min.mjs', () => {
  // ...
})

This seems to be only related to the plyr library as I can see so far. I'm not sure, if this is to be considered as a bug. But this seems to be related to the module resolution that vite/vitest is internally using.

leifmarcus avatar Jun 17 '22 09:06 leifmarcus

There is a bug/inconsistency in Vite (https://github.com/vitejs/vite/issues/8659), and because of that we resolved paths differently, when processing vi.mock and import.

This change should fix that on Vitest side: https://github.com/vitest-dev/vitest/pull/1506

sheremet-va avatar Jun 19 '22 12:06 sheremet-va

@sheremet-va, today I tried the plyr library with Vitest version 0.16.0 and it seems, that the problem is not solved with this fix. I still need to mock the full file path to plyr/dist/plyr.min.mjs.

leifmarcus avatar Jun 28 '22 06:06 leifmarcus

Yeah, the fix would only work if you were doing vi.mock inside a Vue file. You need to wait for https://github.com/vitejs/vite/issues/8659 to be fixed

sheremet-va avatar Jun 28 '22 06:06 sheremet-va

Should be fixed by #1919

sheremet-va avatar Oct 28 '22 16:10 sheremet-va

I had a similar issue and the comment below solved my problem. #1450 (comment)

At the top of my test file, I now have:

const doSomething = vi.fn()
vi.resetModules()

import ...

vi.mock('@/helpers/functions', () => {
  return {
    doSomething,
  }
})

it works for me! thank you!

sunny15100 avatar Feb 09 '23 10:02 sunny15100