Neil Clayton
Neil Clayton

Reputation: 100

Cannot run tests (jasmine, karma, webpack)

I've been trying for a couple of days now to get some tests to run.

I've two environments, one very "empty" and another with a full project. The 'empty' one does run a very simple test (but doesn't contain the Person object that is unable to be constructed in the full project).

I migrated the full project to a very similar environment in terms of installed dev packages, karma, jasmine versions and such. I also copied the tsconfig.json, karma.conf files across. Those are below.

For the life of me I cannot figure out why the karma tests will not run. With previous versions of Karma I would get an error along the lines of 'scheduler_person.b' is not a constructor.

Digging a little deeper, it's failing on this line of test.store.ts:

let neil: Person = new Person("Neil Clayton");

the constructor of this object is:

constructor(name: string = "put name here") {
    super();
    this.name = name;
    this.primary_roles = new Map<Role, number>();
    this.specific_roles = new Map<string, Array<Role>>();
    this.secondary_action_list = [];
    this.condition_rules = [];
    this.unavailable = [];
    this.prefs = new SchedulePrefs();
}

So, the Person class has a constructor, and this code does run within the app itself.

I have since upgraded all of karma/jasmine and the error now changes to: VM105 karma-test-shim.js:629 Uncaught TypeError: $f.b is not a constructor

Looking at the generated code, it's essentially exactly the same inability to call a constructor.

I feel I must be doing something very simple, very stupid, but I cannot see it. Any ideas?

(btw: this project is at https://github.com/scornflake/scheduler)

tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "noImplicitThis": true,
    "lib": [
      "dom",
      "es2015",
      "esnext.asynciterable"
    ],
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,
    "target": "es5"
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules",
    "src/**/*.spec.ts"
  ],
  "typeAcquisition": {
    "enable": true,
    "include": [
      "./src/common/fix.broken.gapi.types.d.ts"
    ]
  },
  "compileOnSave": false,
  "atom": {
    "rewriteTsconfig": false
  }
}

karma.config.json

const webpackConfig = require('./webpack.test.js');

module.exports = function (config) {
    const _config = {
        basePath: '',

        frameworks: [
            'jasmine'
            // 'jasmine-matchers'
        ],

        files: [
            {
                pattern: './karma-test-shim.js',
                watched: true
            }
        ],

        preprocessors: {
            './karma-test-shim.js': ['webpack', 'sourcemap']
        },

        webpack: webpackConfig,

        webpackMiddleware: {
            stats: 'errors-only'
        },

        webpackServer: {
            noInfo: true
        },

        browserConsoleLogOptions: {
            level: 'log',
            format: '%b %T: %m',
            terminal: true
        },

        // reporters: ['kjhtml', 'dots'],
        reporters: ['dots'],
        // reporters: ['kjhtml'],
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['Chrome'],
        singleRun: false
    };

    config.set(_config);
};

karma-test-shim.js

Error.stackTraceLimit = Infinity;

require('core-js/es6');
require('core-js/es7/reflect');

require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy');
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');

var appContext = require.context('../src', true, /\.spec\.ts/);
appContext.keys().forEach(appContext);

var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');

testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting());

package.json

