Enzyme: Testing a Menu

Created on 21 Jun 2017  路  2Comments  路  Source: enzymejs/enzyme

Hi, how would I test a simple menu? For example when I click the menu, two options appear from a dropdown. And when one of the options are clicked, they invoke specific functions.

Most helpful comment

So I'm not associated with airbnb but I think I might be able to help.

I'll assume you have your elements littered with className properties just for simplicity sake

What I hear you describing here is three different test cases:

  • Menu becomes active when clicked
  • Two options rendered (let's say, as <span className="option">) when menu is active
  • Option calls prop onSelect when selected

This is fairly straight forward, so I'll outline each of these here:

Menu becomes active when clicked

it("becomes active when the hamburger button is clicked", () => {
  const wrapper = shallow(<Menu />);
  wrapper.find(".open-menu-button-class").simulate("click");
  expect(wrapper.state("active")).toBeTruthy();
});

In this case, our activation button has some className property set to open-menu-button-class, but the idea there is just to find the button or whatever element activates your menu. Then, simulate the click event. Finally, assert that the wrapper's state has been set to active.

Two options rendered when menu is active

it("renders options when active", () => {
  const wrapper = shallow(<Menu />);
  wrapper.setState({ active: true });
  expect(wrapper.find(".option").length).toBe(2);
});

Here again, we're looking for our options to have some class asociated with them, in this case option. Now, there are other ways to do this (wrapper.containsMatchingElement, for instance), but the important thing here is we're finding a list of options, then asserting that we've found how many we expect (in this case 2).

Option calls prop onSelect when selected

Now at this point, this is more of a test on the option than the menu itself, so I'm assuming Option is its own component and accepts a property onSelect that its parent Menu will pass to it.

describe("options test", () => {
  it("calls prop `onSelect` when clicked", () => {
    const spy = jest.fn();
    const wrapper = shallow(<Option onSelect={spy} />);
    wrapper.find('button').simulate('click');
    expect(spy).toHaveBeenCalled();
  });
});

So this one creates a "spy" (maybe better termed a mock, I'm not really sure) that serves to spoof the onSelect property function that normally a Menu component would provide. Then, we simulate a click on some button in the option. This could be anything (maybe yours is just a span, I don't know). So we click whatever element is decided to "select" the option, then we expect that our spy/mock/spoof function has been called. This means that the property onSelect was called when we selected the option.

All 2 comments

So I'm not associated with airbnb but I think I might be able to help.

I'll assume you have your elements littered with className properties just for simplicity sake

What I hear you describing here is three different test cases:

  • Menu becomes active when clicked
  • Two options rendered (let's say, as <span className="option">) when menu is active
  • Option calls prop onSelect when selected

This is fairly straight forward, so I'll outline each of these here:

Menu becomes active when clicked

it("becomes active when the hamburger button is clicked", () => {
  const wrapper = shallow(<Menu />);
  wrapper.find(".open-menu-button-class").simulate("click");
  expect(wrapper.state("active")).toBeTruthy();
});

In this case, our activation button has some className property set to open-menu-button-class, but the idea there is just to find the button or whatever element activates your menu. Then, simulate the click event. Finally, assert that the wrapper's state has been set to active.

Two options rendered when menu is active

it("renders options when active", () => {
  const wrapper = shallow(<Menu />);
  wrapper.setState({ active: true });
  expect(wrapper.find(".option").length).toBe(2);
});

Here again, we're looking for our options to have some class asociated with them, in this case option. Now, there are other ways to do this (wrapper.containsMatchingElement, for instance), but the important thing here is we're finding a list of options, then asserting that we've found how many we expect (in this case 2).

Option calls prop onSelect when selected

Now at this point, this is more of a test on the option than the menu itself, so I'm assuming Option is its own component and accepts a property onSelect that its parent Menu will pass to it.

describe("options test", () => {
  it("calls prop `onSelect` when clicked", () => {
    const spy = jest.fn();
    const wrapper = shallow(<Option onSelect={spy} />);
    wrapper.find('button').simulate('click');
    expect(spy).toHaveBeenCalled();
  });
});

So this one creates a "spy" (maybe better termed a mock, I'm not really sure) that serves to spoof the onSelect property function that normally a Menu component would provide. Then, we simulate a click on some button in the option. This could be anything (maybe yours is just a span, I don't know). So we click whatever element is decided to "select" the option, then we expect that our spy/mock/spoof function has been called. This means that the property onSelect was called when we selected the option.

This seems answered.

Was this page helpful?
0 / 5 - 0 ratings