moll / node-mitm

Intercept and mock outgoing Node.js network TCP connections and HTTP requests for testing. Intercepts and gives you a Net.Socket, Http.IncomingMessage and Http.ServerResponse to test and respond with. Super useful when testing code that hits remote servers.
Other
637 stars 48 forks source link

Work with supertest #60

Closed kirillgroshkov closed 4 years ago

kirillgroshkov commented 4 years ago

Any ideas on how to let it still work (not throw) with supertest (testing local mocked express server)?

I'm using it as a part of https://github.com/palmerj3/jest-offline:

const Mitm = require('mitm');
const mitm = Mitm();

mitm.on('request', (req, res) => {
  throw new Error('Network requests forbidden in offline mode');
  res.end();
});

Related: https://github.com/palmerj3/jest-offline/issues/1

moll commented 4 years ago

Hey!

Let what work?

If you're after preventing all outgoing requests and failing a test, this is what I use myself to intercept and fail all non-intercepted requests: https://github.com/rahvaalgatus/rahvaalgatus/blob/master/test/mitm.js#L15. Especially the checkIntercept error which tests whether a request was responded to already and if not, errors out with 504 (https://github.com/rahvaalgatus/rahvaalgatus/blob/master/test/mitm.js#L38)

kirillgroshkov commented 4 years ago

@moll this is interesting, I'll check your code and see if it works for me...

kirillgroshkov commented 4 years ago

Meanwhile this almost works for me (answering my own question):

mitm.on("connect", function(socket, opts) {
      if (opts.host == "localhost" || opts.host == '127.0.0.1') {
        socket.bypass()
      }
}

Currently trying to figure out how to log properly for cases when host is not localhost. Currently it hangs in such cases and I'd like it to log smth.

moll commented 4 years ago

While on the subject of testing your local server, I've never understood what problem Supertest is supposed to solve. All you need is to spin your server up for every test (like https://github.com/rahvaalgatus/rahvaalgatus/blob/master/test/web.js) and then proceed with your favorite HTTP library. I use the Fetch API myself with Fetch/Off (https://www.npmjs.com/package/fetch-off).

Here's how a simple redirect test looks like: https://github.com/rahvaalgatus/rahvaalgatus/blob/master/test/bin/web_test.js#L27 this.request is a helper that prepends localhost and is configured in https://github.com/rahvaalgatus/rahvaalgatus/blob/master/test/web.js.

moll commented 4 years ago

Currently trying to figure out how to log properly for cases when host is not localhost. Currently it hangs in such cases and I'd like it to log smth.

Jam logging or a throw into https://github.com/rahvaalgatus/rahvaalgatus/blob/master/test/mitm.js#L38 and you should be done.

kirillgroshkov commented 4 years ago

Ok, closing this with this solution that works for me:

const LOCAL_HOSTS = ['localhost', '127.0.0.1']

/**
 * Based on: https://github.com/palmerj3/jest-offline/blob/master/index.js
 */
export function jestOffline (): void {
  console.log('jest offline mode')
  const Mitm = require('mitm')
  const mitm = Mitm()

  mitm.on('connect', (socket: any, opts: any) => {
    const { host } = opts

    if (!LOCAL_HOSTS.includes(host)) {
      throw new Error(`Network request forbidden by jestOffline(): ${host}`)
    }

    socket.bypass()
  })
}
moll commented 4 years ago

Glad to hear you got it working.

kirillgroshkov commented 4 years ago

Yes, and thanks for amazing package!