<commit_before>var https = require('https');

module.exports = function(riotOptions) {
	return {
		get: function(id, cb) {
			var tempPath = '/api/lol/';
			switch(riotOptions.type) {
				case "match":
					tempPath = tempPath + riotOptions.region + '/v2.2/match/' + id + '?includeTimeline=true';
					break;
				case "champion":
					tempPath = temptPath + 'static-data/' + riotOptions.region + '/v1.2/champion/' + id + '?champData=image";
					break;
			}
			var options = {
				hostname: 'na.api.pvp.net',
				port: '443',
				method: 'GET',
				path: tempPath,
				headers: {
					'X-Riot-Token': riotOptions.key
				}
			};
			https.request(options, function(res) {
				var data = '';
				res.on('data', function(chunk) {
					data += chunk;
				});
				res.on('end', function() {
					cb(JSON.parse(data));

				});
			}).end();
		}
	}
};<commit_msg>typo fix<commit_after>var https = require('https');

module.exports = function(riotOptions) {
	return {
		get: function(id, cb) {
			var tempPath = '/api/lol/';
			switch(riotOptions.type) {
				case "match":
					tempPath = tempPath + riotOptions.region + '/v2.2/match/' + id + '?includeTimeline=true';
					break;
				case "champion":
					tempPath = temptPath + 'static-data/' + riotOptions.region + '/v1.2/champion/' + id + '?champData=image';
					break;
			}
			var options = {
				hostname: 'na.api.pvp.net',
				port: '443',
				method: 'GET',
				path: tempPath,
				headers: {
					'X-Riot-Token': riotOptions.key
				}
			};
			https.request(options, function(res) {
				var data = '';
				res.on('data', function(chunk) {
					data += chunk;
				});
				res.on('end', function() {
					cb(JSON.parse(data));

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


<commit_before>// Copyright (c) 2012 HIRAKI Satoru, https://github.com/Layzie
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

(function(window, undefined) {
  'use strict';

  (function _init() {
    if (window.localStorage && window.sessionStorage) {
      if (_checkArgument('Undefined', window.RS)) {
        window.RS = {};
      }

      window.RS = {
        put: put,
        get: get,
        remove: remove,
        clear: clear,
        is: is
      };
    } else {
      throw new Error('RS: This browser have no storage.');
    }
  })();

  function _selectStorage(flag, fun) {
    var storage;

    if (!_checkArgument('Boolean', flag) && flag !== undefined) {
      throw new Error('RS.' + fun + ': 2nd argument should be boolean');
    } else {
      storage = (flag === true || flag === undefined) ? localStorage : sessionStorage;
    }

    return storage;
  }

  function _checkArgument(type, argument) {
    var object = Object.prototype.toString.call(argument).slice(8, -1);

    return argument !== undefined && argument !== null && object === type;
  }

  function put(obj, flag) {
    var storage = _selectStorage(flag, 'put()');

    if (_checkArgument('Object', obj) && !_checkArgument('Array', obj)) {
      for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
          storage.setItem(i, JSON.stringify(obj[i]));
        }
      }
    } else {
      throw new Error('RS.put(): 1st argument should be object');
    }
  }

  function get(key, flag) {
    var storage = _selectStorage(flag, 'get()'),
        selectKey = storage.getItem(key);

    if (_checkArgument('String', key)) {
      if (selectKey) {
        return JSON.parse(selectKey);
      } else {
        return console.log('RS.get(): This key is not in storage');
      }
    } else {
      throw new Error('RS.get(): 1st argument should be string');
    }
  }

  function remove(key, flag) {
    var storage = _selectStorage(flag, 'remove()'),
        selectKey = storage.getItem(key);

    if (_checkArgument('String', key)) {
      if (selectKey) {
        storage.removeItem(key);
      } else {
        console.log('RS.remove(): This key is not in storage');
      }
    }
  }

  function clear(flag) {
    var storage = _selectStorage(flag, 'clear()');

    storage.clear();
  }

  function is(key, flag) {
    var storage = _selectStorage(flag, 'is()'),
        selectKey = storage.getItem(key);

    if (_checkArgument('String', key)) {
      if (selectKey) {
        return true;
      } else {
        return false;
      }
    } else {
      throw new Error('RS.is(): 1st argument should be strings');
    }
  }
})(this);

<commit_msg>fix return statement's place<commit_after>// Copyright (c) 2012 HIRAKI Satoru, https://github.com/Layzie
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

(function(window, undefined) {
  'use strict';

  (function _init() {
    if (window.localStorage && window.sessionStorage) {
      if (_checkArgument('Undefined', window.RS)) {
        window.RS = {};
      }

      window.RS = {
        put: put,
        get: get,
        remove: remove,
        clear: clear,
        is: is
      };
    } else {
      throw new Error('RS: This browser have no storage.');
    }
  })();

  function _selectStorage(flag, fun) {
    var storage;

    if (!_checkArgument('Boolean', flag) && flag !== undefined) {
      throw new Error('RS.' + fun + ': 2nd argument should be boolean');
    } else {
      storage = (flag === true || flag === undefined) ? localStorage : sessionStorage;

      return storage;
    }
  }

  function _checkArgument(type, argument) {
    var object = Object.prototype.toString.call(argument).slice(8, -1);

    return argument !== undefined && argument !== null && object === type;
  }

  function put(obj, flag) {
    var storage = _selectStorage(flag, 'put()');

    if (_checkArgument('Object', obj) && !_checkArgument('Array', obj)) {
      for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
          storage.setItem(i, JSON.stringify(obj[i]));
        }
      }
    } else {
      throw new Error('RS.put(): 1st argument should be object');
    }
  }

  function get(key, flag) {
    var storage = _selectStorage(flag, 'get()'),
        selectKey = storage.getItem(key);

    if (_checkArgument('String', key)) {
      if (selectKey) {
        return JSON.parse(selectKey);
      } else {
        return console.log('RS.get(): This key is not in storage');
      }
    } else {
      throw new Error('RS.get(): 1st argument should be string');
    }
  }

  function remove(key, flag) {
    var storage = _selectStorage(flag, 'remove()'),
        selectKey = storage.getItem(key);

    if (_checkArgument('String', key)) {
      if (selectKey) {
        storage.removeItem(key);
      } else {
        console.log('RS.remove(): This key is not in storage');
      }
    }
  }

  function clear(flag) {
    var storage = _selectStorage(flag, 'clear()');

    storage.clear();
  }

  function is(key, flag) {
    var storage = _selectStorage(flag, 'is()'),
        selectKey = storage.getItem(key);

    if (_checkArgument('String', key)) {
      if (selectKey) {
        return true;
      } else {
        return false;
      }
    } else {
      throw new Error('RS.is(): 1st argument should be strings');
    }
  }
})(this);

<|endoftext|>


<commit_before>/**
 * UI and function to quick search projects
 */

var $ = require('jquery');
var m = require('mithril');
var $osf = require('js/osfHelpers');
var nodeModule = require('js/quickProjectSearchPlugin');

// XHR config for apiserver connection
var xhrconfig = function(xhr) {
    xhr.withCredentials = true;
};

var newAndNoteworthy = {
    controller: function() {
    },
    view : function(ctrl) {

    }
};

module.exports = newAndNoteworthy;

<commit_msg>Start new/noteworthy view template.<commit_after>/**
 * UI and function to quick search projects
 */

var $ = require('jquery');
var m = require('mithril');
var $osf = require('js/osfHelpers');
var nodeModule = require('js/quickProjectSearchPlugin');

// XHR config for apiserver connection
var xhrconfig = function(xhr) {
    xhr.withCredentials = true;
};

var newAndNoteworthy = {
    controller: function() {

    },
    view : function(ctrl) {
        function newProjectsTemplate () {
            return m('h1', 'Node')

        }
        function noteworthyProjectsTemplate() {
            return m('h1', 'Nodes')

        }
        return m('div', {class: 'container'}, [
            m('div', {class: 'row'}, m('div', {class: 'col-sm-12'}, m('h4', 'Discover Public Projects'))),
            m('div', {class: 'row'},
                m('div', {class: 'col-sm-6'}, [m('h5', 'New'), newProjectsTemplate() ]),
                m('div', {class: 'col-sm-6'}, [m('h5', 'Noteworthy', noteworthyProjectsTemplate())])
            )
        ])
    }
};

module.exports = newAndNoteworthy;

<|endoftext|>


<commit_before>// 'use strict';

var schedule = require('node-schedule');
var slack = require('./slack.js');

module.exports = scheduler;

function scheduler() {
  var hrr11 = slack.students.getChannelGroupOrDMByName('hrr11');
  var hrr12 = slack.students.getChannelGroupOrDMByName('hrr12');
  var hrr13 = slack.students.getChannelGroupOrDMByName('hrr13');
  var general = slack.students.getChannelGroupOrDMByName('general');

  var date = new Date(2016, 01, 09, 23, 00, 0);
  var date2 = new Date(2016, 01, 09, 22, 50, 0);

  var j = schedule.scheduleJob(date, function(){
    var msg = '<!channel> https://zoom.us/j/525181230 Join us for the After Hours talk tonight where <@codydaig> will take us on a deep dive into express. He\'ll be walking us through how to set-up a brand new express app as well as conceptually what express is doing under the hood.';
    hrr11.send(msg);
    hrr12.send(msg);
    hrr13.send(msg);
  }.bind(this));

  var k = schedule.scheduleJob(date, function(){
    var msg = '<!channel> Friendly reminder that there is an after hours talk tonight on a Express! <@codydaig> will take us on a deep dive into express. He\'ll be walking us through how to set-up a brand new express app as well as conceptually what express is doing under the hood.';
    hrr11.send(msg);
    hrr12.send(msg);
    hrr13.send(msg);
  }.bind(this));
}
<commit_msg>debugging<commit_after>// 'use strict';

var schedule = require('node-schedule');
var slack = require('./slack.js');

module.exports = scheduler;

function scheduler() {
  var hrr11 = slack.students.getChannelGroupOrDMByName('hrr11');
  var hrr12 = slack.students.getChannelGroupOrDMByName('hrr12');
  var hrr13 = slack.students.getChannelGroupOrDMByName('hrr13');
  var general = slack.students.getChannelGroupOrDMByName('general');

  var date = new Date(2016, 01, 09, 23, 00, 0);
  var date2 = new Date(2016, 01, 09, 22, 55, 0);

  var j = schedule.scheduleJob(date, function(){
    var msg = '<!channel> https://zoom.us/j/525181230 Join us for the After Hours talk tonight where <@codydaig> will take us on a deep dive into express. He\'ll be walking us through how to set-up a brand new express app as well as conceptually what express is doing under the hood.';
    hrr11.send(msg);
    hrr12.send(msg);
    hrr13.send(msg);
  }.bind(this));

  var k = schedule.scheduleJob(date2, function(){
    var msg = '<!channel> Friendly reminder that there is an after hours talk tonight on a Express! <@codydaig> will take us on a deep dive into express. He\'ll be walking us through how to set-up a brand new express app as well as conceptually what express is doing under the hood.';
    hrr11.send(msg);
    hrr12.send(msg);
    hrr13.send(msg);
  }.bind(this));
}
<|endoftext|>


<commit_before>/* MMM-SL-PublicTransport.js
 *
 * Magic Mirror module - Display public transport in Stockholm/Sweden.
 * This module use the API's provided by Trafiklab.
 *
 * Magic Mirror
 * Module: MMM-SL-PublicTransport
 *
 * Magic Mirror By Michael Teeuw http://michaelteeuw.nl
 * MIT Licensed.
 *
 * Module MMM-SL-PublicTransport By Anders Boghammar
 *
 * Notifications:
 *      GET_DEPARTURES: Is sent when the module wants to get an updated departures list
 *      DEPARTURES: Is sent when there is an updated departures list
 */

Module.register("MMM-SL-PublicTransport", {

    // --------------------------------------- Define module defaults
    defaults: {
        apikey: 'PleaseProvideYourOwn',
        stationid: '',
        stationname: '',
        updateInterval: 5 * 60 * 1000,
        uiUpdateInterval: 1000,
        direction: '',
        lines: [],
        showdisturbances: false,
        fade: true,
        fadePoint: 0.2,
        displaycount: 10,
        SSL: true,
    },

    // --------------------------------------- Define required scripts
    getScripts: function () {
        return [
            //this.file('timehandler.js')
            'moment.js'
        ];
    },
    // --------------------------------------- Define required stylesheets
    /*    getStyles: function() {
            return ["MMM-SL-PublicTransport.css", "font-awesome.css"];
        },
    */
    // --------------------------------------- Get header
    getHeader: function () {
        if (this.currentDepartures !== undefined) {
            var format = (this.config.debug ? 'HH:mm:ss' : 'HH:mm');
            return this.data.header + " " + this.config.stationname + " "
                + (this.loaded ? '('
                    + moment(this.currentDepartures.LatestUpdate).format(format) + ')'
                    + (this.config.debug ? '/('+moment(this.currentDepartures.obtained).format(format)+')' : '')
                    : ""
                );
        } else {
            return this.data.header + " " + this.config.stationname ;
        }
    },

    // --------------------------------------- Start the module
    start: function () {
        Log.info("Starting module: " + this.name);

        // Set locale.
        moment.locale(config.language);

        this.loaded = false;
        this.sendSocketNotification('CONFIG', this.config); // Send config to helper and initiate an update

        // Start timer for ui-updates
        var self = this;
        this.uitimer = setInterval(function () { // This timer is saved in uitimer so that we can cancel it
            self.updateDom();
        }, self.config.uiUpdateInterval);
    },

    // --------------------------------------- Generate dom for module
    getDom: function () {
        var wrapper = document.createElement("div");
        if (this.config.apikey === "" || this.config.apikey === 'PleaseProvideYourOwn') {
            wrapper.innerHTML = this.name + ": Please set API key in config.js.";
            wrapper.className = "dimmed light small";
            return wrapper;
        }
        if (!this.loaded) {
            wrapper.innerHTML = "Loading connections ...";
            wrapper.className = "dimmed light small";
            return wrapper;
        }
        // ------- Create departure table
        var table = document.createElement("table");
        table.className = "xsmall";

        // ------ Table header
        var row = document.createElement("tr");
        var th = document.createElement("th");
        th.innerHTML = "Line "
        th.className = 'align-left';
        row.appendChild(th);
        th = document.createElement("th");
        th.innerHTML = "Destination"
        th.className = 'align-left';
        row.appendChild(th);
        th = document.createElement("th");
        th.innerHTML = "Departure"
        row.appendChild(th);
        table.appendChild(row);

        if (this.currentDepartures !== undefined) {
            // ------ Fill in departures
            this.cdir = -1;
            var displayCount = 0;
            for (var ix = 0; ix < this.currentDepartures.departures.length; ix++) {
                var dep = this.currentDepartures.departures[ix];
                if (this.cdir != -1 && this.cdir != dep.JourneyDirection) {
                    // We are changing direction, create an empty row to separate the two directions
                    this.cdir = dep.JourneyDirection;
                    var row = document.createElement("tr");
                    row.className = 'sup';
                    var td = document.createElement("td");
                    td.colSpan = 3;
                    td.innerHTML = ' ';
                    row.appendChild(td);
                    table.appendChild(row);
                    displayCount = 0; // Restart count of number of items to display for this new direction
                }
                displayCount++;
                if (displayCount <= this.config.displaycount) { // Only show displaycount entries
                    if (this.cdir == -1) this.cdir = dep.JourneyDirection;
                    var row = document.createElement("tr");
                    var td = document.createElement("td");
                    td.className = 'align-left';
                    td.innerHTML = dep.LineNumber;
                    row.appendChild(td);
                    td = document.createElement("td");
                    td.innerHTML = dep.Destination;
                    td.className = 'align-left';
                    row.appendChild(td);
                    td = this.getDepartureTime(dep.TimeTabledDateTime, dep.ExpectedDateTime);
                    row.appendChild(td);
                    table.appendChild(row);
                    this.setFade(row, /*ix*/displayCount, /*this.currentDepartures.departures.length*/this.config.displaycount, this.config.fade, this.config.fadePoint);
                }
            }
        }
        wrapper.appendChild(table);

        // ----- Show service failure if any
        if (this.failure !== undefined) {
            var div = document.createElement("div");
            var msg = (this.failure.resp.Message.Message !== undefined ? this.failure.resp.Message : this.failure.resp.Message.message );
            div.innerHTML = moment(new Date()).format('HH:mm') +" Service: " + this.failure.resp.StatusCode + '-' + msg;
            div.style.color = "red"; // TODO Change this to a custom style
            div.className = "xsmall";
            wrapper.appendChild(div);
        }

        return wrapper;
    },

    // --------------------------------------- Calculate departure time
    // Returns a HTML element that shall be added to the current row
    getDepartureTime: function (tableTime, expectedTime) {
        var td = document.createElement("td");
        if (tableTime == expectedTime) { // There's no delay
            td.innerHTML = this.timeRemaining(moment(tableTime));
        } else {
            td.innerHTML = this.timeRemaining(moment(expectedTime)) + ' ';
            var sp = document.createElement("span");
            sp.innerHTML = this.timeRemaining(moment(tableTime), true);
            sp.style.textDecoration = "line-through" // TODO Change this to a custom style
            td.appendChild(sp);
        }
        td.className = "align-right bright";
        return td;
    },

    // --------------------------------------- Get a human readable duration
    // Dont like the moment.js humanize stuff, too lonmg in swedish and too crud.
    timeRemaining: function (tt, noPrefix) {
        var now = moment();
        var dur = tt.diff(now, 'seconds');

        if (dur < 0) return 'left';
        if (dur < 30) return 'now';
        if (30 <= dur && dur < 60) return (noPrefix ? '' : 'in ') + ' 1 min';
        if (60 <= dur && dur < 15 * 60) return (noPrefix ? '' : 'in ') + Math.round(dur / 60) + ' min';

        return (noPrefix ? '' : 'at ') + tt.format('HH:mm');
    },

    // --------------------------------------- Are we asking for this direction
    isWantedDirection: function (dir) {
        if (this.config.direction !== undefined && this.config.direction != '') {
            return dir == this.config.direction;
        }
        return true;
    },

    // --------------------------------------- Handle table fading
    setFade: function (row, ix, len, fade, fadePoint) {
        if (fade && fadePoint < 1) {
            if (fadePoint < 0) {
                fadePoint = 0;
            }
            var startingPoint = len * fadePoint;
            var steps = len - startingPoint;
            if (ix >= startingPoint) {
                var currentStep = ix - startingPoint;
                row.style.opacity = 1 - (1 / steps * currentStep);
            }
        }
    },
    // --------------------------------------- Handle socketnotifications
    socketNotificationReceived: function (notification, payload) {
        if (notification === "DEPARTURES") {
            this.loaded = true;
            this.failure = undefined;
            // Handle payload
            this.currentDepartures = payload;
            Log.info("Departures updated: " + this.currentDepartures.departures.length);
            this.currentDepartures.obtained = new Date();
            this.updateDom();
        }
        if (notification == "SERVICE_FAILURE") {
            this.loaded = true;
            this.failure = payload;
            Log.info("Service failure: " + this.failure.resp.StatusCode + ':' + this.failure.resp.Message);
            this.updateDom();
        }
    }
})<commit_msg>Handle opacity (fading) better<commit_after>/* MMM-SL-PublicTransport.js
 *
 * Magic Mirror module - Display public transport in Stockholm/Sweden.
 * This module use the API's provided by Trafiklab.
 *
 * Magic Mirror
 * Module: MMM-SL-PublicTransport
 *
 * Magic Mirror By Michael Teeuw http://michaelteeuw.nl
 * MIT Licensed.
 *
 * Module MMM-SL-PublicTransport By Anders Boghammar
 *
 * Notifications:
 *      GET_DEPARTURES: Is sent when the module wants to get an updated departures list
 *      DEPARTURES: Is sent when there is an updated departures list
 */

Module.register("MMM-SL-PublicTransport", {

    // --------------------------------------- Define module defaults
    defaults: {
        apikey: 'PleaseProvideYourOwn',
        stationid: '',
        stationname: '',
        updateInterval: 5 * 60 * 1000,
        uiUpdateInterval: 1000,
        direction: '',
        lines: [],
        showdisturbances: false,
        fade: true,
        fadePoint: 0.2,
        displaycount: 10,
        SSL: true,
    },

    // --------------------------------------- Define required scripts
    getScripts: function () {
        return [
            //this.file('timehandler.js')
            'moment.js'
        ];
    },
    // --------------------------------------- Define required stylesheets
    /*    getStyles: function() {
            return ["MMM-SL-PublicTransport.css", "font-awesome.css"];
        },
    */
    // --------------------------------------- Get header
    getHeader: function () {
        if (this.currentDepartures !== undefined) {
            var format = (this.config.debug ? 'HH:mm:ss' : 'HH:mm');
            return this.data.header + " " + this.config.stationname + " "
                + (this.loaded ? '('
                    + moment(this.currentDepartures.LatestUpdate).format(format) + ')'
                    + (this.config.debug ? '/('+moment(this.currentDepartures.obtained).format(format)+')' : '')
                    : ""
                );
        } else {
            return this.data.header + " " + this.config.stationname ;
        }
    },

    // --------------------------------------- Start the module
    start: function () {
        Log.info("Starting module: " + this.name);

        // Set locale.
        moment.locale(config.language);

        this.loaded = false;
        this.sendSocketNotification('CONFIG', this.config); // Send config to helper and initiate an update

        // Start timer for ui-updates
        var self = this;
        this.uitimer = setInterval(function () { // This timer is saved in uitimer so that we can cancel it
            self.updateDom();
        }, self.config.uiUpdateInterval);
    },

    // --------------------------------------- Generate dom for module
    getDom: function () {
        var wrapper = document.createElement("div");
        if (this.config.apikey === "" || this.config.apikey === 'PleaseProvideYourOwn') {
            wrapper.innerHTML = this.name + ": Please set API key in config.js.";
            wrapper.className = "dimmed light small";
            return wrapper;
        }
        if (!this.loaded) {
            wrapper.innerHTML = "Loading connections ...";
            wrapper.className = "dimmed light small";
            return wrapper;
        }
        // ------- Create departure table
        var table = document.createElement("table");
        table.className = "xsmall";

        // ------ Table header
        var row = document.createElement("tr");
        var th = document.createElement("th");
        th.innerHTML = "Line "
        th.className = 'align-left';
        row.appendChild(th);
        th = document.createElement("th");
        th.innerHTML = "Destination"
        th.className = 'align-left';
        row.appendChild(th);
        th = document.createElement("th");
        th.innerHTML = "Departure"
        row.appendChild(th);
        table.appendChild(row);

        if (this.currentDepartures !== undefined) {
            // ------ Fill in departures
            this.cdir = -1;
            var displayCount = 0;
            for (var ix = 0; ix < this.currentDepartures.departures.length; ix++) {
                var dep = this.currentDepartures.departures[ix];
                if (this.cdir != -1 && this.cdir != dep.JourneyDirection) {
                    // We are changing direction, create an empty row to separate the two directions
                    this.cdir = dep.JourneyDirection;
                    var row = document.createElement("tr");
                    row.className = 'sup';
                    var td = document.createElement("td");
                    td.colSpan = 3;
                    td.innerHTML = ' ';
                    row.appendChild(td);
                    table.appendChild(row);
                    displayCount = 0; // Restart count of number of items to display for this new direction
                }
                displayCount++;
                if (displayCount <= this.config.displaycount) { // Only show displaycount entries
                    if (this.cdir == -1) this.cdir = dep.JourneyDirection;
                    var row = document.createElement("tr");
                    var td = document.createElement("td");
                    td.className = 'align-left';
                    td.innerHTML = dep.LineNumber;
                    row.appendChild(td);
                    td = document.createElement("td");
                    td.innerHTML = dep.Destination;
                    td.className = 'align-left';
                    row.appendChild(td);
                    td = this.getDepartureTime(dep.TimeTabledDateTime, dep.ExpectedDateTime);
                    row.appendChild(td);
                    table.appendChild(row);
                    this.setFade(row, /*ix*/displayCount, /*this.currentDepartures.departures.length*/this.config.displaycount, this.config.fade, this.config.fadePoint);
                }
            }
        }
        wrapper.appendChild(table);

        // ----- Show service failure if any
        if (this.failure !== undefined) {
            var div = document.createElement("div");
            var msg = (this.failure.resp.Message.Message !== undefined ? this.failure.resp.Message : this.failure.resp.Message.message );
            div.innerHTML = moment(new Date()).format('HH:mm') +" Service: " + this.failure.resp.StatusCode + '-' + msg;
            div.style.color = "red"; // TODO Change this to a custom style
            div.className = "xsmall";
            wrapper.appendChild(div);
        }

        return wrapper;
    },

    // --------------------------------------- Calculate departure time
    // Returns a HTML element that shall be added to the current row
    getDepartureTime: function (tableTime, expectedTime) {
        var td = document.createElement("td");
        if (tableTime == expectedTime) { // There's no delay
            td.innerHTML = this.timeRemaining(moment(tableTime));
        } else {
            td.innerHTML = this.timeRemaining(moment(expectedTime)) + ' ';
            var sp = document.createElement("span");
            sp.innerHTML = this.timeRemaining(moment(tableTime), true);
            sp.style.textDecoration = "line-through" // TODO Change this to a custom style
            td.appendChild(sp);
        }
        td.className = "align-right bright";
        return td;
    },

    // --------------------------------------- Get a human readable duration
    // Dont like the moment.js humanize stuff, too lonmg in swedish and too crud.
    timeRemaining: function (tt, noPrefix) {
        var now = moment();
        var dur = tt.diff(now, 'seconds');

        if (dur < 0) return 'left';
        if (dur < 30) return 'now';
        if (30 <= dur && dur < 60) return (noPrefix ? '' : 'in ') + ' 1 min';
        if (60 <= dur && dur < 15 * 60) return (noPrefix ? '' : 'in ') + Math.round(dur / 60) + ' min';

        return (noPrefix ? '' : 'at ') + tt.format('HH:mm');
    },

    // --------------------------------------- Are we asking for this direction
    isWantedDirection: function (dir) {
        if (this.config.direction !== undefined && this.config.direction != '') {
            return dir == this.config.direction;
        }
        return true;
    },

    // --------------------------------------- Handle table fading
    setFade: function (row, ix, len, fade, fadePoint) {
        len = len + 1; // If we dont do this the last line will have opacity 0
        if (fade && fadePoint < 1) {
            if (fadePoint < 0) {
                fadePoint = 0;
            }
            var startingPoint = len * fadePoint;
            var steps = len - startingPoint;
            if (ix >= startingPoint) {
                var currentStep = ix - startingPoint;
                row.style.opacity = 1 - (1 / steps * currentStep);
            }
        }
    },
    // --------------------------------------- Handle socketnotifications
    socketNotificationReceived: function (notification, payload) {
        if (notification === "DEPARTURES") {
            this.loaded = true;
            this.failure = undefined;
            // Handle payload
            this.currentDepartures = payload;
            Log.info("Departures updated: " + this.currentDepartures.departures.length);
            this.currentDepartures.obtained = new Date();
            this.updateDom();
        }
        if (notification == "SERVICE_FAILURE") {
            this.loaded = true;
            this.failure = payload;
            Log.info("Service failure: " + this.failure.resp.StatusCode + ':' + this.failure.resp.Message);
            this.updateDom();
        }
    }
})<|endoftext|>


<commit_before>// isolation
(function () {

var a11ycss = a11ycss || {};

a11ycss.checkalts = {
	imgs : {},
	namespace: "a11ycss_checkalts_",
	reporter: document.createElement('div'),
	strings: {
		ok: "OK",
		info: "empty",
		ko: "missing"
	},
	// string templates for pictograms
	pics: {
		ok:"",
		empty:"",
		missing:""
	},

	extensionpics: {},
	// The reporter is a zone in the page where we gather thumbnails
	buildReporter: function() {
		var reporterid = this.namespace + 'reporter';
		this.reporter.id = reporterid;
		var style = `
			body {
				margin-left: 10rem !important;
			}
			div#${reporterid} {
				background: #fcf9e9;
				color: #3e4b55;
				font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
				font-size: .8rem;
				height: 100vh;
				left: 0;
				margin: 0;
				overflow: auto;
				padding: 0;
				position: fixed;
				top: 0;
				width: 10rem;
				z-index: 2147483647;
			}
			div#${reporterid} figure {
				border-radius: .25rem;
				cursor: pointer;
				margin: .5rem .25rem;
				padding: .25rem;
				position: relative;
			}
			div#${reporterid} figure:focus {
				background: #fff;
				outline: 1px solid #e5dec8;
			}
			div#${reporterid} img {
				height: auto;
				max-width: 100%;
				width: auto;
			}
			div#${reporterid} code {
				background: none;
				border: 0;
				color: inherit;
				font-family: "Consolas", "Monaco", "Andale Mono", monospace;
			}
			div#${reporterid} img.${this.namespace}picto {
				display: none;
				height: 2rem;
				left: 0;
				position: absolute;
				top: 0;
				width: 2rem;
			}
		`;
		var s = document.createElement('style');
		s.innerHTML = style;
		document.getElementsByTagName('head').item(0).appendChild(s);
		document.getElementsByTagName('body').item(0).appendChild(this.reporter);
	},
	// we collect images and add information on them
	collectImages: function() {
		var imgs = document.getElementsByTagName('img');
		var str = '';
		var tpl = `

				{PICTOGRAM}

				alt={ALT}

				title={TITLE}

		`;

		for (var i=0; i < imgs.length; i++) {
			var tmptpl = tpl;
			var tmpimg = imgs[i];
			var tmpstr = '';
			var tmppicto = '';

			tmpimg.classList.add(this.namespace + "targetimage" + i);

			// populate strings
			tmptpl = tmptpl.replace(`{TARGET}`, this.namespace + "targetimage" + i);
			tmptpl = tmptpl.replace(`{SRC}`, tmpimg.src);

			if (tmpimg.getAttribute('alt') === null) {
				tmptpl = tmptpl.replace(`{ALT}`, this.strings.ko);
				tmptpl = tmptpl.replace(`{PICTOGRAM}`,
					this.pics.missing.replace(/{NAMESPACE}/g,this.namespace) );
			} else if(tmpimg.alt === '') {
				tmptpl = tmptpl.replace(`{ALT}`, this.strings.info);
				tmptpl = tmptpl.replace(`{PICTOGRAM}`,
					this.pics.empty.replace(/{NAMESPACE}/g, this.namespace));
			} else {
				tmptpl = tmptpl.replace(`{ALT}`, "'" + tmpimg.alt + "'");
				tmptpl = tmptpl.replace(`{PICTOGRAM}`,
					this.pics.ok.replace(/{NAMESPACE}/g, this.namespace));
			}

			if (tmpimg.getAttribute('title') === null) {
				tmpstr = this.strings.ko;
			} else if (tmpimg.title === '') {
				tmpstr = this.strings.info;
			} else {
				tmpstr = "'" + tmpimg.title + "'";
			}
			tmptpl = tmptpl.replace(`{TITLE}`, tmpstr);

			str += tmptpl;
			// end populate strings

		}
		this.reporter.innerHTML = str;
	},
	// we add behaviour on the figures (thumbnails) we gathered in the reporter
	addBehaviour: function () {
		var that = this; // yeah I know it's cheap but I'm going for easy here.
		var figures = this.reporter.getElementsByTagName('figure');
		for(var i = 0 ; i < figures.length ; i++) {
			var f = figures[i];
			f.setAttribute('tabindex',0);
			f.addEventListener('click',function(){
				that.handleThumbnail(this);
			});
			f.addEventListener('keypress',function(e){
				if (e.keyCode === 13) {
					that.handleThumbnail(this);
				}
			});
		}
	},
	// this handles events on thumbnails and scrolls to desired image
	handleThumbnail: function(elt) {
		var scrollElt = document.getElementsByClassName(elt.getAttribute('data-target')).item(0);
		scrollElt.scrollIntoView({
			block: "start",
			inline: "nearest",
			behavior: "smooth"
		});
	},

	// this changes strings to locale if an array of strings was provided
	// by the extension's call to the script
	updateStrings: function (strings) {
		this.strings = strings;
	},

	// this changes the pictos with icons stored in the webextension
	updatePictos: function(icons) {
		var keys = [ "info", "ko", "ok" ];
		var classPrefix = a11ycss.checkalts.namespace + 'picto_';
		keys.forEach(function(key) {
			var elts = document.getElementsByClassName(classPrefix + key);
			for(var i = 0 ; i < elts.length ; i++) {
				elts[i].src = icons[key.valueOf()];
				elts[i].style = 'display:block;';
				elts[i].alt = a11ycss.checkalts.strings[key.valueOf()];
			}
		}, this);
	},

	init: function() {
		if (document.getElementById(this.namespace + 'reporter')) {
			return;
		}
		this.buildReporter();
		this.collectImages();
		this.addBehaviour();
	}
};

browser.runtime.onMessage.addListener((message) => {
	if (message.a11ycss_action && message.a11ycss_action === "checkalts") {
		if(message.strings) {
			a11ycss.checkalts.updateStrings(message.strings);
		}
		a11ycss.checkalts.init();
		if (message.icons) {
			a11ycss.checkalts.updatePictos(message.icons);
		}
	}
});

})();
// end isolation
<commit_msg>fix: ensure status icon is above checked image<commit_after>// isolation
(function () {

var a11ycss = a11ycss || {};

a11ycss.checkalts = {
	imgs : {},
	namespace: "a11ycss_checkalts_",
	reporter: document.createElement('div'),
	strings: {
		ok: "OK",
		info: "empty",
		ko: "missing"
	},
	// string templates for pictograms
	pics: {
		ok:"",
		empty:"",
		missing:""
	},

	extensionpics: {},
	// The reporter is a zone in the page where we gather thumbnails
	buildReporter: function() {
		var reporterid = this.namespace + 'reporter';
		this.reporter.id = reporterid;
		var style = `
			body {
				margin-left: 10rem !important;
			}
			div#${reporterid} {
				background: #fcf9e9;
				color: #3e4b55;
				font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
				font-size: .8rem;
				height: 100vh;
				left: 0;
				margin: 0;
				overflow: auto;
				padding: 0;
				position: fixed;
				top: 0;
				width: 10rem;
				z-index: 2147483647;
			}
			div#${reporterid} figure {
				border-radius: .25rem;
				cursor: pointer;
				margin: .5rem .25rem;
				padding: .25rem;
				position: relative;
			}
			div#${reporterid} figure:focus {
				background: #fff;
				outline: 1px solid #e5dec8;
			}
			div#${reporterid} img {
				height: auto;
				max-width: 100%;
				width: auto;
			}
			div#${reporterid} code {
				background: none;
				border: 0;
				color: inherit;
				font-family: "Consolas", "Monaco", "Andale Mono", monospace;
			}
			div#${reporterid} img.${this.namespace}picto {
				display: none;
				height: 2rem;
				left: 0;
				position: absolute;
				top: 0;
				width: 2rem;
				z-index: 1;
			}
		`;
		var s = document.createElement('style');
		s.innerHTML = style;
		document.getElementsByTagName('head').item(0).appendChild(s);
		document.getElementsByTagName('body').item(0).appendChild(this.reporter);
	},
	// we collect images and add information on them
	collectImages: function() {
		var imgs = document.getElementsByTagName('img');
		var str = '';
		var tpl = `

				{PICTOGRAM}

				alt={ALT}

				title={TITLE}

		`;

		for (var i=0; i < imgs.length; i++) {
			var tmptpl = tpl;
			var tmpimg = imgs[i];
			var tmpstr = '';
			var tmppicto = '';

			tmpimg.classList.add(this.namespace + "targetimage" + i);

			// populate strings
			tmptpl = tmptpl.replace(`{TARGET}`, this.namespace + "targetimage" + i);
			tmptpl = tmptpl.replace(`{SRC}`, tmpimg.src);

			if (tmpimg.getAttribute('alt') === null) {
				tmptpl = tmptpl.replace(`{ALT}`, this.strings.ko);
				tmptpl = tmptpl.replace(`{PICTOGRAM}`,
					this.pics.missing.replace(/{NAMESPACE}/g,this.namespace) );
			} else if(tmpimg.alt === '') {
				tmptpl = tmptpl.replace(`{ALT}`, this.strings.info);
				tmptpl = tmptpl.replace(`{PICTOGRAM}`,
					this.pics.empty.replace(/{NAMESPACE}/g, this.namespace));
			} else {
				tmptpl = tmptpl.replace(`{ALT}`, "'" + tmpimg.alt + "'");
				tmptpl = tmptpl.replace(`{PICTOGRAM}`,
					this.pics.ok.replace(/{NAMESPACE}/g, this.namespace));
			}

			if (tmpimg.getAttribute('title') === null) {
				tmpstr = this.strings.ko;
			} else if (tmpimg.title === '') {
				tmpstr = this.strings.info;
			} else {
				tmpstr = "'" + tmpimg.title + "'";
			}
			tmptpl = tmptpl.replace(`{TITLE}`, tmpstr);

			str += tmptpl;
			// end populate strings

		}
		this.reporter.innerHTML = str;
	},
	// we add behaviour on the figures (thumbnails) we gathered in the reporter
	addBehaviour: function () {
		var that = this; // yeah I know it's cheap but I'm going for easy here.
		var figures = this.reporter.getElementsByTagName('figure');
		for(var i = 0 ; i < figures.length ; i++) {
			var f = figures[i];
			f.setAttribute('tabindex',0);
			f.addEventListener('click',function(){
				that.handleThumbnail(this);
			});
			f.addEventListener('keypress',function(e){
				if (e.keyCode === 13) {
					that.handleThumbnail(this);
				}
			});
		}
	},
	// this handles events on thumbnails and scrolls to desired image
	handleThumbnail: function(elt) {
		var scrollElt = document.getElementsByClassName(elt.getAttribute('data-target')).item(0);
		scrollElt.scrollIntoView({
			block: "start",
			inline: "nearest",
			behavior: "smooth"
		});
	},

	// this changes strings to locale if an array of strings was provided
	// by the extension's call to the script
	updateStrings: function (strings) {
		this.strings = strings;
	},

	// this changes the pictos with icons stored in the webextension
	updatePictos: function(icons) {
		var keys = [ "info", "ko", "ok" ];
		var classPrefix = a11ycss.checkalts.namespace + 'picto_';
		keys.forEach(function(key) {
			var elts = document.getElementsByClassName(classPrefix + key);
			for(var i = 0 ; i < elts.length ; i++) {
				elts[i].src = icons[key.valueOf()];
				elts[i].style = 'display:block;';
				elts[i].alt = a11ycss.checkalts.strings[key.valueOf()];
			}
		}, this);
	},

	init: function() {
		if (document.getElementById(this.namespace + 'reporter')) {
			return;
		}
		this.buildReporter();
		this.collectImages();
		this.addBehaviour();
	}
};

browser.runtime.onMessage.addListener((message) => {
	if (message.a11ycss_action && message.a11ycss_action === "checkalts") {
		if(message.strings) {
			a11ycss.checkalts.updateStrings(message.strings);
		}
		a11ycss.checkalts.init();
		if (message.icons) {
			a11ycss.checkalts.updatePictos(message.icons);
		}
	}
});

})();
// end isolation
<|endoftext|>


<commit_before>const Discord = require('discord.js')
class embedMessage {
  constructor(msg) {
    this.message = msg
  }

  descEmbed(options) {
    if (!options) {
      throw Error('You must specify the options, options list {content, type}')
    }
    if (options.type === "desc" ) {
      if (!options.content) {
        throw Error ('You did not specify the text inside the constructor options.')
      } else {
        const embed = new Discord.RichEmbed()
        .setDescription(options.content)
        this.message.channel.send({embed})
      }
    } else {
      throw Error ('You chose descEmbed but your option does not have "desc" in it.')
    }
  }
  advanced(options) {
    /**
    *@returns {Error}
    */
    if (!options) {
      throw Error('You must specify at list one option, list {desc, footer, thumbnail, title, author fields[field1, content, field2, content]}')
    }

    /**
    *@returns {Error}
    */
    if (!options.fields[0]) {
      throw Error('You must add atleast 1 field')
    }

    const embed = new Discord.RichEmbed();

    /**
    *@returns {Object}
    *@param {boolean} inline
    *@param {string} title
    *@param {string} content
    */
    for (let i = 0; i < options.fields.length; i++) {
      let inline;
      if (!options.fields[i].inline) {
        inline = false
      } else if (options.fields[i].inline === true) {
        inline = true
      }
      embed.addField(options.fields[i].title, options.fields[i].content, inline)
    }

    /**
    *@param {String} desc
    */
    if (options.desc) {
      embed.setDescription(options.desc)
    }

    /**
    *@param {String} footer
    */
    if (options.footer) {
      embed.setFooter(options.footer)
    }

    /**
    *@param {String} title
    */
    if(options.title) {
      embed.setTitle(options.title)
    }

    /**
    *@param {String} thumbnail
    */
    if (options.thumbnail) {
      embed.setThumbnail(options.thumbnail)
    }

    this.message.channel.send({embed}) //Send the embed after all the options been selected
  }
}
module.exports = embedMessage;
<commit_msg>Added author as an object that contains name and pic<commit_after>const Discord = require('discord.js')
class embedMessage {
  constructor(msg) {
    this.message = msg
  }

  descEmbed(options) {
    if (!options) {
      throw Error('You must specify the options, options list {content, type}')
    }
    if (options.type === "desc" ) {
      if (!options.content) {
        throw Error ('You did not specify the text inside the constructor options.')
      } else {
        const embed = new Discord.RichEmbed()
        .setDescription(options.content)
        this.message.channel.send({embed})
      }
    } else {
      throw Error ('You chose descEmbed but your option does not have "desc" in it.')
    }
  }
  advanced(options) {
    /**
    *@returns {Error}
    */
    if (!options) {
      throw Error('You must specify at list one option, list {desc, footer, thumbnail, title, author fields[field1, content, field2, content]}')
    }

    /**
    *@returns {Error}
    */
    if (!options.fields[0]) {
      throw Error('You must add atleast 1 field')
    }

    const embed = new Discord.RichEmbed();

    /**
    *@returns {Object}
    *@param {boolean} inline
    *@param {string} title
    *@param {string} content
    */
    for (let i = 0; i < options.fields.length; i++) {
      let inline;
      if (!options.fields[i].inline) {
        inline = false
      } else if (options.fields[i].inline === true) {
        inline = true
      }
      embed.addField(options.fields[i].title, options.fields[i].content, inline)
    }

    /**
    *@param {String} desc
    */
    if (options.desc) {
      embed.setDescription(options.desc)
    }

    /**
    *@param {String} footer
    */
    if (options.footer) {
      embed.setFooter(options.footer)
    }

    /**
    *@param {String} title
    */
    if(options.title) {
      embed.setTitle(options.title)
    }

    /**
    *@param {String} thumbnail
    */
    if (options.thumbnail) {
      embed.setThumbnail(options.thumbnail)
    }

    /**
    *@param {String} author
    */
    if (options.author) {
      embed.author(options.author.name, options.author.pic);
    }

    this.message.channel.send({embed}) //Send the embed after all the options been selected
  }
}
module.exports = embedMessage;
<|endoftext|>


<commit_before>var fs = require("mz/fs");
var _ = require("lodash");

// Read and log out options
var opts = JSON.parse(process.argv[3]);
console.log(opts);

// Make results directory
fs.mkdirSync(opts._id);

// Creates a linear scale
var linScale = function(numEls, step, start) {
  return _.map(Array(numEls), function(val, ind) {
    return start + step*ind;
  });
};

// Creates an exponential decay curve with noise
var noisyExp = function(val, ind, coll) {
  var exp = Math.pow(0.9, ind/coll.length) - 0.9;
  return exp + exp*Math.random();
};
var randFill = function(numEls) {
  return _.map(Array(numEls), noisyExp);
};

// Save random results
var train = {
  indices: linScale(100000, 1, 1),
  losses: randFill(100000)
};
fs.writeFileSync(opts._id + "/train.json", JSON.stringify({_train: train}));
var val = {
  indices: linScale(1000, 100, 1),
  losses: randFill(1000),
  score: Math.random()
};
fs.writeFileSync(opts._id + "/val.json", JSON.stringify({_val: val}));
var test = {
  loss: Math.random(),
  score: Math.random()
};
fs.writeFileSync(opts._id + "/test.json", JSON.stringify({_test: test}));
fs.writeFileSync(opts._id + "/custom.json", JSON.stringify({custom: "This is a custom field"}));
<commit_msg>Use multi-word custom field<commit_after>var fs = require("mz/fs");
var _ = require("lodash");

// Read and log out options
var opts = JSON.parse(process.argv[3]);
console.log(opts);

// Make results directory
fs.mkdirSync(opts._id);

// Creates a linear scale
var linScale = function(numEls, step, start) {
  return _.map(Array(numEls), function(val, ind) {
    return start + step*ind;
  });
};

// Creates an exponential decay curve with noise
var noisyExp = function(val, ind, coll) {
  var exp = Math.pow(0.9, ind/coll.length) - 0.9;
  return exp + exp*Math.random();
};
var randFill = function(numEls) {
  return _.map(Array(numEls), noisyExp);
};

// Save random results
var train = {
  indices: linScale(100000, 1, 1),
  losses: randFill(100000)
};
fs.writeFileSync(opts._id + "/train.json", JSON.stringify({_train: train}));
var val = {
  indices: linScale(1000, 100, 1),
  losses: randFill(1000),
  score: Math.random()
};
fs.writeFileSync(opts._id + "/val.json", JSON.stringify({_val: val}));
var test = {
  loss: Math.random(),
  score: Math.random()
};
fs.writeFileSync(opts._id + "/test.json", JSON.stringify({_test: test}));
fs.writeFileSync(opts._id + "/custom.json", JSON.stringify({"Custom Field": "This is a custom field"}));
<|endoftext|>


<commit_before>'use strict';

const Promise = require('bluebird'),
  moment = require('moment'),
  log = require('intel').getLogger('sitespeedio'),
  os = require('os'),
  process = require('process'),
  logging = require('./core/logging'),
  toArray = require('./support/util').toArray,
  difference = require('lodash.difference'),
  merge = require('lodash.merge'),
  pullAll = require('lodash.pullall'),
  union = require('lodash.union'),
  browsertimeConfig = require('./plugins/browsertime').config,
  webpagetestConfig = require('./plugins/webpagetest').config,
  messageMaker = require('./support/messageMaker'),
  filterRegistry = require('./support/filterRegistry'),
  packageInfo = require('../package');

const QueueHandler = require('./core/queueHandler'),
  resultsStorage = require('./core/resultsStorage'),
  loader = require('./core/pluginLoader'),
  urlSource = require('./core/url-source');

const budgetResult = {
  working: {},
  failing: {}
};

function hasFunctionFilter(functionName) {
  return obj => typeof obj[functionName] === 'function';
}

function allInArray(sampleArray, referenceArray) {
  return difference(sampleArray, referenceArray).length === 0;
}

function runOptionalFunction(objects, fN) {
  // NOTE: note slicing due to https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  let args = new Array(arguments.length - 2);
  for (let i = 2; i < arguments.length; i++) {
    args[i - 2] = arguments[i];
  }
  return Promise.resolve(objects)
    .filter(hasFunctionFilter(fN))
    .map(plugin => Promise.resolve(plugin[fN].apply(plugin, args)));
}

module.exports = {
  run(options) {
    const url = options.urls[0];
    const timestamp = moment();

    if (options.utc) {
      timestamp.utc();
    }

    const { storageManager, resultUrls } = resultsStorage(
      url,
      timestamp,
      options.outputFolder,
      options.resultBaseURL
    );

    return storageManager
      .createDataDir('logs')
      .then(logDir => {
        logging.configure(options, logDir);
      })
      .then(() => {
        if (log.isEnabledFor(log.VERBOSE)) {
          Promise.longStackTraces();
        }
        log.info(
          'Versions OS: %s nodejs: %s sitespeed.io: %s browsertime: %s coach: %s',
          os.platform() + ' ' + os.release(),
          process.version,
          packageInfo.version,
          packageInfo.dependencies.browsertime,
          packageInfo.dependencies.webcoach
        );
      })
      .then(() => {
        return loader.parsePluginNames(options);
      })
      .then(pluginNames => {
        const plugins = options.plugins;
        if (plugins) {
          if (plugins.disable) {
            log.warn(
              '--plugins.disable is deprecated, use plugins.remove instead.'
            );
            plugins.remove = plugins.disable;
          }
          if (plugins.load) {
            log.warn('--plugins.load is deprecated, use plugins.add instead.');
            plugins.add = plugins.load;
          }

          pullAll(pluginNames, toArray(plugins.remove));
          pluginNames = union(pluginNames, toArray(plugins.add));

          if (plugins.list) {
            log.info(
              'The following plugins are enabled: %s',
              pluginNames.join(', ')
            );
          }
        }
        // if we run without cli, we still want the default options
        // in options to use it in output
        if (allInArray(['browsertime'], pluginNames)) {
          options.browsertime = merge(
            {},
            browsertimeConfig,
            options.browsertime
          );
        }
        if (allInArray(['webpagetest'], pluginNames)) {
          options.webpagetest = merge(
            {},
            webpagetestConfig,
            options.webpagetest
          );
        }
        if (allInArray(['browsertime', 'coach'], pluginNames)) {
          options.browsertime = merge({}, options.browsertime, {
            coach: true
          });
        }
        if (allInArray(['browsertime', 'screenshot'], pluginNames)) {
          options.browsertime = merge({}, options.browsertime, {
            screenshot: true
          });
        }
        return pluginNames;
      })
      .then(pluginNames => {
        return loader.loadPlugins(pluginNames).then(plugins => {
          let urlSources = [urlSource];
          const allPlugins = urlSources.concat(plugins),
            queueHandler = new QueueHandler(plugins, options);

          const context = {
            storageManager,
            resultUrls,
            timestamp,
            budget: budgetResult,
            name: url,
            log,
            messageMaker,
            filterRegistry
          };
          return runOptionalFunction(allPlugins, 'open', context, options)
            .then(() => queueHandler.run(urlSources))
            .tap(errors =>
              runOptionalFunction(allPlugins, 'close', options, errors)
            );
        });
      })
      .then(errors => {
        log.info('Finished analysing %s', url);
        if (resultUrls.hasBaseUrl()) {
          log.info('Find the result at %s', resultUrls.reportSummaryUrl());
        }

        if (options.summary && options.summary.out) {
          console.log(options.summary.out); // eslint-disable-line no-console
        }
        return {
          errors,
          budgetResult
        };
      })
      .catch(err => {
        log.error(err);
        throw err;
      });
  }
};
<commit_msg>Remove duplicated config logic. (#1763)<commit_after>'use strict';

const Promise = require('bluebird'),
  moment = require('moment'),
  log = require('intel').getLogger('sitespeedio'),
  os = require('os'),
  process = require('process'),
  logging = require('./core/logging'),
  toArray = require('./support/util').toArray,
  difference = require('lodash.difference'),
  merge = require('lodash.merge'),
  pullAll = require('lodash.pullall'),
  union = require('lodash.union'),
  messageMaker = require('./support/messageMaker'),
  filterRegistry = require('./support/filterRegistry'),
  packageInfo = require('../package');

const QueueHandler = require('./core/queueHandler'),
  resultsStorage = require('./core/resultsStorage'),
  loader = require('./core/pluginLoader'),
  urlSource = require('./core/url-source');

const budgetResult = {
  working: {},
  failing: {}
};

function hasFunctionFilter(functionName) {
  return obj => typeof obj[functionName] === 'function';
}

function allInArray(sampleArray, referenceArray) {
  return difference(sampleArray, referenceArray).length === 0;
}

function runOptionalFunction(objects, fN) {
  // NOTE: note slicing due to https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  let args = new Array(arguments.length - 2);
  for (let i = 2; i < arguments.length; i++) {
    args[i - 2] = arguments[i];
  }
  return Promise.resolve(objects)
    .filter(hasFunctionFilter(fN))
    .map(plugin => Promise.resolve(plugin[fN].apply(plugin, args)));
}

module.exports = {
  run(options) {
    const url = options.urls[0];
    const timestamp = moment();

    if (options.utc) {
      timestamp.utc();
    }

    const { storageManager, resultUrls } = resultsStorage(
      url,
      timestamp,
      options.outputFolder,
      options.resultBaseURL
    );

    return storageManager
      .createDataDir('logs')
      .then(logDir => {
        logging.configure(options, logDir);
      })
      .then(() => {
        if (log.isEnabledFor(log.VERBOSE)) {
          Promise.longStackTraces();
        }
        log.info(
          'Versions OS: %s nodejs: %s sitespeed.io: %s browsertime: %s coach: %s',
          os.platform() + ' ' + os.release(),
          process.version,
          packageInfo.version,
          packageInfo.dependencies.browsertime,
          packageInfo.dependencies.webcoach
        );
      })
      .then(() => {
        return loader.parsePluginNames(options);
      })
      .then(pluginNames => {
        const plugins = options.plugins;
        if (plugins) {
          if (plugins.disable) {
            log.warn(
              '--plugins.disable is deprecated, use plugins.remove instead.'
            );
            plugins.remove = plugins.disable;
          }
          if (plugins.load) {
            log.warn('--plugins.load is deprecated, use plugins.add instead.');
            plugins.add = plugins.load;
          }

          pullAll(pluginNames, toArray(plugins.remove));
          pluginNames = union(pluginNames, toArray(plugins.add));

          if (plugins.list) {
            log.info(
              'The following plugins are enabled: %s',
              pluginNames.join(', ')
            );
          }
        }
        if (allInArray(['browsertime', 'coach'], pluginNames)) {
          options.browsertime = merge({}, options.browsertime, {
            coach: true
          });
        }
        if (allInArray(['browsertime', 'screenshot'], pluginNames)) {
          options.browsertime = merge({}, options.browsertime, {
            screenshot: true
          });
        }
        return pluginNames;
      })
      .then(pluginNames => {
        return loader.loadPlugins(pluginNames).then(plugins => {
          let urlSources = [urlSource];
          const allPlugins = urlSources.concat(plugins),
            queueHandler = new QueueHandler(plugins, options);

          const context = {
            storageManager,
            resultUrls,
            timestamp,
            budget: budgetResult,
            name: url,
            log,
            messageMaker,
            filterRegistry
          };
          return runOptionalFunction(allPlugins, 'open', context, options)
            .then(() => queueHandler.run(urlSources))
            .tap(errors =>
              runOptionalFunction(allPlugins, 'close', options, errors)
            );
        });
      })
      .then(errors => {
        log.info('Finished analysing %s', url);
        if (resultUrls.hasBaseUrl()) {
          log.info('Find the result at %s', resultUrls.reportSummaryUrl());
        }

        if (options.summary && options.summary.out) {
          console.log(options.summary.out); // eslint-disable-line no-console
        }
        return {
          errors,
          budgetResult
        };
      })
      .catch(err => {
        log.error(err);
        throw err;
      });
  }
};
<|endoftext|>


<commit_before>define(
  'ephox.alloy.behaviour.transitioning.TransitionApis',

  [
    'ephox.boulder.api.Objects',
    'ephox.katamari.api.Fun',
    'ephox.katamari.api.Option',
    'ephox.sugar.api.properties.Attr',
    'ephox.sugar.api.properties.Class'
  ],

  function (Objects, Fun, Option, Attr, Class) {
    var findRoute = function (component, transConfig, transState, route) {
      return Objects.readOptFrom(transConfig.routes(), route.start()).map(Fun.apply).bind(function (sConfig) {
        return Objects.readOptFrom(sConfig, route.destination()).map(Fun.apply);
      });
    };

    var getTransition = function (comp, transConfig, transState) {
      var route = getCurrentRoute(comp, transConfig, transState);
      return route.bind(function (r) {
        return getTransitionOf(comp, transConfig, transState, r);
      });
    };

    var getTransitionOf = function (comp, transConfig, transState, route) {
      return findRoute(comp, transConfig, transState, route).bind(function (r) {
        console.log('getTransition found route');
        return r.transition().map(function (t) {
          return {
            transition: Fun.constant(t),
            route: Fun.constant(r)
          }
        });
      });
    };

    var disableTransition = function (comp, transConfig, transState) {
      // Disable the current transition
      getTransition(comp, transConfig, transState).each(function (routeTransition) {
        var t = routeTransition.transition();
        Class.remove(comp.element(), t.transitionClass());
        Attr.remove(comp.element(), transConfig.destinationAttr());
      });
    };

    var getNewRoute = function (comp, transConfig, transState, destination) {
      return {
        start: Fun.constant(Attr.get(comp.element(), transConfig.stateAttr())),
        destination: Fun.constant(destination)
      };
    };

    var getCurrentRoute = function (comp, transConfig, transState) {
      var el = comp.element();
      return Attr.has(el, transConfig.destinationAttr()) ? Option.some({
        start: Fun.constant(Attr.get(comp.element(), transConfig.stateAttr())),
        destination: Fun.constant(Attr.get(comp.element(), transConfig.destinationAttr()))
      }) : Option.none();
    };

    var jumpTo = function (comp, transConfig, transState, destination) {
      // Remove the previous transition
      disableTransition(comp, transConfig, transState);
      Attr.set(comp.element(), transConfig.stateAttr(), destination);
    };

    var fasttrack = function (comp, transConfig, transState, destination) {
      if (Attr.has(comp.element(), transConfig.destinationAttr())) {
        Attr.set(comp.element(), transConfig.stateAttr(), Attr.get(comp.element(), transConfig.destinationAttr()));
        Attr.remove(comp.element(), transConfig.destinationAttr());
      }
    }

    var progressTo = function (comp, transConfig, transState, destination) {
      fasttrack(comp, transConfig, transState, destination);
      var route = getNewRoute(comp, transConfig, transState, destination);
      getTransitionOf(comp, transConfig, transState, route).fold(function () {
        jumpTo(comp, transConfig, transState, destination);
      }, function (routeTransition) {
        disableTransition(comp, transConfig, transState);
        var t = routeTransition.transition();
        Class.add(comp.element(), t.transitionClass());
        Attr.set(comp.element(), transConfig.destinationAttr(), destination);
      });
    };

    return {
      findRoute: findRoute,
      disableTransition: disableTransition,
      getCurrentRoute: getCurrentRoute,
      jumpTo: jumpTo,
      progressTo: progressTo
    };
  }
);
<commit_msg>TM-34: removing console log<commit_after>define(
  'ephox.alloy.behaviour.transitioning.TransitionApis',

  [
    'ephox.boulder.api.Objects',
    'ephox.katamari.api.Fun',
    'ephox.katamari.api.Option',
    'ephox.sugar.api.properties.Attr',
    'ephox.sugar.api.properties.Class'
  ],

  function (Objects, Fun, Option, Attr, Class) {
    var findRoute = function (component, transConfig, transState, route) {
      return Objects.readOptFrom(transConfig.routes(), route.start()).map(Fun.apply).bind(function (sConfig) {
        return Objects.readOptFrom(sConfig, route.destination()).map(Fun.apply);
      });
    };

    var getTransition = function (comp, transConfig, transState) {
      var route = getCurrentRoute(comp, transConfig, transState);
      return route.bind(function (r) {
        return getTransitionOf(comp, transConfig, transState, r);
      });
    };

    var getTransitionOf = function (comp, transConfig, transState, route) {
      return findRoute(comp, transConfig, transState, route).bind(function (r) {
        return r.transition().map(function (t) {
          return {
            transition: Fun.constant(t),
            route: Fun.constant(r)
          }
        });
      });
    };

    var disableTransition = function (comp, transConfig, transState) {
      // Disable the current transition
      getTransition(comp, transConfig, transState).each(function (routeTransition) {
        var t = routeTransition.transition();
        Class.remove(comp.element(), t.transitionClass());
        Attr.remove(comp.element(), transConfig.destinationAttr());
      });
    };

    var getNewRoute = function (comp, transConfig, transState, destination) {
      return {
        start: Fun.constant(Attr.get(comp.element(), transConfig.stateAttr())),
        destination: Fun.constant(destination)
      };
    };

    var getCurrentRoute = function (comp, transConfig, transState) {
      var el = comp.element();
      return Attr.has(el, transConfig.destinationAttr()) ? Option.some({
        start: Fun.constant(Attr.get(comp.element(), transConfig.stateAttr())),
        destination: Fun.constant(Attr.get(comp.element(), transConfig.destinationAttr()))
      }) : Option.none();
    };

    var jumpTo = function (comp, transConfig, transState, destination) {
      // Remove the previous transition
      disableTransition(comp, transConfig, transState);
      Attr.set(comp.element(), transConfig.stateAttr(), destination);
    };

    var fasttrack = function (comp, transConfig, transState, destination) {
      if (Attr.has(comp.element(), transConfig.destinationAttr())) {
        Attr.set(comp.element(), transConfig.stateAttr(), Attr.get(comp.element(), transConfig.destinationAttr()));
        Attr.remove(comp.element(), transConfig.destinationAttr());
      }
    }

    var progressTo = function (comp, transConfig, transState, destination) {
      fasttrack(comp, transConfig, transState, destination);
      var route = getNewRoute(comp, transConfig, transState, destination);
      getTransitionOf(comp, transConfig, transState, route).fold(function () {
        jumpTo(comp, transConfig, transState, destination);
      }, function (routeTransition) {
        disableTransition(comp, transConfig, transState);
        var t = routeTransition.transition();
        Class.add(comp.element(), t.transitionClass());
        Attr.set(comp.element(), transConfig.destinationAttr(), destination);
      });
    };

    return {
      findRoute: findRoute,
      disableTransition: disableTransition,
      getCurrentRoute: getCurrentRoute,
      jumpTo: jumpTo,
      progressTo: progressTo
    };
  }
);
<|endoftext|>


<commit_before>$(document).ready(function() {
    $('span.add-plugin').click(function(){
        var select = $(this).parent().children("select");
        var pluginvalue = select.attr('value');
        var placeholder = $(this).parent().parent().parent().parent().parent().children("h2").text();
        var page_id = window.location.href.split("/")[6];
        var language = $('#id_language').attr('value');
        var target_div = $(this).parent().parent().parent().children('div.plugin-editor');
        if (pluginvalue) {
            var pluginname = select.children('[@selected]').text();
            var ul_list = $(this).parent().parent().children("ul.plugin-list");
            $.post("add-plugin/", { page_id:page_id, placeholder:placeholder, plugin_type:pluginvalue, language:language }, function(data){
                if ('error' != data) {
                    loadPluginForm(target_div, data);
                    ul_list.append('
' + pluginname + '
');
                    setclickfunctions();
                }
            }, "html" );
        }
    });
    $('ul.plugin-list').sortable({handle:'span.drag',
                                  //appendTo:'body',
                                  axis:'y',
                                  opacity:0.9,
                                  zIndex:2000,
                                  update:function(event, ui){
                                      var array = ui.element.sortable('toArray');
                                      var d = "";
                                      for(var i=0;i<array.length;i++){
                                          d += array[i].split("plugin_")[1];
                                          if (i!=array.length-1){
                                              d += "_";
                                          }
                                      }

                                      $.post("move-plugin", { ids:d },
                                          function(data){
                                      }, "json");

                                  }
                                 }
                                );
    setclickfunctions();
});

function setclickfunctions(){
    $('ul.plugin-list .text').click(function(){
        var target = $(this).parent().parent().parent().parent().children("div.plugin-editor");
        var id = $(this).parent().attr("id").split("plugin_")[1];
        loadPluginForm(target, id);
        return false;
    });

    $('ul.plugin-list .delete').click(function(){
        var plugin_id = $(this).parent().attr("id").split("plugin_")[1];
        $.post("remove-plugin/", { plugin_id:plugin_id }, function(data){
			var splits = data.split(",")
			id = splits.shift()
       		$("#plugin_"+id).remove();
			$("#iframe_"+id).parent().html("
" + splits.join(",") + "
")
        }, "html");
    });
}

function setiframeheight(height, id){
    $('#iframe_'+id).height(height+"px");
}

function hide_iframe(id, type, title, msg){
	$('#plugin_'+id+" span.text").html(""+type+" [ "+title+ " ]");
    $('#iframe_'+id).parent().html("
"+msg+"
");
}

function loadPluginForm(target, id){
    var object = '';
    target.html(object);
    $('ul.plugin-list .active').removeClass("active");
    $('#plugin_'+id).addClass("active");
};
<commit_msg>fixed a bug with too long urls for extracting the plugin page id<commit_after>$(document).ready(function() {
    $('span.add-plugin').click(function(){
        var select = $(this).parent().children("select");
        var pluginvalue = select.attr('value');
        var placeholder = $(this).parent().parent().parent().parent().parent().children("h2").text();
        var splits = window.location.href.split("/");
        var page_id = splits[splits.length-2];
        var language = $('#id_language').attr('value');
        var target_div = $(this).parent().parent().parent().children('div.plugin-editor');
        if (pluginvalue) {
            var pluginname = select.children('[@selected]').text();
            var ul_list = $(this).parent().parent().children("ul.plugin-list");
            $.post("add-plugin/", { page_id:page_id, placeholder:placeholder, plugin_type:pluginvalue, language:language }, function(data){
                if ('error' != data) {
                    loadPluginForm(target_div, data);
                    ul_list.append('
' + pluginname + '
');
                    setclickfunctions();
                }
            }, "html" );
        }
    });
    $('ul.plugin-list').sortable({handle:'span.drag',
                                  //appendTo:'body',
                                  axis:'y',
                                  opacity:0.9,
                                  zIndex:2000,
                                  update:function(event, ui){
                                      var array = ui.element.sortable('toArray');
                                      var d = "";
                                      for(var i=0;i<array.length;i++){
                                          d += array[i].split("plugin_")[1];
                                          if (i!=array.length-1){
                                              d += "_";
                                          }
                                      }

                                      $.post("move-plugin", { ids:d },
                                          function(data){
                                      }, "json");

                                  }
                                 }
                                );
    setclickfunctions();
});

function setclickfunctions(){
    $('ul.plugin-list .text').click(function(){
        var target = $(this).parent().parent().parent().parent().children("div.plugin-editor");
        var id = $(this).parent().attr("id").split("plugin_")[1];
        loadPluginForm(target, id);
        return false;
    });

    $('ul.plugin-list .delete').click(function(){
        var plugin_id = $(this).parent().attr("id").split("plugin_")[1];
        $.post("remove-plugin/", { plugin_id:plugin_id }, function(data){
			var splits = data.split(",")
			id = splits.shift()
       		$("#plugin_"+id).remove();
			$("#iframe_"+id).parent().html("
" + splits.join(",") + "
")
        }, "html");
    });
}

function setiframeheight(height, id){
    $('#iframe_'+id).height(height+"px");
}

function hide_iframe(id, type, title, msg){
	$('#plugin_'+id+" span.text").html(""+type+" [ "+title+ " ]");
    $('#iframe_'+id).parent().html("
"+msg+"
");
}

function loadPluginForm(target, id){
    var object = '';
    target.html(object);
    $('ul.plugin-list .active').removeClass("active");
    $('#plugin_'+id).addClass("active");
};
<|endoftext|>


<commit_before>'use strict';

var test = require('tape');
var crypto = require('crypto');
var mongoose = require('mongoose');
var beautifulValidation = require('../');

/**
 * Create an unique model name
 * (should be sufficiently unique for a few tests)
 *
 * @return {string} Random model name
 */
function makeUniqueName() {
    return crypto.randomBytes(8).toString('hex');
}

/**
 * Create a model with an unique "name"
 * property and a random name
 *
 * @param {string} custom Custom unique validation message
 * @return {Model} Moongoose model
 */
function makeModel(custom, fieldName) {
    var fields = {};
    fields[fieldName || 'name'] = {
        type: String,
        unique: custom || true
    };

    var schema = new mongoose.Schema(fields);

    schema.plugin(beautifulValidation);
    return mongoose.model(makeUniqueName(), schema);
}

/**
 * Create a model with a compound unique index
 *
 * @param {string} custom Custom unique validation message
 * @return {Model} Mongoose model
 */
function makeCompoundModel(custom) {
    var schema = new mongoose.Schema({
        name: String,
        email: String
    });

    schema.index({
        name: 1,
        email: 1
    }, {unique: custom || true});
    schema.plugin(beautifulValidation);

    return mongoose.model(makeUniqueName(), schema);
}

mongoose.connect('mongodb://127.0.0.1/test');
mongoose.connection.on('open', function () {
    test('should work like save', function (assert) {
        var Model = makeModel(),
            instance, name = 'testing';

        instance = new Model({
            name: name
        });

        instance.save(function (saveErr) {
            assert.error(saveErr, 'should save instance successfully');

            Model.find({
                name: name
            }, function (findErr, found) {
                assert.error(findErr, 'should run find correctly');
                assert.equal(found[0].name, name, 'should keep props & values');
                assert.end();
            });
        });
    });

    test('should work with promises', function (assert) {
        var Model = makeModel(),
            instance, name = 'testing';

        instance = new Model({
            name: name
        });

        instance.save().then(function () {
            Model.find({
                name: name
            }, function (err, found) {
                assert.error(err, 'should run find correctly');
                assert.equal(found[0].name, name, 'should keep props & values');
                assert.end();
            });
        }).catch(function (err) {
            assert.error(err, 'should save instance successfully');
            assert.end();
        });
    });

    test('should emit duplicate validation error', function (assert) {
        var Model = makeModel(),
            originalInst, duplicateInst, name = 'duptest';

        originalInst = new Model({
            name: name
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            duplicateInst = new Model({
                name: name
            });

            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.ok(err, 'err should exist');
            assert.equal(err.name, 'ValidationError', 'outer err should be of type ValidationError');
            assert.equal(err.errors.name.name, 'ValidatorError', 'inner err should be ValidatorError');
            assert.equal(err.errors.name.kind, 'Duplicate value', 'kind of err should be Duplicate value');
            assert.equal(err.errors.name.properties.path, 'name', 'err should be on the correct path');
            assert.equal(err.errors.name.properties.type, 'Duplicate value');
            assert.equal(err.errors.name.properties.value, name, 'err should contain the problematic value');

            assert.end();
        });
    });

    test('should work with compound unique indexes', function (assert) {
        var Model = makeCompoundModel(),
            name = 'duptest', email = 'duptest@example.com',
            originalInst, duplicateInst;

        originalInst = new Model({
            name: name,
            email: email
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            duplicateInst = new Model({
                name: name,
                email: email
            });

            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.ok(err, 'err should exist');
            assert.equal(err.name, 'ValidationError', 'outer err should be of type ValidationError');
            assert.equal(err.errors.name.name, 'ValidatorError', 'inner err should be ValidatorError');
            assert.equal(err.errors.name.kind, 'Duplicate value', 'kind of err should be Duplicate value');
            assert.equal(err.errors.name.properties.path, 'name', 'err should be on the correct path');
            assert.equal(err.errors.name.properties.type, 'Duplicate value');
            assert.equal(err.errors.name.properties.value, name, 'err should contain the problematic value');

            assert.end();
        });
    });

    test('should use custom validation message', function (assert) {
        var message = 'works!', Model = makeModel(message),
            originalInst, duplicateInst, name = 'duptest';

        originalInst = new Model({
            name: name
        });

        duplicateInst = new Model({
            name: name
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.equal(err.errors.name.message, message, 'message should be our custom value');
            assert.end();
        });
    });

    test('should work with spaces in field name', function (assert) {
        var message = 'works!', Model = makeModel(message, 'display name'),
            originalInst, duplicateInst, name = 'duptest';

        originalInst = new Model({
            'display name': name
        });

        duplicateInst = new Model({
            'display name': name
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.equal(err.errors['display name'].properties.path, 'display name', 'should keep the key with spaces');
            assert.end();
        });
    });

    test('should use custom validation message (compound index)', function (assert) {
        var message = 'works!', Model = makeCompoundModel(message),
            originalInst, duplicateInst, name = 'duptest';

        originalInst = new Model({
            name: name
        });

        duplicateInst = new Model({
            name: name
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.equal(err.errors.name.message, message, 'message should be our custom value (compound)');
            assert.end();
        });
    });

    test('closing connection', function (assert) {
        mongoose.disconnect();
        assert.end();
    });
});
<commit_msg>Clean up tests. Ensure the test database name is unique<commit_after>'use strict';

var test = require('tape');
var crypto = require('crypto');
var mongoose = require('mongoose');
var beautifulValidation = require('../');

/**
 * Generate a 8-chars random string
 * (should be sufficiently unique for a few tests)
 *
 * @return {string} Random string
 */
function uniqueString() {
    return crypto.randomBytes(8).toString('hex');
}

/**
 * Create a randomly-named model with any number
 * of fields. This model has an unique index over
 * all created fields
 *
 * @param {Array<string>|string} fieldNames Names of the fields
 * @param {string} [message=default message] Custom unique validation message
 * @return {Model} Mongoose model
 */
function makeModel(fieldNames, message) {
    var schema;

    if (Array.isArray(fieldNames) && fieldNames.length > 1) {
        // if there is more than one field,
        // we create a compound index
        var index = {}, fields = {};

        fieldNames.forEach(fieldName => {
            fields[fieldName] = String;
            index[fieldName] = 1;
        });

        schema = new mongoose.Schema(fields);
        schema.index(index, {
            unique: message || true
        });
    } else {
        // otherwise, we create a simple index
        if (Array.isArray(fieldNames)) {
            fieldNames = fieldNames[0];
        }

        schema = new mongoose.Schema({
            [fieldNames]: {
                type: String,
                unique: message || true
            }
        });
    }

    schema.plugin(beautifulValidation);
    return mongoose.model(uniqueString(), schema);
}

// connect to a database with a random name
mongoose.connect('mongodb://127.0.0.1/mongoose-buv-' + uniqueString());
mongoose.connection.on('open', function () {
    test('should work like save', function (assert) {
        var Model = makeModel('name'),
            instance, name = 'testing';

        instance = new Model({
            name: name
        });

        instance.save(function (saveErr) {
            assert.error(saveErr, 'should save instance successfully');

            Model.find({
                name: name
            }, function (findErr, found) {
                assert.error(findErr, 'should run find correctly');
                assert.equal(found[0].name, name, 'should keep props & values');
                assert.end();
            });
        });
    });

    test('should work with promises', function (assert) {
        var Model = makeModel('name'),
            instance, name = 'testing';

        instance = new Model({
            name: name
        });

        instance.save().then(function () {
            Model.find({
                name: name
            }, function (err, found) {
                assert.error(err, 'should run find correctly');
                assert.equal(found[0].name, name, 'should keep props & values');
                assert.end();
            });
        }).catch(function (err) {
            assert.error(err, 'should save instance successfully');
            assert.end();
        });
    });

    test('should emit duplicate validation error', function (assert) {
        var Model = makeModel('name'),
            originalInst, duplicateInst, name = 'duptest';

        originalInst = new Model({
            name: name
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            duplicateInst = new Model({
                name: name
            });

            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.ok(err, 'err should exist');
            assert.equal(err.name, 'ValidationError', 'outer err should be of type ValidationError');
            assert.equal(err.errors.name.name, 'ValidatorError', 'inner err should be ValidatorError');
            assert.equal(err.errors.name.kind, 'Duplicate value', 'kind of err should be Duplicate value');
            assert.equal(err.errors.name.properties.path, 'name', 'err should be on the correct path');
            assert.equal(err.errors.name.properties.type, 'Duplicate value');
            assert.equal(err.errors.name.properties.value, name, 'err should contain the problematic value');

            assert.end();
        });
    });

    test('should work with spaces in field name', function (assert) {
        var message = 'works!', Model = makeModel('display name', message),
            originalInst, duplicateInst, name = 'duptest';

        originalInst = new Model({
            'display name': name
        });

        duplicateInst = new Model({
            'display name': name
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.equal(err.errors['display name'].properties.path, 'display name', 'should keep the key with spaces');
            assert.end();
        });
    });

    test('should work with compound unique indexes', function (assert) {
        var Model = makeModel(['name', 'email']),
            name = 'duptest', email = 'duptest@example.com',
            originalInst, duplicateInst;

        originalInst = new Model({
            name: name,
            email: email
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            duplicateInst = new Model({
                name: name,
                email: email
            });

            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.ok(err, 'err should exist');
            assert.equal(err.name, 'ValidationError', 'outer err should be of type ValidationError');
            assert.equal(err.errors.name.name, 'ValidatorError', 'inner err should be ValidatorError');
            assert.equal(err.errors.name.kind, 'Duplicate value', 'kind of err should be Duplicate value');
            assert.equal(err.errors.name.properties.path, 'name', 'err should be on the correct path');
            assert.equal(err.errors.name.properties.type, 'Duplicate value');
            assert.equal(err.errors.name.properties.value, name, 'err should contain the problematic value');

            assert.end();
        });
    });

    test('should use custom validation message', function (assert) {
        var message = 'works!', Model = makeModel('name', message),
            originalInst, duplicateInst, name = 'duptest';

        originalInst = new Model({
            name: name
        });

        duplicateInst = new Model({
            name: name
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.equal(err.errors.name.message, message, 'message should be our custom value');
            assert.end();
        });
    });

    test('should use custom validation message (compound index)', function (assert) {
        var message = 'works!', Model = makeModel(['name', 'email'], message),
            originalInst, duplicateInst, name = 'duptest';

        originalInst = new Model({
            name: name
        });

        duplicateInst = new Model({
            name: name
        });

        originalInst.save().catch(function (err) {
            assert.error(err, 'should save original instance successfully');
            assert.end();
        }).then(function () {
            return duplicateInst.save();
        }).then(function () {
            assert.fail('should not save duplicate successfully');
            assert.end();
        }, function (err) {
            assert.equal(err.errors.name.message, message, 'message should be our custom value (compound)');
            assert.end();
        });
    });

    test('closing connection', function (assert) {
        // clean up the test database
        mongoose.connection.db.dropDatabase().then(function (abc) {
            mongoose.disconnect();
            assert.end();
        }).catch(function (err) {
            assert.error(err, 'should clean up the test database');
            assert.end();
        });
    });
});
<|endoftext|>