<commit_before>/* eslint-disable import/prefer-default-export */

export const createRedirectLink = (path, query) => {
  const redirect = `/?redirect=${path}`;
  if (query) {
    return Object.keys(query).reduce((link, param) => {
      const value = query[param];
      if (value) {
        // only if value is set
        // eslint-disable-next-line no-param-reassign
        link += `&${param}=${value}`;
      }
      return link;
    }, redirect);
  }

  return redirect;
};

export const sortActiveProposals = (a, b) => {
  const timeA = new Date(
    a.state === 'proposed' ? a.pollOne.endTime : a.pollTwo.endTime,
  );

  const timeB = new Date(
    b.state === 'proposed' ? b.pollOne.endTime : b.pollTwo.endTime,
  );
  return timeA - timeB;
};
export const sortClosedProposals = (a, b) => {
  let timeA;
  let timeB;
  if (a.pollTwo) {
    timeA = new Date(a.pollTwo.closedAt);
  } else {
    timeA = new Date(a.pollOne.closedAt);
  }
  if (b.pollTwo) {
    timeB = new Date(b.pollTwo.closedAt);
  } else {
    timeB = new Date(b.pollOne.closedAt);
  }
  return timeB - timeA;
};

export const surveyStateFilter = (survey, filter) => {
  if (filter === 'active') {
    return !survey.pollOne.closedAt;
  }
  return survey.pollOne.closedAt;
};
<commit_msg>added null-check for pollOne in survey filter<commit_after>/* eslint-disable import/prefer-default-export */

export const createRedirectLink = (path, query) => {
  const redirect = `/?redirect=${path}`;
  if (query) {
    return Object.keys(query).reduce((link, param) => {
      const value = query[param];
      if (value) {
        // only if value is set
        // eslint-disable-next-line no-param-reassign
        link += `&${param}=${value}`;
      }
      return link;
    }, redirect);
  }

  return redirect;
};

export const sortActiveProposals = (a, b) => {
  const timeA = new Date(
    a.state === 'proposed' ? a.pollOne.endTime : a.pollTwo.endTime,
  );

  const timeB = new Date(
    b.state === 'proposed' ? b.pollOne.endTime : b.pollTwo.endTime,
  );
  return timeA - timeB;
};
export const sortClosedProposals = (a, b) => {
  let timeA;
  let timeB;
  if (a.pollTwo) {
    timeA = new Date(a.pollTwo.closedAt);
  } else {
    timeA = new Date(a.pollOne.closedAt);
  }
  if (b.pollTwo) {
    timeB = new Date(b.pollTwo.closedAt);
  } else {
    timeB = new Date(b.pollOne.closedAt);
  }
  return timeB - timeA;
};

export const surveyStateFilter = (survey, filter) => {
  if (filter === 'active') {
    return survey.pollOne && !survey.pollOne.closedAt;
  }
  return survey.pollOne && survey.pollOne.closedAt;
};
<|endoftext|>


<commit_before>

var Game = {

	stage:null,
	turkey:null,
	goal:null,
	ham:null,
	loader:null,

	init:function(){
		this.stage = new createjs.Stage("gameCanvas");
		this.turkey = this.stage.addChild(new Turkey('blue'));
		this.turkey.x = 195;
		this.turkey.y = 100;
		this.goal = new Goal(200,100,12);
		this.goal.x = 100;
		this.goal.y = 60;
		this.stage.addChildAt(this.goal,0);
		this.ham =  this.goal.addChild(new Ham('red',200));
		this.ham.x = 0;
		this.ham.y = 20;
		//
		this.loadAssets();
	},
	onShot:function(event){
		console.log(event);
		var stageX = event.stageX;
		var stageY = event.stageY;
		var p = this.stage.addChild(new Puck());
		p.x = 300;
		p.y = 345;
		var p_lis = p.on('hit',function(){
			Game.onPuckContact(this);
			p.off('hit',p_lis);
		});
		//to be called after shot animation
		this.turkey.shoot(
			function(){
				p.fire(event.stageX,event.stageY);
			}
		);

	},
	onPuckContact: function (puck){
		//console.log('shoot!');
		var pt = this.goal.globalToLocal(puck.x,puck.y);
		this.regX = this.regY = 50;
		var arr = this.goal.getObjectsUnderPoint(pt.x,pt.y);

		//console.log(pt);
		if(this.ham.hitTest(pt.x,pt.y)){
			alert('save by the ham');
		}else {
			switch(arr[0]){
				case this.goal.right_crossbar:
					alert('wide right');
				break;
				case this.goal.left_crossbar:
					alert('wide left');
				break;
				case this.goal.top_crossbar:
					alert('off the crossbar');
				break;
				default:
					alert('goal!!!!');
				break;
			}
		}

	},
	loadAssets:function(){
		//view-source:http://localhost/EaselJs/examples/SpriteSheet.html
		manifest = [
			{src:"img/sprite_turkey.png",id:"turkey"}
		];
		if(createJS.Sound.initializeDefaultPlugins()){
			//add audio to manifest
			//manifest.push();
		}
		this.loader = new createjs.LoadQueue(false);

		var lis = this.loader.addEventListener("complete", function(event){
			Game.loader.removeEventListener('complete',lis);
			Game.onAssetsLoaded(event);
		});
		this.loader.loadManifest(manifest);

	},
	onAssetsLoaded:function(event){
		console.log(event);
		//TODO wrap this all in a click/touch to play event
		this.turkey.buildSprite(Game.loader.getResult("turkey"));
		this.startGame();
	},
	startGame:function(){
		this.goal.on('click',
			function(event){
				Game.onShot(event);
			}
		);
		createjs.Ticker.setFPS(60);
		createjs.Ticker.addEventListener("tick", this.stage);
	}

};

$(document).ready(function(){
	//alert("let's do it");
	Game.init();
});

$(window).load(function(){

});

<commit_msg>game has been put into a proper class with a namespace, this will hopefully aid in mobile playback of sound<commit_after>
this.hamvturkey = this.hamvturkey || {};
(function(){

	function Game(){
		this.init();
	}
	Game.prototype = {
			stage:null,
			turkey:null,
			goal:null,
			ham:null,
			loader:null,

			init:function(){
				this.stage = new createjs.Stage("gameCanvas");
				this.turkey = this.stage.addChild(new Turkey('blue'));
				this.turkey.x = 195;
				this.turkey.y = 100;
				this.goal = new Goal(200,100,12);
				this.goal.x = 100;
				this.goal.y = 60;
				this.stage.addChildAt(this.goal,0);
				this.ham =  this.goal.addChild(new Ham('red',200));
				this.ham.x = 0;
				this.ham.y = 20;
				//
				this.loadAssets();
			},
			onShot:function(event){
				console.log(event);
				var stageX = event.stageX;
				var stageY = event.stageY;
				var p = this.stage.addChild(new Puck());
				p.x = 300;
				p.y = 345;

				var proxy = createjs.proxy(this.onPuckContact,this);
				p.on('hit',proxy);
				//to be called after shot animation
				this.turkey.shoot(
					function(){
						p.fire(event.stageX,event.stageY);
					}
				);
				//play the sound here

			},
			onPuckContact: function (event){
				//console.log('shoot!');
				var puck = event.currentTarget;
				var pt = this.goal.globalToLocal(puck.x,puck.y);
				var arr = this.goal.getObjectsUnderPoint(pt.x,pt.y);
				//console.log(pt);
				if(this.ham.hitTest(pt.x,pt.y)){
					alert('save by the ham');
				}else {
					switch(arr[0]){
						case this.goal.right_crossbar:
							alert('wide right');
						break;
						case this.goal.left_crossbar:
							alert('wide left');
						break;
						case this.goal.top_crossbar:
							alert('off the crossbar');
						break;
						default:
							alert('goal!!!!');
						break;
					}
				}

			},
			loadAssets:function(){
				//view-source:http://localhost/EaselJs/examples/SpriteSheet.html
				manifest = [
					{src:"img/sprite_turkey.png",id:"turkey"}
				];
				if(createjs.Sound.initializeDefaultPlugins()){
					//add audio to manifest
					//manifest.push();
				}
				this.loader = new createjs.LoadQueue(false);
				this.loader.addEventListener("complete", createjs.proxy(this.onAssetsLoaded,this));
				this.loader.loadManifest(manifest);
			},
			onAssetsLoaded:function(event){
				console.log(event);
				//TODO wrap this all in a "click/touch to play" event
				this.turkey.buildSprite(this.loader.getResult("turkey"));
				this.startGame();
			},
			startGame:function(){
				createjs.Ticker.setFPS(60);
				createjs.Ticker.addEventListener("tick", this.stage);
				this.goal.on('click',createjs.proxy(this.onShot,this));
			}

	}
	hamvturkey.Game = Game;
}());

var game, isMobile;
$(document).ready(function(){
	//alert("let's do it");
	if(isMobile){
		//launch game on touch prompt
	} else {
		game = new hamvturkey.Game();
	}
	//Game.init();
});

$(window).load(function(){

});

<|endoftext|>


<commit_before>//Validate parameters:
//ps are the params defined in the metamodel
//t is the tuple with parameters to pass
function validate$params(ps,t,msg,nothrow) {
  if (t.t===Nothing)return true;
  if (!ps || ps.length==0) {
    if (t.t===Empty)return true;
  } else if (t.t==='T') {
    if (ps.length==t.l.length) {
      //TODO check each parameter
      for (var i=0;i<ps.length;i++) {
        if (!extendsType(t.l[i],ps[i].$t)) {
          if (nothrow)return false;else throw IncompatibleTypeException$meta$model(msg);
        }
      }
      return true;
    }
  } else if (t.t===Empty) {
    if (!ps || ps.length===0)return true;
  } else if (t.t==='u' && ps.length===1) {
    if (extendsType(ps[0].$t,t))return true;
  } else { //it's already a tuple, navigate it
    console.trace("TODO!!!! validate$params with Tuple type");
  }
  if (nothrow)return false;
  throw IncompatibleTypeException$meta$model(msg);
}
function validate$typeparams(t,tparms,types) {
  if (tparms) {
    if (types===undefined||types.size<1)
      throw TypeApplicationException$meta$model("Missing type arguments");
    if (!types.$_get)types=types.sequence();
    var i=0;
    t.a={};
    for (var tp in tparms) {
      var _type=types.$_get(i);
      if (_type===undefined)
        throw TypeApplicationException$meta$model("Missing type argument for " + tp);
      var _tp = tparms[tp];
      var _ta = _type===nothingType$meta$model()?{t:Nothing}:_type.tipo;
      t.a[tp]= _ta.t ? _ta : {t:_type.tipo};
      if ((_tp.sts && _tp.sts.length>0) || (_tp.of && _tp.of.length > 0)) {
        var restraints=(_tp.sts && _tp.sts.length>0)?_tp.sts:_tp.of;
        for (var j=0; j<restraints.length;j++) {
          var _r=restraints[j];if(typeof(_r)==='function')_r=getrtmm$$(_r).$t;
          if (!extendsType(t.a[tp],_r))
            throw TypeApplicationException$meta$model("Type argument for " + tp + " violates type parameter constraints");
        }
      }
      i++;
    }
  }
}
//Convert an array of parameters (value of ps:[]) into a Tuple
function tupleize$params(ps,aux) {
  if (!ps || ps.length==0)return {t:Empty};
  var tupa={t:'T',l:[]};
  for (var i=ps.length-1; i>=ps.length;i--) {
    var e=ps[i].$t;
    if (typeof(e)==='string'&&aux&&aux[e])e=aux[e];
    if (tupa.t==='T') {//tuple
      tupa.l.unshift(e);
    } else { //union
      tupa={t:'T',l:[e,tupa]};
    }
    if (ps[i].def) {
      tupa={t:'u',l:[{t:Empty},tupa]};
    }
  }
  return tupa;
}
//Resolve a type argument by looking into the metamodel,
//as well as the type arguments provided (if any)
function resolve$typearg(ta,mm,$$targs$$) {
  var r;
  if ($$targs$$ && $$targs$$[ta]) {
    r=$$targs$$[ta];
    if (typeof(t)!=='string')return r;
  }
  r=mm.tp?mm.tp[ta]:undefined;
  while (!r && mm.$cont) {
    mm=mm.$cont;
    if (mm.tp)r=mm.tp[ta];
  }
  if (r) {
    if (r.sts)
      return r.sts.length==1?r.sts[0]:{t:'i',l:r.sts};
    return {t:Anything};
  }
  console.log("MISSING definition of type argument " + ta + " in " + qname$(mm));
  return {t:Anything};
}

