diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js
index 4e9558cd..3c54d040 100644
--- a/lib/jasmine-core/jasmine-html.js
+++ b/lib/jasmine-core/jasmine-html.js
@@ -49,9 +49,14 @@ jasmineRequire.HtmlReporter = function(j$) {
};
ResultsStateBuilder.prototype.suiteDone = function(result) {
+ this.currentParent.updateResult(result);
if (this.currentParent !== this.topResults) {
this.currentParent = this.currentParent.parent;
}
+
+ if (result.status === 'failed') {
+ this.failureCount++;
+ }
};
ResultsStateBuilder.prototype.specStarted = function(result) {
@@ -86,10 +91,8 @@ jasmineRequire.HtmlReporter = function(j$) {
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
filterSpecs = options.filterSpecs,
timer = options.timer || noopTimer,
- results = [],
htmlReporterMain,
- symbols,
- failedSuites = [];
+ symbols;
this.initialize = function() {
clearPrior();
@@ -122,11 +125,11 @@ jasmineRequire.HtmlReporter = function(j$) {
};
this.suiteDone = function(result) {
- if (result.status == 'failed') {
- failedSuites.push(result);
- }
-
stateBuilder.suiteDone(result);
+
+ if (result.status === 'failed') {
+ failures.push(failureDom(result));
+ }
};
this.specStarted = function(result) {
@@ -152,21 +155,8 @@ jasmineRequire.HtmlReporter = function(j$) {
}
));
- if (result.status == 'failed') {
- var failure =
- createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
- failureDescription(result, stateBuilder.currentParent),
- createDom('div', {className: 'jasmine-messages'})
- );
- var messages = failure.childNodes[1];
-
- for (var i = 0; i < result.failedExpectations.length; i++) {
- var expectation = result.failedExpectations[i];
- messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
- messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
- }
-
- failures.push(failure);
+ if (result.status === 'failed') {
+ failures.push(failureDom(result));
}
};
@@ -176,59 +166,7 @@ jasmineRequire.HtmlReporter = function(j$) {
var order = doneResult && doneResult.order;
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
- banner.appendChild(
- createDom('div', { className: 'jasmine-run-options' },
- createDom('span', { className: 'jasmine-trigger' }, 'Options'),
- createDom('div', { className: 'jasmine-payload' },
- createDom('div', { className: 'jasmine-exceptions' },
- createDom('input', {
- className: 'jasmine-raise',
- id: 'jasmine-raise-exceptions',
- type: 'checkbox'
- }),
- createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
- createDom('div', { className: 'jasmine-throw-failures' },
- createDom('input', {
- className: 'jasmine-throw',
- id: 'jasmine-throw-failures',
- type: 'checkbox'
- }),
- createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
- createDom('div', { className: 'jasmine-random-order' },
- createDom('input', {
- className: 'jasmine-random',
- id: 'jasmine-random-order',
- type: 'checkbox'
- }),
- createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
- )
- ));
-
- var raiseCheckbox = find('#jasmine-raise-exceptions');
-
- raiseCheckbox.checked = !env.catchingExceptions();
- raiseCheckbox.onclick = onRaiseExceptionsClick;
-
- var throwCheckbox = find('#jasmine-throw-failures');
- throwCheckbox.checked = env.throwingExpectationFailures();
- throwCheckbox.onclick = onThrowExpectationsClick;
-
- var randomCheckbox = find('#jasmine-random-order');
- randomCheckbox.checked = env.randomTests();
- randomCheckbox.onclick = onRandomClick;
-
- var optionsMenu = find('.jasmine-run-options'),
- optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'),
- optionsPayload = optionsMenu.querySelector('.jasmine-payload'),
- isOpen = /\bjasmine-open\b/;
-
- optionsTrigger.onclick = function() {
- if (isOpen.test(optionsPayload.className)) {
- optionsPayload.className = optionsPayload.className.replace(isOpen, '');
- } else {
- optionsPayload.className += ' jasmine-open';
- }
- };
+ banner.appendChild(optionsMenu(env));
if (stateBuilder.specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
@@ -242,7 +180,7 @@ jasmineRequire.HtmlReporter = function(j$) {
var statusBarMessage = '';
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
- var failed = stateBuilder.failureCount + globalFailures.length + failedSuites.length > 0;
+ var failed = stateBuilder.failureCount + globalFailures.length > 0;
if (totalSpecsDefined > 0 || failed) {
statusBarMessage += pluralize('spec', stateBuilder.specsExecuted) + ', ' + pluralize('failure', stateBuilder.failureCount);
@@ -271,13 +209,6 @@ jasmineRequire.HtmlReporter = function(j$) {
var errorBarClassName = 'jasmine-bar jasmine-errored';
var afterAllMessagePrefix = 'AfterAll ';
- for(var i = 0; i < failedSuites.length; i++) {
- var failedSuite = failedSuites[i];
- for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
- alert.appendChild(createDom('span', {className: errorBarClassName}, afterAllMessagePrefix + failedSuite.failedExpectations[j].message));
- }
- }
-
for(i = 0; i < globalFailures.length; i++) {
alert.appendChild(createDom('span', {className: errorBarClassName}, globalFailureMessage(globalFailures[i])));
}
@@ -301,47 +232,6 @@ jasmineRequire.HtmlReporter = function(j$) {
summaryList(stateBuilder.topResults, summary);
- function summaryList(resultsTree, domParent) {
- var specListNode;
- for (var i = 0; i < resultsTree.children.length; i++) {
- var resultNode = resultsTree.children[i];
- if (filterSpecs && !hasActiveSpec(resultNode)) {
- continue;
- }
- if (resultNode.type == 'suite') {
- var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
- createDom('li', {className: 'jasmine-suite-detail'},
- createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
- )
- );
-
- summaryList(resultNode, suiteListNode);
- domParent.appendChild(suiteListNode);
- }
- if (resultNode.type == 'spec') {
- if (domParent.getAttribute('class') != 'jasmine-specs') {
- specListNode = createDom('ul', {className: 'jasmine-specs'});
- domParent.appendChild(specListNode);
- }
- var specDescription = resultNode.result.description;
- if(noExpectations(resultNode.result)) {
- specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
- }
- if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
- specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
- }
- specListNode.appendChild(
- createDom('li', {
- className: 'jasmine-' + resultNode.result.status,
- id: 'spec-' + resultNode.result.id
- },
- createDom('a', {href: specHref(resultNode.result)}, specDescription)
- )
- );
- }
- }
- }
-
if (failures.length) {
alert.appendChild(
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'},
@@ -370,6 +260,120 @@ jasmineRequire.HtmlReporter = function(j$) {
return this;
+ function failureDom(result) {
+ var failure =
+ createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
+ failureDescription(result, stateBuilder.currentParent),
+ createDom('div', {className: 'jasmine-messages'})
+ );
+ var messages = failure.childNodes[1];
+
+ for (var i = 0; i < result.failedExpectations.length; i++) {
+ var expectation = result.failedExpectations[i];
+ messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
+ messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
+ }
+
+ return failure;
+ }
+
+ function summaryList(resultsTree, domParent) {
+ var specListNode;
+ for (var i = 0; i < resultsTree.children.length; i++) {
+ var resultNode = resultsTree.children[i];
+ if (filterSpecs && !hasActiveSpec(resultNode)) {
+ continue;
+ }
+ if (resultNode.type === 'suite') {
+ var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
+ createDom('li', {className: 'jasmine-suite-detail jasmine-' + resultNode.result.status},
+ createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
+ )
+ );
+
+ summaryList(resultNode, suiteListNode);
+ domParent.appendChild(suiteListNode);
+ }
+ if (resultNode.type === 'spec') {
+ if (domParent.getAttribute('class') !== 'jasmine-specs') {
+ specListNode = createDom('ul', {className: 'jasmine-specs'});
+ domParent.appendChild(specListNode);
+ }
+ var specDescription = resultNode.result.description;
+ if(noExpectations(resultNode.result)) {
+ specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
+ }
+ if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
+ specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
+ }
+ specListNode.appendChild(
+ createDom('li', {
+ className: 'jasmine-' + resultNode.result.status,
+ id: 'spec-' + resultNode.result.id
+ },
+ createDom('a', {href: specHref(resultNode.result)}, specDescription)
+ )
+ );
+ }
+ }
+ }
+
+ function optionsMenu(env) {
+ var optionsMenuDom = createDom('div', { className: 'jasmine-run-options' },
+ createDom('span', { className: 'jasmine-trigger' }, 'Options'),
+ createDom('div', { className: 'jasmine-payload' },
+ createDom('div', { className: 'jasmine-exceptions' },
+ createDom('input', {
+ className: 'jasmine-raise',
+ id: 'jasmine-raise-exceptions',
+ type: 'checkbox'
+ }),
+ createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
+ createDom('div', { className: 'jasmine-throw-failures' },
+ createDom('input', {
+ className: 'jasmine-throw',
+ id: 'jasmine-throw-failures',
+ type: 'checkbox'
+ }),
+ createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
+ createDom('div', { className: 'jasmine-random-order' },
+ createDom('input', {
+ className: 'jasmine-random',
+ id: 'jasmine-random-order',
+ type: 'checkbox'
+ }),
+ createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
+ )
+ );
+
+ var raiseCheckbox = optionsMenuDom.querySelector('#jasmine-raise-exceptions');
+
+ raiseCheckbox.checked = !env.catchingExceptions();
+ raiseCheckbox.onclick = onRaiseExceptionsClick;
+
+ var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
+ throwCheckbox.checked = env.throwingExpectationFailures();
+ throwCheckbox.onclick = onThrowExpectationsClick;
+
+ var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
+ randomCheckbox.checked = env.randomTests();
+ randomCheckbox.onclick = onRandomClick;
+
+ var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),
+ optionsPayload = optionsMenuDom.querySelector('.jasmine-payload'),
+ isOpen = /\bjasmine-open\b/;
+
+ optionsTrigger.onclick = function() {
+ if (isOpen.test(optionsPayload.className)) {
+ optionsPayload.className = optionsPayload.className.replace(isOpen, '');
+ } else {
+ optionsPayload.className += ' jasmine-open';
+ }
+ };
+
+ return optionsMenuDom;
+ }
+
function failureDescription(result, suite) {
var wrapper = createDom('div', {className: 'jasmine-description'},
createDom('a', {title: result.description, href: specHref(result)}, result.description)
@@ -510,6 +514,10 @@ jasmineRequire.ResultsNode = function() {
this.last = function() {
return this.children[this.children.length - 1];
};
+
+ this.updateResult = function(result) {
+ this.result = result;
+ };
}
return ResultsNode;
diff --git a/spec/html/HtmlReporterSpec.js b/spec/html/HtmlReporterSpec.js
index 795a5ed9..45e1667a 100644
--- a/spec/html/HtmlReporterSpec.js
+++ b/spec/html/HtmlReporterSpec.js
@@ -177,69 +177,6 @@ describe("HtmlReporter", function() {
});
});
- describe("when there are suite failures", function () {
- it("displays the exceptions in their own alert bars", 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.suiteDone({ status: 'failed', failedExpectations: [{ message: 'My After All Exception' }] });
- reporter.suiteDone({ status: 'failed', failedExpectations: [{ message: 'My Other Exception' }] });
- reporter.jasmineDone({ failedExpectations: [
- { message: 'Global After All Failure', globalErrorType: 'afterAll' },
- { message: 'Your JS is borken', globalErrorType: 'load' }
- ] });
-
- var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
-
- 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/);
- expect(alertBars[4].innerHTML).toMatch(/Error during loading: Your JS is borken/);
- expect(alertBars[4].innerHTML).not.toMatch(/line/);
- });
-
- 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/);
- });
- });
-
describe("when Jasmine is done", function() {
it("adds a warning to the link title of specs that have no expectations", function() {
if (!window.console) {
@@ -351,7 +288,12 @@ describe("HtmlReporter", function() {
reporter.specStarted(specResult);
reporter.specDone(specResult);
- reporter.suiteDone({id: 2});
+ reporter.suiteDone({
+ id: 2,
+ status: 'things',
+ description: "inner suite",
+ fullName: "A Suite inner suite"
+ });
specResult = {
id: 209,
@@ -364,7 +306,12 @@ describe("HtmlReporter", function() {
reporter.specStarted(specResult);
reporter.specDone(specResult);
- reporter.suiteDone({id: 1});
+ reporter.suiteDone({
+ id: 1,
+ status: 'things',
+ description: "A Suite",
+ fullName: "A Suite"
+ });
reporter.jasmineDone({});
var summary = container.querySelector(".jasmine-summary");
@@ -379,7 +326,7 @@ describe("HtmlReporter", function() {
var node = outerSuite.childNodes[i];
classes.push(node.getAttribute("class"));
}
- expect(classes).toEqual(["jasmine-suite-detail", "jasmine-specs", "jasmine-suite", "jasmine-specs"]);
+ expect(classes).toEqual(["jasmine-suite-detail jasmine-things", "jasmine-specs", "jasmine-suite", "jasmine-specs"]);
var suiteDetail = outerSuite.childNodes[0];
var suiteLink = suiteDetail.childNodes[0];
@@ -430,6 +377,65 @@ describe("HtmlReporter", function() {
expect(payload).not.toHaveClass('jasmine-open');
});
+ describe("when there are global errors", function() {
+ it("displays the exceptions in their own alert bars", 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: 'Global After All Failure', globalErrorType: 'afterAll' },
+ { message: 'Your JS is borken', globalErrorType: 'load' }
+ ] });
+
+ var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
+
+ expect(alertBars.length).toEqual(3);
+ expect(alertBars[1].getAttribute("class")).toEqual('jasmine-bar jasmine-errored');
+ expect(alertBars[1].innerHTML).toMatch(/AfterAll Global After All Failure/);
+ expect(alertBars[2].innerHTML).toMatch(/Error during loading: Your JS is borken/);
+ expect(alertBars[2].innerHTML).not.toMatch(/line/);
+ });
+
+ 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/);
+ });
+ });
+
describe("UI for raising/catching exceptions", function() {
it("should be unchecked if the env is catching", function() {
var env = new jasmineUnderTest.Env(),
@@ -928,11 +934,11 @@ describe("HtmlReporter", function() {
description: "inner suite"
});
- var passingResult = {id: 123, status: "passed", passedExpectations: [{passed: true}], failedExpectations: []};
- reporter.specStarted(passingResult);
- reporter.specDone(passingResult);
+ var passingSpecResult = {id: 123, status: "passed", passedExpectations: [{passed: true}], failedExpectations: []};
+ reporter.specStarted(passingSpecResult);
+ reporter.specDone(passingSpecResult);
- var failingResult = {
+ var failingSpecResult = {
id: 124,
status: "failed",
description: "a failing spec",
@@ -945,36 +951,65 @@ describe("HtmlReporter", function() {
}
]
};
- reporter.specStarted(failingResult);
- reporter.specDone(failingResult);
- reporter.suiteDone({});
- reporter.suiteDone({});
- reporter.suiteDone({});
+
+ var passingSuiteResult = {
+ id: 1,
+ description: "A suite"
+ };
+ var failingSuiteResult = {
+ id: 2,
+ description: 'a suite',
+ fullName: 'a suite',
+ status: 'failed',
+ failedExpectations: [{ message: 'My After All Exception' }]
+ };
+ reporter.specStarted(failingSpecResult);
+ reporter.specDone(failingSpecResult);
+ reporter.suiteDone(passingSuiteResult);
+ reporter.suiteDone(failingSuiteResult);
+ reporter.suiteDone(passingSuiteResult);
reporter.jasmineDone({});
});
it("reports the specs counts", function() {
var alertBar = container.querySelector(".jasmine-alert .jasmine-bar");
- expect(alertBar.innerHTML).toMatch(/2 specs, 1 failure/);
+ expect(alertBar.innerHTML).toMatch(/2 specs, 2 failure/);
});
it("reports failure messages and stack traces", function() {
var specFailures = container.querySelector(".jasmine-failures");
- var failure = specFailures.childNodes[0];
- expect(failure.getAttribute("class")).toMatch(/jasmine-failed/);
- expect(failure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
+ expect(specFailures.childNodes.length).toEqual(2);
- var specDiv = failure.childNodes[0];
+ var specFailure = specFailures.childNodes[0];
+ expect(specFailure.getAttribute("class")).toMatch(/jasmine-failed/);
+ expect(specFailure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
+
+ var specDiv = specFailure.childNodes[0];
expect(specDiv.getAttribute("class")).toEqual("jasmine-description");
- var message = failure.childNodes[1].childNodes[0];
+ var message = specFailure.childNodes[1].childNodes[0];
expect(message.getAttribute("class")).toEqual("jasmine-result-message");
expect(message.innerHTML).toEqual("a failure message");
- var stackTrace = failure.childNodes[1].childNodes[1];
+ var stackTrace = specFailure.childNodes[1].childNodes[1];
expect(stackTrace.getAttribute("class")).toEqual("jasmine-stack-trace");
expect(stackTrace.innerHTML).toEqual("a stack trace");
+
+ var suiteFailure = specFailures.childNodes[0];
+ expect(suiteFailure.getAttribute("class")).toMatch(/jasmine-failed/);
+ expect(suiteFailure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
+
+ var suiteDiv = suiteFailure.childNodes[0];
+ expect(suiteDiv.getAttribute("class")).toEqual("jasmine-description");
+
+ var suiteMessage = suiteFailure.childNodes[1].childNodes[0];
+ expect(suiteMessage.getAttribute("class")).toEqual("jasmine-result-message");
+ expect(suiteMessage.innerHTML).toEqual("a failure message");
+
+ var suiteStackTrace = suiteFailure.childNodes[1].childNodes[1];
+ expect(suiteStackTrace.getAttribute("class")).toEqual("jasmine-stack-trace");
+ expect(suiteStackTrace.innerHTML).toEqual("a stack trace");
});
it('provides links to focus on a failure and each containing suite', function() {
@@ -1063,7 +1098,7 @@ describe("HtmlReporter", function() {
});
});
- describe("When the jasmineDone event's overallStatus is 'failed'", function() {
+ describe("When the jasmineDone event's overallStatus is 'incomplete'", function() {
it("has class jasmine-incomplete", function() {
var env = new jasmineUnderTest.Env(),
container = document.createElement("div"),
diff --git a/src/html/HtmlReporter.js b/src/html/HtmlReporter.js
index 72d4ee78..1dfde539 100644
--- a/src/html/HtmlReporter.js
+++ b/src/html/HtmlReporter.js
@@ -19,9 +19,14 @@ jasmineRequire.HtmlReporter = function(j$) {
};
ResultsStateBuilder.prototype.suiteDone = function(result) {
+ this.currentParent.updateResult(result);
if (this.currentParent !== this.topResults) {
this.currentParent = this.currentParent.parent;
}
+
+ if (result.status === 'failed') {
+ this.failureCount++;
+ }
};
ResultsStateBuilder.prototype.specStarted = function(result) {
@@ -56,10 +61,8 @@ jasmineRequire.HtmlReporter = function(j$) {
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
filterSpecs = options.filterSpecs,
timer = options.timer || noopTimer,
- results = [],
htmlReporterMain,
- symbols,
- failedSuites = [];
+ symbols;
this.initialize = function() {
clearPrior();
@@ -92,11 +95,11 @@ jasmineRequire.HtmlReporter = function(j$) {
};
this.suiteDone = function(result) {
- if (result.status == 'failed') {
- failedSuites.push(result);
- }
-
stateBuilder.suiteDone(result);
+
+ if (result.status === 'failed') {
+ failures.push(failureDom(result));
+ }
};
this.specStarted = function(result) {
@@ -122,21 +125,8 @@ jasmineRequire.HtmlReporter = function(j$) {
}
));
- if (result.status == 'failed') {
- var failure =
- createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
- failureDescription(result, stateBuilder.currentParent),
- createDom('div', {className: 'jasmine-messages'})
- );
- var messages = failure.childNodes[1];
-
- for (var i = 0; i < result.failedExpectations.length; i++) {
- var expectation = result.failedExpectations[i];
- messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
- messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
- }
-
- failures.push(failure);
+ if (result.status === 'failed') {
+ failures.push(failureDom(result));
}
};
@@ -146,59 +136,7 @@ jasmineRequire.HtmlReporter = function(j$) {
var order = doneResult && doneResult.order;
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
- banner.appendChild(
- createDom('div', { className: 'jasmine-run-options' },
- createDom('span', { className: 'jasmine-trigger' }, 'Options'),
- createDom('div', { className: 'jasmine-payload' },
- createDom('div', { className: 'jasmine-exceptions' },
- createDom('input', {
- className: 'jasmine-raise',
- id: 'jasmine-raise-exceptions',
- type: 'checkbox'
- }),
- createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
- createDom('div', { className: 'jasmine-throw-failures' },
- createDom('input', {
- className: 'jasmine-throw',
- id: 'jasmine-throw-failures',
- type: 'checkbox'
- }),
- createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
- createDom('div', { className: 'jasmine-random-order' },
- createDom('input', {
- className: 'jasmine-random',
- id: 'jasmine-random-order',
- type: 'checkbox'
- }),
- createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
- )
- ));
-
- var raiseCheckbox = find('#jasmine-raise-exceptions');
-
- raiseCheckbox.checked = !env.catchingExceptions();
- raiseCheckbox.onclick = onRaiseExceptionsClick;
-
- var throwCheckbox = find('#jasmine-throw-failures');
- throwCheckbox.checked = env.throwingExpectationFailures();
- throwCheckbox.onclick = onThrowExpectationsClick;
-
- var randomCheckbox = find('#jasmine-random-order');
- randomCheckbox.checked = env.randomTests();
- randomCheckbox.onclick = onRandomClick;
-
- var optionsMenu = find('.jasmine-run-options'),
- optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'),
- optionsPayload = optionsMenu.querySelector('.jasmine-payload'),
- isOpen = /\bjasmine-open\b/;
-
- optionsTrigger.onclick = function() {
- if (isOpen.test(optionsPayload.className)) {
- optionsPayload.className = optionsPayload.className.replace(isOpen, '');
- } else {
- optionsPayload.className += ' jasmine-open';
- }
- };
+ banner.appendChild(optionsMenu(env));
if (stateBuilder.specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
@@ -212,7 +150,7 @@ jasmineRequire.HtmlReporter = function(j$) {
var statusBarMessage = '';
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
- var failed = stateBuilder.failureCount + globalFailures.length + failedSuites.length > 0;
+ var failed = stateBuilder.failureCount + globalFailures.length > 0;
if (totalSpecsDefined > 0 || failed) {
statusBarMessage += pluralize('spec', stateBuilder.specsExecuted) + ', ' + pluralize('failure', stateBuilder.failureCount);
@@ -241,13 +179,6 @@ jasmineRequire.HtmlReporter = function(j$) {
var errorBarClassName = 'jasmine-bar jasmine-errored';
var afterAllMessagePrefix = 'AfterAll ';
- for(var i = 0; i < failedSuites.length; i++) {
- var failedSuite = failedSuites[i];
- for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
- alert.appendChild(createDom('span', {className: errorBarClassName}, afterAllMessagePrefix + failedSuite.failedExpectations[j].message));
- }
- }
-
for(i = 0; i < globalFailures.length; i++) {
alert.appendChild(createDom('span', {className: errorBarClassName}, globalFailureMessage(globalFailures[i])));
}
@@ -271,47 +202,6 @@ jasmineRequire.HtmlReporter = function(j$) {
summaryList(stateBuilder.topResults, summary);
- function summaryList(resultsTree, domParent) {
- var specListNode;
- for (var i = 0; i < resultsTree.children.length; i++) {
- var resultNode = resultsTree.children[i];
- if (filterSpecs && !hasActiveSpec(resultNode)) {
- continue;
- }
- if (resultNode.type == 'suite') {
- var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
- createDom('li', {className: 'jasmine-suite-detail'},
- createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
- )
- );
-
- summaryList(resultNode, suiteListNode);
- domParent.appendChild(suiteListNode);
- }
- if (resultNode.type == 'spec') {
- if (domParent.getAttribute('class') != 'jasmine-specs') {
- specListNode = createDom('ul', {className: 'jasmine-specs'});
- domParent.appendChild(specListNode);
- }
- var specDescription = resultNode.result.description;
- if(noExpectations(resultNode.result)) {
- specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
- }
- if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
- specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
- }
- specListNode.appendChild(
- createDom('li', {
- className: 'jasmine-' + resultNode.result.status,
- id: 'spec-' + resultNode.result.id
- },
- createDom('a', {href: specHref(resultNode.result)}, specDescription)
- )
- );
- }
- }
- }
-
if (failures.length) {
alert.appendChild(
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'},
@@ -340,6 +230,120 @@ jasmineRequire.HtmlReporter = function(j$) {
return this;
+ function failureDom(result) {
+ var failure =
+ createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
+ failureDescription(result, stateBuilder.currentParent),
+ createDom('div', {className: 'jasmine-messages'})
+ );
+ var messages = failure.childNodes[1];
+
+ for (var i = 0; i < result.failedExpectations.length; i++) {
+ var expectation = result.failedExpectations[i];
+ messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
+ messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
+ }
+
+ return failure;
+ }
+
+ function summaryList(resultsTree, domParent) {
+ var specListNode;
+ for (var i = 0; i < resultsTree.children.length; i++) {
+ var resultNode = resultsTree.children[i];
+ if (filterSpecs && !hasActiveSpec(resultNode)) {
+ continue;
+ }
+ if (resultNode.type === 'suite') {
+ var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
+ createDom('li', {className: 'jasmine-suite-detail jasmine-' + resultNode.result.status},
+ createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
+ )
+ );
+
+ summaryList(resultNode, suiteListNode);
+ domParent.appendChild(suiteListNode);
+ }
+ if (resultNode.type === 'spec') {
+ if (domParent.getAttribute('class') !== 'jasmine-specs') {
+ specListNode = createDom('ul', {className: 'jasmine-specs'});
+ domParent.appendChild(specListNode);
+ }
+ var specDescription = resultNode.result.description;
+ if(noExpectations(resultNode.result)) {
+ specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
+ }
+ if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
+ specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
+ }
+ specListNode.appendChild(
+ createDom('li', {
+ className: 'jasmine-' + resultNode.result.status,
+ id: 'spec-' + resultNode.result.id
+ },
+ createDom('a', {href: specHref(resultNode.result)}, specDescription)
+ )
+ );
+ }
+ }
+ }
+
+ function optionsMenu(env) {
+ var optionsMenuDom = createDom('div', { className: 'jasmine-run-options' },
+ createDom('span', { className: 'jasmine-trigger' }, 'Options'),
+ createDom('div', { className: 'jasmine-payload' },
+ createDom('div', { className: 'jasmine-exceptions' },
+ createDom('input', {
+ className: 'jasmine-raise',
+ id: 'jasmine-raise-exceptions',
+ type: 'checkbox'
+ }),
+ createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
+ createDom('div', { className: 'jasmine-throw-failures' },
+ createDom('input', {
+ className: 'jasmine-throw',
+ id: 'jasmine-throw-failures',
+ type: 'checkbox'
+ }),
+ createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
+ createDom('div', { className: 'jasmine-random-order' },
+ createDom('input', {
+ className: 'jasmine-random',
+ id: 'jasmine-random-order',
+ type: 'checkbox'
+ }),
+ createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
+ )
+ );
+
+ var raiseCheckbox = optionsMenuDom.querySelector('#jasmine-raise-exceptions');
+
+ raiseCheckbox.checked = !env.catchingExceptions();
+ raiseCheckbox.onclick = onRaiseExceptionsClick;
+
+ var throwCheckbox = optionsMenuDom.querySelector('#jasmine-throw-failures');
+ throwCheckbox.checked = env.throwingExpectationFailures();
+ throwCheckbox.onclick = onThrowExpectationsClick;
+
+ var randomCheckbox = optionsMenuDom.querySelector('#jasmine-random-order');
+ randomCheckbox.checked = env.randomTests();
+ randomCheckbox.onclick = onRandomClick;
+
+ var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),
+ optionsPayload = optionsMenuDom.querySelector('.jasmine-payload'),
+ isOpen = /\bjasmine-open\b/;
+
+ optionsTrigger.onclick = function() {
+ if (isOpen.test(optionsPayload.className)) {
+ optionsPayload.className = optionsPayload.className.replace(isOpen, '');
+ } else {
+ optionsPayload.className += ' jasmine-open';
+ }
+ };
+
+ return optionsMenuDom;
+ }
+
function failureDescription(result, suite) {
var wrapper = createDom('div', {className: 'jasmine-description'},
createDom('a', {title: result.description, href: specHref(result)}, result.description)
diff --git a/src/html/ResultsNode.js b/src/html/ResultsNode.js
index 24cea254..bc3e0b4c 100644
--- a/src/html/ResultsNode.js
+++ b/src/html/ResultsNode.js
@@ -13,6 +13,10 @@ jasmineRequire.ResultsNode = function() {
this.last = function() {
return this.children[this.children.length - 1];
};
+
+ this.updateResult = function(result) {
+ this.result = result;
+ };
}
return ResultsNode;