在反应测试中 fireEvent.click 之后将 aria-checked 属性 of radio 设置为 true
set aria-checked property of radio to true after fireEvent.click in react-testing
我想在 fireEvent.click 之后将单选按钮的 aria-checked 属性 设置为 true。我不想通过 setAttribute 而是通过 onclick 来完成。
我尝试了以下代码来测试我的组件。
Radiobutton.js
function Radiobutton(props) {
const { label, onClick, onKeyPress, isChecked } = props;
return (
<div
className="radiobutton"
role="radio"
onClick={onClick}
onKeyDown={onKeyPress}
aria-checked={isChecked}
tabIndex={0}
value={label}
>
<span className="radiobutton__label">{label}</span>
</div>
);
}
Radiobutton.test.jsx
test("radiobuttons must use click", () => {
const handleChange = jest.fn();
const { container } = render(
<Radiobutton onClick={handleChange} isChecked={false} label="Dummy Radio" />
);
const radiobtn = getByRole(container, "radio");
fireEvent.click(radiobtn);
expect(handleChange).toHaveBeenCalledTimes(1);
expect(radiobtn.getAttribute("aria-checked")).toBe("true");
});
我可以调用 handleChange 函数但无法更改 aria-checked 的值。我收到以下错误。
expect(received).toBe(expected) // Object.is equality
Expected: "true"
Received: "false"
30 | expect(handleChange).toHaveBeenCalledTimes(1);
> 31 | expect(radiobtn.getAttribute("aria-checked")).toBe("true");
| ^
32 | console.log(prettyDOM(radiobtn));
33 | });
at Object.toBe (src/__tests__/radiobutton.test.jsx:31:49)
我是测试新手。任何帮助将非常感激。提前致谢。
根据您组件的代码处理,父元素发生变化。要在测试中模拟此行为,您需要在调用 handleChange
后更新 isChecked
属性。
最多 maintainer's comment 实现的方法是 re-rendering 将相同的元素放入具有不同道具的相同容器中:
test("radiobuttons must use click", () => {
const handleChange = jest.fn();
const { container } = render(
<Radiobutton onClick={handleChange} isChecked={false} label="Dummy Radio" />
);
const radiobtn = getByRole(container, "radio");
fireEvent.click(radiobtn);
expect(handleChange).toHaveBeenCalledTimes(1);
render(<Radiobutton onClick={handleChange} isChecked={true} label="Dummy Radio" />, { container });
expect(radiobtn.getAttribute("aria-checked")).toBe("true");
});
您也可以将 re-rendering 逻辑放在 handleChange.mockImplementation
中,但我相信这会使测试用例更难阅读:
test("radiobuttons must use click", () => {
let isChecked = false;
const handleChange = jest.fn();
const { container } = render(
<Radiobutton onClick={handleChange} isChecked={false} label="Dummy Radio" />
);
handleChange.mockImplementation(() => {
isChecked = !isChecked;
render(<Radiobutton onClick={handleChange} isChecked={isChecked} label="Dummy Radio" />, { container });
});
const radiobtn = getByRole(container, "radio");
fireEvent.click(radiobtn);
expect(handleChange).toHaveBeenCalledTimes(1);
expect(radiobtn.getAttribute("aria-checked")).toBe("true");
});
另一个缺点是 handleChange
逻辑应该在父组件中的某处,所以你宁愿测试你自己的模拟而不是测试你的应用程序。
对我来说,它看起来真的很乱,并且不会为您提供任何额外的价值,因为在现实世界中,它是否在 onClick
之后更新 isChecked
取决于父组件。
所以我建议你把测试用例分成两部分。首先检查点击是否调用 onClick
处理程序。并单独检查 isChecked={true}
是否提供 aria-checked
。也许更好的是让第 3 个检查 isChecked={false}
是否不注入 aria-checked
属性。
test('provides aria-checked if isChecked is truly`, () => {
const { container } = render(<Radiobutton isChecked={true} />);
const radiobtn = getByRole(container, "radio");
expect(radiobtn.getAttribute("aria-checked")).toBe("true");
});
test('does not provide aria-checked if isChecked is falsy`, () => {
const { container } = render(<Radiobutton />);
const radiobtn = getByRole(container, "radio");
expect(radiobtn.getAttribute("aria-checked")).not.toBe("true");
});
我想在 fireEvent.click 之后将单选按钮的 aria-checked 属性 设置为 true。我不想通过 setAttribute 而是通过 onclick 来完成。
我尝试了以下代码来测试我的组件。
Radiobutton.js
function Radiobutton(props) {
const { label, onClick, onKeyPress, isChecked } = props;
return (
<div
className="radiobutton"
role="radio"
onClick={onClick}
onKeyDown={onKeyPress}
aria-checked={isChecked}
tabIndex={0}
value={label}
>
<span className="radiobutton__label">{label}</span>
</div>
);
}
Radiobutton.test.jsx
test("radiobuttons must use click", () => {
const handleChange = jest.fn();
const { container } = render(
<Radiobutton onClick={handleChange} isChecked={false} label="Dummy Radio" />
);
const radiobtn = getByRole(container, "radio");
fireEvent.click(radiobtn);
expect(handleChange).toHaveBeenCalledTimes(1);
expect(radiobtn.getAttribute("aria-checked")).toBe("true");
});
我可以调用 handleChange 函数但无法更改 aria-checked 的值。我收到以下错误。
expect(received).toBe(expected) // Object.is equality
Expected: "true"
Received: "false"
30 | expect(handleChange).toHaveBeenCalledTimes(1);
> 31 | expect(radiobtn.getAttribute("aria-checked")).toBe("true");
| ^
32 | console.log(prettyDOM(radiobtn));
33 | });
at Object.toBe (src/__tests__/radiobutton.test.jsx:31:49)
我是测试新手。任何帮助将非常感激。提前致谢。
根据您组件的代码处理,父元素发生变化。要在测试中模拟此行为,您需要在调用 handleChange
后更新 isChecked
属性。
最多 maintainer's comment 实现的方法是 re-rendering 将相同的元素放入具有不同道具的相同容器中:
test("radiobuttons must use click", () => {
const handleChange = jest.fn();
const { container } = render(
<Radiobutton onClick={handleChange} isChecked={false} label="Dummy Radio" />
);
const radiobtn = getByRole(container, "radio");
fireEvent.click(radiobtn);
expect(handleChange).toHaveBeenCalledTimes(1);
render(<Radiobutton onClick={handleChange} isChecked={true} label="Dummy Radio" />, { container });
expect(radiobtn.getAttribute("aria-checked")).toBe("true");
});
您也可以将 re-rendering 逻辑放在 handleChange.mockImplementation
中,但我相信这会使测试用例更难阅读:
test("radiobuttons must use click", () => {
let isChecked = false;
const handleChange = jest.fn();
const { container } = render(
<Radiobutton onClick={handleChange} isChecked={false} label="Dummy Radio" />
);
handleChange.mockImplementation(() => {
isChecked = !isChecked;
render(<Radiobutton onClick={handleChange} isChecked={isChecked} label="Dummy Radio" />, { container });
});
const radiobtn = getByRole(container, "radio");
fireEvent.click(radiobtn);
expect(handleChange).toHaveBeenCalledTimes(1);
expect(radiobtn.getAttribute("aria-checked")).toBe("true");
});
另一个缺点是 handleChange
逻辑应该在父组件中的某处,所以你宁愿测试你自己的模拟而不是测试你的应用程序。
对我来说,它看起来真的很乱,并且不会为您提供任何额外的价值,因为在现实世界中,它是否在 onClick
之后更新 isChecked
取决于父组件。
所以我建议你把测试用例分成两部分。首先检查点击是否调用 onClick
处理程序。并单独检查 isChecked={true}
是否提供 aria-checked
。也许更好的是让第 3 个检查 isChecked={false}
是否不注入 aria-checked
属性。
test('provides aria-checked if isChecked is truly`, () => {
const { container } = render(<Radiobutton isChecked={true} />);
const radiobtn = getByRole(container, "radio");
expect(radiobtn.getAttribute("aria-checked")).toBe("true");
});
test('does not provide aria-checked if isChecked is falsy`, () => {
const { container } = render(<Radiobutton />);
const radiobtn = getByRole(container, "radio");
expect(radiobtn.getAttribute("aria-checked")).not.toBe("true");
});