<commit_before>var gm = require('gm');
var async = require('async');
var Promise = require('bluebird');
var mockimg = require('./mockimg');
var errors = require('./errors');

var CompressionError = errors.CompressionError;

var Oenyi = function Oenyi(fileName) {
  return this.init.call(this, fileName);
};

var doResize;
var resizeByCover;
var resizeByContain;
var calculateCropArea;
var isPortrait;

Oenyi.prototype._queue = null;
Oenyi.prototype._image = null;
Oenyi.prototype._format = null;
Oenyi.prototype._size = null;
Oenyi.prototype._calc = null;

Oenyi.prototype.init = function(fileName) {
  var oenyi = this;
  this._queue = [];
  this._calc = {};

  if (!fileName || fileName === '') {
    this._image = mockimg(fileName);
  } else {
    this._image = gm(fileName);
  }

  return this;
};

isPortrait = function(size) {
  return size.height > size.width;
};

isSquare = function(size) {
  return size.height === size.width;
};

isLandscape = function(size) {
  return size.width > size.height;
};

calculateCropArea = function(original, destiny) {
  var crop = {x: 0, y: 0, height: original.height, width: original.width};
  if (original.ratio > destiny.ratio) {
      crop.width = Math.round(original.height * destiny.ratio);
      crop.x = Math.round((original.width - crop.width) / 2);
  } else {
      crop.height = Math.round(original.width / destiny.ratio);
      crop.y = Math.round((original.height - crop.height) / 2);
  }

  return crop;
};

doResize = function(params, fn) {
  var args = {width: params.width, height: params.height};

  if (params.method === 'cover') return resizeByCover.call(this, args, fn);
  return resizeByContain.call(this, args, fn);
};

resizeByCover = function(params, fn) {
  var oenyi = this;
  var destiny = params;
  var crop;

  destiny.ratio = destiny.width / destiny.height;

  oenyi._getSize(function(err, original) {
    if (err) return fn(err);
    original.ratio = original.width / original.height;

    if (original.ratio === destiny.ratio) {
      oenyi._image.resize(destiny.width, destiny.height);
    } else {
      crop = calculateCropArea(original, destiny);
      oenyi._image
        .crop(crop.width, crop.height, crop.x, crop.y)
        .resize(destiny.width, destiny.height);
    }

    if (crop) {
      oenyi._calc.crop = JSON.parse(JSON.stringify(crop));
    }
    oenyi._calc.resize = JSON.parse(JSON.stringify(destiny));

    fn(null, oenyi._image);
  });
};

resizeByContain = function(params, fn) {
  var oenyi = this;
  var destiny = params;

  this._getSize(function(err, original) {
    if (err) return fn(err);

    var imageFits = original.width === destiny.width && original.height === destiny.height;

    original.ratio = original.width / original.height;
    destiny.ratio  = destiny.width / destiny.height;

    if (imageFits) return fn(null, oenyi._image);

    if (isPortrait(original)) {
      if (isSquare(destiny) || isLandscape(destiny)) {
        destiny.width = Math.round(destiny.height * original.ratio)
      } else if (original.ratio < destiny.ratio) {
        destiny.width = Math.round(destiny.height * original.ratio);
      } else {
        destiny.height = Math.round(destiny.width / original.ratio);
      }
    } else if(isSquare(original)) {
      if (destiny.width < destiny.height) {
        destiny.height = destiny.width;
      } else {
        destiny.width = destiny.height;
      }
    } else {
      if (destiny.ratio > original.ratio) {
        destiny.width = Math.round(destiny.height * original.ratio);
      } else {
        destiny.height = Math.round(destiny.width / original.ratio);
      }
    }
    oenyi._calc = {resize: JSON.parse(JSON.stringify(destiny))};
    oenyi._image.resize(destiny.width, destiny.height);
    return fn(null, oenyi._image);
  });
}

doConvertToJPG = function(fn) {
  var oenyi = this;
  oenyi._calc.convert = {toFormat: 'jpg'};

  oenyi._getFormat(function(err, format) {
    if (err) return fn(err);

    format = format.toLowerCase();
    if (format === 'jpg') return fn(null, oenyi._image);

    if (format === 'gif') {
      oenyi._image
        .scene(1)
        .coalesce();

      oenyi._calc.convert.fromFormat = 'gif';
      oenyi._calc.convert.scene = 0;
      oenyi._calc.convert.coalesce = true;
    }

    if (format === 'png') {
      oenyi._image.flatten();
      oenyi._calc.convert.fromFormat = 'png';
      oenyi._calc.convert.flatten = true;
    }

    fn(null, oenyi._image);
  });
};

doCompress = function(params, fn) {
  var formats = ['jpg', 'jpeg', 'png'];
  var oenyi = this;
  this._getFormat(function(err, format) {
    if (formats.indexOf(format.toLowerCase()) < 0) return fn(new CompressionError('can´t compress this format.'));
    oenyi._image.quality(params.quality);
    oenyi._calc.compress = {quality : params.quality};
    fn(null, oenyi._image);
  });
};

Oenyi.prototype._getSize = function(fn) {
  var oenyi = this;
  if (oenyi._size) return fn(null, oenyi._size);

  oenyi._image.size(function(err, size) {
    if (err) return fn(err);
    oenyi._size = {width: size.width, height: size.height}
    fn(null, oenyi._size);
  });
};

Oenyi.prototype._getFormat = function(fn) {
  var oenyi = this;
  if (oenyi._format) return fn(null, oenyi._format);

  oenyi._image.format(function (err, format) {
    if (err) return fn(err);
    oenyi._format = format;
    fn(null, format);
  });
};

Oenyi.prototype._enqueue = function(process, args) {
  var oenyi = this;
  if (!args) {
    args = [];
  }

  var wrapperFunction = function(fn) {
    args.push(fn);
    process.apply(oenyi, args);
  }

  this._queue.push(wrapperFunction);

  return this;
};

Oenyi.prototype.exec = function(fn) {
  var oenyi = this;

  this._getFormat(function(err, format) {
    async.series(oenyi._queue, function(err, res) {
      if (err) return fn(err);

      var calc = JSON.parse(JSON.stringify(oenyi._calc));
      var ret;

      oenyi._queue = [];
      oenyi._calc = {};
      ret = res.pop();

      ret.toBuffer(oenyi._format, function(err, buff) {
        fn(err, buff, calc);
      });
    });
  });
};

Oenyi.prototype.pipe = function(stream) {
  var oenyi = this;

  return new Promise(function(resolve, reject) {
    oenyi._getFormat(function(err, format) {
      async.series(oenyi._queue, function(err, res) {
        oenyi._queue = [];
        if (err) return reject(err);
        var ret = res.pop();
        ret.stream(oenyi._formatº)
        .pipe(stream);

        return resolve(stream);
      });
    });
  });
};

Oenyi.prototype.resize = function(args) {
  return this._enqueue(doResize, [args]);
};

Oenyi.prototype.toJPG = function() {
  return this._enqueue(doConvertToJPG);
};

Oenyi.prototype.compress = function(args) {
  return this._enqueue(doCompress, [args]);
};

module.exports = Oenyi;
<commit_msg>remove bad spacing<commit_after>var gm = require('gm');
var async = require('async');
var Promise = require('bluebird');
var mockimg = require('./mockimg');
var errors = require('./errors');

var CompressionError = errors.CompressionError;

var Oenyi = function Oenyi(fileName) {
  return this.init.call(this, fileName);
};

var doResize;
var resizeByCover;
var resizeByContain;
var calculateCropArea;
var isPortrait;

Oenyi.prototype._queue = null;
Oenyi.prototype._image = null;
Oenyi.prototype._format = null;
Oenyi.prototype._size = null;
Oenyi.prototype._calc = null;

Oenyi.prototype.init = function(fileName) {
  var oenyi = this;
  this._queue = [];
  this._calc = {};

  if (!fileName || fileName === '') {
    this._image = mockimg(fileName);
  } else {
    this._image = gm(fileName);
  }

  return this;
};

isPortrait = function(size) {
  return size.height > size.width;
};

isSquare = function(size) {
  return size.height === size.width;
};

isLandscape = function(size) {
  return size.width > size.height;
};

calculateCropArea = function(original, destiny) {
  var crop = {x: 0, y: 0, height: original.height, width: original.width};
  if (original.ratio > destiny.ratio) {
    crop.width = Math.round(original.height * destiny.ratio);
    crop.x = Math.round((original.width - crop.width) / 2);
  } else {
    crop.height = Math.round(original.width / destiny.ratio);
    crop.y = Math.round((original.height - crop.height) / 2);
  }

  return crop;
};

doResize = function(params, fn) {
  var args = {width: params.width, height: params.height};

  if (params.method === 'cover') return resizeByCover.call(this, args, fn);
  return resizeByContain.call(this, args, fn);
};

resizeByCover = function(params, fn) {
  var oenyi = this;
  var destiny = params;
  var crop;

  destiny.ratio = destiny.width / destiny.height;

  oenyi._getSize(function(err, original) {
    if (err) return fn(err);
    original.ratio = original.width / original.height;

    if (original.ratio === destiny.ratio) {
      oenyi._image.resize(destiny.width, destiny.height);
    } else {
      crop = calculateCropArea(original, destiny);
      oenyi._image
        .crop(crop.width, crop.height, crop.x, crop.y)
        .resize(destiny.width, destiny.height);
    }

    if (crop) {
      oenyi._calc.crop = JSON.parse(JSON.stringify(crop));
    }
    oenyi._calc.resize = JSON.parse(JSON.stringify(destiny));

    fn(null, oenyi._image);
  });
};

resizeByContain = function(params, fn) {
  var oenyi = this;
  var destiny = params;

  this._getSize(function(err, original) {
    if (err) return fn(err);

    var imageFits = original.width === destiny.width && original.height === destiny.height;

    original.ratio = original.width / original.height;
    destiny.ratio  = destiny.width / destiny.height;

    if (imageFits) return fn(null, oenyi._image);

    if (isPortrait(original)) {
      if (isSquare(destiny) || isLandscape(destiny)) {
        destiny.width = Math.round(destiny.height * original.ratio)
      } else if (original.ratio < destiny.ratio) {
        destiny.width = Math.round(destiny.height * original.ratio);
      } else {
        destiny.height = Math.round(destiny.width / original.ratio);
      }
    } else if(isSquare(original)) {
      if (destiny.width < destiny.height) {
        destiny.height = destiny.width;
      } else {
        destiny.width = destiny.height;
      }
    } else {
      if (destiny.ratio > original.ratio) {
        destiny.width = Math.round(destiny.height * original.ratio);
      } else {
        destiny.height = Math.round(destiny.width / original.ratio);
      }
    }
    oenyi._calc = {resize: JSON.parse(JSON.stringify(destiny))};
    oenyi._image.resize(destiny.width, destiny.height);
    return fn(null, oenyi._image);
  });
}

