测试一个 create-react-app index.js 文件

Test a create-react-app index.js file

我希望 100% 覆盖我的项目。

为此,我需要测试我的 index.js 文件,该文件非常基础:

index.js

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(<App/>, document.getElementById('root'));

我找不到如何测试它。 创建函数时,例如 :

index.js

const index = (div) => {
  ReactDOM.render(<App />, div || document.getElementById('root'));
};

然后测试它:

index.test.js

it('renders without crashing', () => {
  const div = document.createElement('div');
  index(div);
});

导入时出现错误 index: 不变违规:_registerComponent(...):目标容器不是 DOM 元素。

PS:

请注意,我已经进行了以下测试,运行良好:

App.test.jsx

it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App/>, div);
});

主要问题是你想在那里测试什么。如果您想测试 您的 代码是否正常工作,请编写一个监视 ReactDOM.render 并模拟 document.getElementById('root') 的单元测试。因为这就是您的所有代码,使用我们的 App 组件和特定的 div.

调用 ReactDOM.render
import ReactDOM from 'react-dom';
...
jest.mock('react-dom', ()=> ({render: jest.fn()}))


it('renders without crashing', () => {

  const div = document.createElement('div');
  ReactDOM.render(<App/>, div);
  global.document.getElementById = (id) => id ==='root' && div
  expect(ReactDOM.render).toHaveBeenCalledWith(...)
});

如果您想测试该应用程序是否真的在您的页面中启动,您应该使用 Selenium 或 Nightwatch.js

编写集成测试

要获得 100% 的覆盖率,您也可以忽略此文件,方法是将其添加到您的 jest 设置中的 coveragePathIgnorePatterns

如果您的目标是项目的 100% 覆盖率并且 index.js 文件中的代码很简单,那么从覆盖率报告中排除该文件可能是一个不错的选择,正如 Andreas Köberle 指出的那样在他的回答中。

Create-react-app目前在Jest配置中只支持这四个key(source):

collectCoverageFrom
coverageReporters
coverageThreshold
snapshotSerializers

这就是为什么

coveragePathIgnorePatterns": ["src/index.js"]

不行。

将以下代码添加到 package.json 文件的最外层范围:

"jest": {
  "collectCoverageFrom": [
    "src/**/*.{js,jsx}",
    "!src/index.js"
  ]
}

在下图中,您可以看到测试 运行 的输出,此代码已添加到使用 create-react-app v1.4.3 创建的初始应用程序的 package.json 中。请注意,index.js 文件不再出现在报告中,也不会影响覆盖百分比。

我找到了一个 article online 解释这种编写测试的方式...

// index.test.js
import Index from './index.js';

it('renders without crashing', () => {
  expect(JSON.stringify(
    Object.assign({}, Index, { _reactInternalInstance: 'censored' })
  )).toMatchSnapshot();
});

现在相应地更改 index.js 文件:

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

export default ReactDOM.render(
  <App />,
  document.getElementById('root') || document.createElement('div')
);

这就是我测试的方式index.js

index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));

index.test.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

jest.mock("react-dom", () => ({ render: jest.fn() }));

describe("Application root", () => {
  it("should render without crashing", () => {
    const div = document.createElement("div");
    div.id = "root";
    document.body.appendChild(div);
    require("./index.js");
    expect(ReactDOM.render).toHaveBeenCalledWith(<App />, div);
  });
});

上进行扩展,以下是跳过 TypeScript 项目的这些琐碎文件的方法:

  1. 编辑package.json
  2. 在根级别添加以下代码段

    {
      ...rest of existing props,
      "jest": {
        "collectCoverageFrom": [
          "src/**/*.{ts,tsx}",
          "!src/serviceWorker.ts",
          "!src/index.tsx"
        ]
      }
    }
    
  3. 保存并重新运行覆盖

现在覆盖率应该更高了。

这是我所做的,看起来效果非常完美(100% 覆盖率,应用程序不会中断):

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

import './index.css';

export const ReactStrictMode = <React.StrictMode>
  <App />
</React.StrictMode>

export const rootElement = document.getElementById('root')

ReactDOM.render(
  ReactStrictMode,
  rootElement
);

然后在 index.spec.js:

// src/index.spec.js
/* eslint-env jest */
import React from 'react'
import ReactDOM from 'react-dom'
import { ReactStrictMode, rootElement } from './index'

jest.mock('react-dom', () => ({ render: jest.fn() }))

describe('index.js', () => {
  it('renders without crashing', () => {
    ReactDOM.render(ReactStrictMode, rootElement)
    expect(ReactDOM.render).toHaveBeenCalledWith(ReactStrictMode, rootElement)
  })
})

Added a couple of more test cases. Any feedback would be appreciated...

import React from "react";
import { render, cleanup } from "@testing-library/react";
import ReactDOM from "react-dom";
import App from "./App";

afterEach(cleanup);

// jest.mock will mock all the function using jest.fn() that is present inside the react-dom library
jest.mock("react-dom");

describe("Testing Application Root", () => {
  it("should render without crashing", () => {
      const div = document.createElement("div");
      div.id = "root";
      document.body.appendChild(div);
      require("./index");
      expect(ReactDOM.render).toHaveBeenCalledWith(<App />, div);
  });
    
  it("should render the app inside div which has root id", () => {
    expect(global.document.getElementById("root")).toBeDefined();
  });
  
  it("should render App component", () => {
    expect(App).toBeDefined();
  });
});