test-utils icon indicating copy to clipboard operation
test-utils copied to clipboard

Example for testing Nuxt plugins?

Open arishojaei opened this issue 4 years ago • 6 comments

Would it be possible to use this to run unit tests against a plugin? or HTTP requests in a plugin?

arishojaei avatar Sep 01 '21 06:09 arishojaei

Hey @arishojaei ! Great question, there is an inbound PR that introduces some more documentation around plugins, however I do not think that addresses your specific question.

I am also investigating exactly this at the moment. My project is currently using axios.

Currently I have observed that the http requests are not being made against the Nuxt server instantiated by nuxt/test-utils. My hacky workaround has been to use nock to create the responses for the data json endpoints.

thisislawatts avatar Sep 01 '21 10:09 thisislawatts

@arishojaei Could you provide mode details (with code example) of what you are trying to test? Nuxt plugins can be tricky to test if they include conditionally rendered templates. Is this your case? I am glad to help, but it would be useful to better understand your problem.

mrazauskas avatar Sep 01 '21 10:09 mrazauskas

Well, if I want to explain...

  1. I have a function that uses nuxt/axios to GET data and returns it.
  2. Then I imported that function to another class:
import UserRepository from './repository/user.repository'
import { NuxtAxiosInstance } from '@nuxtjs/axios'

export class RepositoryManager {
  constructor(private axios:NuxtAxiosInstance) {}

  getUser() {
    return UserRepository(this.axios)
  }
}
  1. After that, I injected this class as a Nuxt plugin:
import { RepositoryManager } from '~/repositories'

...

const repository: Plugin = (context, inject) => {
  inject('repository', new RepositoryManager(context.$axios))
}

export default repository
  1. With this plugin I can GET my logged in user in any component, like this:
this.$repository.getUser().loggedInUser()

Now after all of these, I want to write a test to check if my HTTP response has data that I need or not. the main problem is that I can't access to the Nuxt plugins

// I setup a mock server with https://mswjs.io/
const server = setupServer(
  rest.get('*', (_, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json({me: {
        first_name:"Thor",
        id:"99",
        last_name:"Odinson" 
      }})
    )
  })
)

// then wrote this for test
it('fetched data should have ID, first_name and last_name', async () => {
    const response = await this.$repository.getUser().loggedInUser()
    console.log(response)
});

Please tell if my scenario is not right and thanks for your help @mrazauskas

arishojaei avatar Sep 03 '21 19:09 arishojaei

@arishojaei If a plugin is just plain JavaScript, it is very easy to unit test it:

import { Context } from '@nuxt/types'
import { NuxtAxiosInstance } from '@nuxtjs/axios'
import plugin from '../plugin'

const mockAxios: Partial<NuxtAxiosInstance> = {
  get: jest.fn().mockResolvedValue({ data: { name: 'John', surname: 'Doe' } })
}

const mockContext = {
  $axios: mockAxios
} as Context

const mockInject = (key: string, value: any) => {
  mockContext['$' + key] = value
}

test('plugin', async () => {
  plugin(mockContext, mockInject)

  const res = await mockContext.$repository.getUser()

  expect(res).toMatchObject({ name: 'John', surname: 'Doe' })

  expect(mockContext.$repository).toBeDefined()
  expect(mockAxios.get).toBeCalledTimes(1)
  expect(mockAxios.get).toBeCalledWith('/user?ID=12345')
})

This is very simple demo. Just a starting point.

The test is running only with Jest v27 (and necessary typings) installed. Jest config looks like this:

module.exports = {
  moduleNameMapper: {
    '~/repositories': '<rootDir>/repositories',
  },
  transform: {
    '\\.[jt]s?$': '@sucrase/jest-plugin'
  }
}

Declare alias paths for Jest’s resolver and include any transformer you prefer.

Let me know if anything looks unclear.

mrazauskas avatar Sep 08 '21 13:09 mrazauskas

nice @mrazauskas, I have similar issue - what if this "repository" plugin is calling (api) on route middleware (from vuex actions) ? - how to mockup this plugin and API response before setupTest ? - which is responsible for server running How to test it as a whole solution with nuxt server ? not only as standalone plugin.

mercs600 avatar Oct 19 '21 21:10 mercs600

@mercs600 Please open separate issue (it helps other users to find solutions easier). And please add minimal reproduction.

mrazauskas avatar Oct 20 '21 05:10 mrazauskas