From b8a8dc4562ff7e9f8aa5c86cbf26b04592f02c1d Mon Sep 17 00:00:00 2001 From: pivotal Date: Mon, 8 Dec 2008 11:35:10 -0800 Subject: [PATCH] dwf: refactoring how reporters work to add callbacks at all levels, separating how/when DOM writing works; --- example/example.html | 2 +- jasmine.iws | 164 +++++++++++++++++++++---------------------- lib/jasmine.js | 91 ++++++++++++------------ lib/json_reporter.js | 74 +++++++++++++++---- test/bootstrap.js | 156 ++++++++++++++++++++++++++-------------- 5 files changed, 288 insertions(+), 199 deletions(-) diff --git a/example/example.html b/example/example.html index 010a61f..40265c0 100644 --- a/example/example.html +++ b/example/example.html @@ -2,7 +2,7 @@ "http://www.w3.org/TR/html4/loose.dtd"> - Jasmine Tests + Jasmine Example diff --git a/jasmine.iws b/jasmine.iws index d60ba1d..70ff270 100644 --- a/jasmine.iws +++ b/jasmine.iws @@ -80,7 +80,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -101,16 +101,16 @@ - + - + - + @@ -119,7 +119,7 @@ - + @@ -137,7 +137,7 @@ - + @@ -305,6 +305,40 @@ + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -534,27 +514,6 @@ - - - - - - - - - - - - - - - - - - - - - @@ -562,6 +521,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/jasmine.js b/lib/jasmine.js index 9b8854f..ec220f9 100755 --- a/lib/jasmine.js +++ b/lib/jasmine.js @@ -18,11 +18,14 @@ if (typeof Function.method !== 'function') { } } +/* + * Jasmine internal classes & objects + */ + /* * object for holding results; allows for the results array to hold another nestedResults() * */ - var nestedResults = function() { var that = { totalCount: 0, @@ -121,6 +124,30 @@ var actionCollection = function () { return that; } +/* + * queuedFunction is how actionCollection's actions are implemented + */ +var queuedFunction = function(func, timeout, spec) { + var that = { + func: func, + next: function () { + spec.finish(); // default value is to be done after one function + }, + execute: function () { + if (timeout > 0) { + setTimeout(function () { + that.func.apply(spec); + that.next(); + }, timeout); + } else { + that.func.apply(spec); + that.next(); + } + } + } + return that; +} + /****************************************************************************** * Jasmine ******************************************************************************/ @@ -159,27 +186,6 @@ Matchers.method('should_not_equal', function (expected) { * Jasmine spec constructor */ -var queuedFunction = function(func, timeout, spec) { - var that = { - func: func, - next: function () { - spec.finish(); // default value is to be done after one function - }, - execute: function () { - if (timeout > 0) { - setTimeout(function () { - that.func.apply(spec); - that.next(); - }, timeout); - } else { - that.func.apply(spec); - that.next(); - } - } - } - return that; -} - var it = function (description, func) { var that = { description: description, @@ -302,39 +308,28 @@ var Runner = function () { return that; } -var JasmineReporters = {}; - var Jasmine = Runner(); var currentSuite; var currentSpec; -JasmineReporters.reporter = function (elementId) { +/* JasmineReporters.reporter + * Base object that will get called whenever a Spec, Suite, or Runner is done. It is up to + * descendants of this object to do something with the results (see json_reporter.js) + */ +var JasmineReporters = {}; + +JasmineReporters.reporter = function (callbacks) { var that = { - element: document.getElementById(elementId), - output: '', + callbacks: callbacks || {}, - reportRunnerResults: function (results) { that.output += ''; }, + doCallback: function (callback, results) { + if (callback) { callback(results); } + }, - reportSuiteResults: function (results) { that.output += ''; }, - - reportSpecResults: function (results) { that.output += ''; }, - - } - - // TODO: throw if no element? - if (that.element) { - that.element.innerHTML = ''; + reportRunnerResults: function (results) { that.doCallback(that.callbacks.runnerCallback, results); }, + reportSuiteResults: function (results) { that.doCallback(that.callbacks.suiteCallback, results); }, + reportSpecResults: function (results) { that.doCallback(that.callbacks.specCallback, results);} } return that; -} - -/* - * TODO: - * - HTML reporter - * - Shows pass/fail progress (just like bootstrap reporter) - * - Lists a Summary: total # specs, # of passed, # of failed - * - Failed reports lists all specs that failed and what the failure was - * - Failed output is styled with red - */ - +} \ No newline at end of file diff --git a/lib/json_reporter.js b/lib/json_reporter.js index 58d0338..dd42445 100644 --- a/lib/json_reporter.js +++ b/lib/json_reporter.js @@ -1,27 +1,73 @@ -JasmineReporters.JSON = function (elementId) { - var that = JasmineReporters.reporter(elementId); +/* + * JasmineReporters.JSON -- + * Basic reporter that keeps a JSON string of the most recent Spec, Suite or Runner + * result. Calling application can then do whatever it wants/needs with the string; + */ +JasmineReporters.JSON = function () { + var that = JasmineReporters.reporter(); + that.specJSON = ''; + that.suiteJSON = ''; + that.runnerJSON = ''; - that.reportRunnerResults = function (results) { - that.output = Object.toJSON(results); + var saveSpecResults = function (results) { + that.specJSON = Object.toJSON(results); + } + that.reportSpecResults = saveSpecResults; - if (that.element) { - that.element.innerHTML += that.output; - } - } + var saveSuiteResults = function (results) { + that.suiteJSON = Object.toJSON(results); + } + that.reportSuiteResults = saveSuiteResults; + + var saveRunnerResults = function (results) { + that.runnerJSON = Object.toJSON(results); + } + that.reportRunnerResults = saveRunnerResults; return that; } -JasmineReporters.IncrementalJSON = function (elementId) { - var that = JasmineReporters.reporter(elementId); +var domWriter = function (elementId) { + var that = { + element: document.getElementById(elementId), - that.reportSpecResults = function (results) { - that.output = Object.toJSON(results); - if (that.element) { - that.element.innerHTML += that.output; + write: function (text) { + if (that.element) { + that.element.innerHTML += text; } + } } + that.element.innerHTML = ''; + return that; } +JasmineReporters.JSONtoDOM = function (elementId) { + var that = JasmineReporters.JSON(); + + that.domWriter = domWriter(elementId); + + var writeRunnerResults = function (results) { + that.domWriter.write(Object.toJSON(results)); + }; + + that.reportRunnerResults = writeRunnerResults; + + return that; +} + + +//JasmineReporters.IncrementalJSON = function (elementId) { +// var that = JasmineReporters.reporter(elementId); +// +// that.reportSpecResults = function (results) { +// that.output = Object.toJSON(results); +// if (that.element) { +// that.element.innerHTML += that.output; +// } +// } +// +// return that; +//} + diff --git a/test/bootstrap.js b/test/bootstrap.js index 0e8dbbf..baa9fab 100755 --- a/test/bootstrap.js +++ b/test/bootstrap.js @@ -19,7 +19,7 @@ var reporter = function () { var fails_report = $('fails'); fails_report.show(); - iconElement = $('icons'); + var iconElement = $('icons'); iconElement.appendChild(new Element('img', {src: '../images/exclamation.png'})); var failMessages = $('fail_messages'); @@ -30,11 +30,11 @@ var reporter = function () { }, summary: function () { - summary = new Element('p', {'class': ((fails > 0) ? 'fail_in_summary' : '') }); - summary.innerHTML = total + ' expectations, ' + passes + ' passing, ' + fails + ' failed.'; + var el = new Element('p', {'class': ((fails > 0) ? 'fail_in_summary' : '') }); + el.innerHTML = total + ' expectations, ' + passes + ' passing, ' + fails + ' failed.'; var summaryElement = $('results_summary'); - summaryElement.appendChild(summary); + summaryElement.appendChild(el); summaryElement.show(); } } @@ -190,6 +190,7 @@ var testAsyncSpecs = function () { 'Calling waits(): Queued expectation failed'); } }; + a_spec.execute(); waitForDone(a_spec, mockSuite); @@ -450,7 +451,7 @@ var testBeforeAndAfterCallbacks = function () { var testSpecScope = function () { - suite = describe('one suite description', function () { + var suite = describe('one suite description', function () { it('should be a test with queuedFunctions', function() { runs(function() { this.foo = 0; @@ -545,7 +546,6 @@ var testRunner = function() { var testRunnerFinishCallback = function () { var runner = Runner(); var foo = 0; - var s runner.finish(); @@ -644,10 +644,70 @@ var testResults = function () { 'Expectation Failed count should be 1, but was ' + runner.results.failedCount); reporter.test((runner.results.description === 'All Jasmine Suites'), 'Jasmine Runner does not have the expected description, has: ' + runner.results.description); - }, 1000); + }, 500); } +var testReporterWithCallbacks = function () { + var foo = 0; + var bar = 0; + var baz = 0; + + var runner = Runner(); + describe('Suite for JSON Reporter with Callbacks', function () { + it('should be a test', function() { + runs(function () { + this.expects_that(true).should_equal(true); + }); + }); + it('should be a failing test', function() { + runs(function () { + this.expects_that(false).should_equal(true); + }); + }); + }); + describe('Suite for JSON Reporter with Callbacks 2', function () { + it('should be a test', function() { + runs(function () { + this.expects_that(true).should_equal(true); + }); + }); + + }); + + + var specCallback = function (results) { + foo++; + } + + var suiteCallback = function (results) { + bar++; + } + + var runnerCallback = function (results) { + baz++; + } + + callbackFunctions = { + specCallback: specCallback, + suiteCallback: suiteCallback, + runnerCallback: runnerCallback + } + + runner.reporter = JasmineReporters.reporter(callbackFunctions); + runner.execute(); + + setTimeout(function() { + reporter.test((foo === 3), + 'foo was expected to be 1, was ' + foo); + reporter.test((bar === 2), + 'bar was expected to be 2, was ' + bar); + reporter.test((baz === 1), + 'baz was expected to be 1, was ' + baz); + + }, 750); +} + var testJSONReporter = function () { var runner = Runner(); describe('Suite for JSON Reporter, NO DOM', function () { @@ -660,17 +720,27 @@ var testJSONReporter = function () { runner.reporter = JasmineReporters.JSON(); - reporter.test((runner.reporter !== undefined), - "Runner's reporter is undefined"); - reporter.test((runner.finishCallback !== undefined), - "Runner's finishCallback is undefined"); - runner.execute(); - var expectedJSONString = '{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"passed": true, "message": "Passed."}], "description": "should be a test"}], "description": "Suite for JSON Reporter, NO DOM"}], "description": "All Jasmine Suites"}'; setTimeout(function() { - reporter.test((runner.reporter.output === expectedJSONString), - 'Jasmine Reporter with No DOM does not have the expected report.
Expected:
' + expectedJSONString + '
Got:
' + runner.reporter.output); + var expectedSpecJSON = '{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"passed": true, "message": "Passed."}], "description": "should be a test"}'; + var expectedSuiteJSON = '{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"passed": true, "message": "Passed."}], "description": "should be a test"}], "description": "Suite for JSON Reporter, NO DOM"}'; + var expectedRunnerJSON = '{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"passed": true, "message": "Passed."}], "description": "should be a test"}], "description": "Suite for JSON Reporter, NO DOM"}], "description": "All Jasmine Suites"}'; + + specJSON = runner.reporter.specJSON; + reporter.test((specJSON === expectedSpecJSON), + 'JSON Reporter does not have the expected Spec results report.
Expected:
' + expectedSpecJSON + + '
Got:
' + specJSON); + + suiteJSON = runner.reporter.suiteJSON; + reporter.test((suiteJSON === expectedSuiteJSON), + 'JSON Reporter does not have the expected Suite results report.
Expected:
' + expectedSuiteJSON + + '
Got:
' + suiteJSON); + + runnerJSON = runner.reporter.runnerJSON; + reporter.test((runnerJSON === expectedRunnerJSON), + 'JSON Reporter does not have the expected Runner results report.
Expected:
' + expectedRunnerJSON + + '
Got:
' + runnerJSON); }, 500); } @@ -684,47 +754,17 @@ var testJSONReporterWithDOM = function () { }); }); - runner.reporter = JasmineReporters.JSON('json_reporter_results'); - + runner.reporter = JasmineReporters.JSONtoDOM('json_reporter_results'); runner.execute(); - var expectedJSONString = '{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"passed": true, "message": "Passed."}], "description": "should be a test"}], "description": "Suite for JSON Reporter/DOM"}], "description": "All Jasmine Suites"}'; setTimeout(function() { + var expectedJSONString = '{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"passed": true, "message": "Passed."}], "description": "should be a test"}], "description": "Suite for JSON Reporter/DOM"}], "description": "All Jasmine Suites"}'; + reporter.test((document.getElementById('json_reporter_results').innerHTML === expectedJSONString), - 'Jasmine Reporter did not output the string to the DOM, got:' + document.getElementById('json_reporter_results').innerHTML); - }, 500); + 'JSON Reporter with DOM did not write the expected report to the DOM, got:' + document.getElementById('json_reporter_results').innerHTML); + }, 250); } -var testJSONReporterWithIncrementalSpecReports = function() { - setTimeout( function () { - var runner = Runner(); - describe('Suite for Incremental JSON Reporter/DOM', function () { - it('should be a test', function() { - runs(function () { - this.expects_that(true).should_equal(true); - }); - }); - it('should be a failing test', function() { - runs(function () { - this.expects_that(false).should_equal(true); - }); - }); - }); - - runner.reporter = JasmineReporters.IncrementalJSON('json_reporter_results_incremental'); - runner.execute(); - var expectedJSONString = '{"totalCount": 1, "passedCount": 1, "failedCount": 0, "results": [{"passed": true, "message": "Passed."}], "description": "should be a test"}{"totalCount": 1, "passedCount": 0, "failedCount": 1, "results": [{"passed": false, "message": "Expected true but got false."}], "description": "should be a failing test"}' - - setTimeout(function() { - reporter.test((document.getElementById('json_reporter_results_incremental').innerHTML === expectedJSONString), - 'Jasmine Incremental Reporter did not output the correct string to the DOM, got ' + document.getElementById('json_reporter_results_incremental').innerHTML); - - }, 500); - }, 2500); - -} - - var runTests = function () { $('spinner').show(); @@ -740,14 +780,22 @@ var runTests = function () { testRunnerFinishCallback(); testNestedResults(); testResults(); - testJSONReporter(); - testJSONReporterWithDOM(); - testJSONReporterWithIncrementalSpecReports(); + + // Timing starts to matter with these tests; ALWAYS use setTimeout() + setTimeout(function () { + testReporterWithCallbacks(); + }, 2000); + setTimeout(function () { + testJSONReporter(); + }, 2750); + setTimeout(function () { + testJSONReporterWithDOM(); + }, 3000); setTimeout(function() { $('spinner').hide(); reporter.summary(); - }, 3500); + }, 4500); }