'Testing functions with arguments in React with Jest Enzyme

I have a function named toggleFilter() in a react component which looks like this:

toggleFilter = (filterType, filterName) => {
        const filterApplied = this.state.appliedFilterList[filterType].includes(filterName);

        if (filterApplied) {
            //Remove the applied filter
            this.setState(prevState => ({
                appliedFilterList: {
                    ...prevState.appliedFilterList,
                    [filterType]: prevState.appliedFilterList[filterType].filter(filter => filter !== filterName)
                }
            }));
        } else {
            //Add the filter
            this.setState(prevState => ({
                appliedFilterList: {
                    ...prevState.appliedFilterList,
                    [filterType]: [...prevState.appliedFilterList[filterType], filterName]
                }
            }));
        }
    };

This function is being passed to the child components as :

 <ChildComponent  toggleFilter={this.toggleFilter} />

So, i am trying to test this toggleFilter() function like this:

 it("checks for the function calls", () => {
    const toggleFilterMockFn = jest.fn();
    const component = shallow(
        <ProductList
            headerText="Hello World"
            productList={data}
            paginationSize="10"
            accessFilters={["a 1", "a 2"]}
            bandwidthFilters={["b 1", "b 2"]}
            termsFilters={["t 1", "t 2"]}
            appliedFilterList={appliedFilter}
            toggleFilter={toggleFilterMockFn}
        />
    );
    component.find(FilterDropdownContent).prop("toggleFilter")({ target: { value: "someValue" } });
});

But I get the error saying :

TypeError: Cannot read property 'includes' of undefined

What may be causing the issue? Can someone please help me with this.

EDIT 1: I tried the below test case:

expect(toggleFilterMockFn).toHaveBeenCalledWith(appliedFilter, "access");

But I get the below error :

expect(jest.fn()).toHaveBeenCalledWith(expected)

    Expected mock function to have been called with:
      [{"access": ["Access Type Of The Service"], "bandwidth": ["the allowed band width ", "the allowed band width"], "term": ["term associated with the service"]}, "access"]
    But it was not called.


Solution 1:[1]

You can't render a parent and test a child function like that. Instead, you should render <FilterDropdownContent /> directly, and then write a test that simulates an event (like click) and checks to see if the function was called.

Something like this for example:

import React from 'react';
import { shallow } from 'enzyme';

describe('<FilterDropdownContent />', () => {
  let wrapper, toggleFilter;
  beforeEach(() => {
    toggleFilter = jest.fn();
    wrapper = shallow(
      <FilterDropdownContent
        toggleFilter={toggleFilter}
      />
    );
  });

  describe('when clicking the .toggle-filter button', () => {
    it('calls `props.toggleFilter()` with the correct data', () => {
      wrapper.find('.toggle-filter').simulate('click');
      expect(toggleFilter).toHaveBeenCalledWith({ target: { value: 'someValue' } });
    });
  }):
});

In this example, clicking a link with the .toggle-filter class calls the function, but you should be able to adapt this to your specific implementation.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 saquino88