在 Angular 14 + Ionic 6 项目中设置 Jest

Nei*_*l89 5 unit-testing typescript ionic-framework angular ts-jest

我正在尝试将 Jest 测试框架设置到我的项目中,该项目使用 Angular 14 和 Ionic 6,以及其他可能存在冲突的插件,例如 firebase 和 ngrx。

\n

我一直主要关注Tim Deschryver 教程和其他一些教程,甚至从堆栈溢出中复制和粘贴一些关于我的 Jest 测试错误的代码,但没有任何效果。即使我尝试重新开始删除所有软件包和修改并重新开始,但没有运气。

\n

我在这里有更新的存储库https://github.com/neil89/igloo(它非常易于管理)。但总的来说,我的主要修改是这些:

\n

包.json

\n
{\n  "name": "igloo",\n  "version": "0.0.1",\n  "author": "Ionic Framework",\n  "homepage": "https://ionicframework.com/",\n  "scripts": {\n    "ng": "ng",\n    "start": "ng serve",\n    "build": "ng build",\n    "test": "jest",\n    "lint": "ng lint",\n    "e2e": "ng e2e"\n  },\n  "private": true,\n  "dependencies": {\n    "@angular/common": "^14.0.0",\n    "@angular/core": "^14.0.0",\n    "@angular/fire": "^7.4.1",\n    "@angular/forms": "^14.0.0",\n    "@angular/platform-browser": "^14.0.0",\n    "@angular/platform-browser-dynamic": "^14.0.0",\n    "@angular/router": "^14.0.0",\n    "@briebug/jest": "^1.3.1",\n    "@ionic/angular": "^6.2.6",\n    "@ngrx/effects": "^14.3.1",\n    "@ngrx/store": "^14.3.1",\n    "firebase": "^9.9.4",\n    "rxjs": "~6.6.0",\n    "tslib": "^2.2.0",\n    "zone.js": "~0.11.4"\n  },\n  "devDependencies": {\n    "@angular-devkit/build-angular": "^14.0.0",\n    "@angular-eslint/builder": "~13.0.1",\n    "@angular-eslint/eslint-plugin": "~13.0.1",\n    "@angular-eslint/eslint-plugin-template": "~13.0.1",\n    "@angular-eslint/template-parser": "~13.0.1",\n    "@angular/cli": "^14.0.0",\n    "@angular/compiler": "^14.0.0",\n    "@angular/compiler-cli": "^14.0.0",\n    "@angular/language-service": "^14.0.0",\n    "@types/jest": "^29.0.1",\n    "@types/node": "^12.11.1",\n    "@typescript-eslint/eslint-plugin": "5.3.0",\n    "@typescript-eslint/parser": "5.3.0",\n    "eslint": "^7.6.0",\n    "eslint-plugin-import": "2.22.1",\n    "eslint-plugin-jsdoc": "30.7.6",\n    "eslint-plugin-prefer-arrow": "1.2.2",\n    "jest": "^28.1.3",\n    "jest-preset-angular": "^12.2.2",\n    "protractor": "~7.0.0",\n    "ts-node": "~8.3.0",\n    "typescript": "~4.7.3"\n  },\n  "jest": {\n    "preset": "jest-preset-angular",\n    "setupFilesAfterEnv": [\n      "<rootDir>/src/setupJest.ts"\n    ],\n    "globalSetup": "jest-preset-angular/global-setup"\n  },\n  "description": "An Ionic project"\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

笑话配置.js

\n
/** @type {import(\'ts-jest/dist/types\').InitialOptionsTsJest} */\nmodule.exports = {\n  globals: {\n    \'ts-jest\': {\n      tsconfig: \'tsconfig.spec.json\',\n      isolatedModules: true,\n    },\n  },\n  moduleNameMapper: {\n    \'@angular/compiler-cli/ngcc\': \'<rootDir>/node_modules/@angular/compiler-cli/bundles/ngcc/main-ngcc.js\',\n  },\n  testEnvironment: \'jsdom\',\n  modulePathIgnorePatterns: [\'examples/.*\', \'website/.*\'],\n  snapshotSerializers: [require.resolve(\'jest-snapshot-serializer-raw\')],\n  testPathIgnorePatterns: [\'/node_modules/\', \'/examples/\', \'/e2e/.*/__tests__\', \'\\\\.snap$\'],\n  transform: {\n    \'^.+\\\\.(ts|js|mjs|html)$\': \'<rootDir>/build/index.js\',\n  },\n  transformIgnorePatterns: [\'node_modules/(?!(jest-test|@ngrx))\'],\n};\n
Run Code Online (Sandbox Code Playgroud)\n

setupJest.ts

\n
import \'jest-preset-angular\';\n
Run Code Online (Sandbox Code Playgroud)\n

我的一个更简单的失败测试:\n app.component.spec.ts

\n
import { TestBed } from \'@angular/core/testing\';\nimport { RouterTestingModule } from \'@angular/router/testing\';\nimport { AppComponent } from \'./app.component\';\n\ndescribe(\'AppComponent\', () => {\n\n  beforeEach(async () => {\n    await TestBed.configureTestingModule({\n      declarations: [\n        AppComponent\n      ],\n      imports: [\n        RouterTestingModule.withRoutes([])\n      ],\n    }).compileComponents();\n  });\n\n  it(\'should create the app\', (() => {\n    const fixture = TestBed.createComponent(AppComponent);\n    const app = fixture.debugElement.componentInstance;\n    expect(app).toBeTruthy();\n  }));\n\n  it(\'should have menu labels\', (() => {\n    const fixture = TestBed.createComponent(AppComponent);\n    fixture.detectChanges();\n    const app = fixture.nativeElement;\n    const menuItems = app.querySelectorAll(\'ion-label\');\n    expect(menuItems.length).toEqual(7);\n    expect(menuItems[0].textContent).toContain(\'Inbox\');\n    expect(menuItems[1].textContent).toContain(\'Outbox\');\n  }));\n\n  it(\'should have urls\', () => {\n    const fixture = TestBed.createComponent(AppComponent);\n    fixture.detectChanges();\n    const app = fixture.nativeElement;\n    const menuItems = app.querySelectorAll(\'ion-item\');\n    expect(menuItems.length).toEqual(7);\n    expect(menuItems[0].getAttribute(\'ng-reflect-router-link\')).toEqual(\'/folder/Inbox\');\n    expect(menuItems[1].getAttribute(\'ng-reflect-router-link\')).toEqual(\'/folder/Outbox\');\n  });\n\n});\n
Run Code Online (Sandbox Code Playgroud)\n

现在,我运行时的输出npm test如下:

\n
> igloo@0.0.1 test\n> jest\n\nDetermining test suites to run...\nngcc-jest-processor: running ngcc\n FAIL  src/app/fridge/fridge.service.spec.ts\n  \xe2\x97\x8f Test suite failed to run\n\n    Jest encountered an unexpected token\n\n    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.\n\n    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.\n\n    By default "node_modules" folder is ignored by transformers.\n\n    Here\'s what you can do:\n     \xe2\x80\xa2 If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.\n     \xe2\x80\xa2 If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript\n     \xe2\x80\xa2 To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.\n     \xe2\x80\xa2 If you need a custom transformation specify a "transform" option in your config.\n     \xe2\x80\xa2 If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.\n\n    You\'ll find more details and examples of these config options in the docs:\n    https://jestjs.io/docs/configuration\n    For information about custom transformations, see:\n    https://jestjs.io/docs/code-transformation\n\n    Details:\n\n    /Users/daniel.rodriguez/Documents/Personal/iGloo/igloo/node_modules/firebase/app/dist/index.esm.js:1\n    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { registerVersion } from \'@firebase/app\';\n                                                                                      ^^^^^^\n\n    SyntaxError: Cannot use import statement outside a module\n\n      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)\n      at node_modules/@angular/fire/bundles/angular-fire.umd.js:2:111\n      at Object.<anonymous> (node_modules/@angular/fire/bundles/angular-fire.umd.js:5:2)\n\n FAIL  src/app/fridge/fridge.component.spec.ts\n  \xe2\x97\x8f Test suite failed to run\n\n    Jest encountered an unexpected token\n\n    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.\n\n    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.\n\n    By default "node_modules" folder is ignored by transformers.\n\n    Here\'s what you can do:\n     \xe2\x80\xa2 If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.\n     \xe2\x80\xa2 If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript\n     \xe2\x80\xa2 To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.\n     \xe2\x80\xa2 If you need a custom transformation specify a "transform" option in your config.\n     \xe2\x80\xa2 If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.\n\n    You\'ll find more details and examples of these config options in the docs:\n    https://jestjs.io/docs/configuration\n    For information about custom transformations, see:\n    https://jestjs.io/docs/code-transformation\n\n    Details:\n\n    /Users/daniel.rodriguez/Documents/Personal/iGloo/igloo/node_modules/firebase/app/dist/index.esm.js:1\n    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { registerVersion } from \'@firebase/app\';\n                                                                                      ^^^^^^\n\n    SyntaxError: Cannot use import statement outside a module\n\n      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1796:14)\n      at node_modules/@angular/fire/bundles/angular-fire.umd.js:2:111\n      at Object.<anonymous> (node_modules/@angular/fire/bundles/angular-fire.umd.js:5:2)\n\n FAIL  src/app/folder/folder.page.spec.ts\n  \xe2\x97\x8f FolderPage \xe2\x80\xba should create\n\n    Need to call TestBed.initTestEnvironment() first\n\n       9 |\n      10 |   beforeEach(async () => {\n    > 11 |     await TestBed.configureTestingModule({\n         |                   ^\n      12 |       declarations: [ FolderPage ],\n      13 |       imports: [IonicModule.forRoot(), RouterModule.forRoot([])]\n      14 |     }).compileComponents();\n\n      at TestBedRender3.get compiler [as compiler] (node_modules/@angular/core/fesm2020/testing.mjs:26367:19)\n      at TestBedRender3.configureTestingModule (node_modules/@angular/core/fesm2020/testing.mjs:26290:14)\n      at Function.configureTestingModule (node_modules/@angular/core/fesm2020/testing.mjs:26126:30)\n      at src/app/folder/folder.page.spec.ts:11:19\n      at node_modules/tslib/tslib.js:118:75\n      at Object.__awaiter (node_modules/tslib/tslib.js:114:16)\n      at Object.<anonymous> (src/app/folder/folder.page.spec.ts:10:25)\n\n  \xe2\x97\x8f FolderPage \xe2\x80\xba should create\n\n    zone-testing.js is needed for the fakeAsync() test helper but could not be found.\n            Please make sure that your environment includes zone.js/testing\n\n      at resetFakeAsyncZone (node_modules/@angular/core/fesm2020/testing.mjs:273:11)\n      at Object.<anonymous> (node_modules/@angular/core/fesm2020/testing.mjs:26603:13)\n\n FAIL  src/app/app.component.spec.ts\n  \xe2\x97\x8f AppComponent \xe2\x80\xba should create the app\n\n    Need to call TestBed.initTestEnvironment() first\n\n       7 |\n       8 |   beforeEach(async () => {\n    >  9 |     await TestBed.configureTestingModule({\n         |                   ^\n      10 |       declarations: [\n      11 |         AppComponent\n      12 |       ],\n\n      at TestBedRender3.get compiler [as compiler] (node_modules/@angular/core/fesm2020/testing.mjs:26367:19)\n      at TestBedRender3.configureTestingModule (node_modules/@angular/core/fesm2020/testing.mjs:26290:14)\n      at Function.configureTestingModule (node_modules/@angular/core/fesm2020/testing.mjs:26126:30)\n      at src/app/app.component.spec.ts:9:19\n      at node_modules/tslib/tslib.js:118:75\n      at Object.__awaiter (node_modules/tslib/tslib.js:114:16)\n      at Object.<anonymous> (src/app/app.component.spec.ts:8:25)\n\n  \xe2\x97\x8f AppComponent \xe2\x80\xba should create the app\n\n    zone-testing.js is needed for the fakeAsync() test helper but could not be found.\n            Please make sure that your environment includes zone.js/testing\n\n      at resetFakeAsyncZone (node_modules/@angular/core/fesm2020/testing.mjs:273:11)\n      at Object.<anonymous> (node_modules/@angular/core/fesm2020/testing.mjs:26603:13)\n\n  \xe2\x97\x8f AppComponent \xe2\x80\xba should have menu labels\n\n    NG0908: In this configuration Angular requires Zone.js\n\n      25 |\n      26 |   it(\'should have menu labels\', (() => {\n    > 27 |     const fixture = TestBed.createComponent(AppComponent);\n         |                             ^\n      28 |     fixture.detectChanges();\n      29 |     const app = fixture.nativeElement;\n      30 |     const menuItems = app.querySelectorAll(\'ion-label\');\n\n      at new NgZone (node_modules/@angular/core/fesm2020/core.mjs:26180:19)\n      at R3TestBedCompiler.compileTestModule (node_modules/@angular/core/fesm2020/testing.mjs:25851:24)\n      at R3TestBedCompiler.finalize (node_modules/@angular/core/fesm2020/testing.mjs:25419:14)\n      at TestBedRender3.get testModuleRef [as testModuleRef] (node_modules/@angular/core/fesm2020/testing.mjs:26377:49)\n      at TestBedRender3.inject (node_modules/@angular/core/fesm2020/testing.mjs:26300:29)\n      at TestBedRender3.createComponent (node_modules/@angular/core/fesm2020/testing.mjs:26340:44)\n      at Function.createComponent (node_modules/@angular/core/fesm2020/testing.mjs:26179:37)\n      at Object.<anonymous> (src/app/app.component.spec.ts:27:29)\n\n  \xe2\x97\x8f AppComponent \xe2\x80\xba should have menu labels\n\n    zone-testing.js is needed for the fakeAsync() test helper but could not be found.\n            Please make sure that your environment includes zone.js/testing\n\n      at resetFakeAsyncZone (node_modules/@angular/core/fesm2020/testing.mjs:273:11)\n      at Object.<anonymous> (node_modules/@angular/core/fesm2020/testing.mjs:26603:13)\n\n  \xe2\x97\x8f AppComponent \xe2\x80\xba should have urls\n\n    NG0908: In this configuration Angular requires Zone.js\n\n      35 |\n      36 |   it(\'should have urls\', () => {\n    > 37 |     const fixture = TestBed.createComponent(AppComponent);\n         |                             ^\n      38 |     fixture.detectChanges();\n      39 |     const app = fixture.nativeElement;\n      40 |     const menuItems = app.querySelectorAll(\'ion-item\');\n\n      at new NgZone (node_modules/@angular/core/fesm2020/core.mjs:26180:19)\n      at R3TestBedCompiler.compileTestModule (node_modules/@angular/core/fesm2020/testing.mjs:25851:24)\n      at R3TestBedCompiler.finalize (node_modules/@angular/core/fesm2020/testing.mjs:25419:14)\n      at TestBedRender3.get testModuleRef [as testModuleRef] (node_modules/@angular/core/fesm2020/testing.mjs:26377:49)\n      at TestBedRender3.inject (node_modules/@angular/core/fesm2020/testing.mjs:26300:29)\n      at TestBedRender3.createComponent (node_modules/@angular/core/fesm2020/testing.mjs:26340:44)\n      at Function.createComponent (node_modules/@angular/core/fesm2020/testing.mjs:26179:37)\n      at Object.<anonymous> (src/app/app.component.spec.ts:37:29)\n\n  \xe2\x97\x8f AppComponent \xe2\x80\xba should have urls\n\n    zone-testing.js is needed for the fakeAsync() test helper but could not be found.\n            Please make sure that your environment includes zone.js/testing\n\n      at resetFakeAsyncZone (node_modules/@angular/core/fesm2020/testing.mjs:273:11)\n      at Object.<anonymous> (node_modules/@angular/core/fesm2020/testing.mjs:26603:13)\n\nTest Suites: 4 failed, 4 total\nTests:       4 failed, 4 total\nSnapshots:   0 total\nTime:        1.861 s, estimated 2 s\nRan all test suites.\n
Run Code Online (Sandbox Code Playgroud)\n

我将不胜感激对此的任何帮助,肯定有一些未配置或未初始化的东西。谢谢!

\n

小智 1

此配置帮助我使用测试库 + 角度 14:

为 Angular 配置 Jest