Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

270
Visualizações
Enzyme testing an authentication Higher Order Component (HOC)

I've created a Higher Order Component / Composed Component to ensure a user is authenticated before loading the Component. It's very basic, but I'm having some trouble testing it. I want to test the points below, which are similar to the tests I already have elsewhere:

  • Renders the Component (I normally check by looking for a Component specific className)
  • Has correct props (in my case authenticated)
  • Renders the wrapped Component if authenticated and renders null if not

The HOC:

import React from 'react';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';

import { makeSelectAuthenticated } from 'containers/App/selectors';

export default function RequireAuth(ComposedComponent) {
  class AuthenticatedComponent extends React.Component {
    static contextTypes = {
      router: React.PropTypes.object,
    }

    static propTypes = {
      authenticated: React.PropTypes.bool,
    }

    componentWillMount() {
      if (!this.props.authenticated) this.context.router.push('/');
    }

    componentWillUpdate(nextProps) {
      if (!nextProps.authenticated) this.context.router.push('/');
    }

    render() {
      return (
        <div className="authenticated">
          { this.props.authenticated ? <ComposedComponent {...this.props} /> : null }
        </div>
      );
    }
  }

  const mapStateToProps = createStructuredSelector({
    authenticated: makeSelectAuthenticated(),
  });

  return connect(mapStateToProps)(AuthenticatedComponent);
}

I'm using enzyme and jest for my tests, but haven't found a way of rendering the HOC successfully during my tests.

Any ideas?

Solution thanks to answer below:

import React from 'react';
import { shallow, mount } from 'enzyme';
import { Provider } from 'react-redux';

import { AuthenticatedComponent } from '../index';

describe('AuthenticatedComponent', () => {
  let MockComponent;

  beforeEach(() => {
    MockComponent = () => <div />;
    MockComponent.displayName = 'MockComponent';
  });

  it('renders its children when authenticated', () => {
    const wrapper = shallow(
      <AuthenticatedComponent
        composedComponent={MockComponent}
        authenticated={true}
      />,
      { context: { router: { push: jest.fn() } } }
    );

    expect(wrapper.find('MockComponent').length).toEqual(1);
  });

  it('renders null when not authenticated', () => {
    const wrapper = shallow(
      <AuthenticatedComponent
        composedComponent={MockComponent}
        authenticated={false}
      />,
      { context: { router: { push: jest.fn() } } }
    );

    expect(wrapper.find('MockComponent').length).toEqual(0);
  });
});
over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

The "tricky" part here is that your HOC returns a connected component, which makes testing harder because you have shallow render two layers (the connected component and the actual component) and you have to mock the redux store.

Instead you could define the AuthenticatedComponent upfront and export it as a named export. Than you can test it independently of connect like you test every other component:

export class AuthenticatedComponent extends React.Component {
  static contextTypes = {
    router: React.PropTypes.object,
  }

  static propTypes = {
    authenticated: React.PropTypes.bool,
    composedComponent: React.PropTypes.any.isRequired,
  }

  componentWillMount() {
    if (!this.props.authenticated) this.context.router.push('/');
  }

  componentWillUpdate(nextProps) {
    if (!nextProps.authenticated) this.context.router.push('/');
  }

  render() {
    const ComposedComponent = this.props.composedComponent;
    return (
      <div className="authenticated">
        { this.props.authenticated ? <ComposedComponent {...this.props} /> : null }
      </div>
    );
  }
}

export default function RequireAuth(ComposedComponent) {
  const mapStateToProps = () => {
    const selectIsAuthenticated = makeSelectAuthenticated();
    return (state) => ({
      authenticated: selectIsAuthenticated(state),
      composedComponent: ComposedComponent,
    });
  };

  return connect(mapStateToProps)(AuthenticatedComponent);
}

Example test:

import React from 'react';
import { shallow, mount } from 'enzyme';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import RequireAuth, { AuthenticatedComponent } from '../';

const Component = () => <div />;
Component.displayName = 'CustomComponent';

const mockStore = configureStore([]);

describe.only('HOC', () => {
  const RequireAuthComponent = RequireAuth(Component);
  const context = { router: { push: jest.fn() } };
  const wrapper = mount(
    <Provider store={mockStore({})}>
      <RequireAuthComponent />
    </Provider>,
    {
      context,
      childContextTypes: { router: React.PropTypes.object.isRequired },
    }
  );
  it('should return a component', () => {
    expect(wrapper.find('Connect(AuthenticatedComponent)')).toHaveLength(1);
  });
  it('should pass correct props', () => {
    expect(wrapper.find('AuthenticatedComponent').props()).toEqual(
      expect.objectContaining({
        authenticated: false,
        composedComponent: Component,
      })
    );
  });
});

describe('rendering', () => {
  describe('is authenticated', () => {
    const wrapper = shallow(
      <AuthenticatedComponent
        composedComponent={Component}
        authenticated
      />,
      { context: { router: { push: jest.fn() } } }
    );
    it('should render the passed component', () => {
      expect(wrapper.find('CustomComponent')).toHaveLength(1);
    });
  });
  describe('is not authenticated', () => {
    const wrapper = shallow(
      <AuthenticatedComponent
        composedComponent={Component}
        authenticated={false}
      />,
      { context: { router: { push: jest.fn() } } }
    );
    it('should not render the passed component', () => {
      expect(wrapper.find('CustomComponent')).toHaveLength(0);
    });
  });
});
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda