Skip to content

Vitest - config.global.provide when using VueQueryPlugin not working #281

Open
@scottmillionnexient

Description

@scottmillionnexient

For testing library providing the VueQueryPlugin works perfect. But sometimes I want to test stores / composables / etc. where I don't render, and I'd prefer not to mock vue query because I want to test what's happening inside my composable (onSuccess / onError, etc.)

Here's my setup currently:


main.ts

import { VueQueryPlugin } from "vue-query"

app.use(VueQueryPlugin)

vitest.setup.ts ( the setup file from vitest config setupFiles: "./src/testing/vitest.setup.ts", )

import { config } from "@vue/test-utils"
import { QueryClient, VUE_QUERY_CLIENT } from "vue-query"

beforeAll(() => {
  config.global.provide = {
    [VUE_QUERY_CLIENT]: new QueryClient({
      defaultOptions: {
        queries: {
          retry: false,
        },
      },
    }),
  }

When running unit test for a composable:

Error: vue-query hooks can only be used inside setup() function.
 ❯ Proxy.useQueryClient node_modules/vue-query/lib/index.js:166:15
 ❯ Module.useAddIIB src/composables/api/model/useAddIIB.ts:18:18
     16| 
     17| function useAddIIB(options: Options = {}) {
     18|   const client = useQueryClient()
       |                  ^
     19| 
     20|   const { addSnackbar } = useSnackbar()

Here is the composable for reference

import { AxiosError } from "axios"
import { useMutation, useQueryClient } from "vue-query"
import queryKeys from "@/composables/api/queryKeys"
import { useLogger } from "@/composables/useLogger"
import useSnackbar from "@/composables/useSnackbar"
import { i18n } from "@/plugins"
import { addIIB } from "@/services/model/addIIB"
import { type IIBPayload, snackbarLevels } from "@/types"

const log = useLogger()

interface Options {
  onSuccessCallback?: () => void
  onErrorCallback?: () => void
}

function useAddIIB(options: Options = {}) {
  const client = useQueryClient()

  const { addSnackbar } = useSnackbar()
  return useMutation(queryKeys.model.addIIB(), (newIIB: IIBPayload) => addIIB(newIIB), {
    onSuccess: async () => {
      addSnackbar({
        level: snackbarLevels.success,
        message: i18n.t("Snackbar_API_Success_AddIIB"),
      })
      await client.invalidateQueries(queryKeys.model.getAllIIBs())
      if (options?.onSuccessCallback) {
        options.onSuccessCallback()
      }
    },
    onError: (error: AxiosError) => {
      log(`${i18n.t("LOG_API_ERROR_addIIB")}: ${error.message}`, { level: "error" })
      addSnackbar({
        level: snackbarLevels.error,
        message: i18n.t("Snackbar_API_Error_AddIIB"),
      })
      if (options?.onErrorCallback) {
        options.onErrorCallback()
      }
    },
  })
}

export default useAddIIB

And here's how it's used in a pinia store

   import { useAddIIB } from "@/composables/api/model"

  const createInterfaceBox = useAddIIB({
    onErrorCallback: handleError,
    onSuccessCallback: handleSuccess,
  })
  
  await createInterfaceBox.mutateAsync(payload)

If I comment out

"if (!vm) {
        throw new Error("vue-query hooks can only be used inside setup() function.");
    }
"

I instead receive:

"Error: No 'queryClient' found in Vue context, use 'VueQueryPlugin' to properly initialize the library."

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions