<commit_before>/* Core (Flow Package) v0.X, Bemi Faison, MIT */
!function(a,b,c,d,e,f){function k(a){return a!=null&&/\w/.test(a)}function l(a){var c=typeof a;return c==="object"&&~(new b).toString.call(a).indexOf("y")?"array":c}var g=e.pkg("core"),h=new genData(function(a,b,d,e,g,h){var i=this,j=1,l={name:i.name,value:i.value,use:1};g.omit=1,i.O=typeof b=="object",i.A=b instanceof c,d?d.A?i.O&&(j=0):g.scan=0:(h.keys||(h.keys={}),i.O&&(j=0));if(j){if(!d||d.A)l.name=b,l.value=f,l.use=0;k(l.name)&&(l.name+="",h.keys.hasOwnProperty(l.name)&&e.splice(h.keys[l.name],1),h.keys[l.name]=e.push(l)-1)}}),i=new genData(function(a,b,c,d,e){var f=this,g="/";f.set=0,f.parent=c,f.done=0,typeof b=="string"&&(~b.indexOf(g)?f.value=b.split(g):b.charAt(0)==="["&&(f.value=b.slice(1,-1).split("|"),f.set=1)),typeof f.value=="string"?(c&&c.set&&(f.set=1,c.last=f),f.first=!d.length):e.omit=1}),j=[];j.every||(c.prototype.every=function(a){"use strict";if(this===void 0||this===null)throw new TypeError;var c=b(this),d=c.length>>>0;if(typeof a!="function")throw new TypeError;var e=arguments[1];for(var f=0;f<d;f++)if(!a.call(e,c[f],f,c))return!1;return!0}),g.events=["on","in","out","over","bover"],g.dataKey=/^_/,g.invalidKey=/^\W+$|^toString$|^[@\[]|[\/\|]/,g.init=function(){var a=this;a.args=[],a.calls=[],a.route=[],a.vars={},a.delay={},a.cache={indexOf:{}},a.trust=0,a.inFnc=0,a.locked=0,a.stateIds={},a.pending=0,a.parentFlows=[],a.targets=[],a.phase=0,a.states.forEach(function(b,c){var d=c&&a.states[b.parentIndex];a.stateIds[b.location]=c,b.pkg=a,b.pendable=d&&!d.pendable?0:b.data.hasOwnProperty("_pendable")?!!b.data._pendable:1,b.isRoot=c<2?1:!!b.data._root,b.rootIndex=b.isRoot?b.index:d.rootIndex,b.restrict=!!(b.data._restrict||d&&d.restrict),b.map=function(){var b=[].slice.call(arguments),d=a.proxy.pkgs.core;return b.unshift(c),d.target.apply(d,b)},b.vars=h(b.data._vars),b.index&&(d.map[b.name]=b.map),b.map.toString=function(){return b.location},b.fncs=g.events.map(function(a){return a="_"+a,typeof b.data[a]=="function"?b.data[a]:0}),!b.fncs[0]&&typeof b.value=="function"&&(b.fncs[0]=b.value)})},g.prototype={indexOf:function(a,b){var c=this,d=c.states,e=c.stateIds,f,g,h,j,k,l=-1;b=b||c.states[c.tank.currentIndex];switch(typeof a){case"object":a!==null&&(a=a.index);case"number":d[a]&&(l=a);break;case"function":a+="";case"string":if(a=="")break;if(a==="..//"||a==="//")l=a==="//"?1:0;else{j=a.match(/^(?:(?:\.{1,2}|[@\[][^\/]+)\/?)+/);if(j){if(!c.cache.indexOf.hasOwnProperty(a+b.index)&&!c.cache.indexOf.hasOwnProperty(a)){f=a.substr(j[0].length),h=0,j=i(j[0]),l=b.index;while((g=d[l])&&j.length){k=j.shift();if(!k.set||!k.parent.done){switch(k.value){case"@child":l=g.firstChildIndex;break;case"@next":l=g.nextIndex;break;case"@parent":case"..":l=g.parentIndex;break;case"@previous":l=g.previousIndex;break;case"@root":l=g.rootIndex;break;case"@program":case"@flow":k.first&&(h=1),l=~k.value.indexOf("f")?0:1;break;case"@oldest":case"@youngest":l=d[g.parentIndex]?d[g.parentIndex][~k.value.indexOf("y")?"firstChildIndex":"lastChildIndex"]:-1;break;case"@self":case".":l=g.index;break;default:k.value&&(l=-1)}k.set&&(l>-1?k.parent.done=1:k.parent.last!==k&&(l=g.index))}}l=g&&(!f||(g=d[e[g.location+f.replace(/([^\/])$/,"$1/")]]))?g.index:-1,c.cache.indexOf[a+(h?"":b.index)]=l}l=c.cache.indexOf.hasOwnProperty(a+b.index)?c.cache.indexOf[a+b.index]:c.cache.indexOf[a]}else a.charAt(0)!=="/"?a=b.location+a:a.charAt(1)!=="/"&&(a=d[b.rootIndex].location+a.substr(1)),a.slice(-1)!=="/"&&(a+="/"),l=e.hasOwnProperty(a)?e[a]:-1}}return l},vetIndexOf:function(a,b){var c=this,d=c.indexOf(a,b);return b=b||c.states[c.tank.currentIndex],~d&&(c.trust||b.canTgt(c.states[d]))?d:-1},getVar:function(a,b){var c=this;return k(a)&&(c.vars.hasOwnProperty(a)?c.vars[a]:c.vars[a]={name:a,values:arguments.length>1?[b]:[]})},go:function(a){var b=this;return a>-1&&(b.targets=[a]),b.pause=0,b.pending||b.locked&&!b.trust?0:b.tank.go(b.targets[0])}},g.onBegin=function(b){var c=this,d=c.delay.callback,e=j[0];e&&e.states[e.tank.currentIndex].pendable&&(e.pending++,~c.parentFlows.indexOf(e)||c.parentFlows.unshift(e)),j.unshift(c),a.clearTimeout(c.delay.timer),c.delay.callback=0,d&&(c.trust=1,d.call(c.proxy),c.trust=0)},g.onTraverse=function(a,b){var c=this,d=c.states[c.tank.currentIndex];c.trust=1,c.outState&&(c.outState.scopeVars(1),c.outState=0);switch(b){case 1:d.scopeVars();break;case 2:c.outState=d}c.phase=b,d.index!==c.route.slice(-1)[0]&&c.route.push(d.index),d.fncs[b]&&(c.calls.push(d.index+"."+b),c.inFnc=1,c.result=d.fncs[b].apply(c.proxy,b||c.targets.length-1?[]:c.args),c.inFnc=0),c.pending&&c.tank.stop(),c.trust=0},g.onEnd=function(a){var b=this,c=b.pause||b.pending;b.phase?j.shift():(~b.tank.targetIndex||b.targets.shift(),!c&&b.targets.length?b.tank.go(b.targets[0]):(j.shift(),c||(b.args=[],b.calls=[],b.route=[],b.parentFlows.length&&(b.parentFlows.forEach(function(a){b.parentFlows.pending--}),b.tank.post(function(){var a=[].concat(b.parentFlows);b.parentFlows=[],a.forEach(function(a){--a.pending||(a.phase?a.go():a.tank.go())})})))))},g.state.canTgt=function(a){var b=this;return!b.restrict||b!==a&&!a.location.indexOf(b.location)},g.state.scopeVars=function(a){var b=this,c=b.pkg;b.vars.forEach(function(b){var d=c.getVar(b.name);a?(d.values.shift(),d.values.length||delete c.vars[b.name]):d.values.unshift(b.use?b.value:d.values[0])})},g.proxy.map=function(){return g(this).states[1].map},g.proxy.query=function(a){var b=g(this),c=[];return a&&[].slice.call(arguments).every(function(a){var d=b.vetIndexOf(a),e=0;return~d&&(c.push(b.states[d].location),e=1),e})?c.length>0?c:c[0]:!1},g.proxy.lock=function(a){var b=g(this),c=!1;return arguments.length?b.trust&&(b.locked=!!a,c=!0):c=!!b.locked,c},g.proxy.vars=function(a,b){var c=g(this),d=arguments.length,e,f=!1;if(d)typeof a=="string"&&/\w/.test(a)&&(e=c.getVar(a),d>1?(e.values[0]=b,f=!0):f=e.values[0]);else{f=[];for(e in c.vars)c.vars.hasOwnProperty(e)&&f.push(e);f.sort()}return f},g.proxy.args=function(a,b){var c=g(this),d=c.args,e=d.length,h=arguments.length,i=l(a),j=!0;return h&&!c.locked?i==="array"?c.args=[].concat(a):i==="number"?h>1?b===f&&a===e-1?d.pop():d[a]=b:a>-1&&a<e?j=d[a]:j=!1:j=!1:h||(j=d.concat()),j},g.proxy.target=function(a){var b=g(this),c=b.vetIndexOf(a);if(~c)b.args=[].slice.call(arguments).slice(1),b.go(c);else return!1;return b.inFnc||b.pending||b.phase||b.pause?!1:b.result===f?!0:b.result},g.proxy.go=function(){var a=g(this),b=a.targets,c=a.pause,d=[],e,f=0;if([].slice.call(arguments).every(function(b){var c=a.vetIndexOf(b);return d.push(c),~c})){if(e=d.length)b.length?(d[e-1]===b[a.phase?0:1]&&d.pop(),a.phase?b=d.concat(b):b.splice.apply(b,[0,1].concat(d))):b=d,a.targets=b;f=a.go()||c}return!!f},g.proxy.wait=function(){var b=g(this),c=arguments,d=c.length,e=d<2,f=e?0:c[0],h=typeof f=="function",i=b.indexOf(f),j=~~c[d-1],k=0;return b.trust&&(!d||j>-1&&(e||~i||h))&&(b.pause=1,b.tank.stop(),a.clearTimeout(b.delay.timer),b.delay.timer=d?a.setTimeout(function(){!e&&~i?b.go(i):(h&&(b.delay.callback=f),b.go())},j):1,k=1),!!k},g.proxy.status=function(){var a=this,b={};return e.pkg().forEach(function(c){var d=e.pkg(c),f,g;if(typeof d.addStatus=="function"){f=d.addStatus.call(d(a),b);for(g in f)f.hasOwnProperty(g)&&(b[g]=f[g])}}),b},g.addStatus=function(a){var b=this,c=b.states[b.tank.currentIndex],e=b.targets.length,f=b.pause||e||b.pending,h=function(a){return b.states[a].location};return{trust:!!b.trust,loops:d.max((b.calls.join().match(new RegExp("\\b"+c.index+"."+b.phase,"g"))||[]).length-1,0),depth:c.depth,paused:!!b.pause,pending:!!b.pending,pendable:!!c.pendable,targets:b.targets.map(h),route:f?b.route.map(h):[],location:c.location,index:c.index,phase:f?g.events[b.phase]:"",state:c.name}}}(this,Object,Array,Math,Flow);<commit_msg>Flow package: Core - minified for testing (7.7K/3.1K)<commit_after>/* Core (Flow Package) v0.X, Bemi Faison, MIT */
!function(a,b,c,d,e,f,g){function l(a){return a!=null&&/\w/.test(a)}function m(a){var c=typeof a;return c==="object"&&~(new b).toString.call(a).indexOf("y")?"array":c}var h=e.pkg("core"),i=new genData(function(a,b,d,e,f,h){var i=this,j=1,k={name:i.name,value:i.value,use:1};f.omit=1,i.O=typeof b=="object",i.A=b instanceof c,d?d.A?i.O&&(j=0):f.scan=0:(h.keys||(h.keys={}),i.O&&(j=0));if(j){if(!d||d.A)k.name=b,k.value=g,k.use=0;l(k.name)&&(k.name+="",h.keys.hasOwnProperty(k.name)&&e.splice(h.keys[k.name],1),h.keys[k.name]=e.push(k)-1)}}),j=new genData(function(a,b,c,d,e){var f=this,g="/";f.set=0,f.parent=c,f.done=0,typeof b=="string"&&(~b.indexOf(g)?f.value=b.split(g):b.charAt(0)==="["&&(f.value=b.slice(1,-1).split("|"),f.set=1)),typeof f.value=="string"?(c&&c.set&&(f.set=1,c.last=f),f.first=!d.length):e.omit=1}),k=[];k.every||(c.prototype.every=function(a){"use strict";if(this===void 0||this===null)throw new TypeError;var c=b(this),d=c.length>>>0;if(typeof a!="function")throw new TypeError;var e=arguments[1];for(var f=0;f<d;f++)if(!a.call(e,c[f],f,c))return!1;return!0}),h.events=["on","in","out","over","bover"],h.dataKey=/^_/,h.invalidKey=/^\W+$|^toString$|^[@\[]|[\/\|]/,h.init=function(){var a=this;a.args=[],a.calls=[],a.route=[],a.vars={},a.delay={},a.cache={indexOf:{}},a.trust=0,a.locked=0,a.stateIds={},a.pending=0,a.parents=[],a.targets=[],a.phase=0,a.states.forEach(function(b,c){var d=c&&a.states[b.parentIndex];a.stateIds[b.location]=c,b.pkg=a,b.pendable=d&&!d.pendable?0:b.data.hasOwnProperty("_pendable")?!!b.data._pendable:1,b.isRoot=c<2?1:!!b.data._root,b.rootIndex=b.isRoot?b.index:d.rootIndex,b.restrict=!!(b.data._restrict||d&&d.restrict),b.map=function(){var b=[].slice.call(arguments),d=a.proxy.pkgs.core;return b.unshift(c),d.target.apply(d,b)},b.vars=i(b.data._vars),b.index&&(d.map[b.name]=b.map),b.map.toString=function(){return b.location},b.fncs=h.events.map(function(a){return a="_"+a,typeof b.data[a]=="function"?b.data[a]:0}),!b.fncs[0]&&typeof b.value=="function"&&(b.fncs[0]=b.value)})},h.prototype={indexOf:function(a,b){var c=this,d=c.states,e=c.stateIds,f,g,h,i,k,l=-1;b=b||c.states[c.tank.currentIndex];switch(typeof a){case"object":a!==null&&(a=a.index);case"number":d[a]&&(l=a);break;case"function":a+="";case"string":if(a=="")break;if(a==="..//"||a==="//")l=a==="//"?1:0;else{i=a.match(/^(?:(?:\.{1,2}|[@\[][^\/]+)\/?)+/);if(i){if(!c.cache.indexOf.hasOwnProperty(a+b.index)&&!c.cache.indexOf.hasOwnProperty(a)){f=a.substr(i[0].length),h=0,i=j(i[0]),l=b.index;while((g=d[l])&&i.length){k=i.shift();if(!k.set||!k.parent.done){switch(k.value){case"@child":l=g.firstChildIndex;break;case"@next":l=g.nextIndex;break;case"@parent":case"..":l=g.parentIndex;break;case"@previous":l=g.previousIndex;break;case"@root":l=g.rootIndex;break;case"@program":case"@flow":k.first&&(h=1),l=~k.value.indexOf("f")?0:1;break;case"@oldest":case"@youngest":l=d[g.parentIndex]?d[g.parentIndex][~k.value.indexOf("y")?"firstChildIndex":"lastChildIndex"]:-1;break;case"@self":case".":l=g.index;break;default:k.value&&(l=-1)}k.set&&(l>-1?k.parent.done=1:k.parent.last!==k&&(l=g.index))}}l=g&&(!f||(g=d[e[g.location+f.replace(/([^\/])$/,"$1/")]]))?g.index:-1,c.cache.indexOf[a+(h?"":b.index)]=l}l=c.cache.indexOf.hasOwnProperty(a+b.index)?c.cache.indexOf[a+b.index]:c.cache.indexOf[a]}else a.charAt(0)!=="/"?a=b.location+a:a.charAt(1)!=="/"&&(a=d[b.rootIndex].location+a.substr(1)),a.slice(-1)!=="/"&&(a+="/"),l=e.hasOwnProperty(a)?e[a]:-1}}return l},vetIndexOf:function(a,b){var c=this,d=c.indexOf(a,b);return b=b||c.states[c.tank.currentIndex],~d&&(c.trust||b.canTgt(c.states[d]))?d:-1},getVar:function(a,b){var c=this;return l(a)&&(c.vars.hasOwnProperty(a)?c.vars[a]:c.vars[a]={name:a,values:arguments.length>1?[b]:[]})},go:function(a){var b=this,c=b.pause;return a>-1&&(b.targets=[a]),b.pause=0,b.pending||b.locked&&!b.trust?0:b.tank.go(!b.targets.length&&c?b.tank.currentIndex:b.targets[0])}},h.onBegin=function(b){var c=this,d=c.delay.callback,e=k[0];e&&e.states[e.tank.currentIndex].pendable&&(e.pending++,~c.parents.indexOf(e)||c.parents.unshift(e)),k.unshift(c),a.clearTimeout(c.delay.timer),c.delay.callback=0,d&&(c.trust=1,d.call(c.proxy),c.trust=0)},h.onTraverse=function(a,b){var c=this,d=c.states[c.tank.currentIndex];if(c.targets.length){c.trust=1,c.outState&&(c.outState.scopeVars(1),c.outState=0);switch(b){case 1:d.scopeVars();break;case 2:c.outState=d}c.phase=b,d.index!==c.route.slice(-1)[0]&&c.route.push(d.index),d.fncs[b]&&(c.calls.push(d.index+"."+b),c.result=d.fncs[b].apply(c.proxy,b||c.targets.length-1?[]:c.args)),c.pending&&c.tank.stop(),c.trust=0}},h.onEnd=function(a){var b=this,c=b.pause||b.pending;b.phase?k.shift():(~b.tank.targetIndex||b.targets.shift(),!c&&b.targets.length?b.tank.go(b.targets[0]):(k.shift(),c||(b.args=[],b.calls=[],b.route=[],b.parents.length&&(b.parents.forEach(function(a){a.pending--}),b.tank.post(function(){var a=[].concat(b.parents);b.parents=[],a.forEach(function(a){a.pending||a.go()})})))))},h.state.canTgt=function(a){var b=this;return!b.restrict||b!==a&&!a.location.indexOf(b.location)},h.state.scopeVars=function(a){var b=this,c=b.pkg;b.vars.forEach(function(b){var d=c.getVar(b.name);a?(d.values.shift(),d.values.length||delete c.vars[b.name]):d.values.unshift(b.use?b.value:d.values[0])})},h.proxy.map=function(){return h(this).states[1].map},h.proxy.query=function(a){var b=h(this),c=[];return a&&[].slice.call(arguments).every(function(a){var d=b.vetIndexOf(a),e=0;return~d&&(c.push(b.states[d].location),e=1),e})?c.length>0?c:c[0]:!1},h.proxy.lock=function(a){var b=h(this),c=!1;return arguments.length?b.trust&&(b.locked=!!a,c=!0):c=!!b.locked,c},h.proxy.vars=function(a,b){var c=h(this),d=arguments.length,e,f=!1;if(d)typeof a=="string"&&/\w/.test(a)&&(e=c.getVar(a),d>1?(e.values[0]=b,f=!0):f=e.values[0]);else{f=[];for(e in c.vars)c.vars.hasOwnProperty(e)&&f.push(e);f.sort()}return f},h.proxy.args=function(a,b){var c=h(this),d=c.args,e=arguments.length,i=m(a),j=!0;return e&&!c.locked?i==="array"?c.args=[].concat(a):i==="number"&&!f(a)&&(a=~~a)>-1?e>1?b===g&&a===d.length-1?d.pop():d[a]=b:j=d[a]:j=!1:e||(j=[].concat(d)),j},h.proxy.target=function(a){var b=h(this),c=b.vetIndexOf(a);if(~c)b.args=[].slice.call(arguments).slice(1),b.go(c);else return!1;return b.trust||b.pending||b.phase||b.pause?!1:b.result===g?!0:b.result},h.proxy.go=function(){var a=h(this),b=a.targets,c=a.pause,d=[],e,f=0;if([].slice.call(arguments).every(function(b){var c=a.vetIndexOf(b);return d.push(c),~c})){if(e=d.length)b.length?(d[e-1]===b[a.phase?0:1]&&d.pop(),a.phase?b=d.concat(b):b.splice.apply(b,[0,1].concat(d))):b=d,a.targets=b;f=a.go()||c}return!!f},h.proxy.wait=function(){var b=h(this),c=arguments,d=c.length,e=d<2,f=e?0:c[0],g=typeof f=="function",i=b.indexOf(f),j=~~c[d-1],k=0;return b.trust&&(!d||j>-1&&(e||~i||g))&&(b.pause=1,b.tank.stop(),a.clearTimeout(b.delay.timer),b.delay.timer=d?a.setTimeout(function(){!e&&~i?b.go(i):(g&&(b.delay.callback=f),b.go())},j):1,k=1),!!k},h.proxy.status=function(){var a=this,b={};return e.pkg().forEach(function(c){var d=e.pkg(c),f,g;if(typeof d.addStatus=="function"){f=d.addStatus.call(d(a),b);for(g in f)f.hasOwnProperty(g)&&(b[g]=f[g])}}),b},h.addStatus=function(a){var b=this,c=b.states[b.tank.currentIndex],e=b.targets.length,f=b.pause||e||b.pending,g=function(a){return b.states[a].location};return{trust:!!b.trust,loops:d.max((b.calls.join().match(new RegExp("\\b"+c.index+"."+b.phase,"g"))||[]).length-1,0),depth:c.depth,paused:!!b.pause,pending:!!b.pending,pendable:!!c.pendable,targets:b.targets.map(g),route:f?b.route.map(g):[],location:c.location,index:c.index,phase:f?h.events[b.phase]:"",state:c.name}}}(this,Object,Array,Math,Flow,isNaN);<|endoftext|>


<commit_before>/* Tests for service.js
 *
 * Copyright 2017 Raising the Floor - International
 *
 * Licensed under the New BSD license. You may not use this file except in
 * compliance with this License.
 *
 * The R&D leading to these results received funding from the
 * Department of Education - Grant H421A150005 (GPII-APCP). However,
 * these results do not necessarily represent the policy of the
 * Department of Education, and you should not assume endorsement by the
 * Federal Government.
 *
 * You may obtain a copy of the License at
 * https://github.com/GPII/universal/blob/master/LICENSE.txt
 */

"use strict";

var jqUnit = require("node-jqunit"),
    os = require("os"),
    path = require("path"),
    fs = require("fs");

var teardowns = [];

jqUnit.module("GPII service tests", {
    teardown: function () {
        while (teardowns.length) {
            teardowns.pop()();
        }
    }
});

jqUnit.test("Test config loader", function () {
    var service = require("../src/service.js");
    // service.js should already have called service.config.
    jqUnit.assertNotNull("service.config is called on startup", service.config);

    // Create a temporary config file.
    var testDir = path.join(os.tmpdir(), "gpii-service-test" + Math.random());
    var testFile = path.join(testDir, "service.json5");
    teardowns.push(function () {
        try {
            fs.unlinkSync(testFile);
            fs.rmdirSync(testDir);
        } catch (e) {
            // ignore
        }
    });

    fs.mkdirSync(testDir);
    fs.writeFileSync(testFile, "{testLoaded: true}");

    // Check a config file will be loaded if the process is running as a service
    try {
        service.config = null;
        service.isService = true;
        service.loadConfig(testDir);
        jqUnit.assertTrue("config should be loaded when running as a service",
            service.config && service.config.testLoaded);
    } finally {
        // Ensure the next user of service.js gets a clean one
        delete require.cache[require.resolve("../src/service.js")];
    }
});

jqUnit.test("Test secret loading", function () {
    try {
        var service = require("../src/service.js");
        var secret = service.getSecrets();
        jqUnit.assertTrue("Secret should have been loaded", !!secret);

        // Try a secret file that does not exist
        service.config.secretFile = "does/not/exist";
        var secret2 = service.getSecrets();
        jqUnit.assertNull("No secret should have been loaded", secret2);
    } finally {
        // Ensure the next user of service.js gets a clean one
        delete require.cache[require.resolve("../src/service.js")];
    }
});
<commit_msg>GPII-4244: Made test pass<commit_after>/* Tests for service.js
 *
 * Copyright 2017 Raising the Floor - International
 *
 * Licensed under the New BSD license. You may not use this file except in
 * compliance with this License.
 *
 * The R&D leading to these results received funding from the
 * Department of Education - Grant H421A150005 (GPII-APCP). However,
 * these results do not necessarily represent the policy of the
 * Department of Education, and you should not assume endorsement by the
 * Federal Government.
 *
 * You may obtain a copy of the License at
 * https://github.com/GPII/universal/blob/master/LICENSE.txt
 */

"use strict";

var jqUnit = require("node-jqunit"),
    os = require("os"),
    path = require("path"),
    fs = require("fs");

var teardowns = [];

jqUnit.module("GPII service tests", {
    teardown: function () {
        while (teardowns.length) {
            teardowns.pop()();
        }
    }
});

jqUnit.test("Test config loader", function () {
    var service = require("../src/service.js");
    // service.js should already have called service.config.
    jqUnit.assertNotNull("service.config is called on startup", service.config);

    // Create a temporary config file.
    var testDir = path.join(os.tmpdir(), "gpii-service-test" + Math.random());
    var testFile = path.join(testDir, "service.json5");
    teardowns.push(function () {
        try {
            fs.unlinkSync(testFile);
            fs.rmdirSync(testDir);
        } catch (e) {
            // ignore
        }
    });

    fs.mkdirSync(testDir);
    fs.writeFileSync(testFile, "{testLoaded: true}");

    // Check a config file will be loaded if the process is running as a service
    try {
        service.isService = true;
        var config = service.loadConfig(testDir);
        jqUnit.assertTrue("config should be loaded when running as a service",
            config && config.testLoaded);
    } finally {
        // Ensure the next user of service.js gets a clean one
        delete require.cache[require.resolve("../src/service.js")];
    }
});

jqUnit.test("Test secret loading", function () {
    try {
        var service = require("../src/service.js");
        var secret = service.getSecrets();
        jqUnit.assertTrue("Secret should have been loaded", !!secret);

        // Try a secret file that does not exist
        service.config.secretFile = "does/not/exist";
        var secret2 = service.getSecrets();
        jqUnit.assertNull("No secret should have been loaded", secret2);
    } finally {
        // Ensure the next user of service.js gets a clean one
        delete require.cache[require.resolve("../src/service.js")];
    }
});
<|endoftext|>


<commit_before>
var kFontStep = 8;
var kMinFontSize = 24;
var kDefaultFontSize = 64;
var gTones = {
  '0': null, '1': null, '2': null, '3': null, '4': null,
  '5': null, '6': null, '7': null, '8': null, '9': null,
  '*': null, '#': null
};

// Bug 690056 implement a visibility API, and it's likely that
// we want this event to be fire when an app come back to life
// or is minimized (it does not now).
window.addEventListener('visibilitychange', function visibleApp(evt) {
  if (!evt.detail.hidden)
    visibilityChanged(evt.detail.url);
});

function visibilityChanged(url) {
  // TODO do something better here
  var contacts = document.getElementById('contacts');
  if (url.indexOf('?choice=contact') != -1 ||
      contacts.hasAttribute('data-active')) {
    choiceChanged(contacts);
  } else if (url.indexOf('?choice=incoming')) {
    var call = window.navigator.mozTelephony.liveCalls[0];
    CallHandler.incoming(call);
  }
}

function choiceChanged(target) {
  if (!target.classList.contains('choice'))
    return;

  var view = document.getElementById(target.id + '-view');
  if (!view)
    return;

  // XXX this should not live here
  Contacts.hideSearch();

  var choices = document.getElementById('choices');
  var choicesCount = choices.childElementCount;
  for (var i = 0; i < choicesCount; i++) {
    var choice = choices.children[i];
    choice.removeAttribute('data-active');

    var choiceView = document.getElementById(choice.id + '-view');
    choiceView.setAttribute('hidden', 'true');
  }

  target.setAttribute('data-active', 'true');
  view.removeAttribute('hidden');
}

var KeyHandler = {
  get phoneNumber() {
    delete this.phoneNumber;
    return this.phoneNumber = document.getElementById('phoneNumber');
  },

  get fakePhoneNumberView() {
    delete this.fakePhoneNumberView;
    return this.fakePhoneNumberView =
      document.getElementById('fakePhoneNumber-view');
  },

  get phoneNumberView() {
    delete this.phoneNumberView;
    return this.phoneNumberView = document.getElementById('phoneNumber-view');
  },

  init: function kh_init() {
    this.phoneNumber.value = '';
    for (var tone in gTones)
        gTones[tone] = document.getElementById('tone' + tone);

    var mainKeys = [
      { title: '1', details: '' },
      { title: '2', details: 'abc' },
      { title: '3', details: 'def' },
      { title: '4', details: 'ghi' },
      { title: '5', details: 'jkl' },
      { title: '6', details: 'mno' },
      { title: '7', details: 'pqrs' },
      { title: '8', details: 'tuv' },
      { title: '9', details: 'wxyz' },
      { title: '\u2217', value: '*', details: '' },
      { title: '0', details: '+' },
      { title: '#', details: '' }
    ];

    var mainKey = document.getElementById('mainKeyset');
    var row = null;
    mainKeys.forEach(function(key, index) {
      if (index % 3 == 0) {
        row = document.createElement('div');
        row.className = 'keyboard-row';
        mainKey.appendChild(row);
      }

      var container = document.createElement('div');
      container.className = 'keyboard-key';
      var value = 'value' in key ? key.value : key.title;
      container.setAttribute('data-value', value);

      var title = document.createElement('span');
      title.appendChild(document.createTextNode(key.title));
      container.appendChild(title);

      var details = document.createElement('span');
      details.appendChild(document.createTextNode(key.details));
      container.appendChild(details);
      row.appendChild(container);
    });
  },

  isContactShortcut: function kh_isContactShortcut(key) {
    // TODO implement key shortcuts
    return false;
  },

  formatPhoneNumber: function kh_formatPhoneNumber(phoneNumber) {
    // TODO implement formatting depending on locale
    return phoneNumber;
  },

  updateFontSize: function kh_updateFontSize() {
    var self = this;
    function getNextFontSize(fontSize, text) {
      var div = self.fakePhoneNumberView;
      div.style.fontSize = fontSize + 'px';
      div.innerHTML = text;

      var windowWidth = document.body.clientWidth;
      var rect = div.getBoundingClientRect();
      if (rect.width > windowWidth) {
        fontSize = Math.max(fontSize - kFontStep, kMinFontSize);
      } else if (fontSize < kDefaultFontSize) {
        div.style.fontSize = (fontSize + kFontStep) + 'px';
        rect = div.getBoundingClientRect();
        if (rect.width <= windowWidth)
          fontSize += kFontStep;
      }

      return fontSize;
    }

    var view = this.phoneNumberView;
    var computedStyle = window.getComputedStyle(view, null);
    var fontSize = computedStyle.getPropertyValue('font-size');

    var text = this.formatPhoneNumber(this.phoneNumber.value);
    view.innerHTML = text;

    var newFontSize =
      text ? getNextFontSize(parseInt(fontSize), text) : kDefaultFontSize;
    if (newFontSize != fontSize)
    view.style.fontSize = newFontSize + 'px';
  },

  keyDown: function kh_keyDown(event) {
    var key = event.target.getAttribute('data-value');
    if (!key)
      return;

    var callback = function(self) {
      switch (key) {
        case '0':
          self.phoneNumber.value = self.phoneNumber.value.slice(0, -1) + '+';
          break;
        case 'del':
          self.phoneNumber.value = '';
          break;
        default:
          if (self.isContactShortcut(key))
            return;
          break;
      }
      self.updateFontSize();
    };

    if (key == 'del') {
      this.phoneNumber.value = KeyHandler.phoneNumber.value.slice(0, -1);
      this.updateFontSize();
    } else if (key == 'call') {
      // TODO: update the call button style to show his availability
      if (this.phoneNumber.value != '') {
        CallHandler.call(this.phoneNumber.value);
      }
    } else {
      this.phoneNumber.value += key;
      this.updateFontSize();
      gTones[key].play();
    }

    this._timeout = window.setTimeout(callback, 400, this);
  },

  keyUp: function kh_keyUp(event) {
    clearTimeout(this._timeout);
  }
};

var CallHandler = {
  // callbacks
  call: function ch_call(number) {
    this.numberView.innerHTML = number;
    this.statusView.innerHTML = 'Calling...';
    this.actionsView.classList.remove('displayed');
    this.callButton.dataset.action = 'end';
    this.toggleCallScreen();

    var call = window.navigator.mozTelephony.call(number);
    call.addEventListener('readystatechange', this);
    this.currentCall = call;
  },
  incoming: function ch_incoming(call) {
    this.currentCall = call;

    this.numberView.innerHTML = call.number;
    this.statusView.innerHTML = 'Incoming call...';
    this.actionsView.classList.remove('displayed');
    this.callButton.dataset.action = 'answer';
    this.toggleCallScreen();
  },
  connected: function ch_connected() {
    // hardening against rapid ending
    if (!document.getElementById('call-screen').classList.contains('oncall'))
      return;

    this.statusView.innerHTML = '00:00';
    this.actionsView.classList.add('displayed');
    this.callButton.dataset.action = 'end';

    this._ticker = setInterval(function ch_updateTimer(self, startTime) {
      var elapsed = new Date(Date.now() - startTime);
      self.statusView.innerHTML = elapsed.toLocaleFormat('%M:%S');
    }, 1000, this, Date.now());
  },
  answer: function ch_answer() {
    this.currentCall.answer();
    this.connected();
  },
  end: function ch_end() {
    this.toggleCallScreen();
    this.currentCall.disconnect();
    this.currentCall.removeEventListener('readystatechange', this);

    this.actionsView.classList.remove('displayed');
    if (this.muteButton.classList.contains('mute'))
      this.toggleMute();

    this.closeModal();
    clearInterval(this._ticker);
  },

  handleEvent: function fm_handleEvent(evt) {
    this.connected();
  },

  // properties / methods
  get numberView() {
    delete this.numberView;
    return this.numberView = document.getElementById('callNumber-view');
  },
  get statusView() {
    delete this.statusView;
    return this.statusView = document.getElementById('callStatus-view');
  },
  get actionsView() {
    delete this.actionsView;
    return this.actionsView = document.getElementById('callActions-container');
  },
  get muteButton() {
    delete this.muteButton;
    return this.muteButton = document.getElementById('mute-button');
  },
  get callButton() {
    delete this.callButton;
    return this.callButton = document.getElementById('call-button');
  },

  execute: function ch_execute(action) {
    if (!this[action]) {
      this.end();
      return;
    }

    this[action]();
  },

  toggleCallScreen: function ch_toggleScreen() {
    document.getElementById('choices').classList.toggle('oncall');
    document.getElementById('views').classList.toggle('oncall');
    document.getElementById('call-screen').classList.toggle('oncall');
  },
  toggleMute: function ch_toggleMute() {
    this.muteButton.classList.toggle('mute');
    // TODO: make the actual mute call on the telephony API
  },
  keypad: function ch_keypad() {
    choiceChanged(document.getElementById('keyboard'));
    document.getElementById('views').classList.add('modal');
  },
  contacts: function ch_contacts() {
    choiceChanged(document.getElementById('contacts'));
    document.getElementById('views').classList.add('modal');
  },
  closeModal: function ch_closeModal() {
    // 2 steps closing to avoid showing the view in its non-modal state
    // during the transition
    var views = document.getElementById('views');
    views.classList.add('hidden');
    views.addEventListener('transitionend', function ch_closeModalFinish() {
      views.removeEventListener('transitionend', ch_closeModalFinish);
      views.classList.remove('modal');
      views.classList.remove('hidden');
    });
  }
};

window.addEventListener('load', function keyboardInit(evt) {
  window.removeEventListener('load', keyboardInit);
  KeyHandler.init();
});

<commit_msg>Fix a typo<commit_after>
var kFontStep = 8;
var kMinFontSize = 24;
var kDefaultFontSize = 64;
var gTones = {
  '0': null, '1': null, '2': null, '3': null, '4': null,
  '5': null, '6': null, '7': null, '8': null, '9': null,
  '*': null, '#': null
};

// Bug 690056 implement a visibility API, and it's likely that
// we want this event to be fire when an app come back to life
// or is minimized (it does not now).
window.addEventListener('visibilitychange', function visibleApp(evt) {
  if (!evt.detail.hidden)
    visibilityChanged(evt.detail.url);
});

function visibilityChanged(url) {
  // TODO do something better here
  var contacts = document.getElementById('contacts');
  if (url.indexOf('?choice=contact') != -1 ||
      contacts.hasAttribute('data-active')) {
    choiceChanged(contacts);
  } else if (url.indexOf('?choice=incoming') != -1) {
    var call = window.navigator.mozTelephony.liveCalls[0];
    CallHandler.incoming(call);
  }
}

function choiceChanged(target) {
  if (!target.classList.contains('choice'))
    return;

  var view = document.getElementById(target.id + '-view');
  if (!view)
    return;

  // XXX this should not live here
  Contacts.hideSearch();

  var choices = document.getElementById('choices');
  var choicesCount = choices.childElementCount;
  for (var i = 0; i < choicesCount; i++) {
    var choice = choices.children[i];
    choice.removeAttribute('data-active');

    var choiceView = document.getElementById(choice.id + '-view');
    choiceView.setAttribute('hidden', 'true');
  }

  target.setAttribute('data-active', 'true');
  view.removeAttribute('hidden');
}

var KeyHandler = {
  get phoneNumber() {
    delete this.phoneNumber;
    return this.phoneNumber = document.getElementById('phoneNumber');
  },

  get fakePhoneNumberView() {
    delete this.fakePhoneNumberView;
    return this.fakePhoneNumberView =
      document.getElementById('fakePhoneNumber-view');
  },

  get phoneNumberView() {
    delete this.phoneNumberView;
    return this.phoneNumberView = document.getElementById('phoneNumber-view');
  },

  init: function kh_init() {
    this.phoneNumber.value = '';
    for (var tone in gTones)
        gTones[tone] = document.getElementById('tone' + tone);

    var mainKeys = [
      { title: '1', details: '' },
      { title: '2', details: 'abc' },
      { title: '3', details: 'def' },
      { title: '4', details: 'ghi' },
      { title: '5', details: 'jkl' },
      { title: '6', details: 'mno' },
      { title: '7', details: 'pqrs' },
      { title: '8', details: 'tuv' },
      { title: '9', details: 'wxyz' },
      { title: '\u2217', value: '*', details: '' },
      { title: '0', details: '+' },
      { title: '#', details: '' }
    ];

    var mainKey = document.getElementById('mainKeyset');
    var row = null;
    mainKeys.forEach(function(key, index) {
      if (index % 3 == 0) {
        row = document.createElement('div');
        row.className = 'keyboard-row';
        mainKey.appendChild(row);
      }

      var container = document.createElement('div');
      container.className = 'keyboard-key';
      var value = 'value' in key ? key.value : key.title;
      container.setAttribute('data-value', value);

      var title = document.createElement('span');
      title.appendChild(document.createTextNode(key.title));
      container.appendChild(title);

      var details = document.createElement('span');
      details.appendChild(document.createTextNode(key.details));
      container.appendChild(details);
      row.appendChild(container);
    });
  },

  isContactShortcut: function kh_isContactShortcut(key) {
    // TODO implement key shortcuts
    return false;
  },

  formatPhoneNumber: function kh_formatPhoneNumber(phoneNumber) {
    // TODO implement formatting depending on locale
    return phoneNumber;
  },

  updateFontSize: function kh_updateFontSize() {
    var self = this;
    function getNextFontSize(fontSize, text) {
      var div = self.fakePhoneNumberView;
      div.style.fontSize = fontSize + 'px';
      div.innerHTML = text;

      var windowWidth = document.body.clientWidth;
      var rect = div.getBoundingClientRect();
      if (rect.width > windowWidth) {
        fontSize = Math.max(fontSize - kFontStep, kMinFontSize);
      } else if (fontSize < kDefaultFontSize) {
        div.style.fontSize = (fontSize + kFontStep) + 'px';
        rect = div.getBoundingClientRect();
        if (rect.width <= windowWidth)
          fontSize += kFontStep;
      }

      return fontSize;
    }

    var view = this.phoneNumberView;
    var computedStyle = window.getComputedStyle(view, null);
    var fontSize = computedStyle.getPropertyValue('font-size');

    var text = this.formatPhoneNumber(this.phoneNumber.value);
    view.innerHTML = text;

    var newFontSize =
      text ? getNextFontSize(parseInt(fontSize), text) : kDefaultFontSize;
    if (newFontSize != fontSize)
    view.style.fontSize = newFontSize + 'px';
  },

  keyDown: function kh_keyDown(event) {
    var key = event.target.getAttribute('data-value');
    if (!key)
      return;

    var callback = function(self) {
      switch (key) {
        case '0':
          self.phoneNumber.value = self.phoneNumber.value.slice(0, -1) + '+';
          break;
        case 'del':
          self.phoneNumber.value = '';
          break;
        default:
          if (self.isContactShortcut(key))
            return;
          break;
      }
      self.updateFontSize();
    };

    if (key == 'del') {
      this.phoneNumber.value = KeyHandler.phoneNumber.value.slice(0, -1);
      this.updateFontSize();
    } else if (key == 'call') {
      // TODO: update the call button style to show his availability
      if (this.phoneNumber.value != '') {
        CallHandler.call(this.phoneNumber.value);
      }
    } else {
      this.phoneNumber.value += key;
      this.updateFontSize();
      gTones[key].play();
    }

    this._timeout = window.setTimeout(callback, 400, this);
  },

  keyUp: function kh_keyUp(event) {
    clearTimeout(this._timeout);
  }
};

var CallHandler = {
  // callbacks
  call: function ch_call(number) {
    this.numberView.innerHTML = number;
    this.statusView.innerHTML = 'Calling...';
    this.actionsView.classList.remove('displayed');
    this.callButton.dataset.action = 'end';
    this.toggleCallScreen();

    var call = window.navigator.mozTelephony.call(number);
    call.addEventListener('readystatechange', this);
    this.currentCall = call;
  },
  incoming: function ch_incoming(call) {
    this.currentCall = call;

    this.numberView.innerHTML = call.number;
    this.statusView.innerHTML = 'Incoming call...';
    this.actionsView.classList.remove('displayed');
    this.callButton.dataset.action = 'answer';
    this.toggleCallScreen();
  },
  connected: function ch_connected() {
    // hardening against rapid ending
    if (!document.getElementById('call-screen').classList.contains('oncall'))
      return;

    this.statusView.innerHTML = '00:00';
    this.actionsView.classList.add('displayed');
    this.callButton.dataset.action = 'end';

    this._ticker = setInterval(function ch_updateTimer(self, startTime) {
      var elapsed = new Date(Date.now() - startTime);
      self.statusView.innerHTML = elapsed.toLocaleFormat('%M:%S');
    }, 1000, this, Date.now());
  },
  answer: function ch_answer() {
    this.currentCall.answer();
    this.connected();
  },
  end: function ch_end() {
    this.toggleCallScreen();
    this.currentCall.disconnect();
    this.currentCall.removeEventListener('readystatechange', this);

    this.actionsView.classList.remove('displayed');
    if (this.muteButton.classList.contains('mute'))
      this.toggleMute();

    this.closeModal();
    clearInterval(this._ticker);
  },

  handleEvent: function fm_handleEvent(evt) {
    this.connected();
  },

  // properties / methods
  get numberView() {
    delete this.numberView;
    return this.numberView = document.getElementById('callNumber-view');
  },
  get statusView() {
    delete this.statusView;
    return this.statusView = document.getElementById('callStatus-view');
  },
  get actionsView() {
    delete this.actionsView;
    return this.actionsView = document.getElementById('callActions-container');
  },
  get muteButton() {
    delete this.muteButton;
    return this.muteButton = document.getElementById('mute-button');
  },
  get callButton() {
    delete this.callButton;
    return this.callButton = document.getElementById('call-button');
  },

  execute: function ch_execute(action) {
    if (!this[action]) {
      this.end();
      return;
    }

    this[action]();
  },

  toggleCallScreen: function ch_toggleScreen() {
    document.getElementById('choices').classList.toggle('oncall');
    document.getElementById('views').classList.toggle('oncall');
    document.getElementById('call-screen').classList.toggle('oncall');
  },
  toggleMute: function ch_toggleMute() {
    this.muteButton.classList.toggle('mute');
    // TODO: make the actual mute call on the telephony API
  },
  keypad: function ch_keypad() {
    choiceChanged(document.getElementById('keyboard'));
    document.getElementById('views').classList.add('modal');
  },
  contacts: function ch_contacts() {
    choiceChanged(document.getElementById('contacts'));
    document.getElementById('views').classList.add('modal');
  },
  closeModal: function ch_closeModal() {
    // 2 steps closing to avoid showing the view in its non-modal state
    // during the transition
    var views = document.getElementById('views');
    views.classList.add('hidden');
    views.addEventListener('transitionend', function ch_closeModalFinish() {
      views.removeEventListener('transitionend', ch_closeModalFinish);
      views.classList.remove('modal');
      views.classList.remove('hidden');
    });
  }
};

window.addEventListener('load', function keyboardInit(evt) {
  window.removeEventListener('load', keyboardInit);
  KeyHandler.init();
});

<|endoftext|>


<commit_before>// import PostsView from './views/Posts';
import ToastsView from './views/Toasts';

export default function IndexController(container) {
  this._container = container;
  this._toastsView = new ToastsView(this._container);
  this._lostConnectionToast = null;
  this._registerServiceWorker();

  var indexController = this;
}

IndexController.prototype._registerServiceWorker = function() {
  if (!navigator.serviceWorker) return;

  var indexController = this;

  navigator.serviceWorker.register('/sw.js').then(function(reg) {
    if (!navigator.serviceWorker.controller) {
      return;
    }

    if (reg.waiting) {
      indexController._updateReady(reg.waiting);
      return;
    }

    if (reg.installing) {
      indexController._trackInstalling(reg.installing);
      return;
    }

    reg.addEventListener('updatefound', function() {
      indexController._trackInstalling(reg.installing);
    });

    navigator.serviceWorker.addEventListener('message', event => {
      indexController._sendMessage(event.data.msg);
    });
  });

  // Ensure refresh is only called once.
  // This works around a bug in "force update on reload".
  var refreshing;
  navigator.serviceWorker.addEventListener('controllerchange', function() {
    if (refreshing) return;
    window.location.reload();
    refreshing = true;
  });
};

IndexController.prototype._sendMessage = function(message) {
 var toast = this._toastsView.show(message, {
    buttons: ['dismiss']
  });

  toast.answer.then(function(answer) {
    return;
  });
}

IndexController.prototype._trackInstalling = function(worker) {
  var indexController = this;
  worker.addEventListener('statechange', function() {
    if (worker.state == 'installed') {
      indexController._updateReady(worker);
    }
  });
};

IndexController.prototype._updateReady = function(worker) {
  var toast = this._toastsView.show("New version available", {
    buttons: ['refresh', 'dismiss']
  });

  toast.answer.then(function(answer) {
    if (answer != 'refresh') return;
    worker.postMessage({action: 'skipWaiting'});
  });
};<commit_msg>pwa: limit to one toast at a time<commit_after>// import PostsView from './views/Posts';
import ToastsView from './views/Toasts';

export default function IndexController(container) {
  this._container = container;
  this._toastsView = new ToastsView(this._container);
  this._lostConnectionToast = null;
  this._registerServiceWorker();

  var indexController = this;
}

IndexController.prototype._registerServiceWorker = function() {
  if (!navigator.serviceWorker) return;

  var indexController = this;

  navigator.serviceWorker.register('/sw.js').then(function(reg) {
    if (!navigator.serviceWorker.controller) {
      return;
    }

    if (reg.waiting) {
      indexController._updateReady(reg.waiting);
      return;
    }

    if (reg.installing) {
      indexController._trackInstalling(reg.installing);
      return;
    }

    reg.addEventListener('updatefound', function() {
      indexController._trackInstalling(reg.installing);
    });

    navigator.serviceWorker.addEventListener('message', event => {
      indexController._sendMessage(event.data.msg);
    });
  });

  // Ensure refresh is only called once.
  // This works around a bug in "force update on reload".
  var refreshing;
  navigator.serviceWorker.addEventListener('controllerchange', function() {
    if (refreshing) return;
    window.location.reload();
    refreshing = true;
  });
};

IndexController.prototype._sendMessage = function(message) {
 if (!this._lostConnectionToast) {
   var toast = this._toastsView.show(message, {
      buttons: ['dismiss']
    });
    this._lostConnectionToast = 1;
    toast.answer.then(function(answer) {
      this._lostConnectionToast = null;
      return;
    });
  }
}

IndexController.prototype._trackInstalling = function(worker) {
  var indexController = this;
  worker.addEventListener('statechange', function() {
    if (worker.state == 'installed') {
      indexController._updateReady(worker);
    }
  });
};

IndexController.prototype._updateReady = function(worker) {
  var toast = this._toastsView.show("New version available", {
    buttons: ['refresh', 'dismiss']
  });

  toast.answer.then(function(answer) {
    if (answer != 'refresh') return;
    worker.postMessage({action: 'skipWaiting'});
  });
};<|endoftext|>


<commit_before>import { React, PropTypes, observer, styled } from 'vendor';
import { Icon } from 'shared';
import { colors } from 'theme';
import moment from 'moment';
import Loading from 'shared/components/loading-animation';
import HomeworkQuestions, { ExerciseNumber } from '../../components/homework-questions';
import S from '../../helpers/string';
import { isEmpty } from 'lodash';
import PreviewTooltip from '../assignment-edit/preview-tooltip';
import DeleteModal from './delete-modal';
import EditModal from './edit-modal';
import GradingBlock from './grading-block';
import { TruncatedText } from '../../components/text';
const DetailsWrapper = styled.div`

`;

const Section = styled.section`
  background: ${colors.neutral.lightest};
  padding: 3.4rem 2.4rem;

  h6 {
    text-transform: uppercase;
    font-weight: bold;
    flex: 1;
  }
`;

const Top = styled.div`
  display: flex;
  align-items: stretch;
  margin: 3.6rem 0 2rem;
  font-size: 1.6rem;
  line-height: 3rem;

  > section {
    &:first-child {
      flex: 1;
      margin-right: 2rem;
    }
    &:last-child {
      flex-basis: 35%;
    }
  }
`;

const Table = styled.div`
  display: table;
  width: 100%;
`;

const Row = styled.div`
  display: table-row;

  > * {
    display: table-cell;
    padding-bottom: 0.7rem;
  }
`;

export const Header = styled.div`
  display: flex;
  align-items: center;
  margin-bottom: 2rem;
`;

const Controls = styled.div`
  align-self: flex-end;
  display: flex;
  .btn.btn-icon {
    min-width: 0;
    width: 5.5rem;
    height: 4rem;
  }
  .btn + .btn {
    margin-left: 1.6rem;
  }
`;

const Title = styled.div`
  width: 18rem;
  margin-right: 3.3rem;
  color: ${colors.neutral.thin};
`;

const Item = ({ children }) => (

<TruncatedText maxWidth="40rem">{children}</TruncatedText>

);
Item.propTypes = {
  children: PropTypes.node.isRequired,
};

const TaskingDefinitionList = styled.div`
  dl {
    display: flex;
    align-items: center;
    max-width: 45rem;

    > * {
      width: 100%;
      &:not(:first-child) {
        dt, dd {
          text-align: center;
        }
      }
    }

    dt, dd {
      border-bottom: 1px solid ${colors.neutral.pale};
      padding-right: 1.6rem;
    }
    dt {
      font-size: 1.4rem;
    }
  }
`;

const TemplateInfoWrapper = styled.span`
  & .btn.btn-primary {
    border-color: ${colors.link};
    background: ${colors.link};
    &:hover, &:not(:disabled):active, &:focus {
      background: ${colors.link_active};
      border-color: ${colors.link};
    }
    color: #fff;
    text-transform: uppercase;
    font-size: 1rem;
    font-weight: bold;
    line-height: 1.2rem;
    border-radius: 0.8rem;
    padding: 0.1rem 0.8rem;
  }
`;

const StyledHomeworkQuestions = styled(HomeworkQuestions)`
  .question-header {
    border-left: 1rem solid ${colors.templates.homework.border};
    font-size: 1.6rem;
  }
  && .card-body {
    background: #fff;

    .question-stem {
      font-size: 1.4rem;
      font-weight: bold;
      line-height: 1.7rem;
    }
  }
`;

const StyledExerciseNumber = styled(ExerciseNumber)`
  font-size: 1.6rem;
`;

const QuestionHeader = observer(({ styleVariant, label, info }) => {
  return (
    <>

      {S.numberWithOneDecimalPlace(info.points)} Points
    </>
  );
});

QuestionHeader.propTypes = {
  styleVariant: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  info:  PropTypes.object.isRequired,
};

const Questions = observer(({ ux, questionsInfo }) => {
  if (ux.isExercisesReady && isEmpty(questionsInfo)) { return null; }
  return (

Questions Assigned

        <Controls>

          <Icon
            className="btn btn-standard btn-icon"
            onClick={ux.onEditAssignedQuestions}
            data-test-id="edit-assigned-questions"
            type="edit"
          />

        </Controls>

      {ux.isExercisesReady ? (

      {S.numberWithOneDecimalPlace(info.availablePoints)} Points
    </>
  );
});

QuestionHeader.propTypes = {
  styleVariant: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  info:  PropTypes.object.isRequired,
};

const Questions = observer(({ ux, questionsInfo }) => {
  if (ux.isExercisesReady && isEmpty(questionsInfo)) { return null; }
  return (

Questions Assigned

        <Controls>

          <Icon
            className="btn btn-standard btn-icon"
            onClick={ux.onEditAssignedQuestions}
            data-test-id="edit-assigned-questions"
            type="edit"
          />

        </Controls>

      {ux.isExercisesReady ? (


<commit_before>var ws;

Pebble.addEventListener("ready",
    function(e) {
        console.log('ready');
    }
);

Pebble.addEventListener("appmessage",
    function(e) {
        console.log(e.payload.control);
        if (ws == null) {
            var host = localStorage.getItem('host');
            ws = new WebSocket('ws://' + host + '/ws');
            ws.onopen = function() {
                ws.send(e.payload.control.toString());
                console.log('send');
            }
        } else {
            ws.send(e.payload.control.toString());
            console.log('send');
        }
    }
)

Pebble.addEventListener("showConfiguration", function() {
  console.log("showing configuration");
  var options = {host: localStorage.getItem('host')};
  var encodedOptions = encodeURIComponent(JSON.stringify(options));
  Pebble.openURL('https://raw.githubusercontent.com/planset/slidecontrol/master/pebble/config.html#' + encodedOptions);
});

Pebble.addEventListener("webviewclosed", function(e) {
  console.log("configuration closed");
  options = JSON.parse(decodeURIComponent(e.response));
  localStorage.setItem('host', options.host);
  console.log("Options = " + JSON.stringify(options));
});;
<commit_msg>Change config.html url<commit_after>var ws;

Pebble.addEventListener("ready",
    function(e) {
        console.log('ready');
    }
);

Pebble.addEventListener("appmessage",
    function(e) {
        console.log(e.payload.control);
        if (ws == null) {
            var host = localStorage.getItem('host');
            ws = new WebSocket('ws://' + host + '/ws');
            ws.onopen = function() {
                ws.send(e.payload.control.toString());
                console.log('send');
            }
        } else {
            ws.send(e.payload.control.toString());
            console.log('send');
        }
    }
)

Pebble.addEventListener("showConfiguration", function() {
  console.log("showing configuration");
  var options = {host: localStorage.getItem('host')};
  var encodedOptions = encodeURIComponent(JSON.stringify(options));
  Pebble.openURL('http://dkpyn.com/sandbox/pebble/config.html#' + encodedOptions);
});

Pebble.addEventListener("webviewclosed", function(e) {
  console.log("configuration closed");
  options = JSON.parse(decodeURIComponent(e.response));
  localStorage.setItem('host', options.host);
  console.log("Options = " + JSON.stringify(options));
});;
<|endoftext|>


<commit_before><commit_msg>Revert "feat(tests): Who knows!"<commit_after><|endoftext|>


<commit_before>var socketio;
if(process.env.MARKER_PATH != null) {
    socketio = require('socket.io')(http, { path: process.env.MARKER_PATH + '/socket.io' });
} else {
    socketio = require('socket.io');
}
var socketioclient = require('socket.io-client');
var request = require('request');

var config = require('./config/config');

var RETRY_ATTEMPTS = 30;
var RETRY_DELAY = 1000;
var RETRY_MAX_DELAY = 3000;

function initiate_pipe_reconnect(pipe) {
    var retry_pipe = pipe;

    if(retry_pipe.retry_attempts > 0) {
        retry_pipe.retry_attempts--;
        var delay = (RETRY_ATTEMPTS - retry_pipe.retry_attempts) * RETRY_DELAY;
        if(delay > RETRY_MAX_DELAY) {
            delay = RETRY_MAX_DELAY;
        }

        console.log('scheduling retry: ' + delay / 1000 + 'secs');
        retry_pipe.timer = setTimeout(function() {
            retry_pipe.timer = null;
            retry_pipe.connect(function(err) {
                if(err) {
                    initiate_pipe_reconnect(retry_pipe);
                }
            });
        }, delay);
    } else {
        retry_pipe.timer = null;
        retry_pipe.mark_dead();
    }
}

var fetch_pipe = {
    connected: false,
    cookies: null,
    baseurl: null,
    fetchurl: null,
    pipe: null,
    emit_socket: null,
    clientinfo: null,
    done: false,
    retry_timer: null,
    retry_attempts: RETRY_ATTEMPTS,

    initialize: function(host, port, socket, clientinfo) {
        this.baseurl = 'http://' + host + ':' + port;
        this.fetchurl = this.baseurl + '/points'
        this.emit_socket = socket;
        this.clientinfo = clientinfo;
    },

    connect: function(callback) {
        this.connected = false;
        if(this.retry_timer) {
            clearTimeout(this.retry_timer);
        }

        var pipe = this;
        request
            .get(pipe.baseurl)
            .on('response', function(res) {
                if (res.headers && res.headers['set-cookie'] && res.headers['set-cookie'].length > 0) {
                    pipe.cookies = res.headers['set-cookie'].join(';');
                }

                if(pipe.cookies) {
                    console.log('setting pipe up with cookies.');
                    pipe.pipe = socketioclient.connect(pipe.fetchurl, {
                        'reconnection': false,
                        'extraHeaders': {
                            'Cookie': pipe.cookies
                        }
                    });
                } else {
                    console.log('setting pipe up without cookies.');
                    pipe.pipe = socketioclient.connect(pipe.fetchurl, {
                        'reconnection': false
                    });
                }
                pipe.pipe.on('connect', function() {
                    console.log('fetch pipe connected.');
                    pipe.connected = true;
                    pipe.retry_attempts = RETRY_ATTEMPTS
                    pipe.pipe.emit('client', JSON.stringify(pipe.clientinfo));
                    pipe.emit_socket.emit('status');
                });
                pipe.pipe.on('disconnect', function() {
                    console.log('fetch pipe disconnected.');
                    if(pipe.connected) {
                        pipe.connected = false;
                    }
                    if(!pipe.done) {
                        console.log('fetch pipe attempting to reconnect.');
                        if(!pipe.retry_timer) {
                            initiate_pipe_reconnect(pipe);
                        } else {
                            console.log('fetch pipe retry timer already in process');
                        }
                    } else {
                        console.log('fetch pipe done, no need to reconnect.');
                        if(pipe.retry_timer) {
                            clearTimeout(pipe.retry_timer);
                            pipe.retry_timer = null;
                        }
                    }
                });
                pipe.pipe.on('point', function(pdata) {
                    console.log('sending client point: ' + pdata);
                    pipe.emit_socket.emit('point', pdata);
                });
                pipe.pipe.on('done', function() {
                    console.log('telling client done.');
                    pipe.done = true;
                    pipe.emit_socket.emit('done');
                    pipe.pipe.disconnect();
                });
            })
            .on('end', function() {
                callback();
            })
            .on('error', function(err) {
                callback(err);
            });
    },

    disconnect: function(teardown) {
        if(this.pipe != null) {
            if(teardown) {
                this.done = true;
            }
            this.connected = false;
            this.pipe.disconnect();
        }
    },

    emit: function(topic, data) {
        if(this.pipe != null && this.connected) {
            if(data) {
                this.pipe.emit(topic, data);
            } else {
                this.pipe.emit(topic);
            }
        }
    },

    mark_dead: function() {
        console.log('marking pipe dead.  telling client done.');
        if(this.emit_socket) {
            this.emit_socket.emit('done');
        }
    }
}

function get_fetch_pipe(host, port, socket, clientinfo) {
    var pipe = Object.create(fetch_pipe);
    pipe.initialize(host, port, socket, clientinfo);
    return pipe;
}

var channel = {
    io: null,
    initialize: function(server) {
        io = socketio(server);

        var client = io
            .of('/client')
            .on('connection', function(socket) {
                // state information
                var fetchpipe = null;
                var clientinfo = null;

                // browser-mapper socket
                // socket events
                socket.on('error', function(err) {
                    console.log('Error: ' + err);
                });
                socket.on('disconnect', function() {
                    console.log('Disconnecting from browser client.');
                    if(fetchpipe) {
                        fetchpipe.disconnect(true);
                        fetchpipe = null;
                    }
                });

                // browser driven events
                socket.on('hello', function(data) {
                    // data is a json blob having the following structure
                    //  {
                    //      "id": "<client id>",
                    //      "lat": <latitude>,
                    //      "lon": <longitude,
                    //  }
                    console.log('Client information: ' + data);
                    clientinfo = JSON.parse(data);

                    fetchpipe = get_fetch_pipe(config.fetchsvc, config.fetchport, socket, clientinfo);
                    if(fetchpipe) {
                        fetchpipe.connect(function(err) {
                            socket.on('status', function(sdata) {
                                console.log('Sending browser status to fetch pipe: ' + sdata);
                                if(fetchpipe) {
                                    fetchpipe.emit('status', sdata)
                                }
                            });
                        });
                    }
                });
            });
    }
};

module.exports = channel;<commit_msg>one more time<commit_after>var socketio;
if(process.env.MARKER_PATH != null) {
    socketio = require('socket.io')({ path: process.env.MARKER_PATH + '/socket.io' });
} else {
    socketio = require('socket.io');
}
var socketioclient = require('socket.io-client');
var request = require('request');

var config = require('./config/config');

var RETRY_ATTEMPTS = 30;
var RETRY_DELAY = 1000;
var RETRY_MAX_DELAY = 3000;

function initiate_pipe_reconnect(pipe) {
    var retry_pipe = pipe;

    if(retry_pipe.retry_attempts > 0) {
        retry_pipe.retry_attempts--;
        var delay = (RETRY_ATTEMPTS - retry_pipe.retry_attempts) * RETRY_DELAY;
        if(delay > RETRY_MAX_DELAY) {
            delay = RETRY_MAX_DELAY;
        }

        console.log('scheduling retry: ' + delay / 1000 + 'secs');
        retry_pipe.timer = setTimeout(function() {
            retry_pipe.timer = null;
            retry_pipe.connect(function(err) {
                if(err) {
                    initiate_pipe_reconnect(retry_pipe);
                }
            });
        }, delay);
    } else {
        retry_pipe.timer = null;
        retry_pipe.mark_dead();
    }
}

var fetch_pipe = {
    connected: false,
    cookies: null,
    baseurl: null,
    fetchurl: null,
    pipe: null,
    emit_socket: null,
    clientinfo: null,
    done: false,
    retry_timer: null,
    retry_attempts: RETRY_ATTEMPTS,

    initialize: function(host, port, socket, clientinfo) {
        this.baseurl = 'http://' + host + ':' + port;
        this.fetchurl = this.baseurl + '/points'
        this.emit_socket = socket;
        this.clientinfo = clientinfo;
    },

    connect: function(callback) {
        this.connected = false;
        if(this.retry_timer) {
            clearTimeout(this.retry_timer);
        }

        var pipe = this;
        request
            .get(pipe.baseurl)
            .on('response', function(res) {
                if (res.headers && res.headers['set-cookie'] && res.headers['set-cookie'].length > 0) {
                    pipe.cookies = res.headers['set-cookie'].join(';');
                }

                if(pipe.cookies) {
                    console.log('setting pipe up with cookies.');
                    pipe.pipe = socketioclient.connect(pipe.fetchurl, {
                        'reconnection': false,
                        'extraHeaders': {
                            'Cookie': pipe.cookies
                        }
                    });
                } else {
                    console.log('setting pipe up without cookies.');
                    pipe.pipe = socketioclient.connect(pipe.fetchurl, {
                        'reconnection': false
                    });
                }
                pipe.pipe.on('connect', function() {
                    console.log('fetch pipe connected.');
                    pipe.connected = true;
                    pipe.retry_attempts = RETRY_ATTEMPTS
                    pipe.pipe.emit('client', JSON.stringify(pipe.clientinfo));
                    pipe.emit_socket.emit('status');
                });
                pipe.pipe.on('disconnect', function() {
                    console.log('fetch pipe disconnected.');
                    if(pipe.connected) {
                        pipe.connected = false;
                    }
                    if(!pipe.done) {
                        console.log('fetch pipe attempting to reconnect.');
                        if(!pipe.retry_timer) {
                            initiate_pipe_reconnect(pipe);
                        } else {
                            console.log('fetch pipe retry timer already in process');
                        }
                    } else {
                        console.log('fetch pipe done, no need to reconnect.');
                        if(pipe.retry_timer) {
                            clearTimeout(pipe.retry_timer);
                            pipe.retry_timer = null;
                        }
                    }
                });
                pipe.pipe.on('point', function(pdata) {
                    console.log('sending client point: ' + pdata);
                    pipe.emit_socket.emit('point', pdata);
                });
                pipe.pipe.on('done', function() {
                    console.log('telling client done.');
                    pipe.done = true;
                    pipe.emit_socket.emit('done');
                    pipe.pipe.disconnect();
                });
            })
            .on('end', function() {
                callback();
            })
            .on('error', function(err) {
                callback(err);
            });
    },

    disconnect: function(teardown) {
        if(this.pipe != null) {
            if(teardown) {
                this.done = true;
            }
            this.connected = false;
            this.pipe.disconnect();
        }
    },

    emit: function(topic, data) {
        if(this.pipe != null && this.connected) {
            if(data) {
                this.pipe.emit(topic, data);
            } else {
                this.pipe.emit(topic);
            }
        }
    },

    mark_dead: function() {
        console.log('marking pipe dead.  telling client done.');
        if(this.emit_socket) {
            this.emit_socket.emit('done');
        }
    }
}

function get_fetch_pipe(host, port, socket, clientinfo) {
    var pipe = Object.create(fetch_pipe);
    pipe.initialize(host, port, socket, clientinfo);
    return pipe;
}

var channel = {
    io: null,
    initialize: function(server) {
        io = socketio(server);

        var client = io
            .of('/client')
            .on('connection', function(socket) {
                // state information
                var fetchpipe = null;
                var clientinfo = null;

                // browser-mapper socket
                // socket events
                socket.on('error', function(err) {
                    console.log('Error: ' + err);
                });
                socket.on('disconnect', function() {
                    console.log('Disconnecting from browser client.');
                    if(fetchpipe) {
                        fetchpipe.disconnect(true);
                        fetchpipe = null;
                    }
                });

                // browser driven events
                socket.on('hello', function(data) {
                    // data is a json blob having the following structure
                    //  {
                    //      "id": "<client id>",
                    //      "lat": <latitude>,
                    //      "lon": <longitude,
                    //  }
                    console.log('Client information: ' + data);
                    clientinfo = JSON.parse(data);

                    fetchpipe = get_fetch_pipe(config.fetchsvc, config.fetchport, socket, clientinfo);
                    if(fetchpipe) {
                        fetchpipe.connect(function(err) {
                            socket.on('status', function(sdata) {
                                console.log('Sending browser status to fetch pipe: ' + sdata);
                                if(fetchpipe) {
                                    fetchpipe.emit('status', sdata)
                                }
                            });
                        });
                    }
                });
            });
    }
};

module.exports = channel;<|endoftext|>


<commit_before>/*global joynrTestRequire: true */
/*jslint es5: true */

/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2015 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

joynrTestRequire(
        "joynr/messaging/channel/TestChannelMessagingSender",
        [
            "global/Promise",
            "joynr/messaging/channel/ChannelMessagingSender",
            "joynr/messaging/JoynrMessage",
            "joynr/system/RoutingTypes/ChannelAddress",
            "joynr/util/Typing",
            "joynr/system/LoggerFactory",
            "joynr/provisioning/provisioning_root"
        ],
        function(Promise, ChannelMessagingSender, JoynrMessage, ChannelAddress, Typing, LoggerFactory, provisioning) {

            var log = LoggerFactory.getLogger("joynr.messaging.TestChannelMessagingSender");

            describe(
                    "libjoynr-js.joynr.messaging.ChannelMessagingSender",
                    function() {
                        var communicationModuleSpy, channelMessageSender;
                        var channelId, channelUrl, channelUrlInformation, joynrMessage;
                        var resendDelay_ms;

                        function outputPromiseError(error) {
                            expect(error.toString()).toBeFalsy();
                        }

                        beforeEach(function() {
                            resendDelay_ms = 500;
                            channelId = "myChannel" + Date.now();
                            channelUrl = provisioning.bounceProxyUrl + "/channels/" + channelId;
                            var channelQos = {
                                resendDelay_ms : resendDelay_ms
                            };

                            joynrMessage = new JoynrMessage(JoynrMessage.JOYNRMESSAGE_TYPE_REQUEST);
                            joynrMessage.setHeader(
                                    JoynrMessage.JOYNRMESSAGE_HEADER_EXPIRYDATE,
                                    9360686108031);
                            joynrMessage.setHeader(
                                    JoynrMessage.JOYNRMESSAGE_HEADER_REPLY_CHANNELID,
                                    "me");
                            joynrMessage.payload = "hello";

                            // instantiate spies
                            communicationModuleSpy =
                                    jasmine.createSpyObj(
                                            "communicationModule",
                                            [ "createXMLHTTPRequest"
                                            ]);

                            channelMessageSender = new ChannelMessagingSender({
                                communicationModule : communicationModuleSpy,
                                channelQos : channelQos
                            });
                        });

                        it("is instantiable and has all members", function() {
                            expect(ChannelMessagingSender).toBeDefined();
                            expect(typeof ChannelMessagingSender === "function").toBeTruthy();
                            expect(channelMessageSender).toBeDefined();
                            expect(channelMessageSender instanceof ChannelMessagingSender)
                                    .toBeTruthy();
                            expect(channelMessageSender.send).toBeDefined();
                            expect(typeof channelMessageSender.send === "function").toBeTruthy();
                        });

                        it(
                                "if communicationModule.createXMLHTTPRequest call fails, channelMessageSender only fails if message expires",
                                function() {
                                    var spy = jasmine.createSpyObj("spy", [
                                        "onFulfilled",
                                        "onRejected"
                                    ]);
                                    var timeStamp;
                                    var relativeExpiryDate = resendDelay_ms * 3;

                                    runs(function() {
                                        communicationModuleSpy.createXMLHTTPRequest.andReturn(Promise.reject({
                                                    status : 500,
                                                    responseText : "responseText",
                                                    statusText : "errorThrown"
                                                }, "errorStatus"));
                                        joynrMessage.header[JoynrMessage.JOYNRMESSAGE_HEADER_EXPIRYDATE] = Date.now() + relativeExpiryDate;
                                        channelMessageSender.start();
                                        timeStamp = Date.now();
                                        channelMessageSender.send(joynrMessage, new ChannelAddress({channelId: channelId, messagingEndpointUrl: "http://testurl"})).then(
                                                spy.onFulfilled).catch(spy.onRejected);
                                    });

                                    waitsFor(function() {
                                        return spy.onRejected.callCount > 0;
                                    }, "message send to fail", relativeExpiryDate * 5);

                                    runs(function() {
                                        expect(spy.onFulfilled).not.toHaveBeenCalled();
                                        expect(spy.onRejected).toHaveBeenCalled();
                                        expect(Date.now()-timeStamp>relativeExpiryDate).toEqual(true);
                                        expect(
                                                Object.prototype.toString
                                                        .call(spy.onRejected.mostRecentCall.args[0]) === "[object Error]")
                                                .toBeTruthy();
                                        expect(communicationModuleSpy.createXMLHTTPRequest)
                                                .toHaveBeenCalled();
                                    });
                                });

                        it(
                                "channelMessageSender.send fails after expiryDate, if ChannelMessagingSender is not started",
                                function() {
                                    var spy = jasmine.createSpyObj("spy", [
                                        "onFulfilled",
                                        "onRejected"
                                    ]);
                                    var relativeExpiryDate = resendDelay_ms;

                                    runs(function() {
                                        joynrMessage.header[JoynrMessage.JOYNRMESSAGE_HEADER_EXPIRYDATE] = Date.now() + relativeExpiryDate;
                                        channelMessageSender.send(joynrMessage, channelId).then(
                                                spy.onFulfilled).catch(spy.onRejected);
                                    });

                                    waitsFor(function() {
                                        return spy.onFulfilled.callCount > 0 || spy.onRejected.callCount > 0;
                                    }, "message send to fail", relativeExpiryDate * 5);

                                    runs(function() {
                                        expect(spy.onFulfilled).not.toHaveBeenCalled();
                                        expect(spy.onRejected).toHaveBeenCalled();
                                        expect(joynrMessage.header[JoynrMessage.JOYNRMESSAGE_HEADER_EXPIRYDATE] < Date.now()).toEqual(true);
                                        expect(
                                                Object.prototype.toString
                                                        .call(spy.onRejected.mostRecentCall.args[0]) === "[object Error]")
                                                .toBeTruthy();

                                        spy.onRejected.reset();
                                        expect(communicationModuleSpy.createXMLHTTPRequest).not.toHaveBeenCalled();
                                    });
                                });

                        it(
                                "sends message using communicationModule.createXMLHTTPRequest",
                                function() {
                                    var spy = jasmine.createSpyObj("spy", [
                                        "onFulfilled",
                                        "onRejected"
                                    ]);
                                    runs(function() {
                                        communicationModuleSpy.createXMLHTTPRequest.andReturn(Promise.resolve());
                                        channelMessageSender.start();
                                        channelMessageSender.send(joynrMessage, channelId).then(
                                                spy.onFulfilled).catch(spy.onRejected);
                                    });

                                    waitsFor(function() {
                                        return spy.onFulfilled.callCount > 0;
                                    }, "message send to fail", provisioning.ttl);

                                    runs(function() {
                                        expect(spy.onFulfilled).toHaveBeenCalled();
                                        expect(spy.onFulfilled).toHaveBeenCalledWith(undefined);
                                        expect(spy.onRejected).not.toHaveBeenCalled();
                                        expect(communicationModuleSpy.createXMLHTTPRequest)
                                                .toHaveBeenCalled();
                                    });
                                });

                    });

        });<commit_msg>[JS] TestChannelMessageSender uses channelAddress instead of channelid<commit_after>/*global joynrTestRequire: true */
/*jslint es5: true */

/*
 * #%L
 * %%
 * Copyright (C) 2011 - 2015 BMW Car IT GmbH
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

joynrTestRequire(
        "joynr/messaging/channel/TestChannelMessagingSender",
        [
            "global/Promise",
            "joynr/messaging/channel/ChannelMessagingSender",
            "joynr/messaging/JoynrMessage",
            "joynr/system/RoutingTypes/ChannelAddress",
            "joynr/util/Typing",
            "joynr/system/LoggerFactory",
            "joynr/provisioning/provisioning_root"
        ],
        function(Promise, ChannelMessagingSender, JoynrMessage, ChannelAddress, Typing, LoggerFactory, provisioning) {

            var log = LoggerFactory.getLogger("joynr.messaging.TestChannelMessagingSender");

            describe(
                    "libjoynr-js.joynr.messaging.ChannelMessagingSender",
                    function() {
                        var communicationModuleSpy, channelMessageSender;
                        var channelAddress, channelUrlInformation, joynrMessage;
                        var resendDelay_ms;

                        function outputPromiseError(error) {
                            expect(error.toString()).toBeFalsy();
                        }

                        beforeEach(function() {
                            resendDelay_ms = 500;
                            channelAddress = new ChannelAddress({
                                messagingEndpointUrl : "http://testurl.com",
                                channelId : "myChannel" + Date.now()
                            });
                            var channelQos = {
                                resendDelay_ms : resendDelay_ms
                            };

                            joynrMessage = new JoynrMessage(JoynrMessage.JOYNRMESSAGE_TYPE_REQUEST);
                            joynrMessage.setHeader(
                                    JoynrMessage.JOYNRMESSAGE_HEADER_EXPIRYDATE,
                                    9360686108031);
                            joynrMessage.setHeader(
                                    JoynrMessage.JOYNRMESSAGE_HEADER_REPLY_CHANNELID,
                                    "me");
                            joynrMessage.payload = "hello";

                            // instantiate spies
                            communicationModuleSpy =
                                    jasmine.createSpyObj(
                                            "communicationModule",
                                            [ "createXMLHTTPRequest"
                                            ]);

                            channelMessageSender = new ChannelMessagingSender({
                                communicationModule : communicationModuleSpy,
                                channelQos : channelQos
                            });
                        });

                        it("is instantiable and has all members", function() {
                            expect(ChannelMessagingSender).toBeDefined();
                            expect(typeof ChannelMessagingSender === "function").toBeTruthy();
                            expect(channelMessageSender).toBeDefined();
                            expect(channelMessageSender instanceof ChannelMessagingSender)
                                    .toBeTruthy();
                            expect(channelMessageSender.send).toBeDefined();
                            expect(typeof channelMessageSender.send === "function").toBeTruthy();
                        });

                        it(
                                "if communicationModule.createXMLHTTPRequest call fails, channelMessageSender only fails if message expires",
                                function() {
                                    var spy = jasmine.createSpyObj("spy", [
                                        "onFulfilled",
                                        "onRejected"
                                    ]);
                                    var timeStamp;
                                    var relativeExpiryDate = resendDelay_ms * 3;

                                    runs(function() {
                                        communicationModuleSpy.createXMLHTTPRequest.andReturn(Promise.reject({
                                                    status : 500,
                                                    responseText : "responseText",
                                                    statusText : "errorThrown"
                                                }, "errorStatus"));
                                        joynrMessage.header[JoynrMessage.JOYNRMESSAGE_HEADER_EXPIRYDATE] = Date.now() + relativeExpiryDate;
                                        channelMessageSender.start();
                                        timeStamp = Date.now();
                                        channelMessageSender.send(joynrMessage, channelAddress).then(
                                                spy.onFulfilled).catch(spy.onRejected);
                                    });

                                    waitsFor(function() {
                                        return spy.onRejected.callCount > 0;
                                    }, "message send to fail", relativeExpiryDate * 5);

                                    runs(function() {
                                        expect(spy.onFulfilled).not.toHaveBeenCalled();
                                        expect(spy.onRejected).toHaveBeenCalled();
                                        expect(Date.now()-timeStamp>relativeExpiryDate).toEqual(true);
                                        expect(
                                                Object.prototype.toString
                                                        .call(spy.onRejected.mostRecentCall.args[0]) === "[object Error]")
                                                .toBeTruthy();
                                        expect(communicationModuleSpy.createXMLHTTPRequest)
                                                .toHaveBeenCalled();
                                    });
                                });

                        it(
                                "channelMessageSender.send fails after expiryDate, if ChannelMessagingSender is not started",
                                function() {
                                        var spy = jasmine.createSpyObj("spy", [
                                                                               "onFulfilled",
                                                                               "onRejected"
                                                                           ]);
                                                                           var relativeExpiryDate = resendDelay_ms;

                                                                           runs(function() {
                                                                               joynrMessage.header[JoynrMessage.JOYNRMESSAGE_HEADER_EXPIRYDATE] = Date.now() + relativeExpiryDate;
                                                                               channelMessageSender.send(joynrMessage, channelAddress).then(
                                                                                spy.onFulfilled).catch(spy.onRejected);
                                                                           });

                                                                           waitsFor(function() {
                                                                               return spy.onFulfilled.callCount > 0 || spy.onRejected.callCount > 0;
                                                                           }, "message send to fail", relativeExpiryDate * 5);

                                                                           runs(function() {
                                                                               expect(spy.onFulfilled).not.toHaveBeenCalled();
                                                                               expect(spy.onRejected).toHaveBeenCalled();
                                                                               expect(joynrMessage.header[JoynrMessage.JOYNRMESSAGE_HEADER_EXPIRYDATE] < Date.now()).toEqual(true);
                                                                               expect(
                                                                                Object.prototype.toString
                                                                                .call(spy.onRejected.mostRecentCall.args[0]) === "[object Error]")
                                                                                .toBeTruthy();

                                                                               spy.onRejected.reset();
                                                                               expect(communicationModuleSpy.createXMLHTTPRequest).not.toHaveBeenCalled();
                                                                           });
                                });

                        it(
                                "sends message using communicationModule.createXMLHTTPRequest",
                                function() {
                                    var spy = jasmine.createSpyObj("spy", [
                                        "onFulfilled",
                                        "onRejected"
                                    ]);
                                    runs(function() {
                                        communicationModuleSpy.createXMLHTTPRequest.andReturn(Promise.resolve());
                                        channelMessageSender.start();
                                        channelMessageSender.send(joynrMessage, channelAddress).then(
                                                spy.onFulfilled).catch(spy.onRejected);
                                    });

                                    waitsFor(function() {
                                        return spy.onFulfilled.callCount > 0;
                                    }, "message send to fail", provisioning.ttl);

                                    runs(function() {
                                        expect(spy.onFulfilled).toHaveBeenCalled();
                                        expect(spy.onFulfilled).toHaveBeenCalledWith(undefined);
                                        expect(spy.onRejected).not.toHaveBeenCalled();
                                        expect(communicationModuleSpy.createXMLHTTPRequest)
                                                .toHaveBeenCalled();
                                    });
                                });

                    });

        });<|endoftext|>