<commit_before>var Joi = require('joi');

module.exports = function(server, feed) {
    server.route({
        method: 'GET',
        path: '/',
        handler: function(request, reply) {
            server.methods.getFolders(function(err, folders) {
                if (err) {
                    console.log(err);
                } else {
                    reply(folders).code(200);
                }
            })
        }
    });

    server.route({
        method: 'GET',
        path: '/{folder_name}/{item_name}',
        handler: function(request, reply) {
            server.methods.getFolderItem(request.params.folder_name, request.params.item_name, function(err, item) {
                if (err) {
                    console.log(err, request.params.folder_name, request.params.item_name);
                    reply(err).code(404);
                } else {
                    reply(item).code(200);
                }
            })
        }
    });

    server.route({
        method: 'GET',
        path: '/{folder_name}',
        handler: function(request, reply) {
            var requested = {
                folder: request.params.folder_name,
                limit: request.query.limit,
                featured: request.query.featured,
                meta: request.query.meta,
                random: request.query.random
            };
            server.methods.getFolder(requested, function(err, folder_items) {
                if (err) {
                    console.log(err, requested.folder);
                    reply(err).code(404);
                } else {
                    reply(folder_items).code(200);
                }
            })
        },
        config: {
            validate: {
                query: {
                    limit: Joi.number().integer(),
                    featured: Joi.boolean(),
                    meta: Joi.boolean(),
                    random: Joi.boolean()
                }
            }
        }
    });
    server.route({
        method: 'GET',
        path: '/sitemap.xml',
        handler: function(request, reply) {
            reply(server.app.sitemap.toString()).code(200);
        }
    });
    server.route({
        method: 'GET',
        path: '/feed.rss',
        handler: function(request, reply) {
            reply(server.app.feed.xml()).code(200);
        }
    });
}
<commit_msg>Changed rss xml url<commit_after>var Joi = require('joi');

module.exports = function(server, feed) {
    server.route({
        method: 'GET',
        path: '/',
        handler: function(request, reply) {
            server.methods.getFolders(function(err, folders) {
                if (err) {
                    console.log(err);
                } else {
                    reply(folders).code(200);
                }
            })
        }
    });

    server.route({
        method: 'GET',
        path: '/{folder_name}/{item_name}',
        handler: function(request, reply) {
            server.methods.getFolderItem(request.params.folder_name, request.params.item_name, function(err, item) {
                if (err) {
                    console.log(err, request.params.folder_name, request.params.item_name);
                    reply(err).code(404);
                } else {
                    reply(item).code(200);
                }
            })
        }
    });

    server.route({
        method: 'GET',
        path: '/{folder_name}',
        handler: function(request, reply) {
            var requested = {
                folder: request.params.folder_name,
                limit: request.query.limit,
                featured: request.query.featured,
                meta: request.query.meta,
                random: request.query.random
            };
            server.methods.getFolder(requested, function(err, folder_items) {
                if (err) {
                    console.log(err, requested.folder);
                    reply(err).code(404);
                } else {
                    reply(folder_items).code(200);
                }
            })
        },
        config: {
            validate: {
                query: {
                    limit: Joi.number().integer(),
                    featured: Joi.boolean(),
                    meta: Joi.boolean(),
                    random: Joi.boolean()
                }
            }
        }
    });
    server.route({
        method: 'GET',
        path: '/sitemap.xml',
        handler: function(request, reply) {
            reply(server.app.sitemap.toString()).code(200);
        }
    });
    server.route({
        method: 'GET',
        path: '/rss.xml',
        handler: function(request, reply) {
            reply(server.app.feed.xml()).code(200);
        }
    });
}
<|endoftext|>


<commit_before>/*
 * Sift
 *
 * Copryright 2011, Craig Condon
 * Licensed under MIT
 *
 * Inspired by mongodb's query language
 */

(function() {

  "use strict";

  //traversable statements
  var TRAV_OP = {
    $and  : true,
    $or   : true,
    $nor  : true,
    $trav : true,
    $not  : true
  };

  var _testers = {

    /**
     */

    $eq: function(a, b) {
      return a.test(b);
    },

    /**
     */

    $ne: function(a, b) {
      return !a.test(b);
    },

    /**
     */

    $lt: function(a, b) {
      return a > b;
    },

    /**
     */

    $gt: function(a, b) {
      return a < b;
    },

    /**
     */

    $lte: function(a, b) {
      return a >= b;
    },

    /**
     */

    $gte: function(a, b) {
      return a <= b;
    },

    /**
     */

    $exists: function(a, b) {
      return a === (b != null);
    },

    /**
     */

    $in: function(a, b) {

      //intersecting an array
      if (b instanceof Array) {

        for (var i = b.length; i--;) {
          if (~a.indexOf(b[i])) return true;
        }

      } else {
        return ~a.indexOf(b);
      }

      return false;
    },

    /**
     */

    $not: function(a, b) {
      if (!a.test) throw new Error("$not test should include an expression, not a value. Use $ne instead.");
      return !a.test(b);
    },

    /**
     */

    $type: function(a, b, org) {
      //instanceof doesn't work for strings / boolean. instanceof works with inheritance
      return org != null ? org instanceof a || org.constructor == a : false;
    },

    /**
     */

    $nin: function(a, b) {
      return !_testers.$in(a, b);
    },

    /**
     */

    $mod: function(a, b) {
      return b % a[0] == a[1];
    },

    /**
     */

    $all: function(a, b) {
      if (!b) b = [];
      for (var i = a.length; i--;) {
        var a1 = a[i];
        var indexInB = ~b.indexOf(a1);
        if (!indexInB) return false;
      }

      return true;
    },

    /**
     */

    $size: function(a, b) {
      return b ? a === b.length : false;
    },

    /**
     */

    $or: function(a, b) {

      var i = a.length;
      var n = i;

      for (; i--;) {
        if (test(a[i], b)) {
          return true;
        }
      }

      return n === 0;
    },

    /**
     */

    $nor: function(a, b) {

      var i = a.length;

      for (; i--;) {
        if (test(a[i], b)) {
          return false;
        }
      }

      return true;
    },

    /**
     */

    $and: function(a, b) {

      for (var i = a.length; i--;) {
        if (!test(a[i], b)) {
          return false;
        }
      }

      return true;
    },

    /**
     */

    $trav: function(a, b) {

      if (b instanceof Array) {

        for (var i = b.length; i--;) {
          var subb = b[i];
          if (subb[a.k] && test(a, subb[a.k])) return true;
        }

        return false;
      }

      //continue to traverse even if there isn't a value - this is needed for
      //something like name:{$exists:false}
      return test(a, b ? b[a.k] : void 0);
    },

    /**
     */

    $regex: function(a, b) {
      var aRE = new RegExp(a);
      return aRE.test(b);
    },

    /**
     */

    $where: function(a, b) {
      return a.call(b, b);
    },

    /**
     */

    $elemMatch: function(a, b) {
      return a.test(b);
    }
  };

  var _prepare = {

    /**
     */

    $eq: function(a) {

      var fn;

      if (a instanceof RegExp) {
        return a;
      } else if (a instanceof Function) {
        fn = a;
      } else {
        fn = function(b) {
          if (b instanceof Array) {
            return ~b.indexOf(a);
          } else {
            return a === b;
          }
        };
      }

      return {
        test: fn
      };
    },

    /**
     */

    $ne: function(a) {
      return _prepare.$eq(a);
    },

    /**
     */

    $where: function(a) {

      if (typeof a === "string") {
        return new Function("obj", "return " + a);
      }

      return a;
    },

    /**
     */

    $elemMatch: function(a) {
      return parse(a);
    }
  };

  /**
   */

  function getExpr(type, key, value) {

    var v = comparable(value);

    return {

      //k key
      k: key,

      //v value
      v: _prepare[type] ? _prepare[type](v) : v,

      //e eval
      e: _testers[type]
    };
  }

  /**
   * tests against data
   */

  function test(statement, data) {

    var exprs    = statement.exprs;

    //generally, expressions are ordered from least efficient, to most efficient.
    for (var i = 0, n = exprs.length; i < n; i++) {

      var expr = exprs[i];

      if (!expr.e(expr.v, comparable(data), data)) return false;

    }

    return true;
  }

  /**
   * parses a statement into something evaluable
   */

  function parse(statement, key) {

    //fixes sift(null, []) issue
    if (!statement) statement = { $eq: statement };

    var testers = [];

    //if the statement is an object, then we're looking at something like: { key: match }
    if (statement && statement.constructor === Object) {

      for (var k in statement) {

        //find the apropriate operator. If one doesn't exist and the key does not start
        //with a $ character, then it's a property, which means we create a new statement
        //(traversing)
        var operator;
        if (!!_testers[k]) {
          operator = k;

        // $ == 36
        } else if (k.charCodeAt(0) !== 36) {
          operator = "$trav";
        } else {
          throw new Error("Unknown operator " + k + ".");
        }

        //value of given statement (the match)
        var value = statement[k];

        //default = match
        var exprValue = value;

        //if we're working with a traversable operator, then set the expr value
        if (TRAV_OP[operator]) {

          //using dot notation? convert into a sub-object
          if (~k.indexOf(".")) {
            var keyParts = k.split(".");
            k = keyParts.shift(); //we're using the first key, so remove it

            exprValue = value = convertDotToSubObject(keyParts, value);
          }

          //*if* the value is an array, then we're dealing with something like: $or, $and
          if (value instanceof Array) {

            exprValue = [];

            for (var i = value.length; i--;) {
              exprValue.push(parse(value[i]));
            }

          //otherwise we're dealing with $trav
          } else {
            exprValue = parse(value, k);
          }
        }

        testers.push(getExpr(operator, k, exprValue));
      }

    //otherwise we're comparing a particular value, so set to eq
    } else {
      testers.push(getExpr("$eq", key, statement));
    }

    var stmt =  {
      exprs: testers,
      k: key,
      test: function(value) {
        return test(stmt, value);
      }
    };

    return stmt;
  }

  /**
   */

  function comparable(value) {
    if (value instanceof Date) {
      return value.getTime();
    } else if (value instanceof Array) {
      return value.map(comparable);
    } else {
      return value;
    }
  }

  /**
   */

  function convertDotToSubObject(keyParts, value) {

    var subObject    = {};
    var currentValue = subObject;

    for (var i = 0, n = keyParts.length - 1; i < n; i++) {
      currentValue = currentValue[keyParts[i]] = {};
    }

    currentValue[keyParts[i]] = value;

    return subObject;
  }

  /**
   */

  function getSelector(selector) {

    if (!selector) {

      return function(value) {
        return value;
      };

    } else if (typeof selector == "function") {
      return selector;
    }

    throw new Error("Unknown sift selector " + selector);
  }

  /**
   * sifts the given function
   * @param query the mongodb query
   * @param target the target array
   * @param rawSelector the selector for plucking data from the given target
   */

  function sift(query, target, rawSelector) {

    //must be an array
    if (typeof target != "object") {
      rawSelector = target;
      target = void 0;
    }

    var selector = getSelector(rawSelector);

    //build the filter for the sifter
    var sifter = parse(query);

    function filter(value) {
      return sifter.test(selector(value));
    }

    if (target) return target.filter(filter);

    filter.query = query;

    return filter;
  }

  sift.use = function(options) {
    if (options.operators) sift.useOperators(options.operators);
    if (typeof options === "function") options(sift);
  };

  sift.useOperators = function(operators) {
    for (var key in operators) {
      sift.useOperator(key, operators[key]);
    }
  };

  sift.useOperator = function(operator, optionsOrFn) {

    var options = {};

    if (typeof optionsOrFn == "object") {
      options = optionsOrFn;
    } else {
      options = { test: optionsOrFn };
    }

    var key = "$" + operator;
    _testers[key] = options.test;

    if (options.traversable || options.traverse) {
      TRAV_OP[key] = true;
    }
  };

  sift.indexOf = function(query, target, rawSelector) {
    var selector = getSelector(rawSelector);

    //build the filter for the sifter
    var sifter = parse(query);

    for (var i = 0; i < target.length; i++) {
      if (sifter.test(selector(target[i]))) {
        return i;
      }
    }

    return -1;
  };

  /* istanbul ignore next */
  if ((typeof module != "undefined") && (typeof module.exports != "undefined")) {
    module.exports = sift;
  } else
  if (typeof window != "undefined") {
    window.sift = sift;
  }
})();
<commit_msg>Add an isObject function and use it.<commit_after>/*
 * Sift
 *
 * Copryright 2011, Craig Condon
 * Licensed under MIT
 *
 * Inspired by mongodb's query language
 */

