Git Product home page Git Product logo

react-router-test-context's Introduction

react-router-test-context

Create a pseudo context object that duplicates React Router's context.router structure. This is useful for shallow unit testing with Enzyme.

Note: This package only works with React Router v4.

Installation

npm install --save-dev react-router-test-context

Usage

import createRouterContext from 'react-router-test-context'
import { shallow } from 'enzyme'

describe('my test', () => {
  it('renders', () => {
    const context = createRouterContext()
    const wrapper = shallow(<MyComponent />, { context })
    // ...
  })
})

enzyme

There are a few things that you should be aware of if you plan to use react-router-test-context with enzyme to test your location-aware components.

mount

If your root component is not a native React Router component (<Switch>, <Route>), you may run into issues with unfound context properties. To deal with this, you have two options.

  1. Define a contextTypes on the root component.
import MyComponent from '../component/MyComponent'

describe('my component', () => {

  // ADD THIS
  MyComponent.contextTypes = {
    router: React.PropTypes.object
  }

  it('renders', () => {
    const context = createRouterContext()
    const wrapper = mount(<MyComponent />, { context })
    // ...
  })
}
  1. Pass a childContextTypes object to enzyme via the options object.
describe('my component', () => {
  // ...
  
  it('renders', () => {
    const context = createRouterContext()
    const childContextTypes = {
      router: React.PropTypes.object
    }
    const wrapper = mount(<MyComponent />, { context, childContextTypes })
    // ...
})

Limitations of shallow Renders

If you are using this to test that a <Switch> is matching as expected, a shallow render will probably not work as expected.

For example, if you were to do the following shallow render, the wrapper node would be a <Route>. This could work to verify that you rendered the correct <Route> by checking that the path of the returned node is the path that you expect to be matched.

const context = createRouterContext({ location: { pathname: '/two' }})
const wrapper = shallow((
  <Switch>
    <Route path='/one' component={One}/>
    <Route path='/two' component={Two}/>
  </Switch>
), { context })
const props = wrapper.props()
expect(props.path).toBe('/two')

This breaks down, however, if you attempt to do this on a component that contains a <Switch>.

const Switcheroo = () => (
  <Switch>
    <Route path='/one' component={One}/>
    <Route path='/two' component={Two}/>
  </Switch>
)

const wrapper = shallow(<Switcheroo />, { context })

The wrapper node returned by shallow rendering the <Switcheroo /> will be a <Switch>. The <Switch> will not have rendered, so we are unable to derive any relevant route matching information from the shallow render.

In cases like this, you will just need to do a full mount if you want to verify that the component renders the correct child component.

const context = createRouterContext({ location: { pathname: '/two' }})
const wrapper = mount((
  <Switch>
    <Route path='/one' component={One}/>
    <Route path='/two' component={Two}/>
  </Switch>
), { context })

expect(wrapper.find(Two).exists()).toBe(true)

react-router-test-context's People

Contributors

pshrmn 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

Watchers

 avatar  avatar  avatar

react-router-test-context's Issues

TypeError: router.setRouteLeaveHook is not a function

Using options 2, however, i am getting

TypeError: router.setRouteLeaveHook is not a function

my router looks

{ history:
   { action: 'POP',
     location: { pathname: '/', search: '', hash: '', key: 'ch3ac9' },
     _listeners: [],
     listen: [Function: listen],
     push: [Function: push],
     replace: [Function: replace],
     _notifyListeners: [Function: _notifyListeners],
     createHref: [Function: createHref] },
  route:
   { match: { path: '/', url: '/', isExact: true, params: {} },
     location: { pathname: '/', search: '', hash: '', key: 'ch3ac9' } },
  staticContext: undefined }

which does not have setRouteLeaveHook function.

Question re. testing routes

Hi,

I was wondering if it's possible to use this module to test that a particular component is being rendered for a given URL? At the moment I'm doing a simple smoke test to check that a component renders:

import React from 'react';
import { shallow } from 'enzyme';
import createRouterContext from 'react-router-test-context';

import Layout from '../layout';

const setup = () =>
{
  const context = createRouterContext();
  const wrapper = shallow(<Layout />, { context });

  return {
    wrapper,
  };
};

describe('Layout', () =>
{
  test('render', () =>
  {
    const { wrapper } = setup();

    expect(wrapper.exists()).toBe(true);
  });
});

Where the component I'm testing is like:

import React from 'react';
import { Link, Switch, Route } from 'react-router-dom';

import HomeView from '../home';
import TestView from '../test';

const layout = () => (
  <div>
    <p>My App</p>

    <Switch>
      <Route path="/test" component={TestView} />
      <Route path="/" component={HomeView} />
    </Switch>
  </div>
);

export default layout;

I'd like to extend my tests to check that individual routes are working correctly, something like:

test('"/test" route', () =>
{
  const { wrapper } = setup('/test'); // Would need to set the route in the setup function

  expect(wrapper.contains(TestView)).toBe(true);
});

Is that possible this this, or am I stuck with using a full mount?

Thanks :)

Warning: Failed context type: The context `router` is marked as required in `Component`, but its value is `undefined`.

Hello. I'm trying to use this package to mock the router context but it still doesn't work event after context providing.

Here is my test.

Btw I also have a question. Even when I'm using the MemoryRouter and mount feature how I can test some method of my real component. enzymeWrapper.instance() doesn't work because the root component is MemoryRouter
Thanks for any help.

import * as React from "react";
// import { MemoryRouter } from "react-router-dom";
import {shallow, ShallowWrapper} from "enzyme";
import createRouterContext from 'react-router-test-context'
import Overview from "../src/modules/customer/Overview";
import { profilesStore } from "../src/store";

let overview: ShallowWrapper<undefined, undefined>;

beforeEach(function() {
		overview=shallow(

			<Overview profilesStore={profilesStore}/>,
			{ context : createRouterContext() }
	)
});

describe('Overview component test suite', () => {
    it('should have an one section with id container', () => {
        expect(overview.find("#container")).toHaveLength(1);
    });
});

Here is the issue message
Warning: Failed context type: The context router is marked as required in
Component, but its value is undefined.
in Link
in header
in section
in default_1

Getting warning testing `Redirect`

I have the following test suite:

import React, {Component} from "react";
import createRouterContext from "react-router-test-context";
import {mount} from "enzyme";
import {PropTypes} from "prop-types";
import {Redirect, Route, Switch} from "react-router-dom";

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {permission: false};
  }

  render() {
    return (
      <Switch>
        <Route exact path="/users">
          <h2>A list of users</h2>
        </Route>
        <Route path="/users/:userId">
          {({match}) => this.state.permission ? <h1>{match.params.userId}</h1> : <Redirect to="/users" />}
        </Route>
      </Switch>
    );
  }
}

describe("render()", () => {
  describe("when route is /users/:userId", () => {
    let app;
    beforeEach(() => {
      const context = createRouterContext({
        location: {pathname: "/users/1"},
        match: {url: "/users/1", path: "/users/:userId", params: {userId: "1"}, isExact: true},
      });
      const childContextTypes = {router: PropTypes.object};
      app = mount(<App />, {context, childContextTypes});
    });

    describe("when user has permission", () => {
      beforeEach(() => {
        app.setState({permission: true});
      });

      it("should show users id", () => {
        expect(app.exists("h1")).toBe(true);
      });
    });

    describe("when user doesn't have permission", () => {
      beforeEach(() => {
        app.setState({permission: false});
      });

      it("should redirect to users list", () => {
        expect(app.exists("Redirect")).toBe(true);
      });
    });
  });
});

Both tests pass, but in the second test case I get the following warning:

Warning: You tried to redirect to the same route you're currently on: "/users"

How should I rewrite my test in order to prevent the warning from occurring?

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.