Darren
Darren

Reputation: 180

In React, how to test a render method inside a component

I have a component which has a render method that is used to render a table. Now I need to implement a unit test in react to test that method (renderTaskAssign())and see if the table was rendered successfully. Can anyone tell me how to do that? Here is the detail about the class that I hope I can write test.

class TaskAssign extends Component {
  constructor(props) {
    super(props);
    this.renderTaskAssign = this.renderTaskAssign.bind(this);
  }

  renderTaskAssign() {
    if (this.props.data_loading) {
      return (
        <div className="dataloader">
        <ClipLoader
          color={types.LOADING_DATA_COLOR}
          loading={this.props.data_loading}
        />
        </div>);
    } else {
      if (this.props.current_tasks !== '') {
        const item_list = this.props.current_tasks.map((key, index) => {
          return (
              <TableRow key={index}>
              <TableRowColumn>{this.props.current_tasks[index]['pos']}</TableRowColumn>
              <TableRowColumn>{this.props.current_tasks[index]['name']}</TableRowColumn>
              <TableRowColumn>{this.props.current_tasks[index]['completion']}</TableRowColumn>
              <TableRowColumn>{this.props.current_tasks[index]['current_task']}</TableRowColumn>
              <TableRowColumn>{this.props.current_tasks[index]['percent_complete']}</TableRowColumn>
              <TableRowColumn>{this.props.current_tasks[index]['status']}</TableRowColumn>
              <TableRowColumn>Do nothing</TableRowColumn>
              </TableRow>
          );
          })
        return (
          <Table multiSelectable>
          <TableHeader>
            <TableRow>
            <TableHeaderColumn>Pos</TableHeaderColumn>
            <TableHeaderColumn>Installer</TableHeaderColumn>
            <TableHeaderColumn>Work Progress</TableHeaderColumn>
            <TableHeaderColumn>Current Task</TableHeaderColumn>
            <TableHeaderColumn>% Completion</TableHeaderColumn>
            <TableHeaderColumn>Status</TableHeaderColumn>
            <TableHeaderColumn>Add.Info</TableHeaderColumn>
            </TableRow>
          </TableHeader>
            <TableBody>
            {item_list}
            </TableBody>
            </Table>
          );
      }
    }
  }

  render() {
    return (
      <div>
        {this.renderTaskAssign()}
      </div>
    );
  }
}

const mapStateToProps=({ task })=> {
  const { current_tasks, error, data_loading } = task;
  return { current_tasks, error, data_loading };
};

export default connect(mapStateToProps)(TaskAssign);

I tried to use enzyme to test the component, here is the test code I wrote. I don't know how to test the table in my case

it("test renderTaskAssign method", () => {
    const renderer = new ShallowRenderer();
    renderer.render(<Provider store={store}>
    <TaskAssign />
    </Provider>);
    const result = renderer.getRenderOutput();
    const taskComponent = new result.type.WrappedComponent();
    taskComponent.props = {
      current_tasks: [
        0: {
          completion: 0.76,
          current_task: 'REASSEMBLE DOORS',
          name: 'A. Smith',
          percent_complete: 0.5,
          pos: 'A1',
          status: 'Good'
        },
        1: {
          completion: 0.66,
          current_task: 'ASEASSEMBLE DOORS',
          name: 'B. Smith',
          percent_complete: 0.7,
          pos: 'B1',
          status: 'Soso'
        }
      ]
    };
    taskComponent.renderTaskAssign()
    console.log(taskComponent.renderTaskAssign().type);
  }
);

Upvotes: 1

Views: 7930

Answers (3)

Jalil
Jalil

Reputation: 3168

Actually, you should test the behavior of your component, not its implementation. From the outside of your component, you should not care about if it has a renderTaskAssign or what this function does, but only what the component does/render.

What it seems you want to do is test your component with specific props, without waiting for your Redux connect to inject them into your component. I suggest the following, where you only test your component, not your store :

