<commit_before>/*global fl, Uint8ClampedArray: true */
"use strict";

const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const url = require("url");
const _ = require("lodash");

const highlightColors = [
  "lime",
  "black",
  "blue",
  "darkblue",
  "fuchsia",
  "gray",
  "green",
  "greenyellow",
  "indigo",
  "magenta",
  "midnightblue",
  "maroon",
  "orange",
  "orangered",
  "purple",
  "red",
  "teal",
  "yellow"
];

const __hasProp = {}.hasOwnProperty;
const inherits = function (child, parent) {
  // from CS :(
  let key;
  for (key in parent) {
    if (__hasProp.call(parent, key)) {
      child[key] = parent[key];
    }
  }
  function Ctor() {
    this.constructor = child;
  }
  Ctor.prototype = parent.prototype;
  child.prototype = new Ctor();
  child.__super__ = parent.prototype;
  return child;
};

function md5 (buffer) {
  return crypto.createHash("md5").update(buffer, "utf8").digest("hex");
}

function user_color (username) {
  var i = _.reduce(md5(username), function (memo, c) {
    return memo + c.charCodeAt(0);
  }, 0);

  return highlightColors[i % highlightColors.length];
}

const unix_path_regex = new RegExp("/", "g");
function to_abs_path (rel_posix_path) {
  return path.join(fl.base_path, rel_posix_path.replace(unix_path_regex, path.sep));
}

const os_path_regex = new RegExp(/\\/g);
function to_unix_path (p) {
  return p.replace(os_path_regex, "/");
}

function to_rel_path (abs_path) {
  return to_unix_path(path.relative(fl.base_path, abs_path));
}

function is_shared (p) {
  if (!p) {
    return false;
  }
  return to_rel_path(p).indexOf("..") === -1;
}

function patched_cleanly (result) {
  var clean_patch = true,
    i = 0;

  for (i; i < result[1].length; i++) {
    if (result[1][i] !== true) {
      clean_patch = false;
      break;
    }
  }
  return clean_patch;
}

function is_binary (bytes, size) {
  var i,
    max_bytes = 512,
    suspicious_bytes = 0,
    total_bytes;

  if (size === 0) {
    return false;
  }

  total_bytes = Math.min(size, max_bytes);

  if (size >= 3 && bytes[0] === 0xEF && bytes[1] === 0xBB && bytes[2] === 0xBF) {
    // UTF-8 BOM. This isn't binary.
    return false;
  }

  if (size > 4 && bytes.slice(0, 5) === "%PDF-") {
    /* PDF. This is binary. */
    return true;
  }

  for (i = 0; i < total_bytes; i++) {
    if (bytes[i] === 0) { // NULL byte--it's binary!
      return true;
    }
    if ((bytes[i] < 7 || bytes[i] > 14) && (bytes[i] < 32 || bytes[i] > 127)) {
      // UTF-8 detection
      if (bytes[i] > 191 && bytes[i] < 224 && i + 1 < total_bytes) {
        i++;
        if (bytes[i] < 192) {
          continue;
        }
      } else if (bytes[i] > 223 && bytes[i] < 239 && i + 2 < total_bytes) {
        i++;
        if (bytes[i] < 192 && bytes[i + 1] < 192) {
          i++;
          continue;
        }
      }
      suspicious_bytes++;
      // Read at least 32 bytes before making a decision
      if (i > 32 && (suspicious_bytes * 100) / total_bytes > 10) {
        return true;
      }
    }
  }
  if ((suspicious_bytes * 100) / total_bytes > 10) {
    return true;
  }

  return false;
}

function load_floo (_path) {
  var floo_file, data = {};

  _path = path.join(_path, ".floo");
  console.debug("Loading floo file", _path);

  try {
    /*eslint-disable no-sync */
    floo_file = fs.readFileSync(_path, {
      encoding: "utf8",
    });
    /*eslint-enable no-sync */
    data = JSON.parse(floo_file);
  } catch (ignore) {
    // Unused
  }
  return data;
}

function write_floo (_path, data) {
  _path = path.join(_path, ".floo");

  console.debug("Writing floo file", _path);
  try {
    /*eslint-disable no-sync */
    fs.writeFileSync(_path, JSON.stringify(data, null, "    "));
    /*eslint-enable no-sync */
  } catch (ignore) {
    // Unused
  }
  return data;
}

function parse_url (workspace_url) {
  var parsed_url,
    res,
    url_path,
    exit = function () {
      console.error("The workspace must be a valid url:", workspace_url);
    };

  try {
    parsed_url = url.parse(workspace_url);
  } catch (e) {
    return exit();
  }
  url_path = parsed_url.path;

  res = url_path.match(/^\/([\-\@\+\.\w]+)\/([\-\.\w]+)\/?.*$/);
  if (!res) {
    return exit();
  }

  return {
    host: parsed_url.hostname,
    port: parsed_url.protocol === "http" ? 3148 : 3448,
    owner: res[1],
    secure: parsed_url.protocol === "https",
    workspace: res[2]
  };
}

function requestFullscreen (elem) {
  if (elem.requestFullscreen) {
    elem.requestFullscreen();
  } else if (elem.msRequestFullscreen) {
    elem.msRequestFullscreen();
  } else if (elem.mozRequestFullScreen) {
    elem.mozRequestFullScreen();
  } else if (elem.webkitRequestFullscreen) {
    elem.webkitRequestFullscreen();
  }
}

function exitFullscreen () {
  if (document.exitFullscreen) {
    document.exitFullscreen();
  } else if (document.msExitFullscreen) {
    document.msExitFullscreen();
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
  } else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen();
  }
}

function getFullscreenElement () {
  return document.fullscreenElement ||
    document.mozFullScreenElement ||
    document.webkitFullscreenElement ||
    document.msFullscreenElement;
}

const BROWSER_CLIENTS = [
  "Atom",
  "Chrome",
  "Firefox",
  "IE",
  "Opera",
  "Safari",
  "web",
];

function findDirectory (pathToFloobits) {
  const dirs = atom.project.getDirectories();
  return _.find(dirs, function (d) {
    // TODO: normalize paths before compare
    /* eslint-disable no-sync */
    return d.getRealPathSync() === pathToFloobits;
    /* eslint-enable no-sync */
  });
}

function padNum (padNum) {
  var n;
  n = padNum.toString(10);
  if (n.length < 2) {
    return "0" + n;
  }
  return n;
}

const MONTHS = [
  "Jan",
  "Feb",
  "Mar",
  "Apr",
  "May",
  "Jun",
  "Jul",
  "Aug",
  "Sep",
  "Oct",
  "Nov",
  "Dec"
];

const ONEMINUTE = 1000 * 60;
const ONEYEAR = ONEMINUTE * 60 * 60 * 24 * 365;

function formatDate (date) {
  const month = MONTHS[date.getMonth()];
  const h = date.getHours();
  const year = date.getFullYear();
  const hour = padNum(h);
  const day = padNum(date.getDate());
  const minute = padNum(date.getMinutes());
  const second = padNum(date.getSeconds());
  const alongtimeago = date.getTime() < (new Date().getTime() - ONEYEAR);
  const ashortimeago = date.getTime() > (new Date().getTime() - (ONEMINUTE * 3));
  const formatted = [
    month,
    " ",
    (alongtimeago ? year + " " : ""),
    day,
    " ",
    hour,
    ":",
    minute,
    (ashortimeago ? ":" + second : ""),
    " ",
  ].join("");
  return {
    date: date,
    formatted: formatted,
    month: month,
    day: day,
    hour: hour,
    minute: minute,
    second: second,
    year: year,
    alongtimeago: alongtimeago,
    ashortimeago: ashortimeago,
    meridian: h < 12 ? "AM" : "PM",
  };
}

const extensions_to_mime = {
  "bmp": "bmp",
  "cgm": "cgm",
  "g3": "g3fax",
  "gif": "gif",
  "ief": "ief",
  "jp2": "jp2",
  "jpeg": "jpeg",
  "jpg": "jpeg",
  "jpe": "jpeg",
  "pict": "pict",
  "pic": "pict",
  "pct": "pict",
  "png": "png",
  "btif": "prs.btif",
  "svg": "svg+xml",
  "svgz": "svg+xml",
  "tiff": "tiff",
  "tif": "tiff",
  "psd": "vnd.adobe.photoshop",
  "djvu": "vnd.djvu",
  "djv": "vnd.djvu",
  "dwg": "vnd.dwg",
  "dxf": "vnd.dxf",
  "fbs": "vnd.fastbidsheet",
  "fpx": "vnd.fpx",
  "fst": "vnd.fst",
  "mmr": "vnd.fujixerox.edmics-mmr",
  "rlc": "vnd.fujixerox.edmics-rlc",
  "mdi": "vnd.ms-modi",
  "npx": "vnd.net-fpx",
  "wbmp": "vnd.wap.wbmp",
  "xif": "vnd.xiff",
  "ras": "x-cmu-raster",
  "cmx": "x-cmx",
  "ico": "x-icon",
  "pntg": "x-macpaint",
  "pnt": "x-macpaint",
  "mac": "x-macpaint",
  "pcx": "x-pcx",
  "pnm": "x-portable-anymap",
  "pbm": "x-portable-bitmap",
  "pgm": "x-portable-graymap",
  "ppm": "x-portable-pixmap",
  "qtif": "x-quicktime",
  "qti": "x-quicktime",
  "rgb": "x-rgb",
  "xbm": "x-xbitmap",
  "xpm": "x-xpixmap",
  "xwd": "x-xwindowdump"
};

function image_mime_from_extension (name) {
  var extension = name.split(".").slice(-1);
  try {
    extension = extension[0].toLowerCase();
    return extensions_to_mime[extension];
  } catch (e) {
    console.log("image_mime_from_extension:", e);
  }
  return null;
}

let uint8array;
if (typeof Uint8ClampedArray !== "undefined") {
  uint8array = Uint8ClampedArray;
} else if (typeof Uint8Array !== "undefined") {
  uint8array = Uint8ClampedArray = Uint8Array;
} else {
  uint8array = Uint8ClampedArray = null;
}

