Packageless - It's time to reduce your dependencies: The Supertest case.
Tags: javascript, testing, package, snippet
Published: 2021-10-01 01:37:35

Hey 👋,
Let me share this small snippet that I hope will make you think differently.

### Are you not tired of Github security bot that yelling at you about potential security issue within your package-lock.json?

YES, YES, YES!
This is why I want to share my small snippets. It's time to reduce the amount of dependencies in your project.

## The Supertest use case.

[Supertest](https://www.npmjs.com/package/supertest) is a Popular library that is used to Unit Test HTTP Server.
However Supertest depends on other libraries:
* superagent (11 dependencies)
* methods (0 dependencies)

Do we really need it? 

Let me share the small express app that we will use for our example:

```js
const app = express()
  .use(express.json())
  .post('/users', (req, res) => {
    res.status(201).json({ id: 1, name: 'Joe' })
  })
```

### Supertest

Here an example on how we use super test to test a simple POST endpoint.

```js
describe('[SUPERTEST] Http server Testing', () => {
  test('POST /users (201)', async () => {
    const response = await supertest(app)
      .post('/users')
      .send({name: 'Joe'})
    expect(response.status).toBe(201)
    const expectedBody = {
      id: 1,
      name: 'Joe'
    }
    expect(response.body).toEqual(expectedBody)
  })
})
```

## Alternatives

I'm assuming that your project is already importing a library to perform HTTP request. And this is exactly what we will try to reuse.

### 1. Axios

If your project is already using axios this snippet is for you:

```js
describe('[AXIOS] Http server Testing', () => {
  test('POST /users (201)', async () => {
    const server = app.listen(0)
    const { port } = server.address()
    const instance = axios.create({
      baseURL: `http://127.0.0.1:${port}`,
      responseType: 'json'
    })
    const response = await instance.post('users', {  name: 'Joe' })
    server.close()
    expect(response.status).toBe(201)
    const expectedBody = {
      id: 1,
      name: 'Joe'
    }
    expect(response.data).toEqual(expectedBody)
  })
})
```

### 2. GOT

If your project is already using GOT this snippet is for you:

```js
describe('[GOT] Http server Testing', () => {
  test('POST /users (201)', async () => {
    const server = app.listen(0)
    const { port } = server.address()
    const instance = got.extend({
      prefixUrl: `http://127.0.0.1:${port}`,
      responseType: 'json'
    })
    const response = await instance.post('users', {
      json: { 
        name: 'Joe'
      }
    })
    server.close()
    expect(response.statusCode).toBe(201)
    const expectedBody = {
      id: 1,
      name: 'Joe'
    }
    expect(response.body).toEqual(expectedBody)
  })
})
```

### 3. Node Fetch

If your project is already using node fetch this snippet is for you:

```js
describe('[FETCH] Http server Testing', () => {
  test('POST /users (201)', async () => {
    const server = app.listen(0)
    const { port } = server.address()
    const response = await fetch(`http://127.0.0.1:${port}/users`, {
      method: 'post',
      body: JSON.stringify({ name: 'Joe' }),
      headers: {'Content-Type': 'application/json'}
    });
    server.close()
    expect(response.status).toBe(201)
    const expectedBody = {
      id: 1,
      name: 'Joe'
    }
    expect(response.json()).resolves.toEqual(expectedBody)
  })
})
```

I hope you like it and understand how you can easily improve the long term maintenance of your project.
Let me know which flavor you like, I will share a more snippet soon.

You can find the full detail of the implementation here: https://github.com/olivierodo/nodejs-packageless/tree/main/supertest

Feel free to contribute if you know another way to reduce the dependency with supertest 😇.