(function() {

  "use strict";

  //traversable statements
  var TRAV_OP = {
    $and  : true,
    $or   : true,
    $nor  : true,
    $trav : true,
    $not  : true
  };

  var _testers = {

    /**
     */

    $eq: function(a, b) {
      return a.test(b);
    },

    /**
     */

    $ne: function(a, b) {
      return !a.test(b);
    },

    /**
     */

    $lt: function(a, b) {
      return a > b;
    },

    /**
     */

    $gt: function(a, b) {
      return a < b;
    },

    /**
     */

    $lte: function(a, b) {
      return a >= b;
    },

    /**
     */

    $gte: function(a, b) {
      return a <= b;
    },

    /**
     */

    $exists: function(a, b) {
      return a === (b != null);
    },

    /**
     */

    $in: function(a, b) {

      //intersecting an array
      if (b instanceof Array) {

        for (var i = b.length; i--;) {
          if (~a.indexOf(b[i])) return true;
        }

      } else {
        return ~a.indexOf(b);
      }

      return false;
    },

    /**
     */

    $not: function(a, b) {
      if (!a.test) throw new Error("$not test should include an expression, not a value. Use $ne instead.");
      return !a.test(b);
    },

    /**
     */

    $type: function(a, b, org) {
      //instanceof doesn't work for strings / boolean. instanceof works with inheritance
      return org != null ? org instanceof a || org.constructor == a : false;
    },

    /**
     */

    $nin: function(a, b) {
      return !_testers.$in(a, b);
    },

    /**
     */

    $mod: function(a, b) {
      return b % a[0] == a[1];
    },

    /**
     */

    $all: function(a, b) {
      if (!b) b = [];
      for (var i = a.length; i--;) {
        var a1 = a[i];
        var indexInB = ~b.indexOf(a1);
        if (!indexInB) return false;
      }

      return true;
    },

    /**
     */

    $size: function(a, b) {
      return b ? a === b.length : false;
    },

    /**
     */

    $or: function(a, b) {

      var i = a.length;
      var n = i;

      for (; i--;) {
        if (test(a[i], b)) {
          return true;
        }
      }

      return n === 0;
    },

    /**
     */

    $nor: function(a, b) {

      var i = a.length;

      for (; i--;) {
        if (test(a[i], b)) {
          return false;
        }
      }

      return true;
    },

    /**
     */

    $and: function(a, b) {

      for (var i = a.length; i--;) {
        if (!test(a[i], b)) {
          return false;
        }
      }

      return true;
    },

    /**
     */

    $trav: function(a, b) {

      if (b instanceof Array) {

        for (var i = b.length; i--;) {
          var subb = b[i];
          if (subb[a.k] && test(a, subb[a.k])) return true;
        }

        return false;
      }

      //continue to traverse even if there isn't a value - this is needed for
      //something like name:{$exists:false}
      return test(a, b ? b[a.k] : void 0);
    },

    /**
     */

    $regex: function(a, b) {
      var aRE = new RegExp(a);
      return aRE.test(b);
    },

    /**
     */

    $where: function(a, b) {
      return a.call(b, b);
    },

    /**
     */

    $elemMatch: function(a, b) {
      return a.test(b);
    }
  };

  var _prepare = {

    /**
     */

    $eq: function(a) {

      var fn;

      if (a instanceof RegExp) {
        return a;
      } else if (a instanceof Function) {
        fn = a;
      } else {
        fn = function(b) {
          if (b instanceof Array) {
            return ~b.indexOf(a);
          } else {
            return a === b;
          }
        };
      }

      return {
        test: fn
      };
    },

    /**
     */

    $ne: function(a) {
      return _prepare.$eq(a);
    },

    /**
     */

    $where: function(a) {

      if (typeof a === "string") {
        return new Function("obj", "return " + a);
      }

      return a;
    },

    /**
     */

    $elemMatch: function(a) {
      return parse(a);
    }
  };

  /**
   */

  function getExpr(type, key, value) {

    var v = comparable(value);

    return {

      //k key
      k: key,

      //v value
      v: _prepare[type] ? _prepare[type](v) : v,

      //e eval
      e: _testers[type]
    };
  }

  /**
   * tests against data
   */

  function test(statement, data) {

    var exprs    = statement.exprs;

    //generally, expressions are ordered from least efficient, to most efficient.
    for (var i = 0, n = exprs.length; i < n; i++) {

      var expr = exprs[i];

      if (!expr.e(expr.v, comparable(data), data)) return false;

    }

    return true;
  }

  /**
   * parses a statement into something evaluable
   */

  function parse(statement, key) {

    //fixes sift(null, []) issue
    if (!statement) statement = { $eq: statement };

    var testers = [];

    //if the statement is an object, then we're looking at something like: { key: match }
    if (statement && isObject(statement)) {

      for (var k in statement) {

        //find the apropriate operator. If one doesn't exist and the key does not start
        //with a $ character, then it's a property, which means we create a new statement
        //(traversing)
        var operator;
        if (!!_testers[k]) {
          operator = k;

        // $ == 36
        } else if (k.charCodeAt(0) !== 36) {
          operator = "$trav";
        } else {
          throw new Error("Unknown operator " + k + ".");
        }

        //value of given statement (the match)
        var value = statement[k];

        //default = match
        var exprValue = value;

        //if we're working with a traversable operator, then set the expr value
        if (TRAV_OP[operator]) {

          //using dot notation? convert into a sub-object
          if (~k.indexOf(".")) {
            var keyParts = k.split(".");
            k = keyParts.shift(); //we're using the first key, so remove it

            exprValue = value = convertDotToSubObject(keyParts, value);
          }

          //*if* the value is an array, then we're dealing with something like: $or, $and
          if (value instanceof Array) {

            exprValue = [];

            for (var i = value.length; i--;) {
              exprValue.push(parse(value[i]));
            }

          //otherwise we're dealing with $trav
          } else {
            exprValue = parse(value, k);
          }
        }

        testers.push(getExpr(operator, k, exprValue));
      }

    //otherwise we're comparing a particular value, so set to eq
    } else {
      testers.push(getExpr("$eq", key, statement));
    }

    var stmt =  {
      exprs: testers,
      k: key,
      test: function(value) {
        return test(stmt, value);
      }
    };

    return stmt;
  }

  /**
   */

  function comparable(value) {
    if (value instanceof Date) {
      return value.getTime();
    } else if (value instanceof Array) {
      return value.map(comparable);
    } else {
      return value;
    }
  }

  /**
   */

  function convertDotToSubObject(keyParts, value) {

    var subObject    = {};
    var currentValue = subObject;

    for (var i = 0, n = keyParts.length - 1; i < n; i++) {
      currentValue = currentValue[keyParts[i]] = {};
    }

    currentValue[keyParts[i]] = value;

    return subObject;
  }

  /**
   */

  function getSelector(selector) {

    if (!selector) {

      return function(value) {
        return value;
      };

    } else if (typeof selector == "function") {
      return selector;
    }

    throw new Error("Unknown sift selector " + selector);
  }

  /**
   * sifts the given function
   * @param query the mongodb query
   * @param target the target array
   * @param rawSelector the selector for plucking data from the given target
   */

  function sift(query, target, rawSelector) {

    //must be an array
    if (typeof target != "object") {
      rawSelector = target;
      target = void 0;
    }

    var selector = getSelector(rawSelector);

    //build the filter for the sifter
    var sifter = parse(query);

    function filter(value) {
      return sifter.test(selector(value));
    }

    if (target) return target.filter(filter);

    filter.query = query;

    return filter;
  }

  sift.use = function(options) {
    if (options.operators) sift.useOperators(options.operators);
    if (typeof options === "function") options(sift);
  };

  sift.useOperators = function(operators) {
    for (var key in operators) {
      sift.useOperator(key, operators[key]);
    }
  };

  sift.useOperator = function(operator, optionsOrFn) {

    var options = {};

    if (typeof optionsOrFn == "object") {
      options = optionsOrFn;
    } else {
      options = { test: optionsOrFn };
    }

    var key = "$" + operator;
    _testers[key] = options.test;

    if (options.traversable || options.traverse) {
      TRAV_OP[key] = true;
    }
  };

  sift.indexOf = function(query, target, rawSelector) {
    var selector = getSelector(rawSelector);

    //build the filter for the sifter
    var sifter = parse(query);

    for (var i = 0; i < target.length; i++) {
      if (sifter.test(selector(target[i]))) {
        return i;
      }
    }

    return -1;
  };

  function isObject(value) {
    // function appropriated from lodash. The check for obj.constructor === Object fails in a custom REPL for node.
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type === 'object' || type === 'function');
  }

  /* istanbul ignore next */
  if ((typeof module != "undefined") && (typeof module.exports != "undefined")) {
    module.exports = sift;
  } else
  if (typeof window != "undefined") {
    window.sift = sift;
  }
})();
<|endoftext|>


