Code Monkey home page Code Monkey logo

remix-stubs's Introduction

โš ๏ธ Remix has now released @remix-run/testing (example tests) which should be used instead of remix-stubs. It has a very similar API so migration is easy. With stubbing now built-in to Remix, remix-stubs won't be updated and only works with older versions of Remix such as <v1.9.

remix-stubs

An example implementation and usage of Ryan Florence's createRemixStub design with Storybook and Vitest.

Examples

Tests

Whilst I won't be publishing remix-stubs as a package, since it relies on deep imports from Remix, please do create issues, examples or discussions so that the example implementation can be improved.

Current Issues

There's a few issues and workarounds you will need to be aware of.

Unit Testing

  • global.FormData wasn't being set to the jsdom class. Manually set it in setup-test-env.ts.
  • happy-dom doesn't support formdata or form submissions so if unit testing those you should set the vitest environment to jsdom in vitest.config.js.
  • jsdom's form submission support isn't perfect and won't pass the form submit button's value as documented in LikeButton.tsx.

Storybook

  • Due to the deep import of RemixEntry in create-remix-stub.tsx from @remix-run/react, you may find webpack/vite bundles both a esm and cjs version of the components code, which causes React context to be inconsistent. For vite I've added an alias in .storybook/main.ts as a temporary workaround.

remix-stubs's People

Contributors

jrestall avatar mcansh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

remix-stubs's Issues

"No routes matched location" error

Whenever I create a test for a page that is not the / route, I get the error:

No routes matched location "/" 

Here is the tests code:

import { describe, expect, it } from 'vitest';

import { createRemixStub, render, screen } from '~/test/test-utils';

import NotFoundComponent from './not-found-component';

describe('NotFound component', () => {
  it('given a link: renders error messages and the correct link', async () => {
    const RemixStub = createRemixStub([
      {
        path: '/some-non-existent-page',
        element: <NotFoundComponent />,
      },
    ]);
    render(<RemixStub />);

    expect(
      screen.getByRole('heading', { level: 1, name: /not found/i }),
    ).toBeInTheDocument();
    expect(screen.getByRole('link', { name: /support/i })).toBeInTheDocument();
    expect(screen.getByRole('link', { name: /home/i })).toHaveAttribute(
      'href',
      '/',
    );
    expect(screen.getByRole('link', { name: /zing/i })).toHaveAttribute(
      'href',
      '/',
    );
  });
});

Is there any thing I'm configuring wrong? Or is this a bug in the package?

TypeScript errors

How can I get past this?

> tsc --noEmit

node_modules/@remix-run/router/history.ts:349:30 - error TS6133: 'window' is declared but its value is never read.

349   function createBrowserHref(window: Window, to: To) {
                                 ~~~~~~

node_modules/@remix-run/router/utils.ts:332:5 - error TS2322: Type 'AgnosticRouteMatch<string, RouteObjectType>[] | null' is not assignable to type 'null'.
  Type 'AgnosticRouteMatch<string, RouteObjectType>[]' is not assignable to type 'null'.

332     matches = matchRouteBranch<string, RouteObjectType>(
        ~~~~~~~

node_modules/@remix-run/router/utils.ts:1149:31 - error TS6133: 'v' is declared but its value is never read.

1149     this.pendingKeys.forEach((v, k) => this.pendingKeys.delete(k));
                                   ~


Found 3 errors in 2 files.

Errors  Files
     1  node_modules/@remix-run/router/history.ts:349
     2  node_modules/@remix-run/router/utils.ts:332
ERROR: "test:types" exited with 2.

can we mock `prefetch="intent"` on the Remix Link component?

I've got prefetch="intent" on many Link components and that throws an exception if I hover over the <Link /> Is it possible to mock it? Base case I don't think we'd want it to fetch data or do anything so () => void is what we want I imagine? What's the method for dealing with Link components atm?

fetcher.data not being parsed correctly when mocked

First of all, thanks for this implementation it makes my life extremely easy mocking out my remix components.

When mocking out components that useFetcher, after calling fetcher.load(route), the fetcher.data returns "[object Object]" as a string, and the data that is being provided to the route in the stub, with the loader being mocked out, is not sent correctly to fetchers.

Is there any solution to this?

Doesn't work anymore with Remix `1.12.0`

After updating Remix to the version 1.12.0 the stub doesn't work anymore as the interfaces have changed and TS is complaing about some type '{ actionData: RouteData | undefined; appState: { trackBoundaries: boolean; trackCatchBoundaries: boolean; catchBoundaryRouteId: null; renderBoundaryRouteId: null; loaderBoundaryRouteId: null; error: undefined; catch: undefined; }; matches: { ...; }[]; routeData: RouteData; manifest: AssetsManifest; routeModules: Rou...' is not assignable to type 'EntryContext'. Object literal may only specify known properties, and 'actionData' does not exist in type 'EntryContext' used in createRemixContext function.

Have you already tried the unstable @remix-run/testing? package?

Handling loader data without passing in `initialLoaderData`

Hi,

I understand this is an implementation of an existing RFC, but I did want to understand if there was an expectation of how to render a component with loader data, but expecting this data to be loaded from the route's loader?

Would it be possible to provide a await RemixStub.load() which can be called in tests to simulate how remix would load the initial data, instead of this being passed in?

I would imagine the reasoning for passing initialLoaderData was because loaders are async and thus need to be "fetched" before the render can take place.

A test might look like

const RemixStub = createRemixStub([{..., loader: () => ["some response"]}])
await RemixStub.load({initialEntries: [...]}); // initial entries used to decide what loaders to call

render(<RemixStub />

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.