jsheroes / community-help

Helping others is fun, ask away and the ClujJavaScripters community will help you!
15 stars 0 forks source link

Testing react component with enzyme that are wrapped with Redux connect #21

Open danielmocan opened 7 years ago

danielmocan commented 7 years ago

I have this component that I want to test: ` import React from "react"; import { connect } from "react-redux"; import { Link } from "react-router-dom";

const CheckoutHeader = ( { newTitle } ) => { const title = newTitle ? "First Title" : "Some title";

return (
    <header className="header-checkout">
        <div className="logo-info container">
            <div className="pull-left">
                    <span className=""/>
            </div>
            <div className="pull-right visible-md">
                <p className="claim"><Link to="/">{ title }</Link></p>
            </div>
        </div>
    </header>
);

};

const mapStateToProps = ( state ) => ( { newTitle: state.general.title } );

export default connect( mapStateToProps )( CheckoutHeader ); `

In order to test it with shallow rendering in need to send the store on the context

`import React from "react"; import expect from "expect.js"; import CheckoutHeader from "./checkoutHeader.react"; import { shallow } from "enzyme"; import configureStore from "../../../redux/store";

const store = configureStore( );

describe( "CheckoutHeader", ( ) => { const props = { };

it( "renders without exploding", ( ) => {
    expect( shallow( <CheckoutHeader { ...props } />, { context: { store } } ).length ).to.equal( 1 );
} );

} );`

I order not to sent the store on the context I will have to do in the component 2 exports ( I would not like to do that ) export default CheckoutHeader; export { CheckoutHeader };

and import the component in the test like this: import { CheckoutHeader } from "./checkoutHeader.react";

How to you guys test components that are connected with redux ? Is there a third option to my problem?

tudorgergely commented 7 years ago

Hi @danielmocan .

Usually when testing components with enzyme you can do three things:

  1. Export the component as well as the connected component:
    
    export class MyComponent extends React.Component {
    ...
    }
    ...

export default connect()(MyComponent);

Then in your tests you can import the unconnected component if you want to test it without redux:

import {MyComponent} from './mycomponent.js';



2. You use redux-mock-store: http://arnaudbenard.com/redux-mock-store/

There is a more comprehensive guide on their site, but basically you can wrap your component in `<Provide/>` and pass the store mocket with `redux-mock-store` to it.

3. You can always create a dumb component which you will use in you connected component. This will duplicate a lot of the functionality from the connected component so I don't see why you would do that. 

Of course, there might be other ways of doing this, so please answer so we all learn a bit more :)
tudorgergely commented 7 years ago

Just as a quick followup, what I usually do is a combination of the first two choices: I export both the connected and unconnected components. In tests I use the unconnected component whenever I want to test something independent of redux (styling, default rendering et al).

When testing logic I use redux-mock-store. Besides injecting the store it allows for beautiful things like checking which actions were dispatched or dispatching actions on your own:

// Dispatch the action
store.dispatch(addTodo());

// Test if your store dispatched the expected actions
const actions = store.getActions();

You can then check the dispatched actions with the actions which were expected to be dispatched @danielmocan

cc @vladnicula maybe you have some more ideas