<commit_before>import Jasmine from 'jasmine'
import JasmineReporter from './reporter'
import { runInFiberContext, wrapCommands, executeHooksWithArgs } from 'wdio-sync'

const INTERFACES = {
    bdd: ['beforeAll', 'beforeEach', 'it', 'xit', 'fit', 'afterEach', 'afterAll']
}

const DEFAULT_TIMEOUT_INTERVAL = 60000

/**
 * Jasmine 2.x runner
 */
class JasmineAdapter {
    constructor (cid, config, specs = [], capabilities = {}) {
        this.cid = cid
        this.capabilities = capabilities
        this.specs = specs
        this.config = Object.assign({}, config)
        this.jasmineNodeOpts = Object.assign({
            cleanStack: true
        }, config.jasmineNodeOpts)
        this.jrunner = {}
        this.reporter = new JasmineReporter({
            cid: this.cid,
            capabilities: this.capabilities,
            specs: this.specs,
            cleanStack: this.jasmineNodeOpts.cleanStack
        })
    }

    async run () {
        let self = this

        this.jrunner = new Jasmine()
        let jasmine = this.jrunner.jasmine

        this.jrunner.randomizeTests(this.getRandomExecutionPolicy())

        this.jrunner.projectBaseDir = ''
        this.jrunner.specDir = ''
        this.jrunner.addSpecFiles(this.specs)

        jasmine.DEFAULT_TIMEOUT_INTERVAL = this.getDefaultInterval()
        jasmine.getEnv().addReporter(this.reporter)

        /**
         * Filter specs to run based on jasmineNodeOpts.grep and jasmineNodeOpts.invert
         */
        jasmine.getEnv().specFilter = (spec) => {
            let grepMatch = this.getGrepMatch(spec)
            let invertGrep = !!this.jasmineNodeOpts.invertGrep
            if (grepMatch === invertGrep) {
                spec.pend()
            }
            return true
        }

        /**
         * enable expectHandler
         */
        jasmine.Spec.prototype.addExpectationResult = this.getExpectationResultHandler(jasmine)

        /**
         * patch jasmine to support promises
         */
        INTERFACES['bdd'].forEach((fnName) => {
            const origFn = global[fnName]
            global[fnName] = (...args) => {
                const retryCnt = typeof args[args.length - 1] === 'number' ? args.pop() : 0
                const specFn = typeof args[0] === 'function' ? args.shift() : (typeof args[1] === 'function' ? args.pop() : undefined)
                const specTitle = args[0]
                const patchedOrigFn = function (done) {
                    // specFn will be replaced by wdio-sync and will always return a promise
                    return specFn.call(this).then(() => done(), (e) => done.fail(e))
                }
                const newArgs = [specTitle, patchedOrigFn, retryCnt].filter(a => Boolean(a))

                if (!specFn) {
                    return origFn(specTitle)
                }

                return origFn.apply(this, newArgs)
            }
        })

        /**
         * wrap commands with wdio-sync
         */
        wrapCommands(global.browser, this.config.beforeCommand, this.config.afterCommand)
        INTERFACES['bdd'].forEach((fnName) => runInFiberContext(
            ['it', 'fit'],
            this.config.beforeHook,
            this.config.afterHook,
            fnName
        ))

        /**
         * for a clean stdout we need to avoid that Jasmine initialises the
         * default reporter
         */
        Jasmine.prototype.configureDefaultReporter = () => {}

        /**
         * wrap Suite and Spec prototypes to get access to their data
         */
        let beforeAllMock = jasmine.Suite.prototype.beforeAll
        jasmine.Suite.prototype.beforeAll = function (...args) {
            self.lastSpec = this.result
            beforeAllMock.apply(this, args)
        }
        let executeMock = jasmine.Spec.prototype.execute
        jasmine.Spec.prototype.execute = function (...args) {
            self.lastTest = this.result
            self.lastTest.start = new Date().getTime()
            executeMock.apply(this, args)
        }

        await executeHooksWithArgs(this.config.before, [this.capabilities, this.specs])
        let result = await new Promise((resolve) => {
            this.jrunner.env.beforeAll(this.wrapHook('beforeSuite'))
            this.jrunner.env.beforeEach(this.wrapHook('beforeTest'))
            this.jrunner.env.afterEach(this.wrapHook('afterTest'))
            this.jrunner.env.afterAll(this.wrapHook('afterSuite'))

            this.jrunner.onComplete(() => resolve(this.reporter.getFailedCount()))
            this.jrunner.execute()
        })
        await executeHooksWithArgs(this.config.after, [result, this.capabilities, this.specs])
        await this.reporter.waitUntilSettled()
        return result
    }

    /**
     * Hooks which are added as true Mocha hooks need to call done() to notify async
     */
    wrapHook (hookName) {
        return (done) => executeHooksWithArgs(
            this.config[hookName],
            this.prepareMessage(hookName)
        ).then(() => done(), (e) => {
            console.log(`Error in ${hookName} hook: ${e.stack.slice(7)}`)
            done()
        })
    }

    prepareMessage (hookName) {
        const params = { type: hookName }

        switch (hookName) {
        case 'beforeSuite':
        case 'afterSuite':
            params.payload = Object.assign({
                file: this.jrunner.specFiles[0]
            }, this.lastSpec)
            break
        case 'beforeTest':
        case 'afterTest':
            params.payload = Object.assign({
                file: this.jrunner.specFiles[0]
            }, this.lastTest)
            break
        }

        return this.formatMessage(params)
    }

    formatMessage (params) {
        let message = {
            type: params.type
        }

        if (params.err) {
            message.err = {
                message: params.err.message,
                stack: params.err.stack
            }
        }

        if (params.payload) {
            message.title = params.payload.description
            message.fullName = params.payload.fullName || null
            message.file = params.payload.file

            if (params.payload.id && params.payload.id.startsWith('spec')) {
                message.parent = this.lastSpec.description
                message.passed = params.payload.failedExpectations.length === 0
            }

            if (params.type === 'afterTest') {
                message.duration = new Date().getTime() - params.payload.start
            }

            if (typeof params.payload.duration === 'number') {
                message.duration = params.payload.duration
            }
        }

        return message
    }

    getDefaultInterval () {
        let { jasmineNodeOpts } = this
        if (jasmineNodeOpts.defaultTimeoutInterval) {
            return jasmineNodeOpts.defaultTimeoutInterval
        }

        return DEFAULT_TIMEOUT_INTERVAL
    }

    getRandomExecutionPolicy () {
        return !!this.jasmineNodeOpts.random
    }

    getGrepMatch (spec) {
        let { grep } = this.jasmineNodeOpts
        return !grep || spec.getFullName().match(new RegExp(grep)) !== null
    }

    getExpectationResultHandler (jasmine) {
        let { jasmineNodeOpts } = this
        const origHandler = jasmine.Spec.prototype.addExpectationResult

        if (typeof jasmineNodeOpts.expectationResultHandler !== 'function') {
            return origHandler
        }

        return this.expectationResultHandler(origHandler)
    }

    expectationResultHandler (origHandler) {
        let { expectationResultHandler } = this.jasmineNodeOpts
        return function (passed, data) {
            try {
                expectationResultHandler.call(global.browser, passed, data)
            } catch (e) {
                /**
                 * propagate expectationResultHandler error if actual assertion passed
                 */
                if (passed) {
                    passed = false
                    data = {
                        passed: false,
                        message: 'expectationResultHandlerError: ' + e.message
                    }
                }
            }

            return origHandler.call(this, passed, data)
        }
    }
}

