@@ -56,7 +56,8 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
|||||||
j$.Clock = jRequire.Clock();
|
j$.Clock = jRequire.Clock();
|
||||||
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
|
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
|
||||||
j$.Env = jRequire.Env(j$);
|
j$.Env = jRequire.Env(j$);
|
||||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter();
|
j$.StackTrace = jRequire.StackTrace(j$);
|
||||||
|
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
|
||||||
j$.Expectation = jRequire.Expectation();
|
j$.Expectation = jRequire.Expectation();
|
||||||
j$.buildExpectationResult = jRequire.buildExpectationResult();
|
j$.buildExpectationResult = jRequire.buildExpectationResult();
|
||||||
j$.JsApiReporter = jRequire.JsApiReporter();
|
j$.JsApiReporter = jRequire.JsApiReporter();
|
||||||
@@ -461,6 +462,54 @@ getJasmineRequireObj().util = function(j$) {
|
|||||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function anyMatch(pattern, lines) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; i++) {
|
||||||
|
if (lines[i].match(pattern)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorWithStack() {
|
||||||
|
// Don't throw and catch if we don't have to, because it makes it harder
|
||||||
|
// for users to debug their code with exception breakpoints.
|
||||||
|
var error = new Error();
|
||||||
|
|
||||||
|
if (error.stack) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// But some browsers (e.g. Phantom) only provide a stack trace if we throw.
|
||||||
|
try {
|
||||||
|
throw new Error();
|
||||||
|
} catch (e) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function callerFile() {
|
||||||
|
var trace = new j$.StackTrace(errorWithStack().stack);
|
||||||
|
return trace.frames[2].file;
|
||||||
|
}
|
||||||
|
|
||||||
|
util.jasmineFile = (function() {
|
||||||
|
var result;
|
||||||
|
|
||||||
|
return function() {
|
||||||
|
var trace;
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
result = callerFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
return util;
|
return util;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2186,8 +2235,10 @@ getJasmineRequireObj().errors = function() {
|
|||||||
ExpectationFailed: ExpectationFailed
|
ExpectationFailed: ExpectationFailed
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
getJasmineRequireObj().ExceptionFormatter = function() {
|
getJasmineRequireObj().ExceptionFormatter = function(j$) {
|
||||||
function ExceptionFormatter() {
|
|
||||||
|
function ExceptionFormatter(options) {
|
||||||
|
var jasmineFile = (options && options.jasmineFile) || j$.util.jasmineFile();
|
||||||
this.message = function(error) {
|
this.message = function(error) {
|
||||||
var message = '';
|
var message = '';
|
||||||
|
|
||||||
@@ -2209,8 +2260,34 @@ getJasmineRequireObj().ExceptionFormatter = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.stack = function(error) {
|
this.stack = function(error) {
|
||||||
return error ? error.stack : null;
|
if (!error || !error.stack) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var stackTrace = new j$.StackTrace(error.stack);
|
||||||
|
var lines = filterJasmine(stackTrace);
|
||||||
|
|
||||||
|
if (stackTrace.message) {
|
||||||
|
lines.unshift(stackTrace.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function filterJasmine(stackTrace) {
|
||||||
|
var result = [],
|
||||||
|
jasmineMarker = stackTrace.style === 'webkit' ? '<Jasmine>' : ' at <Jasmine>';
|
||||||
|
|
||||||
|
stackTrace.frames.forEach(function(frame) {
|
||||||
|
if (frame.file && frame.file !== jasmineFile) {
|
||||||
|
result.push(frame.raw);
|
||||||
|
} else if (result[result.length - 1] !== jasmineMarker) {
|
||||||
|
result.push(jasmineMarker);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExceptionFormatter;
|
return ExceptionFormatter;
|
||||||
@@ -5033,6 +5110,87 @@ getJasmineRequireObj().SpyStrategy = function(j$) {
|
|||||||
return SpyStrategy;
|
return SpyStrategy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getJasmineRequireObj().StackTrace = function(j$) {
|
||||||
|
function StackTrace(rawTrace) {
|
||||||
|
var lines = rawTrace
|
||||||
|
.split('\n')
|
||||||
|
.filter(function(line) { return line !== ''; });
|
||||||
|
|
||||||
|
if (lines[0].match(/^Error/)) {
|
||||||
|
this.message = lines.shift();
|
||||||
|
} else {
|
||||||
|
this.message = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parseResult = tryParseFrames(lines);
|
||||||
|
this.frames = parseResult.frames;
|
||||||
|
this.style = parseResult.style;
|
||||||
|
}
|
||||||
|
|
||||||
|
var framePatterns = [
|
||||||
|
// PhantomJS on Linux, Node, Chrome, IE, Edge
|
||||||
|
// e.g. " at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)"
|
||||||
|
// Note that the "function name" can include a surprisingly large set of
|
||||||
|
// characters, including angle brackets and square brackets.
|
||||||
|
{ re: /^\s*at ([^\)]+) \(([^\)]+)\)$/, fnIx: 1, fileLineColIx: 2, style: 'v8' },
|
||||||
|
|
||||||
|
// NodeJS alternate form, often mixed in with the Chrome style
|
||||||
|
// e.g. " at /some/path:4320:20
|
||||||
|
{ re: /\s*at (.+)$/, fileLineColIx: 1, style: 'v8' },
|
||||||
|
|
||||||
|
// PhantomJS on OS X, Safari, Firefox
|
||||||
|
// e.g. "run@http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||||
|
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||||
|
{ re: /^(([^@\s]+)@)?([^\s]+)$/, fnIx: 2, fileLineColIx: 3, style: 'webkit' }
|
||||||
|
];
|
||||||
|
|
||||||
|
// regexes should capture the function name (if any) as group 1
|
||||||
|
// and the file, line, and column as group 2.
|
||||||
|
function tryParseFrames(lines) {
|
||||||
|
var style = null;
|
||||||
|
var frames = lines.map(function(line) {
|
||||||
|
var convertedLine = first(framePatterns, function(pattern) {
|
||||||
|
var overallMatch = line.match(pattern.re),
|
||||||
|
fileLineColMatch;
|
||||||
|
if (!overallMatch) { return null; }
|
||||||
|
|
||||||
|
fileLineColMatch = overallMatch[pattern.fileLineColIx].match(
|
||||||
|
/^(.*):(\d+):\d+$/);
|
||||||
|
if (!fileLineColMatch) { return null; }
|
||||||
|
|
||||||
|
style = style || pattern.style;
|
||||||
|
return {
|
||||||
|
raw: line,
|
||||||
|
file: fileLineColMatch[1],
|
||||||
|
line: parseInt(fileLineColMatch[2], 10),
|
||||||
|
func: overallMatch[pattern.fnIx]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return convertedLine || { raw: line };
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
style: style,
|
||||||
|
frames: frames
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function first(items, fn) {
|
||||||
|
var i, result;
|
||||||
|
|
||||||
|
for (i = 0; i < items.length; i++) {
|
||||||
|
result = fn(items[i]);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StackTrace;
|
||||||
|
};
|
||||||
|
|
||||||
getJasmineRequireObj().Suite = function(j$) {
|
getJasmineRequireObj().Suite = function(j$) {
|
||||||
function Suite(attrs) {
|
function Suite(attrs) {
|
||||||
this.env = attrs.env;
|
this.env = attrs.env;
|
||||||
|
|||||||
@@ -54,6 +54,65 @@ describe("ExceptionFormatter", function() {
|
|||||||
expect(new jasmineUnderTest.ExceptionFormatter().stack(error)).toMatch(/ExceptionFormatterSpec\.js.*\d+/)
|
expect(new jasmineUnderTest.ExceptionFormatter().stack(error)).toMatch(/ExceptionFormatterSpec\.js.*\d+/)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("filters Jasmine stack frames from V8 style traces", function() {
|
||||||
|
var error = {
|
||||||
|
stack: 'Error: nope\n' +
|
||||||
|
' at fn1 (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||||
|
' at fn2 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
|
||||||
|
' at fn3 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
|
||||||
|
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)\n'
|
||||||
|
};
|
||||||
|
var subject = new jasmineUnderTest.ExceptionFormatter({
|
||||||
|
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||||
|
});
|
||||||
|
var result = subject.stack(error);
|
||||||
|
expect(result).toEqual('Error: nope\n' +
|
||||||
|
' at fn1 (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||||
|
' at <Jasmine>\n' +
|
||||||
|
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("filters Jamine stack frames from Webkit style traces", function() {
|
||||||
|
var error = {
|
||||||
|
stack: 'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||||
|
'fn1@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||||
|
'fn2@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||||
|
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
|
||||||
|
};
|
||||||
|
var subject = new jasmineUnderTest.ExceptionFormatter({
|
||||||
|
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||||
|
});
|
||||||
|
var result = subject.stack(error);
|
||||||
|
expect(result).toEqual(
|
||||||
|
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||||
|
'<Jasmine>\n' +
|
||||||
|
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("filters Jasmine stack frames in this environment", function() {
|
||||||
|
var error, i;
|
||||||
|
try { throw new Error("an error"); } catch(e) { error = e; }
|
||||||
|
var subject = new jasmineUnderTest.ExceptionFormatter({
|
||||||
|
jasmineFile: jasmine.util.jasmineFile()
|
||||||
|
});
|
||||||
|
var result = subject.stack(error);
|
||||||
|
var lines = result.split('\n');
|
||||||
|
|
||||||
|
if (lines[0].match(/an error/)) {
|
||||||
|
lines.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(lines[0]).toMatch(/ExceptionFormatterSpec.js/);
|
||||||
|
expect(lines[1]).toMatch(/<Jasmine>/);
|
||||||
|
|
||||||
|
// Node has some number of additional frames below Jasmine.
|
||||||
|
for (i = 2; i < lines.length; i++) {
|
||||||
|
expect(lines[i]).not.toMatch(/jasmine.js/);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it("returns null if no Error provided", function() {
|
it("returns null if no Error provided", function() {
|
||||||
expect(new jasmineUnderTest.ExceptionFormatter().stack()).toBeNull();
|
expect(new jasmineUnderTest.ExceptionFormatter().stack()).toBeNull();
|
||||||
});
|
});
|
||||||
|
|||||||
166
spec/core/StackTraceSpec.js
Normal file
166
spec/core/StackTraceSpec.js
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
describe("StackTrace", function() {
|
||||||
|
it("understands Chrome/IE/Edge style traces", function() {
|
||||||
|
var raw =
|
||||||
|
'Error: nope\n' +
|
||||||
|
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||||
|
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)';
|
||||||
|
|
||||||
|
var result = new jasmineUnderTest.StackTrace(raw);
|
||||||
|
|
||||||
|
expect(result.message).toEqual('Error: nope');
|
||||||
|
expect(result.style).toEqual('v8');
|
||||||
|
expect(result.frames).toEqual([
|
||||||
|
{
|
||||||
|
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
||||||
|
func: 'UserContext.<anonymous>',
|
||||||
|
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||||
|
line: 115
|
||||||
|
},
|
||||||
|
{
|
||||||
|
raw: ' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
|
||||||
|
func: 'QueueRunner.run',
|
||||||
|
file: 'http://localhost:8888/__jasmine__/jasmine.js',
|
||||||
|
line: 4320
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("understands Node style traces", function() {
|
||||||
|
var raw = 'Error\n' +
|
||||||
|
' at /somewhere/jasmine/lib/jasmine-core/jasmine.js:4255:9\n' +
|
||||||
|
' at QueueRunner.complete [as onComplete] (/somewhere/jasmine/lib/jasmine-core/jasmine.js:579:9)\n' +
|
||||||
|
' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)\n' +
|
||||||
|
' at runCallback (timers.js:672:20)';
|
||||||
|
var result = new jasmineUnderTest.StackTrace(raw);
|
||||||
|
|
||||||
|
expect(result.message).toEqual('Error');
|
||||||
|
expect(result.style).toEqual('v8');
|
||||||
|
expect(result.frames).toEqual([
|
||||||
|
{
|
||||||
|
raw: ' at /somewhere/jasmine/lib/jasmine-core/jasmine.js:4255:9',
|
||||||
|
func: undefined,
|
||||||
|
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
|
||||||
|
line: 4255
|
||||||
|
},
|
||||||
|
{
|
||||||
|
raw: ' at QueueRunner.complete [as onComplete] (/somewhere/jasmine/lib/jasmine-core/jasmine.js:579:9)',
|
||||||
|
func: 'QueueRunner.complete [as onComplete]',
|
||||||
|
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
|
||||||
|
line: 579
|
||||||
|
},
|
||||||
|
{
|
||||||
|
raw: ' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)',
|
||||||
|
func: 'Immediate.<anonymous>',
|
||||||
|
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
|
||||||
|
line: 4314
|
||||||
|
},
|
||||||
|
{
|
||||||
|
raw: ' at runCallback (timers.js:672:20)',
|
||||||
|
func: 'runCallback',
|
||||||
|
file: 'timers.js',
|
||||||
|
line: 672
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("understands Safari/Firefox/Phantom-OS X style traces", function() {
|
||||||
|
var raw =
|
||||||
|
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||||
|
'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27';
|
||||||
|
var result = new jasmineUnderTest.StackTrace(raw);
|
||||||
|
|
||||||
|
expect(result.message).toBeFalsy();
|
||||||
|
expect(result.style).toEqual('webkit');
|
||||||
|
expect(result.frames).toEqual([
|
||||||
|
{
|
||||||
|
raw: 'http://localhost:8888/__spec__/core/UtilSpec.js:115:28',
|
||||||
|
func: undefined,
|
||||||
|
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||||
|
line: 115
|
||||||
|
},
|
||||||
|
{
|
||||||
|
raw: 'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27',
|
||||||
|
func: 'run',
|
||||||
|
file: 'http://localhost:8888/__jasmine__/jasmine.js',
|
||||||
|
line: 4320
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not mistake gibberish for Safari/Firefox/Phantom-OS X style traces", function() {
|
||||||
|
var raw = 'randomcharsnotincludingwhitespace';
|
||||||
|
var result = new jasmineUnderTest.StackTrace(raw);
|
||||||
|
expect(result.style).toBeNull();
|
||||||
|
expect(result.frames).toEqual([
|
||||||
|
{ raw: raw }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("understands Phantom-Linux style traces", function() {
|
||||||
|
var raw =
|
||||||
|
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||||
|
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)';
|
||||||
|
|
||||||
|
var result = new jasmineUnderTest.StackTrace(raw);
|
||||||
|
|
||||||
|
expect(result.message).toBeFalsy();
|
||||||
|
expect(result.style).toEqual('v8');
|
||||||
|
expect(result.frames).toEqual([
|
||||||
|
{
|
||||||
|
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
||||||
|
func: 'UserContext.<anonymous>',
|
||||||
|
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||||
|
line: 115
|
||||||
|
},
|
||||||
|
{
|
||||||
|
raw: ' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
|
||||||
|
func: 'QueueRunner.run',
|
||||||
|
file: 'http://localhost:8888/__jasmine__/jasmine.js',
|
||||||
|
line: 4320
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ignores blank lines", function() {
|
||||||
|
var raw =
|
||||||
|
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n';
|
||||||
|
|
||||||
|
var result = new jasmineUnderTest.StackTrace(raw);
|
||||||
|
|
||||||
|
expect(result.frames).toEqual([
|
||||||
|
{
|
||||||
|
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
||||||
|
func: 'UserContext.<anonymous>',
|
||||||
|
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||||
|
line: 115
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("omits properties except 'raw' for frames that are not understood", function() {
|
||||||
|
var raw =
|
||||||
|
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
|
||||||
|
' but this is quite unexpected\n' +
|
||||||
|
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)';
|
||||||
|
|
||||||
|
var result = new jasmineUnderTest.StackTrace(raw);
|
||||||
|
expect(result.style).toEqual('v8');
|
||||||
|
expect(result.frames).toEqual([
|
||||||
|
{
|
||||||
|
raw: ' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
|
||||||
|
func: 'UserContext.<anonymous>',
|
||||||
|
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
|
||||||
|
line: 115
|
||||||
|
},
|
||||||
|
{
|
||||||
|
raw: ' but this is quite unexpected'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
raw: ' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
|
||||||
|
func: 'QueueRunner.run',
|
||||||
|
file: 'http://localhost:8888/__jasmine__/jasmine.js',
|
||||||
|
line: 4320
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -91,6 +91,13 @@ describe("jasmineUnderTest.util", function() {
|
|||||||
|
|
||||||
expect(jasmineUnderTest.util.objectDifference(a, b)).toEqual({x: 1});
|
expect(jasmineUnderTest.util.objectDifference(a, b)).toEqual({x: 1});
|
||||||
expect(jasmineUnderTest.util.objectDifference(b, a)).toEqual({y: 2});
|
expect(jasmineUnderTest.util.objectDifference(b, a)).toEqual({y: 2});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
|
describe("jasmineFile", function() {
|
||||||
|
it("returns the file containing jasmine.util", function() {
|
||||||
|
expect(jasmineUnderTest.util.jasmineFile()).toMatch(/util.js$/);
|
||||||
|
expect(jasmine.util.jasmineFile()).toMatch(/jasmine.js$/);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
getJasmineRequireObj().ExceptionFormatter = function() {
|
getJasmineRequireObj().ExceptionFormatter = function(j$) {
|
||||||
function ExceptionFormatter() {
|
|
||||||
|
function ExceptionFormatter(options) {
|
||||||
|
var jasmineFile = (options && options.jasmineFile) || j$.util.jasmineFile();
|
||||||
this.message = function(error) {
|
this.message = function(error) {
|
||||||
var message = '';
|
var message = '';
|
||||||
|
|
||||||
@@ -21,8 +23,34 @@ getJasmineRequireObj().ExceptionFormatter = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.stack = function(error) {
|
this.stack = function(error) {
|
||||||
return error ? error.stack : null;
|
if (!error || !error.stack) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var stackTrace = new j$.StackTrace(error.stack);
|
||||||
|
var lines = filterJasmine(stackTrace);
|
||||||
|
|
||||||
|
if (stackTrace.message) {
|
||||||
|
lines.unshift(stackTrace.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function filterJasmine(stackTrace) {
|
||||||
|
var result = [],
|
||||||
|
jasmineMarker = stackTrace.style === 'webkit' ? '<Jasmine>' : ' at <Jasmine>';
|
||||||
|
|
||||||
|
stackTrace.frames.forEach(function(frame) {
|
||||||
|
if (frame.file && frame.file !== jasmineFile) {
|
||||||
|
result.push(frame.raw);
|
||||||
|
} else if (result[result.length - 1] !== jasmineMarker) {
|
||||||
|
result.push(jasmineMarker);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExceptionFormatter;
|
return ExceptionFormatter;
|
||||||
|
|||||||
80
src/core/StackTrace.js
Normal file
80
src/core/StackTrace.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
getJasmineRequireObj().StackTrace = function(j$) {
|
||||||
|
function StackTrace(rawTrace) {
|
||||||
|
var lines = rawTrace
|
||||||
|
.split('\n')
|
||||||
|
.filter(function(line) { return line !== ''; });
|
||||||
|
|
||||||
|
if (lines[0].match(/^Error/)) {
|
||||||
|
this.message = lines.shift();
|
||||||
|
} else {
|
||||||
|
this.message = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parseResult = tryParseFrames(lines);
|
||||||
|
this.frames = parseResult.frames;
|
||||||
|
this.style = parseResult.style;
|
||||||
|
}
|
||||||
|
|
||||||
|
var framePatterns = [
|
||||||
|
// PhantomJS on Linux, Node, Chrome, IE, Edge
|
||||||
|
// e.g. " at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)"
|
||||||
|
// Note that the "function name" can include a surprisingly large set of
|
||||||
|
// characters, including angle brackets and square brackets.
|
||||||
|
{ re: /^\s*at ([^\)]+) \(([^\)]+)\)$/, fnIx: 1, fileLineColIx: 2, style: 'v8' },
|
||||||
|
|
||||||
|
// NodeJS alternate form, often mixed in with the Chrome style
|
||||||
|
// e.g. " at /some/path:4320:20
|
||||||
|
{ re: /\s*at (.+)$/, fileLineColIx: 1, style: 'v8' },
|
||||||
|
|
||||||
|
// PhantomJS on OS X, Safari, Firefox
|
||||||
|
// e.g. "run@http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||||
|
// or "http://localhost:8888/__jasmine__/jasmine.js:4320:27"
|
||||||
|
{ re: /^(([^@\s]+)@)?([^\s]+)$/, fnIx: 2, fileLineColIx: 3, style: 'webkit' }
|
||||||
|
];
|
||||||
|
|
||||||
|
// regexes should capture the function name (if any) as group 1
|
||||||
|
// and the file, line, and column as group 2.
|
||||||
|
function tryParseFrames(lines) {
|
||||||
|
var style = null;
|
||||||
|
var frames = lines.map(function(line) {
|
||||||
|
var convertedLine = first(framePatterns, function(pattern) {
|
||||||
|
var overallMatch = line.match(pattern.re),
|
||||||
|
fileLineColMatch;
|
||||||
|
if (!overallMatch) { return null; }
|
||||||
|
|
||||||
|
fileLineColMatch = overallMatch[pattern.fileLineColIx].match(
|
||||||
|
/^(.*):(\d+):\d+$/);
|
||||||
|
if (!fileLineColMatch) { return null; }
|
||||||
|
|
||||||
|
style = style || pattern.style;
|
||||||
|
return {
|
||||||
|
raw: line,
|
||||||
|
file: fileLineColMatch[1],
|
||||||
|
line: parseInt(fileLineColMatch[2], 10),
|
||||||
|
func: overallMatch[pattern.fnIx]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return convertedLine || { raw: line };
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
style: style,
|
||||||
|
frames: frames
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function first(items, fn) {
|
||||||
|
var i, result;
|
||||||
|
|
||||||
|
for (i = 0; i < items.length; i++) {
|
||||||
|
result = fn(items[i]);
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StackTrace;
|
||||||
|
};
|
||||||
@@ -34,7 +34,8 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
|
|||||||
j$.Clock = jRequire.Clock();
|
j$.Clock = jRequire.Clock();
|
||||||
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
|
j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler();
|
||||||
j$.Env = jRequire.Env(j$);
|
j$.Env = jRequire.Env(j$);
|
||||||
j$.ExceptionFormatter = jRequire.ExceptionFormatter();
|
j$.StackTrace = jRequire.StackTrace(j$);
|
||||||
|
j$.ExceptionFormatter = jRequire.ExceptionFormatter(j$);
|
||||||
j$.Expectation = jRequire.Expectation();
|
j$.Expectation = jRequire.Expectation();
|
||||||
j$.buildExpectationResult = jRequire.buildExpectationResult();
|
j$.buildExpectationResult = jRequire.buildExpectationResult();
|
||||||
j$.JsApiReporter = jRequire.JsApiReporter();
|
j$.JsApiReporter = jRequire.JsApiReporter();
|
||||||
|
|||||||
@@ -100,5 +100,53 @@ getJasmineRequireObj().util = function(j$) {
|
|||||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function anyMatch(pattern, lines) {
|
||||||
|
var i;
|
||||||
|
|
||||||
|
for (i = 0; i < lines.length; i++) {
|
||||||
|
if (lines[i].match(pattern)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorWithStack() {
|
||||||
|
// Don't throw and catch if we don't have to, because it makes it harder
|
||||||
|
// for users to debug their code with exception breakpoints.
|
||||||
|
var error = new Error();
|
||||||
|
|
||||||
|
if (error.stack) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// But some browsers (e.g. Phantom) only provide a stack trace if we throw.
|
||||||
|
try {
|
||||||
|
throw new Error();
|
||||||
|
} catch (e) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function callerFile() {
|
||||||
|
var trace = new j$.StackTrace(errorWithStack().stack);
|
||||||
|
return trace.frames[2].file;
|
||||||
|
}
|
||||||
|
|
||||||
|
util.jasmineFile = (function() {
|
||||||
|
var result;
|
||||||
|
|
||||||
|
return function() {
|
||||||
|
var trace;
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
result = callerFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
return util;
|
return util;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user