I am trying to use Mongo Memory Server in supertest to test my API, but I get the following error:
Starting the MongoMemoryServer Instance failed, enable debug log for more information. Error:
UnexpectedCloseError: Instance closed unexpectedly with code "1" and signal "null"
at MongoInstance.closeHandler (/home/jonathanpotter/code/express-apps/rest-api-tutorial/node_modules/mongodb-memory-server-core/src/util/MongoInstance.ts:543:52)
at ChildProcess.emit (node:events:513:28)
at ChildProcess.emit (node:domain:489:12)
at maybeClose (node:internal/child_process:1091:16)
at Socket.<anonymous> (node:internal/child_process:449:11)
at Socket.emit (node:events:513:28)
at Socket.emit (node:domain:489:12)
at Pipe.<anonymous> (node:net:313:12)
My test is as follows:
import supertest from "supertest";
import createServer from "../utils/server";
import { MongoMemoryServer } from "mongodb-memory-server";
import mongoose from "mongoose";
const app = createServer();
describe("product", () => {
beforeAll(async () => {
const mongoServer = await MongoMemoryServer.create();
await mongoose.connect(mongoServer.getUri());
});
afterAll(async () => {
await mongoose.disconnect();
await mongoose.connection.close();
});
describe("get product", () => {
describe("given the product does not exist", () => {
it("should return a 404", async () => {
const productId = "product123";
await supertest(app).get(`/api/products/${productId}`);
});
});
});
});
My testing dependencies are:
"jest": "^29.3.1",
"mongodb-memory-server": "^8.10.2",
"supertest": "^6.3.3",
"ts-jest": "^29.0.3",
"ts-node-dev": "^2.0.0",
...and I my operating system is Pop!_OS 22.04 LTS.
edit: This all works fine on my Mac, but not on my Linux machine. Does anyone know of a fix for Linux (Pop!OS)?
Related
I've got some legacy code that I'm upgrading from version 3 of the Node.js redis library to version 4 of the Node.js redis library. The basic shape of the code looks like this
var redis = require('redis')
var client = redis.createClient({
port: '6379',
host: process.env.REDIS_HOST,
legacyMode: true
})
client.connect()
client.flushall(function (err, reply) {
client.hkeys('hash key', function (err, replies) {
console.log("key set done")
client.quit()
})
})
console.log("main done")
When I run this code with redis#4.3.1, I get the following error, and node.js exits with a non-zero status code
main done
key set done
events.js:292
throw er; // Unhandled 'error' event
^
SocketClosedUnexpectedlyError: Socket closed unexpectedly
at Socket.<anonymous> (/Users/astorm/Documents/redis4/node_modules/#redis/client/dist/lib/client/socket.js:182:118)
at Object.onceWrapper (events.js:422:26)
at Socket.emit (events.js:315:20)
at TCP.<anonymous> (net.js:673:12)
Emitted 'error' event on Commander instance at:
at RedisSocket.<anonymous> (/Users/astorm/Documents/redis4/node_modules/#redis/client/dist/lib/client/index.js:350:14)
at RedisSocket.emit (events.js:315:20)
at RedisSocket._RedisSocket_onSocketError (/Users/astorm/Documents/redis4/node_modules/#redis/client/dist/lib/client/socket.js:205:10)
at Socket.<anonymous> (/Users/astorm/Documents/redis4/node_modules/#redis/client/dist/lib/client/socket.js:182:107)
at Object.onceWrapper (events.js:422:26)
at Socket.emit (events.js:315:20)
at TCP.<anonymous> (net.js:673:12)
While in redis#3.1.2 it runs (minus the client.connect()) without issue.
I've been able to work around this by replacing client.quit() with client.disconnect(), but the actual code is a little more complex than the above example and I'd rather use the graceful shutdown of client.quit than the harsher "SHUT IT DOWN NOW" of client.disconnect().
Does anyone know what the issue here might be? Why is redis#4 failing with a SocketClosedUnexpectedlyError: Socket closed unexpectedly error.
What I found so far is that after a while (keepAlive default is 5 minutes) without any requests the Redis client closes and throws an error event, but if you don't handle this event it will crash your application.
My solution for that was:
/* eslint-disable no-inline-comments */
import type { RedisClientType } from 'redis'
import { createClient } from 'redis'
import { config } from '#app/config'
import { logger } from '#app/utils/logger'
let redisClient: RedisClientType
let isReady: boolean
const cacheOptions = {
url: config.redis.tlsFlag ? config.redis.urlTls : config.redis.url,
}
if (config.redis.tlsFlag) {
Object.assign(cacheOptions, {
socket: {
// keepAlive: 300, // 5 minutes DEFAULT
tls: false,
},
})
}
async function getCache(): Promise<RedisClientType> {
if (!isReady) {
redisClient = createClient({
...cacheOptions,
})
redisClient.on('error', err => logger.error(`Redis Error: ${err}`))
redisClient.on('connect', () => logger.info('Redis connected'))
redisClient.on('reconnecting', () => logger.info('Redis reconnecting'))
redisClient.on('ready', () => {
isReady = true
logger.info('Redis ready!')
})
await redisClient.connect()
}
return redisClient
}
getCache().then(connection => {
redisClient = connection
}).catch(err => {
// eslint-disable-next-line #typescript-eslint/no-unsafe-assignment
logger.error({ err }, 'Failed to connect to Redis')
})
export {
getCache,
}
anyway... in your situation try to handle the error event
client.on('error', err => logger.error(`Redis Error: ${err}`))
I am new to Vue and Jest, and what I want to do is to test the following XXX.vue component. And the error "Error: Error: connect ECONNREFUSED 127.0.0.1:80" that I mentioned was throw from the part 'renders correctly with different data' (I have narrowed it down by commenting out other tests in the file, so I am sure the error was thrown from the part.
Another questions is that, by running the test multiple times, it may output 3 results:
throw error: Error: Error: connect ECONNREFUSED 127.0.0.1:80 from jsdom
console.error node_modules/jest-environment-jsdom-fifteen/node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Error: connect ECONNREFUSED 127.0.0.1:80
at Object.dispatchError (/Users/jingjiejiang/Documents/My_Project/Tech_Test_Assemble/rakuten_test/rtx-cdt-test-v2/client/node_modules/jest-environment-jsdom-fifteen/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:54:19)
at Request.<anonymous> (/Users/jingjiejiang/Documents/My_Project/Tech_Test_Assemble/rakuten_test/rtx-cdt-test-v2/client/node_modules/jest-environment-jsdom-fifteen/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:675:20)
at Request.emit (node:events:525:35)
at Request.onRequestError (/Users/jingjiejiang/Documents/My_Project/Tech_Test_Assemble/rakuten_test/rtx-cdt-test-v2/client/node_modules/request/request.js:877:8)
at ClientRequest.emit (node:events:513:28)
at Socket.socketErrorListener (node:_http_client:481:9)
at Socket.emit (node:events:513:28)
at emitErrorNT (node:internal/streams/destroy:151:8)
at emitErrorCloseNT (node:internal/streams/destroy:116:3)
at processTicksAndRejections (node:internal/process/task_queues:82:21) undefined
throw "Network error: renders correctly with different data"
● Mounted About › renders correctly with different data
Network Error
at createError (node_modules/axios/lib/core/createError.js:16:15)
at XMLHttpRequest.handleError (node_modules/axios/lib/adapters/xhr.js:117:14)
at Request.onRequestError (node_modules/request/request.js:877:8)
pass the test.
Question:
How to troubleshoot the issue? Thank you so much in advance.
Vue component: XXX.vue:
<template>
<div class="about">
<el-table :data="displayHotels" stripe style="width: 100%">
<el-table-column
prop="property.name"
label="Name"
width="300">
</el-table-column>
<el-table-column
prop="property.location.country"
label="Location"
width="180">
</el-table-column>
<el-table-column prop="property.reviews.summary.score" label="Score">
</el-table-column>
</el-table>
<el-pagination
:page-size="pageSize"
:pager-count="pagerCount"
#current-change="handleCurrentChange"
layout="prev, pager, next"
:total="displayHotelsNum">
</el-pagination>
</div>
</template>
<script>
// import { ref, computed } from 'vue';
import axios from 'axios';
export default {
data() {
return {
hotels: [],
page: 1,
pageSize: 5,
};
},
computed: {
...
},
mounted() {
axios.get('/api/fromSource')
.then((res) => {
this.hotels = res?.data?.outlets?.availability?.results;
});
},
methods: {
handleCurrentChange(pageNum) {
this.page = pageNum;
},
// Filter the data where the record does not have country and/or score
filteredHotels() {
...
},
},
};
</script>
Jest settings
module.exports = {
preset: '#vue/cli-plugin-unit-jest',
transform: {
'^.+\\.vue$': 'vue-jest',
},
};
Jest test file
import { mount } from '#vue/test-utils';
import { readFile } from 'fs/promises';
import rootPath from 'app-root-path';
import path from 'path';
import About from '../../src/views/About.vue';
/**
*
* The unit tests for About.vue.
*
*/
describe('About', () => {
it('has data', () => {
expect(typeof About.data).toBe('function');
});
});
describe('Mounted About', () => {
const wrapper = mount(About);
// afterEach(() => {
// wrapper.unmount();
// });
test('does a wrapper exist', () => {
...
});
// Check if the html page are correctly renderred
it('renders the correct table', () => {
...
});
it('renders correctly with different data', async () => {
const res = await readFile('./tests/utils/sample_data.json', 'utf8');
const hotelData = JSON.parse(res);
wrapper.setData({
hotels: [hotelData],
page: 1,
pageSize: 5,
});
// expect(1).toEqual(1);
);
}, 10000);
});
i'm new to test driven development and i'm trying to test certain api's but the the async code in my server just throwing errors and it really works but i dont know what happens
i have a code similar to this one exactly for my sequelize code , and this is my server code
require("dotenv").config();
const express = require("express");
const app = express();
const sequelize = require("./sequelize/index");
const cookieParser = require("cookie-parser");
const jwt = require("jsonwebtoken");
const taskRoutes = require("./routes/task");
const userRoutes = require("./routes/user");
const authRoutes = require("./routes/auth");
const {
catchErrors,
checkIfUserIsAuthenticated,
getUserAuthorization,
} = require("./middleware/index");
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use("/api/v1/auth", authRoutes);
app.use(checkIfUserIsAuthenticated);
app.use(getUserAuthorization);
app.use("/api/v1/task", taskRoutes);
app.use("/api/v1/user", userRoutes);
app.use(catchErrors);
module.exports = app;
and it works like charm , and in the index.js i'm making sure that the database connected successfully , in the 2 methods below the error arises in the test i've written and i don't know why
index.js:
const Sequelize = require("sequelize");
const { applyAssociation } = require("./associations");
require("dotenv").config();
const sequelize = new Sequelize(
process.env.DB_NAME,
process.env.DB_USERNAME,
process.env.DB_PASSWORD,
{
host: process.env.HOST,
dialect: "mysql",
logging: false,
}
);
const modelDefiners = [
require("./models/user"),
require("./models/role"),
require("./models/task"),
];
modelDefiners.map((modelDefiner) => {
modelDefiner(sequelize);
});
(async () => { ====>>>>>>> this one
try {
await sequelize.authenticate();
console.log("connected to the database successfully");
} catch (error) {
console.error(error);
}
})();
applyAssociation(sequelize);
(async () => { =========>>>>>> and this one
try {
await sequelize.sync({ alter: true });
console.log("synced correctly with the table");
} catch (error) {
console.log(error);
}
})();
module.exports = sequelize;
and this is my test : i know it's not well written but it's my first time writting it
const request = require("supertest");
const app = require("./server");
describe("user API", () => {
it("GET /user --> array of users", async () => {
await request(app)
.get("/api/v1/user/")
.expect("Content-Type", /json/)
.expect(200)
.then((response) => {
expect(response.body).toEqual(
expect.objectContaining({
status: "success",
response: expect.any(String),
})
);
});
});
// it("GET /task/id --> certain task", () => {});
// it("POST /task --> create task", () => {});
});
and this is the error that arises :
FAIL ./server.test.js
user API
✕ GET /user --> array of users (47 ms)
● user API › GET /user --> array of users
expected 200 "OK", got 403 "Forbidden"
7 | .get("/api/v1/user/")
8 | .expect("Content-Type", /json/)
> 9 | .expect(200)
| ^
10 | .then((response) => {
11 | expect(response.body).toEqual(
12 | expect.objectContaining({
at Object.expect (server.test.js:9:8)
----
at Test._assertStatus (node_modules/supertest/lib/test.js:252:14)
at node_modules/supertest/lib/test.js:306:17
at Test._assertFunction (node_modules/supertest/lib/test.js:285:13)
at Test.assert (node_modules/supertest/lib/test.js:164:23)
at Server.localAssert (node_modules/supertest/lib/test.js:120:14)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 0.94 s, estimated 1 s
Ran all test suites.
ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From server.test.js.
at ClientHandshake.handshakeResult (node_modules/mysql2/lib/commands/client_handshake.js:150:26)
at ClientHandshake.execute (node_modules/mysql2/lib/commands/command.js:45:22)
at Connection.handlePacket (node_modules/mysql2/lib/connection.js:456:32)
at PacketParser.onPacket (node_modules/mysql2/lib/connection.js:85:12)
at PacketParser.executeStart (node_modules/mysql2/lib/packet_parser.js:75:16)
console.error
ConnectionError [SequelizeConnectionError]: authSwitch.authSwitchRequest is not a function
at ConnectionManager.connect (/home/esraa/task/TodoApp/backend/node_modules/sequelize/src/dialects/mysql/connection-manager.js:126:17)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at ConnectionManager._connect (/home/esraa/task/TodoApp/backend/node_modules/sequelize/src/dialects/abstract/connection-manager.js:326:24)
at /home/esraa/task/TodoApp/backend/node_modules/sequelize/src/dialects/abstract/connection-manager.js:250:32 {
parent: TypeError: authSwitch.authSwitchRequest is not a function
at ClientHandshake.handshakeResult (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/commands/client_handshake.js:155:22)
at ClientHandshake.execute (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/commands/command.js:45:22)
at Connection.handlePacket (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:456:32)
at PacketParser.onPacket (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:85:12)
at PacketParser.executeStart (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket.<anonymous> (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:92:25)
at Socket.emit (node:events:527:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10) {
code: 'AUTH_SWITCH_PLUGIN_ERROR',
fatal: true
},
original: TypeError: authSwitch.authSwitchRequest is not a function
at ClientHandshake.handshakeResult (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/commands/client_handshake.js:155:22)
at ClientHandshake.execute (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/commands/command.js:45:22)
at Connection.handlePacket (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:456:32)
at PacketParser.onPacket (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:85:12)
at PacketParser.executeStart (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket.<anonymous> (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:92:25)
at Socket.emit (node:events:527:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10) {
code: 'AUTH_SWITCH_PLUGIN_ERROR',
fatal: true
}
}
22 | modelDefiners.map((modelDefiner) => {
23 | modelDefiner(sequelize);
> 24 | });
| ^
25 |
26 | (async () => {
27 | try {
at sequelize/index.js:24:13
● Cannot log after tests are done. Did you forget to wait for something async in your test?
Attempted to log "ConnectionError [SequelizeConnectionError]: authSwitch.authSwitchRequest is not a function
at ConnectionManager.connect (/home/esraa/task/TodoApp/backend/node_modules/sequelize/src/dialects/mysql/connection-manager.js:126:17)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at ConnectionManager._connect (/home/esraa/task/TodoApp/backend/node_modules/sequelize/src/dialects/abstract/connection-manager.js:326:24)
at /home/esraa/task/TodoApp/backend/node_modules/sequelize/src/dialects/abstract/connection-manager.js:250:32 {
parent: TypeError: authSwitch.authSwitchRequest is not a function
at ClientHandshake.handshakeResult (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/commands/client_handshake.js:155:22)
at ClientHandshake.execute (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/commands/command.js:45:22)
at Connection.handlePacket (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:456:32)
at PacketParser.onPacket (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:85:12)
at PacketParser.executeStart (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket.<anonymous> (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:92:25)
at Socket.emit (node:events:527:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10) {
code: 'AUTH_SWITCH_PLUGIN_ERROR',
fatal: true
},
original: TypeError: authSwitch.authSwitchRequest is not a function
at ClientHandshake.handshakeResult (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/commands/client_handshake.js:155:22)
at ClientHandshake.execute (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/commands/command.js:45:22)
at Connection.handlePacket (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:456:32)
at PacketParser.onPacket (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:85:12)
at PacketParser.executeStart (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket.<anonymous> (/home/esraa/task/TodoApp/backend/node_modules/mysql2/lib/connection.js:92:25)
at Socket.emit (node:events:527:28)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10) {
code: 'AUTH_SWITCH_PLUGIN_ERROR',
fatal: true
}
}".
35 | applyAssociation(sequelize);
36 |
> 37 | (async () => {
| ^
38 | try {
39 | await sequelize.sync({ alter: true });
40 | console.log("synced correctly with the table");
at ConnectionManager.connect (node_modules/sequelize/src/dialects/mysql/connection-manager.js:126:17)
at ConnectionManager._connect (node_modules/sequelize/src/dialects/abstract/connection-manager.js:326:24)
at node_modules/sequelize/src/dialects/abstract/connection-manager.js:250:32 {
parent: TypeError: authSwitch.authSwitchRequest is not a function
at ClientHandshake.handshakeResult (node_modules/mysql2/lib/commands/client_handshake.js:155:22)
at ClientHandshake.execute (node_modules/mysql2/lib/commands/command.js:45:22)
at Connection.handlePacket (node_modules/mysql2/lib/connection.js:456:32)
at PacketParser.onPacket (node_modules/mysql2/lib/connection.js:85:12)
at PacketParser.executeStart (node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket.<anonymous> (node_modules/mysql2/lib/connection.js:92:25)
at Socket.Readable.push (node:internal/streams/readable:228:10) {
code: 'AUTH_SWITCH_PLUGIN_ERROR',
fatal: true
},
original: TypeError: authSwitch.authSwitchRequest is not a function
at ClientHandshake.handshakeResult (node_modules/mysql2/lib/commands/client_handshake.js:155:22)
at ClientHandshake.execute (node_modules/mysql2/lib/commands/command.js:45:22)
at Connection.handlePacket (node_modules/mysql2/lib/connection.js:456:32)
at PacketParser.onPacket (node_modules/mysql2/lib/connection.js:85:12)
at PacketParser.executeStart (node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket.<anonymous> (node_modules/mysql2/lib/connection.js:92:25)
at Socket.Readable.push (node:internal/streams/readable:228:10) {
code: 'AUTH_SWITCH_PLUGIN_ERROR',
fatal: true
}
}".
at console.log (node_modules/#jest/console/build/CustomConsole.js:172:10)
at sequelize/index.js:37:13
It's an antipattern to have unchained promise that can't be awaited or handled. It's acceptable to have async IIFE, but primarily in main entry point with errors being handled.
This results in application server being unable to handle database requests within some time after it's started, and also in failed tests.
It can be initialization function instead of asynchronous side effects in sequelize/index.js:
exports.init = async () => {
// no catch, can run promises in parallel with Promise.all
await sequelize.authenticate();
...
}
Then it propagates to server.js:
exports.app = app;
exports.init = async () => {
await sequelize.init();
}
Then it's finally called in main entry point:
(async () => {
try {
await server.init();
server.app.listen(...);
} catch (error) {
console.error(error);
}
})()
And in tests:
beforeAll(async () => {
await server.init();
});
I am implementing unit testing in a project with Keystone but it always throws an error at testing:
an all test suites.
/Project/node_modules/mongodb/lib/mongo_client.js:433
throw err
^
TypeError: require(...) is not a function
at /Project/node_modules/keystone/lib/core/start.js:64:44
at /Project/node_modules/async/dist/async.js:3880:24
at eachOfArrayLike (/Project/node_modules/async/dist/async.js:1069:9)
at eachOf (/Project/node_modules/async/dist/async.js:1117:5)
at _parallel (/Project/node_modules/async/dist/async.js:3879:5)
at Object.parallelLimit [as parallel] (/Project/node_modules/async/dist/async.js:3962:5)
at /Project/node_modules/keystone/lib/core/start.js:60:9
at connected (/Project/node_modules/keystone/lib/core/openDatabaseConnection.js:78:5)
at NativeConnection.<anonymous> (/Project/node_modules/keystone/lib/core/openDatabaseConnection.js:85:4)
at Object.onceWrapper (events.js:273:13)
at NativeConnection.emit (events.js:182:13)
at /Project/node_modules/mongoose/lib/connection.js:860:13
at connectCallback (/Project/node_modules/mongodb/lib/mongo_client.js:527:5)
at /Project/node_modules/mongodb/lib/mongo_client.js:430:11
at process._tickCallback (internal/process/next_tick.js:61:11)
npm ERR! Test failed. See above for more details.
I already tried using "import { init, start, mongoose } from 'keystone';" instead, and using jest async() and await. I run too "jest --clearCache". Jest version: "jest": "^24.3.1"
My .babelrc:
{
"presets": [
["#babel/preset-env",
{"targets": {
"node": "current"
}}
],
"#babel/preset-react"
]
}
test.js:
const Keystone = require('keystone');
beforeAll( done => {
Keystone.init({
'name': 'Keystone CMS',
'cookie secret': 'My_Biscuit',
});
Keystone.start();
done();
})
describe('Test Keystone CMS own features', () => {
test('Keystone connects to MongoDB', (done) => {
expect(Keystone.mongoose.connections._listening).toBeTruthy;
done();
});
});
I will then expand it to test mongoose
It seems, that it is not really possible at the moment:
https://github.com/keystonejs/keystone/issues/3564
On OSX and Linux, the following works great (this is as simplified a reproduction as possible, hopefully without sacrificing meaning):
import { expect } from 'chai';
import { MongoClient, Db } from 'mongodb';
import { Application, Request } from 'express';
import { Server } from 'http';
import * as config from 'config';
describe('some test', () =>
{
let Session:{ new(app:Application):Request } = require('supertest-session'),
app:Application,
server:Server,
mongoClient:MongoClient,
db:Db;
beforeEach(async () =>
{
app = express();
server = app.listen(config.Http.port);
request = new Session(app);
// On Windows tests are executed before this resolves
mongoClient = await MongoClient.connect(config.Database.connectionOptions.url);
db = mongoClient.db(config.Database.connectionOptions.database);
});
afterEach(async () =>
{
await db.dropDatabase();
request.destroy();
server.close();
});
it('works like it oughtta', () =>
{
request.post('/api/account/login')
.send({ email: 'me#example.com', password: 'password' })
.expect(200)
.then((res) =>
{
expect(res.success).to.eq(true);
})
})
});
On a Windows machine, the above fails with the following output from npm:
13 verbose stack Exit status 4
13 verbose stack at EventEmitter.<anonymous> (C:\Path\To\AppData\Roaming\nvm\v9.4.0\node_modules\npm\node_modules\npm-lifecycle\lib\index.js:285:16)
... rest of stack
13 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:220:5)
If I take the database connection out of the beforeEach hook and do this instead, the test will run and pass, but I still notice hard-to-track-down failures in further tests with async hooks:
before(function(done)
{
MongoClient.connect(function(err, client)
{
mongoClient = client;
done();
});
});
after(function(done)
{
mongoClient.close(function() { done(); });
});
I've seen this behavior using Mocha, Jest and FuseBox test runners. Running node#9.4 on both machines. The solution to this cannot be "just make sure I test my tests on a Windows machine before I push".