const _JasmineAdapter = JasmineAdapter
const adapterFactory = {}

adapterFactory.run = async function (cid, config, specs, capabilities) {
    const adapter = new _JasmineAdapter(cid, config, specs, capabilities)
    const result = await adapter.run()
    return result
}

export default adapterFactory
export { JasmineAdapter, adapterFactory }
<commit_msg>fix(adapter): do not skip "it" block when description is empty<commit_after>import Jasmine from 'jasmine'
import JasmineReporter from './reporter'
import { runInFiberContext, wrapCommands, executeHooksWithArgs } from 'wdio-sync'

const INTERFACES = {
    bdd: ['beforeAll', 'beforeEach', 'it', 'xit', 'fit', 'afterEach', 'afterAll']
}

const DEFAULT_TIMEOUT_INTERVAL = 60000

/**
 * Jasmine 2.x runner
 */
class JasmineAdapter {
    constructor (cid, config, specs = [], capabilities = {}) {
        this.cid = cid
        this.capabilities = capabilities
        this.specs = specs
        this.config = Object.assign({}, config)
        this.jasmineNodeOpts = Object.assign({
            cleanStack: true
        }, config.jasmineNodeOpts)
        this.jrunner = {}
        this.reporter = new JasmineReporter({
            cid: this.cid,
            capabilities: this.capabilities,
            specs: this.specs,
            cleanStack: this.jasmineNodeOpts.cleanStack
        })
    }

    async run () {
        let self = this

        this.jrunner = new Jasmine()
        let jasmine = this.jrunner.jasmine

        this.jrunner.randomizeTests(this.getRandomExecutionPolicy())

        this.jrunner.projectBaseDir = ''
        this.jrunner.specDir = ''
        this.jrunner.addSpecFiles(this.specs)

        jasmine.DEFAULT_TIMEOUT_INTERVAL = this.getDefaultInterval()
        jasmine.getEnv().addReporter(this.reporter)

        /**
         * Filter specs to run based on jasmineNodeOpts.grep and jasmineNodeOpts.invert
         */
        jasmine.getEnv().specFilter = (spec) => {
            let grepMatch = this.getGrepMatch(spec)
            let invertGrep = !!this.jasmineNodeOpts.invertGrep
            if (grepMatch === invertGrep) {
                spec.pend()
            }
            return true
        }

        /**
         * enable expectHandler
         */
        jasmine.Spec.prototype.addExpectationResult = this.getExpectationResultHandler(jasmine)

        /**
         * patch jasmine to support promises
         */
        INTERFACES['bdd'].forEach((fnName) => {
            const origFn = global[fnName]
            global[fnName] = (...args) => {
                const retryCnt = typeof args[args.length - 1] === 'number' ? args.pop() : 0
                const specFn = typeof args[0] === 'function' ? args.shift() : (typeof args[1] === 'function' ? args.pop() : undefined)
                const specTitle = args[0]
                const patchedOrigFn = function (done) {
                    // specFn will be replaced by wdio-sync and will always return a promise
                    return specFn.call(this).then(() => done(), (e) => done.fail(e))
                }
                const newArgs = [specTitle, patchedOrigFn, retryCnt].filter(a => {
                    if (a === '') {
                        return true;
                    } else {
                        return Boolean(a);
                    }
                });

                if (!specFn) {
                    return origFn(specTitle)
                }

                return origFn.apply(this, newArgs)
            }
        })

        /**
         * wrap commands with wdio-sync
         */
        wrapCommands(global.browser, this.config.beforeCommand, this.config.afterCommand)
        INTERFACES['bdd'].forEach((fnName) => runInFiberContext(
            ['it', 'fit'],
            this.config.beforeHook,
            this.config.afterHook,
            fnName
        ))

        /**
         * for a clean stdout we need to avoid that Jasmine initialises the
         * default reporter
         */
        Jasmine.prototype.configureDefaultReporter = () => {}

        /**
         * wrap Suite and Spec prototypes to get access to their data
         */
        let beforeAllMock = jasmine.Suite.prototype.beforeAll
        jasmine.Suite.prototype.beforeAll = function (...args) {
            self.lastSpec = this.result
            beforeAllMock.apply(this, args)
        }
        let executeMock = jasmine.Spec.prototype.execute
        jasmine.Spec.prototype.execute = function (...args) {
            self.lastTest = this.result
            self.lastTest.start = new Date().getTime()
            executeMock.apply(this, args)
        }

        await executeHooksWithArgs(this.config.before, [this.capabilities, this.specs])
        let result = await new Promise((resolve) => {
            this.jrunner.env.beforeAll(this.wrapHook('beforeSuite'))
            this.jrunner.env.beforeEach(this.wrapHook('beforeTest'))
            this.jrunner.env.afterEach(this.wrapHook('afterTest'))
            this.jrunner.env.afterAll(this.wrapHook('afterSuite'))

            this.jrunner.onComplete(() => resolve(this.reporter.getFailedCount()))
            this.jrunner.execute()
        })
        await executeHooksWithArgs(this.config.after, [result, this.capabilities, this.specs])
        await this.reporter.waitUntilSettled()
        return result
    }

    /**
     * Hooks which are added as true Mocha hooks need to call done() to notify async
     */
    wrapHook (hookName) {
        return (done) => executeHooksWithArgs(
            this.config[hookName],
            this.prepareMessage(hookName)
        ).then(() => done(), (e) => {
            console.log(`Error in ${hookName} hook: ${e.stack.slice(7)}`)
            done()
        })
    }

    prepareMessage (hookName) {
        const params = { type: hookName }

        switch (hookName) {
        case 'beforeSuite':
        case 'afterSuite':
            params.payload = Object.assign({
                file: this.jrunner.specFiles[0]
            }, this.lastSpec)
            break
        case 'beforeTest':
        case 'afterTest':
            params.payload = Object.assign({
                file: this.jrunner.specFiles[0]
            }, this.lastTest)
            break
        }

        return this.formatMessage(params)
    }

    formatMessage (params) {
        let message = {
            type: params.type
        }

        if (params.err) {
            message.err = {
                message: params.err.message,
                stack: params.err.stack
            }
        }

        if (params.payload) {
            message.title = params.payload.description
            message.fullName = params.payload.fullName || null
            message.file = params.payload.file

            if (params.payload.id && params.payload.id.startsWith('spec')) {
                message.parent = this.lastSpec.description
                message.passed = params.payload.failedExpectations.length === 0
            }

            if (params.type === 'afterTest') {
                message.duration = new Date().getTime() - params.payload.start
            }

            if (typeof params.payload.duration === 'number') {
                message.duration = params.payload.duration
            }
        }

        return message
    }

    getDefaultInterval () {
        let { jasmineNodeOpts } = this
        if (jasmineNodeOpts.defaultTimeoutInterval) {
            return jasmineNodeOpts.defaultTimeoutInterval
        }

        return DEFAULT_TIMEOUT_INTERVAL
    }

    getRandomExecutionPolicy () {
        return !!this.jasmineNodeOpts.random
    }

    getGrepMatch (spec) {
        let { grep } = this.jasmineNodeOpts
        return !grep || spec.getFullName().match(new RegExp(grep)) !== null
    }

    getExpectationResultHandler (jasmine) {
        let { jasmineNodeOpts } = this
        const origHandler = jasmine.Spec.prototype.addExpectationResult

        if (typeof jasmineNodeOpts.expectationResultHandler !== 'function') {
            return origHandler
        }

        return this.expectationResultHandler(origHandler)
    }

    expectationResultHandler (origHandler) {
        let { expectationResultHandler } = this.jasmineNodeOpts
        return function (passed, data) {
            try {
                expectationResultHandler.call(global.browser, passed, data)
            } catch (e) {
                /**
                 * propagate expectationResultHandler error if actual assertion passed
                 */
                if (passed) {
                    passed = false
                    data = {
                        passed: false,
                        message: 'expectationResultHandlerError: ' + e.message
                    }
                }
            }

            return origHandler.call(this, passed, data)
        }
    }
}

const _JasmineAdapter = JasmineAdapter
const adapterFactory = {}

adapterFactory.run = async function (cid, config, specs, capabilities) {
    const adapter = new _JasmineAdapter(cid, config, specs, capabilities)
    const result = await adapter.run()
    return result
}

export default adapterFactory
export { JasmineAdapter, adapterFactory }
<|endoftext|>


<commit_before>/* global beforeEach, describe, it, expect */

import { app, h } from "../src"
import hyperx from "hyperx"
const html = hyperx(h)

function fireDOMLoaded() {
	const event = document.createEvent("Event")
	event.initEvent("DOMContentLoaded", true, true)
	window.document.dispatchEvent(event)
}

beforeEach(() => {
	document.body.innerHTML = ""
})

