使用官方推荐的库来测react hook组件
阅读原文时间:2023年07月17日阅读:5

最近写单元测试的时候遇见了一些问题,当我使用使用jest测React. useRef,  React. useEffect时,总是测不到,

然后我去查阅了一下官方文档,它推荐了使用下面这个库

@testing-library/react

我来试了哈,还是不得行,于是根据这个库我在npm里头找到了相关的库,就是下面这个,专门用来测Hook的   @testing-library/react-hooks

下面开始示范我的用法,如有不对请稍加修改

这是我的组件BarChart

注意: handleSortByReject 是一个处理函数,我没有把代码贴出来,可以忽略掉这个方法

( 节省时间小tips ,主要关注63-75行的内容,目的是测React.useRef和React.useEffect )

1 import * as React from "react";
2 import {Chart} from "react-chartjs-2";
3 import {Chart as ChartJS, Title, Tooltip, Legend, CategoryScale, BarController, BarElement} from "chart.js";
4 import {IChartDataList} from "./IChartDataList";
5 import {ILinkPosition} from "./common";
6 import {ILink} from "./ILink";
7 import {IDatasetWithDetectionId} from "./IDatasetWithDetectionId";
8 import {ItemWithLoading} from "./ItemWithLoading";
9
10 // Register the elements to display ChartJs. Enables tree-shaking reducing bundle size.
11 // See https://www.chartjs.org/docs/latest/getting-started/integration.html#bundlers-webpack-rollup-etc
12 ChartJS.register(Title, Tooltip, Legend, CategoryScale, BarController, BarElement);
13
14 export interface ISum {
15 subscript: number;
16 totalReject: number[];
17 label: string;
18 sumOfTotalReject?: number;
19 }
20
21 export interface IBarChartProps {
22 /** The state of showing loading icon while sending request */
23 showLoading: boolean;
24 /** height of chart */
25 chartHeight: number;
26 /** current bar data */
27 itemData: IChartDataList;
28 /** sort data by label or total reject, if true, sort by total reject */
29 sortByReject: boolean;
30 }
31
32 export const BarChart: React.FC = (props: IBarChartProps) => {
33 const chartRef = React.useRef(null);
34
35 /**
36 * @returns options property or bar chart
37 */
38 const getOptionBarChart = (titleKey?: string) => {
39 return {
40 maintainAspectRatio: false,
41 scales: {
42 x: {
43 stacked: true,
44 },
45 y: {
46 stacked: true,
47 },
48 },
49 plugins: {
50 title: {
51 display: true,
52 text: titleKey,
53 },
54 },
55 };
56 };
57
58 /**
59 * use official function to update chart, more detail you can see
60 * 1. [update.html](https://www.chartjs.org/docs/latest/developers/updates.html)
61 * 2. [chartRef-demo](https://react-chartjs-2.netlify.app/examples/chart-ref/)
62 */
63 const updateChartData = (chart) => {
64 if (chart.data !== null && chart.data !== undefined) {
65 chart = handleSortByReject(chart);
66 chart.update();
67 }
68 };
69
70 React.useEffect(() => {
71 const chart = chartRef.current;
72 if (chart !== null) {
73 updateChartData(chart);
74 }
75 }, [props.sortByReject, props.itemData.chartData.labels, props.showLoading, props.chartHeight]);
76
77 return (
78 <>
79 {/* * before get response of backend, show loading
80 * if backend return empty list, show 'no data'
81 * otherwise, render bar chart */}
82 chartRef-demo\ 92 \*/ 93 100 ) 101 } 102 />
103
104 );
105 };

BarChart

这是我的组件ItemWithLoading

注意:(节省时间小tips, 可以不关注这个组件)