module.exports = {
  formatDate: formatDate,
  image_mime_from_extension: image_mime_from_extension,
  padNum: padNum,
  requestFullscreen: requestFullscreen,
  exitFullscreen: exitFullscreen,
  getFullscreenElement: getFullscreenElement,
  inherits: inherits,
  to_abs_path: to_abs_path,
  to_rel_path: to_rel_path,
  is_binary: is_binary,
  md5: md5,
  load_floo: load_floo,
  write_floo: write_floo,
  is_shared: is_shared,
  parse_url: parse_url,
  patched_cleanly: patched_cleanly,
  user_color: user_color,
  findDirectory: findDirectory,
  Uint8ClampedArray: uint8array,
  BROWSER_CLIENTS: BROWSER_CLIENTS,
};
<commit_msg>Add carriage return regex to utils.<commit_after>/*global fl, Uint8ClampedArray: true */
"use strict";

const crypto = require("crypto");
const fs = require("fs");
const path = require("path");
const url = require("url");
const _ = require("lodash");

const highlightColors = [
  "lime",
  "black",
  "blue",
  "darkblue",
  "fuchsia",
  "gray",
  "green",
  "greenyellow",
  "indigo",
  "magenta",
  "midnightblue",
  "maroon",
  "orange",
  "orangered",
  "purple",
  "red",
  "teal",
  "yellow"
];

/*eslint-disable no-control-regex */
const CRRegex = new RegExp("\r", "g");
/*eslint-enable no-control-regex */

const __hasProp = {}.hasOwnProperty;
const inherits = function (child, parent) {
  // from CS :(
  let key;
  for (key in parent) {
    if (__hasProp.call(parent, key)) {
      child[key] = parent[key];
    }
  }
  function Ctor() {
    this.constructor = child;
  }
  Ctor.prototype = parent.prototype;
  child.prototype = new Ctor();
  child.__super__ = parent.prototype;
  return child;
};

function md5 (buffer) {
  return crypto.createHash("md5").update(buffer, "utf8").digest("hex");
}

function user_color (username) {
  var i = _.reduce(md5(username), function (memo, c) {
    return memo + c.charCodeAt(0);
  }, 0);

  return highlightColors[i % highlightColors.length];
}

const unix_path_regex = new RegExp("/", "g");
function to_abs_path (rel_posix_path) {
  return path.join(fl.base_path, rel_posix_path.replace(unix_path_regex, path.sep));
}

const os_path_regex = new RegExp(/\\/g);
function to_unix_path (p) {
  return p.replace(os_path_regex, "/");
}

function to_rel_path (abs_path) {
  return to_unix_path(path.relative(fl.base_path, abs_path));
}

function is_shared (p) {
  if (!p) {
    return false;
  }
  return to_rel_path(p).indexOf("..") === -1;
}

function patched_cleanly (result) {
  var clean_patch = true,
    i = 0;

  for (i; i < result[1].length; i++) {
    if (result[1][i] !== true) {
      clean_patch = false;
      break;
    }
  }
  return clean_patch;
}

function is_binary (bytes, size) {
  var i,
    max_bytes = 512,
    suspicious_bytes = 0,
    total_bytes;

  if (size === 0) {
    return false;
  }

  total_bytes = Math.min(size, max_bytes);

  if (size >= 3 && bytes[0] === 0xEF && bytes[1] === 0xBB && bytes[2] === 0xBF) {
    // UTF-8 BOM. This isn't binary.
    return false;
  }

  if (size > 4 && bytes.slice(0, 5) === "%PDF-") {
    /* PDF. This is binary. */
    return true;
  }

  for (i = 0; i < total_bytes; i++) {
    if (bytes[i] === 0) { // NULL byte--it's binary!
      return true;
    }
    if ((bytes[i] < 7 || bytes[i] > 14) && (bytes[i] < 32 || bytes[i] > 127)) {
      // UTF-8 detection
      if (bytes[i] > 191 && bytes[i] < 224 && i + 1 < total_bytes) {
        i++;
        if (bytes[i] < 192) {
          continue;
        }
      } else if (bytes[i] > 223 && bytes[i] < 239 && i + 2 < total_bytes) {
        i++;
        if (bytes[i] < 192 && bytes[i + 1] < 192) {
          i++;
          continue;
        }
      }
      suspicious_bytes++;
      // Read at least 32 bytes before making a decision
      if (i > 32 && (suspicious_bytes * 100) / total_bytes > 10) {
        return true;
      }
    }
  }
  if ((suspicious_bytes * 100) / total_bytes > 10) {
    return true;
  }

  return false;
}

function load_floo (_path) {
  var floo_file, data = {};

  _path = path.join(_path, ".floo");
  console.debug("Loading floo file", _path);

  try {
    /*eslint-disable no-sync */
    floo_file = fs.readFileSync(_path, {
      encoding: "utf8",
    });
    /*eslint-enable no-sync */
    data = JSON.parse(floo_file);
  } catch (ignore) {
    // Unused
  }
  return data;
}

function write_floo (_path, data) {
  _path = path.join(_path, ".floo");

  console.debug("Writing floo file", _path);
  try {
    /*eslint-disable no-sync */
    fs.writeFileSync(_path, JSON.stringify(data, null, "    "));
    /*eslint-enable no-sync */
  } catch (ignore) {
    // Unused
  }
  return data;
}

function parse_url (workspace_url) {
  var parsed_url,
    res,
    url_path,
    exit = function () {
      console.error("The workspace must be a valid url:", workspace_url);
    };

  try {
    parsed_url = url.parse(workspace_url);
  } catch (e) {
    return exit();
  }
  url_path = parsed_url.path;

  res = url_path.match(/^\/([\-\@\+\.\w]+)\/([\-\.\w]+)\/?.*$/);
  if (!res) {
    return exit();
  }

  return {
    host: parsed_url.hostname,
    port: parsed_url.protocol === "http" ? 3148 : 3448,
    owner: res[1],
    secure: parsed_url.protocol === "https",
    workspace: res[2]
  };
}

function requestFullscreen (elem) {
  if (elem.requestFullscreen) {
    elem.requestFullscreen();
  } else if (elem.msRequestFullscreen) {
    elem.msRequestFullscreen();
  } else if (elem.mozRequestFullScreen) {
    elem.mozRequestFullScreen();
  } else if (elem.webkitRequestFullscreen) {
    elem.webkitRequestFullscreen();
  }
}

function exitFullscreen () {
  if (document.exitFullscreen) {
    document.exitFullscreen();
  } else if (document.msExitFullscreen) {
    document.msExitFullscreen();
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
  } else if (document.webkitExitFullscreen) {
    document.webkitExitFullscreen();
  }
}

function getFullscreenElement () {
  return document.fullscreenElement ||
    document.mozFullScreenElement ||
    document.webkitFullscreenElement ||
    document.msFullscreenElement;
}

const BROWSER_CLIENTS = [
  "Atom",
  "Chrome",
  "Firefox",
  "IE",
  "Opera",
  "Safari",
  "web",
];

function findDirectory (pathToFloobits) {
  const dirs = atom.project.getDirectories();
  return _.find(dirs, function (d) {
    // TODO: normalize paths before compare
    /* eslint-disable no-sync */
    return d.getRealPathSync() === pathToFloobits;
    /* eslint-enable no-sync */
  });
}

function padNum (padNum) {
  var n;
  n = padNum.toString(10);
  if (n.length < 2) {
    return "0" + n;
  }
  return n;
}

const MONTHS = [
  "Jan",
  "Feb",
  "Mar",
  "Apr",
  "May",
  "Jun",
  "Jul",
  "Aug",
  "Sep",
  "Oct",
  "Nov",
  "Dec"
];

const ONEMINUTE = 1000 * 60;
const ONEYEAR = ONEMINUTE * 60 * 60 * 24 * 365;

function formatDate (date) {
  const month = MONTHS[date.getMonth()];
  const h = date.getHours();
  const year = date.getFullYear();
  const hour = padNum(h);
  const day = padNum(date.getDate());
  const minute = padNum(date.getMinutes());
  const second = padNum(date.getSeconds());
  const alongtimeago = date.getTime() < (new Date().getTime() - ONEYEAR);
  const ashortimeago = date.getTime() > (new Date().getTime() - (ONEMINUTE * 3));
  const formatted = [
    month,
    " ",
    (alongtimeago ? year + " " : ""),
    day,
    " ",
    hour,
    ":",
    minute,
    (ashortimeago ? ":" + second : ""),
    " ",
  ].join("");
  return {
    date: date,
    formatted: formatted,
    month: month,
    day: day,
    hour: hour,
    minute: minute,
    second: second,
    year: year,
    alongtimeago: alongtimeago,
    ashortimeago: ashortimeago,
    meridian: h < 12 ? "AM" : "PM",
  };
}

const extensions_to_mime = {
  "bmp": "bmp",
  "cgm": "cgm",
  "g3": "g3fax",
  "gif": "gif",
  "ief": "ief",
  "jp2": "jp2",
  "jpeg": "jpeg",
  "jpg": "jpeg",
  "jpe": "jpeg",
  "pict": "pict",
  "pic": "pict",
  "pct": "pict",
  "png": "png",
  "btif": "prs.btif",
  "svg": "svg+xml",
  "svgz": "svg+xml",
  "tiff": "tiff",
  "tif": "tiff",
  "psd": "vnd.adobe.photoshop",
  "djvu": "vnd.djvu",
  "djv": "vnd.djvu",
  "dwg": "vnd.dwg",
  "dxf": "vnd.dxf",
  "fbs": "vnd.fastbidsheet",
  "fpx": "vnd.fpx",
  "fst": "vnd.fst",
  "mmr": "vnd.fujixerox.edmics-mmr",
  "rlc": "vnd.fujixerox.edmics-rlc",
  "mdi": "vnd.ms-modi",
  "npx": "vnd.net-fpx",
  "wbmp": "vnd.wap.wbmp",
  "xif": "vnd.xiff",
  "ras": "x-cmu-raster",
  "cmx": "x-cmx",
  "ico": "x-icon",
  "pntg": "x-macpaint",
  "pnt": "x-macpaint",
  "mac": "x-macpaint",
  "pcx": "x-pcx",
  "pnm": "x-portable-anymap",
  "pbm": "x-portable-bitmap",
  "pgm": "x-portable-graymap",
  "ppm": "x-portable-pixmap",
  "qtif": "x-quicktime",
  "qti": "x-quicktime",
  "rgb": "x-rgb",
  "xbm": "x-xbitmap",
  "xpm": "x-xpixmap",
  "xwd": "x-xwindowdump"
};

