diff options
Diffstat (limited to 'src/js/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js')
-rw-r--r-- | src/js/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/src/js/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js b/src/js/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js new file mode 100644 index 0000000..c326ded --- /dev/null +++ b/src/js/lib/phantomjs_jasmine/jasmine-reporters/jasmine.phantomjs-reporter.js @@ -0,0 +1,204 @@ +(function() { + + if (! jasmine) { + throw new Exception("jasmine library does not exist in global namespace!"); + } + + function elapsed(startTime, endTime) { + return (endTime - startTime)/1000; + } + + function ISODateString(d) { + function pad(n) { return n < 10 ? '0'+n : n; } + + return d.getFullYear() + '-' + + pad(d.getMonth()+1) +'-' + + pad(d.getDate()) + 'T' + + pad(d.getHours()) + ':' + + pad(d.getMinutes()) + ':' + + pad(d.getSeconds()); + } + + function trim(str) { + return str.replace(/^\s+/, "" ).replace(/\s+$/, "" ); + } + + function escapeInvalidXmlChars(str) { + return str.replace(/\&/g, "&") + .replace(/</g, "<") + .replace(/\>/g, ">") + .replace(/\"/g, """) + .replace(/\'/g, "'"); + } + + /** + * PhantomJS Reporter generates JUnit XML for the given spec run. + * Allows the test results to be used in java based CI. + * It appends some DOM elements/containers, so that a PhantomJS script can pick that up. + * + * @param {boolean} consolidate whether to save nested describes within the + * same file as their parent; default: true + * @param {boolean} useDotNotation whether to separate suite names with + * dots rather than spaces (ie "Class.init" not + * "Class init"); default: true + */ + var PhantomJSReporter = function(consolidate, useDotNotation) { + this.consolidate = consolidate === jasmine.undefined ? true : consolidate; + this.useDotNotation = useDotNotation === jasmine.undefined ? true : useDotNotation; + }; + + PhantomJSReporter.prototype = { + reportRunnerStarting: function(runner) { + this.log("Runner Started."); + }, + + reportSpecStarting: function(spec) { + spec.startTime = new Date(); + + if (! spec.suite.startTime) { + spec.suite.startTime = spec.startTime; + } + + this.log(spec.suite.description + ' : ' + spec.description + ' ... '); + }, + + reportSpecResults: function(spec) { + var results = spec.results(); + spec.didFail = !results.passed(); + spec.status = spec.didFail ? 'Failed.' : 'Passed.'; + if (results.skipped) { + spec.status = 'Skipped.'; + } + this.log(spec.status); + + spec.duration = elapsed(spec.startTime, new Date()); + spec.output = '<testcase classname="' + this.getFullName(spec.suite) + + '" name="' + escapeInvalidXmlChars(spec.description) + '" time="' + spec.duration + '">'; + + var failure = ""; + var failures = 0; + var resultItems = results.getItems(); + for (var i = 0; i < resultItems.length; i++) { + var result = resultItems[i]; + + if (result.type == 'expect' && result.passed && !result.passed()) { + failures += 1; + failure += (failures + ": " + escapeInvalidXmlChars(result.message) + " "); + } + } + if (failure) { + spec.output += "<failure>" + trim(failure) + "</failure>"; + } + spec.output += "</testcase>"; + }, + + reportSuiteResults: function(suite) { + var results = suite.results(); + var specs = suite.specs(); + var specOutput = ""; + // for JUnit results, let's only include directly failed tests (not nested suites') + var failedCount = 0; + + suite.status = results.passed() ? 'Passed.' : 'Failed.'; + suite.statusPassed = results.passed(); + if (results.totalCount === 0) { // todo: change this to check results.skipped + suite.status = 'Skipped.'; + } + + // if a suite has no (active?) specs, reportSpecStarting is never called + // and thus the suite has no startTime -- account for that here + suite.startTime = suite.startTime || new Date(); + suite.duration = elapsed(suite.startTime, new Date()); + + for (var i = 0; i < specs.length; i++) { + failedCount += specs[i].didFail ? 1 : 0; + specOutput += "\n " + specs[i].output; + } + suite.output = '\n<testsuite name="' + this.getFullName(suite) + + '" errors="0" tests="' + specs.length + '" failures="' + failedCount + + '" time="' + suite.duration + '" timestamp="' + ISODateString(suite.startTime) + '">'; + suite.output += specOutput; + suite.output += "\n</testsuite>"; + this.log(suite.description + ": " + results.passedCount + " of " + results.totalCount + " expectations passed."); + }, + + reportRunnerResults: function(runner) { + this.log("Runner Finished."); + var suites = runner.suites(), + passed = true; + for (var i = 0; i < suites.length; i++) { + var suite = suites[i], + filename = 'TEST-' + this.getFullName(suite, true) + '.xml', + output = '<?xml version="1.0" encoding="UTF-8" ?>'; + + passed = !suite.statusPassed ? false : passed; + + // if we are consolidating, only write out top-level suites + if (this.consolidate && suite.parentSuite) { + continue; + } + else if (this.consolidate) { + output += "\n<testsuites>"; + output += this.getNestedOutput(suite); + output += "\n</testsuites>"; + this.createSuiteResultContainer(filename, output); + } + else { + output += suite.output; + this.createSuiteResultContainer(filename, output); + } + } + this.createTestFinishedContainer(passed); + }, + + getNestedOutput: function(suite) { + var output = suite.output; + for (var i = 0; i < suite.suites().length; i++) { + output += this.getNestedOutput(suite.suites()[i]); + } + return output; + }, + + createSuiteResultContainer: function(filename, xmloutput) { + jasmine.phantomjsXMLReporterResults = jasmine.phantomjsXMLReporterResults || []; + jasmine.phantomjsXMLReporterResults.push({ + "xmlfilename" : filename, + "xmlbody" : xmloutput + }); + }, + + createTestFinishedContainer: function(passed) { + jasmine.phantomjsXMLReporterPassed = passed + }, + + getFullName: function(suite, isFilename) { + var fullName; + if (this.useDotNotation) { + fullName = suite.description; + for (var parentSuite = suite.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { + fullName = parentSuite.description + '.' + fullName; + } + } + else { + fullName = suite.getFullName(); + } + + // Either remove or escape invalid XML characters + if (isFilename) { + return fullName.replace(/[^\w]/g, ""); + } + return escapeInvalidXmlChars(fullName); + }, + + log: function(str) { + var console = jasmine.getGlobal().console; + + if (console && console.log) { + console.log(str); + } + } + }; + + // export public + jasmine.PhantomJSReporter = PhantomJSReporter; +})(); |