4

I need to test the fetchData() function. I have been trying to follow this (and many other) tutorials and trying to get it to work with my function for the past 3 hours but no luck so far. I'd preferably want to do it another way anyway because I don't think jQuery and React should be used together.

I essentially want to check if 1) the function is called when the search form has been submitted (button within SearchForm clicked) and 2) check if the data comes back.

Does anyone have any suggestions on how to get started please?

Thanks

Home

export default class Home extends Component {
  constructor() {
    super();
    this.state = {
      value: '',
      loading: false,
      dataError: false
    }
    this.nodes = [];
    this.fetchData = this.fetchData.bind(this);

  }
  fetchData(e) {
    e.preventDefault();
    this.setState({loading: true});
    axios.get(`https://api.github.com/search/repositories?q=${this.state.value}`)
    .then(res => {
      this.nodes = res.data.items.map((d, k) => <RepoItem {...d} key={k}/>);
      this.setState({loading: false});
    })
    .catch(err => {
      this.setState({dataError: true});
    });
  }
  render() {
    return (
      <div className="home-wrapper">
        <SearchForm value={this.state.value}
                    onSubmit={this.fetchData}
                    onChange={(e) => this.setState({value: e.target.value})}/>
        {this.state.loading ?
        <Spinner/>:
        !this.state.dataError ? this.nodes :
        <h1>Oops! Something went wrong, please try again!</h1>}
      </div>
    );
  }
}

RepoItem

export const RepoItem = props => (
  <div className="repo-item">
    <h1>{props.full_name}</h1>
  </div>);
WillKre
  • 6,280
  • 6
  • 32
  • 62
  • Not sure about testing part, but you probably want to bind 'this' to your fetchData function, so this.setState inside of it refers to Home component. – Mateusz Feb 20 '17 at 19:25
  • edit: nvm I already had it i just removed a few of the lines to dummy down the component. Thanks though! – WillKre Feb 20 '17 at 19:27
  • Hmmm not sure why it works, but basically, if you refer to this inside your function, and then pass it to another component without binding 'this' ( SearchForm in your example ), 'this' will refer to that component when invoked and update state in SearchForm, instead of Home. In your example you use arrow function for onChange event, which auto-binds itself to Home component, so this.setState({value: e.target.value} updates your state in your Home component properly. – Mateusz Feb 20 '17 at 19:35

1 Answers1

2
  1. To check if the function is called upon form submission, you can shallow-render the <SearchForm> component with the spy function passed as a onSubmit prop. Simulate the submit event and check if the spy function is called.
  2. To check if the data comes back, mock the axios service. You can use this library to mock axios calls. Call the fetchData() and see if the this.nodes and state updated correctly.

    const wrapper = shallow(<Home />);
    wrapper.instance().fetchData().then(() => {
      ... your assertions go here ...
    })
    

I think it's always the best practice to return a Promise object or any chainable object from a method where asynchronous action takes place.

Ming Soon
  • 998
  • 2
  • 11
  • 32