Jacob McCarthy Jacob McCarthy - 2 months ago 368
AngularJS Question

ZoneAwarePromise has been overridden

After upgrading an application to rc-7 and running my unit tests to be sure nothing broke, I got this error message on about half of my unit tests.

"Error: Zone.js has detected that ZoneAwarePromise '(window|global).Promise' has been overwritten.
Most likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js) in node_modules/zone.js/dist/zone.js (line 21)"

The closest I thing I can think of is that I mock responses from http calls in my unit tests by manually returning observables.

This is an Angular2 application using Jasmine and Karma for unit testing.

UPDATE
So it would seem this is likely a loading order issue as per the error message, however I am not loading the polyfills anywhere I can determine unless I am accidentally grabbing them. I've attached my karma.conf.js and systemjs.conf.js to aid in finding the error.

Karma.conf.js


module.exports = function(config) {
var gulpConfig = require('../gulp/config')();

/**
* List of npm packages that imported via `import` syntax
*/
var dependencies = [
'@angular',
'lodash',
'rxjs'
];

var configuration = {
basePath: '../../',

browserNoActivityTimeout: 20000,
frameworks: ['jasmine'],
browsers: ['PhantomJS'],
reporters: ['progress', 'coverage'],

preprocessors: {},

// Generate json used for remap-istanbul
coverageReporter: {
includeAllSources: true,
dir: 'coverage/appCoverage/remap/',
reporters: [
{ type: 'json', subdir: 'report-json' }
]
},

files: [
'node_modules/reflect-metadata/Reflect.js',
'node_modules/zone.js/dist/zone.js',
'node_modules/zone.js/dist/long-stack-trace-zone.js',
'node_modules/zone.js/dist/proxy.js',
'node_modules/zone.js/dist/sync-test.js',
'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/angular/angular.js',
'node_modules/core-js/client/shim.min.js',
'node_modules/systemjs/dist/system.src.js'
],

// proxied base paths
proxies: {
// required for component assests fetched by Angular's compiler
"/src/": "/base/src/",
"/app/": "/base/src/app/",
"/node_modules/": "/base/node_modules/"
},

port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
//browserNoActivityTimeout: 100000
};

configuration.preprocessors[gulpConfig.tmpApp + '**/!(*.spec)+(.js)'] = ['coverage'];
configuration.preprocessors[gulpConfig.tmpApp + '**/*.js'] = ['sourcemap'];
configuration.preprocessors[gulpConfig.tmpTest + '**/*.js'] = ['sourcemap'];

var files = [
gulpConfig.tmpTest + 'test-helpers/global/**/*.js',
gulpConfig.src + 'systemjs.conf.js',
'config/test/karma-test-shim.js',
createFilePattern(gulpConfig.tmpApp + '**/*.js', { included: false }),
createFilePattern(gulpConfig.tmpTest + 'test-helpers/*.js', { included: false }),
createFilePattern(gulpConfig.app + '**/*.html', { included: false }),
createFilePattern(gulpConfig.app + '**/*.css', { included: false }),
createFilePattern(gulpConfig.app + '**/*.ts', { included: false, watched: false }),
createFilePattern(gulpConfig.tmpApp + '**/*.js.map', { included: false, watched: false })
];

configuration.files = configuration.files.concat(files);

dependencies.forEach(function(key) {
configuration.files.push({
pattern: 'node_modules/' + key + '/**/*.js',
included: false,
watched: false
});
});

if (process.env.APPVEYOR) {
configuration.browsers = ['IE'];
configuration.singleRun = true;
configuration.browserNoActivityTimeout = 90000; // Note: default value (10000) is not enough
}

config.set(configuration);

// Helpers
function createFilePattern(path, config) {
config.pattern = path;
return config;
}
}




systemjs.conf.js



/*
* This config is only used during development and build phase only
* It will not be available on production
*
*/

