vue-toastification icon indicating copy to clipboard operation
vue-toastification copied to clipboard

[Vue warn]: A plugin must either be a function or an object with an "install" function. Vue test utils

Open SoetZombie opened this issue 2 years ago • 18 comments

Versions

-2.0.5-rc

Describe the bug

Testing components using vueTestUtills on Vite, errors out on not being able to resolve the plugin.

Expected behavior

import VueToastificationPlugin from 'vue-toastification';

const wrapper = mount(InvoiceView, {
      props: { invoiceId: '2B8B364A-A45E-4922-85CF-0334EC5D4354' },
      global: {
        plugins: [store, VueToastificationPlugin],
      },
    });

should work just fine, instead vue displays warning: [Vue warn]: A plugin must either be a function or an object with an "install" function. Vue test utils and the test errors out on TypeError: __vite_ssr_import_16__.useToast is not a function

Steps to reproduce

  • create vite component that uses toastification
  • write a test using vue test utils
  • observe error

SoetZombie avatar Jul 21 '22 09:07 SoetZombie

Same issue here

jmaltis avatar Jul 24 '22 21:07 jmaltis

Same issue using render function of vue testing library

pstieger92 avatar Aug 08 '22 09:08 pstieger92

+1 NuxtRC9

or2e avatar Sep 05 '22 19:09 or2e

I got the same error, also using vite and vitest. In the normal aplication it works, but during tests it failed. Mocking with vi.mock('vue-toastification', ...); unfortunately didn't seem to do anything either.

What I did to solve the problem for now was writing a custom (wrapped) useToast function in a separate file:

src/plugins/toasts/index.ts:

import { useToast as useToastOriginal, ...} from 'vue-toastification';
//...
export const useToast = (): ReturnType<typeof useToastOriginal> => {
  return useToastOriginal();
};
//...

And in the file that you want to use it replace import { useToast } from 'vue-toastification'; with import { useToast } from '@/plugins/toasts'; Or something similar.

In case you wanted to test for a toast notification to be triggered you can place a spy:

const wrapperVm = wrapper.vm as unknown as typeof RootComponent;
const toastSuccessSpy = vi.spyOn(wrapperVm.toast, 'success');

expect(toastSuccessSpy).not.toHaveBeenCalled();

await new Promise(resolve => setTimeout(resolve, 500)); // Just for testing purposes :P

expect(toastSuccessSpy).toHaveBeenCalled();

I hope this helps anyone running into this problem.

arjenprogramic avatar Sep 20 '22 05:09 arjenprogramic

Similar issue here when running vitest + vue test utils.

@arjenprogramic 's solution worked for me

GradeyCullins avatar Sep 27 '22 17:09 GradeyCullins

+1 thanks for the workaround @arjenprogramic

MerzoukeMansouri avatar Sep 30 '22 15:09 MerzoukeMansouri

I'm also having the same issue using Vitest + Vue3

gbyesiltas avatar Oct 03 '22 14:10 gbyesiltas

+1 Same issue with vite, we had to add our custom hooks :/

samuelpoudroux avatar Oct 04 '22 13:10 samuelpoudroux

Same issue :(

tim-kilian avatar Oct 26 '22 09:10 tim-kilian

Same for NuxtRC12

BayBreezy avatar Oct 27 '22 00:10 BayBreezy

NuxtRC12, same issue... Fixed by more explicit import

// ./plugins/vue-toastification.ts

import Toast from "vue-toastification/dist/index.mjs";
import "vue-toastification/dist/index.css";

export default defineNuxtPlugin(nuxtApp => {
    nuxtApp.vueApp.use(Toast)
});

pavloniym avatar Oct 28 '22 21:10 pavloniym

I have the same issue while using vue-toasted, it seems like this is a @vue/test-utils bug which cannot inject plugins functions to the tested instance using @vue/test-utils mount options

I get the cannot read 'error' of undefined when use vm?.$toasted.error() as $toasted is not injected, same things happen with my other plugins

https://replit.com/join/rrjrziigds-bittermeatball

My test file:

import { mount } from "@vue/test-utils";
import { describe, expect, it } from "vitest";
import ToastPlugin from "vue-toasted";

import App from "./App.vue";

describe("App", () => {
  it("should be mounted normally", () => {
    const wrapper = mount(App, {
      global: {
        mocks: {},
        plugins: [ToastPlugin]
      }
    });

    expect(wrapper.vm).toBeTruthy();
  });
});

imrim12 avatar Oct 31 '22 10:10 imrim12

Same here, using vitest + vuejs3

kosekidev avatar Nov 14 '22 12:11 kosekidev

Same for Nuxt 3.0.0 Plugin init (plugins/toastification.js):

mport { defineNuxtPlugin } from 'nuxt/app'
import Toast from 'vue-toastification'

export default defineNuxtPlugin((nuxtApp) => {
  const toastOptions = {
    closeButton: false,
    timeout: 3000,
  }

  nuxtApp.vueApp.use(Toast, toastOptions)
})

kokamvd avatar Nov 23 '22 18:11 kokamvd

Same here, cannot use it as a plugin

victor-ponamariov avatar Jan 28 '23 10:01 victor-ponamariov

same issue, vuejs 3 + vite + vitest + @testing-library/vue

meiyerDev avatar Feb 17 '23 22:02 meiyerDev

https://github.com/Maronato/vue-toastification/issues/341#issuecomment-1295504287 this helps. Also if you want get rid of IDE warnings with import Toast this way, you can simply add // @ts-ignore before import.

// @ts-ignore
import Toast from "vue-toastification/dist/index.mjs";
import "vue-toastification/dist/index.css";

export default defineNuxtPlugin(nuxtApp => {
  nuxtApp.vueApp.use(Toast)
})

michal-stachura avatar Mar 25 '23 20:03 michal-stachura

I am trying to manually instantiate a component and it is giving me this same warning, '[Vue warn]: A plugin must either be a function or an object with an "install" function", for the line where I am trying to pass in my Pinia store.

import { useStore } from '../store/chartStore';

legendGroup = createApp({
        render () {
	        return h(LegendGroup, {
		        indicators: indicators.map(i => i.params),
		        isUpper: panel.isUpper,
		        panelUid: panel.params.uid,
		        activeLegends
	        });
        }
});
legendGroup.use(store);
legendGroup.mount(legendElement, true);

zwsaile avatar Feb 13 '24 01:02 zwsaile