describe("App", () => {
	it("boots with no bugs", () => {
		app({ model: {}, view: () => (html`<div>Hi</div>`) })
	})

	it("allows optional options", () => {
		app({})
	})

	it("renders a model", () => {
		const model = {
			world: "world"
		}

		const view = (model) => html`<div id="test-me">${model.world}</div>`

		app({ model, view })

		expect(document.getElementById("test-me").innerHTML).toEqual(model.world)
	})

	it("renders a model with a loop", () => {
		const model = {
			loop: [
				"string1",
				"string2"
			]
		}

		const view = model =>
			html`<div>${model.loop.map(value => html`
${value}
`)}</div>`

		app({ model, view })

		expect(document.getElementsByTagName("p").length).toEqual(model.loop.length)
	})

	it("renders svg", () => {
		const model = {
			text: "zelda"
		}

		const view = model =>
			html`<svg><text>${model.text}</text></svg>`

		app({ model, view })

		expect(document.getElementsByTagName("svg").length).toEqual(1)
		expect(document.getElementsByTagName("svg")[0].namespaceURI).toEqual("http://www.w3.org/2000/svg")
		expect(document.getElementsByTagName("text")[0].innerHTML).toEqual(model.text)
	})

	it("renders the view when the model changes", () => {
		const firstValue = 'first-value'
		const secondValue = 'second-value'

		const model = firstValue

		const view = (model, update) =>
			html`
<input oninput=${e =>
				update.fire(e.target.value)} value=${model}/>
${model}

`

		const update = { fire: (_, value) => value }

		app({ model, view, update })

		const input = document.getElementsByTagName('input')[0];

		expect(input.value).toEqual(firstValue)

		const evnt = new Event('input', { bubbles: true });
		input.value = secondValue;
		input.dispatchEvent(evnt);

		expect(input.value).toEqual(secondValue)
		expect(document.getElementsByTagName('p')[0].innerHTML).toEqual(secondValue)
	});

	it("boots application on domcontentloaded", done => {
		Object.defineProperty(document, "readyState", {
			writable: true
		})

		window.document.readyState = "loading"

		const model = "foo"

		app({
			model,
			subscriptions: [_ => {
				expect(model).toEqual("foo")
				done()
			}]
		})

		window.document.readyState = "complete"

		fireDOMLoaded()

	})

	it("does not render bools (true)", () => {
		app({
			view: _ => html`<div id="foo">${true}</div>`
		})
		expect(document.getElementById("foo").innerHTML).toEqual("")
	})

	// this is a bug in hyperx, that converts false values to strings
	// making it impossible for our vdom to know whether the user meant
	// the string "false" or the primitive value false
	it.skip("does not render bools (false)", () => {
		app({
			view: _ => html`<div id="foo">${false}</div>`
		})
		expect(document.getElementById("foo").innerHTML).toEqual("")
	})

})

describe("Views", () => {
	it("allows inline styles as object with properties in camelCase", () => {
		const view = (model) => html`
I'm red
`

		app({ view })
		var el = document.getElementById("red")
		expect(el).not.toBe(null)
		expect(el.style["background-color"]).toEqual("red")
		expect(el.style["padding"]).toEqual("10px")
	})

	it("allows the views to be defined directly with h", () => {
		const view = (model) => h("div", { id: "test" }, "inside div")
		app({ view })
		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toEqual("inside div")
	})

	it("allows data to be null", () => {
		const view = (model) => h("div", undefined, "inside div")
		app({ view })
		var el = document.getElementsByTagName("div")[0]

		expect(el).not.toBe(null)
		expect(el.innerHTML).toEqual("
inside div
")
	})

	it("allows tag to be a function", () => {
		const view = (model) => h(_ => h("div", { id: "test" }, "component"), undefined)
		app({ view })
		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toEqual("component")
	})

	it("sets bool attributes", () => {
		const view = (model) => h("div", { id: "test", dummy: false }, "inside div")
		app({ view })
		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.dummy).toEqual(false)
	})

	it("handles nulls and bools", () => {
		app({
			model: 0,
			reducers: {
				add: model => model + 1,
				sub: model => model - 1
			},
			view: (model, actions) =>
				h("div", {}, [
					h("div", { id: "test" }, model > 0 && h("h1", {}, model)),
					h("button", {
						id: "btn-add",
						onclick: actions.add
					}),
					h("button", {
						id: "btn-sub",
						onclick: actions.sub
					}),
					h("div", {}, null)
				])
		})

		const btnAdd = document.getElementById("btn-add")
		const btnSub = document.getElementById("btn-sub")

		const ev = new Event("click", { bubbles: true })
		btnAdd.dispatchEvent(ev)

		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toEqual("
1
")

		btnSub.dispatchEvent(ev)
		expect(el.innerHTML).toEqual("")
	})

	it("handles bool props", () => {
		const items = ["test-10", "test-20", "test-30", "test-40", "test-50"]
		const newItem = (selected, id) => ({ selected, id })
		const newList = items => items.map(i => newItem(true, i))

		app({
			model: {
				items: newList(items)
			},
			view: (model, actions) =>
				h("div", {}, [
					h("button", { onclick: actions.shift }, "Shift"),
					h("button", { onclick: actions.reset }, "Reset"),
					h("ul", {}, model.items.map(i =>
						h("li", {
							id: i.id,
						}, [
								h("label", {}, h(
									"input", {
										id: "input-" + i.id,
										onchange: e => {

											actions.select({
												id: i.id, value: e.target.checked
											})

										},
										type: "checkbox",
										checked: i.selected
									}),
									i.id + "/" + i.selected)
							])
					))
				]),
			reducers: {
				select: (model, { id, value }) => ({
					items: model.items.map(i => i.id === id ? newItem(value, id) : i)
				}),
				reset: model => ({ items: newList(items) }),
				shift: model => ({ items: model.items.slice(1) })
			}
		})

		function simulateClick(id) {
			var event = new MouseEvent("click", {
				"view": window,
				"bubbles": true,
				"cancelable": true
			})
			document.getElementById(id).dispatchEvent(event)
		}

		const sndItem = document.getElementById("test-20")
		const sndInputEl = document.getElementById("input-test-20")

		expect(sndItem).not.toBe(null)
		expect(sndInputEl).not.toBe(null)

		expect(sndInputEl.checked).toEqual(true)

		simulateClick("input-test-20")
		expect(sndInputEl.checked).toEqual(false)

		simulateClick("input-test-20")
		expect(sndInputEl.checked).toEqual(true)
	})

	it("removes element data", () => {
		const model = 0
		const update = {
			add: (model, data) => model + data
		}
		const subscriptions = [(_, msg) => msg.add(2)]

		const view = model => h("div", model === 0 ?
			({
				id: "test",
				className: "foo",
				style: { color: "red" },
				foo: true
			}) :
			({
				id: "test"
			})
			, "...")

		app({ model, view, update, subscriptions })

		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.style.color).toBe("")
	})
})

describe("Subscriptions", () => {
	it("fires all subscriptions when DOM is ready", () => {
		const check = {}

		app({
			view: () => html`<div>View</div>`,
			subscriptions: [
				() => { check["one"] = true },
				() => { check["two"] = true }
			]
		})

		fireDOMLoaded()

		expect(check["one"]).toBe(true)
		expect(check["two"]).toBe(true)
	})
})

describe("Hooks", () => {
	const model = 0

	const view = (model) => html`<div>${model}</div>`

	const update = { add: (model, data) => model + data }

	const subscriptions = [(_, msg) => msg.add(2)]

	it("fires onUpdate when the model is updated", () => {
		let guard = null

		const hooks = {
			onUpdate: (prev, model) => { guard = { prev, model } }
		}

		app({ model, view, update, subscriptions, hooks })

		fireDOMLoaded()

		expect(guard).toEqual({ model: 2, prev: 0 })
	})

	it("fires onAction when a reducer is dispatched", () => {
		let guard = null

		const hooks = {
			onAction: (name, data) => { guard = { name, data } }
		}

		app({ model, view, update, subscriptions, hooks })

		fireDOMLoaded()

		expect(guard).toEqual({ name: "add", data: 2 })
	})

	it("fires onAction when an effect is dispatched", () => {
		let guard = null

		let effectDone = false

		const hooks = {
			onAction: (name, data) => { guard = { name, data } }
		}

		const effects = {
			add: () => { effectDone = true }
		}

		app({ model, view, effects, subscriptions, hooks })

		fireDOMLoaded()

		expect(effectDone).toBe(true)
		expect(guard).toEqual({ name: "add", data: 2 })
	})

	it("fires onError when a effect fails", () => {
		let guard = null

		const hooks = {
			onError: (err) => { guard = err }
		}

		const effects = {
			add: (model, msg, data, error) => { error("effect error") }
		}

		app({ model, view, effects, subscriptions, hooks })

		fireDOMLoaded()

		expect(guard).toEqual("effect error")
	})

	it("throws when onError handler is not given", () => {
		const effects = {
			add: (model, msg, data, error) => {
				try {
					error("no error handler")
				} catch (e) {
					expect(e).toEqual("no error handler")
				}
			}
		}

		app({ model, view, effects, subscriptions })

		fireDOMLoaded()
	})

})

describe("Lifecycle methods", () => {
	const model = 0
	const update = {
		add: (model, data) => model + data
	}
	const subscriptions = [(_, msg) => msg.add(2)]

	it("fires oncreate", done => {
		let guard = null

		app({
			model: {},
			view: () => (html`<div oncreate=${e => guard = e}></div>`)
		})

		setTimeout(() => {
			expect(guard).not.toEqual(null)
			done()
		}, 1)
	})

	it("fires onupdate", done => {
		let guard = null

		const view = (model) => html`<div onupdate=${e => guard = e}></div>`

		app({ model, update, subscriptions, view })

		fireDOMLoaded()

		setTimeout(() => {
			expect(guard).not.toEqual(null)
			done()
		})

	})

	it("fires onremove", done => {
		let guard = null

		const a = html`

1

2

3

4

 guard = e}>foo

`

		const b = html`

foo

bar

`

		const view = model => html`${model === 0 ? a : b}`

		app({ model, view, update, subscriptions })

		fireDOMLoaded()

		setTimeout(() => {
			expect(guard).not.toEqual(null)
			done()
		})
	})
})

