Reputation: 1036
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
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