reactjs - 在基于 Material-UI 的组件中模拟道具 - Jest 和 React-Testing-Library
问题描述
我无法以任何方式模拟 Material-UI 中的 Switch 组件。我应该如何正确模拟组件的道具?
我测试了函数的逻辑并且它有效。手动它也可以。但是我无法通过快照触发 DOM 树中的任何更改;甚至无法将标签从“深色模式”更改为“浅色模式”。
单元测试所有工作;使用 fireEvent.change 进行快照测试,但更改不会出现在快照上。在代码中指出失败的地方。我应该如何正确模拟它?
测试
import React from 'react';
import { render, cleanup, fireEvent, screen } from '@testing-library/react';
import { Provider } from 'react-redux';
import { BrowserRouter as Router } from 'react-router-dom';
import userEvent from '@testing-library/user-event';
import Component from '../index';
import store from '../../../@state/createStore';
import '@testing-library/jest-dom/extend-expect';
import { GtagService, GtagServiceInterface } from '../../../../shared/services/gtag-service/index';
import SENSORS_TABLE_CONSTANTS from '../../../../pages/dashboard-page/components/sensors-table/constants';
import GTAG_EVENTS, { GtagEvent } from '../../../../shared/gtag/constants';
// BASIC UNIT TESTS FOR THE TOGGLE METHODS, all work here
afterEach(cleanup);
describe('Top Bar Switch: methods and behaviour:', () => {
let service: GtagServiceInterface;
let sendEventMockImplementation;
describe('when behaviour tracking is enabled', () => {
beforeEach(() => {
service = new GtagService((...args) => {}, true, SENSORS_TABLE_CONSTANTS.SENSORS_TABLE_COLUMNS);
sendEventMockImplementation = jest.spyOn(service, 'sendEvent').mockImplementation(() => true);
});
describe('method: darkModeToggle', () => {
it('passes GTAG_EVENTS.HEADER.LIGHT_MODE event to sendEvent method when DARK_MODE enabled', () => {
service.darkModeToggle(true);
expect(sendEventMockImplementation).toHaveBeenCalled();
expect(sendEventMockImplementation).toHaveBeenCalledWith(GTAG_EVENTS.HEADER.LIGHT_MODE);
});
});
it('Should pass the correct objects props once the dark mode IS toggled', () => {
service.darkModeToggle(true);
expect(sendEventMockImplementation).toHaveBeenCalledWith({ ACTION: 'Click', CATEGORY: 'Header', LABEL: 'Light Mode', VALUE: 0 });
expect(sendEventMockImplementation).toHaveBeenCalledWith(GTAG_EVENTS.HEADER.LIGHT_MODE);
});
it('Should pass the correct objects props once the dark mode IS NOT toggled', () => {
service.darkModeToggle(false);
expect(sendEventMockImplementation).toHaveBeenCalledWith({ ACTION: 'Click', CATEGORY: 'Header', LABEL: 'Dark Mode', VALUE: 0 });
expect(sendEventMockImplementation).not.toHaveBeenCalledWith(GTAG_EVENTS.HEADER.LIGHT_MODE);
});
});
// SNAPSHOT TESTS - snapshots stay the same, nothing changes even if i try to interract with the app
describe('Switch tests:', () => {
let isDarkModeOn;
const WrappedComponent = (isDarkModeOn: boolean) =>
render(
<Provider store={store}>
<Router>
<Component isDarkModeOn={isDarkModeOn} />
</Router>
</Provider>,
);
it('Should create a snapshot', () => {
const { asFragment } = WrappedComponent((isDarkModeOn = false));
expect(asFragment()).toMatchSnapshot();
});
it('Should create a switch snapshot', () => {
const { getByRole, asFragment, getByTestId } = WrappedComponent((isDarkModeOn = false));
const testswitch = getByTestId('switch');
expect(testswitch).toMatchSnapshot();
});
it('Should change the switch', () => {
const { getByRole, asFragment, getByTestId } = WrappedComponent((isDarkModeOn = false));
const label = getByTestId('label');
fireEvent.change(getByRole('checkbox'), { target: { checked: 'true' } });
// event fired, target checked property correct, but not visible on the snapshot
expect(getByRole('checkbox')).toHaveProperty('checked', true);
// test below fails
expect(label.textContent).toContain('TO LIGHT MODE');
expect(asFragment()).toMatchSnapshot();
});
it('Should NOT change the switch', () => {
const { getByRole, asFragment, getByTestId } = WrappedComponent((isDarkModeOn = false));
const testswitch = getByTestId('switch');
fireEvent.change(getByRole('checkbox'), { target: { checked: '' } });
// Event fired, target checked property correct, but not visible on the snapshot
expect(getByRole('checkbox')).toHaveProperty('checked', false);
expect(asFragment()).toMatchSnapshot();
});
it('Should call gtag Send Event (but idk why it doesnt change the label)', () => {
const { getByRole, asFragment, getByTestId } = WrappedComponent((isDarkModeOn = false));
const label = getByTestId('label');
service.darkModeToggle(true);
// Methods work correctly, correct gtag events are called, but doesnt change the label in the Typography component
expect(sendEventMockImplementation).toHaveBeenCalledWith({ ACTION: 'Click', CATEGORY: 'Header', LABEL: 'Light Mode', VALUE: 0 });
expect(sendEventMockImplementation).toHaveBeenCalledWith(GTAG_EVENTS.HEADER.LIGHT_MODE);
// expect(label.textContent).toContain('TO LIGHT MODE');
expect(asFragment()).toMatchSnapshot();
});
});
});
零件:
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormGroup from '@material-ui/core/FormGroup';
import Switch from '@material-ui/core/Switch';
import Typography from '@material-ui/core/Typography';
import { ClassNameMap } from '@material-ui/styles';
import React, { FC } from 'react';
import { ActionCreator } from 'redux';
import { GtagServiceInterface } from '../../../shared/services/gtag-service';
import { TOGGLE } from '../../@state/@dark-mode/dark-mode-action-annotations';
const Component: FC<Props> = ({ classes, gtagService, isDarkModeOn, darkModeToggle }) => (
<FormGroup>
<FormControlLabel
control={
<Switch
data-testid="switch"
checked={isDarkModeOn}
onChange={() => {
gtagService.darkModeToggle(isDarkModeOn);
darkModeToggle();
}}
/>
}
label={
<Typography variant="button" className={classes.label} data-testid="label">
{isDarkModeOn ? 'TO LIGHT MODE' : 'TO DARK MODE'}
</Typography>
}
labelPlacement="start"
/>
</FormGroup>
);
interface Props {
classes: Partial<ClassNameMap>;
gtagService: GtagServiceInterface;
isDarkModeOn: boolean;
darkModeToggle: ActionCreator<TOGGLE>;
}
export default Component;
解决方案
推荐阅读
- qt - 无法设置 LineSeries 的透明度{}
- ruby-on-rails - Rails 6多态模型给出验证错误
- javascript - 滚动时触发 Lottie 动画
- powershell - 使用 Powershell 将多行对象转换为多个对象
- c++ - 使用带有右值的条件运算符时,采用 const pmr::vector<>& 不传播分配器
- javascript - How do I get BOT to create a private chat? (Discord.js)
- javascript - 推荐部分在我的网站上不起作用
- javascript - 将最后一个参数传递给函数 - JavaScript
- next.js - 在 Axios 拦截器下捕获 400 和 500 用于哨兵
- puppeteer - Crawlera & Puppeteer - HTTPS 中的身份验证问题