fix(ngMock): fix collecting stack trace in inject() on IE10+, PhantomJS

Add support for collecting current stack trace information in browsers
(e.g. IE10+, PhantomJS) that do not automatically store the current stack trace
information in a newly created `Error` object's `stack` property, but
only add it there once the `Error` gets thrown.

The original implementation works fine in Firefox & Chrome, but fails on IE10+
and PhantomJS where it, for example, breaks Karma's error reporting in cases
when an exception is thrown in a test like the following:

```
it('the holy crusade', inject(function() {
  var x = {};
  x.holyGrail();
}));
```

In this case, the ngMock `inject()` implementation would incorrectly add the
word `undefined` at the end of the collected error stack trace information,
thus causing the main error description to be reported back to Karma as
`undefined`.

The added test makes sure this functionality:

- works as expected in browsers supporting JavaScript stack trace
  collection, e.g. Chrome, Firefox, IE10+, Opera & PhantomJS
- does not add any bogus stack track information in browsers that do
  not support JavaScript stack trace collection, e.g. IE9

Fixes #13591
Closes #13592

Closes #13593
This commit is contained in:
Jurko Gospodnetić
2015-12-19 17:31:49 +01:00
committed by Georgios Kalpakas
parent 611dcbc035
commit 56dae6fa1b
2 changed files with 51 additions and 0 deletions
+6
View File
@@ -2480,6 +2480,12 @@ if (window.jasmine || window.mocha) {
window.inject = angular.mock.inject = function() {
var blockFns = Array.prototype.slice.call(arguments, 0);
var errorForStack = new Error('Declaration Location');
// IE10+ and PhanthomJS do not set stack trace information, until the error is thrown
if (!errorForStack.stack) {
try {
throw errorForStack;
} catch (e) {}
}
return isSpecRunning() ? workFn.call(currentSpec) : workFn;
/////////////////////
function workFn() {
+45
View File
@@ -919,6 +919,51 @@ describe('ngMock', function() {
});
}).toThrow('test message');
}));
describe('error stack trace when called outside of spec context', function() {
// - Chrome, Firefox, Edge, Opera give us the stack trace as soon as an Error is created
// - IE10+, PhantomJS give us the stack trace only once the error is thrown
// - IE9 does not provide stack traces
var stackTraceSupported = (function() {
var error = new Error();
if (!error.stack) {
try {
throw error;
} catch (e) {}
}
return !!error.stack;
})();
function testCaller() {
return inject(function() {
throw new Error();
});
}
var throwErrorFromInjectCallback = testCaller();
if (stackTraceSupported) {
describe('on browsers supporting stack traces', function() {
it('should update thrown Error stack trace with inject call location', function() {
try {
throwErrorFromInjectCallback();
} catch (e) {
expect(e.stack).toMatch('testCaller');
}
});
});
} else {
describe('on browsers not supporting stack traces', function() {
it('should not add stack trace information to thrown Error', function() {
try {
throwErrorFromInjectCallback();
} catch (e) {
expect(e.stack).toBeUndefined();
}
});
});
}
});
});
});