From 1922514f2d81770bac40ae2bb786e0249813a479 Mon Sep 17 00:00:00 2001 From: "Christopher Amavisca, Greg Cobb and Luan Santos" Date: Mon, 10 Mar 2014 11:19:07 -0700 Subject: [PATCH] Specs without expectations should be alerted to the user - Add console.error to the HtmlReporter when there is a spec without any expectation - Change the spec's link text and color to include a warning - Create a status for specs to label them as "empty" - console is not accessible to IE unless you have developer tools open, so protect against that by mocking console. [#59424794] --- lib/jasmine-core/jasmine-html.js | 10 ++++- lib/jasmine-core/jasmine.css | 1 + lib/jasmine-core/jasmine.js | 6 +++ spec/core/SpecSpec.js | 7 ++-- spec/html/HtmlReporterSpec.js | 66 ++++++++++++++++++++++++++++++++ src/core/Spec.js | 6 +++ src/html/HtmlReporter.js | 10 ++++- src/html/_HTMLReporter.scss | 8 +++- 8 files changed, 107 insertions(+), 7 deletions(-) diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js index 74952879..e8c5b38f 100644 --- a/lib/jasmine-core/jasmine-html.js +++ b/lib/jasmine-core/jasmine-html.js @@ -95,6 +95,10 @@ jasmineRequire.HtmlReporter = function(j$) { var failures = []; this.specDone = function(result) { + if(result.status == 'empty' && console && console.error) { + console.error('Spec \'' + result.fullName + '\' has no expectations.'); + } + if (result.status != 'disabled') { specsExecuted++; } @@ -189,12 +193,16 @@ jasmineRequire.HtmlReporter = function(j$) { specListNode = createDom('ul', {className: 'specs'}); domParent.appendChild(specListNode); } + var specDescription = resultNode.result.description; + if(resultNode.result.status == 'empty') { + specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; + } specListNode.appendChild( createDom('li', { className: resultNode.result.status, id: 'spec-' + resultNode.result.id }, - createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) + createDom('a', {href: specHref(resultNode.result)}, specDescription) ) ); } diff --git a/lib/jasmine-core/jasmine.css b/lib/jasmine-core/jasmine.css index c622f643..8ef68c48 100644 --- a/lib/jasmine-core/jasmine.css +++ b/lib/jasmine-core/jasmine.css @@ -43,6 +43,7 @@ body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } .html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; } .html-reporter .summary li.passed a { color: #007069; } .html-reporter .summary li.failed a { color: #ca3a11; } +.html-reporter .summary li.empty a { color: #ba9d37; } .html-reporter .summary li.pending a { color: #ba9d37; } .html-reporter .description + .suite { margin-top: 0; } .html-reporter .suite { margin-top: 14px; } diff --git a/lib/jasmine-core/jasmine.js b/lib/jasmine-core/jasmine.js index 2717139e..50e3d6f1 100644 --- a/lib/jasmine-core/jasmine.js +++ b/lib/jasmine-core/jasmine.js @@ -242,6 +242,7 @@ getJasmineRequireObj().Spec = function(j$) { this.expectationResultFactory = attrs.expectationResultFactory || function() { }; this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; + this.expectCalled = false; if (!this.fn) { this.pend(); @@ -256,6 +257,7 @@ getJasmineRequireObj().Spec = function(j$) { } Spec.prototype.addExpectationResult = function(passed, data) { + this.expectCalled = true; if (passed) { return; } @@ -327,6 +329,10 @@ getJasmineRequireObj().Spec = function(j$) { return 'pending'; } + if(!this.expectCalled) { + return 'empty'; + } + if (this.result.failedExpectations.length > 0) { return 'failed'; } else { diff --git a/spec/core/SpecSpec.js b/spec/core/SpecSpec.js index c2056884..9719d1b9 100644 --- a/spec/core/SpecSpec.js +++ b/spec/core/SpecSpec.js @@ -193,9 +193,10 @@ describe("Spec", function() { expect(done).toHaveBeenCalled(); }); - it("#status returns passing by default", function() { - var spec = new j$.Spec({fn: jasmine.createSpy("spec body")}); - expect(spec.status()).toEqual('passed'); + it("#status returns empty by default", function(){ + var emptySpec = new j$.Spec({ fn: function () {} }); + emptySpec.execute(); + expect(emptySpec.status()).toBe("empty"); }); it("#status returns passed if all expectations in the spec have passed", function() { diff --git a/spec/html/HtmlReporterSpec.js b/spec/html/HtmlReporterSpec.js index 0919f3ed..c2a43534 100644 --- a/spec/html/HtmlReporterSpec.js +++ b/spec/html/HtmlReporterSpec.js @@ -46,6 +46,32 @@ describe("New HtmlReporter", function() { }); describe("when a spec is done", function() { + it("logs errors to the console if it is an empty spec", function() { + if (!window.console) { + window.console = { error: function(){} }; + } + + var env = new j$.Env(), + container = document.createElement('div'), + getContainer = function() {return container;}, + reporter = new j$.HtmlReporter({ + env: env, + getContainer: getContainer, + createElement: function() { return document.createElement.apply(document, arguments); }, + createTextNode: function() { return document.createTextNode.apply(document, arguments); } + }); + + spyOn(console, 'error'); + + reporter.initialize(); + + reporter.specDone({ + status: "empty", + fullName: 'Some Name' + }); + expect(console.error).toHaveBeenCalledWith("Spec \'Some Name\' has no expectations."); + }); + it("reports the status symbol of a disabled spec", function() { var env = new j$.Env(), container = document.createElement("div"), @@ -131,6 +157,46 @@ describe("New HtmlReporter", function() { }); describe("when Jasmine is done", function() { + it("adds EMPTY to the link title of specs that have no expectations", function() { + if (!window.console) { + window.console = { error: function(){} }; + } + var env = new j$.Env(), + container = document.createElement('div'), + getContainer = function() {return container;}, + reporter = new j$.HtmlReporter({ + env: env, + getContainer: getContainer, + createElement: function() { return document.createElement.apply(document, arguments); }, + createTextNode: function() { return document.createTextNode.apply(document, arguments); } + }); + + spyOn(console, 'error'); + + reporter.initialize(); + reporter.jasmineStarted({}); + reporter.suiteStarted({id: 1}); + reporter.specStarted({ + status: "empty", + id: 1, + description: 'Spec Description' + }); + reporter.specDone({ + status: "empty", + id: 1, + description: 'Spec Description' + }); + reporter.suiteDone({id: 1}); + reporter.jasmineDone({}); + + var summary = container.querySelector('.summary'); + var suite = summary.childNodes[0]; + var specs = suite.childNodes[1]; + var spec = specs.childNodes[0]; + var specLink = spec.childNodes[0]; + expect(specLink.innerHTML).toMatch(/SPEC HAS NO EXPECTATIONS/); + }); + it("reports the run time", function() { var env = new j$.Env(), container = document.createElement("div"), diff --git a/src/core/Spec.js b/src/core/Spec.js index 94c51522..c714ef17 100644 --- a/src/core/Spec.js +++ b/src/core/Spec.js @@ -13,6 +13,7 @@ getJasmineRequireObj().Spec = function(j$) { this.expectationResultFactory = attrs.expectationResultFactory || function() { }; this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; + this.expectCalled = false; if (!this.fn) { this.pend(); @@ -27,6 +28,7 @@ getJasmineRequireObj().Spec = function(j$) { } Spec.prototype.addExpectationResult = function(passed, data) { + this.expectCalled = true; if (passed) { return; } @@ -98,6 +100,10 @@ getJasmineRequireObj().Spec = function(j$) { return 'pending'; } + if(!this.expectCalled) { + return 'empty'; + } + if (this.result.failedExpectations.length > 0) { return 'failed'; } else { diff --git a/src/html/HtmlReporter.js b/src/html/HtmlReporter.js index a81f6583..34236493 100644 --- a/src/html/HtmlReporter.js +++ b/src/html/HtmlReporter.js @@ -66,6 +66,10 @@ jasmineRequire.HtmlReporter = function(j$) { var failures = []; this.specDone = function(result) { + if(result.status == 'empty' && console && console.error) { + console.error('Spec \'' + result.fullName + '\' has no expectations.'); + } + if (result.status != 'disabled') { specsExecuted++; } @@ -160,12 +164,16 @@ jasmineRequire.HtmlReporter = function(j$) { specListNode = createDom('ul', {className: 'specs'}); domParent.appendChild(specListNode); } + var specDescription = resultNode.result.description; + if(resultNode.result.status == 'empty') { + specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; + } specListNode.appendChild( createDom('li', { className: resultNode.result.status, id: 'spec-' + resultNode.result.id }, - createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) + createDom('a', {href: specHref(resultNode.result)}, specDescription) ) ); } diff --git a/src/html/_HTMLReporter.scss b/src/html/_HTMLReporter.scss index 7b1c76ab..41f38389 100644 --- a/src/html/_HTMLReporter.scss +++ b/src/html/_HTMLReporter.scss @@ -12,7 +12,7 @@ $page-background-color: #eee; $passing-color: #007069; $failing-color: #ca3a11; $pending-color: #ba9d37; - +$empty-color: #eff543; $neutral-color: #bababa; $font-size: 11px; @@ -152,7 +152,7 @@ body { color: #eee; &.failed { - background-color: $failing-color + background-color: $failing-color; } &.passed { @@ -260,6 +260,10 @@ body { color: $failing-color; } + &.empty a { + color: $pending-color; + } + &.pending a { color: $pending-color; }