doConvertToJPG = function(fn) {
  var oenyi = this;
  oenyi._calc.convert = {toFormat: 'jpg'};

  oenyi._getFormat(function(err, format) {
    if (err) return fn(err);

    format = format.toLowerCase();
    if (format === 'jpg') return fn(null, oenyi._image);

    if (format === 'gif') {
      oenyi._image
        .scene(1)
        .coalesce();

      oenyi._calc.convert.fromFormat = 'gif';
      oenyi._calc.convert.scene = 0;
      oenyi._calc.convert.coalesce = true;
    }

    if (format === 'png') {
      oenyi._image.flatten();
      oenyi._calc.convert.fromFormat = 'png';
      oenyi._calc.convert.flatten = true;
    }

    fn(null, oenyi._image);
  });
};

doCompress = function(params, fn) {
  var formats = ['jpg', 'jpeg', 'png'];
  var oenyi = this;
  this._getFormat(function(err, format) {
    if (formats.indexOf(format.toLowerCase()) < 0) return fn(new CompressionError('can´t compress this format.'));
    oenyi._image.quality(params.quality);
    oenyi._calc.compress = {quality : params.quality};
    fn(null, oenyi._image);
  });
};

Oenyi.prototype._getSize = function(fn) {
  var oenyi = this;
  if (oenyi._size) return fn(null, oenyi._size);

  oenyi._image.size(function(err, size) {
    if (err) return fn(err);
    oenyi._size = {width: size.width, height: size.height}
    fn(null, oenyi._size);
  });
};

Oenyi.prototype._getFormat = function(fn) {
  var oenyi = this;
  if (oenyi._format) return fn(null, oenyi._format);

  oenyi._image.format(function (err, format) {
    if (err) return fn(err);
    oenyi._format = format;
    fn(null, format);
  });
};

Oenyi.prototype._enqueue = function(process, args) {
  var oenyi = this;
  if (!args) {
    args = [];
  }

  var wrapperFunction = function(fn) {
    args.push(fn);
    process.apply(oenyi, args);
  }

  this._queue.push(wrapperFunction);

  return this;
};

Oenyi.prototype.exec = function(fn) {
  var oenyi = this;

  this._getFormat(function(err, format) {
    async.series(oenyi._queue, function(err, res) {
      if (err) return fn(err);

      var calc = JSON.parse(JSON.stringify(oenyi._calc));
      var ret;

      oenyi._queue = [];
      oenyi._calc = {};
      ret = res.pop();

      ret.toBuffer(oenyi._format, function(err, buff) {
        fn(err, buff, calc);
      });
    });
  });
};

Oenyi.prototype.pipe = function(stream) {
  var oenyi = this;

  return new Promise(function(resolve, reject) {
    oenyi._getFormat(function(err, format) {
      async.series(oenyi._queue, function(err, res) {
        oenyi._queue = [];
        if (err) return reject(err);
        var ret = res.pop();
        ret.stream(oenyi._formatº)
        .pipe(stream);

        return resolve(stream);
      });
    });
  });
};

Oenyi.prototype.resize = function(args) {
  return this._enqueue(doResize, [args]);
};

Oenyi.prototype.toJPG = function() {
  return this._enqueue(doConvertToJPG);
};

Oenyi.prototype.compress = function(args) {
  return this._enqueue(doCompress, [args]);
};

module.exports = Oenyi;
<|endoftext|>


<commit_before>var ol = require('ol');
// circular dependency :)
var mm = require('map-make');
var utils = require('utils');
// require('olcss!jspm:css');
var switcher = require('layerswitcher');
var mapDef = require('mapDef');

// 1 view per projection
var map, views = {};
var defaultStyles = {
  normal: {
    stroke: {
      color: 'rgba(0, 0, 255, 0.6)',
      width: 3
    },
    fill: {
      color: 'rgba(255, 255, 255, 0.6)'
    }
  },
  highlight: {
    stroke: {
      color: 'rgba(255, 0, 0, 0.6)',
      width: 3
    },
    fill: {
      color: 'rgba(255, 0, 0, 0.1)'
    }
  }
};

var rasterGroup = new ol.layer.Group({id: 'rasters'});
var vectorGroup = new ol.layer.Group({id: 'vectors'});

map = new ol.Map({
  controls: ol.control.defaults({
    attributionOptions: ({
      collapsible: false
    })
  }).extend([new ol.control.ScaleLine()]),
  layers: [rasterGroup, vectorGroup],
  // create default target div if not defined in options
  target: mapDef.target || createMapTarget(mapDef.noKeyboardPan)
});

/**
 * params: options (center, zoom and rotation; only on startup),
 *        projection code, extent, resolutions array from layer def
 * returns ol.View instance
 */
function createView(options, projCode, extent, resolutions) {
  options = options || {};
  // default center is center of raster extent; default zoom 0
  var defaultCenter = extent ? ol.extent.getCenter(extent)
      : [0, 0];
  var center = options.center ?
      ol.proj.transform([options.center.lon, options.center.lat], 'EPSG:4326', projCode)
      : defaultCenter;
  var viewOptions = {
    center: center,
    zoom: options.zoom || 0
  };
  if (projCode) {
    viewOptions.projection = projCode;
  }
  if (resolutions) {
    viewOptions.resolutions = resolutions;
  }
  if (options.rotation) {
    viewOptions.rotation = options.rotation;
  }
  return new ol.View(viewOptions);
}

// create a default div for the map
function createMapTarget(noKeyboardPan) {
  var mapDiv = document.createElement('div');
  mapDiv.id = 'map';
  mapDiv.style.height = '400px'; // make configurable
  if (!noKeyboardPan) {
    mapDiv.tabIndex=0; // so can use keyboard pan/zoom
  }
  document.body.insertBefore(mapDiv, document.body.childNodes[0]);
  return mapDiv;
}

function switcherRasterHandler(evt) {
  // uses 'map', 'rasterGroup', 'vectorGroup' and 'views' as closure
  // click may be on label or checkbox
  var target = document.getElementById(evt.target.htmlFor) || evt.target;
  if (!target.value) {
    return; // do nothing if not label or checkbox
  }
  var oldLayers = rasterGroup.getLayers().getArray().filter(function(l) {
    return l.activeLayer === true;
  });
  var newLayers = rasterGroup.getLayers().getArray().filter(function(l) {
    return l.getProperties().id == target.value;
  });
  for (var i = 0; i < oldLayers.length; i++) {
    oldLayers[i].setVisible(false);
    oldLayers[i].activeLayer = false;
  }
  for (i = 0; i < newLayers.length; i++) {
    newLayers[i].setVisible(true);
    newLayers[i].activeLayer = true;
  }
  var newProjCode = newLayers[0].getSource().getProjection().getCode();
  var oldProjCode = oldLayers[0] ? oldLayers[0].getSource().getProjection().getCode() : 'EPSG:4326';
  if (newProjCode != oldProjCode) {
    // new projection, so change view and reproject vectors
    var oldExtent = map.getView().calculateExtent(map.getSize());
    var newExtent = ol.proj.transformExtent(oldExtent, oldProjCode, newProjCode);
    vectorGroup.getLayers().forEach(function(l) {
      var features = l.getSource().getFeatures();
      for (var j = 0; j < features.length; j++) {
        features[j].getGeometry().transform(oldProjCode, newProjCode);
      }
    });
    map.setView(views[newProjCode]);
    map.getView().fitExtent(newExtent, map.getSize());
  }
}

function switcherVectorHandler(evt) {
  // uses 'vectorGroup' as closure
  // click may be on label or checkbox
  var target = document.getElementById(evt.target.htmlFor) || evt.target;
  var newLayer = vectorGroup.getLayers().getArray().filter(function(l) {
    return l.getProperties().id == target.value;
  })[0]; // only one
  newLayer.setVisible(target.checked);
}

/**
 * params: array of raster modules
 *         options (zoom, rasters for apikey;
 *                  createView uses zoom, center, rotation (only on startup))
 *         all optional
 */
function addRasters(rasters, options) {
  options = options || {};
  for (var i = 0; i < rasters.length; i++) {
    var raster = rasters[i];
    // create view for projection
    var projCode = raster.projCode || 'EPSG:3857';
    if (!views[projCode]) {
      // assumes all layers for 1 projection have same extent/resolutions
      views[projCode] = createView(options, projCode, raster.extent, raster.resolutions);
      // ol doesn't export, so need to add to check entered coords/zoom
      views[projCode].extent = raster.extent ||
          ol.proj.transformExtent([-180, -85, 180, 85], 'EPSG:4326', projCode);
      views[projCode].zoomLevels = raster.resolutions ? raster.resolutions.length : 20;
    }
    // raster may be an object with api key
    var apikey, key;
    if (options.rasters && typeof options.rasters[i] === 'object') {
      for (key in options.rasters[i]) {
        apikey = options.rasters[i][key];
      }
    }
    var layers = raster.getLayers({
      zoom: options.zoom,
      apikey: apikey
    }), layer; // zoom may be needed to set param
    // a raster def may have >1 layer, but if so all should be treated as 1
    for (var j = 0; j < layers.length; j++) {
      layer = layers[j];
      // set layers invisible to start with
      layer.setVisible(false);
      // options only present for initial create
      if (options.rasters && i === 0) {
        layer.activeLayer = true;
      } else {
        layer.activeLayer = false;
      }
      // add layer to map
      rasterGroup.getLayers().push(layer);
    }

    // add to layerswitcher
    switcher.addRasterDiv(layer, switcherRasterHandler);

    if (raster.viewEvent) {
      views[projCode].on(raster.viewEvent.type, raster.viewEvent.func);
    }
  }
}

/**
 * params: array of vector defs
 */
