UNPKG

sl-node-mocha

Version:

SeaLights mocha reporter

232 lines (206 loc) 8.52 kB
/** * Module dependencies. */ var mocha = require("mocha"), Base = mocha.reporters.Base, utils = mocha.utils, inherits = utils.inherits, log = console.log, sealights = require('sl-node'), slProcess = null, executionId = null, fs = require('fs'); /** * Expose `SeaLightsReporter`. */ exports = module.exports = SeaLightsReporter; /** * Initialize a new `SeaLightsReporter` reporter. * * @param {Runner} runner * @api public */ function SeaLightsReporter(runner, options) { Base.call(this, runner, options); var reporter = this, slProcess = null, executionId = null, shutDownTimeout = 60 * 1000, //Allow 1 minute to send all remaining footprints and events counters = { start:0, fail:0, pass:0, end:0, skipped:0 }, warnedOnce = false, reporterName = (options && options.reporterOptions && options.reporterOptions.reporter) || "spec", mochaReporters = mocha.reporters, ChainedReporterType = mochaReporters.spec, chainedReporter = null; if (mochaReporters.hasOwnProperty(reporterName)) { ChainedReporterType = mochaReporters[reporterName]; } else { try { ChainedReporterType = require(reporterName); } catch(e) { log.warn('[SeaLights for Mocha] Cannot find reporter ' + reporterName + ', using default Spec reporter'); //ChainedReporterType = mochaReporters.spec; //default } } chainedReporter = new ChainedReporterType(runner, options); // Before running any suite, initialize SL and create a test execution ID runner.suite.beforeAll(function(done) { console.log('[SeaLights for Mocha] Version ' + reporter.getVersion() + ", agent version " + sealights.getVersion()); console.log('[SeaLights for Mocha] Initializing'); sealights.init({ instrument: false }).then(function (_slProcess) { console.log('[SeaLights for Mocha] Initialized') slProcess = _slProcess; if (slProcess) { executionId = slProcess.createTestSuiteId(); slProcess.pushEvent({ type: 'executionIdStarted', executionId: executionId, framework: 'mocha', reporterVersion: reporter.getVersion() }); var __initTestId = slProcess.createTestId(executionId, '__init'); slProcess.setCurrentTestIdentifier(__initTestId, true); } done(); }).catch(function(e) { console.log('[SeaLights for Mocha] Initialization error'); console.error(e); done(); }); }); // After all tests have been executed, wait for the SL process to shut down runner.suite.afterAll(function(done){ if (!slProcess) return done(); slProcess.pushEvent({ type: 'executionIdEnded', executionId: executionId, meta:{counters:clone(counters)} }); slProcess.resume && slProcess.resume(); executionId = null; var doneCallbackInvoked = false; function invokeDoneCallback(err) { if (doneCallbackInvoked) return; if (handle) { try { clearTimeout(handle); //Don't keep the process running because of this timeout handle = null; } catch(e){ console.error(e); } } doneCallbackInvoked = true; if (done) { done(err); } } var handle = setTimeout(function() { if (doneCallbackInvoked) return; //callback already called handle = null; console.warn('\n[SeaLights for Mocha] Send operation timed out.'); invokeDoneCallback(); }, shutDownTimeout); this.timeout(0); //Disable mocha's timeout, since we handle the timeout here^^. try { console.log('\n[SeaLights for Mocha] Sending remaining data to server'); slProcess.shutDown(invokeDoneCallback); } catch(err) { console.error(err.stack); invokeDoneCallback(); } }); runner.on('test', function (test) { counters.start++; saveCounters(); try{ var testName = test.fullTitle(); var suitePath = getSuitePath(test); //log('RUN: ' + testName); if (!slProcess) { if (!warnedOnce){ console.warn('[SeaLights for Mocha] Mocha reporter was not properly intiailized.') warnedOnce = true; } return; } var testId = slProcess.createTestId(executionId, testName); slProcess.setCurrentTestIdentifier(testId); slProcess.pushEvent({ type: 'testStart', testName: testName, executionId: executionId, testPath: suitePath, meta:{counters:clone(counters)} }); slProcess.suspend && slProcess.suspend(); } catch(e) { writeToLog('error #68: '+e); } }); runner.on('fail', function (test, err) { counters.fail++; saveCounters(); if (err) writeToLog('fail error: '+err + '\n' + err.stack); try{ //log('FAIL: ' + test.fullTitle()); if (!slProcess) return; var testName = test.fullTitle(); var suitePath = getSuitePath(test); slProcess.pushEvent({ type: 'testEnd', testName: testName, executionId: executionId, testPath: suitePath, result: "failed", duration: test.duration, meta:{counters:clone(counters)} }); slProcess.resume && slProcess.resume(); } catch(e) { writeToLog('error #84: '+e); } }); runner.on('pass', function (test, err) { counters.pass++; saveCounters(); if (err) writeToLog('pass error: ' + err + '\n' + err.stack); try { //log('PASS: ' + test.fullTitle()); if (!slProcess) return; var testName = test.fullTitle(); var suitePath = getSuitePath(test); slProcess.pushEvent({ type: 'testEnd', testName: testName, executionId: executionId, testPath: suitePath, result: "passed", duration: test.duration, meta:{counters:clone(counters)} }); slProcess.resume && slProcess.resume(); } catch(e) { writeToLog('error #99: '+e); } }); runner.on('test end', function (test) { counters.end++; saveCounters(); try{ if (!slProcess) return; slProcess.setCurrentTestIdentifier(null); slProcess.resume && slProcess.resume(); } catch(e) { writeToLog('error #110: '+e); } }); runner.on('pending', function(test) { counters.skipped++; saveCounters(); if (!slProcess) return; var testName = test.fullTitle(); var suitePath = getSuitePath(test); slProcess.pushEvent({ type: 'testStart', testName: testName, executionId: executionId, testPath: suitePath, meta:{counters:clone(counters)} }); slProcess.pushEvent({ type: 'testEnd', testName: testName, executionId: executionId, testPath: suitePath, result: "skipped", meta:{counters:clone(counters)} }); slProcess.resume && slProcess.resume(); }); function getSuitePath(t){ //t = t.parent; var parts = []; while(t){ if (t.parent) parts.unshift(t.title); t = t.parent; } return parts; } function saveCounters(){ //var str = '[ ' + new Date().toString()+' ] ' + JSON.stringify(counters) + '\n'; //fs.appendFileSync('sl.mocha.log', str ); } function writeToLog(str){ slProcess && slProcess.writeToLog && slProcess.writeToLog(str); } function clone(o){ return JSON.parse(JSON.stringify(o)); } this.getExecutionId = function getExecutionId() { return executionId; } this.getVersion = function getVersion() { return require('../package.json').version; } } inherits(SeaLightsReporter, Base);