diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js index 6a871546..4f9722bd 100644 --- a/lib/jasmine-core/jasmine-html.js +++ b/lib/jasmine-core/jasmine-html.js @@ -252,9 +252,21 @@ jasmineRequire.HtmlReporter = function(j$) { } for(i = 0; i < globalFailures.length; i++) { - var failure = globalFailures[i]; - var prefix = failure.globalErrorType === 'load' ? 'Error during loading: ' : afterAllMessagePrefix; - alert.appendChild(createDom('span', {className: errorBarClassName}, prefix + failure.message)); + alert.appendChild(createDom('span', {className: errorBarClassName}, globalFailureMessage(globalFailures[i]))); + } + + function globalFailureMessage(failure) { + if (failure.globalErrorType === 'load') { + var prefix = 'Error during loading: ' + failure.message; + + if (failure.filename) { + return prefix + ' in ' + failure.filename + ' line ' + failure.lineno; + } else { + return prefix; + } + } else { + return afterAllMessagePrefix + failure.message; + } } var results = find('.jasmine-results'); diff --git a/lib/jasmine-core/jasmine.css b/lib/jasmine-core/jasmine.css index 63199827..02042214 100644 --- a/lib/jasmine-core/jasmine.css +++ b/lib/jasmine-core/jasmine.css @@ -29,10 +29,9 @@ body { overflow-y: scroll; } .jasmine_html-reporter .jasmine-run-options .jasmine-payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; } .jasmine_html-reporter .jasmine-run-options .jasmine-payload.jasmine-open { display: block; } .jasmine_html-reporter .jasmine-bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } -.jasmine_html-reporter .jasmine-bar.jasmine-failed { background-color: #ca3a11; } +.jasmine_html-reporter .jasmine-bar.jasmine-failed, .jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; border-bottom: 1px solid #eee; } .jasmine_html-reporter .jasmine-bar.jasmine-passed { background-color: #007069; } .jasmine_html-reporter .jasmine-bar.jasmine-skipped { background-color: #bababa; } -.jasmine_html-reporter .jasmine-bar.jasmine-errored { background-color: #ca3a11; } .jasmine_html-reporter .jasmine-bar.jasmine-menu { background-color: #fff; color: #aaa; } .jasmine_html-reporter .jasmine-bar.jasmine-menu a { color: #333; } .jasmine_html-reporter .jasmine-bar a { color: white; } diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index a0a4b525..52304872 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -774,12 +774,14 @@ getJasmineRequireObj().Env = function(j$) { var globalErrors = new j$.GlobalErrors(); globalErrors.install(); - globalErrors.pushListener(function(message) { + globalErrors.pushListener(function(message, filename, lineno) { if (!suppressLoadErrors) { topSuite.result.failedExpectations.push({ passed: false, globalErrorType: 'load', - message: message + message: message, + filename: filename, + lineno: lineno }); } }); diff --git a/spec/core/integration/EnvSpec.js b/spec/core/integration/EnvSpec.js index cc5a44e5..8bbad5fe 100644 --- a/spec/core/integration/EnvSpec.js +++ b/spec/core/integration/EnvSpec.js @@ -2033,12 +2033,16 @@ describe("Env integration", function() { { passed: false, globalErrorType: 'load', - message: 'Uncaught SyntaxError: Unexpected end of input' + message: 'Uncaught SyntaxError: Unexpected end of input', + filename: 'borkenSpec.js', + lineno: 42 }, { passed: false, globalErrorType: 'load', - message: 'Uncaught Error: ENOCHEESE' + message: 'Uncaught Error: ENOCHEESE', + filename: undefined, + lineno: undefined } ]); @@ -2046,7 +2050,7 @@ describe("Env integration", function() { }); env.addReporter(reporter); - global.onerror('Uncaught SyntaxError: Unexpected end of input'); + global.onerror('Uncaught SyntaxError: Unexpected end of input', 'borkenSpec.js', 42); global.onerror('Uncaught Error: ENOCHEESE'); env.execute(); diff --git a/spec/html/HtmlReporterSpec.js b/spec/html/HtmlReporterSpec.js index b88cafa7..84bcd1a3 100644 --- a/spec/html/HtmlReporterSpec.js +++ b/spec/html/HtmlReporterSpec.js @@ -197,21 +197,47 @@ describe("HtmlReporter", function() { reporter.suiteDone({ status: 'failed', failedExpectations: [{ message: 'My Other Exception' }] }); reporter.jasmineDone({ failedExpectations: [ { message: 'Global After All Failure', globalErrorType: 'afterAll' }, - { message: 'Other Global' }, { message: 'Your JS is borken', globalErrorType: 'load' } ] }); var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar"); - expect(alertBars.length).toEqual(6); + expect(alertBars.length).toEqual(5); expect(alertBars[1].innerHTML).toMatch(/My After All Exception/); expect(alertBars[1].getAttribute("class")).toEqual('jasmine-bar jasmine-errored'); expect(alertBars[2].innerHTML).toMatch(/My Other Exception/); expect(alertBars[3].innerHTML).toMatch(/AfterAll Global After All Failure/); - // TODO: What about this? - expect(alertBars[4].innerHTML).toMatch(/Other Global/); + expect(alertBars[4].innerHTML).toMatch(/Error during loading: Your JS is borken/); + expect(alertBars[4].innerHTML).not.toMatch(/line/); + }); - expect(alertBars[5].innerHTML).toMatch(/Error during loading: Your JS is borken/); + it("displays file and line information if available", function() { + var env = new jasmineUnderTest.Env(), + container = document.createElement("div"), + getContainer = function() { return container; }, + reporter = new jasmineUnderTest.HtmlReporter({ + env: env, + getContainer: getContainer, + createElement: function() { return document.createElement.apply(document, arguments); }, + createTextNode: function() { return document.createTextNode.apply(document, arguments); } + }); + + reporter.initialize(); + + reporter.jasmineStarted({}); + reporter.jasmineDone({ failedExpectations: [ + { + message: 'Your JS is borken', + globalErrorType: 'load', + filename: 'some/file.js', + lineno: 42 + } + ] }); + + var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar"); + + expect(alertBars.length).toEqual(2); + expect(alertBars[1].innerHTML).toMatch(/Error during loading: Your JS is borken in some\/file.js line 42/); }); }); diff --git a/src/core/Env.js b/src/core/Env.js index 4875623f..966a6065 100644 --- a/src/core/Env.js +++ b/src/core/Env.js @@ -93,12 +93,14 @@ getJasmineRequireObj().Env = function(j$) { var globalErrors = new j$.GlobalErrors(); globalErrors.install(); - globalErrors.pushListener(function(message) { + globalErrors.pushListener(function(message, filename, lineno) { if (!suppressLoadErrors) { topSuite.result.failedExpectations.push({ passed: false, globalErrorType: 'load', - message: message + message: message, + filename: filename, + lineno: lineno }); } }); diff --git a/src/html/HtmlReporter.js b/src/html/HtmlReporter.js index da5b7df2..cbcd41b8 100644 --- a/src/html/HtmlReporter.js +++ b/src/html/HtmlReporter.js @@ -223,9 +223,21 @@ jasmineRequire.HtmlReporter = function(j$) { } for(i = 0; i < globalFailures.length; i++) { - var failure = globalFailures[i]; - var prefix = failure.globalErrorType === 'load' ? 'Error during loading: ' : afterAllMessagePrefix; - alert.appendChild(createDom('span', {className: errorBarClassName}, prefix + failure.message)); + alert.appendChild(createDom('span', {className: errorBarClassName}, globalFailureMessage(globalFailures[i]))); + } + + function globalFailureMessage(failure) { + if (failure.globalErrorType === 'load') { + var prefix = 'Error during loading: ' + failure.message; + + if (failure.filename) { + return prefix + ' in ' + failure.filename + ' line ' + failure.lineno; + } else { + return prefix; + } + } else { + return afterAllMessagePrefix + failure.message; + } } var results = find('.jasmine-results'); diff --git a/src/html/_HTMLReporter.scss b/src/html/_HTMLReporter.scss index 093692b9..201ffdc1 100644 --- a/src/html/_HTMLReporter.scss +++ b/src/html/_HTMLReporter.scss @@ -200,8 +200,9 @@ body { display: block; color: #eee; - &.jasmine-failed { + &.jasmine-failed, &.jasmine-errored { background-color: $failing-color; + border-bottom: 1px solid $page-background-color; } &.jasmine-passed { @@ -212,10 +213,6 @@ body { background-color: $neutral-color; } - &.jasmine-errored { - background-color: $failing-color; - } - &.jasmine-menu { background-color: #fff; color: $faint-text-color;