describe("Router API", () => {
	it("calls router with object.render(view)", () => {
		const model = "beep"

		app({
			model: "beep",
			router: render => {
				render(model => html`<h1 id="test">${model}</h1>`)
			}
		})

		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toBe(model)
	})

	it("calls router with object.render(view) #2", () => {
		const model = "beep"

		app({
			view: model => html`<h1 id="test">${model}</h1>`,
			model: "beep",
			router: render => render(undefined)
		})

		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toBe(model)
	})
})
<commit_msg>Add namespaces test.<commit_after>/* global beforeEach, describe, it, expect */

import { app, h } from "../src"
import hyperx from "hyperx"
const html = hyperx(h)

function fireDOMLoaded() {
	const event = document.createEvent("Event")
	event.initEvent("DOMContentLoaded", true, true)
	window.document.dispatchEvent(event)
}

beforeEach(() => {
	document.body.innerHTML = ""
})

describe("App", () => {
	it("boots with no bugs", () => {
		app({ model: {}, view: () => (html`<div>Hi</div>`) })
	})

	it("allows optional options", () => {
		app({})
	})

	it("renders a model", () => {
		const model = {
			world: "world"
		}

		const view = (model) => html`<div id="test-me">${model.world}</div>`

		app({ model, view })

		expect(document.getElementById("test-me").innerHTML).toEqual(model.world)
	})

	it("renders a model with a loop", () => {
		const model = {
			loop: [
				"string1",
				"string2"
			]
		}

		const view = model =>
			html`<div>${model.loop.map(value => html`
${value}
`)}</div>`

		app({ model, view })

		expect(document.getElementsByTagName("p").length).toEqual(model.loop.length)
	})

	it("renders svg", () => {
		const model = {
			text: "zelda"
		}

		const view = model =>
			html`<svg><text>${model.text}</text></svg>`

		app({ model, view })

		expect(document.getElementsByTagName("svg").length).toEqual(1)
		expect(document.getElementsByTagName("svg")[0].namespaceURI).toEqual("http://www.w3.org/2000/svg")
		expect(document.getElementsByTagName("text")[0].innerHTML).toEqual(model.text)
	})

	it("renders the view when the model changes", () => {
		const firstValue = 'first-value'
		const secondValue = 'second-value'

		const model = firstValue

		const view = (model, update) =>
			html`
<input oninput=${e =>
				update.fire(e.target.value)} value=${model}/>
${model}

`

		const update = { fire: (_, value) => value }

		app({ model, view, update })

		const input = document.getElementsByTagName('input')[0];

		expect(input.value).toEqual(firstValue)

		const evnt = new Event('input', { bubbles: true });
		input.value = secondValue;
		input.dispatchEvent(evnt);

		expect(input.value).toEqual(secondValue)
		expect(document.getElementsByTagName('p')[0].innerHTML).toEqual(secondValue)
	});

	it("boots application on domcontentloaded", done => {
		Object.defineProperty(document, "readyState", {
			writable: true
		})

		window.document.readyState = "loading"

		const model = "foo"

		app({
			model,
			subscriptions: [_ => {
				expect(model).toEqual("foo")
				done()
			}]
		})

		window.document.readyState = "complete"

		fireDOMLoaded()

	})

	it("does not render bools (true)", () => {
		app({
			view: _ => html`<div id="foo">${true}</div>`
		})
		expect(document.getElementById("foo").innerHTML).toEqual("")
	})

	// this is a bug in hyperx, that converts false values to strings
	// making it impossible for our vdom to know whether the user meant
	// the string "false" or the primitive value false
	it.skip("does not render bools (false)", () => {
		app({
			view: _ => html`<div id="foo">${false}</div>`
		})
		expect(document.getElementById("foo").innerHTML).toEqual("")
	})
})

describe("Namespaces", () => {
	it("", () => {
		app({
			model: true,
			reducers: {
				foo: {
					bar: {
						baz: (model, data) => {
							expect(model).toBe(true)
							expect(data).toBe("foo.bar.baz")
						}
					}
				}
			},
			subscriptions: [
				(_, actions) => actions.foo.bar.baz("foo.bar.baz")
			],
			view: _ => h("div", {}, "")
		})
	})
})

describe("Views", () => {
	it("allows inline styles as object with properties in camelCase", () => {
		const view = (model) => html`
I'm red
`

		app({ view })
		var el = document.getElementById("red")
		expect(el).not.toBe(null)
		expect(el.style["background-color"]).toEqual("red")
		expect(el.style["padding"]).toEqual("10px")
	})

	it("allows the views to be defined directly with h", () => {
		const view = (model) => h("div", { id: "test" }, "inside div")
		app({ view })
		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toEqual("inside div")
	})

	it("allows data to be null", () => {
		const view = (model) => h("div", undefined, "inside div")
		app({ view })
		var el = document.getElementsByTagName("div")[0]

		expect(el).not.toBe(null)
		expect(el.innerHTML).toEqual("
inside div
")
	})

	it("allows tag to be a function", () => {
		const view = (model) => h(_ => h("div", { id: "test" }, "component"), undefined)
		app({ view })
		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toEqual("component")
	})

	it("sets bool attributes", () => {
		const view = (model) => h("div", { id: "test", dummy: false }, "inside div")
		app({ view })
		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.dummy).toEqual(false)
	})

	it("handles nulls and bools", () => {
		app({
			model: 0,
			reducers: {
				add: model => model + 1,
				sub: model => model - 1
			},
			view: (model, actions) =>
				h("div", {}, [
					h("div", { id: "test" }, model > 0 && h("h1", {}, model)),
					h("button", {
						id: "btn-add",
						onclick: actions.add
					}),
					h("button", {
						id: "btn-sub",
						onclick: actions.sub
					}),
					h("div", {}, null)
				])
		})

		const btnAdd = document.getElementById("btn-add")
		const btnSub = document.getElementById("btn-sub")

		const ev = new Event("click", { bubbles: true })
		btnAdd.dispatchEvent(ev)

		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toEqual("
1
")

		btnSub.dispatchEvent(ev)
		expect(el.innerHTML).toEqual("")
	})

	it("handles bool props", () => {
		const items = ["test-10", "test-20", "test-30", "test-40", "test-50"]
		const newItem = (selected, id) => ({ selected, id })
		const newList = items => items.map(i => newItem(true, i))

		app({
			model: {
				items: newList(items)
			},
			view: (model, actions) =>
				h("div", {}, [
					h("button", { onclick: actions.shift }, "Shift"),
					h("button", { onclick: actions.reset }, "Reset"),
					h("ul", {}, model.items.map(i =>
						h("li", {
							id: i.id,
						}, [
								h("label", {}, h(
									"input", {
										id: "input-" + i.id,
										onchange: e => {

											actions.select({
												id: i.id, value: e.target.checked
											})

										},
										type: "checkbox",
										checked: i.selected
									}),
									i.id + "/" + i.selected)
							])
					))
				]),
			reducers: {
				select: (model, { id, value }) => ({
					items: model.items.map(i => i.id === id ? newItem(value, id) : i)
				}),
				reset: model => ({ items: newList(items) }),
				shift: model => ({ items: model.items.slice(1) })
			}
		})

		function simulateClick(id) {
			var event = new MouseEvent("click", {
				"view": window,
				"bubbles": true,
				"cancelable": true
			})
			document.getElementById(id).dispatchEvent(event)
		}

		const sndItem = document.getElementById("test-20")
		const sndInputEl = document.getElementById("input-test-20")

		expect(sndItem).not.toBe(null)
		expect(sndInputEl).not.toBe(null)

		expect(sndInputEl.checked).toEqual(true)

		simulateClick("input-test-20")
		expect(sndInputEl.checked).toEqual(false)

		simulateClick("input-test-20")
		expect(sndInputEl.checked).toEqual(true)
	})

	it("removes element data", () => {
		const model = 0
		const update = {
			add: (model, data) => model + data
		}
		const subscriptions = [(_, msg) => msg.add(2)]

		const view = model => h("div", model === 0 ?
			({
				id: "test",
				className: "foo",
				style: { color: "red" },
				foo: true
			}) :
			({
				id: "test"
			})
			, "...")

		app({ model, view, update, subscriptions })

		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.style.color).toBe("")
	})
})

describe("Subscriptions", () => {
	it("fires all subscriptions when DOM is ready", () => {
		const check = {}

		app({
			view: () => html`<div>View</div>`,
			subscriptions: [
				() => { check["one"] = true },
				() => { check["two"] = true }
			]
		})

		fireDOMLoaded()

		expect(check["one"]).toBe(true)
		expect(check["two"]).toBe(true)
	})
})

describe("Hooks", () => {
	const model = 0

	const view = (model) => html`<div>${model}</div>`

	const update = { add: (model, data) => model + data }

	const subscriptions = [(_, msg) => msg.add(2)]

	it("fires onUpdate when the model is updated", () => {
		let guard = null

		const hooks = {
			onUpdate: (prev, model) => { guard = { prev, model } }
		}

		app({ model, view, update, subscriptions, hooks })

		fireDOMLoaded()

		expect(guard).toEqual({ model: 2, prev: 0 })
	})

	it("fires onAction when a reducer is dispatched", () => {
		let guard = null

		const hooks = {
			onAction: (name, data) => { guard = { name, data } }
		}

		app({ model, view, update, subscriptions, hooks })

		fireDOMLoaded()

		expect(guard).toEqual({ name: "add", data: 2 })
	})

	it("fires onAction when an effect is dispatched", () => {
		let guard = null

		let effectDone = false

		const hooks = {
			onAction: (name, data) => { guard = { name, data } }
		}

		const effects = {
			add: () => { effectDone = true }
		}

		app({ model, view, effects, subscriptions, hooks })

		fireDOMLoaded()

		expect(effectDone).toBe(true)
		expect(guard).toEqual({ name: "add", data: 2 })
	})

	it("fires onError when a effect fails", () => {
		let guard = null

		const hooks = {
			onError: (err) => { guard = err }
		}

		const effects = {
			add: (model, msg, data, error) => { error("effect error") }
		}

		app({ model, view, effects, subscriptions, hooks })

		fireDOMLoaded()

		expect(guard).toEqual("effect error")
	})

	it("throws when onError handler is not given", () => {
		const effects = {
			add: (model, msg, data, error) => {
				try {
					error("no error handler")
				} catch (e) {
					expect(e).toEqual("no error handler")
				}
			}
		}

		app({ model, view, effects, subscriptions })

		fireDOMLoaded()
	})

})

