Hoe kan ik een Reageer component met RouteComponentProps testen?

stemmen
4

Ik heb een component die rekwisieten die zich heeft RouteComponentPropsdat er als volgt uitziet:

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

Nu, als ik mijn component gebruiken in de app, passeer ik deze props aan toe:

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

De rekwisieten zijn reeds beschikbaar, omdat het binnen loopt reageren router.

Nu, hoe kan ik deze component zonder te testen match, location, historybeschikbaar?

Moet ik ze bespotten of is het de bedoeling om hen een of andere manier automatisch geladen met een aantal helper functie?

De vraag is gesteld op 25/10/2017 om 07:20
user
In andere talen...                            


3 antwoorden

stemmen
1

Ik ben al op zoek naar een goede oplossing voor dit. Ik hoopte dat ik zou kunnen doen in de mapStateToProps functie of iets simular, maar zijn niet in staat om dit toch te doen.

Het beste wat ik kon doen was mock dit uit en pas in de wedstrijd, de locatie en geschiedenis. Ik gebruikte de volgende:

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;
}

Toen in mijn test heb ik:

    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()}
                />
      );
antwoordde op 10/11/2017 om 16:57
bron van user

stemmen
2

Als u gebruik maakt Jest (of een andere) spottende bibliotheek, dan kunt u een eenvoudige mock te bieden en de test zal passeren - onderstaand voorbeeld wordt 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();
});

Uiteraard, als je wilt elementen van de wedstrijd, de locatie of de geschiedenis te gebruiken in uw test om de code een bepaald pad volgen, dan overeenkomen / locatie / geschiedenis moet afzonderlijk worden bespot en zoals vereist.

antwoordde op 03/07/2018 om 17:57
bron van user

stemmen
0

Om uw laatste vraag te beantwoorden, is de aanbevolen aanpak is om te gebruiken <MemoryRouter>< *your component here* ></MemoryRouter>in de tests. Typescript niet pikken dat dit onderdeel de benodigde rekwisieten zal doorgeven aan uw component, als zodanig ik neem aan dat het niet om een soort veilige aanpak.

Dit is voor React Router v4 en niet van toepassing op eerdere versies.

Voor een Typesafe methode om onderdelen die zijn verpakt met de HOC testen withRouterkunt u de locatie, de geschiedenis en match van het bouwen react-routeren historypakketten.

Dit voorbeeld maakt gebruik van enzym en snapshot testen, maar kan net zo goed een andere test.

Dit voorkwam me nodig hebben om te gebruiken <MemoryRouter>als een wrapper dat typoscript toch niet leuk vond.

// 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();
});

LET OP Gebruik dit niet tot implementatie detail te testen, kan het verleidelijk zijn, maar het zal ertoe leiden dat u veel pijn moet je wilt refactoren.

Het maken van een helper voor dit zou waarschijnlijk de beste manier om deze re-bruikbaar te maken zijn.

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;
    };

Nu kunnen we gewoon gebruik maken van de routerTestPropsfunctie in onze tests

const { history, location, match } = routerTestProps('/route/:id', { id: '1' });
antwoordde op 05/06/2019 om 02:09
bron van user

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more