1 import * as React from "react";
2 import {AppContext} from "../app/IAppContext";
3 import {Loading} from "../app/Loading";
4 import "../public/style/datalight/ItemWithLoading.scss";
5
6 export interface IItemWithLoadingProps {
7 height: number;
8 /** if true, show loading icon */
9 showLoading: boolean;
10 ele?: JSX.Element | boolean;
11 }
12
13 /** render no data */
14 export const ItemWithLoading: React.FC = (props: IItemWithLoadingProps) => (
15 // before render element, show loading
16 17 {(ctx) => 18 props.showLoading ? ( 19 20 ) : props.ele ? ( 21 props.ele 22 ) : ( 23 // if ele not available, show 'no data' 24

25 {ctx.translator.translate("tes_fe_gallery_filter_nodata")} 26
27 ) 28 } 29
30 );

这是测试

注意: 前面三个测试采用了react-test-renderer库的create方法来测渲染

第四个测试采用了renderHook方法来测update方法有没有被调用,配合jest.spyOn和jest.fn方法

(节省时间小tips, 主要关注第四个测试 )

1 import * as React from "react";
2 import * as TypeMoq from "typemoq";
3 import {describe, expect, it, jest} from "@jest/globals";
4 import {ActiveElement, ChartEvent} from "chart.js";
5 import {hotChartData, hotData, mcalMultiChartData, mxChartData, mxData} from "./panel2MockData";
6 import {create} from "react-test-renderer";
7 import {IChartDataList} from "../../datalight/IChartDataList";
8 import {ILinkPosition} from "../../datalight/common";
9 import {ILink} from "../../datalight/ILink";
10 import {BarChart, IBarChartProps} from "../../datalight/BarChart";
11 import {ItemWithLoading} from "../../datalight/ItemWithLoading";
12 import {Chart} from "react-chartjs-2";
13 import {renderHook} from "@testing-library/react-hooks";
14
15 // define props of bar chart
16 const barChartProps: IBarChartProps = {
17 showLoading: true,
18 chartHeight: 300,
19 itemData: mxData,
20 sortByReject: true,
21 };
22
23 /**
24 *
25 * @param height height of chart
26 * @param sortByReject true means sort by total reject. false means sort by label
27 * @returns render component with given property
28 */
29 const renderFrame = (height?: number, sortByReject = false, chartData?: IChartDataList, showLoading = false) => (
30
36 );
37
38 describe("render bar chart", () => {
39 it("bar height depend on props 'chartHeight'", () => {
40 const chartHeight = 200;
41 const wrappers = create(renderFrame(chartHeight, false));
42 expect(wrappers.root.findByType(ItemWithLoading).props.height).toBe(chartHeight);
43 wrappers.unmount();
44 });
45
46 it("bar showLoading depend on props 'showLoading'", () => {
47 // render component with property 'showLoading' as true
48 const wrapper = create(renderFrame(undefined, undefined, undefined, true));
49 expect(wrapper.root.findByType(ItemWithLoading).props.showLoading).toBeTruthy();
50 wrapper.unmount();
51 });
52
53 it("when props data is empty", () => {
54 const emptyData: IChartDataList = {
55 titleKey: "empty list",
56 detectionArr: [],
57 chartData: {labels: [], datasets: []},
58 };
59 // render component with empty data
60 const frame = create(renderFrame(undefined, undefined, emptyData));
61 expect(frame.root.findByType(ItemWithLoading).props.ele).toBeFalsy();
62 frame.unmount();
63 });
64
65
66 it("when props 'sortByReject' is false, test render hot chart", () => {
67 const newRef = {
68 current: {
69 update: jest.fn(),
70 // hot data has one items
71 data: hotChartData,
72 },
73 };
74 jest.spyOn(React, "useRef").mockReturnValueOnce(newRef);
75 /** render hooks
76 * more detail you can see [react-hooks-testing](https://react-hooks-testing-library.com/)
77 */
78 renderHook(() => BarChart(barChartProps));
79 expect(newRef.current.update).toHaveBeenCalledTimes(1);
80 });
81 });

BarChart.test.tsx

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章