Jest单元测试--testing-library/react

关于安装

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)
    })
})
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值