function image_mime_from_extension (name) {
  var extension = name.split(".").slice(-1);
  try {
    extension = extension[0].toLowerCase();
    return extensions_to_mime[extension];
  } catch (e) {
    console.log("image_mime_from_extension:", e);
  }
  return null;
}

let uint8array;
if (typeof Uint8ClampedArray !== "undefined") {
  uint8array = Uint8ClampedArray;
} else if (typeof Uint8Array !== "undefined") {
  uint8array = Uint8ClampedArray = Uint8Array;
} else {
  uint8array = Uint8ClampedArray = null;
}

module.exports = {
  CRRegex,
  formatDate: formatDate,
  image_mime_from_extension: image_mime_from_extension,
  padNum: padNum,
  requestFullscreen: requestFullscreen,
  exitFullscreen: exitFullscreen,
  getFullscreenElement: getFullscreenElement,
  inherits: inherits,
  to_abs_path: to_abs_path,
  to_rel_path: to_rel_path,
  is_binary: is_binary,
  md5: md5,
  load_floo: load_floo,
  write_floo: write_floo,
  is_shared: is_shared,
  parse_url: parse_url,
  patched_cleanly: patched_cleanly,
  user_color: user_color,
  findDirectory: findDirectory,
  Uint8ClampedArray: uint8array,
  BROWSER_CLIENTS: BROWSER_CLIENTS,
};
<|endoftext|>


<commit_before>/*global suite:true, test:true, setup:true, teardown:true*/ // mocha
/*global suiteSetup:true, suiteTeardown:true*/ // mocha
/*global assert:true*/ // chai

define(['BlinkForms', 'BIC'], function (Forms) {
  suite('4: subForms', function () {
    var $doc = $(document),
      $page = $('[data-role=page]'),
      $content = $page.find('[data-role=content]');

    /**
     * execute once before everything else in this suite
     */
    suiteSetup(function () {
      $content.empty();
      delete Forms.current;
    });

    suite('Form', function () {

      test('BlinkForms global is an Object', function () {
        assert($.isPlainObject(Forms), 'BlinkForms is a JavaScript object');
      });

      test('initialise with form.json', function (done) {
        var form;

        Forms.getDefinition('form1', 'add').then(function (def) {
          Forms.initialize(def, 'add');
          form = Forms.current;
          assert.equal($.type(form), 'object');
          assert.equal(form.get('name'), 'form1');
          assert.equal(form.get('label'), 'Form 1');
          done();
        }, function () {
          assert.fail(true, false, 'getDefinition failed!');
          done();
        });
      });

      test('render form for jQuery Mobile', function (done) {
        var form = Forms.current;

        $content.append(form.$form);

        $doc.one('pageinit', function () {
          done();
        });

        $.mobile.page({}, $page);
        $page.trigger('pagecreate');
        $page.show();
      });

    }); // END: suite('Form', ...)

    suite('Sub-Forms', function () {

      test('add 1st subForm', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          $view = subFormElement.attributes._view.$el,
          $add = $view.children('.ui-btn').children('button'),
          subForms = subFormElement.attributes.forms;

        assert.equal(subForms.length, 0, 'no subForms yet');
        $add.trigger('click');
        setTimeout(function () {
          done();
        }, 0);
      });

      test('Data has _action set properly', function (done) {

        BMP.Forms.current.data().then(function (data) {
          assert.equal(data._action, "add");
          assert.equal(data.comments[0]._action, "add");
          done();
        });
      });

      test('add 2nd subForm', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          $view = subFormElement.attributes._view.$el,
          $add = $view.children('.ui-btn').children('button'),
          subForms = subFormElement.attributes.forms;

        assert.equal(subForms.length, 1, '1 subForm');
        $add.trigger('click');
        setTimeout(function () {
          done();
        }, 0);
      });

      test('test subForms', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          testData = [
            { comment: 'abc' },
            { comment: 'def' }
          ];

        assert.equal(subForms.length, 2, '2 subForms');
        subForms.at(0).getElement('comment').val('abc');
        subForms.at(1).getElement('comment').val('def');
        subFormElement.data()
          .then(function (d) {
            assert.deepEqual(d, testData, 'subFormElement data');
            return Forms.current.data();
          })
          .then(function (d) {
            assert.deepEqual(d.comments, testData, 'total form data');
            done();
          });
      });

      test('remove 1st subForm', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          subForm = subForms.at(0),
          $view = subForm.attributes._view.$el,
          $remove = $view.children('.ui-btn').children('button');

        assert.equal(subForms.length, 2);

        $remove.trigger('click');
        setTimeout(function () {
          assert.equal(subForms.length, 1);
          done();
        }, 0);
      });

      test('test subForms', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          testData = [
            { comment: 'def' }
          ];

        assert.equal(subForms.length, 1, '1 subForm');
        subForms.at(0).getElement('comment').val('def');
        subFormElement.data()
          .then(function (d) {
            assert.deepEqual(d, testData, 'subFormElement data');
            return Forms.current.data();
          })
          .then(function (d) {
            assert.deepEqual(d.comments, testData, 'total form data');
            done();
          });
      });

      test('remove edit subForm (leaving placeholder)', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          subForm = subForms.at(0),
          $view = subForm.attributes._view.$el,
          $remove = $view.children('.ui-btn').children('button'),
          testData = {
            _action: "remove",
            id: 1
          };

        assert.equal($view.children('section').length, 1);
        assert.equal(subForms.length, 1);

        subForm.set('_action', 'edit');
        subForm.set('id', 1);

        $remove.trigger('click');
        setTimeout(function () {
          subFormElement = Forms.current.getElement('comments');
          subForms = subFormElement.attributes.forms;
          subForm = subForms.at(0);

          assert.deepEqual(subForm.attributes, testData, "attributes set correctly");
          assert.equal(subForms.length, 1);
          done();
        }, 0);
      });

      //FORMS-98 # Forms 3: Subform minus button doesn't work
      test('test add subform', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          $view = subFormElement.attributes._view.$el,
          $add = $view.children('.ui-btn').children('button'),
          subForms = subFormElement.attributes.forms;

        assert.equal(subForms.length, 1, 'no subForms yet');
        $add.trigger('click');
        setTimeout(function () {
          done();
        }, 0);
      });

      test('remove subForm (leaving no placeholders)', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          subForm = subForms.at(1),
          $view = subForm.attributes._view.$el,
          $remove = $view.children('.ui-btn').children('button');

        //will have one section available in DOM
        assert.equal($view.children('section').length, 1);
        assert.equal(subForms.length, 2);
        $remove.trigger('click');

        setTimeout(function () {
          //will have zero section available in DOM
          assert.equal($view.children('section').length, 0);
          assert.equal(subForms.length, 1);
          done();
        }, 0);
      });

    });

    suite('incomplete: Edit Form', function () {

      test('initialise with form.json');

/*
      test('initialise with form.json', function (done) {
        var form = Forms.current;
        $.get("getformrecord.xml").then(
          function (data) {
            var record = {}, node, nodes;
            nodes = data.evaluate('//' + form.attributes.name, data);
            node = nodes.iterateNext();
            _.each(node.children, function (key) {
              record[key.nodeName] = key.innerHTML;
            });
            form.setRecord(record).then(function () {
              form.data().then(function (formdata) {
                assert.deepEqual(formdata, record, 'form data');
              });
            });
          }
        );
        done();
      });
    */
    });

  }); // END: suite('1', ...)

});
<commit_msg>Updated test for size() api method<commit_after>/*global suite:true, test:true, setup:true, teardown:true*/ // mocha
/*global suiteSetup:true, suiteTeardown:true*/ // mocha
/*global assert:true*/ // chai

