Cellarise/istanbul-reporter-clover-limits

View on GitHub
Test/testUtils.js

Summary

Maintainability
F
3 days
Test Coverage
"use strict";
var R = require("ramda");
var fs = require("fs");
var path = require('path');
var glob = require("glob");
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var exec = childProcess.exec;
var loopbackServer, beforeAllFlag = false, afterAllFlag = false;

module.exports = function testUtils(opts) {
  var processCoverage = function processCoverage(coverageData) {
    global.__cpmCoverage__ = R.merge(global.__cpmCoverage__, coverageData);
  };
  var _opts = opts;
  return {
    "browsers": _opts.browsers,
    "openBrowser": function openBrowser(worldContext, done) {
      var requestStream;
      var browser = this.browsers.length > 0 ? this.browsers[0] : null;
      var subLogger = worldContext.world.logger.child({"widget_type": 'LOOPBACK'});
      var Bacon, Server, server, Command, request;
      if (browser && !worldContext.browser.remote) { //if .remote exists then web server and browser already started
        //For white-box browser testing setup Request and Leadfoot Webdriver.js server api
        //The Bacon, leadfoot and request packages are only required for white-box browser based testing
        Bacon = require('baconjs').Bacon;
        Server = require("leadfoot/Server");
        server = new Server("http://localhost:4444/wd/hub");
        Command = require("leadfoot/Command");
        request = require("request");
        //start web server
        loopbackServer = spawn('node', ['server/server.js'], {
          'cwd': worldContext.cwd,
          'env': {'path': process.env.path,
            'PORT': worldContext.browser.config.port,
            'NODE_ENV': 'development'
          }
        });
        loopbackServer.stdout.on('data', function onStdout() {
          //worldContext.world.logger.info(data);
        });
        loopbackServer.stderr.on('data', function onStderr(data) {
          subLogger.warn(data.toString('utf8'));
        });
        //provide url on browser object
        worldContext.browser.url = worldContext.browser.config.url + ':' + worldContext.browser.config.port;
        //wait for loopback server startup
        requestStream = Bacon.retry({
          "source": function source() { return Bacon.fromNodeCallback(request, worldContext.browser.url); },
          "retries": 5,
          "delay": function delay() { return 5000; }
        });
        requestStream.onError(done);
        requestStream.onValue(function onValue() {
            //setup browser session
            server.createSession(browser)
              .then(function addSessionToWorld(session) {
                worldContext.browser.request = request;
                worldContext.browser.remote = new Command(session);
              })
              .finally(done);
          });
      } else {
        done();
      }
    },
    //get coverage information and teardown Leadfoot Webdriver.js server api
    "closeBrowser": function closeBrowser(worldContext, done) {
      var browser = this.browsers.length > 0 ? this.browsers[0] : null;
      if (browser && worldContext.browser.remote) { //if .remote exists then web server and browser available to kill
        worldContext.browser.request(_opts.url + '/coverage', function handler(error, response, body) {
          var vasync = require('vasync');
          if (!error && response.statusCode === 200) {
            processCoverage(JSON.parse(body.replace(/c:/g, 'C:')));
          }
          vasync.parallel({
            'funcs': [
              function f1(callback) {
                worldContext.browser.remote
                  .execute('return window.__coverage__')
                  .then(processCoverage)
                  .finally(function sessionQuit() {
                    worldContext.browser.remote.quit()
                      .finally(function quit(){
                        callback();
                      });
                  });
              },
              function f2(callback) {
                exec('taskkill /pid ' + loopbackServer.pid + ' /T /F', callback);
              }
            ]
          }, done);
        });
      } else {
        done();
      }
    },
    "beforeAll": function b(beforeAll, worldContext) {
      if (!beforeAllFlag) {
        beforeAllFlag = true;
        beforeAll(function beforeFn(done) {
          this.openBrowser(worldContext, done);
        }.bind(this));
      }
    },
    "afterAll": function a(afterAll, worldContext) {
      if (!afterAllFlag) {
        afterAllFlag = true;
        afterAll(function afterFn(done) {
          this.closeBrowser(worldContext, done);
        }.bind(this));
      }
    },
    "before": function b(before, worldContext) {
      before(function beforeFn(done) {
        if (worldContext.world.hasOwnProperty("before")) {
          worldContext.world.before(done);
          delete worldContext.world.before;
        } else {
          done();
        }
      });
    },
    "after": function a(after, worldContext) {
      after(function afterFn(done) {
        if (worldContext.world.hasOwnProperty("after")) {
          worldContext.world.after(done);
          delete worldContext.world.after;
        } else {
          done();
        }
      });
    },
    "getTestFeaturesDir": function getTestFeaturesDir(directories, cwd) {
      var testDir = path.join(cwd, directories.test);
      if (directories.hasOwnProperty("testFeatures")) {
        return cwd + path.sep + directories.testFeatures + path.sep;
      }
      return testDir + path.sep;
    },
    "getTestLibrariesDir": function getTestLibrariesDir(directories, cwd) {
      var testDir = path.join(cwd, directories.test);
      if (directories.hasOwnProperty("testLibrary")) {
        return path.join(cwd, directories.testLibrary);
      }
      return testDir;
    },
    "getTstGlob": function getTstGlob(testFeaturesDir) {
      if (process.env.hasOwnProperty("YADDA_FEATURE_GLOB")) {
        return R.map(function mapTstGlob(dir) {
          return dir.replace(/\//g, "\\");
        }, glob.sync(testFeaturesDir + "**/*" + process.env.YADDA_FEATURE_GLOB + "*"));
      }
      return [];
    },
    "requireLibraries": function requireLibraries(librariesArr) {
      return librariesArr.reduce(function requireLibrary(librariesAcc, library) {
        return librariesAcc.concat(require(library));
      }, []);
    },
    "getLibraries": function getLibraries(testFeaturesDir, testLibrariesDir, file, feature) {
      var libraries = [];
      var libraryPath = this.getLibraryRelativePath(testFeaturesDir, testLibrariesDir, file);
      var defaultFeaturePath = this.getDefaultFeaturePath(libraryPath, file);
      //get libraries to load and load
      if (feature.annotations.hasOwnProperty("libraries")) {
        //load any libraries annotated in the feature file
        libraries = R.map(function mapLibraries(value) {
          return path.resolve(libraryPath, value);
        }, feature.annotations.libraries.split(","));
      }
      //add default library
      if (defaultFeaturePath) {
        libraries.push(defaultFeaturePath);
      }
      return libraries;
    },
    "getDefaultFeaturePath": function getDefaultFeaturePath(libraryPath, file) {
      var defaultFeaturePath = path.join(libraryPath, path.basename(file, ".feature") + "-steps.js");
      if (fs.existsSync(defaultFeaturePath)) {
        return defaultFeaturePath;
      }
      return null;
    },
    "getLibraryRelativePath": function getLibraryRelativePath(testFeaturesDir, testLibrariesDir, file) {
      var featureRelativePath = path.relative(testFeaturesDir, path.dirname(file));
      return path.resolve(testLibrariesDir, featureRelativePath);
    },
    "getTestSuite": function getTestSuite(Yadda, worldContext, directories) {
      var testFeaturesDir = this.getTestFeaturesDir(directories, worldContext.cwd);
      var testLibrariesDir = this.getTestLibrariesDir(directories, worldContext.cwd);
      var tstGlob = this.getTstGlob(testFeaturesDir);
      var self = this;
      return function testSuite() {
        //beforeAll
        self.beforeAll(before, worldContext);

        new Yadda.FeatureFileSearch([testFeaturesDir]).each(function eachFeatureFile(file) {
          //if YADDA_FEATURE_GLOB exists then check if featureFile in YADDA_FEATURE_GLOB
          if (tstGlob.length > 0 && !R.contains(file, tstGlob)) {
            return;
          }

          featureFile(file, function featureFile(feature) {
            var libraries = self.getLibraries(testFeaturesDir, testLibrariesDir, file, feature);
            var loadedLibraries = self.requireLibraries(libraries);
            //initiate yadda and execute each scenario
            var yadda = new Yadda.Yadda(loadedLibraries, worldContext);
            scenarios(feature.scenarios, function scenario(scenarioParam) {
              //before test setup
              self.before(before, worldContext);
              //run steps
              /*eslint max-nested-callbacks:0 */
              steps(scenarioParam.steps, function step(stepParam, done) {
                yadda.run(stepParam, worldContext, done);
              });
              //after test teardown
              self.after(after, worldContext);
            });
          });

          //afterAll
          self.afterAll(after, worldContext);
        });
      };
    }
  };
};