Тестирование на наличие модального режима с использованием библиотеки тестирования React с помощью findByRole

Я пытаюсь проверить наличие моего модального окна с помощью библиотеки тестирования React с помощью findByRole. Я продолжаю получать сообщение об ошибке: Unable to find role = "dialog", хотя я ясно вижу, что это распечатано в консоли теста.

Вот мой тест:

import React from "react";
import {
    render,
    screen,
    within,
    fireEvent, cleanup, waitFor
} from '@testing-library/react';
import '@testing-library/jest-dom';
import "@testing-library/react/dont-cleanup-after-each";
import Modal from 'react-modal';

import PackagerModal from './PackagerModal';

const mockedEmptyFn = jest.fn();

const mockBaseProps = {
    openPackager: true,
    setOpenPackager: mockedEmptyFn,
    activeOrder: {
        // ... // lots of irrelevant properties here
        ]
    },
    setOrders: mockedEmptyFn,
    customStyles: {
        content: {
            backgroundColor: "var(--color-primary)",
            border: "1px solid #ccc",
            boxShadow: "-2rem 2rem 2rem rgba(0, 0, 0, 0.5)",
            color: "rgba(var(--RGB-text), 0.8)",
            filter: "blur(0)",
            fontSize: "1.1em",
            fontWeight: "bold",
            margin: "50px auto",
            opacity: 1,
            outline: 0,
            position: "relative",
            visibility: "visible",
            width: "500px"
        },
        overlay: {
            backgroundColor: "rgba(255, 255, 255, 0.9)"
        }
    },
    readOnly: false,
    setReadOnly: mockedEmptyFn,
};

Modal.setAppElement('body');


const Component = (props) =>    <PackagerModal {...mockBaseProps} {...props} />

describe('Packager Modal tests with editable inputs', () => {
    afterAll(() => {
        cleanup();
    });


    test('Should show packager modal', async () => {
        render(
            <Component/>
        );
        // screen.debug();
        const modalWindow = await screen.findByRole('dialog');
        expect(modalWindow).toBeInTheDocument();
    });
});

И вот мой модальный:

import ReactModal from 'react-modal';
import React, { useEffect, useRef, useState } from 'react';
import CloseButton from './CloseButton';
import PropTypes from 'prop-types';

const PackagerModal = (props) => {
    const {
        openPackager,
        setOpenPackager,
        activeOrder,
        setOrders,
        customStyles,
        readOnly,
        setReadOnly,
    } = props;

    const cleanUpModal = () => {
        setReadOnly(false);
        setUserInput(initialState);
    };

    return (
        <ReactModal
            isOpen = {openPackager}
            style = {customStyles}
            className = {'order-details-modal'}
            closeTimeoutMS = {1000}
            onAfterClose = {cleanUpModal}
        >
            <CloseButton setOpenModal = {setOpenPackager} />
            <h2 className = {'title'}>Packager Order Checklist</h2>
        </ReactModal>
    );
};

PackagerModal.propTypes = {
    openPackager: PropTypes.bool.isRequired,
    setOpenPackager: PropTypes.func.isRequired,
    customStyles: PropTypes.object.isRequired,
    activeOrder: PropTypes.object.isRequired,
    setOrders: PropTypes.func.isRequired,
    readOnly: PropTypes.bool.isRequired,
    setReadOnly: PropTypes.func.isRequired,
};

export default PackagerModal;

