JEST component testing

2020-02-15 06:49发布

问题:

I am new to unit testing with Jest. I am testing a component in a React app. There are two components: Home and LogOutButton

This is The Home component:

import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/css/bootstrap-theme.css';
import React from 'react';
import ReactDOM from 'react-dom';
import { LogOutButton } from './LogOutButton.js';

class Home extends React.Component {
  displayName = Home.name;

  state = {
    result: 0,
    val1: 0,
    val2: 0,
  };

  handleChangeOne = event => {
    this.setState({ val1: event.target.value });
  };

  handleChangeTwo = event => {
    this.setState({ val2: event.target.value });
  };

  add = () => {
    this.setState({ 
      result: parseInt(this.state.val1) + parseInt(this.state.val2)
    });
  };

  onLogoutClick = () => {
    window.location.href = 'https://www.MICROSOFT.com';
  }

  render() {
    return (
      <div>
        <h1>Hello world! The result is: {this.state.result}</h1>
        <input type="text" onChange={this.handleChangeOne} />
        +
        <input type="text" onChange={this.handleChangeTwo} />
        = <br />
        <button onClick={this.add}>Add</button>
        <br/><br/> 
        <LogOutButton onLogout={this.onLogoutClick} /> 
      </div>
    );
  }
}

export default Home;
const rootElement = document.getElementById("root");
ReactDOM.render(<Home />, rootElement);

Home component can get 2 numbers and render their sum. Where it also imports LogOutButton Component and when it is clicked, it should redirect you to Microsoft website.

I want to test a scenario where the user click LogOut.

This is my suggestion:

describe('Home />', () => {
  it('Directing to Microsoft site when LogOut is clicked', () => {
     const homeWrapper = shallow(<Home />);
     homeWrapper.find('LogOutButton').simulate('click');
     homeWrapper.update();
     expect(homeWrapper.html).toEqual('https://www.MICROSOFT.com');
  });
}

This does not work.. I am looking for an assistance to write the right test method. Thanks in advance

回答1:

It's hard to tell how your code will behave without seeing the code for your LogOutButton component. But here are a couple of pointers:

First of all, note that your test simulates a 'ckick' event and not a click event as your probably meant.

Second point is that .html is a function so you should add parentheses to it in your test: .html().

Third point is that the call to homeWrapper.update() seems redundant.

Lastly and most importantly, even if your component works as intended, the result of clicking the LogOutButton would be a page redirect to https://www.MICROSOFT.com.

Even if the redirect worked - which I don't think it will, since your test does not run in a real browser - there's no reason to expect that a call to homeWrapper.html() would return the URL. It would return the HTML that makes up the rendered component.

In your case, you can expect the call to homeWrapper.html() to return something like:

<div><h1>Hello world! The result is: 0</h1><input type=\"text\"/>+<input type=\"text\"/>= <br/><button>Add</button><br/><br/><button id=\"x\">LogOut</button></div>

This of course, does not prove that onLogoutClick worked correctly. Instead, you might consider replacing onLogoutClick with a Jest Mock in your test and then expect the mock to have been called once.



回答2:

A fix for your test is a little addition to what you already have.

delete window.location;
window.location = { reload: jest.fn() };

describe('Home', () => {
  it('should click logout button', () => {
    const component = Enzyme.mount(<Home />);
    const logOutButton = component.find(LogOutButton);
    logOutButton.simulate('click');
    expect(window.location.href).toEqual('https://www.MICROSOFT.com');
  });
});

You quickly notice I deleted window.location as window.location is not modifiable in Jest. That is the missing link.