Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to spy on window.scrollTo in Jest?

I got a very simple react component with following functionallity:

componentDidMount() {
  window.scrollTo(0, 0)
}

It seems that you cannot do something like

window.scrollTo = jest.fn()

to spy on scrollTo function.

Therefor, I want to know what is the best way to spy on this function and assert that it has been used in my tests.

Thanks

like image 253
Amir Hoseinian Avatar asked Mar 31 '17 19:03

Amir Hoseinian


People also ask

How do you open mock windows in Jest?

To mock the JavaScript window object using Jest, we can use the jest. spyOn method. let windowSpy; beforeEach(() => { windowSpy = jest. spyOn(window, "window", "get"); }); afterEach(() => { windowSpy.

How do I test a Scrollintoview in Jest?

Here is the unit test: it("should scroll to the second block", () => { const scrollToSecondPart = jest. spyOn(LandingPage. prototype, 'scrollToSecondPart'); const wrapper = shallow(<LandingPage />); const instance = wrapper.


Video Answer


4 Answers

I had a similar problem and just assigning the spy didn't work for me.

Eventually I was able to get this working with this code

const spyScrollTo = jest.fn();
Object.defineProperty(global.window, 'scrollTo', { value: spyScrollTo });

Then in Jest I was able to check it like this

const spyScrollTo = jest.fn();

describe('myComponent', () => {
  beforeEach(() => {
    Object.defineProperty(global.window, 'scrollTo', { value: spyScrollTo });
    Object.defineProperty(global.window, 'scrollY', { value: 1 });
    spyScrollTo.mockClear();
  });

  it('calls window.scrollTo', () => {
    myComponent();
    expect(spyScrollTo).toHaveBeenCalledWith({
      top: 1,
      behavior: 'smooth',
    });
  });
});
like image 109
Martin Vich Avatar answered Oct 20 '22 08:10

Martin Vich


In jest the global name space must be accessed by global not window.

global.scrollTo = jest.fn()
like image 33
Andreas Köberle Avatar answered Oct 20 '22 09:10

Andreas Köberle


Dependencies:

"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"jest": "^24.8.0"
"jest-environment-enzyme": "^7.1.1",
"jest-enzyme": "^7.1.1",
"jsdom": "^15.1.1"

window.scrollTo = jest.fn() works fine.

For example:

index.spec.tsx:

import React, { Component } from 'react';

class SomeComponent extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(e) {
    e.preventDefault();
    window.scrollTo(0, 0);
  }

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Click Me!</button>
      </div>
    );
  }
}

export default SomeComponent;

index.spec.tsx, mock window.scrollTo in each test case:

import React from 'react';
import { shallow } from 'enzyme';
import SomeComponent from './';

describe('SomeComponent', () => {
  test('should handle click', () => {
    const wrapper = shallow(<SomeComponent></SomeComponent>);
    const mEvent = { preventDefault: jest.fn() };
    window.scrollTo = jest.fn();
    wrapper.find('button').simulate('click', mEvent);
    expect(mEvent.preventDefault).toBeCalled();
    expect(window.scrollTo).toBeCalledWith(0, 0);
  });
});

jest.config.js:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'enzyme',
  setupFilesAfterEnv: ['jest-enzyme'],
  testEnvironmentOptions: {
    enzymeAdapter: 'react16'
  },
  coverageReporters: ['json', 'text', 'lcov', 'clover']
};

Unit test result:

 PASS  src/stackoverflow/58585527/index.spec.tsx
  SomeComponent
    ✓ should handle click (13ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.932s, estimated 3s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/58585527

like image 32
slideshowp2 Avatar answered Oct 20 '22 08:10

slideshowp2


Like Andreas said, you will need to access scrollTo() via the global namespace. But to spy on it and make assertions, you will need to assign your spy function to a variable. Something like this:

const scrollToSpy = jest.fn();
global.scrollTo = scrollToSpy;
...
expect(scrollToSpy).toHaveBeenCalled();
like image 2
strausd Avatar answered Oct 20 '22 10:10

strausd