И, наконец, вот часть вывода, который я вижу в консоли из теста:

 ● Packager Modal tests with editable inputs › Should show packager modal

    Unable to find role = "dialog"

    Ignored nodes: comments, script, style
    <body
      aria-hidden = "true"
      class = "ReactModal__Body--open"
    >
      <div
        data-react-modal-body-trap = ""
        style = "position: absolute; opacity: 0;"
        tabindex = "0"
      />
      <div />
      <div
        data-react-modal-body-trap = ""
        style = "position: absolute; opacity: 0;"
        tabindex = "0"
      />
      <div
        class = "ReactModalPortal"
      >
        <div
          class = "ReactModal__Overlay ReactModal__Overlay--after-open"
          style = "position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px; background-color: rgba(255, 255, 255, 0.9);"
        >
          <div
            aria-modal = "true"
            class = "ReactModal__Content ReactModal__Content--after-open order-details-modal"
            role = "dialog"
            style = "border: 1px solid #ccc; box-shadow: -2rem 2rem 2rem rgba(0, 0, 0, 0.5); filter: blur(0); font-size: 1.1em; font-weight: bold; margin: 50px auto; opacity: 1; outline: 0; position: relative; visibility: visible; width: 500px;"
            tabindex = "-1"
          >
          ...

Похоже, тело вашего теста скрыто aria-hidden = "true" (not sure why as I'm not familiar with the package). Вы пробовали запрашивать свой элемент с опцией { hidden: true }? const myModal = getByRole('dialog', { hidden: true }). Дай мне знать, если это работает!

Avi 02.01.2023 11:45

Это сработало! Я посмотрю, как я смоделирую модальное окно, и посмотрю, не делаю ли я что-то не так, чтобы вызвать это. Спасибо!

dmikester1 02.01.2023 23:27

Не стесняйтесь добавлять это в качестве ответа, и я приму это.

dmikester1 02.01.2023 23:28

Круто, рад, что смог помочь. Я разместил свой комментарий как ответ :)

Avi 02.01.2023 23:37
Простое руководство по тестированию взаимодействия с пользователем с помощью библиотеки тестирования React
Простое руководство по тестированию взаимодействия с пользователем с помощью библиотеки тестирования React
В предыдущем посте я показал вам на примерах, как писать базовые тесты в React. Важнейшей частью пользовательского интерфейса приложений является...
3
4
85
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Похоже, тело вашего теста скрыто — aria-hidden = "true" (не знаю, почему, поскольку я не знаком с пакетом). Библиотека тестирования React в значительной степени ориентирована на доступность, поэтому по умолчанию она игнорирует любые недоступные элементы.

Попробуйте запросить свой элемент с опцией { hidden: true }

const myModal = getByRole('dialog', { hidden: true });

Это действительно не лучшее решение, в идеале вы не хотите, чтобы модальное окно появлялось внутри элемента с aria-hidden = "true". Я сталкиваюсь с той же проблемой, когда вам нужно, чтобы эта метка aria была установлена ​​​​на что-то еще, кроме тела

Richard Hpa 25.01.2023 05:43

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

Проблема в том, что вы говорите Modal.setAppElement('body'); в своем тестовом файле. Если вы читаете документы для модального реагирования, они говорят, что вам нужно сообщить модальному модулю, где находится содержимое вашего приложения, чтобы, когда модальное окно было открыто, все в этом элементе имело aria-hidden: true, чтобы программы чтения с экрана не улавливали ни одного из другой контент, кроме того, что находится внутри модального окна, поскольку он отображается через портал, добавленный в конец вашего тела. Таким образом, вы устанавливаете setAppElement в body, что делает все, что внутри скрыто для программ чтения с экрана, включая ваше модальное окно.

Итак, чтобы решить эту проблему, вам нужно установить это на что-то другое, лично у меня есть собственная функция рендеринга, в которой есть такие вещи, как провайдеры, поэтому я просто добавил туда новый div. Но в вашем случае вы можете добавить его в свой Component

const Component = (props) => <div id = "root"><PackagerModal {...mockBaseProps} {...props} /></div>

Затем вы можете изменить строку setAppElement на

Modal.setAppElement('root');

Это будет означать, что вам не нужно добавлять опцию { hidden: true } к вашим запросам. Вам также не нужно использовать findBy, поскольку в вашем тесте пока не происходит никаких асинхронных изменений.

    test('Should show packager modal', () => {
        render(<Component/>);
        const modalWindow = screen.getByRole('dialog');
        expect(modalWindow).toBeInTheDocument();
    });

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