npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lokalise/universal-testing-utils

v3.2.0

Published

Reusable testing utilities that are potentially relevant for both backend and frontend

Readme

universal-testing-utils

Reusable testing utilities that are potentially relevant for both backend and frontend

msw integration with API contracts

Basic usage

import { buildRestContract } from '@lokalise/api-contracts'
import { sendByGetRoute, sendByPayloadRoute } from '@lokalise/frontend-http-client'
import { setupServer } from 'msw/node'
import { afterAll, afterEach, beforeEach, describe, expect, it } from 'vitest'
import wretch, { type Wretch } from 'wretch'
import { z } from 'zod/v4'
import { MswHelper } from '@lokalise/universal-testing-utils'

const REQUEST_BODY_SCHEMA = z.object({
    name: z.string(),
})
const RESPONSE_BODY_SCHEMA = z.object({
    id: z.string(),
})
const PATH_PARAMS_SCHEMA = z.object({
    userId: z.string(),
})

const postContractWithPathParams = buildRestContract({
    successResponseBodySchema: RESPONSE_BODY_SCHEMA,
    requestBodySchema: REQUEST_BODY_SCHEMA,
    requestPathParamsSchema: PATH_PARAMS_SCHEMA,
    method: 'post',
    description: 'some description',
    responseSchemasByStatusCode: {
        200: RESPONSE_BODY_SCHEMA,
    },
    pathResolver: (pathParams) => `/users/${pathParams.userId}`,
})

const BASE_URL = 'http://localhost:8080'

describe('MswHelper', () => {
    const server = setupServer()
    const mswHelper = new MswHelper(BASE_URL)
    const wretchClient = wretch(BASE_URL)

    beforeEach(() => {
        server.listen({ onUnhandledRequest: 'error' })
    })
    afterEach(() => {
        server.resetHandlers()
    })
    afterAll(() => {
        server.close()
    })

    describe('mockValidPayloadResponse', () => {
        it('mocks POST request with path params', async () => {
            mswHelper.mockValidResponse(postContractWithPathParams, server, {
                pathParams: { userId: '3' },
                responseBody: { id: '2' },
            })

            const response = await sendByPayloadRoute(wretchClient, postContractWithPathParams, {
                pathParams: {
                    userId: '3',
                },
                body: { name: 'frf' },
            })

            expect(response).toMatchInlineSnapshot(`
              {
                "id": "2",
              }
            `)
        })
    })

    describe('mockValidResponseWithAnyPath', () => {
        it('mocks POST request with path params', async () => {
            // you don't need specify any path params, they automatically are set to * 
            mswHelper.mockValidResponseWithAnyPath(postContractWithPathParams, server, {
                responseBody: { id: '2' },
            })

            const response = await sendByPayloadRoute(wretchClient, postContractWithPathParams, {
                pathParams: {
                    userId: '9',
                },
                body: { name: 'frf' },
            })

            expect(response).toMatchInlineSnapshot(`
              {
                "id": "2",
              }
            `)
        })
    })

    // use this approach when you need to implement custom logic within mocked endpoint,
    // e. g. call your own mock
    describe("mockValidResponseWithImplementation", () => {
        it("mocks POST request with custom implementation", async () => {
            const apiMock = vi.fn();

            mswHelper.mockValidResponseWithImplementation(postContractWithPathParams, server, {
                // setting this to :userId makes the params accessible by name within the callback
                pathParams: { userId: ':userId' },
                handleRequest: async (requestInfo) => {
                    apiMock(await requestInfo.request.json())

                    return {
                        id: `id-${requestInfo.params.userId}`,
                    }
                },
            })

            const response = await sendByPayloadRoute(
                wretchClient,
                postContractWithPathParams,
                {
                    pathParams: {
                        userId: "9",
                    },
                    body: { name: "test-name" },
                },
            );

            expect(apiMock).toHaveBeenCalledWith({
                name: "test-name",
            });
            expect(response).toMatchInlineSnapshot(`
              {
                "id": "9",
              }
            `);
        });
    })

    describe('mockAnyResponse', () => {
        it('mocks POST request without path params', async () => {
            mswHelper.mockAnyResponse(postContract, server, {
                // you can specify any response, regardless of what contract expects
                responseBody: { wrongId: '1' },
            })

            const response = await wretchClient.post({ name: 'frf' }, mapRouteToPath(postContract))

            expect(await response.json()).toMatchInlineSnapshot(`
              {
                "wrongId": "1",
              }
            `)
        })
    })
})

mockttp integration with API contracts

API contract-based mock servers for testing. Resolves path to be mocked based on the contract and passed path params, and automatically infers type for the response based on the contract schema