function addVectors(options) {
  var vectors = options.vectors;
  var formats = {
    geojson: 'GeoJSON',
    gpx: 'GPX',
    kml: 'KML'
  };
  // var getStyleFunction = function(style) {
  //   return function(feature, resolution) {
  //     return [style];
  //   };
  // };
  for (var i = 0; i < vectors.length; i++) {
    var vector = vectors[i];
    var format, url = vector.url;
    var sourceOptions = {
      attributions: [new ol.Attribution({
        html: vector.attribution || ''
      })]
    };
    if (vector.type == 'mongodb') {
      sourceOptions.loader = function(extent, resolution, projection) {
        utils.httpGet(url).then(function(result) {
          var features = [];
          for (var j = 0; j < result.length; j++) {
            var geom = new ol.geom[result[j].geometry.type](result[j].geometry.coordinates);
            geom.transform('EPSG:4326', projection);
            result[j].geometry = geom;
            features.push(new ol.Feature(result[j]));
          }
          var mongoLayers = vectorGroup.getLayers().getArray().filter(function(l) {
            return l.getProperties().id==vector.id;
          });
          var source = mongoLayers[0].getSource();
          source.addFeatures(features);
        }, mm.errors.fetchFail);
      };
    } else {
      if (url && !vector.format) {
        // define format from file extension
        var ext = url.substring(url.lastIndexOf('.')+1);
        format = formats[ext];
      }
      format = vector.format || format;
      sourceOptions.url = url;
      sourceOptions.format = new ol.format[format]();
    }
    var source = new ol.source.Vector(sourceOptions);
    // if this is an added layer, zoom to data extent
    if (vector.add === true) {
      source.once('change', function(e) {
        map.getView().fitExtent(e.target.getExtent(), map.getSize());
      });
    }
    var vectOpts = {
      source: source,
      id: vector.id || url
    };
    // override default style if in options
    var style = vector.styles ? new ol.style.Style({
        fill: new ol.style.Fill(vector.styles[0].fill || getStyle('normal').getFill()),
        stroke: new ol.style.Stroke(vector.styles[0].stroke || getStyle('normal').getStroke())
      }) : getStyle('normal');
    vectOpts.style = style; //getStyleFunction(style);
    vectorGroup.getLayers().push(new ol.layer.Vector(vectOpts));

    // add to layerswitcher
    // if this is 1st vector layer, add vector widget buttons
    if (switcher.addVectorDiv(vector, switcherVectorHandler)) {
      addVectorWidgetButtons(options.widgets);
    }
  }
}

function getStyle(type) {
  return new ol.style.Style({
    stroke: new ol.style.Stroke(defaultStyles[type].stroke),
    fill: new ol.style.Fill(defaultStyles[type].fill)
  });
}

function addVectorWidgetButtons(widgets) {
  widgets = widgets || {};
  var button, componentDir = 'lib/registry/components/';
  if (!widgets.popup) {
    button = document.createElement('button');
    button.id = 'popupButton';
    button.innerHTML = 'Popup'; // FIXME English
    button.addEventListener('click', function() {
      utils.importComponent('popup', componentDir + 'popup.html');
      this.style.display = 'none';
    });
    document.getElementById('widgets').appendChild(button);
  }

  if (!widgets.tooltip) {
    button = document.createElement('button');
    button.id = 'tooltipButton';
    button.innerHTML = 'Tooltip'; // FIXME English
    button.addEventListener('click', function() {
      utils.importComponent('tooltip', componentDir + 'tooltip.html');
      this.style.display = 'none';
    });
    document.getElementById('widgets').appendChild(button);
  }
}

module.exports = {
  addRasters: addRasters,
  addVectors: addVectors,

  create4326View: function(options) {
    // vectors only, so use 4326 view
    var projCode = 'EPSG:4326';
    views[projCode] = createView(options, projCode);
  },

  setDefaultView: function(view) {
    map.setView(views[view]);
  },

  createView: createView,

  /**
   * Add event returns extent, so can use this to zoom to feature data extent.
   * Make first tile layer visible at this point, so tiles are only fetched after the
   * extent has been established and the appropriate zoom/resolution set.
   *
   * params: vectorLayers
   */
  addFeaturesListener: function () {
    var vectorLayers = vectorGroup.getLayers().getArray();
    var vectorsExtent = ol.extent.createEmpty();
    var sourcesRead = 0;
    // callback
    var callback = function(e) {
      ol.extent.extend(vectorsExtent, e.target.getExtent());
      sourcesRead++;
      if (sourcesRead == vectorLayers.length) {
        // we've loaded all the sources
        // so zoom to data extent and make 1st raster layer visible
        map.getView().fitExtent(vectorsExtent, map.getSize());
        rasterGroup.getLayers().forEach(function(l) {
          if (l.activeLayer === true) {
            l.setVisible(true);
          }
        });
        var status = document.getElementById('status');
        if (status) {
          status.style.display = 'none';
        }
      }
    };
    for (var i = 0; i < vectorLayers.length; i++) {
      vectorLayers[i].getSource().once('change', callback);
    }
  },

  makeActiveLayerVisible: function() {
    // may be >1
    rasterGroup.getLayers().forEach(function(l) {
      if (l.activeLayer === true) {
        l.setVisible(true);
      }
    });
  },

  getStyle: getStyle,

  setFocus: function() {
    map.getTargetElement().focus();
  },

  // add FeatureOverlay if one not present
  addHighlightOverlay() {
    if (!map.highlightOverlay) {
      map.highlightOverlay = new ol.FeatureOverlay({
        map: map,
        style: getStyle('highlight')
      });
    }
  },

  get: function() {
    return map;
  }
};<commit_msg>Standardise makeActiveLayerVisible<commit_after>var ol = require('ol');
// circular dependency :)
var mm = require('map-make');
var utils = require('utils');
// require('olcss!jspm:css');
var switcher = require('layerswitcher');
var mapDef = require('mapDef');

// 1 view per projection
var map, views = {};
var defaultStyles = {
  normal: {
    stroke: {
      color: 'rgba(0, 0, 255, 0.6)',
      width: 3
    },
    fill: {
      color: 'rgba(255, 255, 255, 0.6)'
    }
  },
  highlight: {
    stroke: {
      color: 'rgba(255, 0, 0, 0.6)',
      width: 3
    },
    fill: {
      color: 'rgba(255, 0, 0, 0.1)'
    }
  }
};

var rasterGroup = new ol.layer.Group({id: 'rasters'});
var vectorGroup = new ol.layer.Group({id: 'vectors'});

map = new ol.Map({
  controls: ol.control.defaults({
    attributionOptions: ({
      collapsible: false
    })
  }).extend([new ol.control.ScaleLine()]),
  layers: [rasterGroup, vectorGroup],
  // create default target div if not defined in options
  target: mapDef.target || createMapTarget(mapDef.noKeyboardPan)
});

/**
 * params: options (center, zoom and rotation; only on startup),
 *        projection code, extent, resolutions array from layer def
 * returns ol.View instance
 */
function createView(options, projCode, extent, resolutions) {
  options = options || {};
  // default center is center of raster extent; default zoom 0
  var defaultCenter = extent ? ol.extent.getCenter(extent)
      : [0, 0];
  var center = options.center ?
      ol.proj.transform([options.center.lon, options.center.lat], 'EPSG:4326', projCode)
      : defaultCenter;
  var viewOptions = {
    center: center,
    zoom: options.zoom || 0
  };
  if (projCode) {
    viewOptions.projection = projCode;
  }
  if (resolutions) {
    viewOptions.resolutions = resolutions;
  }
  if (options.rotation) {
    viewOptions.rotation = options.rotation;
  }
  return new ol.View(viewOptions);
}

// create a default div for the map
function createMapTarget(noKeyboardPan) {
  var mapDiv = document.createElement('div');
  mapDiv.id = 'map';
  mapDiv.style.height = '400px'; // make configurable
  if (!noKeyboardPan) {
    mapDiv.tabIndex=0; // so can use keyboard pan/zoom
  }
  document.body.insertBefore(mapDiv, document.body.childNodes[0]);
  return mapDiv;
}

function switcherRasterHandler(evt) {
  // uses 'map', 'rasterGroup', 'vectorGroup' and 'views' as closure
  // click may be on label or checkbox
  var target = document.getElementById(evt.target.htmlFor) || evt.target;
  if (!target.value) {
    return; // do nothing if not label or checkbox
  }
  var oldLayers = rasterGroup.getLayers().getArray().filter(function(l) {
    return l.activeLayer === true;
  });
  var newLayers = rasterGroup.getLayers().getArray().filter(function(l) {
    return l.getProperties().id == target.value;
  });
  for (var i = 0; i < oldLayers.length; i++) {
    oldLayers[i].setVisible(false);
    oldLayers[i].activeLayer = false;
  }
  for (i = 0; i < newLayers.length; i++) {
    newLayers[i].setVisible(true);
    newLayers[i].activeLayer = true;
  }
  var newProjCode = newLayers[0].getSource().getProjection().getCode();
  var oldProjCode = oldLayers[0] ? oldLayers[0].getSource().getProjection().getCode() : 'EPSG:4326';
  if (newProjCode != oldProjCode) {
    // new projection, so change view and reproject vectors
    var oldExtent = map.getView().calculateExtent(map.getSize());
    var newExtent = ol.proj.transformExtent(oldExtent, oldProjCode, newProjCode);
    vectorGroup.getLayers().forEach(function(l) {
      var features = l.getSource().getFeatures();
      for (var j = 0; j < features.length; j++) {
        features[j].getGeometry().transform(oldProjCode, newProjCode);
      }
    });
    map.setView(views[newProjCode]);
    map.getView().fitExtent(newExtent, map.getSize());
  }
}

function switcherVectorHandler(evt) {
  // uses 'vectorGroup' as closure
  // click may be on label or checkbox
  var target = document.getElementById(evt.target.htmlFor) || evt.target;
  var newLayer = vectorGroup.getLayers().getArray().filter(function(l) {
    return l.getProperties().id == target.value;
  })[0]; // only one
  newLayer.setVisible(target.checked);
}

/**
 * params: array of raster modules
 *         options (zoom, rasters for apikey;
 *                  createView uses zoom, center, rotation (only on startup))
 *         all optional
 */
function addRasters(rasters, options) {
  options = options || {};
  for (var i = 0; i < rasters.length; i++) {
    var raster = rasters[i];
    // create view for projection
    var projCode = raster.projCode || 'EPSG:3857';
    if (!views[projCode]) {
      // assumes all layers for 1 projection have same extent/resolutions
      views[projCode] = createView(options, projCode, raster.extent, raster.resolutions);
      // ol doesn't export, so need to add to check entered coords/zoom
      views[projCode].extent = raster.extent ||
          ol.proj.transformExtent([-180, -85, 180, 85], 'EPSG:4326', projCode);
      views[projCode].zoomLevels = raster.resolutions ? raster.resolutions.length : 20;
    }
    // raster may be an object with api key
    var apikey, key;
    if (options.rasters && typeof options.rasters[i] === 'object') {
      for (key in options.rasters[i]) {
        apikey = options.rasters[i][key];
      }
    }
    var layers = raster.getLayers({
      zoom: options.zoom,
      apikey: apikey
    }), layer; // zoom may be needed to set param
    // a raster def may have >1 layer, but if so all should be treated as 1
    for (var j = 0; j < layers.length; j++) {
      layer = layers[j];
      // set layers invisible to start with
      layer.setVisible(false);
      // options only present for initial create
      if (options.rasters && i === 0) {
        layer.activeLayer = true;
      } else {
        layer.activeLayer = false;
      }
      // add layer to map
      rasterGroup.getLayers().push(layer);
    }

    // add to layerswitcher
    switcher.addRasterDiv(layer, switcherRasterHandler);

    if (raster.viewEvent) {
      views[projCode].on(raster.viewEvent.type, raster.viewEvent.func);
    }
  }
}

