使用 Jest 在 Next.JS 中测试 ClientPortal

Test ClientPortal in Next.JS using Jest

我正在使用 NextJS,我正在尝试测试 ClientPortal 组件。我正在使用 Jest 和 React 测试库进行测试。

这是 ClientPortal 组件:

import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";

export default function ClientPortal({ children, selector }) {
  const ref = useRef();
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    ref.current = document.querySelector(selector);

    setMounted(true);
  }, [selector]);

  return mounted ? createPortal(children, ref.current) : null;
}

如何使用 Jest 对其进行测试?

首先,确保 testEnvironment 配置为 jsdom。对于 jestjs v26,默认为 jsdom。对于 jestjs v27,请按照 guide 设置 testEnvironment 配置。

测试方法非常简单。创建一个 DOM 容器来存储门户。查询 DOM 元素并断言它是否存在。

index.jsx:

import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';

export default function ClientPortal({ children, selector }) {
  const ref = useRef();
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    ref.current = document.querySelector(selector);

    setMounted(true);
  }, [selector]);

  return mounted ? createPortal(children, ref.current) : null;
}

index.test.jsx:

import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import ClientPortal from './';

function TestChild() {
  return <div>child</div>;
}
describe('69550058', () => {
  test('should pass', () => {
    const main = document.createElement('main');
    const portalContainer = document.createElement('div');
    portalContainer.id = 'portal-container';
    document.body.appendChild(portalContainer);
    const { container } = render(
      <ClientPortal selector={'#portal-container'}>
        <TestChild />
      </ClientPortal>,
      { container: document.body.appendChild(main) }
    );
    expect(screen.getByText(/child/)).toBeInTheDocument();
    expect(portalContainer.innerHTML).toEqual('<div>child</div>');
    expect(container).toMatchInlineSnapshot(`<main />`);
  });
});

测试结果:

 PASS  examples/69550058/index.test.jsx (8.941 s)
  69550058
    ✓ should pass (33 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 index.jsx |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   1 passed, 1 total
Time:        9.624 s, estimated 11 s

包版本:

"jest": "^26.6.3",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"@testing-library/react": "^11.2.2",