Basic usage

import { buildRestContract } from '@lokalise/api-contracts'
import { sendByGetRoute, sendByPayloadRoute } from '@lokalise/frontend-http-client'
import { getLocal } from 'mockttp'
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import wretch, { type Wretch } from 'wretch'
import { z } from 'zod/v4'
import { MockttpHelper } from '@lokalise/universal-testing-utils'

const REQUEST_BODY_SCHEMA = z.object({
  name: z.string(),
})
const RESPONSE_BODY_SCHEMA = z.object({
  id: z.string(),
})
const PATH_PARAMS_SCHEMA = z.object({
  userId: z.string(),
})
const QUERY_PARAMS_SCHEMA = z.object({
  yearFrom: z.coerce.number(),
})

const postContract = buildRestContract({
  successResponseBodySchema: RESPONSE_BODY_SCHEMA,
  requestBodySchema: REQUEST_BODY_SCHEMA,
  method: 'post',
  description: 'some description',
  responseSchemasByStatusCode: {
    200: RESPONSE_BODY_SCHEMA,
  },
  pathResolver: () => '/',
})

const contractWithPathParams = buildRestContract({
  successResponseBodySchema: RESPONSE_BODY_SCHEMA,
  requestBodySchema: REQUEST_BODY_SCHEMA,
  requestPathParamsSchema: PATH_PARAMS_SCHEMA,
  method: 'post',
  description: 'some description',
  responseSchemasByStatusCode: {
    200: RESPONSE_BODY_SCHEMA,
  },
  pathResolver: (pathParams) => `/users/${pathParams.userId}`,
})

const getContractWithQueryParams = buildRestContract({
  successResponseBodySchema: RESPONSE_BODY_SCHEMA,
  requestQuerySchema: QUERY_PARAMS_SCHEMA,
  description: 'some description',
  responseSchemasByStatusCode: {
    200: RESPONSE_BODY_SCHEMA,
  },
  pathResolver: () => '/items',
})

const getContractWithPathAndQueryParams = buildRestContract({
  successResponseBodySchema: RESPONSE_BODY_SCHEMA,
  requestPathParamsSchema: PATH_PARAMS_SCHEMA,
  requestQuerySchema: QUERY_PARAMS_SCHEMA,
  description: 'some description',
  responseSchemasByStatusCode: {
    200: RESPONSE_BODY_SCHEMA,
  },
  pathResolver: (pathParams) => `/users/${pathParams.userId}`,
})

describe('mockttpUtils', () => {
    const mockServer = getLocal()
    const mockttpHelper = new MockttpHelper(mockServer)
    let wretchClient: Wretch

    beforeEach(async () => {
        await mockServer.start()
        wretchClient = wretch(mockServer.url)
    })
    afterEach(() => mockServer.stop())

    describe('mockValidResponse', () => {
        it('mocks POST request without path params', async () => {
            await mockttpHelper.mockValidResponse(postContract, {
                responseBody: {id: '1'},
            })

            const response = await sendByPayloadRoute(wretchClient, postContract, {
                body: {name: 'frf'},
            })

            expect(response).toMatchInlineSnapshot(`
              {
                "id": "1",
              }
            `)
        })

        it('mocks GET request with query params', async () => {
            await mockttpHelper.mockValidResponse(getContractWithQueryParams, {
                queryParams: { yearFrom: 2020 },
                responseBody: { id: '1' },
            })

            const response = await sendByGetRoute(wretchClient, getContractWithQueryParams, {
                queryParams: { yearFrom: 2020 },
            })

            expect(response).toMatchInlineSnapshot(`
              {
                "id": "1",
              }
            `)
        })

        it('mocks GET request with path params and query params', async () => {
            await mockttpHelper.mockValidResponse(getContractWithPathAndQueryParams, {
                pathParams: { userId: '3' },
                queryParams: { yearFrom: 2020 },
                responseBody: { id: '2' },
            })

            const response = await sendByGetRoute(wretchClient, getContractWithPathAndQueryParams, {
                pathParams: { userId: '3' },
                queryParams: { yearFrom: 2020 },
            })

            expect(response).toMatchInlineSnapshot(`
              {
                "id": "2",
              }
            `)
        })
    })

    describe('mockAnyResponse', () => {
        it('mocks error response with non-matching schema', async () => {
            // mockAnyResponse allows any response body, bypassing schema validation
            // Useful for testing error responses or edge cases
            await mockttpHelper.mockAnyResponse(postContract, {
                responseBody: { error: 'Internal Server Error', code: 'ERR_500' },
                responseCode: 500
            })

            const response = await wretchClient
                .post({ name: 'test' }, '/')
                .json()

            expect(response).toMatchInlineSnapshot(`
              {
                "error": "Internal Server Error",
                "code": "ERR_500"
              }
            `)
        })
    })
})