function convert$params(mm,a,$$targs$$) {
  var ps=mm.ps;
  if (ps===undefined || ps.length===0){
    if (a && a.size>0)
      throw InvocationException$meta$model("Passing parameters to no-args callable");
    return [];
  }
  if (a===undefined)a=[];
  else if (a.nativeArray)a=a.nativeArray();
  var fa=[];
  var sarg;
  for (var i=0; i<ps.length;i++) { //check def/seq params
    var p=ps[i];
    var val_t=restype2$(sarg?sarg.$$targs$$.a.Element$Iterable:p.$t,$$targs$$);
    if (typeof(val_t)==='string')val_t=resolve$typearg(val_t,mm,$$targs$$);
    if (a[i]===undefined) {
      if (p.def||p.seq) {
        if (p.seq && p.$t.t===Sequence)
          throw InvocationException$meta$model("Not enough arguments to function. Expected 1 but got only 0");
        fa.push(undefined);
      } else {
        throw InvocationException$meta$model("Wrong number of arguments (should be " + ps.length + ")");
      }
    } else if (sarg) {
      sarg.push(a[i]);
    } else if (p.seq) {
      for (var eta in p.$t.a)if(eta.startsWith("Element$"))val_t=p.$t.a[eta];
      if (typeof(val_t)==='string')val_t=resolve$typearg(val_t,mm,$$targs$$);
      if (is$(a[i],{t:Iterable,a:{Element$Iterable:val_t}})) {
        fa.push(a[i]);
        val_t={t:Iterable,a:{Element$Iterable:val_t}};
      } else {
        sarg=[].rt$(val_t); fa.push(sarg);
        for (var j=i; j<a.size;j++){
          if (!is$(a[j],val_t))throw IncompatibleTypeException$meta$model("Wrong type for argument " + j + ", expected " + typeLiteral$meta({Type$typeLiteral:val_t},$$targs$$).string + " got " + className(a[j]));
          sarg.push(a[j]);
        }
        i=j;
      }
    } else {
      fa.push(a[i]);
    }
    if (a[i]!==undefined && !is$(a[i],val_t))throw IncompatibleTypeException$meta$model("Wrong type for argument " + i + ", expected " + typeLiteral$meta({Type$typeLiteral:val_t},$$targs$$).string + " got " + className(a[i]));
  }
  if (a.size>i)throw InvocationException$meta$model("Too many arguments");
  a = fa;
  return a;
}
<commit_msg>how the hell has this typo managed to remain here for so long is beyond me.<commit_after>//Validate parameters:
//ps are the params defined in the metamodel
//t is the tuple with parameters to pass
function validate$params(ps,t,msg,nothrow) {
  if (t.t===Nothing)return true;
  if (!ps || ps.length==0) {
    if (t.t===Empty)return true;
  } else if (t.t==='T') {
    if (ps.length==t.l.length) {
      //TODO check each parameter
      for (var i=0;i<ps.length;i++) {
        if (!extendsType(t.l[i],ps[i].$t)) {
          if (nothrow)return false;else throw IncompatibleTypeException$meta$model(msg);
        }
      }
      return true;
    }
  } else if (t.t===Empty) {
    if (!ps || ps.length===0)return true;
  } else if (t.t==='u' && ps.length===1) {
    if (extendsType(ps[0].$t,t))return true;
  } else { //it's already a tuple, navigate it
    console.trace("TODO!!!! validate$params with Tuple type");
  }
  if (nothrow)return false;
  throw IncompatibleTypeException$meta$model(msg);
}
function validate$typeparams(t,tparms,types) {
  if (tparms) {
    if (types===undefined||types.size<1)
      throw TypeApplicationException$meta$model("Missing type arguments");
    if (!types.$_get)types=types.sequence();
    var i=0;
    t.a={};
    for (var tp in tparms) {
      var _type=types.$_get(i);
      if (_type===undefined)
        throw TypeApplicationException$meta$model("Missing type argument for " + tp);
      var _tp = tparms[tp];
      var _ta = _type===nothingType$meta$model()?{t:Nothing}:_type.tipo;
      t.a[tp]= _ta.t ? _ta : {t:_type.tipo};
      if ((_tp.sts && _tp.sts.length>0) || (_tp.of && _tp.of.length > 0)) {
        var restraints=(_tp.sts && _tp.sts.length>0)?_tp.sts:_tp.of;
        for (var j=0; j<restraints.length;j++) {
          var _r=restraints[j];if(typeof(_r)==='function')_r=getrtmm$$(_r).$t;
          if (!extendsType(t.a[tp],_r))
            throw TypeApplicationException$meta$model("Type argument for " + tp + " violates type parameter constraints");
        }
      }
      i++;
    }
  }
}
//Convert an array of parameters (value of ps:[]) into a Tuple
function tupleize$params(ps,aux) {
  if (!ps || ps.length==0)return {t:Empty};
  var tupa={t:'T',l:[]};
  for (var i=ps.length-1; i>=ps.length;i--) {
    var e=ps[i].$t;
    if (typeof(e)==='string'&&aux&&aux[e])e=aux[e];
    if (tupa.t==='T') {//tuple
      tupa.l.unshift(e);
    } else { //union
      tupa={t:'T',l:[e,tupa]};
    }
    if (ps[i].def) {
      tupa={t:'u',l:[{t:Empty},tupa]};
    }
  }
  return tupa;
}
//Resolve a type argument by looking into the metamodel,
//as well as the type arguments provided (if any)
function resolve$typearg(ta,mm,$$targs$$) {
  var r;
  if ($$targs$$ && $$targs$$[ta]) {
    r=$$targs$$[ta];
    if (typeof(r)!=='string')return r;
  }
  r=mm.tp?mm.tp[ta]:undefined;
  while (!r && mm.$cont) {
    mm=mm.$cont;
    if (mm.tp)r=mm.tp[ta];
  }
  if (r) {
    if (r.sts)
      return r.sts.length==1?r.sts[0]:{t:'i',l:r.sts};
    return {t:Anything};
  }
  console.log("MISSING definition of type argument " + ta + " in " + qname$(mm));
  return {t:Anything};
}

function convert$params(mm,a,$$targs$$) {
  var ps=mm.ps;
  if (ps===undefined || ps.length===0){
    if (a && a.size>0)
      throw InvocationException$meta$model("Passing parameters to no-args callable");
    return [];
  }
  if (a===undefined)a=[];
  else if (a.nativeArray)a=a.nativeArray();
  var fa=[];
  var sarg;
  for (var i=0; i<ps.length;i++) { //check def/seq params
    var p=ps[i];
    var val_t=restype2$(sarg?sarg.$$targs$$.a.Element$Iterable:p.$t,$$targs$$);
    if (typeof(val_t)==='string')val_t=resolve$typearg(val_t,mm,$$targs$$);
    if (a[i]===undefined) {
      if (p.def||p.seq) {
        if (p.seq && p.$t.t===Sequence)
          throw InvocationException$meta$model("Not enough arguments to function. Expected 1 but got only 0");
        fa.push(undefined);
      } else {
        throw InvocationException$meta$model("Wrong number of arguments (should be " + ps.length + ")");
      }
    } else if (sarg) {
      sarg.push(a[i]);
    } else if (p.seq) {
      for (var eta in p.$t.a)if(eta.startsWith("Element$"))val_t=p.$t.a[eta];
      if (typeof(val_t)==='string')val_t=resolve$typearg(val_t,mm,$$targs$$);
      if (is$(a[i],{t:Iterable,a:{Element$Iterable:val_t}})) {
        fa.push(a[i]);
        val_t={t:Iterable,a:{Element$Iterable:val_t}};
      } else {
        sarg=[].rt$(val_t); fa.push(sarg);
        for (var j=i; j<a.size;j++){
          if (!is$(a[j],val_t))throw IncompatibleTypeException$meta$model("Wrong type for argument " + j + ", expected " + typeLiteral$meta({Type$typeLiteral:val_t},$$targs$$).string + " got " + className(a[j]));
          sarg.push(a[j]);
        }
        i=j;
      }
    } else {
      fa.push(a[i]);
    }
    if (a[i]!==undefined && !is$(a[i],val_t))throw IncompatibleTypeException$meta$model("Wrong type for argument " + i + ", expected " + typeLiteral$meta({Type$typeLiteral:val_t},$$targs$$).string + " got " + className(a[i]));
  }
  if (a.size>i)throw InvocationException$meta$model("Too many arguments");
  a = fa;
  return a;
}
<|endoftext|>


<commit_before>import test from 'tape'
import Entry, { version } from '../entry'
import moment from 'moment'

test('Entry class has a version number', t => {
  const e = new Entry('8am-10am worked on things')
  t.ok(version >= 1, 'current version is 1')
  t.equals(e.version, version, 'new entries get version')

  t.end()
})

test('simple entry construction 8am-10pm', t => {
  const e = new Entry('8am-10am worked on things')
  const { start, end } = e.getDates()
  t.ok(e.hasDates, 'entry has dates')
  t.equals(e.message, '8am-10am worked on things')
  t.equals(start.getHours(), 8, 'start is 8am')
  t.equals(end.getHours(), 10, 'start is 10am')

  t.end()
})

test('simple entry construction 8am-5pm', t => {
  const e = new Entry('8am-5pm worked on things')
  const { start, end } = e.getDates()
  t.ok(e.hasDates, 'entry has dates')
  t.equals(e.message, '8am-5pm worked on things')
  t.equals(start.getHours(), 8, 'start is 8am')
  t.equals(end.getHours(), 17, 'end is 5pm')

  t.end()
})

test('no times specified does not generate dates', t => {
  const e = new Entry('worked on some things')
  const { start, end } = e.getDates()
  t.notOk(e.hasDates, 'flag indicates that no dates are present')
  t.notOk(start, 'no start date provided')
  t.notOk(end, 'no end date provided')

  t.end()
})

test('passing date influences the dates', t => {
  const date = new Date('Jan 25, 2015 0:00:00')
  const msg = '8am-5pm worked on some things'
  const e = new Entry(msg, {date})
  const { start, end } = e.getDates()

  t.ok(moment(start).isSame(date, 'day'), 'start has the same day')
  t.ok(moment(end).isSame(date, 'day'), 'end has the same day')

  t.end()
})

test('no date defaults to today', t => {
  const date = new Date()
  const msg = '8am-5pm worked on some things'
  const e = new Entry(msg)
  const { start, end } = e.getDates()

  t.ok(moment(start).isSame(date, 'day'), 'start date is today')
  t.ok(moment(end).isSame(date, 'day'), 'end date is today')

  t.end()
})

test('duration set for 8am-10am', t => {
  const e = new Entry('8am-10am worked on some things')

  t.ok(e.duration, 'duration is present')
  t.equals(e.duration.hour, 2, '8am-10am is 2 hours')
  t.equals(e.duration.minute, 0, '8am-10am has 0 minutes')

  t.end()
})

test('duration set for 8am-1:30pm', t => {
  const e = new Entry('8am-1:30pm worked on some things')

  t.equals(e.duration.hour, 5, '8am-1:30pm is 5 hours')
  t.equals(e.duration.minute, 30, '8am-1:30pm trails 30 min')

  t.end()
})

test('duration set for 11pm-2am', t => {
  const e = new Entry('11pm-2am worked on some things')

  t.equals(e.duration.hour, 3, '11pm-2am is 3 hours')

  t.end()
})

