angularjestjsts-jestangular-testangular-testing-library

Angular 14 + Jest - typescript_1.default.canHaveDecorators is not a function


After configuring Jest with Angular 14, I'm getting this error: Test suite failed to run

TypeError: typescript_1.default.canHaveDecorators is not a function

  at TypeScriptReflectionHost.getDecoratorsOfDeclaration (node_modules/jest-preset-angular/build/ngtsc/reflection/src/typescript.js:14:49)
  at visitNodes (node_modules/typescript/lib/typescript.js:87646:48)
  at visitLexicalEnvironment (node_modules/typescript/lib/typescript.js:87686:22)
  at Object.visitEachChild (node_modules/typescript/lib/typescript.js:88234:55)
  at transformSourceFileOrBundle (node_modules/typescript/lib/typescript.js:88930:57)
  at transformation (node_modules/typescript/lib/typescript.js:107888:24)

The Jest configuration is:

import type { Config } from 'jest';

const jestConfig: Config = {
    preset: 'jest-preset-angular',
    verbose: true,
    setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
    globalSetup: 'jest-preset-angular/global-setup',

    resolver: 'jest-preset-angular/build/resolvers/ng-jest-resolver.js',
     transformIgnorePatterns: ['node_modules/(?!@angular)'],
     transform: {
        '^.+\\.(ts|js|mjs|html|svg)$': 'jest-preset-angular',
     },

     
    globals: {
      'ts-jest': {
        useESM: true,
        tsconfig: '<rootDir>/tsconfig.spec.json',
        stringifyContentPathRegex: '\\.(html|svg)$'
      }
    },
    coverageDirectory: 'coverage',
    testResultsProcessor: 'jest-sonar-reporter',
    snapshotSerializers: [
      'jest-preset-angular/build/serializers/no-ng-attributes',
      'jest-preset-angular/build/serializers/ng-snapshot',
      'jest-preset-angular/build/serializers/html-comment'
    ]
};

export default jestConfig;

Where in setup-jest.ts we have:

import 'jest-preset-angular/setup-jest';

And package.json:

 "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build --configuration production",
    "watch": "ng build --watch --configuration development",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:ci": "jest --runInBand"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^14.2.12",
    "@angular/cdk": "^14.2.7",
    "@angular/common": "^14.2.12",
    "@angular/compiler": "^14.2.12",
    "@angular/core": "^14.2.12",
    "@angular/forms": "^14.2.12",
    "@angular/localize": "^14.2.12",
    "@angular/material": "^14.2.7",
    "@angular/platform-browser": "^14.2.12",
    "@angular/platform-browser-dynamic": "^14.2.12",
    "@angular/router": "^14.2.12",
    "rxjs": "~7.5.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-builders/custom-webpack": "^14.1.0",
    "@angular-devkit/build-angular": "^14.2.10",
    "@angular/cli": "^14.2.10",
    "@angular/compiler-cli": "^14.2.12",
    "@types/jest": "^29.2.5",
    "@types/mustache": "^4.1.3",
    "@types/node": "^12.11.1",
    "jest": "^28.1.3",
    "jest-environment-jsdom": "^29.3.1",
    "jest-preset-angular": "^12.2.4",
    "jest-sonar-reporter": "^2.0.0",
    "mustache": "^4.2.0",
    "prettier": "^2.7.1",
    "ts-jest": "^29.0.5",
    "ts-node": "^10.9.1",
    "typescript": "~4.6.2"
  }

Also, tsconfig.spec.ts is configured properly:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/spec",
    "module": "CommonJs",
    "types": ["jest", "node"]
  },
  "files": [
    "src/polyfills.ts",
    "setup-jest.ts"
  ],
  "include": [
    "jest.config.ts",
    "src/**/*.spec.ts",
    "src/**/*.d.ts"
  ]
}

And tsconfig.json contains esModuleInterop:

/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./src",
    "outDir": "./dist/out-tsc",
    "forceConsistentCasingInFileNames": false,
    "strict": false,
    "noImplicitOverride": false,
    "noPropertyAccessFromIndexSignature": false,
    "noImplicitReturns": false,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2020",
    "module": "es2020",
    "lib": ["es2020", "dom"],
    "esModuleInterop": true
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": false,
    "strictInputAccessModifiers": false,
    "strictTemplates": false
  }
}

I tried installing Jest following the official guide, Karma + Jasmine were also removed.

Did anyone encounter this ? What am I missing here ?


Solution

  • I finally made it work. The fix was a typescript version upgrade from 4.6.2 to 4.8.2