web-dev-qa-db-ja.com

react-testing-libraryでマテリアルUIポッパーをテストしているときに、 `TypeError:document.createRange is not a function`エラーを修正する方法

私はmaterial-ui TextFieldを持っています。フォーカスがあるとPopperが開きます。私はreact-testing-libraryを使用してこの動作をテストしようとしています。

コンポーネント

import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import Grow from '@material-ui/core/Grow';
import Paper from '@material-ui/core/Paper';
import Popper from '@material-ui/core/Popper';
import TextField from '@material-ui/core/TextField';
import React from 'react';
import { ItemType } from './types';

export type TextFieldDropDownProps = {
    items: ItemType,
};

export function TextFieldDropDown(props: TextFieldDropDownProps) {
    const [searchTerm, setSearchTerm] = React.useState('');
    const [anchorEl, setAnchorEl] = React.useState(null);

    const handleSearchTermChange = (event: any) => {
        setSearchTerm(event.target.value);
    };

    const onFoucs = (event: any) => {
        setAnchorEl(event.currentTarget);
    };

    const handleClose = (event: any) => {
        setAnchorEl(null);
    };

    const popperTrans = ({ TransitionProps }: any) => {
        return (
          <Grow
            {...TransitionProps}
            style={{ transformOrigin: '0 0 0' }}
          >
            <Paper>
              <ul />
            </Paper>
          </Grow>
        );
    };

    const open = Boolean(anchorEl);
    return (
        <ClickAwayListener onClickAway={handleClose}>
            <div>
                <TextField
                    onChange={handleSearchTermChange}
                    onFocus={onFoucs}
                    value={searchTerm}
                    label='Search'
                />
                <Popper
                    open={open}
                    anchorEl={anchorEl}
                    transition={true}
                    disablePortal={true}
                    placement='bottom-start'
                    style={{zIndex: 999, minWidth: '100%'}}
                >
                    {popperTrans}
                </Popper>
            </div>
        </ClickAwayListener>
    );
}

テスト

import { fireEvent, render, wait } from '@testing-library/react';
import { getTestData } from 'test-data';
import React from 'react';
import { TextFieldDropDown } from './TextFieldDropDown';

test('that on focus on input field, the component shows a dropdown', async () => {
    // Set up test data
    const items: any = getTestData();

    // Render component
    const props = { items };
    const { getByRole, queryByRole } = render(<TextFieldDropDown {...props} />, {});
    await wait();

    expect(queryByRole('list')).toBeNull();

    // Fire event
    const placeSelectInputField = getByRole('textbox') as HTMLInputElement;
    fireEvent.focus(placeSelectInputField);

    // Verify that dropdown is shown
    expect(queryByRole('list')).toBeInTheDocument();

});

テストを実行すると、次のエラーが表示されます-TypeError: document.createRange is not a function

      The above error occurred in the <div> component:
          in div (created by ForwardRef(Portal))
          in ForwardRef(Portal) (created by ForwardRef(Popper))
          in ForwardRef(Popper) (created by TextFieldDropDown)
          in div (created by ForwardRef(ClickAwayListener))
          in ForwardRef(ClickAwayListener) (created by TextFieldDropDown)
          in TextFieldDropDown
          in Provider (created by AllTheProviders)
          in AllTheProviders

      Consider adding an error boundary to your tree to customize error handling behavior.

      The above error occurred in the <ForwardRef(Popper)> component:
          in ForwardRef(Popper) (created by TextFieldDropDown)
          in div (created by ForwardRef(ClickAwayListener))
          in ForwardRef(ClickAwayListener) (created by TextFieldDropDown)
          in TextFieldDropDown
          in Provider (created by AllTheProviders)
          in AllTheProviders

      Consider adding an error boundary to your tree to customize error handling behavior.


  ● that on focus on input field, the component shows a dropdown

    TypeError: document.createRange is not a function

      46 |     // Fire event
      47 |     const TextFieldComponent = getByRole('textbox') as HTMLInputElement;
    > 48 |     fireEvent.focus(TextFieldComponent);
         |               ^
      49 |
      50 |     // Verify that dropdown is shown
      51 |     expect(queryByRole('list')).toBeInTheDocument();

これを機能させるにはどうすればよいですか?

3
Sruthi

問題は、呼び出すためのDOM APIがないときにdocument.createRange関数を呼び出すPopperJSの基本的な実装にあります。解決策は、PopperJSをモックすることです。

// __mocks__/popper.js.js

import PopperJs from 'popper.js';

export default class Popper {
    constructor() {
        this.placements = PopperJs.placements;

        return {
            update: () => {},
            destroy: () => {},
            scheduleUpdate: () => {}
        };
    }
}

jestは/__mocks__ディレクトリ内のモックを自動的に選択するため、このファイルを追加するだけで問題が解決するはずです

1
C Sinclair