Akash
Akash

Reputation: 834

Test ClientPortal in Next.JS using Jest

I'm using NextJS and I'm trying to test the ClientPortal component. I'm using Jest and React Testing Library for testing.

Here's the ClientPortal component:

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;
}

How can this be tested using Jest?

Upvotes: 0

Views: 432

Answers (1)

Lin Du
Lin Du

Reputation: 102207

First, make sure the testEnvironment configuration is jsdom. For jestjs v26, it's jsdom by default. For jestjs v27, follow this guide to setup the testEnvironment configuration.

The test method is very straightforward. Create a DOM container to store the portal. Query the DOM element and assert whether it exists.

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 />`);
  });
});

test result:

 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

package versions:

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

Upvotes: 1

Related Questions