Skip to content

Instantly share code, notes, and snippets.

@gbalbuena
Forked from charleskorn/superagent.js
Last active November 3, 2022 10:50
Show Gist options
  • Save gbalbuena/3ec499535d435712ce16c1eced9f5502 to your computer and use it in GitHub Desktop.
Save gbalbuena/3ec499535d435712ce16c1eced9f5502 to your computer and use it in GitHub Desktop.
A Jest mock for superagent. Place in your __mocks__ directory.
llet mockDelay;
let mockError;
let mockResponse = {
get: jest.fn(),
ok: true,
status: 200,
toError: jest.fn(),
};
let mockResponseBodies;
let responseBodiesIndex;
const Request = {
__setMockDelay(boolValue) {
mockDelay = boolValue;
},
__setMockError(mockErr) {
mockError = mockErr;
},
__setMockResponse(mockRes) {
mockResponse = mockRes;
},
__setMockResponseBodies(bodies) {
mockResponseBodies = bodies;
responseBodiesIndex = -1;
},
__setMockResponseBody(body) {
mockResponse.body = body;
responseBodiesIndex = undefined;
},
accept: jest.fn().mockReturnThis(),
catch: jest.fn().mockReturnThis(),
delete: jest.fn().mockReturnThis(),
end: jest.fn().mockImplementation(callback => {
if (mockDelay) {
this.delayTimer = setTimeout(callback, 0, mockError, mockResponse);
return;
}
callback(mockError, mockResponse);
}),
field: jest.fn().mockReturnThis(),
get: jest.fn().mockReturnThis(),
head: jest.fn().mockReturnThis(),
patch: jest.fn().mockReturnThis(),
post: jest.fn().mockReturnThis(),
put: jest.fn().mockReturnThis(),
query: jest.fn().mockReturnThis(),
redirects: jest.fn().mockReturnThis(),
send: jest.fn().mockReturnThis(),
set: jest.fn().mockReturnThis(),
retry: jest.fn().mockReturnThis(),
then: cb =>
new Promise((resolve, reject) => {
if (typeof responseBodiesIndex !== 'undefined') {
responseBodiesIndex += 1;
mockResponse.body = mockResponseBodies[responseBodiesIndex];
}
if (mockError) {
reject(mockError);
} else {
resolve(cb(mockResponse));
}
}),
timeout: jest.fn().mockReturnThis(),
type: jest.fn().mockReturnThis(),
};
export default Request;
@a8568730
Copy link

a8568730 commented Jun 20, 2019

Thank you @gbalbuena for this great gist, and also thank the .then advise from @frankcalise.
I use superagent-bluebird-promise and stuck on mock. I follow both of your advise and it works.

__mocks__/superagent-bluebird-promise.js

let query = null

const Request = {
  get: jest.fn().mockReturnThis(),
  query: jest.fn(function(q) {
        query = q
        return this
  }),
  then: jest.fn().mockImplementation(callback => {
    if (!query['ANY_PARAM_KEY'])
      return Promise.reject(mockError)
    return Promise.resolve(callback(mockResponse))
  })
}

export default Request;

@fire-cracker
Copy link

fire-cracker commented Jul 21, 2020

@gbalbuena What about restoring the mocks?

@remyoudemans
Copy link

@fire-cracker we reset the mocks like this:

beforeEach(() => {
  request.__setMockError(null);
  request.__setMockResponse({
    get: jest.fn(),
    ok: true,
    status: 200,
    toError: jest.fn(),
  });
});

@remyoudemans
Copy link

@gbalbuena thanks for the great gist! We had to extend it by adding a __setMockResponseBodies to be able to test a function that made multiple successive requests.

In case anybody else needs to do the same thing, this is what it looks like:

let mockDelay;
let mockError;
let mockResponse = {
  get: jest.fn(),
  ok: true,
  status: 200,
  toError: jest.fn(),
};

let mockResponseBodies;
let responseBodiesIndex;

const Request = {
  __setMockDelay(boolValue) {
    mockDelay = boolValue;
  },
  __setMockError(mockErr) {
    mockError = mockErr;
  },
  __setMockResponse(mockRes) {
    mockResponse = mockRes;
  },
  __setMockResponseBodies(bodies) {
    mockResponseBodies = bodies;
    responseBodiesIndex = -1;
  },
  __setMockResponseBody(body) {
    mockResponse.body = body;
    responseBodiesIndex = undefined;
  },
  accept: jest.fn().mockReturnThis(),
  catch: jest.fn().mockReturnThis(),
  delete: jest.fn().mockReturnThis(),
  end: jest.fn().mockImplementation(callback => {
    if (mockDelay) {
      this.delayTimer = setTimeout(callback, 0, mockError, mockResponse);

      return;
    }

    callback(mockError, mockResponse);
  }),
  field: jest.fn().mockReturnThis(),
  get: jest.fn().mockReturnThis(),
  head: jest.fn().mockReturnThis(),
  patch: jest.fn().mockReturnThis(),
  post: jest.fn().mockReturnThis(),
  put: jest.fn().mockReturnThis(),
  query: jest.fn().mockReturnThis(),
  redirects: jest.fn().mockReturnThis(),
  send: jest.fn().mockReturnThis(),
  set: jest.fn().mockReturnThis(),
  then: cb =>
    new Promise((resolve, reject) => {
      if (typeof responseBodiesIndex !== 'undefined') {
        responseBodiesIndex += 1;
        mockResponse.body = mockResponseBodies[responseBodiesIndex];
      }
      if (mockError) {
        reject(mockError);
      } else {
        resolve(cb(mockResponse));
      }
    }),
  timeout: jest.fn().mockReturnThis(),
  type: jest.fn().mockReturnThis(),
};

export default Request;

@gbalbuena
Copy link
Author

Woow, thanks for all the contributions

I haven't worked again with superagent, this is super complete now :)

@AriefLuthfi79
Copy link

How to use this mocks buddy? I mean how to import that thing? Is it automatically resolve the object with superagent?

  • Sorry for noob question

@AriefLuthfi79
Copy link

thanks for sharing this code, i solved my problem already

@jancel
Copy link

jancel commented Nov 19, 2020

first let has two l's

@Bazze
Copy link

Bazze commented Apr 22, 2021

We could also add for retry function:

retry: jest.fn().mockReturnThis(),

@gbalbuena
Copy link
Author

updated, thanks @Bazze

@Asaf-S
Copy link

Asaf-S commented May 21, 2021

Can someone show an example of a Jest test using this mock-up? Especially a test when the superagent call is not being performed in the test itself, but in a function called by the test.

Example:

test('demo', async () => {
  await functionThatUsesSuperagent();
});

Bonus: Doing the test in Typescript 😊

@danielnmai
Copy link

there is a typo on line 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment