我怎样才能让Jest正确编译node_modules/@nativescript/core ?Jest + Native



我目前正在尝试使用Nx monorepo工具建立一个多平台代码共享启动项目。这个项目在web上使用Angular,在跨平台移动平台上使用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
};

应该注意的是,我从web项目中复制了这个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里面肯定有什么东西它有点"及时"transpilation。我认为有一个标志,我需要设置在我的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"
]
}

提前感谢。

我正在使用native - script-vue,我得到了与您相同的错误。我找到了一个解决办法,但我不知道对你是否有效。

不要在.vue文件中使用import Vue from "nativescript-vue";。尝试import { Vue } from "vue-property-decorator";你会得到一些编译错误,当你想使用"native - script-vue"而不是在"vue-property-decorator"中。您可以添加extend/vue-extend。Ts文件添加接口,则编译错误将消失。vue-extend。如下图所示。

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

这对我有用:

  • 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");
});
});

最新更新