/**
 * params: array of vector defs
 */
function addVectors(options) {
  var vectors = options.vectors;
  var formats = {
    geojson: 'GeoJSON',
    gpx: 'GPX',
    kml: 'KML'
  };
  // var getStyleFunction = function(style) {
  //   return function(feature, resolution) {
  //     return [style];
  //   };
  // };
  for (var i = 0; i < vectors.length; i++) {
    var vector = vectors[i];
    var format, url = vector.url;
    var sourceOptions = {
      attributions: [new ol.Attribution({
        html: vector.attribution || ''
      })]
    };
    if (vector.type == 'mongodb') {
      sourceOptions.loader = function(extent, resolution, projection) {
        utils.httpGet(url).then(function(result) {
          var features = [];
          for (var j = 0; j < result.length; j++) {
            var geom = new ol.geom[result[j].geometry.type](result[j].geometry.coordinates);
            geom.transform('EPSG:4326', projection);
            result[j].geometry = geom;
            features.push(new ol.Feature(result[j]));
          }
          var mongoLayers = vectorGroup.getLayers().getArray().filter(function(l) {
            return l.getProperties().id==vector.id;
          });
          var source = mongoLayers[0].getSource();
          source.addFeatures(features);
        }, mm.errors.fetchFail);
      };
    } else {
      if (url && !vector.format) {
        // define format from file extension
        var ext = url.substring(url.lastIndexOf('.')+1);
        format = formats[ext];
      }
      format = vector.format || format;
      sourceOptions.url = url;
      sourceOptions.format = new ol.format[format]();
    }
    var source = new ol.source.Vector(sourceOptions);
    // if this is an added layer, zoom to data extent
    if (vector.add === true) {
      source.once('change', function(e) {
        map.getView().fitExtent(e.target.getExtent(), map.getSize());
      });
    }
    var vectOpts = {
      source: source,
      id: vector.id || url
    };
    // override default style if in options
    var style = vector.styles ? new ol.style.Style({
        fill: new ol.style.Fill(vector.styles[0].fill || getStyle('normal').getFill()),
        stroke: new ol.style.Stroke(vector.styles[0].stroke || getStyle('normal').getStroke())
      }) : getStyle('normal');
    vectOpts.style = style; //getStyleFunction(style);
    vectorGroup.getLayers().push(new ol.layer.Vector(vectOpts));

    // add to layerswitcher
    // if this is 1st vector layer, add vector widget buttons
    if (switcher.addVectorDiv(vector, switcherVectorHandler)) {
      addVectorWidgetButtons(options.widgets);
    }
  }
}

function getStyle(type) {
  return new ol.style.Style({
    stroke: new ol.style.Stroke(defaultStyles[type].stroke),
    fill: new ol.style.Fill(defaultStyles[type].fill)
  });
}

function addVectorWidgetButtons(widgets) {
  widgets = widgets || {};
  var button, componentDir = 'lib/registry/components/';
  if (!widgets.popup) {
    button = document.createElement('button');
    button.id = 'popupButton';
    button.innerHTML = 'Popup'; // FIXME English
    button.addEventListener('click', function() {
      utils.importComponent('popup', componentDir + 'popup.html');
      this.style.display = 'none';
    });
    document.getElementById('widgets').appendChild(button);
  }

  if (!widgets.tooltip) {
    button = document.createElement('button');
    button.id = 'tooltipButton';
    button.innerHTML = 'Tooltip'; // FIXME English
    button.addEventListener('click', function() {
      utils.importComponent('tooltip', componentDir + 'tooltip.html');
      this.style.display = 'none';
    });
    document.getElementById('widgets').appendChild(button);
  }
}

function makeActiveLayerVisible() {
  // may be >1
  rasterGroup.getLayers().forEach(function(l) {
    if (l.activeLayer === true) {
      l.setVisible(true);
    }
  });
}

module.exports = {
  addRasters: addRasters,
  addVectors: addVectors,

  create4326View: function(options) {
    // vectors only, so use 4326 view
    var projCode = 'EPSG:4326';
    views[projCode] = createView(options, projCode);
  },

  setDefaultView: function(view) {
    map.setView(views[view]);
  },

  createView: createView,

  /**
   * Add event returns extent, so can use this to zoom to feature data extent.
   * Make first tile layer visible at this point, so tiles are only fetched after the
   * extent has been established and the appropriate zoom/resolution set.
   *
   * params: vectorLayers
   */
  addFeaturesListener: function () {
    var vectorLayers = vectorGroup.getLayers().getArray();
    var vectorsExtent = ol.extent.createEmpty();
    var sourcesRead = 0;
    // callback
    var callback = function(e) {
      ol.extent.extend(vectorsExtent, e.target.getExtent());
      sourcesRead++;
      if (sourcesRead == vectorLayers.length) {
        // we've loaded all the sources
        // so zoom to data extent and make 1st raster layer visible
        map.getView().fitExtent(vectorsExtent, map.getSize());
        makeActiveLayerVisible();
        var status = document.getElementById('status');
        if (status) {
          status.style.display = 'none';
        }
      }
    };
    for (var i = 0; i < vectorLayers.length; i++) {
      vectorLayers[i].getSource().once('change', callback);
    }
  },

  makeActiveLayerVisible: makeActiveLayerVisible,

  getStyle: getStyle,

  setFocus: function() {
    map.getTargetElement().focus();
  },

  // add FeatureOverlay if one not present
  addHighlightOverlay() {
    if (!map.highlightOverlay) {
      map.highlightOverlay = new ol.FeatureOverlay({
        map: map,
        style: getStyle('highlight')
      });
    }
  },

  get: function() {
    return map;
  }
};<|endoftext|>


<commit_before>const { Application } = require('spectron');
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const path = require('path');

const electronPath = path.join(__dirname, '../..', 'node_modules', '.bin', 'electron');
const appPath = path.join(__dirname, '../..');
const mocksPath = path.join(__dirname, 'mocks.js');

const EXIST_TIMEOUT = 4000;
const NOTIFICATION_DISMISS_TIMEOUT = 6000;
const COMPUTATION_TIMEOUT = 120000;
const USER_ID = 'test1';
const PASS = 'password';
const CONS_NAME = 'e2e-consortium';
const CONS_DESC = 'e2e-description';
const PIPE_NAME = 'e2e-pipeline';
const PIPE_DESC = 'e2e-pipeline-description';

chai.should();
chai.use(chaiAsPromised);

const app = new Application({
  path: electronPath,
  env: { NODE_ENV: 'test' },
  args: [appPath, '-r', mocksPath],
});

