如何检查要使用反应组件参数调用的 ReactDOM.render 方法?

How to check ReactDOM.render method to be called with a react component argument?

代码在这里:

index.tsx:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

export function Loading(props) {
  return <div {...props}>loading...</div>;
}

export class MyComponent extends Component {
  static show() {
    const container = document.createElement('div');
    container.classList.add('loading-container');
    document.body.appendChild(container);
    ReactDOM.render(<Loading className="loading" />, container);
  }
  render() {
    return <div>my component</div>;
  }
}

index.test.tsx:

import React from 'react';
import { Loading, MyComponent } from './';
import ReactDOM from 'react-dom';

describe('MyComponent', () => {
  it('should pass', () => {
    const renderSpy = jest.spyOn(ReactDOM, 'render');
    MyComponent.show();
    const loadingContainer = document.body.querySelector('.loading-container');
    // 1. failed
    // expect(renderSpy).toBeCalledWith(expect.any(Loading), loadingContainer);

    // 2. TS type error
    // expect(renderSpy).toBeCalledWith(Loading, loadingContainer);

    // 3. TS type error
    // expect(renderSpy).toBeCalledWith(<Loading />, loadingContainer);
  });
});

我已经尝试了三种方法来断言 renderSpy 将与 Loading 组件一起调用。但是 none 他们的工作。

我该如何解决?

我认为你只是缺少 <Loading /> 中的 className="loading":

import { Loading, MyComponent } from "./index";
import ReactDOM from "react-dom";

describe("MyComponent", () => {
  it("spying on ReactDOM", () => {
    const spy = jest.spyOn(ReactDOM, "render");
    MyComponent.show();

    expect(spy).toHaveBeenCalledWith(
      <Loading className="loading" />,
      document.body.querySelector(".loading-container")
    );
  });
});

或者,您可以模拟 ReactDOM 而不是监视它:

import { Loading, MyComponent } from "./index";
import ReactDOM from "react-dom";

jest.mock("react-dom", () => ({
  __esModule: true,
  __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {
    Events: [],
  },
  createPortal: jest.fn(),
  findDOMNode: jest.fn(),
  flushSync: jest.fn(),
  hydrate: jest.fn(),
  render: jest.fn(),
  unmountComponentAtNode: jest.fn(),
  unstable_batchedUpdates: jest.fn(),
  unstable_createPortal: jest.fn(),
  unstable_renderSubtreeIntoContainer: jest.fn(),
  version: "17.0.1",
}));

describe("MyComponent", () => {
  it("mocking ReactDOM", () => {
    MyComponent.show();

    expect(ReactDOM.render).toHaveBeenCalledWith(
      <Loading className="loading" />,
      document.body.querySelector(".loading-container")
    );
  });
});