Hithesh kumar
Hithesh kumar

Reputation: 1036

How do I mock document.getElementsByClassName() in jest and react-testing-library for the code-coverage?

How can we mock document.getElementsByClassNames() in jest/ react-testing-library , since these part of the code is not been covered in code-coverage

import { useEffect } from "react";
import "./styles.css";
const numbers = [1, 2, 3, 4, 5, 6];
export default function App() {

  useEffect(() => {
    const headings = [...document.getElementsByClassName("heading")];

    if(!!headings.length){
      console.log("DO SOMETHING !!")
    }
    headings?.map((heading) => {
      return heading.setAttribute("id", "header-toggle");
    });
    
  }, []);

  return (
    <div className="App">
      {numbers?.map((num) => {
        return <h1 className="heading">{num}</h1>;
      })}
    </div>
  );
}

App.test.js

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

afterEach(cleanup);

  it('render App', () => {

document.getElementsByClassName() = jest.fn().mockImplementation([{setAttribute:jest.fn()}])

    const { container } = render(<App/>); 
    expect(container).toBeInTheDocument()
   });

Upvotes: 0

Views: 2915

Answers (1)

Lin Du
Lin Du

Reputation: 102447

Don't mock document.getElementsByClassName() and test the implementation detail. Instead, test the component's behavior such as what the component renders.

You can assert if the id HTML attribute is set correctly or not.

E.g.

App.tsx:

import React from 'react';
import { useEffect } from 'react';

const numbers = [1, 2, 3, 4, 5, 6];
export default function App() {
  useEffect(() => {
    const headings = [...document.getElementsByClassName('heading')];

    if (!!headings.length) {
      console.log('DO SOMETHING !!');
    }
    headings.map((heading, i) => {
      return heading.setAttribute('id', `header-toggle-${i}`);
    });
  }, []);

  return (
    <div className="App">
      {numbers.map((num) => {
        return <h1 key={num} className="heading">{num}</h1>;
      })}
    </div>
  );
}

App.test.tsx:

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

describe('App', () => {
  it('render App', () => {
    const { container } = render(<App />);
    expect(container).toBeInTheDocument();
  });

  it('render App with numbers', () => {
    const { getByText } = render(<App />);
    const numbers = [1, 2, 3, 4, 5, 6];
    numbers.forEach((n, i) => {
      expect(getByText(`${n}`)).toBeInTheDocument();
      expect(getByText(`${n}`).id).toEqual(`header-toggle-${i}`);
    });
  });
});

Test result:

 PASS  stackoverflow/72626153/App.test.tsx (9.755 s)
  App
    ✓ render App (40 ms)
    ✓ render App with numbers (21 ms)

  console.log
    DO SOMETHING !!

      at stackoverflow/72626153/App.tsx:10:15

  console.log
    DO SOMETHING !!

      at stackoverflow/72626153/App.tsx:10:15

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |       50 |     100 |     100 |                   
 App.tsx  |     100 |       50 |     100 |     100 | 9                 
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        10.256 s, estimated 11 s
Ran all test suites related to changed files

Upvotes: 1

Related Questions