"" , HOC , , ( ), .
AuthenticatedComponent . connect, :
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);
}
:
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);
});
});
});