嗨,我正在尝试测试一个由Material创建的Slider组件,但是我无法将我的测试拿到经过上。我想使用fireEvent和@testing-library/react测试值的变化。我一直在跟踪这篇文章来正确地查询DOM,但我无法获得正确的DOM节点。
提前谢谢。
<Slider /> 组件
// @format
// @flow
import * as React from "react";
import styled from "styled-components";
import { Slider as MaterialUISlider } from "@material-ui/core";
import { withStyles, makeStyles } from "@material-ui/core/styles";
import { priceRange } from "../../../domain/Search/PriceRange/priceRange";
const Wrapper = styled.div`
width: 93%;
display: inline-block;
margin-left: 0.5em;
margin-right: 0.5em;
margin-bottom: 0.5em;
`;
// ommited code pertaining props and styles for simplicity
function Slider(props: SliderProps) {
const initialState = [1, 100];
const [value, setValue] = React.useState(initialState);
function onHandleChangeCommitted(e, latestValue) {
e.preventDefault();
const { onUpdate } = props;
const newPriceRange = priceRange(latestValue);
onUpdate(newPriceRange);
}
function onHandleChange(e, newValue) {
e.preventDefault();
setValue(newValue);
}
return (
<Wrapper
aria-label="range-slider"
>
<SliderWithStyles
aria-labelledby="range-slider"
defaultValue={initialState}
// getAriaLabel={index =>
// index === 0 ? "Minimum Price" : "Maximum Price"
// }
getAriaValueText={valueText}
onChange={onHandleChange}
onChangeCommitted={onHandleChangeCommitted}
valueLabelDisplay="auto"
value={value}
/>
</Wrapper>
);
}
export default Slider;Slider.test.js
// @flow
import React from "react";
import { cleanup,
render,
getAllByAltText,
fireEvent,
waitForElement } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";
import Slider from "../Slider";
afterEach(cleanup);
describe("<Slider /> specs", () => {
// [NOTE]: Works, but maybe a better way to do it ?
xdescribe("<Slider /> component aria-label", () => {
it("renders without crashing", () => {
const { container } = render(<Slider />);
expect(container.firstChild).toBeInTheDocument();
});
});
// [ASK]: How to test the event handlers with fireEvent.
describe("<Slider /> props", () => {
it("display a initial min value of '1'", () => {
const renderResult = render(<Slider />);
// TODO
});
it("display a initial max value of '100'", () => {
const renderResult = render(<Slider />);
// TODO
});
xit("display to values via the onHandleChangeCommitted event when dragging stop", () => {
const renderResult = render(<Slider />);
console.log(renderResult)
// fireEvent.change(renderResult.getByText("1"))
// expect(onChange).toHaveBeenCalled(0);
});
// [NOTE]: Does not work, returns undefined
xit("display to values via the onHandleChange event when dragging stop", () => {
const renderResult = render(<Slider />);
console.log(renderResult.container);
const spanNodeWithAriaAttribute = renderResult.container.firstChild.getElementsByTagName("span")[0].getAttribute('aria-label')
expect(spanNodeWithAriaAttribute).toBe(/range-slider/)
});
});
// [ASK]: Works, but a snapshot is an overkill a better way of doing this ?
xdescribe("<Slider /> snapshot", () => {
it("renders without crashing", () => {
const { container } = render(<Slider />);
expect(container.firstChild).toMatchSnapshot();
});
});
});发布于 2020-05-06 06:32:50
我建议不要为自定义组件编写测试,并且相信这个组件适用于我们的所有情况。
有关更多细节,请通过这篇文章阅读。在这方面,他们提到了如何为包装react-select的组件编写单元测试。
我遵循了类似的方法,并为第三方滑块组件编写了一个模拟。
在setupTests.js中
jest.mock('@material-ui/core/Slider', () => (props) => {
const { id, name, min, max, onChange, testid } = props;
return (
<input
data-testid={testid}
type="range"
id={id}
name={name}
min={min}
max={max}
onChange={(event) => onChange(event.target.value)}
/>
);
});使用这个模拟,您只需在测试中触发一个更改事件,如下所示:
fireEvent.change(getByTestId(`slider`), { target: { value: 25 } });确保将正确的testid作为SliderWithStyles组件的支柱传递给
发布于 2020-06-07 03:53:33
在与此斗争了几个小时后,我能够解决与测试MUI滑块相关的问题。
这确实取决于您需要如何测试您的文本,在我的例子中,我必须检查标签文本内容在使用marks滑块道具单击标记后是否发生了变化。
问题
1) slider组件基于元素getBoundingClientRect和MouseEvent计算返回值。
2)如何查询slider并触发事件。
3) JSDOM对阅读元件实际高度和宽度的限制,造成了1号问题。
解决方案
1)模拟getBoundingClientRect还应该修复第3号问题
2)在滑块中添加测试id,并使用fireEvent.mouseDown(contaner, {....})
const sliderLabel = screen.getByText("Default text that the user should see")
// add data-testid to slider
const sliderInput = screen.getByTestId("slider")
// mock the getBoundingClientRect
sliderInput.getBoundingClientRect = jest.fn(() => {
return {
bottom: 286.22918701171875,
height: 28,
left: 19.572917938232422,
right: 583.0937919616699,
top: 258.22918701171875,
width: 563.5208740234375,
x: 19.572917938232422,
y: 258.22918701171875,
}
})
expect(sliderInput).toBeInTheDocument()
expect(sliderLabel).toHaveTextContent("Default text that the user should see")
await fireEvent.mouseDown(sliderInput, { clientX: 162, clientY: 302 })
expect(sliderLabel).toHaveTextContent(
"New text that the user should see"
)发布于 2020-07-09 17:16:00
我把上面提到的解决方案变成了简单的(打字本)助手。
export class Slider {
private static height = 10
// For simplicity pretend that slider's width is 100
private static width = 100
private static getBoundingClientRectMock() {
return {
bottom: Slider.height,
height: Slider.height,
left: 0,
right: Slider.width,
top: 0,
width: Slider.width,
x: 0,
y: 0,
} as DOMRect
}
static change(element: HTMLElement, value: number, min: number = 0, max: number = 100) {
const getBoundingClientRect = element.getBoundingClientRect
element.getBoundingClientRect = Slider.getBoundingClientRectMock
fireEvent.mouseDown(
element,
{
clientX: ((value - min) / (max - min)) * Slider.width,
clientY: Slider.height
}
)
element.getBoundingClientRect = getBoundingClientRect
}
}用法:
Slider.change(getByTestId('mySlider'), 40) // When min=0, max=100 (default)
// Otherwise
Slider.change(getByTestId('mySlider'), 4, 0, 5) // Sets 4 with scale set to 0-5https://stackoverflow.com/questions/58856094
复制相似问题