test('includes yesterday in message', t => {
  const yesterday = moment().subtract(1, 'day')
  const e = new Entry('yesterday 4-5pm worked on some things #test')

  t.ok(yesterday.isSame(e.start, 'day'), 'sets start to yesterday')
  t.ok(yesterday.isSame(e.end, 'day'), 'sets end to yesterday')
  t.equals(e.time, 'yesterday 4-5pm', 'time component includes \'yesterday\'')

  t.end()
})

test('specific day in message', t => {
  const date = new Date(2016, 2, 24) // Thurs, March 24
  const monday = moment(new Date(2016, 2, 21)) // Mon, March 21
  const e = new Entry('monday 4-5pm worked on some things #test', {date})

  t.ok(monday.isSame(e.start, 'day'), 'start is monday')
  t.ok(monday.isSame(e.end, 'day'), 'end is monday')

  t.end()
})

test('constructor assigns _id', t => {
  const e = new Entry('8am-10am worked on some things')

  t.ok(e._id, '_id is ok')
  t.end()
})

test('parse #tags', t => {
  const e = new Entry('8-10am worked on things #tag1 #tag2')

  t.ok(e.tags.has('#tag1'), 'tags are parsed into a Set')
  t.ok(e.tags.has('#tag2'), 'tags are parsed into a Set')
  t.end()
})

test('parse unique #tags', t => {
  const e = new Entry('8-10am worked on things #tag1 #tag1')

  t.equals(e.tags.size, 1, 'tags only appear once')
  t.ok(e.tags.has('#tag1'), 'tags are parsed')
  t.end()
})

test('parse #hyphened-tags and #underscored_tags', t => {
  const e = new Entry('8-10am worked on things #hyphened-tag #underscored_tag')

  t.ok(e.tags.has('#hyphened-tag'), 'hyphened tag is parsed into a Set')
  t.ok(e.tags.has('#underscored_tag'), 'underscore tag is parsed into a Set')
  t.end()
})

test('parsed time string is present', t => {
  const e = new Entry('8-10am worked on things')

  t.equals(e.time, '8-10am', 'entry.time contains matched string')
  t.end()
})

test('toJSON() returns a json obj', t => {
  const e = new Entry('8am-10am worked on some things #tag1 #tag2')

  const json = e.toJSON()
  t.equals(json.message, '8am-10am worked on some things #tag1 #tag2', 'message')
  t.ok(json.hasDates, 'hasDates')
  t.equals(e.start, json.start, 'start')
  t.equals(e.end, json.end, 'end')
  t.equals(json.duration.seconds, 2*60*60, 'duration seconds')
  t.equals(json.time, e.time, 'time')
  t.equals(json._id, e._id, '_id')
  t.equals(json.version, version, 'version')
  t.deepEquals(json.tags, [...e.tags], 'tags array')
  t.ok(moment(json.startArr).isSame(json.start), 'start and startArr are same date')
  t.ok(moment(json.endArr).isSame(json.end), 'end and endArr are same date')
  t.ok(json.startArr instanceof Array, 'startArr is an array')
  t.ok(json.endArr instanceof Array, 'endArr is an array')

  t.end()
})

test('fromJSON() will create an Entry from existing document', t => {
  const date = new Date('Jan 25, 2015 0:00:00')
  const existing = new Entry('8am-10am worked on things #tag1 #tag2', {date})
  const json = existing.toJSON()
  const e = Entry.fromJSON(json)

  t.equals(existing._id, e._id, '_id matches')
  t.equals(existing.version, e.version, 'version matches')
  t.equals(existing.message, e.message, 'message matches')
  t.equals(e.tags.size, 2, '2 tags')
  t.equals(moment(existing.start).toString(), moment(e.start).toString(), 'start matches')
  t.equals(moment(existing.end).toString(), moment(e.end).toString(), 'end matches')
  t.equals(e.time, '8am-10am', 'time is preserved')

  t.end()

})
<commit_msg>test for a specific date<commit_after>import test from 'tape'
import Entry, { version } from '../entry'
import moment from 'moment'

test('Entry class has a version number', t => {
  const e = new Entry('8am-10am worked on things')
  t.ok(version >= 1, 'current version is 1')
  t.equals(e.version, version, 'new entries get version')

  t.end()
})

test('simple entry construction 8am-10pm', t => {
  const e = new Entry('8am-10am worked on things')
  const { start, end } = e.getDates()
  t.ok(e.hasDates, 'entry has dates')
  t.equals(e.message, '8am-10am worked on things')
  t.equals(start.getHours(), 8, 'start is 8am')
  t.equals(end.getHours(), 10, 'start is 10am')

  t.end()
})

test('simple entry construction 8am-5pm', t => {
  const e = new Entry('8am-5pm worked on things')
  const { start, end } = e.getDates()
  t.ok(e.hasDates, 'entry has dates')
  t.equals(e.message, '8am-5pm worked on things')
  t.equals(start.getHours(), 8, 'start is 8am')
  t.equals(end.getHours(), 17, 'end is 5pm')

  t.end()
})

test('no times specified does not generate dates', t => {
  const e = new Entry('worked on some things')
  const { start, end } = e.getDates()
  t.notOk(e.hasDates, 'flag indicates that no dates are present')
  t.notOk(start, 'no start date provided')
  t.notOk(end, 'no end date provided')

  t.end()
})

test('passing date influences the dates', t => {
  const date = new Date('Jan 25, 2015 0:00:00')
  const msg = '8am-5pm worked on some things'
  const e = new Entry(msg, {date})
  const { start, end } = e.getDates()

  t.ok(moment(start).isSame(date, 'day'), 'start has the same day')
  t.ok(moment(end).isSame(date, 'day'), 'end has the same day')

  t.end()
})

test('no date defaults to today', t => {
  const date = new Date()
  const msg = '8am-5pm worked on some things'
  const e = new Entry(msg)
  const { start, end } = e.getDates()

  t.ok(moment(start).isSame(date, 'day'), 'start date is today')
  t.ok(moment(end).isSame(date, 'day'), 'end date is today')

  t.end()
})

test('duration set for 8am-10am', t => {
  const e = new Entry('8am-10am worked on some things')

  t.ok(e.duration, 'duration is present')
  t.equals(e.duration.hour, 2, '8am-10am is 2 hours')
  t.equals(e.duration.minute, 0, '8am-10am has 0 minutes')

  t.end()
})

test('duration set for 8am-1:30pm', t => {
  const e = new Entry('8am-1:30pm worked on some things')

  t.equals(e.duration.hour, 5, '8am-1:30pm is 5 hours')
  t.equals(e.duration.minute, 30, '8am-1:30pm trails 30 min')

  t.end()
})

test('duration set for 11pm-2am', t => {
  const e = new Entry('11pm-2am worked on some things')

  t.equals(e.duration.hour, 3, '11pm-2am is 3 hours')

  t.end()
})

test('includes yesterday in message', t => {
  const yesterday = moment().subtract(1, 'day')
  const e = new Entry('yesterday 4-5pm worked on some things #test')

  t.ok(yesterday.isSame(e.start, 'day'), 'sets start to yesterday')
  t.ok(yesterday.isSame(e.end, 'day'), 'sets end to yesterday')
  t.equals(e.time, 'yesterday 4-5pm', 'time component includes \'yesterday\'')

  t.end()
})

test('specific day of week in message', t => {
  const date = new Date(2016, 2, 24) // Thurs, March 24
  const monday = moment(new Date(2016, 2, 21)) // Mon, March 21
  const e = new Entry('monday 4-5pm worked on some things #test', {date})

  t.ok(monday.isSame(e.start, 'day'), 'start is monday')
  t.ok(monday.isSame(e.end, 'day'), 'end is monday')

  t.end()
})

test('specific date in message', t => {
  const date = new Date(2016, 2, 24) // Thurs, March 24
  const mar15 = moment(new Date(2016, 2, 15)) // Mon, March 21
  const e = new Entry('Mar 15 4-5pm worked on some things #test', {date})

  t.ok(monday.isSame(e.start, 'day'), 'start is mar 15')
  t.ok(monday.isSame(e.end, 'day'), 'end is mar 15')

  t.end()
})

test('constructor assigns _id', t => {
  const e = new Entry('8am-10am worked on some things')

  t.ok(e._id, '_id is ok')
  t.end()
})

test('parse #tags', t => {
  const e = new Entry('8-10am worked on things #tag1 #tag2')

  t.ok(e.tags.has('#tag1'), 'tags are parsed into a Set')
  t.ok(e.tags.has('#tag2'), 'tags are parsed into a Set')
  t.end()
})

test('parse unique #tags', t => {
  const e = new Entry('8-10am worked on things #tag1 #tag1')

  t.equals(e.tags.size, 1, 'tags only appear once')
  t.ok(e.tags.has('#tag1'), 'tags are parsed')
  t.end()
})

test('parse #hyphened-tags and #underscored_tags', t => {
  const e = new Entry('8-10am worked on things #hyphened-tag #underscored_tag')

  t.ok(e.tags.has('#hyphened-tag'), 'hyphened tag is parsed into a Set')
  t.ok(e.tags.has('#underscored_tag'), 'underscore tag is parsed into a Set')
  t.end()
})

test('parsed time string is present', t => {
  const e = new Entry('8-10am worked on things')

  t.equals(e.time, '8-10am', 'entry.time contains matched string')
  t.end()
})

test('toJSON() returns a json obj', t => {
  const e = new Entry('8am-10am worked on some things #tag1 #tag2')

  const json = e.toJSON()
  t.equals(json.message, '8am-10am worked on some things #tag1 #tag2', 'message')
  t.ok(json.hasDates, 'hasDates')
  t.equals(e.start, json.start, 'start')
  t.equals(e.end, json.end, 'end')
  t.equals(json.duration.seconds, 2*60*60, 'duration seconds')
  t.equals(json.time, e.time, 'time')
  t.equals(json._id, e._id, '_id')
  t.equals(json.version, version, 'version')
  t.deepEquals(json.tags, [...e.tags], 'tags array')
  t.ok(moment(json.startArr).isSame(json.start), 'start and startArr are same date')
  t.ok(moment(json.endArr).isSame(json.end), 'end and endArr are same date')
  t.ok(json.startArr instanceof Array, 'startArr is an array')
  t.ok(json.endArr instanceof Array, 'endArr is an array')

  t.end()
})

test('fromJSON() will create an Entry from existing document', t => {
  const date = new Date('Jan 25, 2015 0:00:00')
  const existing = new Entry('8am-10am worked on things #tag1 #tag2', {date})
  const json = existing.toJSON()
  const e = Entry.fromJSON(json)

  t.equals(existing._id, e._id, '_id matches')
  t.equals(existing.version, e.version, 'version matches')
  t.equals(existing.message, e.message, 'message matches')
  t.equals(e.tags.size, 2, '2 tags')
  t.equals(moment(existing.start).toString(), moment(e.start).toString(), 'start matches')
  t.equals(moment(existing.end).toString(), moment(e.end).toString(), 'end matches')
  t.equals(e.time, '8am-10am', 'time is preserved')

  t.end()

})
<|endoftext|>


<commit_before>var winston = require('winston');
var express = require('express');
var router = express.Router();
var Planet = require('mongoose').model('Planet');
var ObjectId = require('mongoose').Types.ObjectId;

router.get('/', function(req, res, next){
  Planet.find({}, {'_id':false}, function(err, data) {
    if(!err) {
      res.status(200).json(data);
    }
  })
});

router.get('/:id', function (req, res, next) {
  var planetId = req.params.id;
  Planet.find({_id: new ObjectID(planetId)}, {_id: false}, function(err, data) {
    if(!err) {
      res.status(200).json(data);
    }
  })
});

router.post('/', function(req, res, next) {
  var planetData = req.body;
  var newPlanet = new Planet(planetData);
  newPlanet.save(function(err, saved) {
    if(!err) {
      res.status(200).json(saved);
    } else {
      console.log(err);
    }
  })
});

router.delete('/:id', function(req, res, next) {
  var planetId = req.params.id;
  Planet.remove({_id: new ObjectId(planetId)}, function(err){
    if(!err) {
      res.status(200).send(true);
    }
  });
});

