6

I am writing a unit test using jest. How can I test for axios.post? I looked into everything but almost everyone had examples using axios.get but not with the post.

 handleLogout(event) {
    event.preventDefault();
    axios
      .post("/logout")
      .then(function(response) {
        window.location = "/login";
      })
      .catch(function(error) {
        console.log(error);
      });

This method is triggered by a button onclick event.

<button
    type="button"
    value="Logout"
    onClick={this.handleLogout}
  >
    Logout
  </button>

How can I write a test case for this scenario in jest?

edit 1:

  it("testing for axios", () => {
wrapper.simulate(
  "click",
  {
    preventDefault: () => {}
  },
);
console.log("here");
expect.assertions(1);

It gave me error:

TypeError: _axios2.default.post is not a function

If I don't simulate prevent default, it gives me this

"TypeError: Cannot read property 'preventDefault' of undefined".

So I assume I need to somehow mock axios after handling preventDefault(). Am I on the right path? How to solve this?

Lin Du
  • 88,126
  • 95
  • 281
  • 483
senpAi95
  • 86
  • 1
  • 4

1 Answers1

1

Here is the solution:

index.tsx:

import React from 'react';
import axios from 'axios';

export class SomeComponent extends React.Component {
  constructor(props) {
    super(props);
    this.handleLogout = this.handleLogout.bind(this);
  }
  public render() {
    return (
      <div>
        <button type="button" value="Logout" onClick={this.handleLogout}>
          Logout
        </button>
      </div>
    );
  }

  private handleLogout(event: React.MouseEvent<HTMLButtonElement>) {
    event.preventDefault();
    axios
      .post('/logout')
      .then(response => {
        console.log(response);
      })
      .catch(error => {
        console.log(error);
      });
  }
}

Unit test:

index.spec.tsx:

import React from 'react';
import { shallow } from 'enzyme';
import axios from 'axios';
import { SomeComponent } from './';

jest.mock('axios', () => {
  return {
    post: jest.fn()
  };
});

describe('SomeComponent', () => {
  describe('#handleLogout', () => {
    const mockedMouseEvent = {
      preventDefault: jest.fn()
    };
    it('should logout correctly', done => {
      const mockedData = 'mocked data';
      const wrapper = shallow(<SomeComponent></SomeComponent>);
      expect(wrapper.find('button')).toHaveLength(1);
      (axios.post as jest.MockedFunction<typeof axios.post>).mockResolvedValueOnce(mockedData);
      const consoleLogSpyOn = jest.spyOn(console, 'log');

      wrapper.find('button').simulate('click', mockedMouseEvent);
      expect(wrapper.find('button').text()).toBe('Logout');
      expect(axios.post).toBeCalledWith('/logout');

      setImmediate(() => {
        expect(consoleLogSpyOn).toBeCalledWith(mockedData);
        consoleLogSpyOn.mockRestore();
        done();
      });
    });

    it('should throw error when axios post error', done => {
      const mockedError = new Error('network error');
      const wrapper = shallow(<SomeComponent></SomeComponent>);
      expect(wrapper.find('button')).toHaveLength(1);
      (axios.post as jest.MockedFunction<typeof axios.post>).mockRejectedValueOnce(mockedError);
      const consoleLogSpyOn = jest.spyOn(console, 'log');
      wrapper.find('button').simulate('click', mockedMouseEvent);
      expect(wrapper.find('button').text()).toBe('Logout');
      expect(axios.post).toBeCalledWith('/logout');

      setImmediate(() => {
        expect(consoleLogSpyOn).toBeCalledWith(mockedError);
        consoleLogSpyOn.mockRestore();
        done();
      });
    });
  });
});

Unit test result with 100% coverage:

 PASS  src/stackoverflow/54555039/index.spec.tsx
  SomeComponent
    #handleLogout
      ✓ should logout correctly (29ms)
      ✓ should throw error when axios post error (14ms)

  console.log node_modules/jest-mock/build/index.js:860
    mocked data

  console.log node_modules/jest-mock/build/index.js:860
    Error: network error
        at Object.<anonymous> (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/54555039/index.spec.tsx:36:27)
        at resolve (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:43:12)
        at new Promise (<anonymous>)
        at mapper (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:26:19)
        at promise.then (/Users/ldu020/workspace/github.com/mrdulin/jest-codelab/node_modules/jest-jasmine2/build/queueRunner.js:73:41)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 index.tsx |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.483s, estimated 5s

Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/54555039

Lin Du
  • 88,126
  • 95
  • 281
  • 483