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

expect-fetch

v0.1.0

Published

Expressive Vitest matchers for native Fetch API requests and responses

Readme

expect-fetch

Jest DOM-style assertions for native Fetch API requests and responses.

expect-fetch adds expressive HTTP matchers to Vitest without mocking globalThis.fetch. Use it to test Next.js route handlers, Remix loaders, SvelteKit and Astro endpoints, Hono applications, Cloudflare Workers, or any code that produces native Request or Response objects.

import 'expect-fetch/vitest';

const response = await app.request('/users/123');

expect(response).toHaveStatus(200);
expect(response).toHaveHeader('content-type', /json/);

await expect(response).toHaveJson({
  id: '123',
  name: 'Ada',
});

Request assertions use the same API:

expect(request).toHaveMethod('POST');
expect(request).toHaveUrl('/users?page=2');
expect(request).toHaveQuery({ page: '2' });
expect(request).toHaveHeader('authorization', /^Bearer /);

await expect(request).toHaveJson({ name: 'Ada' });

Installation

npm install --save-dev expect-fetch

Add the integration to a Vitest setup file:

// test/setup.ts
import 'expect-fetch/vitest';
// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    setupFiles: ['./test/setup.ts'],
  },
});

You can also import the integration directly in an individual test file.

Matchers

toHaveStatus

expect(response).toHaveStatus(201);

toHaveHeader

Header names are case-insensitive. Values can be exact strings or regular expressions. Requests and responses are supported.

expect(response).toHaveHeader('content-type');
expect(response).toHaveHeader('content-type', /application\/json/);
expect(response).toHaveHeader('x-request-id', 'req_123');

toHaveJson

The request or response is cloned before its body is read, so the matcher does not consume the original body. Vitest asymmetric matchers are supported.

await expect(response).toHaveJson({
  id: expect.any(String),
  role: 'admin',
});

toHaveText

await expect(response).toHaveText('Not found');
await expect(response).toHaveText(/not found/i);

toHaveFormData

Repeated fields are represented as arrays. Requests and responses are supported.

await expect(request).toHaveFormData({
  name: 'Ada',
  roles: ['admin', 'author'],
  avatar: expect.any(File),
});

toHaveMethod

Method comparison is case-insensitive.

expect(request).toHaveMethod('POST');

toHaveUrl

Absolute URLs, URL objects, regular expressions, and relative URLs containing the path, query, and fragment are supported.

expect(request).toHaveUrl('/users?page=2');
expect(request).toHaveUrl(/^https:\/\/example\.com\/users/);

toHaveQuery

Query values are decoded. Repeated parameters are represented as arrays.

expect(request).toHaveQuery({
  q: 'Ada Lovelace',
  tag: ['math', 'code'],
});

toRedirectTo

Without an explicit status, any status from 300 through 399 is accepted.

expect(response).toRedirectTo('/login');
expect(response).toRedirectTo('/login', 307);

toSetCookie

expect(response).toSetCookie('session', {
  value: /^eyJ/,
  path: '/',
  httpOnly: true,
  secure: true,
  sameSite: 'lax',
  maxAge: 3600,
});

Supported expectations are value, domain, path, expires, maxAge, secure, httpOnly, and sameSite. Omitted fields are not checked.

Set-Cookie is intentionally supported for server-side response tests. Browsers do not expose this response header to client-side JavaScript.

Why not fetch-mock?

Fetch mocking tools fake the server that your code calls. expect-fetch verifies the Response produced by the server or handler you are building. They solve different problems and can be used together.

Compatibility

  • Node.js 20 or newer
  • Vitest 2, 3, or 4
  • Any framework using standards-compatible Fetch API objects

The matchers use structural checks rather than instanceof Response, allowing responses created in another JavaScript realm or by compatible runtimes. Failure diagnostics redact Authorization, Proxy-Authorization, Cookie, and Set-Cookie values so credentials do not leak into test or CI logs.

License

MIT

Contributing and security

See CONTRIBUTING.md for development and release guidance. Please use the private process in SECURITY.md to report vulnerabilities.