define(['BlinkForms', 'BIC'], function (Forms) {
  suite('4: subForms', function () {
    var $doc = $(document),
      $page = $('[data-role=page]'),
      $content = $page.find('[data-role=content]');

    /**
     * execute once before everything else in this suite
     */
    suiteSetup(function () {
      $content.empty();
      delete Forms.current;
    });

    suite('Form', function () {

      test('BlinkForms global is an Object', function () {
        assert($.isPlainObject(Forms), 'BlinkForms is a JavaScript object');
      });

      test('initialise with form.json', function (done) {
        var form;

        Forms.getDefinition('form1', 'add').then(function (def) {
          Forms.initialize(def, 'add');
          form = Forms.current;
          assert.equal($.type(form), 'object');
          assert.equal(form.get('name'), 'form1');
          assert.equal(form.get('label'), 'Form 1');
          done();
        }, function () {
          assert.fail(true, false, 'getDefinition failed!');
          done();
        });
      });

      test('render form for jQuery Mobile', function (done) {
        var form = Forms.current;

        $content.append(form.$form);

        $doc.one('pageinit', function () {
          done();
        });

        $.mobile.page({}, $page);
        $page.trigger('pagecreate');
        $page.show();
      });

    }); // END: suite('Form', ...)

    suite('Sub-Forms', function () {

      test('add 1st subForm', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          $view = subFormElement.attributes._view.$el,
          $add = $view.children('.ui-btn').children('button'),
          subForms = subFormElement.attributes.forms;

        assert.equal(subForms.length, 0, 'no subForms yet');
        $add.trigger('click');
        setTimeout(function () {
          done();
        }, 0);
      });

      test('Data has _action set properly', function (done) {

        BMP.Forms.current.data().then(function (data) {
          assert.equal(data._action, "add");
          assert.equal(data.comments[0]._action, "add");
          done();
        });
      });

      test('add 2nd subForm', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          $view = subFormElement.attributes._view.$el,
          $add = $view.children('.ui-btn').children('button'),
          subForms = subFormElement.attributes.forms;

        assert.equal(subForms.length, 1, '1 subForm');
        $add.trigger('click');
        setTimeout(function () {
          done();
        }, 0);
      });

      test('test subForms', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          testData = [
            { comment: 'abc' },
            { comment: 'def' }
          ];

        assert.equal(subForms.length, 2, '2 subForms');
        subForms.at(0).getElement('comment').val('abc');
        subForms.at(1).getElement('comment').val('def');
        subFormElement.data()
          .then(function (d) {
            assert.deepEqual(d, testData, 'subFormElement data');
            return Forms.current.data();
          })
          .then(function (d) {
            assert.deepEqual(d.comments, testData, 'total form data');
            done();
          });
      });

      test('remove 1st subForm', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          subForm = subForms.at(0),
          $view = subForm.attributes._view.$el,
          $remove = $view.children('.ui-btn').children('button');

        assert.equal(subForms.length, 2);

        $remove.trigger('click');
        setTimeout(function () {
          assert.equal(subForms.length, 1);
          done();
        }, 0);
      });

      test('test subForms', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          testData = [
            { comment: 'def' }
          ];

        assert.equal(subForms.length, 1, '1 subForm');
        subForms.at(0).getElement('comment').val('def');
        subFormElement.data()
          .then(function (d) {
            assert.deepEqual(d, testData, 'subFormElement data');
            return Forms.current.data();
          })
          .then(function (d) {
            assert.deepEqual(d.comments, testData, 'total form data');
            done();
          });
      });

      test('remove edit subForm (leaving placeholder)', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          subForm = subForms.at(0),
          $view = subForm.attributes._view.$el,
          $remove = $view.children('.ui-btn').children('button'),
          testData = {
            _action: "remove",
            id: 1
          };

        assert.equal($view.children('section').length, 1);
        assert.equal(subForms.length, 1);
        assert.equal(subForms.size(), 1);

        subForm.set('_action', 'edit');
        subForm.set('id', 1);

        $remove.trigger('click');
        setTimeout(function () {
          subFormElement = Forms.current.getElement('comments');
          subForms = subFormElement.attributes.forms;
          subForm = subForms.at(0);

          assert.deepEqual(subForm.attributes, testData, "attributes set correctly");
          assert.equal(subForms.length, 1);
          assert.equal(subForms.size(), 1);
          done();
        }, 0);
      });

      //FORMS-98 # Forms 3: Subform minus button doesn't work
      test('test add subform', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          $view = subFormElement.attributes._view.$el,
          $add = $view.children('.ui-btn').children('button'),
          subForms = subFormElement.attributes.forms;

        assert.equal(subForms.length, 1, 'no subForms yet');
        assert.equal(subForms.size(), 1);
        $add.trigger('click');
        setTimeout(function () {
          done();
        }, 0);
      });

      test('remove subForm (leaving no placeholders)', function (done) {
        var subFormElement = Forms.current.getElement('comments'),
          subForms = subFormElement.attributes.forms,
          subForm = subForms.at(1),
          $view = subForm.attributes._view.$el,
          $remove = $view.children('.ui-btn').children('button');

        //will have one section available in DOM
        assert.equal($view.children('section').length, 1);
        assert.equal(subForms.length, 2);
        assert.equal(subForms.size(), 2);

        $remove.trigger('click');

        setTimeout(function () {
          //will have zero section available in DOM
          assert.equal($view.children('section').length, 0);
          assert.equal(subForms.length, 1);
          assert.equal(subForms.size(), 1);
          done();
        }, 0);
      });

    });

    suite('incomplete: Edit Form', function () {

      test('initialise with form.json');

/*
      test('initialise with form.json', function (done) {
        var form = Forms.current;
        $.get("getformrecord.xml").then(
          function (data) {
            var record = {}, node, nodes;
            nodes = data.evaluate('//' + form.attributes.name, data);
            node = nodes.iterateNext();
            _.each(node.children, function (key) {
              record[key.nodeName] = key.innerHTML;
            });
            form.setRecord(record).then(function () {
              form.data().then(function (formdata) {
                assert.deepEqual(formdata, record, 'form data');
              });
            });
          }
        );
        done();
      });
    */
    });

  }); // END: suite('1', ...)

});
<|endoftext|>


<commit_before>("undefined"!==typeof define?define:function(d){composed=d()})(function(){function d(a,b){return 0>=b?g:1===b?a:f(d(a,b-1),a)}function e(a){return function(b){var c=l.call(arguments,1);if(0===c.length)c=g;else var d=c,e=a(b),c=function(){return m.call(d,e,arguments)};return c}}function h(a,b){return function(){return n.call(a,b,arguments)}}function g(){}function i(a){return function(b,c){return c.apply(a,b)}}function j(a){return function(b,c){return[c.apply(a,b)]}}var k=Array.prototype.concat,l=Array.prototype.slice,
m=Array.prototype.reduce,n=Array.prototype.reduceRight,f,p=j(void 0);f=function(){var a=h(arguments,p);return function(){return a.apply(void 0,arguments)[0]}};var q=i(void 0);return{compose:f,composeChain:e(j),composeChainExplicit:e(function(a){return function(b,c){return[c.apply(void 0,k.apply([a],b))]}}),composeIterate:d,wrap:function(){return h(arguments,q)},wrapChain:e(i),wrapChainExplicit:e(function(a){return function(b,c){return c.apply(void 0,k.apply([a],b))}})}});<commit_msg>Updated min<commit_after>("undefined"!==typeof define?define:function(f){composed=f()})(function(){function f(a,b){return 0>=b?i:1===b?a:l(f(a,b-1),a)}function l(){return g(m,d(arguments,n))}function p(a,b){return 0>=b?i:1===b?a:q(p(a,b-1),a)}function q(){return d(arguments,r)}function c(a,b){return function(c){return 1===arguments.length?i:a(u.call(arguments,1),b(c))}}function s(a){return g(t,j(a))}function k(a){return g(t,h(a))}function j(a){return function(b,c){return c.apply(void 0,v.apply([a],b))}}function h(a){return function(b,
c){return c.apply(a,b)}}function d(a,b){return function(){return w.call(a,b,arguments)}}function e(a,b){return function(){return x.call(a,b,arguments)}}function g(a,b){return function(){return a(b.apply(void 0,arguments))}}function t(a){return[a]}function m(a){return a[0]}function i(){}var v=Array.prototype.concat,u=Array.prototype.slice,x=Array.prototype.reduce,w=Array.prototype.reduceRight,r=h(void 0),n=k(void 0);return{compose:l,composel:function(){return g(m,e(arguments,n))},composeChain:c(d,
k),composeChainl:c(e,k),composeChainExplicit:c(d,s),composeChainExplicitl:c(e,s),composeIterate:f,wrap:q,wrapl:function(){return e(arguments,r)},wrapChain:c(d,h),wrapChainl:c(e,h),wrapChainExplicit:c(d,j),wrapChainExplicitl:c(d,j),wrapIterate:p}});<|endoftext|>


<commit_before>'use strict'

const fs = require('fs')
const path = require('path')
const chalk = require('chalk')

const console = require('../helpers/color-console')
const sfs = require('../helpers/sfs')
const zip = require('../helpers/zip')

const {createTemplate} = require('./template')

const config = require('../config')
const {imagesFolderName, authorizedImageFormats} = require('../assets')

// -------------------------------------------------------------
// Module.
// -------------------------------------------------------------

function build (dataFile, presskit, {
  company = {},
  products = [],
  analytics = ''
} = {}) {
  const template = createTemplate(presskit.type)
  const assetsSourceDir = getImagesFolder(dataFile)
  const images = getImages(assetsSourceDir)

  // Apply data to template.
  let html = template({
    presskit: presskit,
    company,
    products,
    images: images,
    assets: (presskit.type !== 'company' ? '..' : '.'),
    analytics,

    // Handlebars can't check for equality, so we provide two
    // variables to differentiate a product and a company sheet.
    isCompany: presskit.type === 'company',
    isProduct: presskit.type === 'product'
  })

  const buildDir = createAndGetBuildFolder()
  let targetDir = buildDir

  if (presskit.type !== 'company') {
    // Company should be placed in the root folder
    // but each product is a subfolder, named as the source's folder name
    targetDir = path.join(buildDir, path.basename(path.dirname(dataFile)))
    sfs.createDir(targetDir)
  }

  // Prepare output filename
  let htmlFilename = 'index.html'
  let htmlDestination = path.join(targetDir, htmlFilename)

  console.log(`- "${presskit.title}" -> ${chalk.blue(htmlDestination)}`)

  // -- Write HTML
  fs.writeFileSync(htmlDestination, html)

  // Copy all assets from images/ to build/images/
  // ---------------------------------------------------------------
  let assetsTargetDir = path.join(targetDir, imagesFolderName)
  if (fs.existsSync(assetsSourceDir)) {
    // Create target dir if necessary
    sfs.createDir(assetsTargetDir)

    // Copy all assets from source to target
    fs.readdirSync(assetsSourceDir).forEach(function (name) {
      let source = path.join(assetsSourceDir, name)
      let target = path.join(assetsTargetDir, name)
      fs.writeFileSync(target, fs.readFileSync(source))
    })
  }

  // Create an archive for images.
  if (images) {
    if (images.screenshots) {
      zip('images.zip', images.screenshots, assetsSourceDir, assetsTargetDir)
    }
    if (images.logos) {
      zip('logo.zip', images.logos, assetsSourceDir, assetsTargetDir)
    }
  }

  // Output relative path from build/
  return path.relative(buildDir, htmlDestination)
}

// Get the folder containing the images.
function getImagesFolder (dataFile) {
  const stat = fs.statSync(dataFile)
  const dataFileFolder = stat.isFile() ? path.dirname(dataFile) : dataFile

  return path.join(dataFileFolder, imagesFolderName)
}