router.patch('/:id', function(req, res, next) {
  var planetId = req.params.id;
  var planetData = req.body;
  Planet.update({_id: planetId}, {$set: planetData}, function(err) {
    if(!err) {
      res.status(200).end();
    }
  });
});

module.exports = router; //When calling require('tasks'), we get the router.<commit_msg>changed objectId<commit_after>var winston = require('winston');
var express = require('express');
var router = express.Router();
var Planet = require('mongoose').model('Planet');
var ObjectId = require('mongoose').Types.ObjectId;

router.get('/', function(req, res, next){
  Planet.find({}, {'_id':false}, function(err, data) {
    if(!err) {
      res.status(200).json(data);
    }
  })
});

router.get('/:id', function (req, res, next) {
  var planetId = req.params.id;
  Planet.find({_id: new ObjectId(planetId)}, {_id: false}, function(err, data) {
    if(!err) {
      res.status(200).json(data);
    }
  })
});

router.post('/', function(req, res, next) {
  var planetData = req.body;
  var newPlanet = new Planet(planetData);
  newPlanet.save(function(err, saved) {
    if(!err) {
      res.status(200).json(saved);
    } else {
      console.log(err);
    }
  })
});

router.delete('/:id', function(req, res, next) {
  var planetId = req.params.id;
  Planet.remove({_id: new ObjectId(planetId)}, function(err){
    if(!err) {
      res.status(200).send(true);
    }
  });
});

router.patch('/:id', function(req, res, next) {
  var planetId = req.params.id;
  var planetData = req.body;
  Planet.update({_id: planetId}, {$set: planetData}, function(err) {
    if(!err) {
      res.status(200).end();
    }
  });
});

module.exports = router; //When calling require('tasks'), we get the router.<|endoftext|>


<commit_before>"use strict";

var test = require("tape");
var instantiate = require("..");
var request = require("../lib/request.js");

var opts = {
  index: "index",
  type: "articles",
  host: process.env.ES_HOST,
  port: Number(process.env.ES_PORT)
};

console.log(opts);

var articles = instantiate(opts);

test("wipe db", function (t) {

  var opts = {
    method: "DELETE",
    uri: "http://127.0.0.1:9200/index/articles/"
  };
  request(opts, function () {

    t.end();
  });

});

test("instantiate should return an object", function (t) {

  t.equals(typeof articles, "object", "instantiate returns object");
  t.end();
});

test("object should have a create, findOne, update, delete and query methods", function (t) {

  ["create", "findOne", "update", "del"].forEach(function(q) {

    t.ok(articles.hasOwnProperty(q), "object has " + q + " property");
  });

  t.end();
});

test("#create should create new entry in database", function (t) {

  articles.create({
    name: "hello",
    message: "yes",
    id: 1234
  }, function (e, r) {

    console.log(arguments);

    t.notOk(e, "no error received");
    t.ok(r.created, "object created");

    var opts = {
      method: "GET",
      uri: "http://127.0.0.1:9200/index/articles/1234"
    };
    request(opts, function (e, r) {

      t.ok(r.found, "object created");
      t.end();
    });
  });
});

test("#create should with id", function (t) {

  articles.create({
    name: "hello",
    message: "yes",
  }, function (e, r) {

    t.notOk(e, "no error received");
    t.ok(r.created, "object created");
    var opts = {
      method: "GET",
      uri: "http://127.0.0.1:9200/index/articles/" + r._id
    };
    request(opts, function (e, r) {

      t.ok(r.found, "object created");
      t.end();
    });
  });
});

test("#findOne should return match from database if there is one", function (t) {

  articles.findOne({
    id: 1234
  }, function (e, r) {

    t.notOk(e, "no error returned");
    t.ok(r.found, "object found");
    t.ok(r._source.name, "hello", "correct obj returned");
    t.end();
  });
});

test("#findOne should return err if no matches", function (t) {

  articles.findOne({
    id: 4321
  }, function (e, r) {

    t.ok(e, "error returned");
    t.notOk(r, "no data passed to cb");
    t.end();
  });
});

test("#findOne should return err if no id", function (t) {

  articles.findOne({
    hid: 4321
  }, function (e, r) {

    t.ok(e, "error returned");
    t.notOk(r, "no data passed to cb");
    t.end();
  });
});

test("#update should update entry in database", function (t) {

  articles.update({
    id: 1234
  }, {
    name: "bob"
  }, function (e) {

    t.notOk(e, "error not returned");

    var opts = {
      method: "GET",
      uri: "http://127.0.0.1:9200/index/articles/1234"
    };
    request(opts, function (e, r) {

      t.ok(r.found, "object created");
      t.equals(r._source.name, "bob", "object updated");
      t.equals(r._source.message, "yes", "original object properties not destroyed");
      t.end();
    });

  });

});

test("#update should return err if no match in db", function (t) {

  articles.update({
    id: 4321
  }, {
    name: "bob"
  }, function (e) {

    t.ok(e, "error returned");
    t.end();
  });

});

test("#update should return err if no id", function (t) {

  articles.update({
    hid: 4321
  }, {
    name: "bob"
  }, function (e) {

    t.ok(e, "error returned");
    t.end();
  });

});

test("#del should delete entry from database", function (t) {

  articles.del({
    id: 1234
  }, function (e, r) {

    t.ok(r.found, "record found");
    t.notOk(e, "error not returned");

    var opts = {
      method: "GET",
      uri: "http://127.0.0.1:9200/index/articles/1234"
    };
    request(opts, function (e, r) {
      t.notOk(r.found, "object deleted");
      t.end();
    });
  });
});

test("#del should throw err if no match in db", function (t) {

  articles.del({
    id: 1234
  }, function (e) {

    t.ok(e, "error returned");
    t.end();
  });

});

test("#del should throw err if no id", function (t) {

  articles.del({
    hid: 1234
  }, function (e) {

    t.ok(e, "error returned");
    t.end();
  });

});

test("wipe db", function (t) {

  var opts = {
    method: "DELETE",
    uri: "http://127.0.0.1:9200/index/articles/"
  };
  request(opts, function () {

    t.end();
  });

});
<commit_msg>remove console logs<commit_after>"use strict";

var test = require("tape");
var instantiate = require("..");
var request = require("../lib/request.js");

var opts = {
  index: "index",
  type: "articles",
  host: process.env.ES_HOST,
  port: Number(process.env.ES_PORT)
};

var articles = instantiate(opts);

test("wipe db", function (t) {

  var opts = {
    method: "DELETE",
    uri: "http://127.0.0.1:9200/index/articles/"
  };
  request(opts, function () {

    t.end();
  });

});

test("instantiate should return an object", function (t) {

  t.equals(typeof articles, "object", "instantiate returns object");
  t.end();
});

test("object should have a create, findOne, update, delete and query methods", function (t) {

  ["create", "findOne", "update", "del"].forEach(function(q) {

    t.ok(articles.hasOwnProperty(q), "object has " + q + " property");
  });

  t.end();
});

test("#create should create new entry in database", function (t) {

  articles.create({
    name: "hello",
    message: "yes",
    id: 1234
  }, function (e, r) {

    t.notOk(e, "no error received");
    t.ok(r.created, "object created");

    var opts = {
      method: "GET",
      uri: "http://127.0.0.1:9200/index/articles/1234"
    };
    request(opts, function (e, r) {

      t.ok(r.found, "object created");
      t.end();
    });
  });
});

test("#create should with id", function (t) {

  articles.create({
    name: "hello",
    message: "yes",
  }, function (e, r) {

    t.notOk(e, "no error received");
    t.ok(r.created, "object created");
    var opts = {
      method: "GET",
      uri: "http://127.0.0.1:9200/index/articles/" + r._id
    };
    request(opts, function (e, r) {

      t.ok(r.found, "object created");
      t.end();
    });
  });
});

test("#findOne should return match from database if there is one", function (t) {

  articles.findOne({
    id: 1234
  }, function (e, r) {

    t.notOk(e, "no error returned");
    t.ok(r.found, "object found");
    t.ok(r._source.name, "hello", "correct obj returned");
    t.end();
  });
});

test("#findOne should return err if no matches", function (t) {

  articles.findOne({
    id: 4321
  }, function (e, r) {

    t.ok(e, "error returned");
    t.notOk(r, "no data passed to cb");
    t.end();
  });
});

test("#findOne should return err if no id", function (t) {

  articles.findOne({
    hid: 4321
  }, function (e, r) {

    t.ok(e, "error returned");
    t.notOk(r, "no data passed to cb");
    t.end();
  });
});

test("#update should update entry in database", function (t) {

  articles.update({
    id: 1234
  }, {
    name: "bob"
  }, function (e) {

    t.notOk(e, "error not returned");

    var opts = {
      method: "GET",
      uri: "http://127.0.0.1:9200/index/articles/1234"
    };
    request(opts, function (e, r) {

      t.ok(r.found, "object created");
      t.equals(r._source.name, "bob", "object updated");
      t.equals(r._source.message, "yes", "original object properties not destroyed");
      t.end();
    });

  });

});

test("#update should return err if no match in db", function (t) {

  articles.update({
    id: 4321
  }, {
    name: "bob"
  }, function (e) {

    t.ok(e, "error returned");
    t.end();
  });

});

test("#update should return err if no id", function (t) {

  articles.update({
    hid: 4321
  }, {
    name: "bob"
  }, function (e) {

    t.ok(e, "error returned");
    t.end();
  });

});

test("#del should delete entry from database", function (t) {

  articles.del({
    id: 1234
  }, function (e, r) {

    t.ok(r.found, "record found");
    t.notOk(e, "error not returned");

    var opts = {
      method: "GET",
      uri: "http://127.0.0.1:9200/index/articles/1234"
    };
    request(opts, function (e, r) {
      t.notOk(r.found, "object deleted");
      t.end();
    });
  });
});

test("#del should throw err if no match in db", function (t) {

  articles.del({
    id: 1234
  }, function (e) {

    t.ok(e, "error returned");
    t.end();
  });

});

test("#del should throw err if no id", function (t) {

  articles.del({
    hid: 1234
  }, function (e) {

    t.ok(e, "error returned");
    t.end();
  });

});

test("wipe db", function (t) {

  var opts = {
    method: "DELETE",
    uri: "http://127.0.0.1:9200/index/articles/"
  };
  request(opts, function () {

    t.end();
  });

});
<|endoftext|>


<commit_before>// pushserv.js
// Requests schedule data of specified token
// Created on 11-10-2015
// Status 0
var request = require('request');
var PushBullet = require('pushbullet');
var mongojs = require('mongojs');
var exchangeAppcode = require('./exchangeAppcode.js');
var strtotime = require('./strtotime.js');
var sendPush = require('./sendPush.js');
var pusher = new PushBullet('nCWCoD4saWNZ8YPqlAxCkPnqcFYvgqL5');
var db = mongojs('userdata', ['users']);

function updateSendNotifications(email, id){
  db.users.update({'email':email}, {$push: {already_sent : id}}, function(){
    console.log('Added sent notification');
  });
}

function notificationIsNotSent(email, id, callback){
  db.users.find({'email':email}, function(err, doc){
    if(err){
      console.log(err);
    } else {
      if(doc[0].already_sent.indexOf(id) == -1){
        callback();
      }
    }
  });
}

function retrieveLeerlingnum(token, callback){
  var url = "https://scmoost.zportal.nl/api/v2/users/~me?access_token=" + token;
  request(url, function(err, response, body){
    if(!err & response.statusCode == 200){
      var leerlingnum = JSON.parse(response.body).response.data[0].code;
      callback(null, leerlingnum);
    } else {
      callback(err, null);
    }
  });
}