Query params support

Both mockValidResponse and mockAnyResponse support queryParams. When provided, the mock server will only match requests that include the specified query parameters. The queryParams type is inferred from the contract's requestQuerySchema, so you pass the same values as you would to frontend-http-client (strings, numbers, etc.).

mockAnyResponse

The mockAnyResponse method allows you to mock API responses with any response body, bypassing contract schema validation. This is particularly useful for:

  • Testing error responses (4xx, 5xx status codes)
  • Testing edge cases where the response doesn't match the expected schema
  • Simulating malformed responses to test error handling

Unlike mockValidResponse which enforces schema validation, mockAnyResponse accepts any response body structure, making it ideal for testing how your application handles unexpected API responses.

SSE mock support

Both MswHelper and MockttpHelper support mocking SSE (Server-Sent Events) endpoints via mockSseResponse. This method works with SSEContractDefinition and DualModeContractDefinition contracts built using buildSseContract from @lokalise/api-contracts.

Event names and data shapes are fully type-safe — typing event: 'item.updated' narrows the data field to the matching schema's input type.

mockttp SSE example

import { buildSseContract } from '@lokalise/api-contracts'
import { getLocal } from 'mockttp'
import { z } from 'zod/v4'
import { MockttpHelper } from '@lokalise/universal-testing-utils'

const sseContract = buildSseContract({
  method: 'get',
  pathResolver: () => '/events/stream',
  serverSentEventSchemas: {
    'item.updated': z.object({ items: z.array(z.object({ id: z.string() })) }),
    completed: z.object({ totalCount: z.number() }),
  },
})

const sseContractWithPathParams = buildSseContract({
  method: 'get',
  requestPathParamsSchema: z.object({ userId: z.string() }),
  pathResolver: (params) => `/users/${params.userId}/events`,
  serverSentEventSchemas: {
    'item.updated': z.object({ items: z.array(z.object({ id: z.string() })) }),
    completed: z.object({ totalCount: z.number() }),
  },
})

const mockServer = getLocal()
const mockttpHelper = new MockttpHelper(mockServer)

// No path params — pathParams is not required
await mockttpHelper.mockSseResponse(sseContract, {
  events: [
    { event: 'item.updated', data: { items: [{ id: '1' }] } }, // fully typed
    { event: 'completed', data: { totalCount: 1 } },
  ],
})

// With path params — pathParams is required and typed
await mockttpHelper.mockSseResponse(sseContractWithPathParams, {
  pathParams: { userId: '42' },
  events: [{ event: 'item.updated', data: { items: [{ id: '1' }] } }],
})

// Custom response code
await mockttpHelper.mockSseResponse(sseContract, {
  responseCode: 201,
  events: [{ event: 'completed', data: { totalCount: 0 } }],
})

MSW SSE example

import { setupServer } from 'msw/node'
import { MswHelper } from '@lokalise/universal-testing-utils'

const server = setupServer()
const mswHelper = new MswHelper('http://localhost:8080')

// Same contract definitions as above
mswHelper.mockSseResponse(sseContract, server, {
  events: [
    { event: 'item.updated', data: { items: [{ id: '1' }] } },
    { event: 'completed', data: { totalCount: 1 } },
  ],
})

Dual-mode contracts

mockSseResponse also works with dual-mode contracts (built with successResponseBodySchema), which support both JSON and SSE responses:

const dualModeContract = buildSseContract({
  method: 'post',
  pathResolver: () => '/events/dual',
  requestBodySchema: z.object({ name: z.string() }),
  successResponseBodySchema: z.object({ id: z.string() }),
  serverSentEventSchemas: {
    'item.updated': z.object({ items: z.array(z.object({ id: z.string() })) }),
  },
})

// Mock the SSE response mode
await mockttpHelper.mockSseResponse(dualModeContract, {
  events: [{ event: 'item.updated', data: { items: [{ id: '1' }] } }],
})

formatSseResponse

A standalone helper is also exported for manual SSE response formatting:

import { formatSseResponse } from '@lokalise/universal-testing-utils'

const body = formatSseResponse([
  { event: 'item.updated', data: { items: [{ id: '1' }] } },
  { event: 'completed', data: { totalCount: 1 } },
])
// "event: item.updated\ndata: {\"items\":[{\"id\":\"1\"}]}\n\nevent: completed\ndata: {\"totalCount\":1}\n"