使用redux连接组件测试react-router v4路由

时间:2017-10-28 14:12:34

标签: javascript reactjs redux react-router react-redux

我正在尝试验证我的路线是否已正确设置。就像我有一个特定的URI一样,然后加载适当的组件。只是为了防止我误导错误路径。

这是一个示例连接页面:

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

export const ConnectPage = (props) => {
  return <div>{props.code}</div>;
};

export default connect(
  (state) => ({}),
  (dispatch) => ({})
)(ConnectPage);

主页:

import React from 'react';
import LoginPage from './LoginPage';

const MainPage = () => (
  <LoginPage/>
);

export default MainPage;

这是我的路线档案:

import React from 'react';
import {Route, Switch, Redirect} from 'react-router-dom';
import qs from 'query-string';

import MainPage from './MainPage';
import ConnectPage from './ConnectPage';

class Routes extends React.Component {

  render() {
    return (<Switch>
      <Route path={'/connect/:provider'} render={(matches) => {
        const search = qs.parse(matches.location.search);

        if (search.code) {
          return <ConnectPage code={search.code}/>;
        }

        return <Redirect to={'/'}/>;

      }}/>
      <Route exact path={'/'} component={MainPage}/>
    </Switch>
    );
  }
}

export default Routes;

我的考验是,我遇到了麻烦:

import React from 'react';
import {mount} from 'enzyme';
import {MemoryRouter} from 'react-router';
import configureStore from 'redux-mock-store';
import Chance from 'chance';

import Routes from './Routes';

import MainPage from './MainPage';
import ConnectPage from './ConnectPage';
import {createProvider as Provider} from 'react-redux';

const chance = new Chance();

const middlewares = [];
let mockStore;

describe('The Routes', () => {

  beforeAll(()=>{
    mockStore = configureStore(middlewares);
  });

  it('loads the Main Page on /', () => {
    const component = mount(
      <MemoryRouter initialEntries={['/']} initialIndex={0}>
        <Routes store={mockStore}/>
      </MemoryRouter>

    );
    expect(component.find(MainPage).length).toBe(1);

  });

  it('redirects to the main page if no code', () => {
    const url = '/connect/someprovider';

    const component = mount(
      <MemoryRouter initialEntries={[url]} initialIndex={0}>
        <Routes/>
      </MemoryRouter>
    );

    expect(component.find(MainPage).length).toBe(1);

  });

  it('loads the Connect Page on /connect/provider', () => {
    const code = chance.word({length: 32});
    const url = `/connect/provider?code=${code}`;

    const component = mount(
      <Provider store={mockStore}>
        <MemoryRouter initialEntries={[url]} initialIndex={0}>
          <Routes/>
        </MemoryRouter>
      </Provider>);

    try {
      expect(component.find(ConnectPage).length).toBe(1);
    } catch (e) {
      console.log('Used url:', url);
      throw (e);
    }

  });

});

我不能为我的生活弄清楚如何进行第三次测试。我只是想确保ConnectedPage在适当的时候到位。

在这种状态下,我得到:

Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
      in createProvider (created by WrapperComponent)
      in WrapperComponent

1 个答案:

答案 0 :(得分:0)

我在此期间找到了答案,所以我会在这里发布它以获得繁荣。如果您对此有任何了解,请告诉我们!

以下是修订后的测试用例:

  it('loads the Connect Page on /connect/provider', () => {
    const code = chance.word({length: 32});
    const url = `/connect/provider?code=${code}`;

    const component = mount(
      <MemoryRouter initialEntries={[url]} initialIndex={0}>
        <Routes/>
      </MemoryRouter>,
      {
        context: {
          store: mockStore()
        },
        childContextTypes: {
          store: PropTypes.object.isRequired
        }
      });

    try {
      expect(component.find(ConnectPage).length).toBe(1);
    } catch (e) {
      console.log('Used url:', url);
      throw (e);
    }

  });

调用mockStore似乎是主要的解决方案,而不仅仅是在上下文中传递它。我不确定为什么这有效,但确实如此。我现在会用它滚动,但我很乐意听到一些解释,以便我可以学习。