function retrieveSchedule(email, leerlingnum, token){
  var curtime = Math.round((new Date().getTime()) / 1000); // Seconds elapsed since 1-1-1970
  var startTime = curtime;
  var endTime = strtotime('next saturday', curtime);

  var roosterurl = 'http://lschoonheid.leerik.nl/beta/?id='+leerlingnum;
  var apiurl = 'https://scmoost.zportal.nl/api/v2/appointments?user=~me&start='+startTime+'&end='+endTime+'&access_token='+token+'&valid='+true;

  request(apiurl, function(err, response, body){
    if (!err && response.statusCode == 200){
      console.log('Succesful request');
      var data = JSON.parse(body).response.data;
      for(var i = 0; i < data.length; i++){
        var les = data[i].subjects;
        var leraar = data[i].teachers;
        if(data[i].cancelled === true){
          var title = les + ' van ' + leraar + ' is vervallen!';
          var body = 'Les vervallen!';
          var title = "";
          var id = data[i].id;
          notificationIsNotSent(email, id, function(){
            sendPush(email, title, body, roosterurl);
            updateSendNotifications(email, id);
          });
        } else if(data[i].modified === true){
          var title = 'Wijziging voor ' + les + ' van ' + leraar;
          var body = data[i].changeDescription;
          var id = data[i].id;
          notificationIsNotSent(email, id, function(){
            sendPush(email, title, body, roosterurl);
            updateSendNotifications(email, id);
          });
        }
      }
    } else {
      console.log('Error occured: ' + err);
      db.close();
    }
  });
}

module.exports = function(){
  console.log('Push server started');
  setInterval(function(){
    db.users.find({first_time: 0}, function(err, docs){
      if(err){
        console.log(err);
      } else {
        for(var i = 0; i < docs.length; i++){
          var email = docs[i].email;
          var token = docs[i].token;
          retrieveLeerlingnum(docs[i].token, function(leerlingnum){
            retrieveSchedule(email, leerlingnum, token);
          });
        }
      }
    });
  }, 15 * 60 * 1000);
};
<commit_msg>Fix roosterurl bug<commit_after>// pushserv.js
// Requests schedule data of specified token
// Created on 11-10-2015
// Status 0
var request = require('request');
var PushBullet = require('pushbullet');
var mongojs = require('mongojs');
var exchangeAppcode = require('./exchangeAppcode.js');
var strtotime = require('./strtotime.js');
var sendPush = require('./sendPush.js');
var pusher = new PushBullet('nCWCoD4saWNZ8YPqlAxCkPnqcFYvgqL5');
var db = mongojs('userdata', ['users']);

function updateSendNotifications(email, id){
  db.users.update({'email':email}, {$push: {already_sent : id}}, function(){
    console.log('Added sent notification');
  });
}

function notificationIsNotSent(email, id, callback){
  db.users.find({'email':email}, function(err, doc){
    if(err){
      console.log(err);
    } else {
      if(doc[0].already_sent.indexOf(id) == -1){
        callback();
      }
    }
  });
}

function retrieveLeerlingnum(token, callback){
  var url = "https://scmoost.zportal.nl/api/v2/users/~me?access_token=" + token;
  request(url, function(err, response, body){
    if(!err & response.statusCode == 200){
      var leerlingnum = JSON.parse(response.body).response.data[0].code;
      callback(null, leerlingnum);
    } else {
      callback(err, null);
    }
  });
}

function retrieveSchedule(email, leerlingnum, token){
  var curtime = Math.round((new Date().getTime()) / 1000); // Seconds elapsed since 1-1-1970
  var startTime = curtime;
  var endTime = strtotime('next saturday', curtime);

  var roosterurl = 'http://lschoonheid.leerik.nl/zermelo/alpha/?id='+leerlingnum;
  var apiurl = 'https://scmoost.zportal.nl/api/v2/appointments?user=~me&start='+startTime+'&end='+endTime+'&access_token='+token+'&valid='+true;

  request(apiurl, function(err, response, body){
    if (!err && response.statusCode == 200){
      console.log('Succesful request');
      var data = JSON.parse(body).response.data;
      for(var i = 0; i < data.length; i++){
        var les = data[i].subjects;
        var leraar = data[i].teachers;
        if(data[i].cancelled === true){
          var title = les + ' van ' + leraar + ' is vervallen!';
          var body = 'Les vervallen!';
          var title = "";
          var id = data[i].id;
          notificationIsNotSent(email, id, function(){
            sendPush(email, title, body, roosterurl);
            updateSendNotifications(email, id);
          });
        } else if(data[i].modified === true){
          var title = 'Wijziging voor ' + les + ' van ' + leraar;
          var body = data[i].changeDescription;
          var id = data[i].id;
          notificationIsNotSent(email, id, function(){
            sendPush(email, title, body, roosterurl);
            updateSendNotifications(email, id);
          });
        }
      }
    } else {
      console.log('Error occured: ' + err);
      db.close();
    }
  });
}

module.exports = function(){
  console.log('Push server started');
  setInterval(function(){
    db.users.find({first_time: 0}, function(err, docs){
      if(err){
        console.log(err);
      } else {
        for(var i = 0; i < docs.length; i++){
          var email = docs[i].email;
          var token = docs[i].token;
          retrieveLeerlingnum(token, function(err, leerlingnum){
            if(!err){
              retrieveSchedule(email, leerlingnum, token);
            } else {
              console.log(err);
            }
          });
        }
      }
    });
  }, 5 * 1000);
};
<|endoftext|>


<commit_before>var path = require('path');
var expect = require('chai').expect;
var pkg = path.normalize(
  path.join(__dirname, '..', '..', '..', 'package.json'));

var HelpDocument = require('../../../lib/help/doc/doc').HelpDocument;

describe('cli-command:', function() {
  it('should listen for help event', function(done) {
    var cli = require('../../..')(pkg, 'mock-help');
    cli.configure({exit: false});
    var args = ['-h'];
    cli
      .on('help', function(data, document) {
        expect(data).to.be.an('object');
        expect(document).to.be.an('object');
        expect(document.sections).to.be.an('array');
        expect(document.write).to.be.a('function');
        document.header.call(this, null);
        document.header.call(this, 'Arguments:');
        var plain = new HelpDocument();
        plain.remove('unknown');
        plain.write(this, data);
      })
      .help()
      .parse(args);
    done();
  });
})
<commit_msg>Complete help class assertions.<commit_after>var path = require('path');
var expect = require('chai').expect;
var pkg = path.normalize(
  path.join(__dirname, '..', '..', '..', 'package.json'));

var HelpDocument = require('../../../lib/help/doc/doc').HelpDocument;

describe('cli-command:', function() {
  it('should listen for help event', function(done) {
    var cli = require('../../..')(pkg, 'mock-help');
    cli.configure({exit: false});
    var args = ['-h'];
    cli
      .on('help', function(data, document) {
        expect(data).to.be.an('object');
        expect(document).to.be.an('object');
        expect(document.sections).to.be.an('array');
        expect(document.write).to.be.a('function');
        document.header.call(this, null);
        document.header.call(this, 'Arguments:');
        var plain = new HelpDocument();
        plain.remove('unknown');
        plain.write(this, data);
        plain.options = function(data, stream, doc) {
          return 'Header'
        }
        plain.write(this, data);
      })
      .help()
      .parse(args);
    done();
  });
})
<|endoftext|>


<commit_before>module.exports = function(config) {
	config.set({
		basePath: '../..'
		, logLevel: 'DEBUG'
		, frameworks: ["jasmine-ajax", "jasmine", "commonjs"]
		, files: ["src/test/spec/*Spec.js", {pattern: "src/main/js/*.js", included: true}]
		, preprocessors: {
			"**/*Spec.js": ["commonjs"]
			, "src/main/js/*.js": ["babel", "commonjs"]
		}
		, browsers: ["Chrome", "Firefox"]
		, singleRun: true
		, babelPreprocessor: {
			options: {
				presets: ['es2015']
				, plugins: ["babel-plugin-add-module-exports"]
			}
		}
	});
};
<commit_msg>Update karma.conf.js<commit_after>module.exports = function(config) {
	config.set({
		basePath: '../..'
		, logLevel: 'DEBUG'
		, frameworks: ["jasmine-ajax", "jasmine", "commonjs"]
		, files: ["src/test/spec/*Spec.js", {pattern: "src/main/js/*.js", included: true}]
		, preprocessors: {
			"**/*Spec.js": ["commonjs"]
			, "src/main/js/*.js": ["babel", "commonjs"]
		}
		, browsers: ["Firefox"]
		, singleRun: true
		, babelPreprocessor: {
			options: {
				presets: ['es2015']
				, plugins: ["babel-plugin-add-module-exports"]
			}
		}
	});
};
<|endoftext|>


<commit_before>import './styles/main.scss'
import * as api from './rest.js';
import * as auth from './authorisation.js';
import * as sectionInfo from './sections/info.js';
import * as sectionManual from './sections/manual.js';
import * as sectionMetrics from './sections/metrics.js';
import * as sectionSettings from './sections/settings.js';
import * as sectionSchedule from './sections/schedule.js';
import * as sectionStart from './sections/start.js';
import ReconnectingWebSocket from 'reconnecting-websocket';

// store for local state.
global.liam = {
  config: {},
  data: {
    status: {},
    system: {},
  },
  sections: {
    start: sectionStart,
    manual: sectionManual,
    metrics: sectionMetrics,
    settings: sectionSettings,
    schedule: sectionSchedule,
    info: sectionInfo,
  }
};

let currentActiveSection,
    isSmallDisplay = $(window).width() < 480,
    socket,
    socketDisconnectedTimeout;

function addClickEffect() {
  // Add click effect on widgets that are clickable
  $(document).on('click', '.clickable', function(e) {
    let target = $(this);

    target.addClass('clickable-active');

    setTimeout(() => {
      target.removeClass('clickable-active');
    }, 20);
  });
}

function setTheme(name) {
  $('html').addClass(name ? 'theme-' + name : liam.config.theme ? 'theme-' + liam.config.theme : 'theme-default');
}

function showSection(section) {
  let sections = $('.js-section'),
      navItems = $('.js-main-nav-item'),
      sectionEl = $('.js-section-' + section),
      navSectionEl = $('.js-nav-section-' + section);

  navItems.removeClass('active');
  navSectionEl.addClass('active');
  sections.hide();
  sectionEl.show();

  if (currentActiveSection) {
    currentActiveSection.unselected();
  }

  currentActiveSection = liam.sections[section];
  currentActiveSection.selected();
}

function showLostConnectionModal() {
  document.querySelector('.js-no-connection-modal').style.display = 'block';
  document.querySelector('.js-loginbox').style.display = 'none';
  document.getElementById('modal').style.display = 'block';
}

function hideLostConnectionModal() {
  document.getElementById('modal').style.display = 'none';
  document.querySelector('.js-loginbox').style.display = 'none';
}

function startSubscribingOnStatus() {
  socket = new ReconnectingWebSocket('ws://' + location.host + '/ws');

  socket.addEventListener('open', () => {
    console.info('Got WS connection.');
    if (socketDisconnectedTimeout) {
      clearTimeout(socketDisconnectedTimeout);
      socketDisconnectedTimeout = undefined;
    }
    if (!auth.isLoginDialogVisible()) {
      hideLostConnectionModal();
    }
  });

  socket.addEventListener('close', () => {
    console.info('Lost WS connection.');
    // show lost connection modal if we have not been able to reconnect within 2 seconds.
    socketDisconnectedTimeout = setTimeout(() => {
      // if we are not currently logging in, show lost connection warning.
      if (!auth.isLoginDialogVisible()) {
        showLostConnectionModal();
      }
    }, 2000);
  });

  socket.addEventListener('error', (error) => {
    console.warn(`Got WS error: ${error.message}`);
  });

  // Listen for messages
  socket.addEventListener('message', function (event) {
    let message = JSON.parse(event.data);

    if (message.type === 'status') {
      let status = message.payload;
      if (JSON.stringify(status) !== JSON.stringify(liam.data.status)) {
        liam.data.status = status;
        window.dispatchEvent(new Event('statusUpdated'));
      }
    }
  });
}

function initialSetup() {
  // get initial settings and system information.
  $.when(api.getSystem(), api.getStatus())
  .done((system, status) => {
    liam.data.system = system[0];
    liam.data.status = status[0];
    showLostConnectionModal();

    for (let section in global.liam.sections) {
      global.liam.sections[section].init();
    }

    window.dispatchEvent(new Event('statusUpdated'));
    showSection('start');
    startSubscribingOnStatus();
  }).catch(error => {
    if (error.status === 401) {
      auth.showLogin().then(() => {
        initialSetup();
      });
    } else {
      setTimeout(initialSetup, 500); // retry if failed.
    }
  });
}

