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 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-router-test-routes

v1.0.0-beta.10

Published

A utility for react-router get get routes that can be used for testing with vitest.

Readme

React Router Test Routes

A small library to use when you need react-router routes in your tests.

Motivation

When testing React Router applications in framework mode, developers can often face challenges when testing Routes or components that rely on hooks like useLoaderData() or useNavigation because they are expecting your component to be server rendered and also re-hydrated on the client browser.

The official documentation from react-router recommends that you use createRoutesStub with the action and loader info for your route. There are several problems with that approach. First, taking that approach would require you to do that for every new route that you create which can be a tedious process for a simple component test. Second, that is only simulating client-side hydration, so if you have nested routes and need to call all of the loaders down the tree, then this approach will require a lot of manual code. That's where this library comes in.

This library takes care of that manual tedious process of creating a "test router" for you, and instead it simulates the same behavior that react-router does when it build it's router component (by looking at routes.tsx file, calling the loaders on all the nested routes for a particular request). Additionally, if you wanted to add a request header or query parameters to a specific route for testing, you'd have to manually call your loader or action function with a specific request object, which works great for unit testing, but I often find myself wanting to write an integration test to know that the parts work together rather than in isolation.

This library addresses these limitations by providing a thin abstraction to enable developers to modify requests while maintaining consistency with production routing behavior. Rather than relying on mocks (as some articles might suggest), it leverages React Router's existing methods to create a testing environment that closely mirrors the production router implementation.

Usage

Basic Usage The simplest way to use this library.

Update vite.config.ts

import testRoutes from "react-router-test-routes/vite";

export default defineConfig({
  plugins: [
    testRoutes(), // <- add plugin
  ],
});
import { navigateTo } from "react-router-test-routes";

it("should render", async () => {
  // ⬇️ this will call all of your loaders along the deeply nested path and add the custom header to the request
  await navigateTo("/my/deeply/nested/path");

  expect(screen.getByText("Hello world!")).toBeInTheDocument();
});

Adding headers Add headers to the navigation request.

import { navigateTo } from "react-router-test-routes";

it("should render", async () => {
  await navigateTo("/my/deeply/nested/path", {
    headers: {
      "my-auth-header": "fakeTokenForTesting",
    },
  });

  expect(screen.getByText("Hello world!")).toBeInTheDocument();
});

Middleware Injecting headers into all requests

import { navigateTo, routerMiddleware } from "react-router-test-routes";

beforeAll(() => {
  // add an auth header to all requests when calling navigateTo
  routerMiddleware.use(({ request, route }) => {
    // only append headers if its not in there, otherwise we might append it multiple times
    if (!request.headers.has("my-auth-header")) {
      request.headers.append("my-auth-header", "someUserWhoIsAwesomeAuthToken");
    }
  });
});

it("should render", async () => {
  await navigateTo("/my-path");

  expect(screen.getByText("Hello world!")).toBeInTheDocument();
});

routerMiddleware

routerMiddleware.use(callback)

callback - a callback that takes in arg of type {request: Request, route: {routeId: string, path: string} }. It will be called for all loaders down the nested path when calling navigateTo. That means if you have a route like /deeply/nested/route the callback will be called for the following routes: root, and deeply.nested.route. Note that it's always called for the root loader since root is always matched for all requests.

routerMiddleware.removeAllListeners()

Removes all the middleware. Useful when you have different test cases that might add different middleware. For example, in my setup.ts file I like to have

import { navigateTo, routerMiddleware } from "react-router-test-routes";

beforeEach(() => routerMiddleware.removeAllListeners());