// Get the images in the source, and sort them by types.
// We are interested in three types of images:
// - the header, starting with 'header'.
// - the logos, starting with 'logo'.
// - And the rest (what we call "screenshots").
function getImages (source) {
  if (!fs.existsSync(source)) {
    console.error(`No images found for "${source}"`, '🤔')
    return
  }

  const images = {header: null, screenshots: [], logos: []}

  fs.readdirSync(source)
    .forEach(f => {
      const ext = path.extname(f)

      // Authorize only these formats.
      if (!authorizedImageFormats.includes(ext)) return

      // And put in the correct category.
      if (f.toLowerCase().startsWith('header')) {
        images.header = f
      } else if (f.toLowerCase().startsWith('logo')) {
        images.logos.push(f)
      } else {
        images.screenshots.push(f)
      }
    })

  return images
}

function createAndGetBuildFolder () {
  const destination = path.join(config.commands.build.output || process.cwd(), 'build')
  sfs.createDir(destination)

  return destination
}

// -------------------------------------------------------------
// Exports.
// -------------------------------------------------------------

module.exports = {
  build,
  createAndGetBuildFolder
}
<commit_msg>Rename variables<commit_after>'use strict'

const fs = require('fs')
const path = require('path')
const chalk = require('chalk')

const console = require('../helpers/color-console')
const sfs = require('../helpers/sfs')
const zip = require('../helpers/zip')

const {createTemplate} = require('./template')

const config = require('../config')
const {imagesFolderName, authorizedImageFormats} = require('../assets')

// -------------------------------------------------------------
// Module.
// -------------------------------------------------------------

function build (dataFile, presskit, {
  company = {},
  products = [],
  analytics = ''
} = {}) {
  const template = createTemplate(presskit.type)
  const assetsSource = getImagesFolder(dataFile)
  const images = getImages(assetsSource)

  // Apply data to template.
  let html = template({
    presskit: presskit,
    company,
    products,
    images: images,
    assets: (presskit.type !== 'company' ? '..' : '.'),
    analytics,

    // Handlebars can't check for equality, so we provide two
    // variables to differentiate a product and a company sheet.
    isCompany: presskit.type === 'company',
    isProduct: presskit.type === 'product'
  })

  const buildDir = createAndGetBuildFolder()
  let targetDir = buildDir

  if (presskit.type !== 'company') {
    // Company should be placed in the root folder.
    // but each product is a subfolder, named as the source's folder name.
    targetDir = path.join(buildDir, path.basename(path.dirname(dataFile)))
    sfs.createDir(targetDir)
  }

  // Prepare output filename.
  let htmlFilename = 'index.html'
  let htmlDestination = path.join(targetDir, htmlFilename)

  console.log(`- "${presskit.title}" -> ${chalk.blue(htmlDestination)}`)

  // Export the HTML to a file.
  fs.writeFileSync(htmlDestination, html)

  // Copy all assets from `images/` to `build/images/`.
  let assetsTarget = path.join(targetDir, imagesFolderName)
  if (fs.existsSync(assetsSource)) {
    // Create target dir if necessary.
    sfs.createDir(assetsTarget)

    // Copy all assets from source to target.
    fs.readdirSync(assetsSource).forEach(function (name) {
      let source = path.join(assetsSource, name)
      let target = path.join(assetsTarget, name)
      fs.writeFileSync(target, fs.readFileSync(source))
    })
  }

  // Create an archive for images.
  if (images) {
    if (images.screenshots) {
      zip('images.zip', images.screenshots, assetsSource, assetsTarget)
    }
    if (images.logos) {
      zip('logo.zip', images.logos, assetsSource, assetsTarget)
    }
  }

  // Output relative path from `build/`.
  return path.relative(buildDir, htmlDestination)
}

// Get the folder containing the images.
function getImagesFolder (dataFile) {
  const stat = fs.statSync(dataFile)
  const dataFileFolder = stat.isFile() ? path.dirname(dataFile) : dataFile

  return path.join(dataFileFolder, imagesFolderName)
}

// Get the images in the source, and sort them by types.
// We are interested in three types of images:
// - the header, starting with 'header'.
// - the logos, starting with 'logo'.
// - And the rest (what we call "screenshots").
function getImages (source) {
  if (!fs.existsSync(source)) {
    console.error(`No images found for "${source}"`, '🤔')
    return
  }

  const images = {header: null, screenshots: [], logos: []}

  fs.readdirSync(source)
    .forEach(f => {
      const ext = path.extname(f)

      // Authorize only these formats.
      if (!authorizedImageFormats.includes(ext)) return

      // And put in the correct category.
      if (f.toLowerCase().startsWith('header')) {
        images.header = f
      } else if (f.toLowerCase().startsWith('logo')) {
        images.logos.push(f)
      } else {
        images.screenshots.push(f)
      }
    })

  return images
}

function createAndGetBuildFolder () {
  const destination = path.join(config.commands.build.output || process.cwd(), 'build')
  sfs.createDir(destination)

  return destination
}

// -------------------------------------------------------------
// Exports.
// -------------------------------------------------------------

module.exports = {
  build,
  createAndGetBuildFolder
}
<|endoftext|>


<commit_before>var path = require('path'),
	_ = require('underscore'),
	debug = require('debug')('keystone:core:options'),
	cloudinary = require('cloudinary'),
	mandrillapi = require('mandrill-api'),
	utils = require('keystone-utils');

function options(moduleRoot) {

	var exports = {};

	/**
	 * This file contains methods specific to dealing with Keystone's options.
	 * All exports are added to the Keystone.prototype
	 */

	// Deprecated options that have been mapped to new keys
	var remappedOptions = {
		'signin success': 'signin redirect',
		'signout': 'signout url'
	};

	/**
	 * Sets keystone options
	 *
	 * ####Example:
	 *
	 *     keystone.set('user model', 'User') // sets the 'user model' option to `User`
	 *
	 * @param {String} key
	 * @param {String} value
	 * @api public
	 */
	exports.set = function(key, value) {

		if (arguments.length === 1) {
			return this._options[key];
		}

		if (remappedOptions[key]) {
			if (this.get('logger')) {
				console.log('\nWarning: the `' + key + '` option has been deprecated. Please use `' + remappedOptions[key] + '` instead.\n\n' +
					'Support for `' + key + '` will be removed in a future version.');
			}
			key = remappedOptions[key];
		}

		// handle special settings
		switch (key) {
			case 'cloudinary config':
				if (_.isObject(value)) {
					cloudinary.config(value);
				}
				value = cloudinary.config();
			break;
			case 'mandrill api key':
				if (value) {
					debug('found mandril key');
					this.mandrillAPI = new mandrillapi.Mandrill(value);
				}
			break;
			case 'auth':
				if (value === true && !this.get('session')) {
					debug('setting session for auth');
					this.set('session', true);
				}
			break;
			case 'nav':
				debug('setting nav');
				this.nav = this.initNav(value);
			break;
			case 'mongo':
				if ('string' !== typeof value) {
					if (Array.isArray(value) && (value.length === 2 || value.length === 3)) {
						console.log('\nWarning: using an array for the `mongo` option has been deprecated.\nPlease use a mongodb connection string, e.g. mongodb://localhost/db_name instead.\n\n' +
							'Support for arrays as the `mongo` setting will be removed in a future version.');
						value = (value.length === 2) ? 'mongodb://' + value[0] + '/' + value[1] : 'mongodb://' + value[0] + ':' + value[2] + '/' + value[1];
					} else {
						console.error('\nInvalid Configuration:\nThe `mongo` option must be a mongodb connection string, e.g. mongodb://localhost/db_name\n');
						process.exit(1);
					}
				}
			break;
		}

		this._options[key] = value;
		return this;
	};

	/**
	 * Sets multiple keystone options.
	 *
	 * ####Example:
	 *
	 *     keystone.set({test: value}) // sets the 'test' option to `value`
	 *
	 * @param {Object} options
	 * @api public
	 */

	exports.options = function(options) {
		if (!arguments.length)
			return this._options;
		if (utils.isObject(options)) {
			debug('settings options');
			var keys = Object.keys(options),
				i = keys.length,
				k;
			while (i--) {
				k = keys[i];
				this.set(k, options[k]);
			}
		}
		return this._options;
	};

	/**
	 * Gets keystone options
	 *
	 * ####Example:
	 *
	 *     keystone.get('test') // returns the 'test' value
	 *
	 * @param {String} key
	 * @api public
	 */

	exports.get = exports.set;

	/**
	 * Gets an expanded path option, expanded to include moduleRoot if it is relative
	 *
	 * ####Example:
	 *
	 *     keystone.get('pathOption', 'defaultValue')
	 *
	 * @param {String} key
	 * @param {String} defaultValue
	 * @api public
	 */

	exports.getPath = function(key, defaultValue) {
		return this.expandPath(this.get(key) || defaultValue);
	};

	/**
	 * Expands a path to include moduleRoot if it is relative
	 *
	 * @param {String} pathValue
	 * @api public
	 */

	exports.expandPath = function(pathValue) {
		pathValue = ('string' === typeof pathValue && pathValue.substr(0,1) !== path.sep && pathValue.substr(1,2) !== ':\\')
			? path.join(moduleRoot, pathValue)
			: pathValue;
		return pathValue;
	};

	return exports;

}

module.exports = options;
<commit_msg>Allow cloudinary config option to be a string - closes #890<commit_after>var path = require('path'),
	url = require('url'),
	_ = require('underscore'),
	debug = require('debug')('keystone:core:options'),
	cloudinary = require('cloudinary'),
	mandrillapi = require('mandrill-api'),
	utils = require('keystone-utils');

