ngMock window.inject() does not get current stack trace correctly on PhantomJS and IE10+ #13591
Description
Overview of the Issue
ngMock
window.inject()
function collects the current stack trace by expecting to find it in a locally created Error
object's stack
property. This however does not hold true in case when using a browser that fills an Error
object's stack
information only when that object gets thrown.
Motivation for or Use Case
The bug was found while researching why karma reports invalid error information when using PhantomJS in cases like this:
it('the holy crusade', inject(function() {
var x = {};
x.holyGrail();
}));
where the ngMock inject()
implementation would incorrectly add the word undefined
(read too early from the Error
object's stack
property) to the end of the collected error stack trace information, thus causing the main error description (gotten by parsing the collected error stack trace information, assuming it has specific structure) to be reported back to karma as undefined
.
Angular Version(s)
- reproduced using angular version
1.4.8
- current
master
version still has the exact same code so should be affected by the same bug
Browsers and Operating System
- reproduced using PhantomJS browser
- if MSDN docs are to be believed, should not work when used in IE browsers as well
- reproduced using
Ubuntu 15.10
, but should not be OS specific
Reproduce the Error
Here's a test for the angular ngMock test suite that can be used to reproduce the error:
describe('when called outside of test spec context and inject callback throws an Error', function () {
function testCaller() {
return inject(function () {
throw new Error();
});
}
var throwErrorFromInjectCallback = testCaller();
it('should update thrown Error stack with inject call location', function () {
try {
throwErrorFromInjectCallback();
} catch (e) {
expect(e.stack).toMatch('testCaller');
}
});
});
Note that this whole functionality is completely untested and, at least to me, seems buggy or unfinished, but I'll open separate issues for that, while this one is targeted specifically to the error stack information constructed in ngMock
's window.inject()
.
Suggest a Fix
- after creating the
Error
object in question, throw it and catch it in case it does not already havestack
information stored on it