How to setup up test enviroment with Karma and Jasmine

#1

Hi.

I am migranting my Ionic2 project from beta 11 to RC5. My functional code is ok now (after a lot of hours and headache :confounded:) but my test enviroment with karma and Jasmine are destroyed. I started to rebuild it but i found some problems with dependencies compatibility. Can feel I’m almost there, but now I can’t go on alone.

I have this error when run npm test:

...
13 01 2017 14:18:57.824:INFO [karma]: Karma v1.3.0 server started at http://localhost:9888/
13 01 2017 14:18:57.827:INFO [launcher]: Launching browser Chrome with unlimited concurrency
13 01 2017 14:18:57.864:INFO [launcher]: Starting browser Chrome
13 01 2017 14:18:58.393:INFO [Chrome 55.0.2883 (Windows 10 0.0.0)]: Connected on socket /#jDCBhNAJU3mWZHVMAAAA with id 4035564
Chrome 55.0.2883 (Windows 10 0.0.0) ERROR
  Uncaught SyntaxError: Unexpected token import
  at C:/Users/ROBERT~1.DEB/AppData/Local/Temp/karma-typescript-bundle-17080mXskCmFwBEQ7.js:79541

Debuggin I found what looks to be an error in @ionic/storage. The file C:/Users/ROBERT~1.DEB/AppData/Local/Temp/karma-typescript-bundle-17080mXskCmFwBEQ7.js:79541 showed in error constains:

79541: window.wrappers['C:/Users/roberto.debarba/git/mobilidade/hcm-frontend-mobile/node_modules/@ionic/storage/es2015/index.js']=[function(require,module,exports,__dirname,__filename){ import     { Storage } from './storage';
79542: export { Storage };

And the file node_modules/@ionic/storage/es2015/index.js contains:

import { Storage } from './storage';
export { Storage };

I don’t have idea what can I do. I tried to change the dependencies versions, but didn’t work.
Anyone have any idea? Thanks.

This is my actual enviroment configuration:
package.json

{
  "name": "",
  "description": "",
  "author": "",
  "homepage": "",
  "private": true,
  "scripts": {
    "build": "ionic-app-scripts build",
    "clean": "ionic-app-scripts clean",
    "ionic:build": "ionic-app-scripts build",
    "ionic:serve": "ionic-app-scripts serve",
    "test": "karma start karma.conf.js"
  },
  "dependencies": {
    "@angular/common": "2.1.1",
    "@angular/compiler": "2.1.1",
    "@angular/compiler-cli": "2.1.1",
    "@angular/core": "2.1.1",
    "@angular/forms": "2.1.1",
    "@angular/http": "2.1.1",
    "@angular/platform-browser": "2.1.1",
    "@angular/platform-browser-dynamic": "2.1.1",
    "@angular/platform-server": "2.1.1",
    "@ionic/storage": "1.1.6",
    "ionic-angular": "2.0.0-rc.5",
    "ionic-native": "2.2.11",
    "ionicons": "3.0.0",
    "moment": "2.14.1",
    "rxjs": "5.0.0-beta.12",
    "sw-toolbox": "3.4.0",
    "zone.js": "0.6.26"
  },
  "devDependencies": {
    "@ionic/app-scripts": "1.0.0",
    "typescript": "2.0.9",

    "//": "Dependencias para testes automatizados",
    "jasmine-core": "2.5.2",
    "karma": "1.3.0",
    "karma-chrome-launcher": "2.0.0",
    "karma-jasmine": "1.1.0",
    "karma-typescript": "2.1.5",

    "//": [
      "Dependencias usadas para os scripts Gulp.",
      "Com a liberação do Ionic RC0, não deve mais ser usado Gulp nos projetos, porém não foi disponibilizada nenhuma",
      "alternativa para para troca de ambientes. Quando for liberada apagar as dependencias a seguir e o arquivo gulpfile.js."
    ],
    "gulp": "3.9.1",
    "gulp-rename": "1.2.2",
    "ionic-gulp-browserify-typescript": "2.0.0",
    "replace": "0.3.0",
    "run-sequence": "1.2.2"
  },
  "cordovaPlugins": [
    "cordova-plugin-device",
    "cordova-plugin-console",
    "cordova-plugin-whitelist",
    "cordova-plugin-splashscreen",
    "cordova-plugin-statusbar",
    "cordova-plugin-crosswalk-webview@1.5.0",
    "ionic-plugin-keyboard"
  ],
  "cordovaPlatforms": [
    "ios@4.3.1",
    "android@5.2.2"
  ]
}

karma.conf.js

// Karma configuration
// Generated on Thu Jan 12 2017 16:48:10 GMT-0200 (Horário brasileiro de verão)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',


    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine', 'karma-typescript'],


    // list of files / patterns to load in the browser
    files: [
      'node_modules/es6-shim/es6-shim.js',        // TypeError: undefined is not a constructor (evaluating 'new exports.Map()')
      'node_modules/reflect-metadata/Reflect.js', // 'Uncaught reflect-metadata shim is required when using class decorators'
      // 'node_modules/zone.js/dist/zone.js',        // Zone.js dependencies (Zone undefined)
      // 'node_modules/zone.js/dist/jasmine-patch.js',
      // 'node_modules/zone.js/dist/async-test.js',
      // 'node_modules/zone.js/dist/fake-async-test.js',

      'node_modules/zone.js/dist/zone.js',
      'node_modules/zone.js/dist/long-stack-trace-zone.js',
      'node_modules/zone.js/dist/async-test.js',
      'node_modules/zone.js/dist/fake-async-test.js',
      'node_modules/zone.js/dist/sync-test.js',
      'node_modules/zone.js/dist/proxy-zone.js',
      'node_modules/zone.js/dist/proxy.js',
      'node_modules/zone.js/dist/jasmine-patch.js',

      // './src/polyfills.ts',
      // './src/mocks.ts',
      './src/**/*.ts',
      // './src/**/*.spec.ts'
      './src/auth/*.spec.ts'
    ],


    // list of files to exclude
    exclude: [
      'node_modules/angular2/**/*_spec.js',
      'node_modules/@angular/**/*_spec.js',
      'node_modules/ionic-angular/**/*spec*'
    ],


    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      // './src/polyfills.ts': ['karma-typescript'],
      // './src/mocks.ts': ['karma-typescript'],
      './src/**/*.ts': ['karma-typescript'],
      './src/**/*.spec.ts': ['karma-typescript']
    },


    typescriptPreprocessor: {
      options: {
        sourceMap: false,
        target: 'ES5',
        module: 'amd',
        noImplicitAny: true,
        noResolve: true,
        removeComments: true,
        concatenateOutput: false
      },
      transformPath: function(path) {
        return path.replace(/\.ts$/, '.js');
      }
    },


    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress', 'karma-typescript'],


    // web server port
    port: 9876,


    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,


    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome'],


    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  })
};
#2

sounds like your typescript preprocessor does not work correctly, because there should not be any import keywords after you have generated ES5 modules.

#3

Thanks, but didn’t work.
I find an issue on github that describes the same error. Looks like the karma’s executor cannot support es2015, and it’s used on @ionic/storage implementation.

ES5 should be the default “main” in package.json

#4

Maybe try something like this in the provider that imports Storage? Not sure if this will lead to other issues. I’ve been beating myself silly trying to get karma and jasmine working in RC4.

import { Storage } from '@ionic/storage/es5/storage';
#5

I could not make it work that way, but i found a GitHub repository with some articles and code samples that show how to setup test enviroment.
It’s not like I was doing but works pretty well.