function options(moduleRoot) {

	var exports = {};

	/**
	 * This file contains methods specific to dealing with Keystone's options.
	 * All exports are added to the Keystone.prototype
	 */

	// Deprecated options that have been mapped to new keys
	var remappedOptions = {
		'signin success': 'signin redirect',
		'signout': 'signout url'
	};

	/**
	 * Sets keystone options
	 *
	 * ####Example:
	 *
	 *     keystone.set('user model', 'User') // sets the 'user model' option to `User`
	 *
	 * @param {String} key
	 * @param {String} value
	 * @api public
	 */
	exports.set = function(key, value) {

		if (arguments.length === 1) {
			return this._options[key];
		}

		if (remappedOptions[key]) {
			if (this.get('logger')) {
				console.log('\nWarning: the `' + key + '` option has been deprecated. Please use `' + remappedOptions[key] + '` instead.\n\n' +
					'Support for `' + key + '` will be removed in a future version.');
			}
			key = remappedOptions[key];
		}

		// handle special settings
		switch (key) {
			case 'cloudinary config':
				if (_.isString(value)) {
			        var parts = url.parse(value, true);
			        var auth = parts.auth ? parts.auth.split(":") : [];
			        value = {
			          cloud_name: parts.host,
			          api_key: auth[0],
			          api_secret: auth[1],
			          private_cdn: parts.pathname != null,
			          secure_distribution: parts.pathname && parts.pathname.substring(1)
			        };
				}
				if (_.isObject(value)) {
					cloudinary.config(value);
				}
				value = cloudinary.config();
			break;
			case 'mandrill api key':
				if (value) {
					debug('found mandril key');
					this.mandrillAPI = new mandrillapi.Mandrill(value);
				}
			break;
			case 'auth':
				if (value === true && !this.get('session')) {
					debug('setting session for auth');
					this.set('session', true);
				}
			break;
			case 'nav':
				debug('setting nav');
				this.nav = this.initNav(value);
			break;
			case 'mongo':
				if ('string' !== typeof value) {
					if (Array.isArray(value) && (value.length === 2 || value.length === 3)) {
						console.log('\nWarning: using an array for the `mongo` option has been deprecated.\nPlease use a mongodb connection string, e.g. mongodb://localhost/db_name instead.\n\n' +
							'Support for arrays as the `mongo` setting will be removed in a future version.');
						value = (value.length === 2) ? 'mongodb://' + value[0] + '/' + value[1] : 'mongodb://' + value[0] + ':' + value[2] + '/' + value[1];
					} else {
						console.error('\nInvalid Configuration:\nThe `mongo` option must be a mongodb connection string, e.g. mongodb://localhost/db_name\n');
						process.exit(1);
					}
				}
			break;
		}

		this._options[key] = value;
		return this;
	};

	/**
	 * Sets multiple keystone options.
	 *
	 * ####Example:
	 *
	 *     keystone.set({test: value}) // sets the 'test' option to `value`
	 *
	 * @param {Object} options
	 * @api public
	 */

	exports.options = function(options) {
		if (!arguments.length)
			return this._options;
		if (utils.isObject(options)) {
			debug('settings options');
			var keys = Object.keys(options),
				i = keys.length,
				k;
			while (i--) {
				k = keys[i];
				this.set(k, options[k]);
			}
		}
		return this._options;
	};

	/**
	 * Gets keystone options
	 *
	 * ####Example:
	 *
	 *     keystone.get('test') // returns the 'test' value
	 *
	 * @param {String} key
	 * @api public
	 */

	exports.get = exports.set;

	/**
	 * Gets an expanded path option, expanded to include moduleRoot if it is relative
	 *
	 * ####Example:
	 *
	 *     keystone.get('pathOption', 'defaultValue')
	 *
	 * @param {String} key
	 * @param {String} defaultValue
	 * @api public
	 */

	exports.getPath = function(key, defaultValue) {
		return this.expandPath(this.get(key) || defaultValue);
	};

	/**
	 * Expands a path to include moduleRoot if it is relative
	 *
	 * @param {String} pathValue
	 * @api public
	 */

	exports.expandPath = function(pathValue) {
		pathValue = ('string' === typeof pathValue && pathValue.substr(0,1) !== path.sep && pathValue.substr(1,2) !== ':\\')
			? path.join(moduleRoot, pathValue)
			: pathValue;
		return pathValue;
	};

	return exports;

}

module.exports = options;
<|endoftext|>


<commit_before>/* Testing if I can make a quick set of dummy tests to explore the possibility o fadding test profiles.  This is copied and pasted from the non_templating file. */

(function (module, fs, extend, moment, request, requestPromise, chai, liburl, Joi, helper, multipartParser, redirect) {
    // "use strict";

    var expect = chai.expect;

    if(global.OAUTH)
        request = helper.OAuthRequest(request);

describe('New requirements for specification version 1.0.3', function() {

    describe('Stored Statements property is a “Timestamp (Formatted according to ISO 8601) of when this Statement was recorded. Set by LRS.” (4.1 Statement Properties)', function () {
        it('Message goes here', function (done) {

            var templates = [
                {statement: '{{statements.default}}'}
            ];
            var data = createFromTemplate(templates).statement;
            data.id = helper.generateUUID();

            request(helper.getEndpointAndAuth())
            .post(helper.getEndpointStatements())
            .headers(helper.addAllHeaders())
            .json(data)
            .expect(200, done);
            // done();
        });
    });

    describe('Statements returned by an LRS MUST retain the version they are accepted with. (4.1.10)', function () {
        // done();
    });

    describe('If it (LRS) accepts the attachment, it can match the raw data of an attachment with the attachment header in a Statement by comparing the SHA-2 of the raw data to the SHA-2 declared in the header. It (LRS) MUST not do so any other way. (4.4.11)', function () {
        // done();
    });

    describe('When handling Statement Signature, LRS MUST do the following (4.4)', function () {

        it('Reject requests to store Statements that contain malformed signatures, with HTTP 400.', function (done) {
            done();
        });

        it('Decode the JWS signature, and load the signed serialization of the Statement from the JWS signature payload.', function (done) {
            done();
        });

        it('Validate that the "original" Statement is logically equivalent to the received Statement.', function (done) {
            // When making this equivalence check, differences which could have been caused by allowed or required LRS processing of "id", "authority", "stored", "timestamp", or "version" MUST be ignored.
            done();
        });

        it('If the JWS header includes an X.509 certificate, validate the signature against that certificate as defined in JWS.', function (done) {
            done();
        });
    });

    describe('An LRS must support HTTP/1.1 entity tags (ETags) to implement optimistic concurrency control when handling APIs where PUT may overwrite existing data (State, Agent Profile, and Activity Profile). (6.3)', function () {

        it('When responding to a GET request, include an ETag HTTP header in the response', function (done) {
            done();
        });

        it('When returning an ETag header, the value should be calculated as a SHA1 hexadecimal value', function (done) {
            done();
        });

        it('When responding to a GET Request the Etag header must be enclosed in quotes', function (done) {
            done();
        });

        it('When responding to a PUT request, must handle the If-Match header as described in RFC 2616, HTTP/1.1 if it contains an ETag', function (done) {
            done();
        });

        it('When responding to a PUT request, handle the If-None-Match header as described in RFC 2616, HTTP/1.1 if it contains “*”', function (done) {
            done();
        });

        describe('If Header precondition in PUT Requests for RFC2616 fail', function () {

            it('Return HTTP 412 (Precondition faileD)', function (done) {
                done();
            });

            it('Do not modify the resource', function (done) {
                done();
            });
        });

        describe('If put request is received without either header for a resource that already exists', function () {

            it('Return 409 conflict', function (done) {
                done();
            });

            it('Return plaintext body explaining the situation', function (done) {
                done();
            });

            it('Do not modify the resource', function (done) {
                done();
            });
        });

    });

    describe('The LRS MUST support authentication using at least one of the following methods: (6.4)', function () {

        it('OAuth 1.0 (RFC 5849), with signature methods of "HMAC-SHA1", "RSA-SHA1", and "PLAINTEXT"', function (done) {
            done();
        });

        it('HTTP Basic Authentication', function (done) {
            done();
        });

        it('Common Access Cards (implementation details to follow in a later version)', function (done) {
            done();
        });
    });

});

    // describe('An LRS populates the "authority" property if it is not provided in the Statement, based on header information with the Agent corresponding to the user (contained within the header) (Implicit, 4.1.9.b, 4.1.9.c)', function () {
    //     it('should populate authority', function (done) {
    //         var templates = [
    //             {statement: '{{statements.default}}'}
    //         ];
    //         var data = createFromTemplate(templates);
    //         data = data.statement;
    //         data.id = helper.generateUUID();
    //
    //         request(helper.getEndpoint())
    //             .post(helper.getEndpointStatements())
    //             .headers(helper.addAllHeaders({}))
    //             .json(data)
    //             .expect(200)
    //             .end()
    //             .get(helper.getEndpointStatements() + '?statementId=' + data.id)
    //             .headers(helper.addAllHeaders({}))
    //             .expect(200).end(function (err, res) {
    //                 if (err) {
    //                     done(err);
    //                 } else {
    //                     var statement = parse(res.body, done);
    //                     expect(statement).to.have.property('authority');
    //                     done();
    //                 }
    //             });
    //     });
    // });

    // describe('A Voiding Statement cannot Target another Voiding Statement (4.3)', function () {
    //     var voidedId;
    //
    //     before('persist voided statement', function (done) {
    //         var templates = [
    //             {statement: '{{statements.default}}'}
    //         ];
    //         var data = createFromTemplate(templates);
    //         data = data.statement;
    //         request(helper.getEndpoint())
    //             .post(helper.getEndpointStatements())
    //             .headers(helper.addAllHeaders({}))
    //             .json(data).expect(200).end(function (err, res) {
    //                 if (err) {
    //                     done(err);
    //                 } else {
    //                     voidedId = res.body[0];
    //                     done();
    //                 }
    //             });
    //     });
    //
    //     before('persist voiding statement', function (done) {
    //         var templates = [
    //             {statement: '{{statements.object_statementref}}'},
    //             {verb: '{{verbs.voided}}'}
    //         ];
    //         var data = createFromTemplate(templates);
    //         data = data.statement;
    //         data.object.id = voidedId;
    //         request(helper.getEndpoint())
    //             .post(helper.getEndpointStatements())
    //             .headers(helper.addAllHeaders({}))
    //             .json(data).expect(200).end(function (err, res) {
    //                 if (err) {
    //                     done(err);
    //                 } else {
    //                     done();
    //                 }
    //             });
    //     });
    //
    //     it('should fail when "StatementRef" points to a voiding statement', function (done) {
    //         var templates = [
    //             {statement: '{{statements.object_statementref}}'},
    //             {verb: '{{verbs.voided}}'}
    //         ];
    //         var data = createFromTemplate(templates);
    //         data = data.statement;
    //         data.object.id = voidedId;
    //         request(helper.getEndpoint())
    //             .post(helper.getEndpointStatements())
    //             .headers(helper.addAllHeaders({}))
    //             .json(data).expect(400).end(function (err, res) {
    //                 if (err) {
    //                     done(err);
    //                 } else {
    //                     done();
    //                 }
    //             });
    //     });
    // });

    // describe('Welcome to Option D.  An LRS returns a ContextActivity in an array, even if only a single ContextActivity is returned (4.1.6.2.c, 4.1.6.2.d)', function () {
    //     var types = ['parent', 'grouping', 'category', 'other'];

        // types.forEach(function (type) {
        //     it('should return array for statement context "' + type + '"  when single ContextActivity is passed', function (done) {
        //         var templates = [
        //             {statement: '{{statements.context}}'},
        //             {context: '{{contexts.' + type + '}}'}
        //         ];
        //         var data = createFromTemplate(templates);
        //         data = data.statement;
        //         data.id = helper.generateUUID();
        //
        //         request(helper.getEndpoint())
        //             .post(helper.getEndpointStatements())
        //             .headers(helper.addAllHeaders({}))
        //             .json(data)
        //             .expect(200)
        //             .end()
        //             .get(helper.getEndpointStatements() + '?statementId=' + data.id)
        //             .headers(helper.addAllHeaders({}))
        //             .expect(200)
        //             .end(function (err, res) {
        //                 if (err) {
        //                     done(err);
        //                 } else {
        //                     var statement = parse(res.body, done);
        //                     expect(statement).to.have.property('context').to.have.property('contextActivities');
        //                     expect(statement.context.contextActivities).to.have.property(type);
        //                     expect(statement.context.contextActivities[type]).to.be.an('array');
        //                     done();
        //                 }
        //             });
        //     });
        // });

    //     types.forEach(function (type) {
    //         it('should return array for statement substatement context "' + type + '"  when single ContextActivity is passed', function (done) {
    //             var templates = [
    //                 {statement: '{{statements.object_substatement}}'},
    //                 {object: '{{substatements.context}}'},
    //                 {context: '{{contexts.' + type + '}}'}
    //             ];
    //             var data = createFromTemplate(templates);
    //             data = data.statement;
    //             data.id = helper.generateUUID();
    //
    //             request(helper.getEndpoint())
    //                 .post(helper.getEndpointStatements())
    //                 .headers(helper.addAllHeaders({}))
    //                 .json(data)
    //                 .expect(200)
    //                 .end()
    //                 .get(helper.getEndpointStatements() + '?statementId=' + data.id)
    //                 .headers(helper.addAllHeaders({}))
    //                 .expect(200)
    //                 .end(function (err, res) {
    //                     if (err) {
    //                         done(err);
    //                     } else {
    //                         var statement = parse(res.body, done);
    //                         expect(statement).to.have.property('object').to.have.property('context').to.have.property('contextActivities');
    //                         expect(statement.object.context.contextActivities).to.have.property(type);
    //                         expect(statement.object.context.contextActivities[type]).to.be.an('array');
    //                         done();
    //                     }
    //                 });
    //         });
    //     });
    // });
    //
    // describe('Will these three tests now show up??', function () {
    //
    //     it('An LRS\'s Statement API, upon processing a successful GET request, will return a single "statements" property (Multiplicity, Format, 4.2.table1.row1.c)', function (done) {
    //         // JSON parser validates this
    //         done();
    //     });
    //
    //     it('A "more" property\'s referenced container object follows the same rules as the original GET request, originating with a single "statements" property and a single "more" property (4.2.table1.row1.b)', function (done) {
    //         // JSON parser validates this
    //         done();
    //     });
    //
    //     it('An LRS\'s Statement API rejects with Error Code 400 Bad Request any DELETE request (7.2)', function (done) {
    //         // Using requirement: An LRS rejects with error code 405 Method Not Allowed to any request to an API which uses a method not in this specification **Implicit ONLY in that HTML normally does this behavior**
    //         done();
    //     });
    // });

    function createFromTemplate(templates) {
        // convert template mapping to JSON objects
        var converted = helper.convertTemplate(templates);
        // this handles if no override
        var mockObject = helper.createTestObject(converted);
        return mockObject;
    }

    function parse(string, done) {
        var parsed;
        try {
            parsed = JSON.parse(string);
        } catch (error) {
            done(error);
        }
        return parsed;
    }

}(module, require('fs'), require('extend'), require('moment'), require('super-request'), require('supertest-as-promised'), require('chai'), require('url'), require('joi'), require('./../helper'), require('./../multipartParser'), require('./../redirect.js')));
<commit_msg>Stored property is a Timestamp<commit_after>/* Testing if I can make a quick set of dummy tests to explore the possibility o fadding test profiles.  This is copied and pasted from the non_templating file. */