describe('Testing::e2e', () => {
  before(() => app.start());

  after(() => {
    if (app && app.isRunning()) {
      return app.stop();
    }
  });

  it('opens a single window', () => (
    app.client.waitUntilWindowLoaded()
      .getWindowCount().should.eventually.equal(1)
  ));

  it('displays the correct title', () => (
    app.client.waitUntilWindowLoaded()
      .getTitle().should.eventually.equal('COINSTAC')
  ));

  it('authenticates demo user', () => (
    app.client
      .waitForVisible('#login-username', EXIST_TIMEOUT)
      .setValue('#login-username', USER_ID)
      .setValue('#login-password', PASS)
      .click('button=Log In')
      .waitForExist('.user-account-name', EXIST_TIMEOUT)
      .getText('.user-account-name').should.eventually.equal(USER_ID)
  ));

  it('accesses the Add Consortium page', () => (
    app.client
      .click('a=Consortia')
      .waitForVisible('a=Create Consortium', EXIST_TIMEOUT)
      .click('a=Create Consortium')
      .isVisible('h1=Consortium Creation').should.eventually.equal(true)
  ));

  it('creates a consortium', () => (
    app.client
      .setValue('#name', CONS_NAME)
      .setValue('#description', CONS_DESC)
      .click('button=Save')
      .waitForText('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal('Consortium Saved'))
      .then(() => app.client
        .waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true)
        .click('a=Consortia')
        .waitForVisible(`h3=${CONS_NAME}`))
  ));

  it('accesses the Add Pipeline page', () => (
    app.client
      .click('a=Pipelines')
      .waitForVisible('a=Create Pipeline', EXIST_TIMEOUT)
      .click('a=Create Pipeline')
      .isVisible('h1=Pipeline Creation').should.eventually.equal(true)
  ));

  it('creates a pipeline', () => (
    app.client
      .setValue('#name', PIPE_NAME)
      .setValue('#description', PIPE_DESC)
      .click('#pipelineconsortia')
      .waitForVisible('.dropdown-menu[aria-labelledby="pipelineconsortia"]', EXIST_TIMEOUT)
      .click(`a=${CONS_NAME}`)
      .click('#computation-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="computation-dropdown"]', EXIST_TIMEOUT)
      .click('a=single shot regression demo')
      .waitForVisible('button=Add Covariates')
      .click('button=Add Covariates')
      .click('#covariates-0-data-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="covariates-0-data-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="covariates-0-data-dropdown"]')
      .click('a=boolean')
      .click('#input-source-0-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="input-source-0-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="input-source-0-dropdown"]')
      .click('a=File')
      .setValue('#covariates-0-input-name', 'isControl')
      .click('button=Add Covariates')
      .click('#covariates-1-data-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="covariates-1-data-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="covariates-1-data-dropdown"]')
      .click('a=number')
      .click('#input-source-1-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="input-source-1-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="input-source-1-dropdown"]')
      .click('a=File')
      .setValue('#covariates-1-input-name', 'age')
      .click('button=Add Data')
      .click('#data-0-data-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="data-0-data-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="data-0-data-dropdown"]')
      .click('a=FreeSurfer')
      .click('#data-0-area .Select-control')
      .waitForVisible('#data-0-area .Select-menu-outer', EXIST_TIMEOUT)
      .element('#data-0-area .Select-menu-outer')
      .click('div=5th-Ventricle', EXIST_TIMEOUT)
      .click('#data-0-area .Select-control')
      .waitForVisible('#data-0-area .Select-menu-outer', EXIST_TIMEOUT)
      .element('#data-0-area .Select-menu-outer')
      .click('div=BrainSegVol', EXIST_TIMEOUT)
      .setValue('[name="step-lambda"]', '0')
      .click('button=Save Pipeline')
      .waitForVisible('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal('Pipeline Saved.'))
      .then(() => app.client
        .waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true))
  ));

  it('sets the created pipeline to the consortium', () => (
    app.client
      .click('a=Consortia')
      .waitForVisible(`a[name="${CONS_NAME}"]`, EXIST_TIMEOUT)
      .click(`a[name="${CONS_NAME}"]`)
      .waitForExist('#consortium-tabs #consortium-tabs-tab-2', EXIST_TIMEOUT)
      .element('#consortium-tabs')
      .click('a=Pipelines')
      .waitForVisible('#owned-pipelines-dropdown', EXIST_TIMEOUT)
      .click('#owned-pipelines-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="owned-pipelines-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="owned-pipelines-dropdown"]')
      .click(`a=${PIPE_NAME}`)
      .waitForVisible(`h4=${PIPE_NAME}`, EXIST_TIMEOUT)
  ));

  it('creates a file collection', () => (
    app.client
      .click('a=Collections')
      .waitForVisible('h1=File Collections', EXIST_TIMEOUT)
      .click('a=Create File Collection')
      .waitForVisible('h1=New Collection', EXIST_TIMEOUT)
      .setValue('#name', CONS_NAME)
      .setValue('#description', CONS_DESC)
      .click('button=Save')
      .waitForText('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal('Collection Saved.'))
      .then(() => app.client.waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true))
  ));

  it('sets the data set into the file collection', () => (
    app.client
      .element('#collection-tabs')
      .click('a=Files')
      .waitForVisible('h3=Collection Files', EXIST_TIMEOUT)
      .click('button=Add Group')
      .waitForVisible('button=Add Files Group', EXIST_TIMEOUT)
      .click('label=A metadata file containing file paths and covariates.')
      .click('button=Add Files Group')
      .waitForVisible('button=Remove File Group', EXIST_TIMEOUT)
      .waitForVisible('.notification-message', EXIST_TIMEOUT)
      .waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true)
      .element('#collection-tabs')
      .click('a=Consortia')
      .waitForVisible('h3=Add to Consortia', EXIST_TIMEOUT)
      .click('#member-consortia-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="member-consortia-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="member-consortia-dropdown"]')
      .click(`a=${CONS_NAME}`)
      .waitForVisible('div.panel', EXIST_TIMEOUT)
      .element('.tab-pane.active .panel-body li')
      .click('select')
      .element('.tab-pane.active .panel-body li')
      .click('option=Group 1 (.CSV)')
      .element('.tab-pane.active .panel-body li:nth-child(2)')
      .click('select')
      .element('.tab-pane.active .panel-body li:nth-child(2)')
      .click('option=Group 1 (.CSV)')
      .element('.tab-pane.active .panel-body > div:nth-child(2)')
      .click('select')
      .element('.tab-pane.active .panel-body > div:nth-child(2)')
      .click('option=Group 1 (.CSV)')
      .element('.tab-pane.active')
      .click('button=Save')
      .waitForText('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal('Collection Saved.'))
      .then(() => app.client.waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true))
  ));

  it('runs a computation', () => (
    app.client
      .click('a=Consortia')
      .waitForVisible('h1=Consortia', EXIST_TIMEOUT)
      .click('button=Start Pipeline')
      .waitForText('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal(`Decentralized Pipeline Starting for ${CONS_NAME}.`))
      .then(() => app.client.waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true))
  ));

  it('displays computation progress', () => (
    app.client
      .click('a=Home')
      .waitForVisible('div.panel:first-child', EXIST_TIMEOUT)
      .element('div.panel:first-child')
      .isVisible('span=In Progress').should.eventually.equal(true)
  ));

  it('displays results', () => (
    app.client
      .click('a=Home')
      .waitForVisible('div.panel:first-child', EXIST_TIMEOUT)
      .element('div.panel:first-child')
      .waitForVisible('a=View Results', COMPUTATION_TIMEOUT)
      .element('div.panel:first-child')
      .click('a=View Results')
      .waitForVisible('h3=Regressions', EXIST_TIMEOUT)
      .isVisible(`span=Results: ${CONS_NAME} || ${PIPE_NAME}`).should.eventually.equal(true)
  ));

  it('deletes consortium', () => (
    app.client
      .click('a=Consortia')
      .waitForVisible(`button[name="${CONS_NAME}-delete"]`, EXIST_TIMEOUT)
      .click(`button[name="${CONS_NAME}-delete"]`)
      .element('.modal-dialog')
      .click('button=Delete')
      .waitForVisible(`h3=${CONS_NAME}`, EXIST_TIMEOUT, true)
  ));

  it('logs out', () => (
    app.client
      .waitForVisible('button=Log Out', EXIST_TIMEOUT)
      .click('button=Log Out')
      .waitForVisible('button=Log In', EXIST_TIMEOUT)
  ));
});
<commit_msg>Dismiss notifications when setting pipeline on consortium<commit_after>const { Application } = require('spectron');
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const path = require('path');

const electronPath = path.join(__dirname, '../..', 'node_modules', '.bin', 'electron');
const appPath = path.join(__dirname, '../..');
const mocksPath = path.join(__dirname, 'mocks.js');

const EXIST_TIMEOUT = 4000;
const NOTIFICATION_DISMISS_TIMEOUT = 6000;
const COMPUTATION_TIMEOUT = 120000;
const COMPUTATION_DOWNLOAD_TIMEOUT = 30000;
const USER_ID = 'test1';
const PASS = 'password';
const CONS_NAME = 'e2e-consortium';
const CONS_DESC = 'e2e-description';
const PIPE_NAME = 'e2e-pipeline';
const PIPE_DESC = 'e2e-pipeline-description';
const PIPELINE_COMPUTATION_STEP_NAME = 'single shot regression demo';

chai.should();
chai.use(chaiAsPromised);

const app = new Application({
  path: electronPath,
  env: { NODE_ENV: 'test' },
  args: [appPath, '-r', mocksPath],
});

