Jest 快照不适用于某些 Semantic-UI-React 组件

Jest snapshots not working with some Semantic-UI-React components

当我尝试创建包含 Semantic-UI-React 'Modal' 组件的 React 组件 'LoadingModal' 的 Jest 快照时,快照最终为空,.snap 文件中有 'null' .我已经测试了拍摄其他语义-UI-React 组件的快照,例如 'Button'、'Dropdown' 和 'Sidebar',它们使用正确的 html 进行渲染和快照输出就好了。

这看起来不像是 Jest 快照本身的问题,而是 react-test-renderer 它的 .create() 和 .toJson() 方法返回 null。

为什么 react-test-renderer 会正确地渲染一些语义-UI-React 组件,而不是像 'Modal' 这样的其他组件? react-test-render 似乎是序列化 React 组件以进行快照的标准方法,并且是 Jest's snapshotting docs.

中使用的方法

我正在使用 react@16.2.0、jest@22.1.4、react-test-renderer@16.2.0 和 semantic-ui-react@0.77.1


更新:

似乎出于某种原因,Semantic-UI-React Modal 组件在未在浏览器内呈现时特别设置为呈现 null。

有关详细信息,请参阅 github 存储库中我的 issue


LoadingModal.test.js

import React from 'react'
import renderer from 'react-test-renderer'
import LoadingModal from './LoadingModal'

test('should render correctly', () => {
    const tree = renderer.create(
        <LoadingModal/>
    ).toJSON()
    expect(tree).toMatchSnapshot()
})

LoadingModal.test.js.snap

// Jest Snapshot v1

exports[`should render correctly 1`] = `null`;

LoadingModal.js

import React from 'react';
import PropTypes from 'prop-types'

import { Modal, Dimmer, Loader} from 'semantic-ui-react'

class LoadingModal extends React.Component {
    static propTypes = {
        header: PropTypes.func,
        content: PropTypes.func,
        loading: PropTypes.bool,
        onClose: PropTypes.func,
        size: PropTypes.string,
        height: PropTypes.string
    };
    static defaultProps = {
        size: 'tiny',
        height: '500px'
    }

    _render_content = (content) => {
        if (this.props.loading === true) {
            return <Dimmer active inverted><Loader active size='large' inline='centered'/></Dimmer>
        } else {
            return content && content()
        }
    }

    render () {
        const {
          header,
          content,
          loading,
          onClose,
          size,
          height
        } = this.props;

        return (
            <Modal size={size} dimmer='blurring' open={true} onClose={onClose}>
              {header && header()}
              <Modal.Content>
                <div style={{height: height}}>
                    {this._render_content(content)}
                </div>
              </Modal.Content>
            </Modal>
        );
    }
}

export default LoadingModal

如您所述,这可能是因为您在浏览器外部进行测试。但是,这可以使用 jsdom.

修复

我假设你有 jsdom 设置,因为 react-test-renderer 需要 jsdom 或其他一些模拟 windowdocument 的设置。

根据我的假设,Semantic-UI-React 的模态仍会呈现 null。这是因为它使用了 Portal component and renders the modal on the document.body node.

Semantic-UI-React的解决方案

看看如何 Semantic-UI-React tests the modal:

it('renders child components', () => {
  const child = <div data-child />
  wrapperMount(<Modal open>{child}</Modal>)

  document
    .querySelector('.ui.modal')
    .querySelector('[data-child]')
    .should.not.equal(null, 'Modal did not render the child component.')
})

他们必须使用 DOM 和 css 选择器来测试,因为 react-test-rendererenzyme 无法针对 document.body.[=30 进行测试=]

我的解决方案

我找到了另一个允许使用 react-test-rendererenzyme 的解决方案,这意味着您可以进行快照!我使用 jest.mock 模拟 Portal 组件作为渲染其子组件的组件,而不是渲染到 document.body 节点上。

import React from 'react';
import renderer from 'react-test-renderer';
import Portal from 'semantic-ui-react/dist/commonjs/addons/Portal/Portal';
import { Modal } from 'semantic-ui-react';

jest.mock('semantic-ui-react/dist/commonjs/addons/Portal/Portal', () => ({ children }) => children);

describe('<Modal />', () => {
  test('snapshot', () => {
    const tree == renderer.create(<Modal open>Inside my modal!</Modal>).toJSON();

    expect(tree).toMatchSnapshot();
  });
});

快照如下所示:

exports[`<CaptureModal /> snapshot 1`] = `
<div
  className="ui modal transition visible active"
  style={
    Object {
      "marginTop": undefined,
    }
  }
>
  Inside my modal!
</div>
`;