(function (module, fs, extend, moment, request, requestPromise, chai, liburl, Joi, helper, multipartParser, redirect) {
    // "use strict";

    var expect = chai.expect;

    if(global.OAUTH)
        request = helper.OAuthRequest(request);

describe('New requirements for specification version 1.0.3', function() {

    describe('Stored Statements property is a “Timestamp (Formatted according to ISO 8601) of when this Statement was recorded. Set by LRS.” (4.1 Statement Properties)', function () {
        it('Message goes here', function (done) {

            function testTime (ctr) {
                console.log('Attempt #', ctr);
                var templates = [
                    {statement: '{{statements.default}}'}
                ];
                var data = createFromTemplate(templates).statement;
                data.id = helper.generateUUID();
                var query = '?statementId=' + data.id;
                var stmtTime = Date.now();

                request(helper.getEndpointAndAuth())
                .post(helper.getEndpointStatements())
                .headers(helper.addAllHeaders())
                .json(data)
                .expect(200)
                .end()
                .get(helper.getEndpointStatements() + query)
                // .wait(stmtTime, query, data.id);
                .headers(helper.addAllHeaders())
                .expect(200)
                .end(function (err, res) {
                    if (err) {
                        done(err);
                    } else {
                        console.log('This is the first thing that should be printed in the results section');
                        stmt = parse(res.body);
                        console.log('We have parsed the body of the res');
                        expect(stmt).to.have.property('stored');
                        console.log('There is a stored property');
                        var stored = moment(stmt.stored, moment.ISO_8601, true);
                        console.log('This is after the moment strict iso thing');
                        expect(stored.isValid()).to.be.true;
                        console.log('Stored property is', Object.keys(stored), stored._i);
                        stored._pf.parsedDateParts[6] = 0;
                        console.log("Ciao", stored._pf, stored._pf.parsedDateParts[6]);
                        //The following will send and recieve multiple times if necessary to determine that an LRS preserves a timestamp to at least milliseconds
                        if (stored._pf.parsedDateParts[6] === 0) {
                            if (ctr < 5) {
                                testTime(++ctr);
                            } else {
                                throw new Error("LRS did not preseve milliseconds");
                                done(err);
                            }
                        } else {
                            done();
                        }
                    }
                });
            } testTime(1);
        });
    });

    describe('Statements returned by an LRS MUST retain the version they are accepted with. (4.1.10)', function () {
        // done();
    });

    describe('If it (LRS) accepts the attachment, it can match the raw data of an attachment with the attachment header in a Statement by comparing the SHA-2 of the raw data to the SHA-2 declared in the header. It (LRS) MUST not do so any other way. (4.4.11)', function () {
        // done();
    });

    describe('When handling Statement Signature, LRS MUST do the following (4.4)', function () {

        it('Reject requests to store Statements that contain malformed signatures, with HTTP 400.', function (done) {
            done();
        });

        it('Decode the JWS signature, and load the signed serialization of the Statement from the JWS signature payload.', function (done) {
            done();
        });

        it('Validate that the "original" Statement is logically equivalent to the received Statement.', function (done) {
            // When making this equivalence check, differences which could have been caused by allowed or required LRS processing of "id", "authority", "stored", "timestamp", or "version" MUST be ignored.
            done();
        });

        it('If the JWS header includes an X.509 certificate, validate the signature against that certificate as defined in JWS.', function (done) {
            done();
        });
    });

    describe('An LRS must support HTTP/1.1 entity tags (ETags) to implement optimistic concurrency control when handling APIs where PUT may overwrite existing data (State, Agent Profile, and Activity Profile). (6.3)', function () {

        it('When responding to a GET request, include an ETag HTTP header in the response', function (done) {
            done();
        });

        it('When returning an ETag header, the value should be calculated as a SHA1 hexadecimal value', function (done) {
            done();
        });

        it('When responding to a GET Request the Etag header must be enclosed in quotes', function (done) {
            done();
        });

        it('When responding to a PUT request, must handle the If-Match header as described in RFC 2616, HTTP/1.1 if it contains an ETag', function (done) {
            done();
        });

        it('When responding to a PUT request, handle the If-None-Match header as described in RFC 2616, HTTP/1.1 if it contains “*”', function (done) {
            done();
        });

        describe('If Header precondition in PUT Requests for RFC2616 fail', function () {

            it('Return HTTP 412 (Precondition Failed)', function (done) {
                done();
            });

            it('Do not modify the resource', function (done) {
                done();
            });
        });

        describe('If put request is received without either header for a resource that already exists', function () {

            it('Return 409 conflict', function (done) {
                done();
            });

            it('Return plaintext body explaining the situation', function (done) {
                done();
            });

            it('Do not modify the resource', function (done) {
                done();
            });
        });

    });

    describe('The LRS MUST support authentication using at least one of the following methods: (6.4)', function () {

        it('OAuth 1.0 (RFC 5849), with signature methods of "HMAC-SHA1", "RSA-SHA1", and "PLAINTEXT"', function (done) {
            done();
        });

        it('HTTP Basic Authentication', function (done) {
            done();
        });

        it('Common Access Cards (implementation details to follow in a later version)', function (done) {
            done();
        });
    });

});

    // describe('An LRS populates the "authority" property if it is not provided in the Statement, based on header information with the Agent corresponding to the user (contained within the header) (Implicit, 4.1.9.b, 4.1.9.c)', function () {
    //     it('should populate authority', function (done) {
    //         var templates = [
    //             {statement: '{{statements.default}}'}
    //         ];
    //         var data = createFromTemplate(templates);
    //         data = data.statement;
    //         data.id = helper.generateUUID();
    //
    //         request(helper.getEndpoint())
    //             .post(helper.getEndpointStatements())
    //             .headers(helper.addAllHeaders({}))
    //             .json(data)
    //             .expect(200)
    //             .end()
    //             .get(helper.getEndpointStatements() + '?statementId=' + data.id)
    //             .headers(helper.addAllHeaders({}))
    //             .expect(200).end(function (err, res) {
    //                 if (err) {
    //                     done(err);
    //                 } else {
    //                     var statement = parse(res.body, done);
    //                     expect(statement).to.have.property('authority');
    //                     done();
    //                 }
    //             });
    //     });
    // });

    // describe('A Voiding Statement cannot Target another Voiding Statement (4.3)', function () {
    //     var voidedId;
    //
    //     before('persist voided statement', function (done) {
    //         var templates = [
    //             {statement: '{{statements.default}}'}
    //         ];
    //         var data = createFromTemplate(templates);
    //         data = data.statement;
    //         request(helper.getEndpoint())
    //             .post(helper.getEndpointStatements())
    //             .headers(helper.addAllHeaders({}))
    //             .json(data).expect(200).end(function (err, res) {
    //                 if (err) {
    //                     done(err);
    //                 } else {
    //                     voidedId = res.body[0];
    //                     done();
    //                 }
    //             });
    //     });
    //
    //     before('persist voiding statement', function (done) {
    //         var templates = [
    //             {statement: '{{statements.object_statementref}}'},
    //             {verb: '{{verbs.voided}}'}
    //         ];
    //         var data = createFromTemplate(templates);
    //         data = data.statement;
    //         data.object.id = voidedId;
    //         request(helper.getEndpoint())
    //             .post(helper.getEndpointStatements())
    //             .headers(helper.addAllHeaders({}))
    //             .json(data).expect(200).end(function (err, res) {
    //                 if (err) {
    //                     done(err);
    //                 } else {
    //                     done();
    //                 }
    //             });
    //     });
    //
    //     it('should fail when "StatementRef" points to a voiding statement', function (done) {
    //         var templates = [
    //             {statement: '{{statements.object_statementref}}'},
    //             {verb: '{{verbs.voided}}'}
    //         ];
    //         var data = createFromTemplate(templates);
    //         data = data.statement;
    //         data.object.id = voidedId;
    //         request(helper.getEndpoint())
    //             .post(helper.getEndpointStatements())
    //             .headers(helper.addAllHeaders({}))
    //             .json(data).expect(400).end(function (err, res) {
    //                 if (err) {
    //                     done(err);
    //                 } else {
    //                     done();
    //                 }
    //             });
    //     });
    // });

    // describe('Welcome to Option D.  An LRS returns a ContextActivity in an array, even if only a single ContextActivity is returned (4.1.6.2.c, 4.1.6.2.d)', function () {
    //     var types = ['parent', 'grouping', 'category', 'other'];

        // types.forEach(function (type) {
        //     it('should return array for statement context "' + type + '"  when single ContextActivity is passed', function (done) {
        //         var templates = [
        //             {statement: '{{statements.context}}'},
        //             {context: '{{contexts.' + type + '}}'}
        //         ];
        //         var data = createFromTemplate(templates);
        //         data = data.statement;
        //         data.id = helper.generateUUID();
        //
        //         request(helper.getEndpoint())
        //             .post(helper.getEndpointStatements())
        //             .headers(helper.addAllHeaders({}))
        //             .json(data)
        //             .expect(200)
        //             .end()
        //             .get(helper.getEndpointStatements() + '?statementId=' + data.id)
        //             .headers(helper.addAllHeaders({}))
        //             .expect(200)
        //             .end(function (err, res) {
        //                 if (err) {
        //                     done(err);
        //                 } else {
        //                     var statement = parse(res.body, done);
        //                     expect(statement).to.have.property('context').to.have.property('contextActivities');
        //                     expect(statement.context.contextActivities).to.have.property(type);
        //                     expect(statement.context.contextActivities[type]).to.be.an('array');
        //                     done();
        //                 }
        //             });
        //     });
        // });

    //     types.forEach(function (type) {
    //         it('should return array for statement substatement context "' + type + '"  when single ContextActivity is passed', function (done) {
    //             var templates = [
    //                 {statement: '{{statements.object_substatement}}'},
    //                 {object: '{{substatements.context}}'},
    //                 {context: '{{contexts.' + type + '}}'}
    //             ];
    //             var data = createFromTemplate(templates);
    //             data = data.statement;
    //             data.id = helper.generateUUID();
    //
    //             request(helper.getEndpoint())
    //                 .post(helper.getEndpointStatements())
    //                 .headers(helper.addAllHeaders({}))
    //                 .json(data)
    //                 .expect(200)
    //                 .end()
    //                 .get(helper.getEndpointStatements() + '?statementId=' + data.id)
    //                 .headers(helper.addAllHeaders({}))
    //                 .expect(200)
    //                 .end(function (err, res) {
    //                     if (err) {
    //                         done(err);
    //                     } else {
    //                         var statement = parse(res.body, done);
    //                         expect(statement).to.have.property('object').to.have.property('context').to.have.property('contextActivities');
    //                         expect(statement.object.context.contextActivities).to.have.property(type);
    //                         expect(statement.object.context.contextActivities[type]).to.be.an('array');
    //                         done();
    //                     }
    //                 });
    //         });
    //     });
    // });
    //
    // describe('Will these three tests now show up??', function () {
    //
    //     it('An LRS\'s Statement API, upon processing a successful GET request, will return a single "statements" property (Multiplicity, Format, 4.2.table1.row1.c)', function (done) {
    //         // JSON parser validates this
    //         done();
    //     });
    //
    //     it('A "more" property\'s referenced container object follows the same rules as the original GET request, originating with a single "statements" property and a single "more" property (4.2.table1.row1.b)', function (done) {
    //         // JSON parser validates this
    //         done();
    //     });
    //
    //     it('An LRS\'s Statement API rejects with Error Code 400 Bad Request any DELETE request (7.2)', function (done) {
    //         // Using requirement: An LRS rejects with error code 405 Method Not Allowed to any request to an API which uses a method not in this specification **Implicit ONLY in that HTML normally does this behavior**
    //         done();
    //     });
    // });

    function createFromTemplate(templates) {
        // convert template mapping to JSON objects
        var converted = helper.convertTemplate(templates);
        // this handles if no override
        var mockObject = helper.createTestObject(converted);
        return mockObject;
    }

    function parse(string, done) {
        var parsed;
        try {
            parsed = JSON.parse(string);
        } catch (error) {
            done(error);
        }
        return parsed;
    }

}(module, require('fs'), require('extend'), require('moment'), require('super-request'), require('supertest-as-promised'), require('chai'), require('url'), require('joi'), require('./../helper'), require('./../multipartParser'), require('./../redirect.js')));
<|endoftext|>


