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;
@frankcalise
Copy link

Hey thanks for sharing this. If you use promise chaining though, the mock will fail. You can add this to your mock request and it should do the trick:

then: jest.fn().mockImplementation(callback => {
    return new Promise((resolve, reject) => {
      if (mockError) {
        return reject(mockError)
      }
      return resolve(callback(mockResponse))
    })
  }),

@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