text: // Node v4 requires "use strict" to allow block scoped let & const
  "use strict";
  
  var MemoryFS = require("memory-fs");
  var realFs = require("fs");
  var webpack = require("webpack");
  var path = require("path");
  var jsdom = require("jsdom");
  
  var assert = require("assert");
  
  var compiler;
  var jsdomHtml;
  
  module.exports = {
    setup: function(webpackConfig, _jsdomHtml) {
      let fs = new MemoryFS();
  
      jsdomHtml = _jsdomHtml;
  
      // Makes webpack resolve style-loader to local folder instead of node_modules
      Object.assign(webpackConfig, {
        resolveLoader: {
          alias: {
            "style-loader": path.resolve(__dirname, "../")
          }
        }
      });
  
      compiler = webpack(webpackConfig);
  
      // Tell webpack to use our in-memory FS
      compiler.inputFileSystem = fs;
      compiler.outputFileSystem = fs;
      compiler.resolvers.normal.fileSystem = fs;
      compiler.resolvers.context.fileSystem = fs;
  
      ["readFileSync", "statSync"].forEach(fn => {
        // Preserve the reference to original function
        fs["mem" + fn] = fs[fn];
  
        compiler.inputFileSystem[fn] = function(_path) {
          // Fallback to real FS if file is not in the memoryFS
          if (fs.existsSync(_path)) {
            return fs["mem" + fn].apply(fs, arguments);
          } else {
            return realFs[fn].apply(realFs, arguments);
          }
        };
      });
  
      return fs;
    },
  
    /*
     *  @param {string} expected - Expected value.
     *  @param {function} done - Async callback from Mocha.
     *  @param {function} actual - Executed in the context of jsdom window, should return a string to compare to.
     */
    runCompilerTest: function(expected, done, actual, selector) {
      selector = selector || "head"
      compiler.run(function(err, stats) {
        if (stats.compilation.errors.length) {
          throw new Error(stats.compilation.errors);
        }
  
        const bundleJs = stats.compilation.assets["bundle.js"].source();
  
        jsdom.env({
          html: jsdomHtml,
          src: [bundleJs],
          virtualConsole: jsdom.createVirtualConsole().sendTo(console),
          done: function(err, window) {
            if (typeof actual === 'function') {
              assert.equal(actual.apply(window), expected);  
            } else {
              assert.equal(window.document.querySelector(selector).innerHTML.trim(), expected);
            }
            // free memory associated with the window
            window.close();
  
            done();
          }
        });
      });
    }
  };
  