如何测试 React 路由 ?

sxkk20082年前知识分享141

前言

本文承接上文 如何测试 React 异步组件?,这次我将继续使用 @testing-library/react 来测试我们的 React 应用,并简要简要说明如何测试路由系统。

基本示例

以下代码使用 react-router V6 版本, V5 使用 Switch 包裹组件

通常我们的程序会写下如下代码:

首先我们有 2 个页面

  • src/routes/home.jsx 主页
export default function Home() {
  return (
    <main style={{ padding: '1rem 0' }}>
      <h2>这是主页h2>
    main>
  )
}
  • src/routes/about.jsx 关于页面
export default function Home() {
  return (
    <main style={{ padding: '1rem 0' }}>
      <h2>这是关于页h2>
    main>
  )
}

然后使用 HashRouter 或者 BrowserRouter 包裹,形成我们的程序的主入口index.jsx

  • src/index.jsx 程序入口
import { HashRouter, Routes, Route, Link } from 'react-router-dom'
import Home from './routes/home'
import About from './routes/about'

const NoMatch = () => <div>No Founddiv>

function App() {
  return (
    <HashRouter>
      <div>
        <Link to="/">主页Link>
        <Link to="/about">关于Link>
      div>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="*" element={<NoMatch />} />
      Routes>
    HashRouter>
  )
}

export default App

因为我们的页面足够简单,所以页面不会报错,那如果当页面变量的复杂,页面下的其中一个组件报错,就会引起白屏

例如 现在在 about 页面下添加一个错误组件

import React from 'react'

function AboutContent() {
  throw new Error('抛出一个测试错误')
}

export default function About() {
  return (
    <main style={{ padding: '1rem 0' }}>
      <h2>这是关于页h2>
      <AboutContent />
    main>
  )
}

此时页面就会报错,但如果我们没有点击 about 页面,我们的程序任然正常运行,所以我们需要对路由进行测试。

测试方法

我们知道 @testing-library/react 是运行在 node 环境中的,但浏览器中并没有 HashRouter 或者 BrowserRouter ,所以我们需要一个用到 MemoryRouter

此时我们需要将原先的 index.jsx 拆分到 app.jsx

  • src/index.jsx 入口
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { HashRouter } from 'react-router-dom'

ReactDOM.render(
  <React.StrictMode>
    <HashRouter>
      <App />
    HashRouter>
  React.StrictMode>,
  document.getElementById('root')
)
  • src/app.jsx
import { HashRouter, Routes, Route, Link } from 'react-router-dom'
import Home from './routes/home'
import About from './routes/about'

const NoMatch = () => <div>No Founddiv>

function App() {
  return (
    <HashRouter>
      <div>
        <Link to="/">主页Link>
        <Link to="/about">关于Link>
      div>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="*" element={<NoMatch />} />
      Routes>
    HashRouter>
  )
}

export default App

此时我们可以添加单元测试

import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { createMemoryHistory } from 'history'
import React from 'react'
import { Router } from 'react-router-dom'
import App from './App'

test('测试整个路由系统', () => {
  render(
    <MemoryRouter>
      <App />
    MemoryRouter>
  )
  expect(screen.getByText(/这是主页/i)).toBeInTheDocument()

  userEvent.click(screen.getByText(/关于/i))
  expect(screen.getByText(/这是关于页/i)).toBeInTheDocument()
})

MemoryRouter 有 2 个参数

  • 第一个参数 initialEntries={["/users/mjackson"]} 配置初始化路由
  • 第二个参数 initialIndex 默认是 initialEntries 中的最后一个值

测试 404 页面

test('测试路由未匹配', () => {
  render(
    <MemoryRouter initialEntries={['/some/bad/route']}>
      <App />
    MemoryRouter>
  )

  expect(screen.getByText(/Not Found/i)).toBeInTheDocument()
})

通用测试

当页面有多个的时候,我们可以添加一个通用组件来确保每个页面都没有错误

import { useLocation } from 'react-router-dom'

export const LocationDisplay = ({ children }) => {
  const location = useLocation()

  return (
    <>
      <div data-testid="location-display">{location.pathname}div>
      {children}
    >
  )
}

将 url 显示在页面上, 通过遍历确保每个页面可以正确渲染。

let routes = ['/', '/about']

