gpt4 book ai didi

reactjs - Jest 在 React 中测试异步图像上传

转载 作者:行者123 更新时间:2023-12-04 12:54:25 29 4
gpt4 key购买 nike

我正在尝试测试一系列在用户上传文件后异步运行的函数。这些函数都在一个名为 UploadImageModal 的 React 组件中。这些函数由这个 on change 函数触发:

const onChange = async () => {
try {
const file = document.querySelector('#upload-profile-img-dialog')
.files[0];
if (file) {
const fileData = {
mimeType: file.type,
base64: await getBase64(file),
file
};

await hasMinPicDimension(fileData);
setPicFile(fileData);
}
} catch (error_) {
setError(error_.message);
}
};
这个 on change 函数然后调用这个 hasMinPicDimensions 函数:
const hasMinPicDimension = ({ mimeType, base64, file }) =>
new Promise((resolve, reject) => {
const image = new Image();
image.src = `data:${mimeType};base64,${base64}`;
image.addEventListener('load', () => {
if (!['image/gif', 'image/jpeg', 'image/png'].includes(mimeType)) {
return reject(new Error('Image is not a supported type'));
}

if (image.height >= 151 && image.width >= 151) {
return resolve({ mimeType, base64, file });
}

return reject(new Error('Image is too small'));
});

image.addEventListener('error', () => {
reject(new Error('File is not an image'));
});
});
在该函数解析它的 promise 之后,setPicFile,这是一个 react 状态更改,它将组件 src 更改为具有图像的数据 URI。
这是图像上传输入组件:
<Input
id="upload-profile-img-dialog"
name="profileImage"
type="file"
accept="image/gif,image/jpeg,image/png"
onChange={onChange}
sx={{ visibility: 'hidden' }}
data-testid="fileinput"
/>
我曾尝试通过仅使用 Jest 来模拟图像上传来测试此功能 - 但无论上述功能如何都不会触发,因为 Jest 不会等待 promise 解决。
有没有人对我如何用 Jest 做到这一点有任何建议?如果我也需要使用 enyzme,那就没问题了。

最佳答案

我们测试组件,模拟组件依赖的其他模块以及模块导出的功能。
例如。index.jsx :

import React, { useState } from 'react';
import { getBase64, hasMinPicDimension } from './helpers';

export function UploadImageModal() {
const [error, setError] = useState('');
const [picFile, setPicFile] = useState();

const onChange = async () => {
try {
const file = document.querySelector('#upload-profile-img-dialog').files[0];
if (file) {
const fileData = {
mimeType: file.type,
base64: await getBase64(file),
file,
};

await hasMinPicDimension(fileData);
setPicFile(fileData);
}
} catch (error_) {
setError(error_.message);
}
};

if (error) return <p>{error}</p>;

// I use console.log to simulate using picFile
console.log('picFile: ', picFile);

return (
<input
id="upload-profile-img-dialog"
name="profileImage"
type="file"
accept="image/gif,image/jpeg,image/png"
onChange={onChange}
data-testid="fileinput"
/>
);
}
helpers.js :
export const hasMinPicDimension = async ({ mimeType, base64, file }) =>
new Promise((resolve, reject) => {
const image = new Image();
image.src = `data:${mimeType};base64,${base64}`;
image.addEventListener('load', () => {
if (!['image/gif', 'image/jpeg', 'image/png'].includes(mimeType)) {
return reject(new Error('Image is not a supported type'));
}

if (image.height >= 151 && image.width >= 151) {
return resolve({ mimeType, base64, file });
}

return reject(new Error('Image is too small'));
});

image.addEventListener('error', () => {
reject(new Error('File is not an image'));
});
});

export async function getBase64(file) {
console.log('Your getBase64 real implementation');
}
index.test.jsx :
import React from 'react';
import { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
import { UploadImageModal } from './';
import { getBase64, hasMinPicDimension } from './helpers';

jest.mock('./helpers');

describe('68818166', () => {
afterEach(() => {
jest.restoreAllMocks();
});
afterAll(() => {
jest.resetAllMocks();
});
test('should upload file', async () => {
const file = new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' });
jest.spyOn(document, 'querySelector').mockReturnValueOnce({ files: [file] });
const logSpy = jest.spyOn(console, 'log');
getBase64.mockResolvedValueOnce('mocked file base64 string');
hasMinPicDimension.mockImplementationOnce((file) => file);
render(<UploadImageModal />);
fireEvent.change(screen.queryByTestId('fileinput'));
await waitFor(() =>
expect(logSpy).toBeCalledWith('picFile: ', {
mimeType: 'image/png',
base64: 'mocked file base64 string',
file,
})
);
});

test('should handle error if file is invalid', async () => {
const file = new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' });
jest.spyOn(document, 'querySelector').mockReturnValueOnce({ files: [file] });
getBase64.mockResolvedValueOnce('mocked file base64 string');
hasMinPicDimension.mockRejectedValueOnce(new Error('Image is too small'));
render(<UploadImageModal />);
await act(async () => {
fireEvent.change(screen.queryByTestId('fileinput'));
});
await waitFor(() => {
expect(screen.findByText(/Image is too small/)).toBeTruthy();
});
});
});
测试结果:
  console.log
picFile: undefined

at console.<anonymous> (node_modules/jest-mock/build/index.js:845:25)

console.log
picFile: {
mimeType: 'image/png',
base64: 'mocked file base64 string',
file: File {}
}

at console.<anonymous> (node_modules/jest-mock/build/index.js:845:25)

console.log
picFile: undefined

at UploadImageModal (examples/68818166/index.jsx:29:11)

PASS examples/68818166/index.test.jsx
68818166
✓ should upload file (105 ms)
✓ should handle error if file is invalid (10 ms)

------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 61.76 | 30 | 33.33 | 60 |
helpers.js | 18.75 | 0 | 0 | 14.29 | 2-18,23
index.jsx | 100 | 75 | 100 | 100 | 11
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 2.409 s, estimated 10 s

关于reactjs - Jest 在 React 中测试异步图像上传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68818166/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com