wheresrhys/fetch-mock-jest

Improve failure messages for toHaveLastFetched

Closed this issue · 6 comments

I've used fetch-mock before but just installed fetch-mock-jest to try it out and provide some feedback :)

I'm doing this sort of thing in my tests:

expect(fetchMock).toHaveLastFetched({
  url: "/ownerships",
  body: {
    paint_id: "V76-517",
    quantity: 1
  }
})

I was expecting this to pass, but it didn't. The failure message I get is:

Last call to fetch should have had a URL of [object Object]

This made it quite tricky to work out what was actually going on, I had to use console.log(fetchMock.calls()) to see the call that was made and discovered that the wrong quantity was being sent:

[
  [
    '/ownerships',
    {
      method: 'POST',
      body: '{"paint_id":"V76-517","quantity":1}',
      credentials: 'same-origin',
      headers: [Object]
    },
    request: undefined,
    identifier: '/ownerships',
    isUnmatched: undefined
  ]
]

I think it would be really great if the toHaveLastFetched matcher could inspect the arguments it received and then respond with a corresponding output.

For example:

expect(fetchMock).toHaveLastFetched("/ownerships")

# Fails with
Last call to fetch should have had a URL of "/ownerships" but was "/owner_ships"

If toHaveLastFetched is called with an object literal, maybe the corresponding keys could be pulled from the resulting request and then nicely diffed so the user knows exactly what went wrong.

I'm going to keep playing, thanks for listening and for all of your hard work on fetch-mock :)

Now I think I am using toHaveLastFetched totally wrong, it seems to only accept a URL as the first parameter.

Additionally, I have two tests, in the first one I can't see any calls in fetchMock.calls() and in the second test I see the call that would have been created from the first test.

So I suspect I am doing something very, very wrong. Probably to do with something that is asynchronous. Sigh.

Here's something weird, the following expectation results in a passing test:

expect(fetchMock).toHaveLastFetched("/ownershipsxxxxxx", {
  body: {
    paint_id: "V76-517dsfsdfsdfsfsdf",
    quantity: 7722222222
  }
})

It seems whatever I change that to, it'll always pass.

Is it possible that if fetchMock.calls().length === 0 then toHaveLastFetched always returns true?

Yes, me, I think that is possible:

const lastCall = [...fetchMock.calls()].pop()
const lastUrlCall = [...fetchMock.calls("/ddddfsdfsdf", {})].pop()

console.log("lastCall", lastCall)
console.log("lastUrlCall", lastUrlCall)
console.log("lastUrlCall === lastUrlCall", lastCall === lastUrlCall)
____________

  console.log app/assets/components/paint_collection/index.test.js:186
    lastCall undefined

  console.log app/assets/components/paint_collection/index.test.js:187
    lastUrlCall undefined

  console.log app/assets/components/paint_collection/index.test.js:188
    lastUrlCall === lastUrlCall true

That's enough of my nonsense for the night :)

Not nonsense at all - this is all really useful feedback. I can't promise to address it all, or to do so quickly, but will look into all your points.

Most of the above is addressed now. Feel free to raise a separate issue for anyt things I may have missed, and thanks again for the feedback

@wheresrhys those changes look perfect, I'll upgrade and carry on testing :) Thanks!