reactjs - 如何使用 FormData 发送 event.target 以模拟函数

标签 reactjs jestjs enzyme

我试图模拟一个使用 FormData 的函数.该函数接受依赖于目标中某些内容的事件参数。

  buildFormData: (event) => {
    event.preventDefault();
    const { target } = event;
    const data = new FormData(target);

    if (target.querySelectorAll('.ant-select').length) {
      const selectTags = target.querySelectorAll('.ant-select');

      selectTags.forEach((selectTag) => {
        const value = selectTag.querySelector('.ant-select-selection-selected-value').getAttribute('title');
        const property = selectTag.getAttribute('id');
        data.append(property, value);
      });
    }

    const getDataObject = {};

    for (var pair of data.entries()) {
      // Ensures that the data from the forms have a value
      if (pair[1]) {
        getDataObject[pair[0]] = pair[1];
      }
    }

    return getDataObject;
  }

我想确保该函数从模拟形式返回一个值对象。

我试过通过:
const event = {
  target: {}
}

但很快意识到目标是空的。

有没有一种简单的方法来模拟这些数据,以便我从上面的函数中获得预期的返回?

最佳答案

这是解决方案,您可以模拟 FormData并填写 event手动:
index.tsx :

import React, { Component } from 'react';
import console = require('console');

class XComponent extends Component {
  constructor(props) {
    super(props);
    this.buildFormData = this.buildFormData.bind(this);
  }
  public buildFormData(event) {
    event.preventDefault();
    const { target } = event;
    const data: any = new FormData(target);

    if (target.querySelectorAll('.ant-select').length) {
      const selectTags = target.querySelectorAll('.ant-select');

      selectTags.forEach(selectTag => {
        const value = selectTag.querySelector('.ant-select-selection-selected-value').getAttribute('title');
        const property = selectTag.getAttribute('id');
        data.append(property, value);
      });
    }

    const getDataObject = {};
    for (const pair of data.entries()) {
      // Ensures that the data from the forms have a value
      if (pair[1]) {
        getDataObject[pair[0]] = pair[1];
      }
    }

    return getDataObject;
  }

  public render() {
    return (
      <div>
        <form onSubmit={this.buildFormData}></form>
      </div>
    );
  }
}

export default XComponent;
index.spec.tsx :

import React from 'react';
import XComponent from './';
import { shallow } from 'enzyme';

const FormDataMock = {
  append: jest.fn(),
  entries: jest.fn()
};

describe('XComponent', () => {
  const mockedFormEvent = { target: { querySelectorAll: jest.fn() }, preventDefault: jest.fn() };

  beforeEach(() => {
    (global as any).FormData = jest.fn(() => FormDataMock);
  });

  afterEach(() => {
    jest.resetAllMocks();
  });

  it('should build form data correctly without select tags', () => {
    mockedFormEvent.target.querySelectorAll.mockReturnValueOnce([]);
    FormDataMock.entries.mockReturnValueOnce([['k1', 'v1'], ['k2', 'v2'], ['k3', 'v3']]);
    const wrapper = shallow(<XComponent></XComponent>);
    const actualValue = (wrapper.instance() as any).buildFormData(mockedFormEvent);
    expect(actualValue).toEqual({ k1: 'v1', k2: 'v2', k3: 'v3' });
    expect(mockedFormEvent.preventDefault).toBeCalledTimes(1);
    expect(mockedFormEvent.target.querySelectorAll).toBeCalledWith('.ant-select');
    expect((global as any).FormData).toBeCalledTimes(1);
  });

  it('should build form data correctly with select tags', () => {
    const mockedSelectTag = { querySelector: jest.fn().mockReturnThis(), getAttribute: jest.fn() };
    const mockedSelectTags = [mockedSelectTag];
    (mockedSelectTag.querySelector().getAttribute as any).mockReturnValueOnce('value').mockReturnValueOnce('property');
    mockedFormEvent.target.querySelectorAll.mockReturnValue(mockedSelectTags);
    FormDataMock.entries.mockReturnValueOnce([['k1', 'v1'], ['k2', 'v2'], ['k3', 'v3']]);
    const wrapper = shallow(<XComponent></XComponent>);
    const actualValue = (wrapper.instance() as any).buildFormData(mockedFormEvent);
    expect((global as any).FormData).toBeCalledTimes(1);
    expect(actualValue).toEqual({ k1: 'v1', k2: 'v2', k3: 'v3' });
    expect(FormDataMock.append).toBeCalledWith('property', 'value');
    expect(mockedFormEvent.preventDefault).toBeCalledTimes(1);
    expect(mockedFormEvent.target.querySelectorAll).toBeCalledWith('.ant-select');
  });
});

带有覆盖率报告的单元测试结果:

 PASS  src/stackoverflow/58136380/index.spec.tsx (5.601s)
  XComponent
    ✓ should build form data correctly without select tags (11ms)
    ✓ should build form data correctly with select tags (3ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |    83.33 |      100 |      100 |                   |
 index.tsx |      100 |    83.33 |      100 |      100 |                27 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        10.438s, estimated 15s

源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58136380

关于reactjs - 如何使用 FormData 发送 event.target 以模拟函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58136380/

相关文章:

javascript - React-Boilerplate 在没有端口的情况下运行生产

javascript - 获取 API 不通过 post 发送数据

TypeScript 无法识别我的 jest mock 模块

reactjs - enzyme 无法通过构造函数选择器找到,但通过显示名称选择器成功找到

javascript - React/Flux 调度程序作为 Typescript 中的单例

reactjs - 为什么 create-react-app 在尝试 eslint 时会给出 typescript 错误(尽管没有 typescript 文件)?

reactjs - 不能在测试中设置属性

javascript - JavaScript 中自定义错误消息的单元测试

reactjs - 如何在enzyme中调用多个setProps?

javascript - 与 jsdom 开 Jest ,文档在 Promise 解析中未定义