React tesing libaray 用例编写

178 阅读3分钟

寻找元素

前缀

  • Get:返回查询的匹配节点,如果没元素匹配,则会报错(针对单查如果查到多个也会报错);
  • Query:返回查询的匹配节点,如果没有元素匹配会返回 null,但是不会报错(同样针对单查,如果查到多个匹配元素也会报错)
  • Find:返回一个 Promise,默认超时时间为 1000 ms, 如果没有元素匹配或者查找超时,Promise 状态切为 reject(同样针对单查,如果查到多个元素,也会返回 reject)。

后缀

前缀后缀
get
query
find
role(角色)
labelText (标签文本)
placeholderText (暗纹)
text (文本)
displayValue (表单值)
altText (图片alt)
title (标题)
testid (如果前面都用不了,那么改代码加testid)

role

role 是dom元素的隐藏属性,如

<button>按钮</button>
// 相遇于
<button role="button">按钮</button>

常见的role属性对照可以查看W3C 对应的提案

标签属性
a , hreflink
a (没有 href 属性), body, div, spangeneric
formform
h1 到 h6heading
htmldocument
imgimg
pparagraph
tabletable
urllist
lilistitem

另外还可以通过name属性在诸多一样的元素中寻找特定的那个

    // 代码
    <div aria-label="test_note">1234</div>
    
   // 单测代码 
   const note = screen.getByRole("generic", { name: "test_note" });

labelText

标签文本(labelText):针对 label 标签的 text 查询,通过这个可以查询到对应 label 的输入节点(比如 input)

    // 代码
    <label> testLabel <input /> </label>
    
    // 单测
    const label = screen.getByLabelText("testLabel");

placeholdertext

暗纹(placeholdertext): 通过 placeholder 来查询,也可以有效查到对应的表单元素,如果你没有使用 label 标签的时候,可以使用这个来作为替代

    // 代码
    <Input
      maxLength={100}
      showCount
      placeholder="请输入人员姓名"
      style={{ width: rowWidth }}
      disabled
    />
    
    // 单测
    const input2 = screen.getByPlaceholderText('请输入人员姓名')

text

text(文本内容),用来找又指定文字的元素

    // 代码
    <button>确定</button>
    
    // 单测
    const confrimBtn = await screen.findByText('确 定')

img alt

这个是根据 img 的 alt 来查询

    // 代码
    <img src="111" />
    
    //单测
    const altImg = screen.getByAltText("111");

title

这个是靠元素的title提示来找元素的

        // 代码
    <div title="111" >123</div>
    
    //单测
    const altImg = screen.getByTitle("111");

testid

如果你前面的都不能用上,那么还是给留了个作弊一样的方法,这就需要新增新增 data-testid 属性来进行查询

    // 代码
    <div data-testid="111">123</div>
    
    //单测
    const altImg = screen.getByTestId("111");

页面元素断言

断言使用场景断言

断言试用场景断言api
页面可见toBeEmptyDOMElement toBeVisible toBeInTheDocument toHaveTextContent
表单验证toBeDisabled toBeEnabled toBeRequired toHaveFocus toBeChecked toHaveFormValues toHaveValue
代码层面验证toHaveAttribute toHaveClass toHaveStyle

Mock引用

mock一个function

jest.mock('next/config', () => ({
  __esModule: true,
  default: () => ({
    publicRuntimeConfig: {
      STATIC_ASSETS_URL: '111',
      API_HOST: '111',
    },
  }),
}));

mock一个返回

jest.mock('ahooks', () =>
  jest.fn().mockReturnValue({
    data: [],
    error: false,
    loading: false,
    refresh: false,
  }),
);

mock api

import {getChannelList} from '@/api/op';

jest.mock('@/api/op');

const mockedGetChannelList = getChannelList as jest.MockedFunction<typeof getChannelList>;


describe('ChannelManagement', () => {
    it('renders the table with correct columns', async () => {
      const mockData = [
        {
          id: 100076,
          name: '我是个名称',
        },
      ];
      mockedGetChannelList.mockResolvedValue({
        content: mockData,
        totalElements: 720,
      });
      render(<ChannelManagement />);
      
      // test something
    });
})

实用技巧

antd select下拉写法

<Select
  placeholder="时间精度"
  data-testid="select-dateType"
  options={dateOptions}
  defaultValue={'DAY'}
  onChange={(v: string) => setDateType(v)}
/>


// 获取时间精度下拉框
const dateSelect = screen.getByTestId('select-dateType').firstElementChild;

// 触发时间精度下拉框的点击事件
fireEvent.mouseDown(dateSelect as Element);

// 获取下拉选项
expect(screen.queryByText('全部')).toBeInTheDocument();
expect(screen.queryByText('按周')).toBeInTheDocument();
expect(screen.queryByText('按月')).toBeInTheDocument();

fireEvent.click(screen.queryByText('按周') as Element);

antd rangepicker写法,datepicker同理

<RangePicker
  format="YYYY-MM-DD"
  open={open}
  data-testid="select-rangePicker"
  onOpenChange={(open) => handleCloseRanger(open)}
  defaultValue={[
    moment().subtract('days', 29),
    moment().endOf('d'),
  ]}
  allowClear={false}
  disabledDate={disabledDate}
  onChange={handleDateValueChange}
/>



// grab the input
const rangePicker = screen
  .getByTestId('select-rangePicker')
  .querySelectorAll('input')[0];
// mouseDown opens the calendar popup, set focus on the input
fireEvent.mouseDown(rangePicker);
// type date in input
fireEvent.change(rangePicker, { target: { value: '2020-01-15' } });
// now calendar popup is opened and 2020-01-15 cell is selected, just click on it
fireEvent.click(
  document.querySelector('.ant-picker-cell-selected') as Element,
);

没有标识的input

没有label,没有placeholder的input,如果用form包裹,那么他就会打上id,可以考虑用queryselector

<Form.Item
  name="allocationCount"
  validateFirst
  validateTrigger="onBlur"
>
  <Input />
</Form.Item>



const allocationCount = document.querySelector('#allocationCount');

// 在搜索输入框中输入 'test'
fireEvent.change(allocationCount as Element, {
  target: { value: '100' },
});