function init() {
  // Hide all sections first, showSection() will show the appropriate one.
  $('.section').hide();
  $('.js-main-nav').on('click', '.js-main-nav-item', function() {
    showSection($(this).data('section'));
  });

  setTheme();
  addClickEffect();
  initialSetup();
}

// Start application.
init();<commit_msg>Handle websocket connection when running behind SSL terminating loadbalancer.<commit_after>import './styles/main.scss'
import * as api from './rest.js';
import * as auth from './authorisation.js';
import * as sectionInfo from './sections/info.js';
import * as sectionManual from './sections/manual.js';
import * as sectionMetrics from './sections/metrics.js';
import * as sectionSettings from './sections/settings.js';
import * as sectionSchedule from './sections/schedule.js';
import * as sectionStart from './sections/start.js';
import ReconnectingWebSocket from 'reconnecting-websocket';

// store for local state.
global.liam = {
  config: {},
  data: {
    status: {},
    system: {},
  },
  sections: {
    start: sectionStart,
    manual: sectionManual,
    metrics: sectionMetrics,
    settings: sectionSettings,
    schedule: sectionSchedule,
    info: sectionInfo,
  }
};

let currentActiveSection,
    isSmallDisplay = $(window).width() < 480,
    socket,
    socketDisconnectedTimeout;

function addClickEffect() {
  // Add click effect on widgets that are clickable
  $(document).on('click', '.clickable', function(e) {
    let target = $(this);

    target.addClass('clickable-active');

    setTimeout(() => {
      target.removeClass('clickable-active');
    }, 20);
  });
}

function setTheme(name) {
  $('html').addClass(name ? 'theme-' + name : liam.config.theme ? 'theme-' + liam.config.theme : 'theme-default');
}

function showSection(section) {
  let sections = $('.js-section'),
      navItems = $('.js-main-nav-item'),
      sectionEl = $('.js-section-' + section),
      navSectionEl = $('.js-nav-section-' + section);

  navItems.removeClass('active');
  navSectionEl.addClass('active');
  sections.hide();
  sectionEl.show();

  if (currentActiveSection) {
    currentActiveSection.unselected();
  }

  currentActiveSection = liam.sections[section];
  currentActiveSection.selected();
}

function showLostConnectionModal() {
  document.querySelector('.js-no-connection-modal').style.display = 'block';
  document.querySelector('.js-loginbox').style.display = 'none';
  document.getElementById('modal').style.display = 'block';
}

function hideLostConnectionModal() {
  document.getElementById('modal').style.display = 'none';
  document.querySelector('.js-loginbox').style.display = 'none';
}

function startSubscribingOnStatus() {
  let protocol = location.protocol.indexOf('https') === 0 ? 'wss' : 'ws';
  socket = new ReconnectingWebSocket(`${protocol}://${location.host}/ws`);

  socket.addEventListener('open', () => {
    console.info('Got WS connection.');
    if (socketDisconnectedTimeout) {
      clearTimeout(socketDisconnectedTimeout);
      socketDisconnectedTimeout = undefined;
    }
    if (!auth.isLoginDialogVisible()) {
      hideLostConnectionModal();
    }
  });

  socket.addEventListener('close', () => {
    console.info('Lost WS connection.');
    // show lost connection modal if we have not been able to reconnect within 2 seconds.
    socketDisconnectedTimeout = setTimeout(() => {
      // if we are not currently logging in, show lost connection warning.
      if (!auth.isLoginDialogVisible()) {
        showLostConnectionModal();
      }
    }, 2000);
  });

  socket.addEventListener('error', (error) => {
    console.warn(`Got WS error: ${error.message}`);
  });

  // Listen for messages
  socket.addEventListener('message', function (event) {
    let message = JSON.parse(event.data);

    if (message.type === 'status') {
      let status = message.payload;
      if (JSON.stringify(status) !== JSON.stringify(liam.data.status)) {
        liam.data.status = status;
        window.dispatchEvent(new Event('statusUpdated'));
      }
    }
  });
}

function initialSetup() {
  // get initial settings and system information.
  $.when(api.getSystem(), api.getStatus())
  .done((system, status) => {
    liam.data.system = system[0];
    liam.data.status = status[0];
    showLostConnectionModal();

    for (let section in global.liam.sections) {
      global.liam.sections[section].init();
    }

    window.dispatchEvent(new Event('statusUpdated'));
    showSection('start');
    startSubscribingOnStatus();
  }).catch(error => {
    if (error.status === 401) {
      auth.showLogin().then(() => {
        initialSetup();
      });
    } else {
      setTimeout(initialSetup, 500); // retry if failed.
    }
  });
}

function init() {
  // Hide all sections first, showSection() will show the appropriate one.
  $('.section').hide();
  $('.js-main-nav').on('click', '.js-main-nav-item', function() {
    showSection($(this).data('section'));
  });

  setTheme();
  addClickEffect();
  initialSetup();
}

// Start application.
init();<|endoftext|>


