【问题标题】:How can I get Jest to transpile node_modules/@nativescript/core properly? Jest + NativeScript + Angular + Nx如何让 Jest 正确转换 node_modules/@nativescript/core? Jest + NativeScript + Angular + Nx
【发布时间】:2021-05-16 07:02:49
【问题描述】:

我目前正在尝试使用 Nx monorepo 工具设置多平台代码共享入门项目。该项目使用 Angular 用于 Web,NativeScript 用于跨平台移动。

理想情况下,我希望能够使用 Jest 运行所有单元测试。目前,我能够使用根目录中的 jest 成功运行单元测试。它们为 Angular 应用程序及其库正确执行,但在尝试为 NativeScript(NativeScript Angular)项目执行单元测试时遇到错误,特别是当这些单元测试导入 NativeScript 组件时(即实际上很有用)。也就是说,期望 truetrue 的虚拟测试工作正常,因此 Jest 可以毫无问题地查找和运行测试。但是当我尝试导入组件时,我遇到了问题。

我已经解决了一些问题。最初我得到的错误:

  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /home/james/WebstormProjects/please-remind.me/apps/mobile/node_modules/@nativescript/core/index.js:3
    import './globals';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (../../node_modules/jest-runtime/build/index.js:1350:14)
      at node_modules/@nativescript/angular/bundles/nativescript-angular.umd.js:2:85
      at Object.<anonymous> (node_modules/@nativescript/angular/bundles/nativescript-angular.umd.js:5:2)

所以我按照说明访问了 Jest 网站,在该网站上我被指示对我的 jest.config.js 进行以下更改:

module.exports = {
    displayName: 'mobile',
    preset: '../../jest.preset.js',
    setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
    globals: {
        'ts-jest': {
            tsConfig: '<rootDir>/tsconfig.spec.json',
            stringifyContentPathRegex: '\\.(html|svg)$',
            astTransformers: {
                before: [
                    'jest-preset-angular/build/InlineFilesTransformer',
                    'jest-preset-angular/build/StripStylesTransformer',
                ],
            },
        },
    },
    coverageDirectory: '../../coverage/apps/mobile',
    snapshotSerializers: [
        'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js',
        'jest-preset-angular/build/AngularSnapshotSerializer.js',
        'jest-preset-angular/build/HTMLCommentSerializer.js',
    ],
    transformIgnorePatterns: [                         <<<<<<< Added
        '../../node_modules/(?!(@nativescript)/)'      <<<<<<< Added
    ]                                                  <<<<<<< Added
};

需要注意的是,我从网络项目中复制了这个jest.config.js,它是自动生成的。

所以我有一个非常简单的单元测试app.component.spec.ts 尝试导入 AppComponent:

import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
    beforeEach(async () => {
        await TestBed.configureTestingModule({
            imports: [RouterTestingModule],
            declarations: [AppComponent],
        }).compileComponents();
    });

    it('should create the app', () => {
        const fixture = TestBed.createComponent(AppComponent);
        const app = fixture.componentInstance;
        expect(app).toBeTruthy();
    });
});

现在错误是:

  ● Test suite failed to run

    Cannot find module './application' from 'node_modules/@nativescript/core/index.js'

    Require stack:
      node_modules/@nativescript/core/index.js
      node_modules/@nativescript/angular/bundles/nativescript-angular.umd.js
      src/app/app.component.ts
      src/app/app.component.spec.ts

      at Resolver.resolveModule (../../node_modules/jest-resolve/build/index.js:306:11)
      at Object.<anonymous> (node_modules/@nativescript/core/index.js:4:1)

  console.log
    Profiling startup failed to figure out defaults from package.json, error: Error: Cannot find module '~/package.json' from 'node_modules/@nativescript/core/profiling/index.js'

      at Object.<anonymous> (node_modules/@nativescript/core/profiling/index.js:134:17)

我尝试将 testEnvironment: "node", 添加到我的 jest.config.js 中:

module.exports = {
    displayName: 'mobile',
    preset: '../../jest.preset.js',
    setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
    globals: {
        'ts-jest': {
            tsConfig: '<rootDir>/tsconfig.spec.json',
            stringifyContentPathRegex: '\\.(html|svg)$',
            astTransformers: {
                before: [
                    'jest-preset-angular/build/InlineFilesTransformer',
                    'jest-preset-angular/build/StripStylesTransformer',
                ],
            },
        },
    },
    coverageDirectory: '../../coverage/apps/mobile',
    snapshotSerializers: [
        'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js',
        'jest-preset-angular/build/AngularSnapshotSerializer.js',
        'jest-preset-angular/build/HTMLCommentSerializer.js',
    ],
    transformIgnorePatterns: [                         <<<<<<< Added
        '../../node_modules/(?!(@nativescript)/)'      <<<<<<< Added
    ]                                                  <<<<<<< Added
    testEnvironment: "node"                            <<<<<<< Added
};

