开玩笑:无法读取未定义的属性"辅助" - 在 MUI 从 V4 升级到 V5 之后



我们将MUI从v4升级到v5,UI测试开始失败。错误为:

TypeError: Cannot read property 'secondary' of undefined (I added comment to which line in code this refers)

测试示例:

describe('<AnonDragNDropFileUpload />', () => {
it('should render', () => {
const blob = () => {
return new File(['Test string'], 'Test file.txt');
};
const fileSet: AnonFileSet = {
originalFile: { get: blob, set: () => undefined },
compressedFile: { get: () => undefined, set: () => undefined },
};
const result = render(<AnonDragNDropFileUpload fileSet={fileSet} downloadFileAction={jest.fn()} clearFileAction={jest.fn()} />);
expect(result).toBeTruthy();
});
});

代码:

import { Paper } from '@mui/material';
import { green, red } from '@mui/material/colors';
import { lighten, Theme } from '@mui/material/styles';
import makeStyles from '@mui/styles/makeStyles';
import { JobInputFileTypeEnum } from 'app/api';
import React, { useCallback, useEffect, useState } from 'react';
import { useDropzone } from 'react-dropzone';
import { AnonFileSet } from '.';
const useDropZoneStyles = makeStyles((theme: Theme) => ({
dragndropZone: {
backgroundColor: lighten(theme.palette.secondary.light, 0.8), // <-- this line fails
width: '100%',
},
info: {
backgroundColor: green[100],
width: '100%',
},
}));
interface Props {
fileSet: AnonFileSet;
clearFileAction: (fileType?: JobInputFileTypeEnum) => void;
downloadFileAction: () => void;
}
export const AnonDragNDropFileUpload: React.FC<Props> = ({ fileSet, clearFileAction, downloadFileAction }) => {
const classes = useDropZoneStyles();
const [fileLabel, setFileLabel] = useState('');
const onDrop = useCallback(async (acceptedFiles: File[]) => {
setFileLabel(fileSet.originalFile.get()?.name ?? '');
fileSet.originalFile.set(acceptedFiles[0]);
}, []);
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({ onDrop, multiple: false, accept: '.csv' });
const { ref, ...rootProps } = getRootProps();
const handleDeleteFile = () => {
acceptedFiles.splice(
acceptedFiles.findIndex((x) => x.name === fileSet.originalFile.get()?.name),
1,
);
clearFileAction();
};
useEffect(() => {
setFileLabel(fileSet.originalFile.get()?.name ?? '');
}, [fileSet.originalFile.get()]);
if (fileSet.originalFile.get())
return (
<Paper variant="outlined">
<div className="flex px-8 py-32 justify-center">
<div className="flex">
<a style={{ color: '#888888', textDecoration: 'underline', cursor: 'default' }}>{fileLabel}</a>
<p className="mx-4">&nbsp;</p>
<a onClick={handleDeleteFile} style={{ color: red[600], cursor: 'pointer' }} role="link">
{'[Clear File]'}
</a>
<p className="mx-4">&nbsp;</p>
{fileSet.compressedFile?.get() && (
<a onClick={downloadFileAction} style={{ color: green[600], cursor: 'pointer' }} role="link">
{'[Download File]'}
</a>
)}
</div>
</div>
</Paper>
);
return (
<Paper {...rootProps} className={classes.dragndropZone} variant="outlined">
<div className="flex px-8 py-32 justify-center">
<input {...getInputProps()} name="customerCSVFilename" placeholder="CSV File"/>
<p>{fileLabel}</p>
</div>
</Paper>
);
};

到目前为止我尝试过的:

  • 已检查ThemeProvider是否可用
  • 仅向失败的代码块添加了自定义主题

所有其他测试挂钩或自定义逻辑(如纯TypeScript(都可以正常工作,但似乎以某种方式使用MUI中的样式不起作用。当我删除这些行时,测试通过了,所以我猜它与MUImakeStyles有关。有什么想法吗?谢谢你帮我。

尝试使用封装在ThemeProvider实例中的模拟组件:

import theme from './path/to/your/theme'
const MockAnonDragNDropFileUpload = (props: any) => {
return (
<ThemeProvider theme={theme}>
<AnonDragNDropFileUpload {...props} />
</ThemeProvider>
);
}

要使用现有的theme模拟组件,可以将其声明分离为一个不同的文件:

const theme = createTheme({
...
});
export default theme;

然后在测试中使用模拟实例:

describe('<AnonDragNDropFileUpload />', () => {
it('should render', () => {
...
const result = render(
<MockAnonDragNDropFileUpload
fileSet={fileSet}
downloadFileAction={jest.fn()}
clearFileAction={jest.fn()}
/>
);
expect(result).toBeTruthy();
});
});

最新更新