nuxt-open-fetch icon indicating copy to clipboard operation
nuxt-open-fetch copied to clipboard

Allow to mock $[client] methods

Open xavier-ottolini opened this issue 1 year ago • 0 comments

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

xavier-ottolini avatar Nov 14 '24 08:11 xavier-ottolini