class TaskAssign extends Component {
  constructor(props) {
    super(props);
    this.renderTaskAssign = this.renderTaskAssign.bind(this);
  }

  renderTaskAssign() {
      // some render code
  }

render() {
    return (
      <div>
        {this.renderTaskAssign()}
      </div>
    );
  }
}

const mapStateToProps=({ task })=&gt; {
  const { current_tasks, error, data_loading } = task;
  return { current_tasks, error, data_loading };
};

export default connect(mapStateToProps)(TaskAssign);

export const TaskAssign // <- This enables you to test your component, without the mapStateToProps connection. 

and then :

import { TaskAssign } from './'; // <-- Import the 'unconnected' version

it("test renderTaskAssign method", () => {
    const renderer = new ShallowRenderer();
    renderer.render( // <- Directly inject your props, not need for an entire store
    <TaskAssign current_tasks={[
        0: {
          completion: 0.76,
          current_task: 'REASSEMBLE DOORS',
          name: 'A. Smith',
          percent_complete: 0.5,
          pos: 'A1',
          status: 'Good'
        },
        1: {
          completion: 0.66,
          current_task: 'ASEASSEMBLE DOORS',
          name: 'B. Smith',
          percent_complete: 0.7,
          pos: 'B1',
          status: 'Soso'
        }
      ]} />
    );
    const result = renderer.getRenderOutput();

    // Test whatever you want : 
    expect(wrapper.is(Table)).toEqual(true);
    expect(wrapper.find(TableRowColumn).length).toEqual(7);
  }
);

Now, from there (and completely out of scope :-) ) :

  • I do not get it what is the utility of your renderTaskAssign function
  • It is recommanded to use functional components when possible (no lifecycle).
  • You could replace your map with another component
  • You can use babel-plugin-jsx-control-statements to simplify your JSX

So, I would actually write your component something like this :

const TaskAssign = ({ current_tasks, data_loading }) => (
  <div>
    <Choose>
      <When condition={data_loading} />
        <div className="dataloader">
          <ClipLoader
            color={types.LOADING_DATA_COLOR}
            loading={data_loading}
          />
          </div>
      </When>
      <When condition={current_tasks !== ''}>
        <Table multiSelectable>
          <TableHeader>
            <TableRow>
            <TableHeaderColumn>Pos</TableHeaderColumn>
            <TableHeaderColumn>Installer</TableHeaderColumn>
            <TableHeaderColumn>Work Progress</TableHeaderColumn>
            <TableHeaderColumn>Current Task</TableHeaderColumn>
            <TableHeaderColumn>% Completion</TableHeaderColumn>
            <TableHeaderColumn>Status</TableHeaderColumn>
            <TableHeaderColumn>Add.Info</TableHeaderColumn>
            </TableRow>
          </TableHeader>
            <TableBody>
              <For each="task" of={current_tasks} >
                <SomeItemTableRowComponent task={task} />
              </For>
            </TableBody>
            </Table>
          </When>
        </Choose>
      </div>
    );

const mapStateToProps=({ task })=&gt; {
  const { current_tasks, error, data_loading } = task;
  return { current_tasks, error, data_loading };
};

export default connect(mapStateToProps)(TaskAssign);

export const TaskAssign

Hope that helps

Upvotes: 1

ruanmer
ruanmer

Reputation: 31

You can use Jest to generate snapshots. http://facebook.github.io/jest/docs/en/snapshot-testing.html

Upvotes: 0

Timofey Lavrenyuk
Timofey Lavrenyuk

Reputation: 407

Basically, with Enzyme you can check if the inner component is rendered. For example:

it('should use Table', () => {
    const wrapper = shallow(
      <TaskAssign />
    );
    expect(wrapper.is(Table)).toBe(true);
  });

Then you can check that this component contains another component. For example:

it('should render multiple header columns', () => {
    const wrapper = mount(
      <TaskAssign />
    );
    expect(wrapper.find(TableRowColumn).length).toBe(7);
  });

Upvotes: 0

Related Questions