Skip to content

Allow to mock $[client] methods #77

@xavier-ottolini

Description

@xavier-ottolini

Environment



Reproduction

Hi,

Il try to create unit tests with Vitest to validate that response is correct and that the parameters are correctly called.

When run the unit test, the following statement

    vi.spyOn(nuxtApp, '$auth').mockResolvedValueOnce({
      id,
      name: 'MyOrganization',
      credit_balance: 0,
      key: 'key',
    })

throw an error "Cannot redefine property: $auth".

Describe the bug

In nuxt.config.ts, I wrote the following parameters:

export default defineNuxtConfig({
  ssr: false,
  openFetch: {
    clients: {
      aiCoaching: {
        baseURL: `${APP_HOST}/coaching`,
        schema: `${schema_path}/coaching/openapi.json`,
      },
      ai: {
        baseURL: `${APP_HOST}/ai`,
        schema: `${schema_path}/ai/openapi.json`,
      },
      auth: {
        baseURL: `${APP_HOST}/auth`,
        schema: `${schema_path}/auth/openapi.json`,
      },
    },
    disableNuxtPlugin: true,
  },
  pinia: {
    storesDirs: ['./stores/**'],
  },
  testUtils: {
    startOnBoot: true,
    logToConsole: true,
    vitestConfig: {
      config: 'vitest.config.mts',
    },
  },
})

The store is the following:

import { FetchError } from 'ofetch'
import type { Organization, OrganizationRead, OrganizationsFetchPaginatedParams, PaginatedListResponseOrganizationRead } from '~/utils/types/Organization'
import type { OrganizationState } from '~/utils/types/OrganizationState.interface'

export const useOrganizationsStore = defineStore('organizationsStore', {
  state: (): OrganizationState => ({
    organizations: [],
    has_more: false,
    items_per_page: DEFAULT_BACKEND_ITEMS_PER_PAGE,
    page: 1,
    total_count: 0,
  }),
  actions: {
   async fetchById(id: string): Promise<FetchError | undefined> {
      const nuxtApp = useNuxtApp()

      return nuxtApp.runWithContext(async (): Promise<FetchError | undefined> => {
        const { $auth } = nuxtApp
        let data: OrganizationRead | undefined
        let error: FetchError | undefined
        try {
          data = await $auth('/v1/organizations/get/{id}', {
            path: {
              id,
            },
            headers: {
              'Content-Length': '0',
            }
          })
        } catch (fetchError) {
          error = fetchError as FetchError
        }

        if (data && !error) {
          if (Array.isArray(this.organizations)) {
            const index = this.organizations.findIndex(
              (currentOrganization) => currentOrganization.id === data?.id,
            )

            if (index >= 0) {
              this.organizations.splice(index, 1, data)
            } else {
              this.organizations.push(data)
            }
          } else {
            this.organizations = [data]
          }
        }

        return error
      })
    },
  },
  getters: {
    getOrganizationById: (state) => (id: string) => {
      return state.organizations.find((organization) => organization.id === id)
    },
  }
})

When I run the unit test

// @vitest-environment nuxt
// anotation important for the test to be succcessfull
import * as openFetch from '#build/open-fetch'
import { FetchError } from 'ofetch'
import { createPinia, setActivePinia } from 'pinia'
import { beforeEach, describe, expect, test, vi } from 'vitest'
import { DATA_REQUEST_HEADER, EMPTY_REQUEST_HEADER } from '~/utils/constants/globales'
import type { AuthPaths } from '~/utils/types/AuthPaths'
import type {
  Organization,
  OrganizationRead,
  OrganizationsFetchPaginatedParams,
  PaginatedListResponseOrganizationRead,
} from '~/utils/types/Organization'

describe('Organization store', () => {
  const fetchByIdPath: AuthPaths = '/v1/organizations/get/{id}'

  beforeEach(() => {
    vi.resetAllMocks()

    // creates a fresh pinia and makes it active
    // so it's automatically picked up by any useStore() call
    // without having to pass it to it: `useStore(pinia)`
    setActivePinia(createPinia())
  })
  
  test('should fetch an organization by id successfully', async () => {
    const readyStore = useReadyStore()
    readyStore.setIsReady()
    const id = 'f786972a-9dcb-425b-9992-4682c9739e60'
    const mockOrganization: OrganizationRead = {
      id,
      name: 'Veonum',
      credit_balance: 0,
      openai_key: 'openai_key',
      mistral_key: 'mistral_key',
      veonum_key: 'veonum_key',
      azure_key: 'azure_key',
    }

    const store = useOrganizationsStore()
    const nuxtApp = useNuxtApp()
    // Spy to check the params calls parameters
    vi.spyOn(nuxtApp, '$auth').mockResolvedValueOnce(mockOrganization)

    const result = await store.fetchById(id)
    expect(result).toBeUndefined()
    const { getOrganizationById } = storeToRefs(store)
    const resultOrganization = getOrganizationById.value(id)
    expect(mockOrganization).toEqual(resultOrganization)
    expect($auth).toHaveBeenCalledWith(
      fetchByIdPath,
      {
        path: {
          id,
        },
        headers: {
          'Content-Length': '0',,
        },
      },
      expect.stringContaining('$'),
    )
  }) 
})

When run the unit test, There is an error: throw an error "Cannot redefine property: $auth".

Additional context

No response

Logs

No response

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