Home > other >  Cannot mock document.body.append in React Component
Cannot mock document.body.append in React Component

Time:02-03

Test.tsx

import { useEffect } from 'react';

const Test = () => {
  useEffect(() => {
    const inlineScript = document.createElement('script');
    inlineScript.setAttribute('data-name', 'john');
    inlineScript.innerHTML = 'console.log(123);';
    document.body.append(inlineScript);
  }, []);

  return <div>Test</div>;
};

export default Test;

Test.spec.tsx

import { render } from '@testing-library/react';
import '@testing-library/jest-dom';
import Test from './Test';

Object.defineProperty(document, 'body', {
  value: {
    append: jest.fn()
  },
  writable: true,
  configurable: true
});

describe('<Test /> component test', () => {
  it('should work', () => {
    render(<Test />);
  });
});

It works fine when I remove the Object.defineProperty code. But, I would like to mock the document.body.append to be a jest function. Then, it would give me following error. I tried to mock the appendChild as jest.fn() too but it still failed.

  TypeError: baseElement.appendChild is not a function

  13 | describe('<Test /> component test', () => {
  14 |   it('should work', () => {
> 15 |     render(<Test />);
     |           ^
  16 |   });
  17 | });
  18 |

  at render (node_modules/@testing-library/react/dist/pure.js:87:29)
  at Object.<anonymous> (src/Test.spec.tsx:15:11)`enter code here`

Here is my list of related dependency and devDependency:

"react": "^17.0.2",
"react-dom": "^17.0.2",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.1.2",
"@testing-library/react-hooks": "^8.0.0",
"@testing-library/user-event": "^14.4.3",

CodePudding user response:

You can mock it by creating a mock function and replacing the original append property with the mock function.

e.g.

// Mock function
const mockAppend = jest.fn();
document.body.append = mockAppend;

// Verify that the mock was called correctly
expect(mockAppend).toHaveBeenCalled();

Or if you want to override document.body.append, I think this should work

let originalAppend = document.body.append;

Object.defineProperty(document.body, 'append', {
  get() {
    return (...args) => {
      // Your custom implementation
      console.log('Intercepted document.body.append call');
      originalAppend.apply(document.body, args);
    };
  },
  set(value) {
    originalAppend = value;
  },
});

document.body.append('asd');

  • Related