Change element size using Jest
Asked Answered
P

3

18

I have following code in my component

var rect = ReactDOM.findDOMNode(this).getBoundingClientRect();

I use d3js and render graph in the component. But when I run test there are any svg tags. I assume that it happens because all rect's fields equals 0.

Here is output for console.log(rect) in browser:

ClientRect {top: 89, right: 808, bottom: 689, left: 8, width: 800…}

and when I run test:

{ bottom: 0, height: 0, left: 0, right: 0, top: 0, width: 0 }

So is there a way to set size of the element?

Pin answered 29/7, 2016 at 10:29 Comment(0)
P
50

My solution is to mock getBoundingClientRect (I'm currently using jest 16.0.1)

describe('Mock `getBoundingClientRect`', () => {
    beforeEach(() => {
        Element.prototype.getBoundingClientRect = jest.fn(() => {
            return {
                width: 120,
                height: 120,
                top: 0,
                left: 0,
                bottom: 0,
                right: 0,
            }
        });
    });
    it('should mock `getBoundingClientRect`', () => {
        const element = document.createElement('span');
        const rect = element.getBoundingClientRect();
        expect(rect.width).toEqual(120);
    });

});
Patman answered 12/10, 2016 at 19:16 Comment(3)
thanks for the answer. Just wondering, where is the "Element" came from?Derayne
@WayneChiu AFAIK, jest uses jsdom to mock DOM classes (such as Element, etc) - github.com/tmpvar/jsdomPatman
N.B. If you have multiple describes that have specific cases for getBoundingClientRect, you'll need to set this mock again for that particular describe, since the global objects prototype is being mutatedBankhead
J
2

Don't forget to put the original value of getBoundingClientRect back, because changing it might affect other tests.

Also, no need to do it in beforeEach: beforeAll will do.

describe("Mock `getBoundingClientRect`", () => {
  let boundingClientRect;

  const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect;

  beforeAll(() => {
    Element.prototype.getBoundingClientRect = () => boundingClientRect;
  });

  afterAll(() => {
    Element.prototype.getBoundingClientRect = originalGetBoundingClientRect;
  });

  it("should mock `getBoundingClientRect`", () => {
    const element = document.createElement("div");
    boundingClientRect = new DOMRect(0, 0, 120, 120);
    const rect = element.getBoundingClientRect();
    expect(rect.width).toEqual(120);
  });
});


I took the idea from this answer

Jasso answered 14/10, 2021 at 16:8 Comment(0)
O
0

The existing answers mock Element.prototype.getBoundingClientRect. This will affect the apparent size of all DOM elements in your tests.

If you know what element you care about in advance, you can mock getBoundingClientRect on a single element. This does not affect the apparent size of other elements. If you want two elements to have different sizes in the same test, this is the way you need to do it.

describe("Mock `getBoundingClientRect` on a single element", () => {
  it("should mock `getBoundingClientRect`", () => {
    const myElement = document.createElement("div");
    myElement.getBoundingClientRect = jest.fn(() => 
      new DOMRect(0, 0, 120, 120);
    );
    const rect = element.getBoundingClientRect();
    expect(rect.width).toEqual(120);
  });
});
Overdrive answered 24/3, 2022 at 20:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.