Тестирование React с помощью React-Router v.5, useHistory, useSelector и useEffect - PullRequest
1 голос
/ 14 января 2020

Я борюсь с написанием правильного теста для компонента, который защищает некоторые маршруты и программно перенаправляет неавторизованных пользователей. Компонент выглядит следующим образом:

import { useEffect } from 'react';
import { useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { isAuthed } from 'redux/selectors/auth';

const mapState = state => ({
  isAuthenticated: isAuthed(state),
});

const LoginShield = ({ children }) => {
  const { isAuthenticated } = useSelector(mapState);
  const history = useHistory();

  useEffect(() => {
    if (!isAuthenticated) {
      history.push('/login');
    }
  }, [isAuthenticated]);

  return children;
};

export default LoginShield;

Я хотел бы проверить, что компонент перенаправляет неаутентифицированного пользователя и не перенаправляет аутентифицированного пользователя (два базовых c теста). Я попробовал несколько подходов, используя Jest / Enzyme или Jest / ReactTestingLibrary, и не могу найти хорошего решения.

Пока мой тест - беспорядок, но я поделюсь им, чтобы кто-то мог показать мне, в чем проблема:

import React, { useEffect } from 'react';
import { act } from 'react-dom/test-utils';
import { mount } from 'enzyme';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { Router } from 'react-router-dom';
import rootReducer from 'redux/reducers';
import LoginShield from 'components/LoginShield/LoginShield';

describe('LoginShield component', () => {
  let wrapper;
  let historyMock;

  beforeEach(() => {
    const initialState = { auth: { loginId: 'Foo' } };
    const store = createStore(rootReducer, initialState);
    historyMock = {
      push: jest.fn(),
      location: {},
      listen: jest.fn(),
    };
    jest.mock('react-redux', () => ({
      useSelector: jest.fn(fn => fn()),
    }));
    wrapper = mount(
      <Provider store={store}>
        <Router history={historyMock}>
          <LoginShield>
            <h5>Hello Component</h5>
          </LoginShield>
        </Router>
      </Provider>,
    );
  });

  it('renders its children', () => {
    expect(wrapper.find('h5').text()).toEqual('Hello Component');
  });

  it('redirects to the login page if user is not authenticated', async () => {
    await act(async () => {
      await Promise.resolve(wrapper);
      await new Promise(resolve => setImmediate(resolve));
      wrapper.update();
    });
    // is the above necessary?


    console.log(historyMock.push.mock.calls);
    // returns empty array

    // ... ? 

  });

  it('doesn`t redirect authenticated users', () => {
    // .... ?
  });
});

Любые советы приветствуются! Заранее спасибо. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...