describe("Lifecycle methods", () => {
	const model = 0
	const update = {
		add: (model, data) => model + data
	}
	const subscriptions = [(_, msg) => msg.add(2)]

	it("fires oncreate", done => {
		let guard = null

		app({
			model: {},
			view: () => (html`<div oncreate=${e => guard = e}></div>`)
		})

		setTimeout(() => {
			expect(guard).not.toEqual(null)
			done()
		}, 1)
	})

	it("fires onupdate", done => {
		let guard = null

		const view = (model) => html`<div onupdate=${e => guard = e}></div>`

		app({ model, update, subscriptions, view })

		fireDOMLoaded()

		setTimeout(() => {
			expect(guard).not.toEqual(null)
			done()
		})

	})

	it("fires onremove", done => {
		let guard = null

		const a = html`

1

2

3

4

 guard = e}>foo

`

		const b = html`

foo

bar

`

		const view = model => html`${model === 0 ? a : b}`

		app({ model, view, update, subscriptions })

		fireDOMLoaded()

		setTimeout(() => {
			expect(guard).not.toEqual(null)
			done()
		})
	})
})

describe("Router API", () => {
	it("calls router with object.render(view)", () => {
		const model = "beep"

		app({
			model: "beep",
			router: render => {
				render(model => html`<h1 id="test">${model}</h1>`)
			}
		})

		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toBe(model)
	})

	it("calls router with object.render(view) #2", () => {
		const model = "beep"

		app({
			view: model => html`<h1 id="test">${model}</h1>`,
			model: "beep",
			router: render => render(undefined)
		})

		var el = document.getElementById("test")

		expect(el).not.toBe(null)
		expect(el.innerHTML).toBe(model)
	})
})
<|endoftext|>


<commit_before>'use strict';

var ensureObject = require('es5-ext/object/valid-object');

module.exports = function (processingStepsMeta) {
	ensureObject(processingStepsMeta);

	return {
		'/': require('../view/statistics-dashboard'),
		files: {
			decorateContext: function () { this.processingStepsMeta = processingStepsMeta; },
			view: require('../view/statistics-files-pending')
		},
		'files/completed': require('../view/statistics-files-completed'),
		'files/rejected': require('../view/statistics-files-rejected'),
		'files/accounts': require('../view/statistics-files-accounts'),
		time: require('../view/statistics-time-per-role'),
		'time/per-person': require('../view/statistics-time-per-person'),
		analysis: require('../view/statistics-analysis'),

		profile: require('../view/user-profile')
	};
};
<commit_msg>#1529 adjusted routes<commit_after>'use strict';

var ensureObject = require('es5-ext/object/valid-object');

module.exports = function (processingStepsMeta) {
	ensureObject(processingStepsMeta);

	return {
		'/': require('../view/statistics-dashboard'),
		files: require('../view/statistics-files-completed'),
		'files/pending': {
			decorateContext: function () { this.processingStepsMeta = processingStepsMeta; },
			view: require('../view/statistics-files-pending')
		},
		'files/rejected': require('../view/statistics-files-rejected'),
		'files/accounts': require('../view/statistics-files-accounts'),
		time: require('../view/statistics-time-per-role'),
		'time/per-person': require('../view/statistics-time-per-person'),
		analysis: require('../view/statistics-analysis'),

		profile: require('../view/user-profile')
	};
};
<|endoftext|>


<commit_before>// takes an IR function object and returns a list of Scratch blocks

module.exports.ffi = {};

module.exports.generateFunctionHat = function(func) {
	var spec = func.funcName;
	var inputs = [];
	var defaults = [];

	for(var i = 0; i < func.paramList.length; ++i) {
		if(func.paramList[i][1])
			inputs.push(func.paramList[i][1]);
		else
			inputs.push("param"+i);

		defaults.push(defaultForType(func.paramList[i][0]));
		spec += " "+specifierForType(func.paramList[i][0]);
	}

	return ["procDef", spec, inputs, defaults, false];

}

module.exports.compileFunction = function(func) {
	console.log("Compiling "+JSON.stringify(func)+"...");

	var blockList = [module.exports.generateFunctionHat(func)]
					.concat(initLocal());

	for(var i = 0; i < func.code.length; ++i) {
		console.log(func.code[i]);
		blockList = blockList.concat(compileInstruction(func.code[i]));
	}

	blockList = blockList.concat(returnBlock());

	return blockList;
}

function compileInstruction(block) {
	if(block.type == "call") {
		// calling a (potentially foreign) function
		return callBlock(block);
	} else if(block.type == "ffi") {
		// FFI block
		// load the code from the options
		return module.exports.ffi[block.ffiBlock];
	} else if(block.type == "set") {
		return compileInstruction(block.computation)
				.concat(allocateLocal(block.val));

	}
}

// fixme: stub
function defaultForType(type) {
	console.log(type);
	return 0;
}

// fixme: stub
function specifierForType(type) {
	return "%s";
}

// fixme: stub
function formatValue(type, value) {
	return value;
}

// higher-level code generation
function initLocal() {
	return [
		["append:toList:", "0", "# of locals"]
	]
}

function allocateLocal(val) {
	return [
		["setLine:ofList:to:", "last", "# of locals", ["+", ["getLine:ofList:", "last", "# of locals"], 1]],
		["append:toList:", val, "Stack"]
	];
}

function freeLocals() {
	return [
		["doRepeat", ["getLine:ofList:", "last", "# of locals"], [["deleteLine:ofList:", "last", "Stack"]]],
		["deleteLine:ofList:", "last", "# of locals"]
	];
}

function returnBlock(val) {
	var proc = freeLocals();

	if(val) {
		proc.push(["setVar:to:", "return value", val]);
	}

	proc.push(["stopScripts", "this script"]);

	return proc;
}

function callBlock(block) {
	var spec = block.funcName;
	var args = [];

	for(var a = 0; a < block.paramList.length; ++a) {
		args.push(formatValue(block.paramList[a][0], block.paramList[a][1]));
		spec += " "+specifierForType(block.paramList[a][0]);
	}

	return [
		["call", spec].concat(args)
	];
}<commit_msg>Backend for ret instruction<commit_after>// takes an IR function object and returns a list of Scratch blocks

module.exports.ffi = {};

module.exports.generateFunctionHat = function(func) {
	var spec = func.funcName;
	var inputs = [];
	var defaults = [];

	for(var i = 0; i < func.paramList.length; ++i) {
		if(func.paramList[i][1])
			inputs.push(func.paramList[i][1]);
		else
			inputs.push("param"+i);

		defaults.push(defaultForType(func.paramList[i][0]));
		spec += " "+specifierForType(func.paramList[i][0]);
	}

	return ["procDef", spec, inputs, defaults, false];

}

module.exports.compileFunction = function(func) {
	console.log("Compiling "+JSON.stringify(func)+"...");

	var blockList = [module.exports.generateFunctionHat(func)]
					.concat(initLocal());

	for(var i = 0; i < func.code.length; ++i) {
		console.log(func.code[i]);
		blockList = blockList.concat(compileInstruction(func.code[i]));
	}

	//blockList = blockList.concat(returnBlock());

	return blockList;
}

function compileInstruction(block) {
	if(block.type == "call") {
		// calling a (potentially foreign) function
		return callBlock(block);
	} else if(block.type == "ffi") {
		// FFI block
		// load the code from the options
		return module.exports.ffi[block.ffiBlock];
	} else if(block.type == "set") {
		return compileInstruction(block.computation)
				.concat(allocateLocal(block.val));
	} else if(block.type == "ret") {
		return returnBlock(block.value);
	}
}

// fixme: stub
function defaultForType(type) {
	console.log(type);
	return 0;
}

// fixme: stub
function specifierForType(type) {
	return "%s";
}

// fixme: stub
function formatValue(type, value) {
	return value;
}

// higher-level code generation
function initLocal() {
	return [
		["append:toList:", "0", "# of locals"]
	]
}

function allocateLocal(val) {
	return [
		["setLine:ofList:to:", "last", "# of locals", ["+", ["getLine:ofList:", "last", "# of locals"], 1]],
		["append:toList:", val, "Stack"]
	];
}

function freeLocals() {
	return [
		["doRepeat", ["getLine:ofList:", "last", "# of locals"], [["deleteLine:ofList:", "last", "Stack"]]],
		["deleteLine:ofList:", "last", "# of locals"]
	];
}

function returnBlock(val) {
	var proc = freeLocals();

	if(val) {
		proc.push(["setVar:to:", "return value", val]);
	}

	proc.push(["stopScripts", "this script"]);

	return proc;
}

