How to test React component using RouteComponentProps?

I have a component with details that extend RouteComponentPropsthat looks like this:

export interface RouteComponentProps<P> {
  match: match<P>;
  location: H.Location;
  history: H.History;
  staticContext?: any;
}

Now, when I use my component in the application, I pass the following details to it:

<MyComponent
    match={this.props.match}
    location={this.props.location}
    history={this.props.history}
/>

Details are already available due to the fact that it works inside a responsive router.

Now, how to test this component, without match, location, history?

Do I need to mock them or does it somehow have to automatically load them using some helper function?

+9
source share
3 answers

Jest ( - ) -, , - jest:

test('renders without crashing', () => {

    let mock: any = jest.fn();

    const wrapper = enzyme.mount(
        <TeamSetupApp
            match = {mock}
            location = {mock}
            history= {mock} />
      );

    expect(wrapper).not.toBeNull();
});

, , , , // .

+6

. , mapStateToProps - , .

, , - , . :

import { RouteComponentProps } from 'react-router'
import { match } from 'react-router-dom';
import {UnregisterCallback, Href} from 'history'

export function getMockRouterProps<P>(data: P) {

    var location: {
            hash: "",
            key: "",
            pathname: "",
            search: "",
            state: {}
        };

    var props: RouteComponentProps<P> = {
    match: {
            isExact: true,
            params: data,
            path: "",
            url: ""
        },
        location: location,
        history: {
            length:2,
            action:"POP",
            location: location,
            push: () => {},
            replace: () => {},
            go: (num) => {},
            goBack: () => {},
            goForward: () => {},
            block: (t) => {
                var temp: UnregisterCallback = null;
                return temp;
            },
            createHref: (t) => {
                var temp: Href = "";
                return temp;
            },
            listen: (t) => {
                var temp: UnregisterCallback = null;
                return temp;
            }

        },
        staticContext: {
        }
    };


    return props;
}

:

    var routerProps = getMockRouterProps<ReduxTestComponentProps>(null);

    const wrapper = mount<ReduxTestComponent, ReduxTestComponentState>(
            <ReduxTestComponent
                history={routerProps.history}
                location={routerProps.location}
                match={routerProps.match}
                isLoadingTodo={false}
                todos={todos}
                addAsyncTodoActionDispatch={() => mockTodoAddDispatch()}
                deleteTodoActionDispatch={() => mockTodoDeleteDispatch()}
                />
      );
+2

, <MemoryRouter>< *your component here* ></MemoryRouter> . Typescript , , , .

React Router v4 .

, HOC withRouter , withRouter react-router history.

, .

<MemoryRouter> <MemoryRouter> , .

// Other imports here
import { createMemoryHistory, createLocation } from 'history';
import { match } from 'react-router';

const history = createMemoryHistory();
const path = '/route/:id';

const match: match<{ id: string }> = {
    isExact: false,
    path,
    url: path.replace(':id', '1'),
    params: { id: "1" }
};

const location = createLocation(match.url);

test('shallow render', () => {
    const wrapper = shallow(
        <MyComponent history={history}
                     location={location}
                     match={match} />
    );

    expect(wrapper).toMatchSnapshot();
});

ATTENTION ! Do not use this to check implementation details, it may be tempting, but it can cause you a lot of pain if you want to refactor.

Creating an assistant for this would probably be the best way to make it reusable.

import { createLocation, createMemoryHistory } from 'history';
import { match as routerMatch } from 'react-router';

type MatchParameter<Params> = { [K in keyof Params]?: string };

export const routerTestProps = <Params extends MatchParameter<Params> = {}>
    (path: string, params: Params, extendMatch: Partial<routerMatch<any>> = {}) => {
        const match: routerMatch<Params> = Object.assign({}, {
            isExact: false,
            path,
            url: generateUrl(path, params),
            params
        }, extendMatch);
        const history = createMemoryHistory();
        const location = createLocation(match.url);

        return { history, location, match };
    };


const generateUrl = <Params extends MatchParameter<Params>>
    (path: string, params: Params): string => {
        let tempPath = path;

        for (const param in params) {
            if (params.hasOwnProperty(param)) {
                const value = params[param];
                tempPath = tempPath.replace(
                    ':${param}', value as NonNullable<typeof value>
                );
            }
        }

        return tempPath;
    };

Now we can just use the function routerTestPropsin our tests.

const { history, location, match } = routerTestProps('/route/:id', { id: '1' });
0
source

Source: https://habr.com/ru/post/1688121/


All Articles