(function(global) {
// ENV
global.ENV = global.ENV || 'development';

// map tells the System loader where to look for things
var map = {
'app': 'src/tmp/app',
'test': 'src/tmp/test',
'primeng': 'node_modules/primeng',
'@angular/core': 'node_modules/@angular/core/bundles/core.umd.js',
'@angular/common': 'node_modules/@angular/common/bundles/common.umd.js',
'@angular/compiler': 'node_modules/@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'node_modules/@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'node_modules/@angular/http/bundles/http.umd.js',
'@angular/router': 'node_modules/@angular/router/bundles/router.umd.js',
'@angular/forms': 'node_modules/@angular/forms/bundles/forms.umd.js',

// angular testing umd bundles
'@angular/core/testing': 'node_modules/@angular/core/bundles/core-testing.umd.js',
'@angular/common/testing': 'node_modules/@angular/common/bundles/common-testing.umd.js',
'@angular/compiler/testing': 'node_modules/@angular/compiler/bundles/compiler-testing.umd.js',
'@angular/platform-browser/testing': 'node_modules/@angular/platform-browser/bundles/platform-browser-testing.umd.js',
'@angular/platform-browser-dynamic/testing': 'node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
'@angular/http/testing': 'node_modules/@angular/http/bundles/http-testing.umd.js',
'@angular/router/testing': 'node_modules/@angular/router/bundles/router-testing.umd.js',
'@angular/forms/testing': 'node_modules/@angular/forms/bundles/forms-testing.umd.js',
'moment': 'node_modules/moment/moment.js',
'ng2-bootstrap': 'node_modules/ng2-bootstrap'
};

// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': {
defaultExtension: 'js'
},
'test': {
defaultExtension: 'js'
},
'rxjs': {
defaultExtension: 'js'
},
'primeng': {
defaultExtension: 'js'
},
'ng2-bootstrap': {
main: 'ng2-bootstrap',
defaultExtension: 'js'
}
};

// List npm packages here
var npmPackages = [
'@angular',
'rxjs',
'lodash'
];

// Add package entries for packages that expose barrels using index.js
var packageNames = [
// App barrels
'app/shared',

// 3rd party barrels
'lodash'
];

npmPackages.forEach(function (pkgName) {
map[pkgName] = 'node_modules/' + pkgName;
});

packageNames.forEach(function(pkgName) {
packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});

var config = {
map: map,
packages: packages
};

// filterSystemConfig - index.html's chance to modify config before we register it.
if (global.filterSystemConfig) { global.filterSystemConfig(config); }

System.config(config);

})(this);



Answer

I encountered the same problem. (Angular 2 RC.7 Jasmine Karma) It was due to the order I was loading the test files in my karma.conf.js. I was loading /zone.js/dist/zone.js before /systemjs/dist/system-polyfills.js. Changing the order of the files to load the zone.js AFTER the systemjs polyfills resolved this problem.

Here is my current setup in karma.conf.js that resolved the error for me.

files: [
  {pattern: 'dist/vendor/es6-shim/es6-shim.js', included: true, watched: false},
  {pattern: 'dist/vendor/reflect-metadata/Reflect.js', included: true, watched: false},
  {pattern: 'dist/vendor/systemjs/dist/system-polyfills.js', included: true, watched: false},
  {pattern: 'dist/vendor/systemjs/dist/system.src.js', included: true, watched: false},
  {pattern: 'dist/vendor/zone.js/dist/zone.js', included: true, watched: false},
  {pattern: 'dist/vendor/zone.js/dist/proxy.js', included: true, watched: false},
  {pattern: 'dist/vendor/zone.js/dist/sync-test.js', included: true, watched: false},
  {pattern: 'dist/vendor/zone.js/dist/long-stack-trace-zone.js', included: true, watched: false},
  {pattern: 'dist/vendor/zone.js/dist/async-test.js', included: true, watched: false},
  {pattern: 'dist/vendor/zone.js/dist/fake-async-test.js', included: true, watched: false},
  {pattern: 'dist/vendor/zone.js/dist/jasmine-patch.js', included: true, watched: false},

  {pattern: 'config/karma-test-shim.js', included: true, watched: true},

  // Distribution folder.
  {pattern: 'dist/**/*', included: false, watched: true}
],
Comments