UNPKG

protractor-html-screenshot-reporter

Version:

An npm module and grunt plugin which generates your Protractor test reports in HTML with screenshots

227 lines (196 loc) 7.59 kB
var util = require('./lib/util') , mkdirp = require('mkdirp') , _ = require('underscore') , path = require('path'); /** Function: defaultPathBuilder * This function builds paths for a screenshot file. It is appended to the * constructors base directory and gets prependend with `.png` or `.json` when * storing a screenshot or JSON meta data file. * * Parameters: * (Object) spec - The spec currently reported * (Array) descriptions - The specs and their parent suites descriptions * (Object) result - The result object of the current test spec. * (Object) capabilities - WebDrivers capabilities object containing * in-depth information about the Selenium node * which executed the test case. * * Returns: * (String) containing the built path */ function defaultPathBuilder(spec, descriptions, results, capabilities) { return util.generateGuid(); } /** Function: defaultMetaDataBuilder * Uses passed information to generate a meta data object which can be saved * along with a screenshot. * You do not have to add the screenshots file path since this will be appended * automatially. * * Parameters: * (Object) spec - The spec currently reported * (Array) descriptions - The specs and their parent suites descriptions * (Object) result - The result object of the current test spec. * (Object) capabilities - WebDrivers capabilities object containing * in-depth information about the Selenium node * which executed the test case. * * Returns: * (Object) containig meta data to store along with a screenshot */ function defaultMetaDataBuilder(spec, descriptions, results, capabilities) { var metaData = { description: descriptions.join(' ') , passed: results.passed() , os: capabilities.caps_.platform , browser: { name: capabilities.caps_.browserName , version: capabilities.caps_.version } }; if(results.items_.length > 0) { var result = results.items_[0]; if(!results.passed()){ var failedItem = _.where(results.items_,{passed_: false})[0]; if(failedItem){ metaData.message = failedItem.message || 'Failed'; metaData.trace = failedItem.trace? (failedItem.trace.stack || 'No Stack trace information') : 'No Stack trace information'; } }else{ metaData.message = result.message || 'Passed'; metaData.trace = result.trace.stack; } } return metaData; } /** Class: ScreenshotReporter * Creates a new screenshot reporter using the given `options` object. * * For more information, please look at the README.md file. * * Parameters: * (Object) options - Object with options as described below. * * Possible options: * (String) baseDirectory - The path to the directory where screenshots are * stored. If not existing, it gets created. * Mandatory. * (Function) pathBuilder - A function which returns a path for a screenshot * to be stored. Optional. * (Function) metaDataBuilder - Function which returns an object literal * containing meta data to store along with * the screenshot. Optional. * (Boolean) takeScreenShotsForSkippedSpecs - Do you want to capture a * screenshot for a skipped spec? * Optional (default: false). */ function ScreenshotReporter(options) { options = options || {}; if(!options.baseDirectory || options.baseDirectory.length === 0) { throw new Error('Please pass a valid base directory to store the ' + 'screenshots into.'); } else { this.baseDirectory = options.baseDirectory; } if(typeof (options.cssOverrideFile) !== 'undefined' && _.isString(options.cssOverrideFile) ){ this.cssOverrideFile = options.cssOverrideFile; } else { this.cssOverrideFile = null; } this.pathBuilder = options.pathBuilder || defaultPathBuilder; this.disableMetaData = options.disableMetaData || false; this.combinedJsonFileName = options.combinedJsonFileName || 'combined.json'; this.docTitle = options.docTitle || 'Generated test report'; this.docHeader = options.docHeader || 'Test Results'; this.docName = options.docName || 'report.html'; this.metaDataBuilder = options.metaDataBuilder || defaultMetaDataBuilder; this.preserveDirectory = options.preserveDirectory || false; this.takeScreenShotsForSkippedSpecs = options.takeScreenShotsForSkippedSpecs || false; this.takeScreenShotsOnlyForFailedSpecs = options.takeScreenShotsOnlyForFailedSpecs || false; this.finalOptions = { takeScreenShotsOnlyForFailedSpecs: this.takeScreenShotsOnlyForFailedSpecs, takeScreenShotsForSkippedSpecs: this.takeScreenShotsForSkippedSpecs, metaDataBuilder: this.metaDataBuilder, pathBuilder: this.pathBuilder, disableMetaData: this.disableMetaData, combinedJsonFileName: this.combinedJsonFileName, baseDirectory: this.baseDirectory, docTitle: this.docTitle, docHeader: this.docHeader, docName: this.docName, cssOverrideFile: this.cssOverrideFile }; if(!this.preserveDirectory){ util.removeDirectory(this.finalOptions.baseDirectory); } } /** Function: reportSpecResults * Called by Jasmine when reporting results for a test spec. It triggers the * whole screenshot capture process and stores any relevant information. * * Parameters: * (Object) spec - The test spec to report. */ ScreenshotReporter.prototype.reportSpecResults = function reportSpecResults(spec) { /* global browser */ var self = this , results = spec.results() , takeScreenshot , finishReport; if(!self.takeScreenShotsForSkippedSpecs && results.skipped) { return; } takeScreenshot = !(self.takeScreenShotsOnlyForFailedSpecs && results.passed()); finishReport = function(png) { browser.getCapabilities().then(function (capabilities) { var descriptions = util.gatherDescriptions( spec.suite , [spec.description] ) , baseName = self.pathBuilder( spec , descriptions , results , capabilities ) , metaData = self.metaDataBuilder( spec , descriptions , results , capabilities ) , screenShotFile = baseName + '.png' , metaFile = baseName + '.json' , screenShotPath = path.join(self.baseDirectory, screenShotFile) , metaDataPath = path.join(self.baseDirectory, metaFile) // pathBuilder can return a subfoldered path too. So extract the // directory path without the baseName , directory = path.dirname(screenShotPath); metaData.screenShotFile = screenShotFile; mkdirp(directory, function(err) { if(err) { throw new Error('Could not create directory ' + directory); } else { util.addMetaData(metaData, metaDataPath, descriptions, self.finalOptions); if(takeScreenshot) { util.storeScreenShot(png, screenShotPath); } if (!self.finalOptions.disableMetaData) { util.storeMetaData(metaData, metaDataPath); } } }); }); }; if (takeScreenshot) { browser.takeScreenshot().then(function (png) { finishReport(png); }); } else { finishReport(); } }; module.exports = ScreenshotReporter;