使用 Enzyme 测试 React Router Links 上的点击行为

rea*_*tor 5 reactjs enzyme react-router-v4

虽然我最终尝试为此反应路由器示例中的流程编写酶测试:https://reacttraining.com/react-router/web/example/auth-workflow

import React from 'react';
import ReactDOM from 'react-dom';
import Enzyme, { shallow, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { MemoryRouter, Route, Switch, Link } from 'react-router-dom';

const Home = () => <div>Home</div>;
const MockComp = () => (
  <div className="protected">
    <nav>hi</nav>
    Protected
  </div>
);
const MockDenied = () => <div className="denied">Denied</div>;

test('Renders visited protected component if authorized', () => {
  const wrapper = mount(
    <MemoryRouter initialEntries={['/']}>
      <div>
        <Link to="/foo" />
        <Switch>
          <Route path="/" component={Home} />
          <Route path="/401" component={MockDenied} />
          <ProtectedRouteBasic
            path="/foo"
            auth={{ hasAuth: true }}
            component={MockComp}
          />
        </Switch>
      </div>
    </MemoryRouter>
  );
  wrapper.find('a').simulate('click', { button: 0 });
  expect(wrapper.find('.protected').length).toEqual(1);
  expect(wrapper.find('.denied').length).toEqual(0);
});
Run Code Online (Sandbox Code Playgroud)

我发现了许多问题,并尝试消除复杂性,然后慢慢地重新引入我已删除的元素。

因此,我已经开始进行此测试,因为我需要继续进行以下工作:

test('Clicking link will render component associated with path', () => {
  const wrapper = mount(
    <MemoryRouter>
      <div>
        <Link to="/foo" />
        <Switch>
          <Route path="/" component={Home} />
          <Route path="/foo" component={MockComp} />
        </Switch>
      </div>
    </MemoryRouter>
  );
  wrapper.find('a').simulate('click', { button: 0 });
  expect(wrapper.find('.protected')).toHaveLength(1);
});
Run Code Online (Sandbox Code Playgroud)

但是,该测试并未按预期工作,因为我期望测试在当前状态下通过。我已阅读此线程以更新我的simulate调用以包含{button: 0}以及此线程有关将整个路由器包装在功能组件中的信息,但是,据我所知,该选项对我来说不可用,因为我正在使用的框架似乎不允许。此外,我相信那篇文章对我遇到的问题并不重要。也就是说,任何帮助将不胜感激。

Bri*_*ams 2

来自Switch 文档

渲染第一个子项<Route><Redirect>与位置匹配的子项。


在这种情况下,<Route path="/" component={Home} />当路径为两者时匹配//foo因此Home始终呈现。

您可以通过使用以下任一方法来修复此问题:仅exact当路径恰好为 时才匹配/,或者将其移动到列表末尾Route以便其他路由首先匹配:

test('Clicking link will render component associated with path', () => {
  const wrapper = mount(
    <MemoryRouter>
      <div>
        <Link to="/foo" />
        <Switch>
          <Route path="/foo" component={MockComp} />
          <Route path="/" component={Home} />
        </Switch>
      </div>
    </MemoryRouter>
  );
  wrapper.find('a').simulate('click', { button: 0 });
  expect(wrapper.find('.protected')).toHaveLength(1);  // SUCCESS
});
Run Code Online (Sandbox Code Playgroud)