Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing async method using React testing library

I have button in component:

<button
    type="button"
    title="Logout"
    data-testid="logout"
    onClick={logout}
>

and method logout:

const logout = async () => {
    try {
        await authLogout()
    } catch (error) {
        console.error(error)
    } finally {
        props.history.push('/login')
    }
}

Now I trying testing logout method by click on button:

describe('UserMenuComponent', () => {
  it('go to login page after click on logout', async () => {
    const history = createMemoryHistory()

    const { getByTestId } = render(
      <Router history={history}>
        <UserMenuComponent />,
      </Router>,
      {
        initialState: { reducersAuth: initialState },
      },
    )

    fireEvent.click(getByTestId('logout'))
    expect(history.location.pathname).toBe('/login')
  })
})

Inside method logout in finally block I have props.history.push('/login') and I check this in my test: expect(history.location.pathname).toBe('/login') but test return error:

expect(received).toBe(expected) // Object.is equality

Expected: "/login"
Received: "/"
like image 833
major697 Avatar asked Jun 13 '26 23:06

major697


1 Answers

You should use useHistory() hook to get history object inside your SFC.

Besides, since the logout function is an async function, you should use waitFor method to wait for your expectations to pass.

E.g.

UserMenuComponent.tsx:

import React from 'react';
import { useHistory } from 'react-router-dom';

async function authLogout() {}

export function UserMenuComponent() {
  const history = useHistory();
  const logout = async () => {
    try {
      await authLogout();
    } catch (error) {
      console.error(error);
    } finally {
      history.push('/login');
    }
  };

  return <button type="button" title="Logout" data-testid="logout" onClick={logout}></button>;
}

UserMenuComponent.test.tsx:

import { fireEvent, render, waitFor } from '@testing-library/react';
import React from 'react';
import { Router } from 'react-router-dom';
import { createMemoryHistory } from 'history';
import { UserMenuComponent } from './UserMenuComponent';

describe('UserMenuComponent', () => {
  it('go to login page after click on logout', async () => {
    const history = createMemoryHistory();
    const pushSpy = jest.spyOn(history, 'push');

    const { getByTestId } = render(
      <Router history={history}>
        <UserMenuComponent />,
      </Router>
    );

    fireEvent.click(getByTestId('logout'));
    await waitFor(() => {
      expect(pushSpy).toBeCalledWith('/login');
      expect(history.location.pathname).toBe('/login');
    });
  });
});

test result:

 PASS  examples/66571376/UserMenuComponent.test.tsx
  UserMenuComponent
    ✓ go to login page after click on logout (82 ms)

-----------------------|---------|----------|---------|---------|-------------------
File                   | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------------------|---------|----------|---------|---------|-------------------
All files              |   91.67 |      100 |     100 |   90.91 |                   
 UserMenuComponent.tsx |   91.67 |      100 |     100 |   90.91 | 12                
-----------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.881 s, estimated 4 s
like image 97
slideshowp2 Avatar answered Jun 18 '26 00:06

slideshowp2