Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test callback function with jest

I'm trying to test a function with a callback inside. I set up a mock function, but I also need to test a callback.

I've tried to separate it as another mock function, but it doesn't counted as covered.

Function I'm trying to test:

export const checkDescription = async page => {
    const metaDescription = await page.$eval(
      'meta[name="description"]',
      description => description.getAttribute("content")
    );
    return metaDescription;
};

I've mocked the page function :

const page = {
  $eval: jest.fn(() => "Value")
};

my test :

test("Should return description", async () => {
  expect(await checkDescription(page)).toBe("Value"); 
  expect(page.$eval).toHaveBeenCalled();
});

I've tried to separate description :

const description = {
  getAttribute: jest.fn(() => "Value")
};  

but I don't think that it's a correct way to cover description inside $eval.

like image 416
Elena Avatar asked May 02 '19 18:05

Elena


1 Answers

You're close!

The description arrow function is passed to your page.$eval mock function so you can use mockFn.mock.calls to retrieve it.

Once you've retrieved it, you can call it directly to test it and get full code coverage:

test("Should return description", async () => {
  expect(await checkDescription(page)).toBe("Value");  // Success!
  expect(page.$eval).toHaveBeenCalled();  // Success!

  const description = page.$eval.mock.calls[0][1];  // <= get the description arrow function
  const getAttributeMock = jest.fn(() => 'mock content');
  expect(description({ getAttribute: getAttributeMock })).toBe('mock content');  // Success!
  expect(getAttributeMock).toHaveBeenCalledWith('content');  // Success!
  // Success!  checkDescription now has full code coverage
});
like image 89
Brian Adams Avatar answered Sep 19 '22 13:09

Brian Adams