Search code examples
reactjsunit-testingjestjstddenzyme

Mocking a simple function in react.js, jest, enzyme


I am new to testing in react and am building a simple todo application. I am struggling to mock the delete function in the lists component.

My test looks like this at the moment

  it('deletes an item from the list', () => {
    const deleteItem = jest.fn();
    const items = [{body: "New note", id: "12345"}]
    const textEl = wrapper.find("#text-output p")
    wrapper = shallow(<ListItems list={items} deleteItem={deleteItem}/>)
    wrapper.find('#delete').simulate('click')
    expect(textEl.text()).toContain("//Should be empty")
  })

currently the when I run the tests the error reads..

Expected substring: "//Should be empty"
Received string:    "New note X"

The application works fine, but I am not mocking the delete function correctly in my test as a "New Note" is still being passed through. What am I doing wrong?

just in case it helps, here is the file I am testing..

function ListItems(props) {
   const list = props.list
    const displayItems = list.map((item, index) => 
    {
      return <div id='text-output' key={index}>
            <p>
              {item.body } 
              &nbsp;
              <button
              id="delete"
              onClick={ () => props.deleteItem(item.id)}>
                X
              </button>
            </p>
        </div>
    })
  return(
  <div>
    <h1>This is the list</h1>
    {displayItems}
  </div>
  )
}

any help would be great!


Solution

  • In your test since you mocked the deleteItem callback it doesn't actually delete an item from the items object passed to the list prop. Also, const textEl = wrapper.find("#text-output p") before wrapper = shallow(<ListItems list={items} deleteItem={deleteItem}/>) probably also won't work as expected.

    You can however instead assert the deleteItem mock was called with the specified item id. TBH, that is what the test should be anyway since that component under test doesn't appear to have any logic other than rendering a list of items and attaching an onClick callback.

    .toHaveBeenCalledWith

    it('should invoke deleteItem callback on button click with item id', () => {
      const deleteItemMock = jest.fn();
      const items = [{body: "New note", id: "12345"}];
    
      wrapper = shallow(<ListItems list={items} deleteItem={deleteItemMock}/>);
      wrapper.find('#delete').simulate('click');
    
      expect(deleteItemMock).toHaveBeenCalledWith("12345");
    });