describe('Testing::e2e', () => {
  before(() => app.start());

  after(() => {
    if (app && app.isRunning()) {
      return app.stop();
    }
  });

  it('opens a single window', () => (
    app.client.waitUntilWindowLoaded()
      .getWindowCount().should.eventually.equal(1)
  ));

  it('displays the correct title', () => (
    app.client.waitUntilWindowLoaded()
      .getTitle().should.eventually.equal('COINSTAC')
  ));

  it('authenticates demo user', () => (
    app.client
      .waitForVisible('#login-username', EXIST_TIMEOUT)
      .setValue('#login-username', USER_ID)
      .setValue('#login-password', PASS)
      .click('button=Log In')
      .waitForExist('.user-account-name', EXIST_TIMEOUT)
      .getText('.user-account-name').should.eventually.equal(USER_ID)
  ));

  it('accesses the Add Consortium page', () => (
    app.client
      .click('a=Consortia')
      .waitForVisible('a=Create Consortium', EXIST_TIMEOUT)
      .click('a=Create Consortium')
      .isVisible('h1=Consortium Creation').should.eventually.equal(true)
  ));

  it('creates a consortium', () => (
    app.client
      .setValue('#name', CONS_NAME)
      .setValue('#description', CONS_DESC)
      .click('button=Save')
      .waitForText('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal('Consortium Saved'))
      .then(() => app.client
        .waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true)
        .click('a=Consortia')
        .waitForVisible(`h3=${CONS_NAME}`))
  ));

  it('accesses the Add Pipeline page', () => (
    app.client
      .click('a=Pipelines')
      .waitForVisible('a=Create Pipeline', EXIST_TIMEOUT)
      .click('a=Create Pipeline')
      .isVisible('h1=Pipeline Creation').should.eventually.equal(true)
  ));

  it('creates a pipeline', () => (
    app.client
      .setValue('#name', PIPE_NAME)
      .setValue('#description', PIPE_DESC)
      .click('#pipelineconsortia')
      .waitForVisible('.dropdown-menu[aria-labelledby="pipelineconsortia"]', EXIST_TIMEOUT)
      .click(`a=${CONS_NAME}`)
      .click('#computation-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="computation-dropdown"]', EXIST_TIMEOUT)
      .click(`a=${PIPELINE_COMPUTATION_STEP_NAME}`)
      .waitForVisible('button=Add Covariates')
      .click('button=Add Covariates')
      .click('#covariates-0-data-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="covariates-0-data-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="covariates-0-data-dropdown"]')
      .click('a=boolean')
      .click('#input-source-0-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="input-source-0-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="input-source-0-dropdown"]')
      .click('a=File')
      .setValue('#covariates-0-input-name', 'isControl')
      .click('button=Add Covariates')
      .click('#covariates-1-data-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="covariates-1-data-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="covariates-1-data-dropdown"]')
      .click('a=number')
      .click('#input-source-1-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="input-source-1-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="input-source-1-dropdown"]')
      .click('a=File')
      .setValue('#covariates-1-input-name', 'age')
      .click('button=Add Data')
      .click('#data-0-data-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="data-0-data-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="data-0-data-dropdown"]')
      .click('a=FreeSurfer')
      .click('#data-0-area .Select-control')
      .waitForVisible('#data-0-area .Select-menu-outer', EXIST_TIMEOUT)
      .element('#data-0-area .Select-menu-outer')
      .click('div=5th-Ventricle', EXIST_TIMEOUT)
      .click('#data-0-area .Select-control')
      .waitForVisible('#data-0-area .Select-menu-outer', EXIST_TIMEOUT)
      .element('#data-0-area .Select-menu-outer')
      .click('div=BrainSegVol', EXIST_TIMEOUT)
      .setValue('[name="step-lambda"]', '0')
      .click('button=Save Pipeline')
      .waitForVisible('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal('Pipeline Saved.'))
      .then(() => app.client
        .waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true))
  ));

  it('sets the created pipeline to the consortium', () => (
    app.client
      .click('a=Consortia')
      .waitForVisible(`a[name="${CONS_NAME}"]`, EXIST_TIMEOUT)
      .click(`a[name="${CONS_NAME}"]`)
      .waitForExist('#consortium-tabs #consortium-tabs-tab-2', EXIST_TIMEOUT)
      .element('#consortium-tabs')
      .click('a=Pipelines')
      .waitForVisible('#owned-pipelines-dropdown', EXIST_TIMEOUT)
      .click('#owned-pipelines-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="owned-pipelines-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="owned-pipelines-dropdown"]')
      .click(`a=${PIPE_NAME}`)
      .waitForVisible(`h4=${PIPE_NAME}`, EXIST_TIMEOUT)
      .waitForVisible('div=Pipeline computations downloading via Docker.', EXIST_TIMEOUT)
      .click('.notification .notification-dismiss')
      .waitForVisible('div=Pipeline computations downloading via Docker.', EXIST_TIMEOUT, true)
      .waitForVisible(`div=${PIPELINE_COMPUTATION_STEP_NAME} Download Complete`, COMPUTATION_DOWNLOAD_TIMEOUT)
      .click('.notification .notification-dismiss')
      .waitForVisible(`div=${PIPELINE_COMPUTATION_STEP_NAME} Download Complete`, EXIST_TIMEOUT, true)
      .waitForVisible('.notification', COMPUTATION_DOWNLOAD_TIMEOUT)
      .click('.notification .notification-dismiss')
      .waitForVisible('.notification', EXIST_TIMEOUT, true)
  ));

  it('creates a file collection', () => (
    app.client
      .click('a=Collections')
      .waitForVisible('h1=File Collections', EXIST_TIMEOUT)
      .click('a=Create File Collection')
      .waitForVisible('h1=New Collection', EXIST_TIMEOUT)
      .setValue('#name', CONS_NAME)
      .setValue('#description', CONS_DESC)
      .click('button=Save')
      .waitForText('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal('Collection Saved.'))
      .then(() => app.client.waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true))
  ));

  it('sets the data set into the file collection', () => (
    app.client
      .element('#collection-tabs')
      .click('a=Files')
      .waitForVisible('h3=Collection Files', EXIST_TIMEOUT)
      .click('button=Add Group')
      .waitForVisible('button=Add Files Group', EXIST_TIMEOUT)
      .click('label=A metadata file containing file paths and covariates.')
      .click('button=Add Files Group')
      .waitForVisible('button=Remove File Group', EXIST_TIMEOUT)
      .waitForVisible('.notification-message', EXIST_TIMEOUT)
      .waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true)
      .element('#collection-tabs')
      .click('a=Consortia')
      .waitForVisible('h3=Add to Consortia', EXIST_TIMEOUT)
      .click('#member-consortia-dropdown')
      .waitForVisible('.dropdown-menu[aria-labelledby="member-consortia-dropdown"]', EXIST_TIMEOUT)
      .element('.dropdown-menu[aria-labelledby="member-consortia-dropdown"]')
      .click(`a=${CONS_NAME}`)
      .waitForVisible('div.panel', EXIST_TIMEOUT)
      .element('.tab-pane.active .panel-body li')
      .click('select')
      .element('.tab-pane.active .panel-body li')
      .click('option=Group 1 (.CSV)')
      .element('.tab-pane.active .panel-body li:nth-child(2)')
      .click('select')
      .element('.tab-pane.active .panel-body li:nth-child(2)')
      .click('option=Group 1 (.CSV)')
      .element('.tab-pane.active .panel-body > div:nth-child(2)')
      .click('select')
      .element('.tab-pane.active .panel-body > div:nth-child(2)')
      .click('option=Group 1 (.CSV)')
      .element('.tab-pane.active')
      .click('button=Save')
      .waitForText('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal('Collection Saved.'))
      .then(() => app.client.waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true))
  ));

  it('runs a computation', () => (
    app.client
      .click('a=Consortia')
      .waitForVisible('h1=Consortia', EXIST_TIMEOUT)
      .click('button=Start Pipeline')
      .waitForText('.notification-message', EXIST_TIMEOUT)
      .getText('.notification-message')
      .then(notificationMessage => notificationMessage.should.equal(`Decentralized Pipeline Starting for ${CONS_NAME}.`))
      .then(() => app.client.waitForVisible('.notification-message', NOTIFICATION_DISMISS_TIMEOUT, true))
  ));

  it('displays computation progress', () => (
    app.client
      .click('a=Home')
      .waitForVisible('div.panel:first-child', EXIST_TIMEOUT)
      .element('div.panel:first-child')
      .isVisible('span=In Progress').should.eventually.equal(true)
  ));

  it('displays results', () => (
    app.client
      .click('a=Home')
      .waitForVisible('div.panel:first-child', EXIST_TIMEOUT)
      .element('div.panel:first-child')
      .waitForVisible('a=View Results', COMPUTATION_TIMEOUT)
      .element('div.panel:first-child')
      .click('a=View Results')
      .waitForVisible('h3=Regressions', EXIST_TIMEOUT)
      .isVisible(`span=Results: ${CONS_NAME} || ${PIPE_NAME}`).should.eventually.equal(true)
  ));

  it('deletes consortium', () => (
    app.client
      .click('a=Consortia')
      .waitForVisible(`button[name="${CONS_NAME}-delete"]`, EXIST_TIMEOUT)
      .click(`button[name="${CONS_NAME}-delete"]`)
      .element('.modal-dialog')
      .click('button=Delete')
      .waitForVisible(`h3=${CONS_NAME}`, EXIST_TIMEOUT, true)
  ));

  it('logs out', () => (
    app.client
      .waitForVisible('button=Log Out', EXIST_TIMEOUT)
      .click('button=Log Out')
      .waitForVisible('button=Log In', EXIST_TIMEOUT)
  ));
});
<|endoftext|>


<commit_before>/**
 *
 *  CS3283/4 storage.js
 *  This class acts as a facade for other developers to access to the database.
 *  The implementation is a non-SQL local storage to support the WebApp.
 *
 */

import constants from 'src/database/constants';
import entitiesCreator from 'src/database/create/entitiesCreator';
import query from 'src/database/retrieve/query';
import dataModifier from 'src/database/data-modifier/dataModifier';
import exceptions from 'src/database/exceptions';

let databaseName = constants.INDEXEDDB_NAME;

