4

I have a HOC, adding some props to the component, for handling network requests and passing down data as prop. The following is a very simplified version of the HOC:

export const withTags = (Component) => {
  class WithTags extends PureComponent {
    getItems() {
      return getTags({
            search: this.state.searchTerm
          })
        .then((items) => this.setState({
          items
        }));
    }

    .
    .
    .

    render() {
      return (
        <Component
          {...this.props}
          items={this.state.items}
          getItems={this.getItems}
        />
      );
    }
  }

  return withTags;
}

Using enzyme I can easily do something like:

    it('should return tags', async () => {
      const mockComponent = jest.fn(() => null);
      const WithTagsComponent = withTags(mockComponent);

      const wrapper = shallow(<WithTagsComponent />);
      const res = await wrapper.props().getItems();

      expect(res).toEqual(getTagsResponseMock);
      expect(tagsApi.getTags).toHaveBeenCalledTimes(1);
      expect(tagsApi.getTags).toHaveBeenCalledWith({
        limit: PAGE_SIZE,
      });
      expect(wrapper.props().items).toEqual([tagFlowMock]);
    });

But this approach won't work in React Testing Library, as we should test from the end-user's perspective, and not access props. So, how should I test such HOCs using React Testing Library?

2
  • Using a class inside a function seems unnecessary. Commented Feb 5, 2021 at 16:17
  • 1
    React Testing Library, yes, generally works by interacting with the component under test like a user or other components would. Seems you need to make a mock component that consumes the items and getItems props and does something testable, i.e. some interaction like displaying the items and clicking a button to get new items. Can you provide a more complete HOC code example? Commented Feb 5, 2021 at 16:22

1 Answer 1

1

I think your test almost works fine but you need to replace two things. Since you're manually calling getItems here you could create a mock Component that would ideally do similar stuff as the components you plan to use with your HOC. For example, this mock component coould have a button that when clicked would call getItems and would also display items.

const MockComponent = ({items, getItems}) => { 
  return (
    <div>
      <button data-testid="button" onClick={getItems}>Click me</button>
      <ul>
        { items.map((item, index) => <li key={index}>{item}</li>) }
      </ul>
    </div>
  )

Then in your test instead of manually calling getItems:

const res = await wrapper.props().getItems();

you could do something like

fireEvent.click(getByTestId('button')

and then assert that your tagsApi was called and that your component displays correct items.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.