【问题标题】:Test ClientPortal in Next.JS using Jest使用 Jest 在 Next.JS 中测试 ClientPortal
【发布时间】:2021-10-13 05:11:56
【问题描述】:

我正在使用 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 进行测试?

【问题讨论】:

    标签: javascript reactjs jestjs next.js


    【解决方案1】:

    首先,确保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",
    

    【讨论】:

    • 非常感谢@slideshowp2,它就像一个魅力!你能解释一下expect(container).toMatchInlineSnapshot("&lt;main /&gt;"); 的作用吗?
    • @Akash 断言ClientPortal 的容器为空。如果容器包含其他组件,它可以匹配其他组件的渲染结构。但是对于这个简单的示例,您可以删除此断言。
    猜你喜欢
    • 2020-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    相关资源
    最近更新 更多