routes.forEach((route) => {
  test(`确保${route} 的 url 可以正确显示`, () => {
    render(
      <MemoryRouter initialEntries={[route]}>
        <LocationDisplay>
          <App />
        LocationDisplay>
      MemoryRouter>
    )

    expect(screen.getByText(new RegExp(route))).toBeInTheDocument()
  })
})

小结

以下是路由测试的步骤:

  1. 将程序和使用什么路由分开;
  2. 使用 MemoryRouter 来测试;
  3. 通过 userEvent.click 点击确保页面可以正确渲染;
  4. 提供一个公共包裹组件,通过遍历来测试每个页面,确保渲染

以上就是本文的全部内容,那么如何测试 react hooks ?请关注我,我会尽快出 React test 系列的下文。

希望这篇文章对大家有所帮助,也可以参考我往期的文章或者在评论区交流你的想法和心得,欢迎一起探索前端。

相关文章

百度虚拟人:改变未来AI互动体验的先锋技术

百度虚拟人:改变未来AI互动体验的先锋技术

  人工智能为核心的百度虚拟人,是一项技术创新,将人们的互动体验提升到了一个全新的层次。通过对话、声音和图像的感知,虚拟人可以模拟人类的思维和行为,与用户进行智能化的交互。在...

经过一晚上的配置和折腾,花钱不说,虽然可以实现在 iPad 上编程的需求,但体验远却比不上 PC,今天我就来推荐一种新的方式,让你的 iPad 变成真正的生产力工具。

Cloud Studio 简介

Cloud Studio 是基于浏览器的集成式开发环境(IDE),为开发者提供了一个永不间断的云端工作站。用户在使用 Cloud Studio 时无需安装,随时随地打开浏览器就能使用。

Cloud Studio iPad 编程 以上是我用 iPad 浏览器,在 1 分钟内初始化了一个 next 初始化模板,可以说速度比本地开发还快,当我在左侧修改代码时,右侧预览界面便会同步热更新。

Cloud Studio 安装 react snippts

Cloud Studio 可以说是提供了一台云服务器,并且把 VSCode 搬到了线上,我们可以同本地开发一样,在上面安装插件,比如可以在左侧扩展中搜索 react,安装这个 react snippts 扩展,便可以帮助我们提供常用代码片段,快速创建组件。

iPad 编程生产力

前言iPad 有个口号,就是“买前生产力,买后爱奇艺”,使用 iPad,配合 Procreate 来作画体验还可以, 如果你想让你的 iPad 可以编程,你却不得不为之花费时间和精力,我搜了网上的教程...

医学人工智能:将技术与医疗融合的未来展望

医学人工智能:将技术与医疗融合的未来展望

  随着科技的飞速发展,人工智能(AI)在医学领域的应用正逐渐成为现实。医学人工智能的出现为医疗带来了巨大的变革,并且具有着深远的影响。  医学人工智能是指利用机器学习、深度...

实现原理

接下来,我们就来说说,这个脚本的实现原理。那并不是任何网站都可以破解会员,是因为这个网站不够建全,我们可以利用一些前端知识来绕过付费。

打开 chrome dev tools, 在 HTML 中搜索 water ,我们可以搜索到带水印的 div,给这个 div 加一个样式: display none。就可以实现去水印了。 原理就是通过这一行代码实现去水印了, 现在我们可以使用截图工具截图保存即可。

image.png

油猴脚本去水印实现原理

本文同步视频地址前言上周微信公众号推出了一种新的形式,类似小红书这样子,群里有小伙伴调侃,是否是小红书的产品经理跳槽到微信了,那作为一个公众号运营者,我也想利用这一点。那么如何快速设计出好看的小红书封...

科技改变生活:体验智能家居带来的变革

科技改变生活:体验智能家居带来的变革

  在当今时代,科技已经成为我们生活中不可或缺的一部分。在家居领域中,智能家居的兴起大大改善了我们的生活质量,使得我们能够更加便利地享受生活。本文将着重介绍智能家居给我们带来...

智能手机推动生活的进步与变革

智能手机推动生活的进步与变革

  近年来,智能手机在全球范围内的普及率越来越高,不仅成为人们日常生活中必不可少的通讯工具,更为社会带来了深远的影响和变革。本文将从智能手机对人们生活方式、社交方式、消费习惯...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。