简体   繁体   中英

How do you test a basic method in a React Component?

I have a React component that has a simple input form and button to input an email. My codebase is unit tested with Jest (using jest-dom and also @testing-library/react) as well as integration tested with Cypress.

I want to write a unit test for this simple method on a React Component called ContactBox.

You will note that this handler is simply attached to the form element using onSubmit={this.addEmail}

addEmail(event) {
    event.stopPropagation()
    event.preventDefault()
    let email = this.emailCaptureRef.current.value

    let  domain = 'https://somedomain.com/'

    fetch(domain + 'newsletter/sign_up', {
      method: "POST",
      body: JSON.stringify({_method: 'POST', email: email})
    })
      .then((response) => {
        if (response.status >= 400) {

        }
        return response.json().then((result) => {
          this.setState({email_box_used: true})
        })
      })
  }

Is there a good way to go about testing this with Jest ?

I guess what I'm curious about is that the Jest documentation all shows various strategies to render the React component(s), is it possible to unit test this method on the component without having to render?

React Component class is just JavaScript class, we can test the methods of the class directly using Class.prototype.method without using React related test utils.

index.tsx :

import React, { Component } from 'react';

class ContactBox extends Component {
  emailCaptureRef;
  constructor(props) {
    super(props);
    this.state = { email_box_used: false };
  }

  addEmail(event) {
    event.stopPropagation();
    event.preventDefault();
    const email = this.emailCaptureRef.current.value;
    const domain = 'https://somedomain.com/';

    fetch(domain + 'newsletter/sign_up', {
      method: 'POST',
      body: JSON.stringify({ _method: 'POST', email }),
    }).then((response) => {
      return response.json().then((result) => {
        this.setState({ email_box_used: true });
      });
    });
  }
  render() {
    return (
      <div>
        <form onSubmit={this.addEmail}></form>
      </div>
    );
  }
}

export default ContactBox;

index.test.tsx :

import ContactBox from './';

const whenStable = () => new Promise((resolve) => setTimeout(resolve));

describe('60403489', () => {
  it('should add email', async () => {
    const mResponse = { json: jest.fn().mockResolvedValueOnce({}) };
    const mFetch = jest.fn().mockResolvedValueOnce(mResponse);
    (global as any).fetch = mFetch;
    const setStateSpy = jest.spyOn(ContactBox.prototype, 'setState').mockReturnValueOnce();
    const mEvent = { stopPropagation: jest.fn(), preventDefault: jest.fn() };
    ContactBox.prototype.emailCaptureRef = { current: { value: 'example@gmail.com' } };
    ContactBox.prototype.addEmail(mEvent);
    await whenStable();
    expect(mFetch).toBeCalledWith('https://somedomain.com/newsletter/sign_up', {
      method: 'POST',
      body: JSON.stringify({ _method: 'POST', email: 'example@gmail.com' }),
    });
    expect(mResponse.json).toBeCalledTimes(1);
    expect(setStateSpy).toBeCalledWith({ email_box_used: true });
  });
});

unit test results with coverage report:

 PASS  stackoverflow/60403489/index.test.tsx
  60403489
    ✓ should add email (8ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   83.33 |        0 |   66.67 |   81.25 |                   
 index.tsx |   83.33 |        0 |   66.67 |   81.25 | 6,7,26            
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.822s, estimated 10s

source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60403489

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM