Skip to main content

Testing with stubbed globalThis.fetch

Use case

Write unit tests for code that uses parcely by stubbing or mocking globalThis.fetch.

Vitest example

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { createClient } from '@parcely/core'

describe('UserService', () => {
const http = createClient({ baseURL: 'https://api.example.com' })

let fetchSpy: ReturnType<typeof vi.fn>

beforeEach(() => {
fetchSpy = vi.fn()
globalThis.fetch = fetchSpy
})

afterEach(() => {
vi.restoreAllMocks()
})

it('fetches a user', async () => {
fetchSpy.mockResolvedValueOnce(
new Response(JSON.stringify({ id: '1', name: 'Mickey' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
}),
)

const { data } = await http.get('/users/1')

expect(data).toEqual({ id: '1', name: 'Mickey' })
expect(fetchSpy).toHaveBeenCalledOnce()
})

it('handles errors', async () => {
fetchSpy.mockResolvedValueOnce(
new Response(JSON.stringify({ error: 'Not found' }), {
status: 404,
headers: { 'Content-Type': 'application/json' },
}),
)

await expect(http.get('/users/999')).rejects.toMatchObject({
code: 'ERR_HTTP_STATUS',
status: 404,
})
})
})

Jest example

import { createClient } from '@parcely/core'

const http = createClient({ baseURL: 'https://api.example.com' })

beforeEach(() => {
globalThis.fetch = jest.fn()
})

afterEach(() => {
jest.restoreAllMocks()
})

test('fetches data', async () => {
(globalThis.fetch as jest.Mock).mockResolvedValueOnce(
new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
}),
)

const { data } = await http.get('/health')
expect(data).toEqual({ ok: true })
})

Axios equivalent

In axios, you would use axios-mock-adapter or stub axios.create. In parcely, you stub globalThis.fetch -- no adapter library needed.

Notes and gotchas

  • parcely always uses globalThis.fetch, so stubbing it is the most reliable approach.
  • Return new Response(body, init) from your mock to match the fetch API contract.
  • Remember to set the Content-Type header in mock responses so that parcely parses the body correctly.
  • For integration tests, consider using MSW (Mock Service Worker) which intercepts fetch at a lower level.