title: Jest not terminating after tests complete successfully
body: <p>I'm working with <code>jest</code> &amp; <code>supertest</code> to test my api endpoints and the tests are passing with no problems; however <code>jest</code> is never exiting with the <em>Done in X amount of time</em> statement that I would normally see. I looked to make sure the <code>--watch</code> flag was not being used and it was not. It seems as if the connection to the server is never ending so <code>jest</code> is left wondering what is next. <code>UserFactory.generate()</code> creates fake user data using the <code>faker</code> library.</p>
  
  <p>I'm at a loss on trying to troubleshoot this. I've followed the recommended strategies on <code>jest</code>'s help page with no luck and been digging around in the issue tracker as well but see nothing about similar issues.</p>
  
  <p>This is what I will see on running my test suite:</p>
  
  <p><a href="https://i.stack.imgur.com/QPTJt.png" rel="noreferrer"><img src="https://i.stack.imgur.com/QPTJt.png" alt="enter image description here"></a></p>
  
  <p>As you can see the test is ran 7 passes. I'm told that all tests have been run and then <code>morgan</code> shows the <code>POST</code> that has happened. <code>jest</code> never <em>exits</em> so in reality this is failing because it will timeout on any CI sever barring a manual exit.</p>
  
  <p>I have tried using <code>.end() &amp; done()</code> as well as <code>.then() &amp; done()</code> in place of the <code>async/await</code>. They all are returning the same end result and if it were an issue of a promise not resolving <code>jest</code> will error out over an unresolved promise so I am beyond stumped on why this is not terminating as <code>jest</code> normally would.</p>
  
  <p>Has anyone encountered an issue like this before?</p>
  
  <p><em>user.controller.test.js</em></p>
  
  <pre><code>import mongoose from 'mongoose';
  import request from 'supertest';
  import { UserFactory } from '../../__mocks__';
  import { User } from '../../modules';
  import { config } from '../../utils';
  import app from '../../';
  
  const mockRoute = data =&gt; request(app).post(`${config.ENDPOINT}/user/sign-up`).send(data);
  
  describe(`POST: /user/sign-up`, () =&gt; {
    // remove any user data from db prior to running tests.
    beforeAll(async () =&gt; { await User.remove(); });
    test('Returns status 201 on success.', async () =&gt; {
      // Returns the response object: res.status === { status }
      const { status }  = await mockRoute(UserFactory.generate());
      expect(status).toEqual(201);
    });
    afterAll(async () =&gt; {
      // drop connection to the collection
      const { users } = mongoose.connection.collections;
      await users.drop();
    });
  });
  </code></pre>
  
  <p><em>user/routes.js</em></p>
  
  <pre><code>import { Router } from 'express';
  import validate from 'express-validation';
  
  import { signUp } from './controller';
  import valid from './validation'
  
  const routes = new Router();
  
  /**
   * 1. Define the route: 'user/signup'.
   * 2. Validate the data being provided on the POST
   *    against valid.signUp object.
   * 3. Provide data to signUp controller method for
   *    creating a user in the database.
   */
   routes.post('/user/sign-up', validate(valid.signUp), signUp);
  
   export default routes;
  </code></pre>
  
  <p><em>user/controller.js</em></p>
  
  <pre><code>import HTTPStatus from 'http-status';
  import User from './model';
  import { config, filterBody } from '../../utils';
  
  export const signUp = async (req, res, next) =&gt; {
    const filteredBody = filterBody(req.body, config.WHITELIST.users.signUp);
    try {
      const user = await User.create(filteredBody);
      return res.status(HTTPStatus.CREATED).json(user.toAuthJSON());
    } catch (e) {
      e.status = HTTPStatus.BAD_REQUEST;
      return next(e);
    }
  }
  </code></pre>
  
  <p><em>user/model.js</em></p>
  
  <pre><code>import mongoose, { Schema } from 'mongoose';
  import uniqueValidator from 'mongoose-unique-validator';
  import { hashSync, compareSync } from 'bcrypt-nodejs';
  import jwt from 'jsonwebtoken';
  
  import { config } from '../../utils';
  
  const UserSchema = new Schema({
    email: {
      type: String,
      unique: true,
      required: [true, 'Email is required!'],
      trim: true,
      validate: {
        validator(email) {
          const emailRegex = /^[-a-z0-9%S_+]+(\.[-a-z0-9%S_+]+)*@(?:[a-z0-9-]{1,63}\.){1,125}[a-z]{2,63}$/i;
          return emailRegex.test(email);
        },
        message: '{VALUE} is not a valid email!',
      }
     },
     password: {
        type: String,
        required: [true, 'Password is required!'],
        trim: true,
        minlength: [6, 'Password need to be longer!'],
        validate: {
          validator(password) {
          return password.length &gt;= 6 &amp;&amp; password.match(/\d+/g);
          },
        },
    }
  }, { timestamps: true })
  
  UserSchema.plugin(uniqueValidator, {
    message: '{VALUE} already taken!',
  });
  
  UserSchema.pre('save', function(next) {
    if (this.isModified('password')) {
     this.password = this._hashPassword(this.password);
     return next();
    }
    return next();
  });
  
  
  UserSchema.methods = {
    authenticateUser(password) {
      return compareSync(password, this.password);
    },
    _hashPassword(password) {
      return hashSync(password);
    },
    createToken() {
      return jwt.sign({ _id: this._id }, config.JWT_SECRET);
    },
    toAuthJSON() {
      return {
        _id: this._id,
        token: `JWT ${this.createToken()}`,
      };
    },
    toJSON() {
      return {
        _id: this._id,
        username: this.username,
      };
    },
  };
  
  let User;
  
  try {
     User = mongoose.model('User');
  } catch (e) {
     User = mongoose.model('User', UserSchema);
  }
  
  export default User;
  </code></pre>
  
  <p><em>user/validation.js</em></p>
  
  <pre><code>import Joi from 'joi';
  
  export default {
     signUp: {
      body: {
        email: Joi.string().email().required(),
        password: Joi.string()
          .min(6)
          .regex(/^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$/)
          .required(),
      },
    },
  };
  </code></pre>
  
  <p><em>middlewares.js</em></p>
  
  <pre><code>import bodyParser from 'body-parser';
  import compression from 'compression';
  import cors from 'cors';
  import morgan from 'morgan';
  import { userRoutes } from '../modules';
  
  export default app =&gt; {
    app.use(compression());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(cors());
    app.use(morgan('dev'));
    // applying api routes last.
    app.use('/api/v1', [userRoutes]);
  }
  </code></pre>
  
  <p><em>index.js</em></p>
  
  <pre><code>import express from 'express';
  import {
    database,
    config,
    middlewares,
  } from './utils';
  
  // Create instance of Express.
  const app = express();
  const MODE = process.env.NODE_ENV;
  
  // Apply middlewares to Express.
  middlewares(app);
  // Connect to the environment determined database.
  database(config.MONGO_URI)
  
  app.listen(config.PORT, err =&gt; {
    if (err) { return console.error(err); }
    console.log(`App running on port: ${config.PORT} in ${MODE} mode.`);
  });
  
  export default app;
  </code></pre>