Search code examples
javascriptreactjsunit-testingjestjs

Mock DOMMatrix instance in jest React


I'm trying to mock an instance of DOMMatrix that I'm using within a React custom hook, but after different attempts, I'm not succeeding.

I have this instance creation in the hook:

  const matrix = new DOMMatrix(getComputedStyle(element).transform);
  matrix.e += e.movementX;
  matrix.f += e.movementY;

And then I'm trying to mock this since from jest side, DOMMatrix doesn't exist.

If I do it like this:

    jest.spyOn(global, 'DOMMatrix').mockImplementation(() => {
      return {
        a: 1,
        b: 0,
        c: 0,
        d: 1,
        e: 919,
        f: 510,
        is2D: true,
        isIdentity: false,
        m11: 1,
        m12: 0,
        m13: 0,
        m14: 0,
        m21: 0,
        m22: 1,
        m23: 0,
        m24: 0,
        m31: 0,
        m32: 0,
        m33: 1,
        m34: 0,
        m41: 919,
        m42: 510,
        m43: 0,
        m44: 1,
      } as DOMMatrix;
    });

It throws:

Cannot spy the DOMMatrix property because it is not a function; undefined given instead

I also tried doing this:

    jest.mock('DOMMatrix', () => {
      return jest.fn(() => {
        return {
          a: 1,
          b: 0,
          c: 0,
          d: 1,
          e: 919,
          f: 510,
          is2D: true,
          isIdentity: false,
          m11: 1,
          m12: 0,
          m13: 0,
          m14: 0,
          m21: 0,
          m22: 1,
          m23: 0,
          m24: 0,
          m31: 0,
          m32: 0,
          m33: 1,
          m34: 0,
          m41: 919,
          m42: 510,
          m43: 0,
          m44: 1,
        };
      });
    });

I also tried creating a Mock class of DOMMatrix

class MockDOMMatrix {
  e: number;
  f: number;

  constructor(init?: string | number[]) {
    this.e = 0;
    this.f = 0;
  }
}

But nothing so far works.

I would like to have the test, as soon as it creates the new DOMMatrix instance, to return a DOMMatrix-like object like the one above with all the values being set.

Any idea how can I accomplish testing this?


Solution

  • // mock the DOMMatrix
    const matrixMock = jest.fn(() => ({
            e: 0,
            f: 0,
    })) as jest.Mock;
    
    global.DOMMatrix = matrixMock;
    
    // then mock getComputedStyle
    const getComputedStyleMock = jest.fn(() => ({
        transform: 'matrix(1, 0, 0, 1, 0, 0)',
      })) as jest.Mock;
    
    window.getComputedStyle = getComputedStyleMock; 
    
    //then pass element 
      const e = { movementX: 10, movementY: 20 };
      const matrix = new DOMMatrix(getComputedStyle(element).transform);
      matrix.e += e.movementX;
      matrix.f += e.movementY;
    
    expect(matrixMock).toHaveBeenCalled()
    expect(getComputedStyleMock).toHaveBeenCalled() // or with element