Ошибка установки при установке @swc/jest внутри Angular 15 и Jest
В проектах Angular и Jest мы стремимся улучшить время отклика модульных тестов. Искал решения, все указывало на использование SWC внутри проекта, мы его уже реализовали, но при прохождении тестов получили ошибку в компонентах.
пакет.json
{
"name": "app-ui",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"postinstall": "ngcc && husky install",
"start": "ng serve --proxy-config proxy.conf.json",
"start:dev": "ng serve -o --live-reload --configuration development --proxy-config proxy.conf.json",
"start:local": "ng serve -o --live-reload --configuration development --proxy-config proxy.conf.local.json",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "jest --detect-open-handles",
"test1": "cross-env NODE_ENV=test jest --config ./jest.config.mjs",
"test2": "node --experimental-vm-modules --no-warnings ./node_modules/jest/bin/jest.js --config ./jest.config.mjs --ci --coverage",
"test:browser": "node --experimental-vm-modules --no-warnings ./node_modules/jest/bin/jest.js --config ./jest.config.mjs",
"test:watch": "jest --watch",
"test:coverage": "jest --ci --coverage",
"test:cc": "jest --ci --coverage --coverageReporters='text-summary'",
"test:pre": "jest --ci --coverage --coverageReporters='text-summary' --silent --detectOpenHandles",
"test:deploy": "jest --ci --coverage --detect-open-handles --forceExit",
"test:report": "allure serve allure-results/",
"eslint": "eslint -c .eslintrc.json --ext .ts src/ --ignore-pattern node_modules/ --fix",
"lint-report": "eslint -c .eslintrc.json --ext .ts src/ --ignore-pattern node_modules/ --fix -f node_modules/eslint-html-reporter/reporter.js -o report.html",
"format": "prettier --write \"src/**/*.{js,ts,css,json,html,scss}\" --config ./.prettierrc.json",
"sonar": "sonar-scanner",
"unused-css": "ngx-unused-css"
},
"private": true,
"type": "module",
"dependencies": {
"@angular/animations": "^15.1.1",
"@angular/cdk": "^15.1.1",
"@angular/common": "^15.1.1",
"@angular/compiler": "^15.1.1",
"@angular/core": "^15.1.1",
"@angular/forms": "^15.1.1",
"@angular/material": "^15.1.1",
"@angular/material-moment-adapter": "^15.1.1",
"@angular/platform-browser": "^15.1.1",
"@angular/platform-browser-dynamic": "^15.1.1",
"@angular/router": "^15.1.1",
"@azure/storage-blob": "^12.12.0",
"@ngx-translate/core": "^14.0.0",
"@ngx-translate/http-loader": "^7.0.0",
"@popperjs/core": "^2.11.6",
"@types/event-source-polyfill": "^1.0.1",
"angular-auth-oidc-client": "15.0.3",
"apexcharts": "^3.36.3",
"bootstrap": "^5.2.3",
"classlist.js": "^1.1.20150312",
"esbuild-wasm": "0.17.4",
"event-source-polyfill": "^1.0.31",
"moment": "^2.29.4",
"ng-apexcharts": "^1.7.4",
"ngx-material-timepicker": "^5.5.3",
"rxjs": "~7.8.0",
"tslib": "^2.4.1",
"web-animations-js": "^2.3.2",
"zone.js": "~0.12.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^15.1.2",
"@angular-eslint/builder": "15.2.0",
"@angular-eslint/eslint-plugin": "15.2.0",
"@angular-eslint/eslint-plugin-template": "15.2.0",
"@angular-eslint/schematics": "15.2.0",
"@angular-eslint/template-parser": "15.2.0",
"@angular/cli": "^15.1.2",
"@angular/compiler-cli": "^15.1.1",
"@babel/core": "^7.20.12",
"@babel/plugin-transform-typescript": "^7.20.13",
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.18.6",
"@briebug/jest-schematic": "^6.0.0",
"@jest/globals": "^29.4.0",
"@ngneat/spectator": "^14.0.0",
"@swc/cli": "^0.1.59",
"@swc/core": "^1.3.28",
"@swc/jest": "^0.2.24",
"@types/jest": "^29.4.0",
"@types/node": "^18.11.18",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/eslint-plugin-tslint": "^5.49.0",
"@typescript-eslint/parser": "5.49.0",
"@typescript-eslint/typescript-estree": "^5.49.0",
"allure-commandline": "^2.20.1",
"babel-core": "^6.26.3",
"babel-jest": "^29.4.0",
"babel-preset-jest": "^29.4.0",
"cross-env": "^7.0.3",
"cypress": "^12.4.0",
"esbuild": "^0.17.4",
"esbuild-jest": "^0.5.0",
"eslint": "^8.32.0",
"eslint-config-prettier": "^8.6.0",
"eslint-html-reporter": "^0.7.4",
"eslint-plugin-angular": "^4.1.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsdoc": "^39.6.8",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-sonarjs": "^0.18.0",
"husky": "^8.0.3",
"jest": "^29.4.0",
"jest-allure": "^0.1.3",
"jest-allure-image-snapshot": "^0.0.10",
"jest-browser": "^0.1.0",
"jest-css-modules-transform": "^4.4.2",
"jest-environment-jsdom": "^29.4.0",
"jest-jasmine2": "^29.4.0",
"jest-junit-reporter": "^1.1.0",
"jest-preset-angular": "^12.2.5",
"jest-raw-loader": "^1.0.1",
"lint-staged": "^13.1.0",
"ngx-unused-css": "^4.0.0-1",
"prettier": "^2.8.3",
"prettier-eslint": "^15.0.1",
"sonar-scanner": "^3.1.0",
"ts-jest": "^29.0.5",
"ts-node": "^10.9.1",
"tslint": "^6.1.3",
"tslint-angular": "^3.0.3",
"typescript": "~4.8.4"
},
"prettier": {
"printWidth": 150,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"arrowParens": "always",
"proseWrap": "preserve",
"htmlWhitespaceSensitivity": "css",
"endOfLine": "auto",
"quoteProps": "consistent",
"overrides": [
{
"files": [
"**/*.css",
"**/*.scss",
"**/*.html"
],
"options": {
"singleQuote": false
}
}
]
},
"lint-staged": {
"src/**/*.{js,ts,scss,md,html,json}": [
"prettier --write",
"git add"
],
"src/**/*.{js,ts}": [
"npm run eslint",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"pre-push": "npm run eslint && ng build --aot true"
}
}
}
.swcrc
{
"test": ".*.ts$",
"jsc": {
"target": "es2022",
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": false,
"dynamicImport": false
},
"externalHelpers": true
},
"module": {
"type": "commonjs"
},
"sourceMaps": true
}
tsconfig.spec.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": ["jest","node"],
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,
"module": "CommonJs",
"moduleResolution": "node",
"target": "ES2022",
"sourceMap": true,
"inlineSources": true,
"inlineSourceMap": true,
"paths": {
"@shared/*": ["./src/app/shared/*"],
"@services/*": ["./src/app/services/*"],
"@utils/*": ["./src/app/utils/*"],
"@pages/*": ["./src/app/pages/*"],
"@global/*": ["./src/app/global/*"],
"@guards/*": ["./src/app/guards/*"],
"@auth/*": ["./src/app/auth/*"],
"@mock/*": ["./src/mock/*"],
"@helpers/*": ["./src/helpers/*"],
"@pipes/*": ["./src/app/pipes/*"],
"@directives/*": ["./src/app/directives/*"],
"@constants/*": ["./src/app/constants/*"],
"@interceptors/*": ["./src/app/interceptors/*"]
}
},
"include": ["src/**/*.spec.ts","src/**/*.d.ts"]
}
jest.config.mjs
const esModules = ['@angular'].join('|');
export default {
collectCoverage: true,
testRunner: 'jest-jasmine2',
coverageReporters: ['json', 'lcov', 'html'],
collectCoverageFrom: [
'src/**/*.{js,ts}',
'!src/**/*.module.{js,ts}',
'!src/**/*-routing.module.{js,ts}',
'!src/**/index.{js,ts}',
'!src/**/main.{js,ts}',
'!src/**/polyfills.{js,ts}',
'!src/**/vendor.{js,ts}'
],
extensionsToTreatAsEsm: ['.ts', '.tsx'],
testEnvironment: 'jsdom',
globalSetup: 'jest-preset-angular/global-setup.mjs',
timers: 'fake',
setupFilesAfterEnv: ['<rootDir>/setup-jest.mjs', 'jest-allure/dist/setup'],
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
isolatedModules: true,
stringifyContentPathRegex: '\\.(html|svg)$',
allowSyntheticDefaultImports: true,
useESM: true
}
},
roots: ['<rootDir>/src'],
transformIgnorePatterns: [`/node_modules/(?!${esModules})`],
moduleNameMapper: {
'tslib': 'tslib/tslib.es6.js',
'^rxjs$': '<rootDir>/node_modules/rxjs/dist/bundles/rxjs.umd.js',
'^rxjs/operators$': '<rootDir>/node_modules/rxjs/dist/bundles/rxjs.umd.js',
'^rxjs/testing$': '<rootDir>/node_modules/rxjs/dist/cjs/testing/index.js',
'^rxjs/webSocket$': '<rootDir>/node_modules/rxjs/dist/cjs/webSocket/index.js',
'^rxjs/ajax$': '<rootDir>/node_modules/rxjs/dist/cjs/ajax/index.js',
'@angular/core/testing': '<rootDir>/node_modules/@angular/core/fesm2020/testing.mjs',
'@angular/platform-browser/testing': '<rootDir>/node_modules/@angular/platform-browser/fesm2020/testing.mjs',
'@angular/platform-browser-dynamic/testing': '<rootDir>/node_modules/@angular/platform-browser-dynamic/fesm2020/testing.mjs',
'^app/(.*)$': '<rootDir>/src/app/$1',
'^assets/(.*)$': '<rootDir>/src/assets/$1',
'^environments/(.*)$': '<rootDir>/src/environments/$1',
'^@shared/(.*)$': '<rootDir>/src/app/shared/$1',
'^@constants/(.*)$': '<rootDir>/src/app/constants/$1',
'^@services/(.*)$': '<rootDir>/src/app/services/$1',
'^@utils/(.*)$': '<rootDir>/src/app/utils/$1',
'^@pages/(.*)$': '<rootDir>/src/app/pages/$1',
'^@global/(.*)$': '<rootDir>/src/app/global/$1',
'^@guards/(.*)$': '<rootDir>/src/app/guards/$1',
'^@mock/(.*)$': '<rootDir>/src/mock/$1',
'^@helpers/(.*)$': '<rootDir>/src/helpers/$1',
'^@pipes/(.*)$': '<rootDir>/src/app/pipes/$1',
'^@directives/(.*)$': '<rootDir>/src/app/directives/$1',
'^@auth/(.*)$': '<rootDir>/src/app/auth/$1',
'^@interceptors/(.*)$': '<rootDir>/src/app/interceptors/$1'
},
transform: {
'^.+\\.[tj]s?$': [
'@swc/jest',
{
jsc: {
target: 'es2022'
},
sourceMaps: true
}
]
},
maxWorkers: '8'
};
Результат:
Test Suites: 206 failed, 1 passed, 207 total
Tests: 5 passed, 5 total
Snapshots: 0 total
Time: 31.545 s
Ran all test suites.
Результат app.component
FAIL src/app/app.component.spec.ts
● Test suite failed to run
x Expression expected
,-[C:\Users\xxxxxxxx\src\app\app.component.ts:6:1]
6 | import { Subscription } from 'rxjs';
7 | import { SidebarService } from '@services/sidebar/sidebar.service';
8 |
9 | @Component({
: ^
10 | selector: 'app-root',
11 | templateUrl: './app.component.html',
11 | styleUrls: ['./app.component.scss'],
`----
Caused by:
Syntax Error
,-[C:\Users\xxxxxxxx\src\app\app.component.ts:6:1]
6 | import { Subscription } from 'rxjs';
7 | import { SidebarService } from '@services/sidebar/sidebar.service';
8 |
9 | @Component({
: ^
10 | selector: 'app-root',
11 | templateUrl: './app.component.html',
11 | styleUrls: ['./app.component.scss'],
`----
Caused by:
Syntax Error
другие результаты
FAIL src/app/pipes/numbercomparatorpipe.pipe.spec.ts
● Test suite failed to run
x Expression expected
,-[C:\Users\XXXXXXXX\src\app\pipes\numbercomparatorpipe.pipe.ts:1:1]
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({
: ^
4 | name: 'comparatorpipe'
5 | })
5 | export class NumberComparatorPipe implements PipeTransform {
`----
Caused by:
Syntax Error
,-[C:\Users\XXXXXXXX\src\app\pipes\numbercomparatorpipe.pipe.ts:1:1]
1 | import { Pipe, PipeTransform } from '@angular/core';
2 |
3 | @Pipe({
: ^
4 | name: 'comparatorpipe'
5 | })
5 | export class NumberComparatorPipe implements PipeTransform {
`----
Caused by:
Syntax Error
FAIL src/app/interceptors/login/NotEmployees.interceptor.spec.ts
● Test suite failed to run
x Expression expected
,-[C:\Users\XXXXXXXX\src\app\interceptors\login\NotEmployees.interceptor.ts:6:1]
6 | import { TranslateService } from '@ngx-translate/core';
7 | import { OidcSecurityService } from 'angular-auth-oidc-client';
8 | import { UserApiService } from '@services/api/user-api/user-api.service';
9 | @Injectable()
: ^
10 | export class NotEmployees implements HttpInterceptor {
11 | size: string;
11 |
`----
Caused by:
Syntax Error
,-[C:\Users\XXXXXXXX\src\app\interceptors\login\NotEmployees.interceptor.ts:6:1]
6 | import { TranslateService } from '@ngx-translate/core';
7 | import { OidcSecurityService } from 'angular-auth-oidc-client';
8 | import { UserApiService } from '@services/api/user-api/user-api.service';
9 | @Injectable()
: ^
10 | export class NotEmployees implements HttpInterceptor {
11 | size: string;
11 |
`----
Caused by:
Syntax Error
FAIL src/app/pipes/form-control-pipe.pipe.spec.ts
● Test suite failed to run
x Expression expected
,-[C:\Users\XXXXXXXX\src\app\pipes\form-control-pipe.pipe.ts:1:1]
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import { AbstractControl, UntypedFormControl } from '@angular/forms';
3 |
4 | @Pipe({
: ^
5 | name: 'formControlPipe'
6 | })
6 | export class FormControlPipe implements PipeTransform {
`----
Caused by:
Syntax Error
,-[C:\Users\XXXXXXXX\src\app\pipes\form-control-pipe.pipe.ts:1:1]
1 | import { Pipe, PipeTransform } from '@angular/core';
2 | import { AbstractControl, UntypedFormControl } from '@angular/forms';
3 |
4 | @Pipe({
: ^
5 | name: 'formControlPipe'
6 | })
6 | export class FormControlPipe implements PipeTransform {
`----
Caused by:
Syntax Error
Я уже пытался внедрить babelvs esbuild, и оба выдают похожие ошибки, поэтому я не думаю, что это библиотека, а что-то в шутливой или угловой конфигурации.