然后出现不同的错误:

  ● Test suite failed to run

    Cannot find module '../timer' from 'node_modules/@nativescript/core/globals/index.js'

      at Resolver.resolveModule (../../node_modules/jest-resolve/build/index.js:306:11)
      at Object.loader (node_modules/@nativescript/core/globals/index.js:256:46)
      at loadModule (node_modules/@nativescript/core/globals/index.js:203:43)
      at Object.get [as clearInterval] (node_modules/@nativescript/core/globals/index.js:9:30)

  console.log
    Profiling startup failed to figure out defaults from package.json, error: Error: Cannot find module '~/package.json' from 'node_modules/@nativescript/core/profiling/index.js'

      at Object.<anonymous> (node_modules/@nativescript/core/profiling/index.js:134:17)

因此,ts-jest 肯定与某些东西有关,这是一种“及时”的翻译。我在想我需要在tsconfig.spec.json 中设置一个标志:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "../../dist/out-tsc",
    "module": "commonjs",
    "allowJs": true,
    "types": ["jest", "node"]
  },
  "files": ["src/test-setup.ts"],
  "include": ["**/*.spec.ts", "**/*.d.ts"]
}

这是上面扩展的基础tsconfig.json

{
    "compilerOptions": {
        "module": "esnext",
        "target": "es2017",
        "moduleResolution": "node",
        "experimentalDecorators": true,
        "emitDecoratorMetadata": true,
        "noEmitHelpers": true,
        "noEmitOnError": true,
        "skipLibCheck": true,
        "lib": [
            "es2017",
            "dom"
        ],
        "baseUrl": ".",
        "paths": {
            "~/*": [
                "src/*"
            ]
        }
    },
    "exclude": [
        "node_modules",
        "platforms"
    ]
}

提前致谢。

【问题讨论】:

  • 你解决了吗?我有完全相同的问题...
  • 不幸的是,没有。我还没有找到解决办法。

标签: angular typescript jestjs nativescript nrwl


【解决方案1】:

我正在使用 Nativescript-vue,我遇到了同样的错误。 我找到了一个解决方案,但我不知道它对你有用。

不要在你的 .vue 文件中使用import Vue from "nativescript-vue";。 试试import { Vue } from "vue-property-decorator"; 当你想在“nativescript-vue”而不是“vue-property-decorator”中使用某些东西时,会出现一些编译错误。 可以添加extend/vue-extend.ts文件来添加接口,编译错误就消失了。 vue-extend.ts 如下所示。

import { Vue } from "vue-property-decorator";
declare module "vue-property-decorator" {
  interface Vue {
    $navigateTo(args: any): any;
    $navigateTo(args: any, {}): any;
    $navigateBack(): any;
  }
}

【讨论】:

    【解决方案2】:

    这对我有用:

    • npm i jest -D
    • npm i @babel/preset-env -D
    • npm i @types/jest -D
    • npm i babel-preset-env -D
    • npm i @vue/test-utils vue-jest babel-jest -D
    • npm i --save-dev @vue/vue2-jest
    //jest.config.js
    
    module.exports = {
      verbose: true,
      moduleFileExtensions: ["ts", "js", "json", "vue"],
      transform: {
        ".*\\.(vue)$": "@vue/vue2-jest",
        "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
        "^.+\\.tsx?$": "ts-jest",
      },
      moduleNameMapper: {
        "^@/(.*)": "<rootDir>/app/$1",
    
        "^~/(.*)": "<rootDir>/app/$1",
      },
      roots: ["<rootDir>/tests/"],
      testEnvironment: "jsdom",
      setupFiles: ["<rootDir>/tests/setup.ts"],
    };
    
    
    //setup.ts
    import Vue from "vue";
    import { config } from "@vue/test-utils";
    
    jest.mock("nativescript-vue", () => Vue);
    
    const NSElements = [
      "ActionBar",
      "ActionItem",
      "FormattedString",
      "GridLayout",
      "HtmlView",
      "NavigationButton",
      "Page",
      "StackLayout",
      "AbsoluteLayout",
      "FlexboxLayout",
      "TabView",
      "TabViewItem",
      "TextField",
    ];
    NSElements.forEach((ele) => {
      Vue.config.ignoredElements.push(ele);
    });
    
    
    //.babelrc
    
    {
      "presets": [
        ["env", { "modules": false }]
    
      ],
      "env": {
        "test": {
          "presets": [
            ["env", { "targets": { "node": "current" }}]
          ]
        }
      }
    }
    
    
    //tsconfig.json
    ....
    "types": ["jest","node"],
    "include": ["app", "types"],
    "typeRoots": ["types"], //REMOVE THIS LINE
    ....
    
    

    然后:

    // Component.test.ts
    import { shallowMount } from "@vue/test-utils";
    import Component from "../../app/components/Component.vue";
    
    let wrapper: any;
    
    beforeEach(() => {
      wrapper = shallowMount(Component, {
        propsData: { text: "aBC" },
        mocks: {},
        stubs: {},
        methods: {},
      });
    });
    
    afterEach(() => {
      wrapper.destroy();
    });
    
    describe("Component", () => {
      it("is a Vue instance", () => {
        expect(wrapper.isVueInstance).toBeTruthy();
      });
    
      it("ComputedProp", () => {
        expect(wrapper.vm.computedProp).toBe("valueExpeted");
      });
    });
    
    

    【讨论】:

      猜你喜欢
      • 2017-03-25
      • 1970-01-01
      • 2021-02-15
      • 2018-08-25
      • 2019-09-20
      • 1970-01-01
      • 2020-12-17
      • 2021-10-15
      • 2019-10-16
      相关资源
      最近更新 更多