// dummy function to initialize createTables promises
function initCreateTable() {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      resolve(true);
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

function createUserTable(isUserTableFirstInitialize) {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      if (!isUserTableFirstInitialize) {
        entitiesCreator.createUserTable()
        .then(success => resolve(true))
        .catch(sqlError => reject(sqlError));
      } else {
        resolve('false');
      }
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

function createOrganizationTable(isOrganizationTableFirstInitialize) {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      if (!isOrganizationTableFirstInitialize) {
        entitiesCreator.createOrganizationTable()
        .then(success => resolve(true))
        .catch(sqlError => reject(sqlError));
      } else {
        resolve('false');
      }
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

function createFolderTable(isFolderTableFirstInitialize) {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      if (!isFolderTableFirstInitialize) {
        entitiesCreator.createFolderTable()
        .then(success => resolve(true))
        .catch(sqlError => reject(sqlError));
      } else {
        resolve('false');
      }
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

function createFileManagerTable(isFileTableFirstInitialize) {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      if (!isFileTableFirstInitialize) {
        entitiesCreator.createFileManagerTable()
        .then(success => resolve(true))
        .catch(sqlError => reject(sqlError));
      } else {
        resolve('false');
      }
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

function creationOfTables() {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      initCreateTable()
      .then(() =>
        query.isTableExistsInDatabase(constants.ENTITIES_USER)
        .then(isUserTableFirstInitialize =>
          createUserTable(isUserTableFirstInitialize)
          .then(isSuccess => isSuccess)
          .catch(sqlError => reject(sqlError))
          )
        .catch(sqlError => reject(sqlError))
      )
      .then(() =>
        query.isTableExistsInDatabase(constants.ENTITIES_ORGANIZATION)
        .then(isOrganizationTableFirstInitialize =>
          createOrganizationTable(isOrganizationTableFirstInitialize))
          .then(isSuccess => isSuccess)
          .catch(sqlError => reject(sqlError))
        .catch(sqlError => reject(sqlError))
      )
      .then(() => query.isTableExistsInDatabase(constants.ENTITIES_FOLDER)
        .then(isFolderTableFirstInitialize =>
          createFolderTable(isFolderTableFirstInitialize))
          .then(isSuccess => isSuccess)
          .catch(sqlError => reject(sqlError))
        .catch(sqlError => reject(sqlError))
      )
      .then(() => query.isTableExistsInDatabase(constants.ENTITIES_FILE_MANAGER)
        .then(isFileTableFirstInitialize =>
          createFileManagerTable(isFileTableFirstInitialize)
          .then(isSuccess => isSuccess)
          .catch(sqlError => reject(sqlError)))
        .catch(sqlError => reject(sqlError))
      .then(isSuccess => resolve(isSuccess))
      .catch(sqlError => reject(sqlError))
      );
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

export default class storage {
  static constructor() {}

  static initializeDatabase(newDatabaseName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) => {
        databaseName = newDatabaseName || databaseName;
        entitiesCreator.initializeDatabase(databaseName)
        .then(step1 => creationOfTables()
          .then(isFirstInstance => isFirstInstance)
          .catch(sqlErr => reject(sqlErr)))
        .then((isFirstInstance) => {
          if (typeof isFirstInstance === 'boolean') {
            return entitiesCreator.fillUpDefaultData()
            .then(isFilledUp => resolve(isFilledUp))
            .catch(sqlErr => reject(sqlErr));
          } else {
            return resolve(true);
          }
        })
        .catch(sqlError => reject(sqlError));
      });
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static loadAllFilesAndFolders() {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        query.getAllFilesAndFolders()
        .then(returnedArr => resolve(returnedArr))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  // Searching the filename and foldername ONLY
  static partialSearch(searchString) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        query.searchString(searchString)
        .then(returnedArr => resolve(returnedArr))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static getList(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        query.loadFolder(folderId)
        .then(returnedArr => resolve(returnedArr))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static loadFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        query.loadFile(fileId)
        .then(returnedArr => resolve(returnedArr))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static saveFile(fileId, fileString) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.saveFile(fileId, fileString)
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static createFile(organizationId, filePath, folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.createNewFile(organizationId, filePath, folderId)
        .then(data => resolve(data))
        .catch(err => reject(err))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static deleteFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.deleteFile(fileId)
          .then(data => resolve(true))
          .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static createFolder(organizationId, folderPath, currentFolderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.createNewFolder(organizationId, folderPath, currentFolderId)
        .then(data => resolve(data))
        .catch(err => reject(err))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  // only delete folder for now without cascade delete
  static deleteFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.deleteFolder(folderId)
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static deleteAll(newDatabaseName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) => {
        databaseName = newDatabaseName || databaseName;
        return dataModifier.deleteAllEntities(databaseName)
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError));
      });
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }
}
<commit_msg>Remove initCreateTable function in storage.js<commit_after>/**
 *
 *  CS3283/4 storage.js
 *  This class acts as a facade for other developers to access to the database.
 *  The implementation is a non-SQL local storage to support the WebApp.
 *
 */

import constants from 'src/database/constants';
import entitiesCreator from 'src/database/create/entitiesCreator';
import query from 'src/database/retrieve/query';
import dataModifier from 'src/database/data-modifier/dataModifier';
import exceptions from 'src/database/exceptions';

let databaseName = constants.INDEXEDDB_NAME;

function createUserTable(isUserTableFirstInitialize) {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      if (!isUserTableFirstInitialize) {
        entitiesCreator.createUserTable()
        .then(success => resolve(true))
        .catch(sqlError => reject(sqlError));
      } else {
        resolve('false');
      }
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

function createOrganizationTable(isOrganizationTableFirstInitialize) {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      if (!isOrganizationTableFirstInitialize) {
        entitiesCreator.createOrganizationTable()
        .then(success => resolve(true))
        .catch(sqlError => reject(sqlError));
      } else {
        resolve('false');
      }
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

function createFolderTable(isFolderTableFirstInitialize) {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      if (!isFolderTableFirstInitialize) {
        entitiesCreator.createFolderTable()
        .then(success => resolve(true))
        .catch(sqlError => reject(sqlError));
      } else {
        resolve('false');
      }
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

function createFileManagerTable(isFileTableFirstInitialize) {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      if (!isFileTableFirstInitialize) {
        entitiesCreator.createFileManagerTable()
        .then(success => resolve(true))
        .catch(sqlError => reject(sqlError));
      } else {
        resolve('false');
      }
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

function creationOfTables() {
  if (typeof Promise === 'function') {
    return new Promise((resolve, reject) => {
      query.isTableExistsInDatabase(constants.ENTITIES_USER)
      .then(isUserTableFirstInitialize =>
        createUserTable(isUserTableFirstInitialize)
        .then(isSuccess => isSuccess)
        .catch(sqlError => reject(sqlError))
      )
      .then(() =>
        query.isTableExistsInDatabase(constants.ENTITIES_ORGANIZATION)
        .then(isOrganizationTableFirstInitialize =>
          createOrganizationTable(isOrganizationTableFirstInitialize))
          .then(isSuccess => isSuccess)
          .catch(sqlError => reject(sqlError))
        .catch(sqlError => reject(sqlError))
      )
      .then(() =>
        query.isTableExistsInDatabase(constants.ENTITIES_FOLDER)
        .then(isFolderTableFirstInitialize =>
          createFolderTable(isFolderTableFirstInitialize))
          .then(isSuccess => isSuccess)
          .catch(sqlError => reject(sqlError))
        .catch(sqlError => reject(sqlError))
      )
      .then(() =>
        query.isTableExistsInDatabase(constants.ENTITIES_FILE_MANAGER)
        .then(isFileTableFirstInitialize =>
          createFileManagerTable(isFileTableFirstInitialize)
          .then(isSuccess => isSuccess)
          .catch(sqlError => reject(sqlError))
        )
        .catch(sqlError => reject(sqlError))
      )
      .then(isSuccess => resolve(isSuccess))
      .catch(sqlError => reject(sqlError));
    });
  } else {
    throw new exceptions.PromiseFunctionNotDefined();
  }
}

export default class storage {
  static constructor() {}

  static initializeDatabase(newDatabaseName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) => {
        databaseName = newDatabaseName || databaseName;
        entitiesCreator.initializeDatabase(databaseName)
        .then(step1 => creationOfTables()
          .then(isFirstInstance => isFirstInstance)
          .catch(sqlErr => reject(sqlErr)))
        .then((isFirstInstance) => {
          if (typeof isFirstInstance === 'boolean') {
            return entitiesCreator.fillUpDefaultData()
            .then(isFilledUp => resolve(isFilledUp))
            .catch(sqlErr => reject(sqlErr));
          } else {
            return resolve(true);
          }
        })
        .catch(sqlError => reject(sqlError));
      });
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static loadAllFilesAndFolders() {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        query.getAllFilesAndFolders()
        .then(returnedArr => resolve(returnedArr))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  // Searching the filename and foldername ONLY
  static partialSearch(searchString) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        query.searchString(searchString)
        .then(returnedArr => resolve(returnedArr))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static getList(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        query.loadFolder(folderId)
        .then(returnedArr => resolve(returnedArr))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static loadFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        query.loadFile(fileId)
        .then(returnedArr => resolve(returnedArr))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static saveFile(fileId, fileString) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.saveFile(fileId, fileString)
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static createFile(organizationId, filePath, folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.createNewFile(organizationId, filePath, folderId)
        .then(data => resolve(data))
        .catch(err => reject(err))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static deleteFile(fileId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.deleteFile(fileId)
          .then(data => resolve(true))
          .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static createFolder(organizationId, folderPath, currentFolderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.createNewFolder(organizationId, folderPath, currentFolderId)
        .then(data => resolve(data))
        .catch(err => reject(err))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  // only delete folder for now without cascade delete
  static deleteFolder(folderId) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) =>
        dataModifier.deleteFolder(folderId)
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError))
      );
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }

  static deleteAll(newDatabaseName) {
    if (typeof Promise === 'function') {
      return new Promise((resolve, reject) => {
        databaseName = newDatabaseName || databaseName;
        return dataModifier.deleteAllEntities(databaseName)
        .then(data => resolve(true))
        .catch(sqlError => reject(sqlError));
      });
    } else {
      throw new exceptions.PromiseFunctionNotDefined();
    }
  }
}
<|endoftext|>


<commit_before>// @flow
import {getDetailedBuildingStatus} from '../get-detailed-status'
import {plainMoment} from './moment.helper'

it('returns a list of [isOpen, scheduleName, verboseStatus] tuples', () => {
  let m = plainMoment('06-23-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo', 'Tu', 'We', 'Th'], from: '10:30am', to: '12:00am'},
          {days: ['Fr', 'Sa'], from: '10:30am', to: '2:00am'},
          {days: ['Su'], from: '10:30am', to: '12:00am'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)

  expect(actual).toBeInstanceOf(Array)
  expect(actual.length).toEqual(1)
  expect(typeof actual[0].isActive).toBe('boolean')
  expect(typeof actual[0].label).toBe('string')
  expect(typeof actual[0].status).toBe('string')

  expect(actual).toMatchSnapshot()
})

it('checks a list of schedules to see if any are open', () => {
  let m = plainMoment('06-23-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo', 'Tu', 'We', 'Th'], from: '10:30am', to: '12:00am'},
          {days: ['Fr', 'Sa'], from: '10:30am', to: '2:00am'},
          {days: ['Su'], from: '10:30am', to: '12:00am'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(true)
})

it('handles multiple internal schedules for the same timeframe', () => {
  let m = plainMoment('06-19-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo'], from: '10:30am', to: '12:00pm'},
          {days: ['Mo'], from: '1:00pm', to: '3:00pm'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(false)
  expect(actual[1].isActive).toBe(true)
})

it('handles multiple named schedules for the same timeframe', () => {
  let m = plainMoment('06-19-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [{days: ['Mo'], from: '10:30am', to: '12:00pm'}],
      },
      {
        title: 'Hours2',
        hours: [
          {days: ['Mo'], from: '10:30am', to: '12:00pm'},
          {days: ['Mo'], from: '1:00pm', to: '3:00pm'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(false)
  expect(actual[1].isActive).toBe(false)
  expect(actual[2].isActive).toBe(true)
})

it('returns false if none are available for this day', () => {
  let m = plainMoment('06-18-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo', 'Tu', 'We', 'Th'], from: '10:30am', to: '12:00am'},
          {days: ['Fr', 'Sa'], from: '10:30am', to: '2:00am'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(false)
})

it('returns false if none are open', () => {
  let m = plainMoment('06-19-2018 3:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo', 'Tu', 'We', 'Th'], from: '10:30am', to: '2:00pm'},
          {days: ['Fr', 'Sa'], from: '10:30am', to: '2:00pm'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(false)
})
<commit_msg>Tweak days in snapshot test examples to match the same week in 2018<commit_after>// @flow
import {getDetailedBuildingStatus} from '../get-detailed-status'
import {plainMoment} from './moment.helper'

it('returns a list of [isOpen, scheduleName, verboseStatus] tuples', () => {
  let m = plainMoment('06-23-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo', 'Tu', 'We', 'Th'], from: '10:30am', to: '12:00am'},
          {days: ['Fr', 'Sa'], from: '10:30am', to: '2:00am'},
          {days: ['Su'], from: '10:30am', to: '12:00am'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)

  expect(actual).toBeInstanceOf(Array)
  expect(actual.length).toEqual(1)
  expect(typeof actual[0].isActive).toBe('boolean')
  expect(typeof actual[0].label).toBe('string')
  expect(typeof actual[0].status).toBe('string')

  expect(actual).toMatchSnapshot()
})

it('checks a list of schedules to see if any are open', () => {
  let m = plainMoment('06-23-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo', 'Tu', 'We', 'Th'], from: '10:30am', to: '12:00am'},
          {days: ['Fr', 'Sa'], from: '10:30am', to: '2:00am'},
          {days: ['Su'], from: '10:30am', to: '12:00am'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(true)
})

it('handles multiple internal schedules for the same timeframe', () => {
  let m = plainMoment('06-18-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo'], from: '10:30am', to: '12:00pm'},
          {days: ['Mo'], from: '1:00pm', to: '3:00pm'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(false)
  expect(actual[1].isActive).toBe(true)
})

it('handles multiple named schedules for the same timeframe', () => {
  let m = plainMoment('06-18-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [{days: ['Mo'], from: '10:30am', to: '12:00pm'}],
      },
      {
        title: 'Hours2',
        hours: [
          {days: ['Mo'], from: '10:30am', to: '12:00pm'},
          {days: ['Mo'], from: '1:00pm', to: '3:00pm'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(false)
  expect(actual[1].isActive).toBe(false)
  expect(actual[2].isActive).toBe(true)
})

it('returns false if none are available for this day', () => {
  let m = plainMoment('06-17-2018 1:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo', 'Tu', 'We', 'Th'], from: '10:30am', to: '12:00am'},
          {days: ['Fr', 'Sa'], from: '10:30am', to: '2:00am'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(false)
})

it('returns false if none are open', () => {
  let m = plainMoment('06-19-2018 3:00pm', 'MM-DD-YYYY h:mma')
  let building = {
    name: 'building',
    category: '???',
    breakSchedule: {},
    schedule: [
      {
        title: 'Hours',
        hours: [
          {days: ['Mo', 'Tu', 'We', 'Th'], from: '10:30am', to: '2:00pm'},
          {days: ['Fr', 'Sa'], from: '10:30am', to: '2:00pm'},
        ],
      },
    ],
  }

  const actual = getDetailedBuildingStatus(building, m)
  expect(actual).toMatchSnapshot()

  expect(actual[0].isActive).toBe(false)
})
<|endoftext|>


<commit_before>import patch from './module';

const parse = require('parametric-svg-parse');
const test = require('tape-catch');
const {safeLoad: yaml} = require('js-yaml');
const {jsdom} = require('jsdom');
const {DOMParser: XmldomParser} = require('xmldom');
const asObject = require('as/object');
const asArray = require('as/array');

const wrap = (element) => (
`<svg
  version="1.1"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:parametric="//parametric-svg.js.org/v1"
>${element}</svg>
`);

if (typeof require.ensure !== 'function') require.ensure =
  require('isomorphic-ensure')({
    loaders: {
      raw: require('raw-loader'),
    },
    dirname: __dirname,
  });

require.ensure([
  'raw!parametric-svg-spec/specs/usage-html5.yaml',
  'raw!parametric-svg-spec/specs/usage-xml.yaml',
  'raw!parametric-svg-spec/specs/parametric-attributes.yaml',
  'raw!parametric-svg-spec/specs/syntax-operators.yaml',
  'raw!parametric-svg-spec/specs/syntax-variables.yaml',
    // NOTE: These paths have to be hard-coded in stone – otherwise webpack
    // gets confused. Remember to keep them in sync with the `require`
    // calls below.
], (require) => {
  const specs = [
    require('raw!parametric-svg-spec/specs/usage-html5.yaml'),
    require('raw!parametric-svg-spec/specs/usage-xml.yaml'),
    require('raw!parametric-svg-spec/specs/parametric-attributes.yaml'),
    require('raw!parametric-svg-spec/specs/syntax-operators.yaml'),
    require('raw!parametric-svg-spec/specs/syntax-variables.yaml'),
      // NOTE: See above.
  ].map(yaml);

  specs.forEach(({
    name,
    tests,
    mode,
  }) => tests.forEach(({
    description,
    original,
    example_data: data,
    example_output: expected,
  }) => {
    test(`${name}: ${description}`, (is) => {
      const inBrowser = typeof window !== 'undefined' && window.DOMParser;

      const htmlMode = mode === 'HTML5 document';
      const xmlMode = mode === 'XML document';
      const elementMode = mode === 'Element';
      if (!htmlMode && !xmlMode && !elementMode) throw new Error(
        'Unknown test mode'
      );

      const contentType = (htmlMode ?
        'text/html' :
        'application/xml'
      );

      const Parser = (inBrowser ?
        window.DOMParser :
        XmldomParser
      );

      const toString = (
        (htmlMode &&
          ((node) => node.outerHTML)
        ) ||
        (inBrowser &&
          ((node) => (new window.XMLSerializer()).serializeToString(node))
        ) ||
        String
      );

      const rootElements = asObject(asArray({
        original,
        expected,
      }).map(({key, value}) => {
        const documentSource = (elementMode ?
          wrap(value) :
          value
        );

        const document = (!inBrowser && htmlMode ?
          jsdom(documentSource).defaultView.document :
          (new Parser()).parseFromString(documentSource, contentType)
        ).documentElement;

        return {key, value: (elementMode ?
          document.firstChild :
          document
        )};
      }));

      const ast = parse(rootElements.original);
      patch(rootElements.original, ast, data);

      is.equal(
        toString(rootElements.original),
        toString(rootElements.expected),
        'expected output matches'
      );

      is.end();
    });
  }));
});
<commit_msg>Include new specs in patch<commit_after>import patch from './module';

const parse = require('parametric-svg-parse');
const test = require('tape-catch');
const {safeLoad: yaml} = require('js-yaml');
const {jsdom} = require('jsdom');
const {DOMParser: XmldomParser} = require('xmldom');
const asObject = require('as/object');
const asArray = require('as/array');

const wrap = (element) => (
`<svg
  version="1.1"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:parametric="//parametric-svg.js.org/v1"
>${element}</svg>
`);

if (typeof require.ensure !== 'function') require.ensure =
  require('isomorphic-ensure')({
    loaders: {
      raw: require('raw-loader'),
    },
    dirname: __dirname,
  });

require.ensure([
  'raw!parametric-svg-spec/specs/usage-html5.yaml',
  'raw!parametric-svg-spec/specs/usage-xml.yaml',
  'raw!parametric-svg-spec/specs/parametric-attributes.yaml',
  'raw!parametric-svg-spec/specs/syntax-operators.yaml',
  'raw!parametric-svg-spec/specs/syntax-template-strings.yaml',
  'raw!parametric-svg-spec/specs/syntax-types.yaml',
  'raw!parametric-svg-spec/specs/syntax-variables.yaml',
    // NOTE: These paths have to be hard-coded in stone – otherwise webpack
    // gets confused. Remember to keep them in sync with the `require`
    // calls below.
], (require) => {
  const specs = [
    require('raw!parametric-svg-spec/specs/usage-html5.yaml'),
    require('raw!parametric-svg-spec/specs/usage-xml.yaml'),
    require('raw!parametric-svg-spec/specs/parametric-attributes.yaml'),
    require('raw!parametric-svg-spec/specs/syntax-operators.yaml'),
    require('raw!parametric-svg-spec/specs/syntax-template-strings.yaml'),
    require('raw!parametric-svg-spec/specs/syntax-types.yaml'),
    require('raw!parametric-svg-spec/specs/syntax-variables.yaml'),
      // NOTE: See above.
  ].map(yaml);

  specs.forEach(({
    name,
    tests,
    mode,
  }) => tests.forEach(({
    description,
    original,
    example_data: data,
    example_output: expected,
  }) => {
    test(`${name}: ${description}`, (is) => {
      const inBrowser = typeof window !== 'undefined' && window.DOMParser;

      const htmlMode = mode === 'HTML5 document';
      const xmlMode = mode === 'XML document';
      const elementMode = mode === 'Element';
      if (!htmlMode && !xmlMode && !elementMode) throw new Error(
        'Unknown test mode'
      );

      const contentType = (htmlMode ?
        'text/html' :
        'application/xml'
      );

      const Parser = (inBrowser ?
        window.DOMParser :
        XmldomParser
      );

      const toString = (
        (htmlMode &&
          ((node) => node.outerHTML)
        ) ||
        (inBrowser &&
          ((node) => (new window.XMLSerializer()).serializeToString(node))
        ) ||
        String
      );

      const rootElements = asObject(asArray({
        original,
        expected,
      }).map(({key, value}) => {
        const documentSource = (elementMode ?
          wrap(value) :
          value
        );

        const document = (!inBrowser && htmlMode ?
          jsdom(documentSource).defaultView.document :
          (new Parser()).parseFromString(documentSource, contentType)
        ).documentElement;

        return {key, value: (elementMode ?
          document.firstChild :
          document
        )};
      }));

      const ast = parse(rootElements.original);
      patch(rootElements.original, ast, data);

      is.equal(
        toString(rootElements.original),
        toString(rootElements.expected),
        'expected output matches'
      );

      is.end();
    });
  }));
});
<|endoftext|>


<commit_before>/*
  Wrapper for enabling/disabling ember addon build output based on
  whether the addon is enabled in cardstack hub.
*/
const ConditionalInclude = require('./conditional-include');
const hub = require('@cardstack/plugin-utils/locate-hub');
const request = require('superagent');

const treeMethods = [
  'treeForAddon',
  'treeForAddonTemplates',
  'treeForAddonTestSupport',
  'treeForApp',
  'treeForPublic',
  'treeForStyles',
  'treeForTemplates',
  'treeForTestSupport',
  'treeForVendor'
];

module.exports = function whenEnabled(plugin) {
  async function enabled() {
    let baseURL = await hub().url();
    let url = `${baseURL}/api/plugins/${encodeURIComponent(plugin.name)}`;
    let response;
    try {
      response = await request.get(url);
    } catch (err) {
      throw new Error(`Unable to check whether plugin ${plugin.name} is enabled: got exception ${err.message} from ${url}`);
    }
    if (response.status !== 200) {
      throw new Error(`Unable to check whether plugin ${plugin.name} is enabled: got status ${response.status} from ${url}`);
    }
    return response.body.data.attributes.enabled;
  }

  function gate(methodName) {
    return function(tree) {
      let func = plugin[methodName] || this._super;
      let upstreamTree = func.call(this, tree);
      if (upstreamTree) {
        return new ConditionalInclude(upstreamTree, { predicate: enabled, name: plugin.name });
      }
    };
  }

  let overrides = {};
  for (let method of treeMethods) {
    overrides[method] = gate(method);
  }
  return Object.assign({}, plugin, overrides);
};
<commit_msg>don't break when no hub is configured at all<commit_after>/*
  Wrapper for enabling/disabling ember addon build output based on
  whether the addon is enabled in cardstack hub.
*/
const ConditionalInclude = require('./conditional-include');
const hub = require('@cardstack/plugin-utils/locate-hub');
const request = require('superagent');

const treeMethods = [
  'treeForAddon',
  'treeForAddonTemplates',
  'treeForAddonTestSupport',
  'treeForApp',
  'treeForPublic',
  'treeForStyles',
  'treeForTemplates',
  'treeForTestSupport',
  'treeForVendor'
];

module.exports = function whenEnabled(plugin) {
  async function enabled() {
    let baseURL = await hub().url();
    if (!baseURL) {
      // no hub is configured. so there can't be any config in that
      // hub disabling any plugins, so we default to enabled.
      return true;
    }
    let url = `${baseURL}/api/plugins/${encodeURIComponent(plugin.name)}`;
    let response;
    try {
      response = await request.get(url);
    } catch (err) {
      throw new Error(`Unable to check whether plugin ${plugin.name} is enabled: got exception ${err.message} from ${url}`);
    }
    if (response.status !== 200) {
      throw new Error(`Unable to check whether plugin ${plugin.name} is enabled: got status ${response.status} from ${url}`);
    }
    return response.body.data.attributes.enabled;
  }

  function gate(methodName) {
    return function(tree) {
      let func = plugin[methodName] || this._super;
      let upstreamTree = func.call(this, tree);
      if (upstreamTree) {
        return new ConditionalInclude(upstreamTree, { predicate: enabled, name: plugin.name });
      }
    };
  }

  let overrides = {};
  for (let method of treeMethods) {
    overrides[method] = gate(method);
  }
  return Object.assign({}, plugin, overrides);
};
<|endoftext|>