Reputation: 11250
When running Jest against the base package, I get an error in Jest in running the test, which does not appear when simply running ionic serve
. Jest gets an error on
import { Platform } from '@ionic/angular';
which is:
export { IonicModule } from './ionic-module';
^^^^^^
SyntaxError: Unexpected token export
3 | import { RouterTestingModule } from '@angular/router/testing';
4 |
> 5 | import { Platform } from '@ionic/angular';
| ^
6 | import { SplashScreen } from '@ionic-native/splash-screen/ngx';
7 | import { StatusBar } from '@ionic-native/status-bar/ngx';
8 |
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17)
at Object.<anonymous> (src/app/app.component.spec.ts:5:1)
My Jest.config.json
module.exports = {
collectCoverage: true,
collectCoverageFrom: [
"src/**/*.ts"
],
coverageDirectory: "<rootDir>/coverage/",
moduleNameMapper: {
"@core/(.*)": "<rootDir>/src/app/core/$1",
"@state/(.*)": "<rootDir>/src/app/state/$1"
},
preset: "jest-preset-angular",
roots: ['src'],
setupTestFrameworkScriptFile: "<rootDir>/src/setup-jest.ts",
transformIgnorePatterns: [
"node_modules/(?!(@ionic-native|@ionic|angularfire2)/)"
],
verbose: false
}
I am just using the sample side menu template and adjusting the components to run Jest.
Upvotes: 6
Views: 2045
Reputation: 3203
In my case, with Ionic 5, Angular 10 and NX monorepo, I had to do the following to enable Jest testing of an Ionic app.
Note: Skip the first 4 steps if you already have standard Jest setup.
Note 2: The order of steps doesn't really matter.
1. Delete all Karma and Jasmine files and dependencies
karma.conf.js
and src/test.ts
.karma
and jasmine
from package.json
(e.g. @types/jasmine
, karma
etc.)2. Add Jest dependencies
Add jest
, jest-preset-angular
, @types/jest
and ts-jest
to your devDependencies
, if you don't have them yet:
# if you use yarn:
yarn add --dev jest jest-preset-angular @types/jest ts-jest
# or if you use npm:
npm install --save-dev jest jest-preset-angular @types/jest ts-jest
3. Update angular.json
Update your angular.json
file. Replace architect
-> test
configurations for Karma with configurations for Jest:
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "apps/my-app/jest.config.js",
"polyfills": "apps/my-app/src/polyfills.ts"
}
}
Note: I use @nrwl/jest:jest
builder. If you aren't using NX monorepo, just specify @angular-builders/jest:run
as a builder, and remove "apps/my-app/" from the config options.
4. Create test-setup.ts
Create src/test-setup.ts
file with a single line content:
import 'jest-preset-angular';
5. Add Babel dependencies
Add babel-jest
, @babel/preset-env
and @babel/plugin-syntax-dynamic-import
to your devDependencies
:
# if you use yarn:
yarn add --dev babel-jest @babel/preset-env @babel/plugin-syntax-dynamic-import
# or if you use npm:
npm install --save-dev babel-jest @babel/preset-env @babel/plugin-syntax-dynamic-import
6. Update tsconfig.spec.json
Add "allowJs": true
and types
to the compilerOptions
in your TypeScript config. Add files
to compile test-setup.ts
file created earlier.
My final version of tsconfig.spec.json
:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"allowJs": true,
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"files": ["src/test-setup.ts"],
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}
7. Create or update jest.config.js
Create jest.config.js
in your app root (where you have package.json
), if you haven't yet.
Note: I added transformIgnorePatterns
and global.ts-jest.babelConfig
settings to the default version of Jest config for Angular.
The final version of the file looks like this:
const esModules = ['@ionic'].join('|');
module.exports = {
preset: '../../jest.preset.js',
coverageDirectory: '../../coverage/apps/mobile-ui',
snapshotSerializers: [
'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js',
'jest-preset-angular/build/AngularSnapshotSerializer.js',
'jest-preset-angular/build/HTMLCommentSerializer.js',
],
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], // leave `<rootDir>` string as is
globals: {
'ts-jest': {
babelConfig: {
presets: [
[
'@babel/preset-env',
{ targets: { node: true }, modules: 'commonjs' }
]
],
plugins: ['@babel/plugin-syntax-dynamic-import']
},
tsConfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
astTransformers: {
before: [
'jest-preset-angular/build/InlineFilesTransformer',
'jest-preset-angular/build/StripStylesTransformer',
]
},
},
},
// To transform Ionic modules to UMD, because Jest can't import them otherwise
// (see here: https://medium.com/@gregor.woiwode/how-to-setup-jest-in-an-ionic-4-project-ff1e5b72dd79)
transformIgnorePatterns: [
`/node_modules/(?!${esModules})`
],
displayName: 'my-app',
};
Kudos to this article which helped me with identifying these steps: How to setup Jest in an Ionic 4 project | Gregor Woiwode | Apr 25, 2019 | Medium
Upvotes: 1
Reputation: 992
Seeing all answers being quite long I have decided to give show what worked for me after reading Jest unit testing no longer works with Ionic 4.
To make it work you need to add to jest.config.ts
:
transformIgnorePatterns: [
"node_modules/(?!@ionic-native|@ionic)"
],
And in tsconfig.spec.json
set:
"compilerOptions": {
"allowJs": true,
},
Upvotes: 4
Reputation: 631
Your answer didn't work for me. However, I noticed that removing the extra parenthesis got rid of the error. Try changing:
transformIgnorePatterns: [
"node_modules/(?!(@ionic-native|@ionic|angularfire2)/)"
],
to
transformIgnorePatterns: [
"node_modules/(?!@ionic-native|@ionic|angularfire2)"
],
For me, though, this now brings a new error:
Cannot find module '@ionic/core/loader' from 'app-initialize.js'
at Resolver.resolveModule (node_modules/jest-resolve/build/index.js:221:17)
at Object.<anonymous> (node_modules/@ionic/angular/dist/app-initialize.js:1:1)
This was all working fine until I upgraded to Ionic 4 beta 11 (from beta 8). I am also now using Jest 23.6.0 but it fails in Jest 23.5.0 as well.
I get these errors with or without your babelrc
config.
For reference, here is my ionic info
:
Ionic:
ionic (Ionic CLI) : 4.1.2
Ionic Framework : @ionic/angular 4.0.0-beta.11
@angular-devkit/core : 0.8.3
@angular-devkit/schematics : 0.8.3
@angular/cli : 6.2.3
@ionic/ng-toolkit : 1.0.7
@ionic/schematics-angular : 1.0.6
Cordova:
cordova (Cordova CLI) : 7.1.0
Cordova Platforms : none
Cordova Plugins : no whitelisted plugins (0 plugins total)
System:
Android SDK Tools : 26.1.1 (/Users/rc101077/Library/Android/sdk)
ios-deploy : 2.0.0
ios-sim : 7.0.0
NodeJS : v8.11.4 (/Users/rc101077/.nvm/versions/node/v8.11.4/bin/node)
npm : 6.4.1
OS : macOS High Sierra
Xcode : Xcode 9.4.1 Build version 9F2000
Upvotes: 1
Reputation: 2118
This issue appears when some file needs to be preprocessed before it can be used in Jest. In this case the ionic imports needs to be preprocessed but normally is ignored via the transformIgnorePatterns
. But this is half the issue. We also need to add some babel to process the files so that they can run.
I was able to solve this issue by adding a .babelrc file with the following config
{
"presets": [["@babel/preset-env", {
"modules": "commonjs",
"targets": {
"node": "current"
}
}]],
"plugins": ["transform-export-extensions", "@babel/plugin-transform-runtime"]
}
I used the following jest config
{
"jest": {
"preset": "jest-preset-angular",
"setupTestFrameworkScriptFile": "<rootDir>/src/setup-jest.ts",
"globals": {
"ts-jest": {
"tsConfigFile": "tsconfig.jest.json",
"useBabelrc": true
},
"__TRANSFORM_HTML__": true
},
"transformIgnorePatterns": [
"node_modules/(?!@ngrx|angular2-ui-switch|ng-dynamic|@ionic|@ionic-native)"
],
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
]
}
}
The src/tsconfig.spec.json also needed some minor adjustment.
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"baseUrl": "./",
"module": "commonjs",
"allowJs": true,
"types": [
"jest",
"jquery",
"jsdom",
"node"
]
},
"include": [
"polyfills.ts",
"**/*.spec.ts",
"**/*.d.ts"
]
}
Upvotes: 1