knee-cola/jest-mock-axios

Is there a better way to separate multiple requests with the same url and method–eg. params?

Closed this issue · 2 comments

I have two calls to the same endpoints that happen in parallel without guaranteed order, let's just say for simplicity:

GET /api/request { params: { supported: true } }
GET /api/request { params: { supported: false } }

It looked like I could've attempted to resolve this like so, but it didn't feel scalable (I didn't try):

getReqByRegex({ url: /\/api\/request/, config: /params.*supported=true/ });
getReqByRegex({ url: /\/api\/request/, config: /params.*supported=false/ });

This is how I resolved it, basically writing my own getReqMatching(criteria) and iterating over the queue directly instead. This is fine actually, I just expect a major version bump in this repo may require a rewrite of my repo's code is all.

Would this be something you'd consider a PR on? I just wanted to pop the issue even if I do open a PR later.

My primary concern was AxiosRequestConfig['params'] is typed as any in Axios, but I am explicitly treating it as an object and comparing that all of the params in criteria are in the QueueItem.config.params object as well.

/** Find the request in the queue based on: criteria: `url`, `method`, and `params`. */
const request = queue.find((item: AxiosMockQueueItem) => {
  /** If we provided a method and it didn't match, this is not the request. */
  if (method !== undefined && method?.toLowerCase() !== item.method?.toLowerCase()) {
    return false;
  }

  /** If we provided a url and it didn't match, this is not the request. */
  if (url !== undefined && url !== item.url) return false;

  if (
    params !== undefined &&
    item.config.params !== undefined &&
    isObject(item.config.params) // EXAMPLE NOTE: This is an internal function, think lodash/isObject
  ) {
    /** If all of the params from our config are in the request, we've found the correct request. */
    const hasAllCriteriaParams = Object.entries(params).every(
      ([key, value]) => item.config.params[key] === value
    );

    if (!hasAllCriteriaParams) return false;
  }

  return true;
});

if (!request) throw new Error('…');

mockResponse({ data }, request);

Hi,

sorry for the late response. I added support for params in the getReqMatching support in v4.5.0, inspired by the code you provided above. Therefore, something like this should work now:

const req = mockAxios.getReqMatching({url: '/api/request', params: {success: true}})

Can you test this? Does this meet your needs?

@kingjan1999 That's perfect actually, a much quicker turnaround than I expected!

I was in fact able to essentially revert my entire PR and go back to (roughly):

const request = mockAxios.getReqMatching({ url, method, params });
mockAxios.mockResponse({ data, status, statusText, headers, config }, request)

Works for me, closing this.