首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用玩笑正确地模拟‘`antd`’上传Dragger?

如何用玩笑正确地模拟‘`antd`’上传Dragger?
EN

Stack Overflow用户
提问于 2021-06-08 22:06:30
回答 1查看 1.6K关注 0票数 9

我的项目中有以下反应代码

代码语言:javascript
复制
import React from 'react';
import { Upload } from 'antd';

const { Dragger } = Upload;

...

<Dragger
  accept={ACCEPTED_FORMATS}
  beforeUpload={beforeUpload}
  data-testid="upload-dragger"
  maxCount={1}
  onChange={({ file: { status } }) => {
    if (status === 'done') onUploadComplete();
  }}
  progress={progress}
  showUploadList={false}
>
{/* here i have a button, code ommited for clarity, if needed i'll post it */}
</Dragger>

我想测试回调函数onUploadComplete()在file.status是'done'时是否被调用。

下面是我现在做这个测试的方法:

  1. 我有一个jest.mock来模拟一个总是成功的哑请求。
代码语言:javascript
复制
import React from 'react';
import { fireEvent, render, waitFor } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { DraggerProps } from 'antd/lib/upload';
import userEvent from '@testing-library/user-event';

import UploadCompanyLogo from '../UploadCompanyLogo'; // This is the component where the dragger is placed

jest.mock('antd', () => {
  const antd = jest.requireActual('antd');
  const { Upload } = antd;
  const { Dragger } = Upload;

  const MockedDragger = (props: DraggerProps) => {
    console.log('log test');
    return (
      <Dragger
        {...props}
        action="greetings"
        customRequest={({ onSuccess }) => {
          setTimeout(() => {
            onSuccess('ok');
          }, 0);
        }}
      />
    );
  };

  return { ...antd, Upload: { ...Upload, Dragger: MockedDragger } };
});
  1. 测试本身(与模拟文件相同),它呈现组件(其中将导入antd ),模拟上传,然后检查回调是否已被调用。
代码语言:javascript
复制
it('completes the image upload', async () => {
    const flushPromises = () => new Promise(setImmediate);

    const { getByTestId } = render(elementRenderer({ onUploadComplete }));

    const file = new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' });

    const uploadDragger = await waitFor(() => getByTestId('upload-dragger'));

    await act(async () => {
      userEvent.upload(uploadDragger, file);
    });

    await flushPromises();

    expect(onUploadComplete).toHaveBeenCalledTimes(1);
    expect(onUploadComplete).toHaveBeenCalledWith();
  });
  1. elementRenderer
代码语言:javascript
复制
const elementRenderer = ({
  onUploadComplete = () => {}
}) => (
  <ApplicationProvider>
    <UploadCompanyLogo
      onUploadComplete={onUploadComplete}
    />
  </ApplicationProvider>
);
  1. ApplicationProvider
代码语言:javascript
复制
import React, { PropsWithChildren } from 'react';
import { ConfigProvider as AntdProvider } from 'antd';
import { RendererProvider as FelaProvider } from 'react-fela';
import { createRenderer } from 'fela';
import { I18nextProvider } from 'react-i18next';

import antdExternalContainer, {
  EXTERNAL_CONTAINER_ID,
} from 'src/util/antdExternalContainer';
import { antdLocale } from 'src/util/locales';
import rendererConfig from 'src/fela/felaConfig';
import i18n from 'src/i18n';

const ApplicationProvider = (props: PropsWithChildren<{}>) => {
  const { children } = props;

  return (
    <AntdProvider locale={antdLocale} getPopupContainer={antdExternalContainer}>
      <FelaProvider renderer={createRenderer(rendererConfig)}>
        <I18nextProvider i18n={i18n}>
          <div className="antd-local">
            <div id={EXTERNAL_CONTAINER_ID} />
            {children}
          </div>
        </I18nextProvider>
      </FelaProvider>
    </AntdProvider>
  );
};

export default ApplicationProvider;

这目前还不起作用,但已经在@diedu的帮助下得到了改进。

我把console.log()放进了MockedDragger,它现在还没有显示出来。如果我将一个console.log()放在组件和mockedDragger中,它会打印组件日志。

有什么关于如何进行的建议吗?我已经看过这个问题了,但没有帮上忙。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-14 01:49:04

您应该更改的第一件事是在模拟中所做的返回。您正在返回一个名为MockedDragger的新组件,而不是Dragger

代码语言:javascript
复制
  return { ...antd, Upload: { ...Upload, Dragger: MockedDragger } };

下一件事是事件触发。根据本期,您应该使用RTL用户事件库,并将调用包装在act中。

代码语言:javascript
复制
import userEvent from "@testing-library/user-event";

...
  await act(async () => {
    userEvent.upload(uploadDragger, file);
  });
...

最后,由于一些异步代码在检查调用之前运行你需要清除那些悬而未决的承诺

代码语言:javascript
复制
  const flushPromises = () => new Promise(setImmediate);
  ...
  await flushPromises();
  expect(onUploadComplete).toHaveBeenCalled()

这是完整的版本

代码语言:javascript
复制
import { render, waitFor } from "@testing-library/react";
import App from "./App";
import userEvent from "@testing-library/user-event";
import { act } from "react-dom/test-utils";
import { DraggerProps } from "antd/lib/upload";

jest.mock('antd', () => {
  const antd = jest.requireActual('antd');
  const { Upload } = antd;
  const { Dragger } = Upload;

  const MockedDragger = (props: DraggerProps) => {
    return <Dragger {...props} customRequest={({ onSuccess }) => {
      setTimeout(() => {
        onSuccess('ok');
      }, 0)
    }} />;
  };

  return { ...antd, Upload: { ...Upload, Dragger: MockedDragger } };
});

it("completes the image upload", async () => {
  const onUploadComplete = jest.fn();
  const flushPromises = () => new Promise(setImmediate);

  const { getByTestId } = render(
    <App onUploadComplete={onUploadComplete} />
  );

  const file = new File(["(⌐□_□)"], "chucknorris.png", { type: "image/png" });

  const uploadDragger = await waitFor(() => getByTestId("upload-dragger"));
  await act(async () => {
    userEvent.upload(uploadDragger, file);
  });
  await flushPromises();
  expect(onUploadComplete).toHaveBeenCalled();
});

不幸的是,我无法设置一个代码框来显示它是有效的,但是如果您面临任何问题,请告诉我,我可以将代码推送到回购程序中。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67895146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档