<commit_before>define(["Test", "Tone/signal/TickSignal", "helper/Offline"],
	function (Test, TickSignal, Offline) {

	describe("TickSignal", function(){

		it("can be created and disposed", function(){
			var tickSignal = new TickSignal();
			tickSignal.dispose();
			Test.wasDisposed(tickSignal);
		});

		it("can schedule a change in the future", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(2, 0.2);
			tickSignal.dispose();
		});

		it("can schedule a ramp in the future", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(2, 0);
			tickSignal.linearRampToValueAtTime(0.1, 0.2);
			tickSignal.exponentialRampToValueAtTime(1, 0.4);
			tickSignal.dispose();
		});

		it("calculates the ticks when no changes are scheduled", function(){
			var tickSignal0 = new TickSignal(2);
			expect(tickSignal0.getTickAtTime(1)).to.be.closeTo(2, 0.01);
			expect(tickSignal0.getTickAtTime(2)).to.be.closeTo(4, 0.01);
			tickSignal0.dispose();

			var tickSignal1 = new TickSignal(1);
			expect(tickSignal1.getTickAtTime(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal1.getTickAtTime(2)).to.be.closeTo(2, 0.01);
			tickSignal1.dispose();
		});

		it("calculates the ticks in the future when a setValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(2, 0.5);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.5, 0.01);
			// expect(tickSignal.getTickAtTime(0.75)).to.be.closeTo(1, 0.01);
			// expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.01);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when multiple setValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(2, 1);
			tickSignal.setValueAtTime(4, 2);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.5, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal.getTickAtTime(1.5)).to.be.closeTo(2, 0.01);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(3, 0.01);
			expect(tickSignal.getTickAtTime(2.5)).to.be.closeTo(5, 0.01);
			expect(tickSignal.getTickAtTime(3)).to.be.closeTo(7, 0.01);
			tickSignal.dispose();
		});

		it("if ticks are 0, getTickAtTime will return 0", function(){
			var tickSignal = new TickSignal(0);
			tickSignal.setValueAtTime(0, 1);
			tickSignal.linearRampToValueAtTime(0, 2);
			expect(tickSignal.getTickAtTime(0)).to.equal(0);
			expect(tickSignal.getTickAtTime(1)).to.equal(0);
			expect(tickSignal.getTickAtTime(2)).to.equal(0);
			expect(tickSignal.getTickAtTime(3)).to.equal(0);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when a linearRampToValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.linearRampToValueAtTime(2, 1);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.62, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.01);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(3.5, 0.01);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when multiple linearRampToValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.linearRampToValueAtTime(2, 1);
			tickSignal.linearRampToValueAtTime(0, 2);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.62, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.01);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(2.5, 0.01);
			expect(tickSignal.getTickAtTime(3)).to.be.closeTo(2.5, 0.01);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when a exponentialRampToValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.exponentialRampToValueAtTime(2, 1);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.6, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.1);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(3.5, 0.1);
			expect(tickSignal.getTickAtTime(3)).to.be.closeTo(5.5, 0.1);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when multiple exponentialRampToValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.exponentialRampToValueAtTime(2, 1);
			tickSignal.exponentialRampToValueAtTime(0, 2);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.6, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.1);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(1.66, 0.1);
			expect(tickSignal.getTickAtTime(3)).to.be.closeTo(1.66, 0.1);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when setTargetAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setTargetAtTime(0.5, 0, 0.1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(1.88, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(3.86, 0.01);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when multiple setTargetAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setTargetAtTime(0.5, 0, 0.1);
			tickSignal.setTargetAtTime(2, 1, 1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(1.45, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(2.28, 0.01);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when nothing is scheduled", function(){
			var tickSignal0 = new TickSignal(1);
			expect(tickSignal0.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal0.getTimeOfTick(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal0.getTimeOfTick(2)).to.be.closeTo(2, 0.01);
			expect(tickSignal0.getTimeOfTick(3)).to.be.closeTo(3, 0.01);
			tickSignal0.dispose();

			var tickSigna1 = new TickSignal(2);
			expect(tickSigna1.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSigna1.getTimeOfTick(1)).to.be.closeTo(0.5, 0.01);
			expect(tickSigna1.getTimeOfTick(2)).to.be.closeTo(1, 0.01);
			expect(tickSigna1.getTimeOfTick(3)).to.be.closeTo(1.5, 0.01);
			tickSigna1.dispose();
		});

		it("computes the time of a given tick when setValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(0.5, 1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(3, 0.01);
			expect(tickSignal.getTimeOfTick(3)).to.be.closeTo(5, 0.01);
			tickSignal.dispose();
		});

		it("returns Infinity if the tick interval is 0", function(){
			var tickSignal = new TickSignal(0);
			expect(tickSignal.getTimeOfTick(1)).to.equal(Infinity);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when multiple setValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(0.5, 1);
			tickSignal.setValueAtTime(0, 2);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal.getTimeOfTick(1.499)).to.be.closeTo(2, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.equal(Infinity);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when a linearRampToValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.linearRampToValueAtTime(2, 1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(0.66, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(1.25, 0.01);
			expect(tickSignal.getTimeOfTick(3)).to.be.closeTo(1.75, 0.01);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when multiple linearRampToValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.linearRampToValueAtTime(2, 1);
			tickSignal.linearRampToValueAtTime(0, 2);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(0.66, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(1.5, 0.01);
			expect(tickSignal.getTimeOfTick(3)).to.equal(Infinity);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when a exponentialRampToValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.exponentialRampToValueAtTime(2, 1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(1.25, 0.1);
			expect(tickSignal.getTimeOfTick(3)).to.be.closeTo(1.75, 0.1);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when multiple exponentialRampToValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.exponentialRampToValueAtTime(2, 1);
			tickSignal.exponentialRampToValueAtTime(0, 2);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(0.5)).to.be.closeTo(0.5, 0.1);
			expect(tickSignal.getTimeOfTick(1.5)).to.be.closeTo(1, 0.1);
			expect(tickSignal.getTimeOfTick(3)).to.equal(Infinity);
			tickSignal.dispose();
		});

		it("can schedule multiple types of curves", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.exponentialRampToValueAtTime(0.5, 1);
			tickSignal.linearRampToValueAtTime(3, 2);
			tickSignal.setValueAtTime(2, 3);
			tickSignal.linearRampToValueAtTime(2, 4);
			tickSignal.setTargetAtTime(8, 5, 0.2);

			for (var time = 0; time < 6; time+=0.5){
				var tick = tickSignal.getTickAtTime(time);
				expect(tickSignal.getTimeOfTick(tick)).to.be.closeTo(time, 0.25);
			}

			tickSignal.dispose();
		});
	});
});<commit_msg>updating with more accurate values<commit_after>define(["Test", "Tone/signal/TickSignal", "helper/Offline"],
	function (Test, TickSignal, Offline) {

	describe("TickSignal", function(){

		it("can be created and disposed", function(){
			var tickSignal = new TickSignal();
			tickSignal.dispose();
			Test.wasDisposed(tickSignal);
		});

		it("can schedule a change in the future", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(2, 0.2);
			tickSignal.dispose();
		});

		it("can schedule a ramp in the future", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(2, 0);
			tickSignal.linearRampToValueAtTime(0.1, 0.2);
			tickSignal.exponentialRampToValueAtTime(1, 0.4);
			tickSignal.dispose();
		});

		it("calculates the ticks when no changes are scheduled", function(){
			var tickSignal0 = new TickSignal(2);
			expect(tickSignal0.getTickAtTime(1)).to.be.closeTo(2, 0.01);
			expect(tickSignal0.getTickAtTime(2)).to.be.closeTo(4, 0.01);
			tickSignal0.dispose();

			var tickSignal1 = new TickSignal(1);
			expect(tickSignal1.getTickAtTime(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal1.getTickAtTime(2)).to.be.closeTo(2, 0.01);
			tickSignal1.dispose();
		});

		it("calculates the ticks in the future when a setValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(2, 0.5);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.5, 0.01);
			expect(tickSignal.getTickAtTime(0.75)).to.be.closeTo(1, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.01);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when multiple setValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(2, 1);
			tickSignal.setValueAtTime(4, 2);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.5, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal.getTickAtTime(1.5)).to.be.closeTo(2, 0.01);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(3, 0.01);
			expect(tickSignal.getTickAtTime(2.5)).to.be.closeTo(5, 0.01);
			expect(tickSignal.getTickAtTime(3)).to.be.closeTo(7, 0.01);
			tickSignal.dispose();
		});

		it("if ticks are 0, getTickAtTime will return 0", function(){
			var tickSignal = new TickSignal(0);
			tickSignal.setValueAtTime(0, 1);
			tickSignal.linearRampToValueAtTime(0, 2);
			expect(tickSignal.getTickAtTime(0)).to.equal(0);
			expect(tickSignal.getTickAtTime(1)).to.equal(0);
			expect(tickSignal.getTickAtTime(2)).to.equal(0);
			expect(tickSignal.getTickAtTime(3)).to.equal(0);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when a linearRampToValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.linearRampToValueAtTime(2, 1);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.62, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.01);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(3.5, 0.01);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when multiple linearRampToValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.linearRampToValueAtTime(2, 1);
			tickSignal.linearRampToValueAtTime(0, 2);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.62, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.01);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(2.5, 0.01);
			expect(tickSignal.getTickAtTime(3)).to.be.closeTo(2.5, 0.01);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when a exponentialRampToValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.exponentialRampToValueAtTime(2, 1);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.6, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.1);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(3.5, 0.1);
			expect(tickSignal.getTickAtTime(3)).to.be.closeTo(5.5, 0.1);
			tickSignal.dispose();
		});

		it("calculates the ticks in the future when multiple exponentialRampToValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.exponentialRampToValueAtTime(2, 1);
			tickSignal.exponentialRampToValueAtTime(0, 2);
			expect(tickSignal.getTickAtTime(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTickAtTime(0.5)).to.be.closeTo(0.6, 0.01);
			expect(tickSignal.getTickAtTime(1)).to.be.closeTo(1.5, 0.1);
			expect(tickSignal.getTickAtTime(2)).to.be.closeTo(1.66, 0.1);
			expect(tickSignal.getTickAtTime(3)).to.be.closeTo(1.66, 0.1);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when setTargetAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setTargetAtTime(0.5, 0, 0.1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(1.88, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(3.86, 0.01);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when multiple setTargetAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setTargetAtTime(0.5, 0, 0.1);
			tickSignal.setTargetAtTime(2, 1, 1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(1.5, 0.1);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(2.28, 0.1);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when nothing is scheduled", function(){
			var tickSignal0 = new TickSignal(1);
			expect(tickSignal0.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal0.getTimeOfTick(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal0.getTimeOfTick(2)).to.be.closeTo(2, 0.01);
			expect(tickSignal0.getTimeOfTick(3)).to.be.closeTo(3, 0.01);
			tickSignal0.dispose();

			var tickSigna1 = new TickSignal(2);
			expect(tickSigna1.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSigna1.getTimeOfTick(1)).to.be.closeTo(0.5, 0.01);
			expect(tickSigna1.getTimeOfTick(2)).to.be.closeTo(1, 0.01);
			expect(tickSigna1.getTimeOfTick(3)).to.be.closeTo(1.5, 0.01);
			tickSigna1.dispose();
		});

		it("computes the time of a given tick when setValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(0.5, 1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(3, 0.01);
			expect(tickSignal.getTimeOfTick(3)).to.be.closeTo(5, 0.01);
			tickSignal.dispose();
		});

		it("returns Infinity if the tick interval is 0", function(){
			var tickSignal = new TickSignal(0);
			expect(tickSignal.getTimeOfTick(1)).to.equal(Infinity);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when multiple setValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(0.5, 1);
			tickSignal.setValueAtTime(0, 2);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(1, 0.01);
			expect(tickSignal.getTimeOfTick(1.499)).to.be.closeTo(2, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.equal(Infinity);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when a linearRampToValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.linearRampToValueAtTime(2, 1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(0.75, 0.1);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(1.25, 0.1);
			expect(tickSignal.getTimeOfTick(3)).to.be.closeTo(1.75, 0.1);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when multiple linearRampToValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.linearRampToValueAtTime(2, 1);
			tickSignal.linearRampToValueAtTime(0, 2);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.1);
			expect(tickSignal.getTimeOfTick(1)).to.be.closeTo(0.75, 0.1);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(1.25, 0.1);
			expect(tickSignal.getTimeOfTick(3)).to.equal(Infinity);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when a exponentialRampToValueAtTime is scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.exponentialRampToValueAtTime(2, 1);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(2)).to.be.closeTo(1.25, 0.1);
			expect(tickSignal.getTimeOfTick(3)).to.be.closeTo(1.75, 0.1);
			tickSignal.dispose();
		});

		it("computes the time of a given tick when multiple exponentialRampToValueAtTime are scheduled", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.exponentialRampToValueAtTime(2, 1);
			tickSignal.exponentialRampToValueAtTime(0, 2);
			expect(tickSignal.getTimeOfTick(0)).to.be.closeTo(0, 0.01);
			expect(tickSignal.getTimeOfTick(0.5)).to.be.closeTo(0.5, 0.1);
			expect(tickSignal.getTimeOfTick(1.5)).to.be.closeTo(1, 0.1);
			expect(tickSignal.getTimeOfTick(3)).to.equal(Infinity);
			tickSignal.dispose();
		});

		it("can schedule multiple types of curves", function(){
			var tickSignal = new TickSignal(1);
			tickSignal.setValueAtTime(1, 0);
			tickSignal.exponentialRampToValueAtTime(4, 1);
			tickSignal.linearRampToValueAtTime(0.2, 2);
			tickSignal.setValueAtTime(2, 3);
			tickSignal.linearRampToValueAtTime(2, 4);
			tickSignal.setTargetAtTime(8, 5, 0.2);

			for (var time = 0; time < 5; time+=0.2){
				var tick = tickSignal.getTickAtTime(time);
				expect(tickSignal.getTimeOfTick(tick)).to.be.closeTo(time, 0.1);
			}

			tickSignal.dispose();
		});
	});
});<|endoftext|>


<commit_before><commit_msg>unit tests<commit_after>/**
 * @file
 */
'use strict';

// Require Node modules and perform setup.
const chai           = require('chai');
const chaiAsPromised = require('chai-as-promised');
const path           = require('path');
const proxyquire     = require('proxyquire')
const sinon          = require('sinon');
const sinonChai      = require('sinon-chai');
const stream         = require('stream');
chai.should();
chai.use(chaiAsPromised);
chai.use(sinonChai);

const Readable = stream.Readable;

let fsStub   = {},
    pathStub = {};

// Swap Bluebird for the native Promise object.
const Promise = require('bluebird');

// Define local constants.
const TEMPLATE_CONTENTS  = 'Hello, {{name}}';
const TEMPLATE_DIRECTORY = 'test/views';
const TEMPLATE_EXTENSION = 'hbs';
const TEMPLATE_NAME      = 'testing';
const TEMPLATE_TYPE      = 'view';

// Require module to test.
const Renderer = proxyquire('../../index.js', {
  'fs':   fsStub,
  'path': pathStub
});

