React Native Testing Library не находит текст, хотя находится в режиме отладки

Я создаю приложение React Native с помощью TypeScript. Я использую React Native Testing Library для своих тестов компонентов.

У меня есть простой компонент, который отображает два кликабельных значка и текст. Это счетчик, который может увеличивать и уменьшать число.

import React, { PureComponent } from "react";
import { Text, TouchableOpacity, View } from "react-native";
import { Button, Icon } from "react-native-elements";
import { getIconName } from "../../services/core";
import styles from "./styles";

export interface AmountButtonProps {
  amount: number;
  onDecrement: () => void;
  onIncrement: () => void;
  size: "small" | "large";
}

export class AmountButtons extends PureComponent<AmountButtonProps> {
  render() {
    const { amount, onDecrement, onIncrement, size } = this.props;
    const fontSize = size === "small" ? 14 : 26;
    const minusDisabled = amount <= 1;
    const plusDisabled = amount >= 25;
    return (
      <View style={styles.container}>
        <Icon
          containerStyle={[
            styles[size],
            styles.iconContainer,
            styles.minusIcon,
            minusDisabled && styles.disabled
          ]}
          onPress={onDecrement}
          type="ionicon"
          name={getIconName("remove")}
          disabled={minusDisabled}
          disabledStyle={[styles.iconDisabled, styles.disabled]}
          size={fontSize}
          component={TouchableOpacity}
        />
        <View style={[styles[size], styles.amountContainer, styles.iconContainer]}>
          <Text style={{ fontSize }}>{amount}</Text>
        </View>
        <Icon
          containerStyle={[
            styles[size],
            styles.iconContainer,
            styles.addIcon,
            plusDisabled && styles.disabled
          ]}
          onPress={onIncrement}
          type="ionicon"
          name={getIconName("add")}
          disabled={plusDisabled}
          disabledStyle={styles.iconDisabled}
          color="white"
          size={fontSize}
          component={TouchableOpacity}
        />
      </View>
    );
  }
}

export default AmountButtons;

Я хотел написать простой модульный тест, чтобы увидеть, может ли пользователь увидеть сумму. Вот что я написал.

import React from "react";
import { debug, fireEvent, render } from "react-native-testing-library";
import { getIconName } from "../../services/core";
import AmountButtons, { AmountButtonProps } from "./AmountButtons";

const createTestProps = (props?: object): AmountButtonProps => ({
  amount: 1,
  onDecrement: jest.fn(),
  onIncrement: jest.fn(),
  size: "large",
  ...props
});

describe("AmountButtons", () => {
  const props = createTestProps();
  const { getByText, getByProps } = render(<AmountButtons {...props} />);

  it("displays the amount", () => {
    debug(<AmountButtons {...props} />);
    expect(getByText(props.amount.toString())).toBeDefined();
  });
});

Проблема в том, что этот тест выдает ошибку:

● AmountButtons › displays the amount

    Component not found.

      18 |   it("displays the amount", () => {
      19 |     debug(<AmountButtons {...props} />);
    > 20 |     expect(getByText(props.amount.toString())).toBeDefined();
         |            ^
      21 |   });
      22 |
      23 |   it("calls onIncrement", () => {

      at Object.it (app/components/AmountButtons/AmountButtons.test.tsx:20:12)

Хотя в выводе debug Я могу видеть сумму, оказываемую:

...
       }
      >
        <Text
          style={
            Object {
              "fontSize": 26,
            }
          }
        >
          1
        </Text>
      </View>
      <Themed.Icon
...

Что здесь происходит? Почему React Testing Library не видит этот текст? Как я могу проверить это?

2 ответа

Проблема в том, что рендеринг вашего компонента с помощью RTL renderметод не происходит синхронно с тестовым примером. Поэтому, когда блок запускается, вы не можете быть уверены, что эта строка кода

      const { getByText, getByProps } = render(<AmountButtons {...props} />);

бежал и getByText переплетается должным образом.

Чтобы решить эту проблему, вы можете:

  1. переместить рендеринг внутрь it блокировать:
      describe("AmountButtons", () => {
  const props = createTestProps();

  it("displays the amount", () => {
    const { getByText, getByProps } = render(<AmountButtons {...props} />);
    expect(getByText(props.amount.toString())).toBeDefined();
  });
});
  1. переместить рендеринг внутри beforeEach/ before блокировать:
      describe("AmountButtons", () => {
  const props = createTestProps();
  let getByText, getByProps;

  beforeEach(() => {
    ({ getByText, getByProps }) = render(<AmountButtons {...props} />);
  })

  it("displays the amount", () => {
    expect(getByText(props.amount.toString())).toBeDefined();
  });
});

но в этом случае вы должны оставаться в let переменные все getBy помощники.

Другой способ получить текст через Query

const {queryByA11yLabel} = render(<AmountButtons />)expect(queryByA11yLabel("1")).toBeDefined()

Другие вопросы по тегам