UNPKG

jasmine-istanbul-reporter

Version:

Jasmine report plugin that scrapes test pages for istanbul coverage stats and writes them to a set of files for eventual conversion to LCOV, Cobertura, etc.

119 lines (101 loc) 5.4 kB
var merge = require('merge'); var browser = require('./lib/browser'); var fileSystem = require('./lib/file-system'); var uuid = require('uuid'); var path = require('path'); var ArgumentError = require('./lib/error').ArgumentError; module.exports = JasmineReporterIstanbul; function JasmineReporterIstanbul(options) { var JasmineReporterIstanbulInstance = this; JasmineReporterIstanbulInstance.defaultOptions = { outputPath: './coverage', functionBindingList: [], driver: undefined }; JasmineReporterIstanbulInstance.preserveCoverage = preserveCoverage; JasmineReporterIstanbulInstance.specDone = specDone; JasmineReporterIstanbulInstance.options = processOptions(options); function preserveCoverage() { // TODO - find a way to clean this up without breaking the synchronous nature of this method // TODO - what about async methods that you wrap? maybe just easier to re-use/abuse sinon? var originalFunction = arguments.callee.originalFunction; var originalArguments = arguments; browser.executeScript('return __coverage__;', function (error, coverageObject) { if (error) throw error; originalFunction.apply(this, originalArguments); var coverageString = JSON.stringify(coverageObject); browser.executeScript('__coverage__ = JSON.parse(\'' + coverageString + '\');', function (error) { if (error) throw error; }); }); } function specDone() { // TODO - find a way to clean this up without breaking the synchronous nature of this method console.info("Attempting to gather coverage from the finished test"); var generatedCoverageFileName = uuid.v4() + '.json'; var generatedCoverageFilePath = path.join(JasmineReporterIstanbulInstance.options.outputPath, generatedCoverageFileName); browser.executeScript('return __coverage__;', function (error, coverageObject) { if (error || !coverageObject) { console.info("Failed to gather coverage from the finished test"); return; } fileSystem.writeJsonToFile(coverageObject, generatedCoverageFilePath, function (error) { if (error) { console.info("Failed to write coverage for the finished test to " + generatedCoverageFilePath); return; } console.info("Succeeded in writing coverage to " + generatedCoverageFilePath); }); }); } function processOptions(pendingOptions) { // TODO - these are not quite all on the same level of abstraction pendingOptions = merge(JasmineReporterIstanbulInstance.defaultOptions, pendingOptions); validateOptions(pendingOptions); applyOptions(pendingOptions); return pendingOptions; } function validateOptions(pendingOptions) { // TODO - these are not quite all on the same level of abstraction if (typeof pendingOptions.outputPath !== 'string') throw new ArgumentError('please pass in a string for the output path'); if (!(pendingOptions.functionBindingList instanceof Array)) throw new ArgumentError('please pass in an array of function bindings to wrap'); validateFunctionBindingList(pendingOptions.functionBindingList); if (!pendingOptions.driver) throw new ArgumentError('driver option is required'); } function applyOptions(pendingOptions) { wrapFunctionBindingList(pendingOptions.functionBindingList); browser.setDriver(pendingOptions.driver); } function validateFunctionBindingList(functionBindingList) { functionBindingList.forEach(function (functionBindingEntry) { validateFunctionBindingEntry(functionBindingEntry); }); } function validateFunctionBindingEntry(functionBindingEntry) { if (typeof functionBindingEntry !== 'object') throw new ArgumentError('please pass in an array of function bindings to wrap'); Object.keys(functionBindingEntry).forEach(function (functionBindingName) { var functionBindingObject = functionBindingEntry[functionBindingName]; var functionBinding = functionBindingObject[functionBindingName]; if (!(functionBinding instanceof Function)) throw new ArgumentError('please pass in an array of function bindings to wrap'); }); } function wrapFunctionBindingList(functionBindingList) { functionBindingList.forEach(function (functionBindingEntry) { wrapFunctionBindingEntry(functionBindingEntry); }); } function wrapFunctionBindingEntry(functionBindingEntry) { Object.keys(functionBindingEntry).forEach(function (functionBindingName) { var functionBindingObject = functionBindingEntry[functionBindingName]; var functionBinding = functionBindingObject[functionBindingName]; function Proxy() { this.originalFunction = functionBinding; this.originalFunction.displayName = this.originalFunction.name; var f = JasmineReporterIstanbulInstance.preserveCoverage; f.__proto__ = this; return f; } functionBindingObject[functionBindingName] = new Proxy(); }); } }