// Describe tests.
describe('Renderer', function() {
  let renderer;

  beforeEach(function() {
    renderer = new Renderer;

    fsStub.createReadStream = sinon.stub().callsFake(function(file, options) {
      let stream = new Readable;

      stream._read = function() {
        if (file !== path.join(TEMPLATE_DIRECTORY, TEMPLATE_NAME + '.' + TEMPLATE_EXTENSION)) {
          this.emit('error', new Error('Testing error'));
        } else {
          this.push(TEMPLATE_CONTENTS);
          this.push(null);
        }
      };

      return stream;
    });
    fsStub.readdir = sinon.stub().callsFake(function(directory, callback) {
      if (directory !== TEMPLATE_DIRECTORY) {
        return callback(directory);
      }

      return callback(null, [
        TEMPLATE_NAME + '.' + TEMPLATE_EXTENSION,
        'another.nope'
      ]);
    });

    pathStub.join = sinon.stub().callsFake(function() {
      return path.join.apply(path, arguments);
    });
    pathStub.normalize = sinon.stub().callsFake(function() {
      return path.normalize.apply(path, arguments);
    });
  });

  describe('constructor', function() {
    it('should create an empty template object cache', function() {
      renderer._cache.should.be.an('object');
      renderer._cache.should.have.all.keys('layout', 'partial', 'view');
    });

    it('should create a new Handlebars environment', function() {
      renderer.hbs.constructor.name.should.equal('HandlebarsEnvironment');
    });
  });

  describe('#_compileTemplate', function() {
    it('should compile the template via this.hbs.compile', function() {
      sinon.spy(renderer.hbs, 'compile');

      renderer._compileTemplate(TEMPLATE_TYPE, TEMPLATE_NAME, TEMPLATE_CONTENTS);
      renderer.hbs.compile.should.have.been.calledOnce;
      renderer.hbs.compile.should.have.been.calledWith(TEMPLATE_CONTENTS);
    });

    it('should cache the compiled template', function() {
      renderer._compileTemplate(TEMPLATE_TYPE, TEMPLATE_NAME, TEMPLATE_CONTENTS);
      renderer._cache[TEMPLATE_TYPE][TEMPLATE_NAME].should.exist;
      renderer._cache[TEMPLATE_TYPE][TEMPLATE_NAME].should.be.a('function');
    });

    it('should set the _name of the compiled template', function() {
      renderer._compileTemplate(TEMPLATE_TYPE, TEMPLATE_NAME, TEMPLATE_CONTENTS);
      renderer._cache[TEMPLATE_TYPE][TEMPLATE_NAME]._name.should.exist;
      renderer._cache[TEMPLATE_TYPE][TEMPLATE_NAME]._name.should.equal(TEMPLATE_NAME);
    });

    it('should rely on Date.now() to obtain the current time', function() {
      sinon.spy(Date, 'now');

      renderer._compileTemplate(TEMPLATE_TYPE, TEMPLATE_NAME, TEMPLATE_CONTENTS);
      Date.now.should.have.been.calledOnce;

      Date.now.restore();
    });

    it('should rely on Math.floor() to round the current time to the nearest second', function() {
      sinon.spy(Math, 'floor');

      renderer._compileTemplate(TEMPLATE_TYPE, TEMPLATE_NAME, TEMPLATE_CONTENTS);
      Math.floor.should.have.been.calledOnce;

      Math.floor.restore();
    });

    it('should set the _cached timestamp of the compiled template', function() {
      renderer._compileTemplate(TEMPLATE_TYPE, TEMPLATE_NAME, TEMPLATE_CONTENTS);
      renderer._cache[TEMPLATE_TYPE][TEMPLATE_NAME]._cached.should.exist;
      renderer._cache[TEMPLATE_TYPE][TEMPLATE_NAME]._cached.should.be.a('number');
    });

    it('should return the compiled template', function() {
      let template = renderer._compileTemplate(TEMPLATE_TYPE, TEMPLATE_NAME, TEMPLATE_CONTENTS);
      template.should.deep.equal(renderer._cache[TEMPLATE_TYPE][TEMPLATE_NAME]);
    });
  });

  describe('#_loadFile', function() {
    it('should normalize the target path via path.normalize', function() {
      let p = renderer._loadFile(TEMPLATE_DIRECTORY, TEMPLATE_NAME, TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60);
      pathStub.normalize.should.have.been.calledOnce;
    });

    it('should join the specified directory, filename, and extension via path.join', function() {
      let p = renderer._loadFile(TEMPLATE_DIRECTORY, TEMPLATE_NAME, TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60);
      pathStub.join.should.have.been.calledOnce;
      pathStub.join.should.have.been.calledWith(TEMPLATE_DIRECTORY, TEMPLATE_NAME + '.' + TEMPLATE_EXTENSION);
    });

    it('should return a Promise', function() {
      let p = renderer._loadFile(TEMPLATE_DIRECTORY, TEMPLATE_NAME, TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60);
      p.should.be.an('object');
      p.constructor.name.should.equal('Promise');
    });

    it('should resolve to cached template if one exists and has not expired', function(done) {
      renderer._compileTemplate(TEMPLATE_TYPE, TEMPLATE_NAME, TEMPLATE_CONTENTS);

      let p = renderer._loadFile(TEMPLATE_DIRECTORY, TEMPLATE_NAME, TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60);
      p.then((cached) => {
        cached.should.deep.equal(renderer._cache[TEMPLATE_TYPE][TEMPLATE_NAME]);
      });
      p.should.be.fulfilled.notify(done);
    });

    it('should create a Readable stream via fs.createReadStream', function() {
      renderer._loadFile(TEMPLATE_DIRECTORY, TEMPLATE_NAME, TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60);
      fsStub.createReadStream.should.have.been.calledOnce;
    });

    it('should reject on error', function(done) {
      renderer._loadFile(TEMPLATE_DIRECTORY, 'bad', TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60).should.be.rejected.notify(done);
    });

    it('should compile loaded template via this._compileTemplate', function(done) {
      sinon.spy(renderer, '_compileTemplate');
      renderer._loadFile(TEMPLATE_DIRECTORY, TEMPLATE_NAME, TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60).then(function() {
        renderer._compileTemplate.should.have.been.calledOnce;
        renderer._compileTemplate.should.have.been.calledWith(TEMPLATE_TYPE, TEMPLATE_NAME, TEMPLATE_CONTENTS);
        renderer._compileTemplate.restore();
      }).should.be.fulfilled.notify(done);
    });
  });

  describe('#_loadFiles', function() {
    it('should return a promise', function() {
      let p = renderer._loadFiles(TEMPLATE_DIRECTORY, TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60);
      p.should.be.an('object');
      p.constructor.name.should.equal('Promise');
    });

    it('should reject on error', function(done) {
      renderer._loadFiles('bad', TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60).should.be.rejected.notify(done);
    });

    it('should call this._loadFile for each matching file in the directory', function(done) {
      sinon.spy(renderer, '_loadFile');
      renderer._loadFiles(TEMPLATE_DIRECTORY, TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60).then(function() {
        renderer._loadFile.should.have.been.calledOnce;
        renderer._loadFile.restore();
      }).should.be.fulfilled.notify(done);
    });

    it('should resolve to a map of compiled templates from the cache', function(done) {
      renderer._loadFiles(TEMPLATE_DIRECTORY, TEMPLATE_EXTENSION, TEMPLATE_TYPE, 60).then(function(result) {
        result.should.be.an('object');
        renderer._cache['view'][TEMPLATE_NAME].should.deep.equal(result[TEMPLATE_NAME]);
      }).should.be.fulfilled.notify(done);
    });
  });

  describe('#_render', function() {
    let context = { value: 'context' },
        options = { value: 'options' };

    let view, layout;

    beforeEach(function() {
      view   = sinon.spy();
      layout = sinon.spy();
    });

    it('should execute a specified view template function', function() {
      renderer._render(view, layout, context, options);
      view.should.have.been.calledOnce;
      view.should.have.been.calledWith(context, options);
    });

    it('should execute a specified layout template function', function() {
      renderer._render(view, layout, context, options);
      layout.should.have.been.calledOnce;
      layout.should.have.been.calledWith(Object.assign({}, context, {
        body: view(context, options)
      }), options);
    });
  });

  describe('#middleware', function() {
    it('should return an asynchronous function', function() {
      renderer.middleware({
        paths: { views: TEMPLATE_DIRECTORY }
      }).should.be.an('AsyncFunction');
    });

    it('should throw ReferenceError if option.paths is undefined', function() {
      (function() {
        renderer.middleware();
      }).should.throw(ReferenceError);
    });

    it('should throw ReferenceError if option.paths.views is undefined', function() {
      (function() {
        renderer.middleware({
          paths: {}
        });
      }).should.throw(ReferenceError);
    });

    describe('middleware async function', function() {
      let fn, next;

      beforeEach(function() {
        fn = renderer.middleware({
          paths: { views: TEMPLATE_DIRECTORY }
        });
        next = sinon.spy();
      });

      it('should attach a render method to specified context', function() {
        let ctx = {};
        fn(ctx, next);
        ctx.render.should.exist;
        ctx.render.should.be.an('AsyncFunction');
      });

      it('should await next', function() {
        fn({}, next);
        next.should.have.been.calledOnce;
      });
    });

    describe('ctx.render', function() {
      let ctx;

      beforeEach(function() {
        ctx = {};
      });

      it('should call this._loadFile to load the specified view', function(done) {
        sinon.spy(renderer, '_loadFile');
        renderer.middleware({
          paths: { views: TEMPLATE_DIRECTORY }
        })(ctx, function() {
          Promise.resolve(ctx.render(TEMPLATE_NAME)).then(() => {
            renderer._loadFile.should.have.been.calledOnce;
            renderer._loadFile.restore();
          }).should.be.fulfilled.notify(done);
        });
      });

      it('should call this._loadFile to load the specified layout if options.paths.layouts is specified', function(done) {
        sinon.spy(renderer, '_loadFile');
        renderer.middleware({
          paths: {
            views: TEMPLATE_DIRECTORY,
            layouts: TEMPLATE_DIRECTORY
          },
          defaultLayout: 'testing'
        })(ctx, function() {
          Promise.resolve(ctx.render(TEMPLATE_NAME)).then(() => {
            renderer._loadFile.should.have.been.calledTwice;
            renderer._loadFile.restore();
          }).should.be.fulfilled.notify(done);
        });
      });

      it('should override options.defaultLayout if context.layout is specified', function(done) {
        sinon.spy(renderer, '_loadFile');
        renderer.middleware({
          paths: {
            views: TEMPLATE_DIRECTORY,
            layouts: TEMPLATE_DIRECTORY
          },
          defaultLayout: 'bad'
        })(ctx, function() {
          Promise.resolve(ctx.render(TEMPLATE_NAME, {
            layout: TEMPLATE_NAME
          })).then(() => {
            renderer._loadFile.should.have.been.calledTwice;
            renderer._loadFile.restore();
          }).should.be.fulfilled.notify(done);
        });
      });

      it('should call this._loadFiles to load the specified partials if options.paths.partials is specified', function(done) {
        sinon.spy(renderer, '_loadFiles');
        renderer.middleware({
          paths: {
            views: TEMPLATE_DIRECTORY,
            partials: TEMPLATE_DIRECTORY
          }
        })(ctx, function() {
          Promise.resolve(ctx.render(TEMPLATE_NAME)).then(() => {
            renderer._loadFiles.should.have.been.calledOnce;
            renderer._loadFiles.restore();
          }).should.be.fulfilled.notify(done);
        });
      });

      it('should set ctx.type to text/html; charset=utf-8', function(done) {
        renderer.middleware({
          paths: { views: TEMPLATE_DIRECTORY }
        })(ctx, function() {
          Promise.resolve(ctx.render(TEMPLATE_NAME)).then(() => {
            ctx.type.should.equal('text/html; charset=utf-8');
          }).should.be.fulfilled.notify(done);
        });
      });

      it('should set ctx.body to the rendered template', function(done) {
        renderer.middleware({
          paths: { views: TEMPLATE_DIRECTORY }
        })(ctx, function() {
          Promise.resolve(ctx.render(TEMPLATE_NAME, {
            name: 'test'
          })).then(() => {
            ctx.body.should.be.a('string');
            ctx.body.should.equal('Hello, test');
          }).should.be.fulfilled.notify(done);
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>var assert = require('chai').assert;
var index = require('../../index');

describe('Entry Point', function () {
  it('Should properly export', function () {
    assert.isObject(index);
  });
});
<commit_msg>Implement LocationService<commit_after>var assert = require('chai').assert;
var LocationService = require('../../');

describe('LocationService', function () {
  it('Should properly export', function () {
    assert.isObject(LocationService);
    assert.isFunction(LocationService.create);
  });

  it('Should properly create location instances', function () {
  });

  it('Should properly throw error on unrecognized type', function () {
    assert.throws(function () {
      LocationService.create('NOT_EXISTS');
    }, Error);
  });
});
<|endoftext|>


<commit_before>// Copyright 2016 Keith DeLong (n8xd)
// Apache 2.0 license - http://www.apache.org/licenses/LICENSE-2.0
'use strict';
exports.handler = function( event, context ) {
   var https = require( 'https' );
   var STappID = 'x';
   var STtoken = 'x';

   if (event.request.intent.name == "DeviceOperation") {
        var Operator = event.request.intent.slots.Operator.value;
        var Device = event.request.intent.slots.Device.value;
        var Num = event.request.intent.slots.Num.value;
        var url = 'https://graph.api.smartthings.com/api/smartapps/installations/' + STappID + '/' + Device + '/' + Operator + '/' + Num + '?access_token=' + STtoken;
        https.get( url, function( response ) {
            response.on( 'data', function( data ) {
                var resJSON = JSON.parse(data);
                var speechText = "I don't understand";
                if (resJSON.talk2me) { speechText = resJSON.talk2me; }
                console.log(speechText);
                output(speechText, context);
                console.log("after the fact");
            } );
        } );
    }
   if (event.request.intent.name == "ReportOperation") {
       output("Another intent goes here.", context)
    }
};

function output( text, context ) {
   var response = {
      outputSpeech: {
         type: "PlainText",
         text: text
      },
      card: {
         type: "Simple",
         title: "System Data",
         content: text
      },
   shouldEndSession: true
   };
   context.succeed( { response: response } );
}
<commit_msg>Update AskAlexaNode.js<commit_after>// Copyright 2016 Michael Struck & Keith DeLong (n8xd)
// Apache 2.0 license - http://www.apache.org/licenses/LICENSE-2.0
'use strict';
exports.handler = function( event, context ) {
   var https = require( 'https' );
   var STappID = 'x';
   var STtoken = 'x';
   var url = 'https://graph.api.smartthings.com/api/smartapps/installations/' + STappID + '/' ;

    if (event.request.intent.name == "DeviceOperation") {
        var Operator = event.request.intent.slots.Operator.value;
        var Device = event.request.intent.slots.Device.value;
        var Num = event.request.intent.slots.Num.value;
        url += Device + '/' + Operator + '/' + Num + '?access_token=' + STtoken;

    }
   if (event.request.intent.name == "ReportOperation") {
       output("Another intent goes here.", context);
    }
    https.get( url, function( response ) {
            response.on( 'data', function( data ) {
                var resJSON = JSON.parse(data);
                var speechText = "I don't understand";
                if (resJSON.talk2me) { speechText = resJSON.talk2me; }
                console.log(speechText);
                output(speechText, context);
            } );
    } );
};

function output( text, context ) {
   var response = {
      outputSpeech: {
         type: "PlainText",
         text: text
      },
      card: {
         type: "Simple",
         title: "System Data",
         content: text
      },
   shouldEndSession: true
   };
   context.succeed( { response: response } );
}
<|endoftext|>