Jest spy on component's property method
Asked Answered
T

2

11

I'm trying to test if an event has been added in the init method called by componentDidMount, but that event is going to be added only if a component's attribute is set in "true" so I want to spy on the addEventHandler method and call the "toBeCalledWith('eventName')" so I have something like this:

export interface IMyComponentProps{
    flag?: boolean;
}

export class MyComponent extends Component<IMyComponentProps> {
    private myProperty: HTMLElement;

    public componentDidMount() {
        this.init();
    }

    private init() {
        if (this.props.flag) {
            this.myProperty.addEventListener("event", arg2, arg3);
        }
    }
}

Then I have my test looking like this:

test("Test 1", () => {
   const spyInit = jest.spyOn(MyComponent.prototype, "init");
   wrapper = mount(
      <MyComponent />
   );

   expect(spyInit).toBeCalled();
})

but the test above does not cover if the addEventListener is called or not so I'm trying different ways like following, without success:

const spyAddListener = jest.spyOn(MyComponent.prototype, "myProperty.addEventHandler"); 
const spyAddListener = jest.spyOn(MyComponent.instance().myProperty, "addEventHandler"); 
const spyAddListener = jest.spyOn(MyComponent.prototype.myProperty, "addEventHandler");

any suggestion?

Thermodynamic answered 17/3, 2020 at 0:43 Comment(0)
M
5

You need to pass the flag props to the component. E.g.

index.ts:

import { Component } from 'react';

export interface IMyComponentProps {
  flag?: boolean;
}

export class MyComponent extends Component<IMyComponentProps> {
  private myProperty!: HTMLElement;

  public componentDidMount() {
    this.init();
  }
  public render() {
    return null;
  }

  private init() {
    if (this.props.flag) {
      this.myProperty.addEventListener('event', () => null, false);
    }
  }
}

index.test.tsx:

import { MyComponent } from './';
import { mount } from 'enzyme';
import React from 'react';

describe('60714899', () => {
  it('should add event listener', () => {
    const spyInit = jest.spyOn(MyComponent.prototype as any, 'init');
    const mMyProperty = { addEventListener: jest.fn() } as any;
    MyComponent.prototype['myProperty'] = mMyProperty;
    const wrapper = mount(<MyComponent flag={true} />);
    expect(spyInit).toBeCalled();
    expect(mMyProperty.addEventListener).toBeCalledWith('event', expect.any(Function), false);
  });

  it('should NOT add event listener', () => {
    const spyInit = jest.spyOn(MyComponent.prototype as any, 'init');
    const mMyProperty = { addEventListener: jest.fn() } as any;
    MyComponent.prototype['myProperty'] = mMyProperty;
    const wrapper = mount(<MyComponent flag={false} />);
    expect(spyInit).toBeCalled();
    expect(mMyProperty.addEventListener).not.toBeCalled();
  });
});

unit test results with 100% coverage:

 PASS  stackoverflow/60714899/index.test.tsx
  60714899
    ✓ should add event listener (42ms)
    ✓ should NOT add event listener (2ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   92.31 |      100 |      80 |     100 |                   
 index.tsx |   92.31 |      100 |      80 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.77s, estimated 10s

source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60714899

Miscalculate answered 18/3, 2020 at 3:59 Comment(0)
F
43

Not exactly answering the question, but people who are migrating from jasmine to jest may find this useful.

jest.spyOn(component, 'propertyName', 'get').mockReturnValue(...);

This is an equivalent to jasmine's spyOnProperty:

jasmine.spyOnProperty(component, 'propertyName').and.returnValue(...);
Furlong answered 2/11, 2020 at 22:50 Comment(4)
I found this helpful even though I am not migrating :D. It matches the title of the question. Bringing jasmine into play is not a good idea thouh, since this question is not about that. I you think this is missing on SO, you can create a question and self-answer it.Carnation
@WilliMentzel: I found this question when looking for this answer. But this answer wasn't there, so I fixed it.Furlong
Thanks for doing that :)Carnation
Thanks for the Jasmine reference, the solution makes perfect sense now.Topic
M
5

You need to pass the flag props to the component. E.g.

index.ts:

import { Component } from 'react';

export interface IMyComponentProps {
  flag?: boolean;
}

export class MyComponent extends Component<IMyComponentProps> {
  private myProperty!: HTMLElement;

  public componentDidMount() {
    this.init();
  }
  public render() {
    return null;
  }

  private init() {
    if (this.props.flag) {
      this.myProperty.addEventListener('event', () => null, false);
    }
  }
}

index.test.tsx:

import { MyComponent } from './';
import { mount } from 'enzyme';
import React from 'react';

describe('60714899', () => {
  it('should add event listener', () => {
    const spyInit = jest.spyOn(MyComponent.prototype as any, 'init');
    const mMyProperty = { addEventListener: jest.fn() } as any;
    MyComponent.prototype['myProperty'] = mMyProperty;
    const wrapper = mount(<MyComponent flag={true} />);
    expect(spyInit).toBeCalled();
    expect(mMyProperty.addEventListener).toBeCalledWith('event', expect.any(Function), false);
  });

  it('should NOT add event listener', () => {
    const spyInit = jest.spyOn(MyComponent.prototype as any, 'init');
    const mMyProperty = { addEventListener: jest.fn() } as any;
    MyComponent.prototype['myProperty'] = mMyProperty;
    const wrapper = mount(<MyComponent flag={false} />);
    expect(spyInit).toBeCalled();
    expect(mMyProperty.addEventListener).not.toBeCalled();
  });
});

unit test results with 100% coverage:

 PASS  stackoverflow/60714899/index.test.tsx
  60714899
    ✓ should add event listener (42ms)
    ✓ should NOT add event listener (2ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   92.31 |      100 |      80 |     100 |                   
 index.tsx |   92.31 |      100 |      80 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.77s, estimated 10s

source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60714899

Miscalculate answered 18/3, 2020 at 3:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.