4

I have a top-level await to load application secrets as follows:

// lib/config/secrets.ts
const secrets = await loadSecrets();
export default secrets;

I import this in other modules for db connection setup, etc:

// lib/db/index.ts
import { Pool } from "pg";
import secrets from "lib/config/secrets";

const pool = new Pool({
   connectionString: secrets.dbUrl,
   ...
});


This works fine when running my application via Webpack, but when running unit tests with jest, I get the following error: SyntaxError: await is only valid in async functions and the top level bodies of modules. I've been stuck on this for some time and have even considered other avenues to avoid the asynchronous secret loading altogether since I haven't found a solution. I've seen this similar question Jest won't accept top-level-awaits with NodeJS16 & TypeScript, but I'm not using ts-jest in my project. Is there anything obvious about my configuration that would cause this issue during tests, or is this just not supported?

My next.config.js to support top-level await via Webpack:

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  webpack: (config) => {
    config.experiments.topLevelAwait = true;
    return config;
  },
};

module.exports = nextConfig;

My jest.config.js:

const nextJest = require("next/jest");

const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir: "./",
});

// Add any custom config to be passed to Jest
const customJestConfig = {
  moduleDirectories: ["node_modules", "<rootDir>"],
  modulePaths: ["<rootDir>/lib"],
  //   setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
  moduleNameMapper: {
    // Handle module aliases (this will be automatically configured for you soon)
    "^components/(.*)$": "<rootDir>/components/$1",
    "^lib/(.*)$": "<rootDir>/lib/$1",
    "^pages/(.*)$": "<rootDir>/pages/$1",
  },
  testEnvironment: "jest-environment-jsdom",
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);

My package.json:

{
  "name": "app",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
     ...
  },
  "dependencies": {
    "@aws-sdk/client-secrets-manager": "^3.199.0",
    "@emotion/react": "^11.7.1",
    "@emotion/styled": "^11.6.0",
    "@mui/icons-material": "^5.3.1",
    "@mui/material": "^5.4.0",
    "install": "^0.13.0",
    "next": "^12.1.0",
    "next-auth": "^4.2.1",
    "npm": "^8.4.1",
    "pg": "^8.7.3",
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
  "devDependencies": {
    "@babel/core": "^7.17.5",
    "@babel/preset-env": "^7.16.11",
    "@babel/preset-typescript": "^7.16.7",
    "@types/aws-lambda": "^8.10.108",
    "@types/jest": "^27.4.1",
    "@types/node": "17.0.8",
    "@types/pg": "^8.6.5",
    "@types/react": "17.0.38",
    "@typescript-eslint/eslint-plugin": "^5.11.0",
    "@typescript-eslint/parser": "^5.11.0",
    "babel-jest": "^27.5.1",
    "esbuild": "^0.15.12",
    "eslint": "8.6.0",
    "eslint-config-next": "12.0.8",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.0.0",
    "eslint-plugin-simple-import-sort": "^7.0.0",
    "eslint-plugin-unused-imports": "^2.0.0",
    "jest": "^27.5.1",
    "prettier": "^2.6.2",
    "typescript": "4.5.4"
  }
}

My .babelrc:

{
  "presets": ["next/babel"],
  "plugins": []
}

My tsconfig.json:

{
  "compilerOptions": {
    "target": "esnext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "baseUrl": ".",
    "paths": {
      "components": ["components/"],
      "lib": ["lib/"],
      "sql": ["sql/"],
      "styles": ["styles/"]
    }
  },
  "include": ["types/*.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}
Update:

I tried adding "type":"module" to the package.json and updating the jest.config and next.config extensions to .cjs. It still produces the same error: SyntaxError: await is only valid in async functions and the top level bodies of modules.

Michael
  • 93
  • 1
  • 1
  • 8
  • 1
    Does this answer your question? [Jest won't accept top-level-awaits with NodeJS16 & TypeScript](https://stackoverflow.com/questions/70725063/jest-wont-accept-top-level-awaits-with-nodejs16-typescript) – gunwin Nov 02 '22 at 19:53
  • Hi @gunwin, I mention this same question in my description. I'm not using `ts-jest`. – Michael Nov 02 '22 at 20:25
  • 1
    Your package is not an es module so jest loads it as commonjs. This part `and the top level bodies of modules`. – morganney Nov 02 '22 at 23:00
  • Hi @morganney, I switched the package `type` to `module` and still get this error. Did you mean something else by switching to an es module? – Michael Nov 03 '22 at 14:31
  • I have the same issue, I do not use ts in my project. Did you manage to solve this? – J4v4Scr1pt Feb 27 '23 at 16:45

0 Answers0