Search code examples
typescriptjestjsts-jesttsconfig

top level await with jest and typescript


I'm running npx jest test

Getting this error, no matter how I change my configuration:

error TS1378: Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', 'node16', or 'nodenext', and the 'target' option is set to 'es2017' or higher.

tsconfig

{
  "ts-node": { "esm": true },
  "compilerOptions": {
    "target": "ESNext",
    "module": "NodeNext",
    "allowImportingTsExtensions": true,
    "moduleResolution": "NodeNext",
    "noEmit": true,
    "esModuleInterop": true,
    "strict": true
  }
}

jest.config.json

{ "preset": "ts-jest/presets/default-esm" }

package.json


{
  "name": "my-app,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "node --loader ts-node/esm src/index.ts",
    "test": "jest test"
  },
  "dependencies": {
   ...
  },
  "types": "./src/index.d.ts",
  "devDependencies": {
    "@babel/preset-env": "^7.23.2",
    "@types/jest": "^29.5.7",
    "eslint": "^8.52.0",
    "eslint-config-prettier": "^9.0.0",
    "eslint-plugin-jest": "^27.6.0",
    "eslint-plugin-sort-imports-es6-autofix": "^0.6.0",
    "eslint-plugin-unused-imports": "^3.0.0",
    "jest": "^29.7.0",
    "ts-jest": "^29.1.1",
    "ts-node": "^10.9.1",
    "typescript": "^5.2.2"
  }
}

Solution

  • It was easier to just write my own testing framework

    import chalk from "chalk";
    import { expect, JestAssertionError } from "expect";
    
    const testFilter = () =>
      /--filter[=\s]([^-]*\S)/g
        .exec(process.argv.join(" "))?.[1]
        .toLocaleLowerCase();
    
    export const testAll =
      <T>(
        f: (tc: T) => any, // eslint-disable-line @typescript-eslint/no-explicit-any
      ) =>
      async (cases: T[]) => {
        for (const testCase of cases) {
          const testFilterPhrase = testFilter();
          if (
            testFilterPhrase &&
            !JSON.stringify(testCase).toLocaleLowerCase().includes(testFilterPhrase)
          )
            continue;
          if (testFilterPhrase) console.log("running test", testCase);
          try {
            await f(testCase);
          } catch (e) {
            console.log(chalk.red(`Failed case ${JSON.stringify(testCase)}`));
            if (e) console.log((e as JestAssertionError).message);
          }
        }
      };
    
    export const testFn = <F extends Func>(f: F) =>
      testAll(async ([input, expected]: [Parameters<F>, Awaited<ReturnType<F>>]) =>
        expect(await f(...input)).toEqual(expected),
      );
    
    export const testUnaryFn = <F extends Unary>(f: F) =>
      testAll(
        async ([input, expected]: [Parameters<F>[0], Awaited<ReturnType<F>>]) =>
          expect(await f(input)).toEqual(expected),
      );
    

    Usage:

    testUnaryFn((x) => x * 3)([
      [1, 3],
      [3, 9],
    ]);
    
    

    And you can even --filter 9 to filter one test