I'm trying to use a top level await during testing with Jest but Jest complains that
error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher.
Here's the file (src/lib/mongodb.ts
)which is problematic:
import { MongoClient } from 'mongodb';
import mongoUri from 'mongo-uri-tool';
import { getMongoURI } from './settings/settings.js';
const getConnectionOptions = () => {
const uri = getMongoURI();
return {
uri,
parsedUri: mongoUri.parseUri(uri),
};
};
const connectToMongoDB = async () => {
const connectionOptions = getConnectionOptions();
const mongodb = await MongoClient.connect(connectionOptions.uri);
return mongodb.db(connectionOptions.parsedUri.db);
};
export const MongoDB = await connectToMongoDB();
Here's the test (src/api/trips/trips.test.ts
) file which is ultimately import the above:
import { Trips } from './index'; // <--------- this is the import which leads to importing mongodb
import generateId from '../../lib/generateId';
describe('find trip by id', () => {
test('find trip by id', async () => {
const id = generateId();
const slug = 'lol';
await Trips.insertOne({ _id: id, slug });
const trip = await Trips.findOne({ _id: id });
expect(trip._id).toStrictEqual(id);
});
});
When I run npx tsc
no problems are reported:
11:12AM /Users/paymahn/code/tripvector/tripvector-mono/backend testing ✭ ✱ ➜ ◼
❮❮❮ npx tsc
11:12AM /Users/paymahn/code/tripvector/tripvector-mono/backend testing ✭ ✱ ➜ ◼
Here's my tsconfig.json
which has the correct module
and target
:
{
"compilerOptions": {
"sourceMap": true,
"esModuleInterop": true,
"allowJs": true,
"noImplicitAny": true,
"moduleResolution": "node",
"lib": ["es2022", "DOM"],
"module": "es2022",
"target": "es2017",
"rootDir": "src",
"baseUrl": ".",
"paths": {
"*": ["node_modules/*", "src/types/*"]
},
"types": ["node", "jest"],
"typeRoots": ["node_modules/@types", "src/types"],
"outDir": "./built"
},
"include": ["./src/**/*", "jest.config.js"],
"exclude": ["node_modules", "dist"]
}
and here's my jest.config.cjs
:
const { jsWithTsESM: tsjPreset } = require("ts-jest/presets");
module.exports = {
...tsjPreset,
globals: {
"ts-jest": {
tsconfig: "tsconfig.json",
}
},
testEnvironment: 'node',
moduleFileExtensions: ["ts", "js"],
testRegex: ".*.test.ts"
};
Here's my project structure:
Why is it that Jest and ts-jest complain that I can't use a top-level await but tsc
and my IDE (Webstorm) don't complain at all? How can I correctly configure Jest and ts-jest to allow top level awaits with ESM for both JS and TS files (I'm slowly migrating from JS to TS)?
Note that Jest was working great until I added the first test which relies on a top level await. It seems I have Jest and ts-jest correctly configured to work with ESM and a mix of JS and TS files. The new problem is figuring out top level awaits with ts-jest.
EDIT: if I add @ts-ignore
to the problematic top level await, I get another similar issue reported by Jest:
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
export const MongoDB = await connectToMongoDB();
Details:
/Users/paymahn/code/tripvector/tripvector-mono/backend/src/lib/mongodb.ts:24
exports.MongoDB = await connectToMongoDB();
^^^^^
SyntaxError: await is only valid in async functions and the top level bodies of modules
Could this be an issue of which version of node I'm using? I'm currently using v17:
11:53AM /Users/paymahn/code/tripvector/tripvector-mono/backend testing ✭ ✱ ➜ ◼
❯❯❯ node --version
v17.6.0
11:53AM /Users/paymahn/code/tripvector/tripvector-mono/backend testing ✭ ✱ ➜ ◼
❯❯❯ npm --version
7.6.0
EDIT: interesting, I migrated to mocha and executing mocha with -n loader=ts-node/esm
works perfectly. I wonder what's going on with jest...