Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use with msw to mock requests #775

Closed
rinux55 opened this issue Mar 14, 2024 · 7 comments
Closed

Unable to use with msw to mock requests #775

rinux55 opened this issue Mar 14, 2024 · 7 comments

Comments

@rinux55
Copy link

rinux55 commented Mar 14, 2024

Environment


  • Operating System: Darwin
  • Node Version: v18.19.1
  • Nuxt Version: 3.10.3
  • CLI Version: 3.10.1
  • Nitro Version: 2.9.3
  • Package Manager: npm@10.2.4
  • Builder: -
  • User Config: devtools
  • Runtime Modules: -
  • Build Modules: -

Reproduction

https://stackblitz.com/~/github.com/rinux55/nuxt-fetch

See app.test.ts. In the test/setup.ts and test/server.ts there is an msw server being set up with a mocked endpoint.

Describe the bug

To mock requests made using $fetch and useFetch, I expect to be able to use a utility like msw.

Unfortunately, this doesn't seem to work in combination with @nuxt/test-utils.

I've created a reproduction where you can see that globalThis.fetch is mocked just fine, but useFetch or fetch is not:

https://stackblitz.com/~/github.com/rinux55/nuxt-fetch

Any help with this would be greatly appreciated.

Additional context

No response

Logs

No response

@rinux55
Copy link
Author

rinux55 commented Mar 22, 2024

Linking unjs/ofetch#295 here as well

@ExEr7um
Copy link
Contributor

ExEr7um commented Apr 14, 2024

As a workaround you can try to use registerEndpoint function.

@bcorey85
Copy link

bcorey85 commented Jul 2, 2024

Just a shot in the dark, but it seems that the addition of vi.resetModules() in @nuxt/test-utils/dist/runtime/entry.mjs is breaking my MSW setup. I'm unable to upgrade past 3.10 due to that change. Commenting out that line makes all of my tests pass as expected.

v3.10.0...v3.11.0#diff-aed062a1fdd005bf79a0cf1ce9791008fa96eb4b91dbcd9e85d1820b6257450a

Edit: I found a workaround to fix our setup:

    let mockApi

    // Nuxt Vitest environment clears modules after setup, so we're saving a global reference to the first mockApi instance
    if (window.mockApi) {
        mockApi = window.mockApi
    } else {
        mockApi = setupServer()
        window.mockApi = mockApi
    }

@david-mears-2
Copy link

david-mears-2 commented Jul 31, 2024

@bcorey85 Where would you add that workaround?

@bcorey85
Copy link

bcorey85 commented Jul 31, 2024

@david-mears-2 It's ultimately in my Vitest setupFiles. I have it wrapped in a function that I call when my test environment spins up:

export const setupMockApi = () => {
    let mockApi

    // Nuxt Vitest environment clears modules after setup, so we're saving a global reference to the first mockApi instance
    if (window.mockApi) {
        mockApi = window.mockApi
    } else {
        mockApi = setupServer()
        window.mockApi = mockApi
    }

    const DEBUG = false

    mockApi.events.on('request:start', ({ request }) => {
        if (DEBUG) {
            console.log('Outgoing:', request.method, request.url)
        }
    })

    // Establish API mocking before all tests.
    beforeAll(() =>
        mockApi.listen({
            // Change this to 'warn' if you need to debug a missing API route.
            // Otherwise leave it on 'bypass' so it doesn't spam warnings when we don't add unnecessary routes
            onUnhandledRequest: DEBUG ? 'warn' : 'bypass'
        })
    )
    // Reset any request handlers that we may add during the tests,
    // so they don't affect other tests.
    afterEach(() => {
        mockApi.resetHandlers()
    })
    // Clean up after the tests are finished.
    afterAll(() => mockApi.close())

    const createMockEndpoint = ({
        path,
        response,
        status = 200,
        method = 'get',
        baseUrl,
        delay,
        showConsoleError = false
    }: MockResponseParams) => {
        const base = baseUrl ?? `${mockApiUrl}/api/1`
        const requestPath = `${base}${path}`

        if (status >= 400 && status <= 599 && !showConsoleError) {
            // Suppress automatic Axios console errors for expected errors
            vi.spyOn(console, 'error').mockImplementation(() => {})
        }

        return mockApi.use(
            http[method](requestPath, async () => {
                if (delay) {
                    await mswDelay(delay)
                }

                return HttpResponse.json(response, { status })
            })
        )
    }

    return {
        mockApi,
        createMockEndpoint
    }
}

@shunnNet
Copy link

Hello, I have created a Nuxt module called nuxt-msw that can be used with Nuxt 3 and @nuxt/test-utils to work with msw. You can give it a try and see if it solves your problem.

@rinux55
Copy link
Author

rinux55 commented Oct 29, 2024

This is now working. You only need to overwrite nuxt's $fetch instance:

import { createFetch } from 'ofetch'

// your msw server
import { server } from './mocks/server'

beforeAll(() => {
  server.listen()
  globalThis.$fetch = createFetch()
})

@rinux55 rinux55 closed this as completed Oct 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants