关于安装
create-react-app创建的应用自带Jest库,执行命令npm run test
就会进入测试单元界面。同时提供强行运行所有单元测试代码、选择只用心满足过滤条件的单元测试用例等高级功能。
关于使用
1.对于页面只引用组件的根目录可通过@testing-library/react 中的render函数直接渲染组件进行测试。
当测试组件中有router的使用时需要在测试组件的外层嵌套<BrowserRouter>标签,来声明我们使用的了router
user.tsx
import { TableContainer } from "@material-ui/core";
import { createContext, useReducer, useState } from "react";
import Header from "./header";
import Table from "./table";
import { reducer } from "../../store";
export const Context = createContext(null as any)
const User = () => {
const [state, dispatch] = useReducer(reducer, [])
return (
<Context.Provider value={{data: state, dispatch}}>
<TableContainer component={"div"}>
<Header />
<Table />
</TableContainer>
</Context.Provider>
);
};
export default User;
user.test.tsx
import User from "..";
import { render } from '@testing-library/react'
import { BrowserRouter } from 'react-router-dom'
describe("测试User组件", () => {
it("组件渲染", () => {
render(
<BrowserRouter>
<User></User>
</BrowserRouter>)
})
})
2.测试React Hooks时可以使用@testing-library/react来进行测试
测试useContext时,可以使用<Context.Provider value={{ data: [], dispatch }}>来进行测试
table.tsx
import {
Table,
TableHead,
TableRow,
TableCell,
TableBody,
Button,
Checkbox,
} from "@material-ui/core";
import { useEffect,useContext, useState } from "react";
import { useNavigate } from "react-router-dom";
import styles from './index.module.css';
import Dialog, {UserProps} from '../../../components/Dialog'
import { Context } from "..";
const tableHeader = ["名称", "应用", "角色类型", "操作"];
interface TableProps {
}
const defaultUser = {
id: '',
name: '',
application: '',
type: ''
}
export default ({ }: TableProps) => {
const navigate = useNavigate()
const [open, setOpen] = useState(false as boolean)
const [user, setUser] = useState({ ...defaultUser })
const [checkedAll, setCheckedAll] = useState(false)
const {data: bodyData, dispatch} = useContext(Context)
const useStyle = {
header: {
backgroundColor: "#F4F4F6",
},
headerBar: {
display: "flex",
},
};
const toDetailHandler = (item: any) => {
// console.log(item)
navigate(`/detail/${item.name}`)
}
const editHandler = (item: any) => {
setOpen(true)
setUser(item)
}
const onSave = (e: any)=> {
setOpen(false)
const newData: Array<UserProps> = bodyData.map((item: any)=> item.id === e.id ? e : item)
// getData(newData)
dispatch({
type: 'EDIT',
state: newData
})
}
const onCancel = (e: any)=> {
setOpen(false)
setUser({...defaultUser})
}
const checkedAllHandler = ()=> {
const newCheckedAll = !checkedAll
dispatch({
type: 'CHECKED_ALL',
state: bodyData.map((item: any)=> {
return {
...item,
checked: newCheckedAll
}
})
})
}
const checkedHandler = (id: string)=> {
dispatch({
type: 'CHECKED',
state: bodyData,
id
})
// setCheckedAll(newData.every(item=> item.checked === true))
}
useEffect(()=> {
setCheckedAll(bodyData.length > 0 && bodyData.every((item: any)=> item.checked === true))
}, [bodyData])
return (
<>
<Table>
<TableHead>
<TableRow style={useStyle.header}>
<TableCell>
<Checkbox data-testid="checked-all" checked={checkedAll} onClick={checkedAllHandler}/>
</TableCell>
{tableHeader.map((item, index) => {
return <TableCell key={index} align="left">{item}</TableCell>;
})}
</TableRow>
</TableHead>
<TableBody>
{bodyData.map((item: any, index: number) => {
return (
<TableRow key={index}>
<TableCell>
<Checkbox data-testid={`checked-${index}`} onClick={()=> checkedHandler(item.id)} checked={item.checked ? item.checked : false}/>
</TableCell>
<TableCell component="th" scope="row" align="left">
<a data-testid={`detail-${index}`} onClick={toDetailHandler.bind(null, item)} className={styles.name}>
{item.name}
</a>
</TableCell>
<TableCell>{item.application}</TableCell>
<TableCell>{item.type}</TableCell>
<TableCell>
<Button data-testid={`edit-${index}`} onClick={()=> editHandler(item)} style={{ color: '#744DFE' }}>编辑</Button>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
<Dialog
disabledId={true}
dialogTitle={'编辑'}
defaultUser={user}
open={open}
onSave={onSave}
onCancel={onCancel} />
</>)
}
table.test.tsx
import Table from "..";
import { render, fireEvent } from '@testing-library/react'
import { Context } from '../..'
import { bodyData } from "../../common";//数据源
import { BrowserRouter } from "react-router-dom";
describe("测试Table组件", () => {
it("组件渲染", () => {
const dispatch = jest.fn()
render(
<BrowserRouter>
<Context.Provider value={{ data: [], dispatch }}>
<Table></Table>
</Context.Provider>
</BrowserRouter>
)
})
it("测试编辑按钮", () => {
const dispatch = jest.fn()
const { getByTestId } = render(
<BrowserRouter>
<Context.Provider value={{ data: bodyData, dispatch }}>
<Table />
</Context.Provider>
</BrowserRouter>
)
const editBtn = getByTestId("edit-0");
fireEvent.click(editBtn)
})
it("测试详细按钮", () => {
const dispatch = jest.fn()
const { getByTestId } = render(
<BrowserRouter>
<Context.Provider value={{ data: bodyData, dispatch }}>
<Table />
</Context.Provider>
</BrowserRouter>
)
const detailBtn = getByTestId("detail-0");
fireEvent.click(detailBtn)
})
it("测试Dialog Save按钮", () => {
const dispatch = jest.fn()
const { getByText,getByTestId } = render(
<BrowserRouter>
<Context.Provider value={{ data: bodyData, dispatch }}>
<Table />
</Context.Provider>
</BrowserRouter>
)
const editBtn = getByTestId("edit-0");
fireEvent.click(editBtn)
const saveBtn = getByText("Save");
fireEvent.click(saveBtn)
})
it("测试Dialog Cancel按钮", () => {
const dispatch = jest.fn()
const { getByText,getByTestId } = render(
<BrowserRouter>
<Context.Provider value={{ data: bodyData, dispatch }}>
<Table />
</Context.Provider>
</BrowserRouter>
)
const editBtn = getByTestId("edit-0");
fireEvent.click(editBtn)
const cancelBtn = getByText("Cancel");
fireEvent.click(cancelBtn)
})
it("测试checkbox All 点击事件", () => {
const dispatch = jest.fn()
const { getByTestId } = render(
<BrowserRouter>
<Context.Provider value={{ data: bodyData, dispatch }}>
<Table />
</Context.Provider>
</BrowserRouter>
)
const checkedAll = getByTestId("checked-all");
fireEvent.click(checkedAll)
})
it("测试循环中checkbox点击事件", () => {
const dispatch = jest.fn()
const { getByTestId } = render(
<BrowserRouter>
<Context.Provider value={{ data: bodyData, dispatch }}>
<Table />
</Context.Provider>
</BrowserRouter>
)
const checkedBtn = getByTestId("checked-0");
fireEvent.click(checkedBtn)
})
})