是否可以等待组件渲染?React 测试库/Jest

Pra*_*ra 19 jestjs react-native react-testing-library

我有一个组件。它有一个按钮。按下按钮后,我使用 setState 函数更改按钮文本(颜色)的样式。当我测试更改的组件时,测试失败,因为更改是异步发生的。我想做一些这里给出的事情(https://testing-library.com/docs/dom-testing-library/api-async/

const button = screen.getByRole('button', { name: 'Click Me' })
fireEvent.click(button)
await screen.findByText('Clicked once')
fireEvent.click(button)
await screen.findByText('Clicked twice')
Run Code Online (Sandbox Code Playgroud)

但不是等待文本更改。我想等待文字颜色改变。谢谢

这是我的按钮的代码

<Button onPress = {() => {this.setState({state : 1});}}>
<Text style = {style}>Button Text</Text>
</Button>
Run Code Online (Sandbox Code Playgroud)

所以当这个按钮被按下时。state 设置为 1。并且在 render 中:

if(this.state.state === 1) style = style1
else style = style2;
Run Code Online (Sandbox Code Playgroud)

但从日志中可以看出,render是在测试检查样式后调用的。那么如何等待渲染完成后再检查字体颜色是否已更改?

这是测试代码

test('The button text style changes after press', () => {
  const {getByText} = render(<Component/>);
  fireEvent.press(getByText('button'));
  expect(getByText('button')).toHaveStyle({
    color : '#ffffff'
  });
})
Run Code Online (Sandbox Code Playgroud)

ggo*_*len 22

看起来您有一个自定义按钮,而不是本机按钮。我猜你的组件是这样的:

import React from "react";
import {Text, TouchableOpacity} from "react-native";

const Button = ({pressHandler, children}) => (
  <TouchableOpacity onPress={pressHandler}>
    {children}
  </TouchableOpacity>
);

const ColorChangingButton = ({text}) => {
  const [color, setColor] = React.useState("red");
  const toggleColor = () => setTimeout(() => 
    setColor(color === "green" ? "red" : "green"), 1000
  );
  return (
    <Button pressHandler={toggleColor}>
      <Text style={{color}}>{text}</Text>
    </Button>
  );
};
export default ColorChangingButton;
Run Code Online (Sandbox Code Playgroud)

如果是这样,您可以按照此处waitFor所述进行测试:

import React from "react";
import {
  fireEvent, 
  render,
  waitFor,
} from "@testing-library/react-native";
import ColorChangingButton from "../src/components/ColorChangingButton";

it("should change the button's text color", async () => {
  const text = "foobar";
  const {getByText} = render(<ColorChangingButton text={text} />);
  fireEvent.press(getByText(text));
  await waitFor(() => {
    expect(getByText(text)).toHaveStyle({color: "green"});
  });
});
Run Code Online (Sandbox Code Playgroud)

对于具有用于更改颜色的严格语义且不接受子元素的本机按钮,请改为使用title="foo",调用debug()显示它扩展到一些嵌套元素。您可以使用

const text = within(getByRole("button")).getByText(/./);
expect(text).toHaveStyle({color: "green"});
Run Code Online (Sandbox Code Playgroud)

在回调中waitFor浸入按钮的文本子级并等待它具有所需的颜色。

我在这篇文章中使用了相同的包/版本,如React 测试库:测试元素是否已映射/渲染中所示。

  • @DarkTrick 感谢您的反馈,但您的断言是模糊且不可操作的。为什么它不“扩展”?为什么它脆弱?为什么它不是解决问题的通用方法?请用您自己的答案进行澄清,或者让我知道我可以具体做什么来改进这个答案。我将查看文档和肯特的文章,并尝试找出问题所在。确实,像这样通过文本查询和测试 CSS 属性并不是好的做法,但答案的关键点是“waitFor”而不是查询。这是一个人为的、最小的例子来说明一点。 (3认同)
  • 感谢您的澄清,但我仍然不同意您提出的比“waitFor”更好的解决方案。 (2认同)