function callBlock(block) {
	var spec = block.funcName;
	var args = [];

	for(var a = 0; a < block.paramList.length; ++a) {
		args.push(formatValue(block.paramList[a][0], block.paramList[a][1]));
		spec += " "+specifierForType(block.paramList[a][0]);
	}

	return [
		["call", spec].concat(args)
	];
}<|endoftext|>


<commit_before>import { capture, wrap, Match, Skip } from "chimpanzee";
import { root } from "./";
import { composite } from "isotropy-analyzer-utils";

export default function(state, analysisState) {
  return composite(
    {
      type: "MemberExpression",
      object: wrap(root(state, analysisState), {
        key: "root",
        selector: "path"
      }),
      property: {
        type: "Identifier",
        name: capture("collection")
      }
    },
    {
      build: obj => context => result => {
        return result instanceof Match
          ? (() => {
              const database = result.value.root.databases[result.value.collection];
              return database
                ? {
                    identifier: result.value.root.identifier,
                    database,
                  }
                : new Error(
                    `Could not find configuration for key value database ${result
                      .value.collection}.`
                  );
            })()
          : result;
      }
    }
  );
}
<commit_msg>Fixed error message<commit_after>import { capture, wrap, Match, Skip } from "chimpanzee";
import { root } from "./";
import { composite } from "isotropy-analyzer-utils";

export default function(state, analysisState) {
  return composite(
    {
      type: "MemberExpression",
      object: wrap(root(state, analysisState), {
        key: "root",
        selector: "path"
      }),
      property: {
        type: "Identifier",
        name: capture("collection")
      }
    },
    {
      build: obj => context => result => {
        return result instanceof Match
          ? (() => {
              const database =
                result.value.root.databases[result.value.collection];
              return database
                ? {
                    identifier: result.value.root.identifier,
                    database
                  }
                : new Error(
                    `Could not find isotropy plugin configuration for KeyValueDB ${result
                      .value.collection}.`
                  );
            })()
          : result;
      }
    }
  );
}
<|endoftext|>


<commit_before>/* global describe before it */

const helpers = require('yeoman-test');
const assert  = require('yeoman-assert');
const path    = require('path');

describe('generator-api', () => {
  describe('Run yeoman generator-api with no docker support', () => {
    before(() => helpers.run(path.join(__dirname, '../generators/app'))
      .withPrompts({
        serverName       : 'serverName',
        serverDescription: 'serverDescription',
        serverVersion    : 'serverVersion',
        authorName       : 'authorName',
        authorEmail      : 'authorEmail',
        models           : ['foo', 'bar', 'BazFoo'],
        databaseName     : 'databaseName',
        useDocker        : false
      })
      .toPromise());

    // test included files
    [{
      desc : 'generates an index.js file',
      files: ['index.js']
    }, {
      desc : 'generates a router.js file',
      files: ['routes.js']
    }, {
      desc : 'generates a package.json file',
      files: ['package.json']
    }, {
      desc : 'generates a .eslintignore file',
      files: ['.eslintignore']
    }, {
      desc : 'generates a .eslintrc.json file',
      files: ['.eslintrc.json']
    }, {
      desc : 'generates a .gitignore file',
      files: ['.gitignore']
    }, {
      desc : 'generates a config.js file',
      files: ['config.js']
    }, {
      desc : 'generates a README.md file',
      files: ['README.md']
    }].forEach((fileCase) => {
      it(fileCase.desc, () => {
        assert.file(fileCase.files);
      });
    });

    // test not included files
    [{
      desc : 'doest not generate docker files when useDocker = false',
      files: ['Dockerfile', 'docker-compose.yml']
    }].forEach((fileCase) => {
      it(fileCase.desc, () => {
        assert.noFile(fileCase.files);
      });
    });

    it('generated README.md does not include references to docker', () => {
      assert.noFileContent('README.md', /Docker/);
    });

    describe('models', () => {
      it('generates a folder for each model', () => {
        assert.file([
          'model/foo',
          'model/bar',
          'model/foo'
        ]);
      });

      describe('controllers', () => {
        it('generates a controller for each model', () => {
          assert.file([
            'model/foo/controller.js',
            'model/bar/controller.js',
            'model/foo/controller.js'
          ]);
        });
      });

      describe('facades', () => {
        it('generates a facade for each model', () => {
          assert.file([
            'model/foo/facade.js',
            'model/bar/facade.js',
            'model/foo/facade.js'
          ]);
        });
      });

      describe('routes', () => {
        it('generates a router for each model', () => {
          assert.file([
            'model/foo/router.js',
            'model/bar/router.js',
            'model/foo/router.js'
          ]);
        });
      });

      describe('schemas', () => {
        it('generates a schema for each model', () => {
          assert.file([
            'model/foo/schema.js',
            'model/bar/schema.js',
            'model/foo/schema.js'
          ]);
        });
      });
    });

    describe('libs', () => {
      it('generates a lib/controller.js file', () => {
        assert.file(['lib/controller.js']);
      });

      it('generates a lib/facade.js file', () => {
        assert.file(['lib/facade.js']);
      });
    });
  });

  describe.skip('Run yeoman generator-api with docker support', () => {
    before(() => helpers.run(path.join(__dirname, '../generators/app'))
      .withPrompts({
        serverName       : 'serverName',
        serverDescription: 'serverDescription',
        serverVersion    : 'serverVersion',
        authorName       : 'authorName',
        authorEmail      : 'authorEmail',
        models           : ['foo'],
        databaseName     : 'databaseName',
        useDocker        : true
      })
      .toPromise());

    it('generates docker files when use Docker options is set to true', () => {
      assert.file('Dockerfile', 'docker-compose.yml');
    });

    it('generated README.md does include references to docker', () => {
      assert.fileContent('README.md', /Docker/);
    });
  });
});
<commit_msg>Update tests so now it generates 3 different models<commit_after>/* global describe before it */

const helpers = require('yeoman-test');
const assert  = require('yeoman-assert');
const path    = require('path');

describe('generator-api', () => {
  describe('Run yeoman generator-api with no docker support', () => {
    before(() => helpers.run(path.join(__dirname, '../generators/app'))
      .withPrompts({
        serverName       : 'serverName',
        serverDescription: 'serverDescription',
        serverVersion    : 'serverVersion',
        authorName       : 'authorName',
        authorEmail      : 'authorEmail',
        models           : ['foo', 'bar', 'BazFoo'],
        databaseName     : 'databaseName',
        useDocker        : false
      })
      .toPromise());

    // test included files
    [{
      desc : 'generates an index.js file',
      files: ['index.js']
    }, {
      desc : 'generates a router.js file',
      files: ['routes.js']
    }, {
      desc : 'generates a package.json file',
      files: ['package.json']
    }, {
      desc : 'generates a .eslintignore file',
      files: ['.eslintignore']
    }, {
      desc : 'generates a .eslintrc.json file',
      files: ['.eslintrc.json']
    }, {
      desc : 'generates a .gitignore file',
      files: ['.gitignore']
    }, {
      desc : 'generates a config.js file',
      files: ['config.js']
    }, {
      desc : 'generates a README.md file',
      files: ['README.md']
    }].forEach((fileCase) => {
      it(fileCase.desc, () => {
        assert.file(fileCase.files);
      });
    });

    // test not included files
    [{
      desc : 'doest not generate docker files when useDocker = false',
      files: ['Dockerfile', 'docker-compose.yml']
    }].forEach((fileCase) => {
      it(fileCase.desc, () => {
        assert.noFile(fileCase.files);
      });
    });

    it('generated README.md does not include references to docker', () => {
      assert.noFileContent('README.md', /Docker/);
    });

    describe('models', () => {
      it('generates a folder for each model', () => {
        assert.file([
          'model/foo',
          'model/bar',
          'model/baz-foo'
        ]);
      });

      describe('controllers', () => {
        it('generates a controller for each model', () => {
          assert.file([
            'model/foo/controller.js',
            'model/bar/controller.js',
            'model/baz-foo/controller.js'
          ]);
        });
      });

      describe('facades', () => {
        it('generates a facade for each model', () => {
          assert.file([
            'model/foo/facade.js',
            'model/bar/facade.js',
            'model/baz-foo/facade.js'
          ]);
        });
      });

      describe('routes', () => {
        it('generates a router for each model', () => {
          assert.file([
            'model/foo/router.js',
            'model/bar/router.js',
            'model/baz-foo/router.js'
          ]);
        });
      });

      describe('schemas', () => {
        it('generates a schema for each model', () => {
          assert.file([
            'model/foo/schema.js',
            'model/bar/schema.js',
            'model/baz-foo/schema.js'
          ]);
        });
      });
    });

    describe('libs', () => {
      it('generates a lib/controller.js file', () => {
        assert.file(['lib/controller.js']);
      });

      it('generates a lib/facade.js file', () => {
        assert.file(['lib/facade.js']);
      });
    });
  });

  describe.skip('Run yeoman generator-api with docker support', () => {
    before(() => helpers.run(path.join(__dirname, '../generators/app'))
      .withPrompts({
        serverName       : 'serverName',
        serverDescription: 'serverDescription',
        serverVersion    : 'serverVersion',
        authorName       : 'authorName',
        authorEmail      : 'authorEmail',
        models           : ['foo'],
        databaseName     : 'databaseName',
        useDocker        : true
      })
      .toPromise());

    it('generates docker files when use Docker options is set to true', () => {
      assert.file('Dockerfile', 'docker-compose.yml');
    });

    it('generated README.md does include references to docker', () => {
      assert.fileContent('README.md', /Docker/);
    });
  });
});
<|endoftext|>


<commit_before><commit_msg>Pt. 2 - got AutoComplete to work<commit_after><|endoftext|>