今天來練習測試 React Router ,範例程式碼的部分針對 React Router 文件的介紹稍微修改後如下:
import * as React from "react";
import { Routes, Route, Link } from "react-router-dom";
const App = () => {
const Home = () => (
<>
<main>
<h2>Welcome to the home page!</h2>
</main>
</>
);
const About = () => (
<>
<main>
<h2>Welcome to the about page!</h2>
</main>
</>
);
return (
<div>
<header>
<h1>Welcome to React Router!</h1>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</header>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</div>
);
};
export default App;
在 App 元件內有 Home 、 About 元件,點擊時可切換頁面:
首先來釐清測試內容,在釐清時可以想像自己是使用者,當自己是使用者時希望網頁給自己怎樣的操作體驗 ?
如:希望能正確呈現頁面、希望點擊網頁連結時能正確換頁等。
Router
要測試的主要部分包含:
接下來會使用 MemoryRouter 來進行測試,底下是關於 MemoryRouter 的介紹:
MemoryRouter
A Router that keeps the history of your “URL” in memory (does not read or write to the address bar). Useful in tests and non-browser environments like React Native.
而使用方式有兩種,第一種方式如下:
方法一
第一種方式需下載 history library,history 套件為 React Router 主要依賴項之一,透過將 history 傳給 Router
使用:
使用 fireEvent.click
點擊相關連結後並透過 history.location.pathname
斷言現在 url 位置是否正確。
import React from "react";
import { Router } from "react-router-dom";
import { screen, render, fireEvent } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { createMemoryHistory } from "history";
import App from "./App";
describe("Method one", () => {
test("The initial page is Home Page", () => {
const history = createMemoryHistory();
render(
<Router location={history.location} navigator={history}>
<App />
</Router>
);
expect(history.location.pathname).toBe("/");
});
test("Click the link to jump to the page", () => {
const history = createMemoryHistory();
render(
<Router location={history.location} navigator={history}>
<App />
</Router>
);
fireEvent.click(screen.getByText("About"));
expect(history.location.pathname).toBe("/about");
fireEvent.click(screen.getByText("Home"));
expect(history.location.pathname).toBe("/");
});
});
備註:navigator={history}
在 React Router v4、v5 版本時等於 history={history}
方法二
直接在 render 時使用 MemoryRouter
包覆 App 元件,並透過 initialEntries
陣列傳入初始頁面,底下為 initialEntries
詳細介紹:
initialEntries: array
An array oflocation
s in the history stack. These may be full-blown location objects with{ pathname, search, hash, state }
or simple string URLs.
最後透過 Jest DOM 的 toBeInTheDocument
斷言點擊時是否有切換頁面成功:
import React from "react";
import { Router } from "react-router-dom";
import { screen, render, fireEvent } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import { MemoryRouter } from "react-router-dom";
import App from "./App";
describe("Method two", () => {
test("The initial page is Home Page", () => {
render(
<MemoryRouter initialEntries={["/"]}>
<App />
</MemoryRouter>
);
expect(screen.getByText("Home")).toBeInTheDocument();
});
test("Click the link to jump to the page", () => {
render(
<MemoryRouter initialEntries={["/"]}>
<App />
</MemoryRouter>
);
fireEvent.click(screen.getByText("About"));
expect(screen.getByText("About")).toBeInTheDocument();
fireEvent.click(screen.getByText("Home"));
expect(screen.getByText("Home")).toBeInTheDocument();
});
});
這樣就完成模擬路由的切換囉!
https://testing-library.com/docs/example-react-router/
https://reactrouter.com/en/v6.3.0/getting-started/installation
https://www.gushiciku.cn/pl/ptd1/zh-tw
https://stackoverflow.com/questions/69859509/cannot-read-properties-of-undefined-reading-pathname-when-testing-pages-in
https://medium.com/enjoy-life-enjoy-coding/react-unit-test-react-的-route-單元測試-feat-jest-react-testing-library-e89b5c7e6d35