{
  "name": "scheduler",
  "version": "0.0.1",
  "author": "Neil Clayton",
  "homepage": "http://ionicframework.com/",
  "private": true,
  "scripts": {
    "clean": "ionic-app-scripts clean",
    "build": "ionic-app-scripts build --copy ./config/copy.config.js",
    "lint": "ionic-app-scripts lint",
    "ionic:build": "ionic-app-scripts build --copy ./config/copy.config.js",
    "ionic:serve": "ionic-app-scripts serve --copy ./config/copy.config.js",
    "test-coverage": "ng test --code-coverage",
    "test": "ng test"
  },
  "dependencies": {
    "@angular/common": "5.0.3",
    "@angular/compiler": "5.0.3",
    "@angular/compiler-cli": "5.0.3",
    "@angular/core": "5.0.3",
    "@angular/forms": "5.0.3",
    "@angular/http": "5.0.3",
    "@angular/platform-browser": "5.0.3",
    "@angular/platform-browser-dynamic": "5.0.3",
    "@ionic-native/core": "4.3.2",
    "@ionic-native/splash-screen": "4.3.2",
    "@ionic-native/status-bar": "4.3.2",
    "@ionic/storage": "2.1.3",
    "@types/gapi": "^0.0.35",
    "@types/gapi.auth2": "^0.0.47",
    "@types/gapi.client": "^1.0.0",
    "@types/gapi.client.drive": "^3.0.1",
    "@types/gapi.client.sheets": "^4.0.0",
    "angular-pipes": "^6.5.3",
    "apollo-angular": "^1.0.1",
    "apollo-angular-link-http": "^1.0.2",
    "apollo-cache-inmemory": "^1.1.12",
    "apollo-client": "^2.2.8",
    "apollo-link": "^1.2.2",
    "cordova-browser": "5.0.1",
    "cordova-plugin-device": "^1.1.4",
    "cordova-plugin-ionic-webview": "^1.1.16",
    "cordova-plugin-splashscreen": "^4.0.3",
    "cordova-plugin-whitelist": "^1.3.1",
    "file-saver": "^1.3.8",
    "google-auth-library": "^1.4.0",
    "googleapis": "^28.1.0",
    "graphql": "^0.13.2",
    "graphql-tag": "^2.8.0",
    "ionic-angular": "3.9.2",
    "ionic-configuration-service": "^6.0.0",
    "ionic-logging-service": "^5.0.0",
    "ionic-plugin-keyboard": "^2.2.1",
    "ionicons": "3.0.0",
    "json2csv": "^3.11.5",
    "lodash": "^4.17.4",
    "mobx": "^4.1.1",
    "mobx-angular": "^3.0.1",
    "moment": "^2.20.1",
    "ng-circle-progress": "^0.9.9",
    "rxjs": "5.5.2",
    "short-unique-id": "^1.1.0",
    "sw-toolbox": "3.6.0",
    "to-case": "^2.0.0",
    "zone.js": "^0.8.26"
  },
  "devDependencies": {
    "@ionic/app-scripts": "3.1.6",
    "@types/jasmine": "2.8.4",
    "@types/node": "8.5.8",
    "angular2-template-loader": "^0.6.2",
    "file-save": "^0.2.0",
    "html-loader": "^0.5.5",
    "jasmine-core": "3.1.0",
    "jasmine-expect": "^3.8.3",
    "jasmine-spec-reporter": "^4.1.0",
    "karma": "^2.0.2",
    "karma-chrome-launcher": "^2.2.0",
    "karma-jasmine": "^1.1.1",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-webpack": "^3.0.0",
    "null-loader": "^0.1.1",
    "protractor": "5.3.0",
    "ts-loader": "^4.2.0",
    "ts-node": "4.1.0",
    "typescript": "2.4.2",
    "webpack": "^4.6.0"
  },
  "description": "Scheduler",
  "cordova": {
    "plugins": {
      "ionic-plugin-keyboard": {},
      "cordova-plugin-whitelist": {},
      "cordova-plugin-device": {},
      "cordova-plugin-splashscreen": {},
      "cordova-plugin-ionic-webview": {}
    },
    "platforms": [
      "browser"
    ]
  }
}

Finally, some pics of the browser errors:

running from webstorm

karma stack trace

a bit more detail

Upvotes: 1

Views: 813

Answers (1)

DanielGibbs
DanielGibbs

Reputation: 10190

In src/providers/store/test.store.ts you need to move all of your global constants (and subsequent method calls) into the SetupStore method of the NPBCStoreConstruction class. When I do this I can run the test suite properly.

The cause of issue is that when Webpack/Typescript/something compiles everything, it picks an arbitrary order to include all the files and if you look at the generated code you can see that the global invocation of the person Person constructor happens before it is defined.

Upvotes: 2

Related Questions