From d742ada71d2d78d8753367ac671035441e7221ba Mon Sep 17 00:00:00 2001 From: Steve Gravrock Date: Mon, 18 Dec 2017 16:51:41 -0800 Subject: [PATCH] Added links to re-run the suites containing a failing spec [Finishes #25508053] --- lib/jasmine-core/jasmine-html.js | 32 +++++++++++++++++++++++++--- lib/jasmine-core/jasmine.css | 2 +- spec/html/HtmlReporterSpec.js | 36 ++++++++++++++++++++++++++------ src/html/HtmlReporter.js | 32 +++++++++++++++++++++++++--- src/html/_HTMLReporter.scss | 1 + 5 files changed, 90 insertions(+), 13 deletions(-) diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js index debec5e2..50de0be7 100644 --- a/lib/jasmine-core/jasmine-html.js +++ b/lib/jasmine-core/jasmine-html.js @@ -128,9 +128,7 @@ jasmineRequire.HtmlReporter = function(j$) { var failure = createDom('div', {className: 'jasmine-spec-detail jasmine-failed'}, - createDom('div', {className: 'jasmine-description'}, - createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) - ), + failureDescription(result, currentParent), createDom('div', {className: 'jasmine-messages'}) ); var messages = failure.childNodes[1]; @@ -349,6 +347,34 @@ jasmineRequire.HtmlReporter = function(j$) { return this; + function failureDescription(result, suite) { + var wrapper = createDom('div', {className: 'jasmine-description'}, + createDom('a', {title: result.description, href: specHref(result)}, result.description) + ); + var suiteLink; + + while (suite && suite.parent) { + wrapper.insertBefore(createTextNode(' > '), wrapper.firstChild); + suiteLink = createDom('a', {href: suiteHref(suite)}, suite.result.description); + wrapper.insertBefore(suiteLink, wrapper.firstChild); + + suite = suite.parent; + } + + return wrapper; + } + + function suiteHref(suite) { + var els = []; + + while (suite && suite.parent) { + els.unshift(suite.result.description); + suite = suite.parent; + } + + return addToExistingQueryString('spec', els.join(' ')); + } + function find(selector) { return getContainer().querySelector('.jasmine_html-reporter ' + selector); } diff --git a/lib/jasmine-core/jasmine.css b/lib/jasmine-core/jasmine.css index 002cb17b..a10d0838 100644 --- a/lib/jasmine-core/jasmine.css +++ b/lib/jasmine-core/jasmine.css @@ -51,7 +51,7 @@ body { overflow-y: scroll; } .jasmine_html-reporter .jasmine-suite { margin-top: 14px; } .jasmine_html-reporter .jasmine-suite a { color: #333; } .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail { margin-bottom: 28px; } -.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; } +.jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description { background-color: #ca3a11; color: white; } .jasmine_html-reporter .jasmine-failures .jasmine-spec-detail .jasmine-description a { color: white; } .jasmine_html-reporter .jasmine-result-message { padding-top: 14px; color: #333; white-space: pre; } .jasmine_html-reporter .jasmine-result-message span.jasmine-result { display: block; } diff --git a/spec/html/HtmlReporterSpec.js b/spec/html/HtmlReporterSpec.js index 27c2da49..ed93195c 100644 --- a/spec/html/HtmlReporterSpec.js +++ b/spec/html/HtmlReporterSpec.js @@ -395,7 +395,6 @@ describe("HtmlReporter", function() { var specLink = spec.childNodes[0]; expect(specLink.innerHTML).toEqual("with a spec"); expect(specLink.getAttribute("href")).toEqual("?foo=bar&spec=A Suite with a spec"); -// expect(specLink.getAttribute("title")).toEqual("A Suite with a spec"); }); it("has an options menu", function() { @@ -922,6 +921,14 @@ describe("HtmlReporter", function() { reporter.initialize(); reporter.jasmineStarted({ totalSpecsDefined: 1 }); + reporter.suiteStarted({ + id: 1, + description: "A suite" + }); + reporter.suiteStarted({ + id: 2, + description: "inner suite" + }); var passingResult = {id: 123, status: "passed", passedExpectations: [{passed: true}], failedExpectations: []}; reporter.specStarted(passingResult); @@ -931,7 +938,7 @@ describe("HtmlReporter", function() { id: 124, status: "failed", description: "a failing spec", - fullName: "a suite with a failing spec", + fullName: "a suite inner suite a failing spec", passedExpectations: [], failedExpectations: [ { @@ -942,6 +949,9 @@ describe("HtmlReporter", function() { }; reporter.specStarted(failingResult); reporter.specDone(failingResult); + reporter.suiteDone({}); + reporter.suiteDone({}); + reporter.suiteDone({}); reporter.jasmineDone({}); }); @@ -960,10 +970,6 @@ describe("HtmlReporter", function() { var specDiv = failure.childNodes[0]; expect(specDiv.getAttribute("class")).toEqual("jasmine-description"); - var specLink = specDiv.childNodes[0]; - expect(specLink.getAttribute("title")).toEqual("a suite with a failing spec"); - expect(specLink.getAttribute("href")).toEqual("?foo=bar&spec=a suite with a failing spec"); - var message = failure.childNodes[1].childNodes[0]; expect(message.getAttribute("class")).toEqual("jasmine-result-message"); expect(message.innerHTML).toEqual("a failure message"); @@ -973,6 +979,24 @@ describe("HtmlReporter", function() { expect(stackTrace.innerHTML).toEqual("a stack trace"); }); + it('provides links to focus on a failure and each containing suite', function() { + var description = container.querySelector('.jasmine-failures .jasmine-description'); + var links = description.querySelectorAll('a'); + + expect(description.textContent).toEqual('A suite > inner suite > a failing spec'); + + expect(links.length).toEqual(3); + expect(links[0].textContent).toEqual('A suite'); + + expect(links[0].getAttribute('href')).toMatch(/\?foo=bar&spec=A suite/); + + expect(links[1].textContent).toEqual('inner suite'); + expect(links[1].getAttribute('href')).toMatch(/\?foo=bar&spec=A suite inner suite/); + + expect(links[2].textContent).toEqual('a failing spec'); + expect(links[2].getAttribute('href')).toMatch(/\?foo=bar&spec=a suite inner suite a failing spec/); + }); + it("allows switching between failure details and the spec summary", function() { var menuBar = container.querySelectorAll(".jasmine-bar")[1]; diff --git a/src/html/HtmlReporter.js b/src/html/HtmlReporter.js index e089d536..181ee3a9 100644 --- a/src/html/HtmlReporter.js +++ b/src/html/HtmlReporter.js @@ -98,9 +98,7 @@ jasmineRequire.HtmlReporter = function(j$) { var failure = createDom('div', {className: 'jasmine-spec-detail jasmine-failed'}, - createDom('div', {className: 'jasmine-description'}, - createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) - ), + failureDescription(result, currentParent), createDom('div', {className: 'jasmine-messages'}) ); var messages = failure.childNodes[1]; @@ -319,6 +317,34 @@ jasmineRequire.HtmlReporter = function(j$) { return this; + function failureDescription(result, suite) { + var wrapper = createDom('div', {className: 'jasmine-description'}, + createDom('a', {title: result.description, href: specHref(result)}, result.description) + ); + var suiteLink; + + while (suite && suite.parent) { + wrapper.insertBefore(createTextNode(' > '), wrapper.firstChild); + suiteLink = createDom('a', {href: suiteHref(suite)}, suite.result.description); + wrapper.insertBefore(suiteLink, wrapper.firstChild); + + suite = suite.parent; + } + + return wrapper; + } + + function suiteHref(suite) { + var els = []; + + while (suite && suite.parent) { + els.unshift(suite.result.description); + suite = suite.parent; + } + + return addToExistingQueryString('spec', els.join(' ')); + } + function find(selector) { return getContainer().querySelector('.jasmine_html-reporter ' + selector); } diff --git a/src/html/_HTMLReporter.scss b/src/html/_HTMLReporter.scss index 4031a777..f7eace89 100644 --- a/src/html/_HTMLReporter.scss +++ b/src/html/_HTMLReporter.scss @@ -313,6 +313,7 @@ body { .jasmine-description { background-color: $failing-color; + color: white; a { color: white;