<commit_before>const pp        = require('./ppublish');
const pt        = require('./ptalk');
const utils     = require('../common/utils');
const fs        = require('fs');
const commander = require('commander');
const path      = require('path');

commander
    .option('-m --module <file>', 'specify a pjs file')
    .option('-s --server <String>', 'specify the server address')
    .parse(process.argv);

if (commander.module && commander.server) {
    console.log(commander.module, commander.server)
    fs.readFile(commander.module, function (err, data) {
        if (err) throw err;

        utils.rndPort().then((port) => {
            var addr = "tcp://127.0.0.1:" + port;
            data = JSON.parse(data);
            data.port = addr;

            pp.announce(data, commander.server);

            const dirname = path.dirname(commander.module);

            const imported = require(path.resolve(path.join(dirname, data.name)));

            pt(addr, function (name, params) {
                return imported[name](params);
            });

        }).catch((err) => {
            console.log(err)
        });
    });
}<commit_msg>Add automatic pjs module search<commit_after>const pp        = require('./ppublish');
const pt        = require('./ptalk');
const utils     = require('../common/utils');
const fs        = require('fs');
const commander = require('commander');
const path      = require('path');
const { exec }  = require('child_process');

commander
    .option('-m --module <file>', 'specify a pjs file')
    .option('-s --server <String>', 'specify the server address')
    .parse(process.argv);

function findFiles(folder, extension, cb){
    folder = path.resolve(folder);

    var command = "";

    if(/^win/.test(process.platform)){
        command = `dir /B ${folder}\\*."${extension}`;
    } else{
        command = `ls -1 ${folder}/*.${extension}`;
    }

    exec(command, (err, stdout, stderr) => {
        if(err) return cb(err, null);
        //get rid of \r from windows
        stdout = stdout.replace(/\r/g,"");
        var files = stdout.split("\n");
        //remove last entry because it is empty
        files.splice(-1, 1);
        cb(err, files);
    });
}

if (commander.module && commander.server) {
    findFiles(commander.module, 'pjs', (err, files) => {
        fs.readFile(files[0], (err, data) => {
            if (err) throw err;

            utils.rndPort().then((port) => {
                var addr = "tcp://127.0.0.1:" + port;
                data = JSON.parse(data);
                data.port = addr;

                pp.announce(data, commander.server);

                const imported = require(path.resolve(path.join(commander.module, data.name)));

                pt(addr, function (name, params) {
                    return imported[name](params);
                });

            }).catch((err) => {
                console.log(err)
            });
        });
    });
}<|endoftext|>