<commit_before>//fgnass.github.com/spin.js#v2.0.1
!function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define(b):a.Spinner=b()}(this,function(){"use strict";function a(a,b){var c,d=document.createElement(a||"div");for(c in b)d[c]=b[c];return d}function b(a){for(var b=1,c=arguments.length;c>b;b++)a.appendChild(arguments[b]);return a}function c(a,b,c,d){var e=["opacity",b,~~(100*a),c,d].join("-"),f=.01+c/d*100,g=Math.max(1-(1-a)/b*(100-f),a),h=j.substring(0,j.indexOf("Animation")).toLowerCase(),i=h&&"-"+h+"-"||"";return l[e]||(m.insertRule("@"+i+"keyframes "+e+"{0%{opacity:"+g+"}"+f+"%{opacity:"+a+"}"+(f+.01)+"%{opacity:1}"+(f+b)%100+"%{opacity:"+a+"}100%{opacity:"+g+"}}",m.cssRules.length),l[e]=1),e}function d(a,b){var c,d,e=a.style;for(b=b.charAt(0).toUpperCase()+b.slice(1),d=0;d<k.length;d++)if(c=k[d]+b,void 0!==e[c])return c;return void 0!==e[b]?b:void 0}function e(a,b){for(var c in b)a.style[d(a,c)||c]=b[c];return a}function f(a){for(var b=1;b<arguments.length;b++){var c=arguments[b];for(var d in c)void 0===a[d]&&(a[d]=c[d])}return a}function g(a,b){return"string"==typeof a?a:a[b%a.length]}function h(a){this.opts=f(a||{},h.defaults,n)}function i(){function c(b,c){return a("<"+b+' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">',c)}m.addRule(".spin-vml","behavior:url(#default#VML)"),h.prototype.lines=function(a,d){function f(){return e(c("group",{coordsize:k+" "+k,coordorigin:-j+" "+-j}),{width:k,height:k})}function h(a,h,i){b(m,b(e(f(),{rotation:360/d.lines*a+"deg",left:~~h}),b(e(c("roundrect",{arcsize:d.corners}),{width:j,height:d.width,left:d.radius,top:-d.width>>1,filter:i}),c("fill",{color:g(d.color,a),opacity:d.opacity}),c("stroke",{opacity:0}))))}var i,j=d.length+d.width,k=2*j,l=2*-(d.width+d.length)+"px",m=e(f(),{position:"absolute",top:l,left:l});if(d.shadow)for(i=1;i<=d.lines;i++)h(i,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(i=1;i<=d.lines;i++)h(i);return b(a,m)},h.prototype.opacity=function(a,b,c,d){var e=a.firstChild;d=d.shadow&&d.lines||0,e&&b+d<e.childNodes.length&&(e=e.childNodes[b+d],e=e&&e.firstChild,e=e&&e.firstChild,e&&(e.opacity=c))}}var j,k=["webkit","Moz","ms","O"],l={},m=function(){var c=a("style",{type:"text/css"});return b(document.getElementsByTagName("head")[0],c),c.sheet||c.styleSheet}(),n={lines:12,length:7,width:5,radius:10,rotate:0,corners:1,color:"#000",direction:1,speed:1,trail:100,opacity:.25,fps:20,zIndex:2e9,className:"spinner",top:"50%",left:"50%",position:"absolute"};h.defaults={},f(h.prototype,{spin:function(b){this.stop();{var c=this,d=c.opts,f=c.el=e(a(0,{className:d.className}),{position:d.position,width:0,zIndex:d.zIndex});d.radius+d.length+d.width}if(e(f,{left:d.left,top:d.top}),b&&b.insertBefore(f,b.firstChild||null),f.setAttribute("role","progressbar"),c.lines(f,c.opts),!j){var g,h=0,i=(d.lines-1)*(1-d.direction)/2,k=d.fps,l=k/d.speed,m=(1-d.opacity)/(l*d.trail/100),n=l/d.lines;!function o(){h++;for(var a=0;a<d.lines;a++)g=Math.max(1-(h+(d.lines-a)*n)%l*m,d.opacity),c.opacity(f,a*d.direction+i,g,d);c.timeout=c.el&&setTimeout(o,~~(1e3/k))}()}return c},stop:function(){var a=this.el;return a&&(clearTimeout(this.timeout),a.parentNode&&a.parentNode.removeChild(a),this.el=void 0),this},lines:function(d,f){function h(b,c){return e(a(),{position:"absolute",width:f.length+f.width+"px",height:f.width+"px",background:b,boxShadow:c,transformOrigin:"left",transform:"rotate("+~~(360/f.lines*k+f.rotate)+"deg) translate("+f.radius+"px,0)",borderRadius:(f.corners*f.width>>1)+"px"})}for(var i,k=0,l=(f.lines-1)*(1-f.direction)/2;k<f.lines;k++)i=e(a(),{position:"absolute",top:1+~(f.width/2)+"px",transform:f.hwaccel?"translate3d(0,0,0)":"",opacity:f.opacity,animation:j&&c(f.opacity,f.trail,l+k*f.direction,f.lines)+" "+1/f.speed+"s linear infinite"}),f.shadow&&b(i,e(h("#000","0 0 4px #000"),{top:"2px"})),b(d,b(i,h(g(f.color,k),"0 0 1px rgba(0,0,0,.1)")));return d},opacity:function(a,b,c){b<a.childNodes.length&&(a.childNodes[b].style.opacity=c)}});var o=e(a("group"),{behavior:"url(#default#VML)"});return!d(o,"transform")&&o.adj?i():j=d(o,"animation"),h});

$.fn.romoIndicator = function() {
  return $.map(this, function(element) {
    return new RomoIndicator(element);
  });
}

var RomoIndicator = function(element) {
  this.elem = $(element);
  this.spinnerOpts = {
    lines: 11, // The number of lines to draw
    width: 2, // The line thickness
    length: parseInt(this.elem.css('font-size')) / 2, // The length of each line
    radius: parseInt(this.elem.css('font-size')) / 3, // The radius of the inner circle
    corners: 1, // Corner roundness (0..1)
    rotate: 0, // The rotation offset
    direction: 1, // 1: clockwise, -1: counterclockwise
    color: this.elem.css('color'), // #rgb or #rrggbb or array of colors
    speed: 1, // Rounds per second
    trail: 60, // Afterglow percentage
    shadow: false, // Whether to render a shadow
    hwaccel: false, // Whether to use hardware acceleration
    className: 'spinner', // The CSS class to assign to the spinner
    zIndex: 1000, // The z-index (defaults to 2000000000)
    top: '50%', // Top position relative to parent
    left: '50%'// Left position relative to parent
  };

  this.doInit();
  this.spinner = new Spinner(this.spinnerOpts);

  this.elem.on('indicator:triggerStart', $.proxy(this.onStart, this));
  this.elem.on('indicator:triggerStop', $.proxy(this.onStop, this));

  if (this.elem.data('romo-indicator-stop-on-pageshow') !== false) {
    $(window).on("pageshow", $.proxy(function(e) {
      this.elem.trigger('indicator:triggerStop');
    }, this));
  }

  this.elem.trigger('indicator:ready', [this]);
}

RomoIndicator.prototype.doInit = function() {
  // override as needed
}

RomoIndicator.prototype.onStart = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }

  this.doStart();
}

RomoIndicator.prototype.onStop = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }

  this.doStop();
}

RomoIndicator.prototype.doStart = function() {
  this.elemHtml  = this.elem.html();
  this.elemStyle = this.elem.attr('style');
  this.elem.css({
    'position': 'relative',
    'width':    this.elem.css('width'),
    'height':   this.elem.css('height'),
  });
  this.elem.html('');
  this.spinner.spin(this.elem[0]);
  this.elem.trigger('indicator:start', [this]);
}

RomoIndicator.prototype.doStop = function() {
  this.spinner.stop();
  if (this.elemHtml !== undefined) {
    this.elem.html(this.elemHtml);
  }
  this.elem.css({
    'position': '',
    'width':    '',
    'height':   '',
  });
  if (this.elemStyle !== undefined) {
    this.elem.attr('style', this.elemStyle);
  }
  this.elem.trigger('indicator:stop', [this]);
}

Romo.onInitUI(function(e) {
  Romo.initUIElems(e, '[data-romo-indicator-auto="true"]').romoIndicator();
});
<commit_msg>hotfix: fix for indicator wiping width/height inline styles on init<commit_after>//fgnass.github.com/spin.js#v2.0.1
!function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define(b):a.Spinner=b()}(this,function(){"use strict";function a(a,b){var c,d=document.createElement(a||"div");for(c in b)d[c]=b[c];return d}function b(a){for(var b=1,c=arguments.length;c>b;b++)a.appendChild(arguments[b]);return a}function c(a,b,c,d){var e=["opacity",b,~~(100*a),c,d].join("-"),f=.01+c/d*100,g=Math.max(1-(1-a)/b*(100-f),a),h=j.substring(0,j.indexOf("Animation")).toLowerCase(),i=h&&"-"+h+"-"||"";return l[e]||(m.insertRule("@"+i+"keyframes "+e+"{0%{opacity:"+g+"}"+f+"%{opacity:"+a+"}"+(f+.01)+"%{opacity:1}"+(f+b)%100+"%{opacity:"+a+"}100%{opacity:"+g+"}}",m.cssRules.length),l[e]=1),e}function d(a,b){var c,d,e=a.style;for(b=b.charAt(0).toUpperCase()+b.slice(1),d=0;d<k.length;d++)if(c=k[d]+b,void 0!==e[c])return c;return void 0!==e[b]?b:void 0}function e(a,b){for(var c in b)a.style[d(a,c)||c]=b[c];return a}function f(a){for(var b=1;b<arguments.length;b++){var c=arguments[b];for(var d in c)void 0===a[d]&&(a[d]=c[d])}return a}function g(a,b){return"string"==typeof a?a:a[b%a.length]}function h(a){this.opts=f(a||{},h.defaults,n)}function i(){function c(b,c){return a("<"+b+' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">',c)}m.addRule(".spin-vml","behavior:url(#default#VML)"),h.prototype.lines=function(a,d){function f(){return e(c("group",{coordsize:k+" "+k,coordorigin:-j+" "+-j}),{width:k,height:k})}function h(a,h,i){b(m,b(e(f(),{rotation:360/d.lines*a+"deg",left:~~h}),b(e(c("roundrect",{arcsize:d.corners}),{width:j,height:d.width,left:d.radius,top:-d.width>>1,filter:i}),c("fill",{color:g(d.color,a),opacity:d.opacity}),c("stroke",{opacity:0}))))}var i,j=d.length+d.width,k=2*j,l=2*-(d.width+d.length)+"px",m=e(f(),{position:"absolute",top:l,left:l});if(d.shadow)for(i=1;i<=d.lines;i++)h(i,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(i=1;i<=d.lines;i++)h(i);return b(a,m)},h.prototype.opacity=function(a,b,c,d){var e=a.firstChild;d=d.shadow&&d.lines||0,e&&b+d<e.childNodes.length&&(e=e.childNodes[b+d],e=e&&e.firstChild,e=e&&e.firstChild,e&&(e.opacity=c))}}var j,k=["webkit","Moz","ms","O"],l={},m=function(){var c=a("style",{type:"text/css"});return b(document.getElementsByTagName("head")[0],c),c.sheet||c.styleSheet}(),n={lines:12,length:7,width:5,radius:10,rotate:0,corners:1,color:"#000",direction:1,speed:1,trail:100,opacity:.25,fps:20,zIndex:2e9,className:"spinner",top:"50%",left:"50%",position:"absolute"};h.defaults={},f(h.prototype,{spin:function(b){this.stop();{var c=this,d=c.opts,f=c.el=e(a(0,{className:d.className}),{position:d.position,width:0,zIndex:d.zIndex});d.radius+d.length+d.width}if(e(f,{left:d.left,top:d.top}),b&&b.insertBefore(f,b.firstChild||null),f.setAttribute("role","progressbar"),c.lines(f,c.opts),!j){var g,h=0,i=(d.lines-1)*(1-d.direction)/2,k=d.fps,l=k/d.speed,m=(1-d.opacity)/(l*d.trail/100),n=l/d.lines;!function o(){h++;for(var a=0;a<d.lines;a++)g=Math.max(1-(h+(d.lines-a)*n)%l*m,d.opacity),c.opacity(f,a*d.direction+i,g,d);c.timeout=c.el&&setTimeout(o,~~(1e3/k))}()}return c},stop:function(){var a=this.el;return a&&(clearTimeout(this.timeout),a.parentNode&&a.parentNode.removeChild(a),this.el=void 0),this},lines:function(d,f){function h(b,c){return e(a(),{position:"absolute",width:f.length+f.width+"px",height:f.width+"px",background:b,boxShadow:c,transformOrigin:"left",transform:"rotate("+~~(360/f.lines*k+f.rotate)+"deg) translate("+f.radius+"px,0)",borderRadius:(f.corners*f.width>>1)+"px"})}for(var i,k=0,l=(f.lines-1)*(1-f.direction)/2;k<f.lines;k++)i=e(a(),{position:"absolute",top:1+~(f.width/2)+"px",transform:f.hwaccel?"translate3d(0,0,0)":"",opacity:f.opacity,animation:j&&c(f.opacity,f.trail,l+k*f.direction,f.lines)+" "+1/f.speed+"s linear infinite"}),f.shadow&&b(i,e(h("#000","0 0 4px #000"),{top:"2px"})),b(d,b(i,h(g(f.color,k),"0 0 1px rgba(0,0,0,.1)")));return d},opacity:function(a,b,c){b<a.childNodes.length&&(a.childNodes[b].style.opacity=c)}});var o=e(a("group"),{behavior:"url(#default#VML)"});return!d(o,"transform")&&o.adj?i():j=d(o,"animation"),h});

$.fn.romoIndicator = function() {
  return $.map(this, function(element) {
    return new RomoIndicator(element);
  });
}

var RomoIndicator = function(element) {
  this.elem = $(element);
  this.spinnerOpts = {
    lines: 11, // The number of lines to draw
    width: 2, // The line thickness
    length: parseInt(this.elem.css('font-size')) / 2, // The length of each line
    radius: parseInt(this.elem.css('font-size')) / 3, // The radius of the inner circle
    corners: 1, // Corner roundness (0..1)
    rotate: 0, // The rotation offset
    direction: 1, // 1: clockwise, -1: counterclockwise
    color: this.elem.css('color'), // #rgb or #rrggbb or array of colors
    speed: 1, // Rounds per second
    trail: 60, // Afterglow percentage
    shadow: false, // Whether to render a shadow
    hwaccel: false, // Whether to use hardware acceleration
    className: 'spinner', // The CSS class to assign to the spinner
    zIndex: 1000, // The z-index (defaults to 2000000000)
    top: '50%', // Top position relative to parent
    left: '50%'// Left position relative to parent
  };

  this.elemStyle = this.elem.attr('style');
  this.doInit();
  this.spinner = new Spinner(this.spinnerOpts);

  this.elem.on('indicator:triggerStart', $.proxy(this.onStart, this));
  this.elem.on('indicator:triggerStop', $.proxy(this.onStop, this));

  if (this.elem.data('romo-indicator-stop-on-pageshow') !== false) {
    $(window).on("pageshow", $.proxy(function(e) {
      this.elem.trigger('indicator:triggerStop');
    }, this));
  }

  this.elem.trigger('indicator:ready', [this]);
}

RomoIndicator.prototype.doInit = function() {
  // override as needed
}

RomoIndicator.prototype.onStart = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }

  this.doStart();
}

RomoIndicator.prototype.onStop = function(e) {
  if (e !== undefined) {
    e.preventDefault();
  }

  this.doStop();
}

RomoIndicator.prototype.doStart = function() {
  this.elemHtml  = this.elem.html();
  this.elemStyle = this.elem.attr('style');
  this.elem.css({
    'position': 'relative',
    'width':    this.elem.css('width'),
    'height':   this.elem.css('height'),
  });
  this.elem.html('');
  this.spinner.spin(this.elem[0]);
  this.elem.trigger('indicator:start', [this]);
}

RomoIndicator.prototype.doStop = function() {
  this.spinner.stop();
  if (this.elemHtml !== undefined) {
    this.elem.html(this.elemHtml);
  }
  this.elem.css({
    'position': '',
    'width':    '',
    'height':   '',
  });
  if (this.elemStyle !== undefined) {
    this.elem.attr('style', this.elemStyle);
  }
  this.elem.trigger('indicator:stop', [this]);
}

Romo.onInitUI(function(e) {
  Romo.initUIElems(e, '[data-romo-indicator-auto="true"]').romoIndicator();
});
<|endoftext|>


<commit_before>var StatusSelector = React.createClass({
  handleChange: function(event) {
    this.props.updateStatusFilter(event.target.value)
  },
  render: function() {
    return (

              <button type="button" value="" className="btn btn-default navbar-btn" onClick={this.handleChange}>Any</button>
              <button type="button" value="success" className="btn btn-default navbar-btn alert-success" onClick={this.handleChange}>Success</button>
              <button type="button" value="warning" className="btn btn-default navbar-btn alert-warning" onClick={this.handleChange}>Warning</button>
              <button type="button" value="danger" className="btn btn-default navbar-btn alert-danger" onClick={this.handleChange}>Dagner</button>
              <button type="button" value="info" className="btn btn-default navbar-btn alert-info" onClick={this.handleChange}>Info</button>

    );
  }
});

var Title = React.createClass({
  render: function() {
    return (
      : {this.props.category}
    );
  }
});

var Category = React.createClass({
  handleClick: function(event) {
    this.props.updateCategory(this.props.name)
  },
  render: function() {
    var active = this.props.currentCategory == this.props.name ? "active" : "";
    return (

{this.props.name}

    );
  }
});

var Categories = React.createClass({
  handleChange: function(cat) {
    this.props.updateCategory(cat)
  },
  render: function() {
    var currentCategory = this.props.currentCategory
    var handleChange = this.handleChange
    var cats = this.props.data.map(function(cat, index) {
      return (
        <Category key={index} name={cat} currentCategory={currentCategory} updateCategory={handleChange}/>
      );
    });
    return (

        {cats}

    );
  }
});

var Item = React.createClass({
  render: function() {
    var item = this.props.item;
    var icon = "glyphicon";
    var status = item.status;
    if (item.status != "success" && item.status != "info") {
      icon += " glyphicon-alert";
      status += " alert-" + item.status;
    }
    return (

           {item.node}
          {item.address}
          {item.key}
          {item.timestamp}

          <ItemBody>{item.data}</ItemBody>

    );
  }
});

var ItemBody = React.createClass({
  handleClick: function() {
    if ( this.state.expanded && window.getSelection().toString() != "" ) {
      return;
    }
    this.setState({ expanded: !this.state.expanded })
  },
  getInitialState: function() {
    return { expanded: false };
  },
  render: function() {
    var classString = "item_body"
    if (this.state.expanded) {
      classString = "item_body_expanded"
    }
    return (

{this.props.children}

    );
  }
});

var Dashboard = React.createClass({
  loadCategoriesFromServer: function() {
    $.ajax({
      url: "/api/?keys",
      dataType: 'json',
      success: function(data, textStatus, request) {
        if (!this.state.currentCategory) {
          location.pathname = "/" + data[0]
        } else {
          this.setState({categories: data})
        }
      }.bind(this),
      error: function(xhr, status, err) {
        console.error("/api/?keys", status, err.toString());
      }.bind(this)
    });
  },
  loadDashboardFromServer: function() {
    if (!this.state.currentCategory) {
        setTimeout(this.loadDashboardFromServer, this.props.pollWait / 5);
        return;
    }
    var statusFilter = this.state.statusFilter;
    var ajax = $.ajax({
      url: "/api/" + this.state.currentCategory + "?recurse&wait=55s&index=" + this.state.index || 0,
      dataType: 'json',
      success: function(data, textStatus, request) {
        var timer = setTimeout(this.loadDashboardFromServer, this.props.pollWait);
        var index = request.getResponseHeader('X-Consul-Index')
        this.setState({
          items: data,
          index: index,
          timer: timer,
        });
      }.bind(this),
      error: function(xhr, status, err) {
        console.log("ajax error:" + err)
        var wait = this.props.pollWait * 5
        if (err == "abort") {
          wait = 0
        }
        var timer = setTimeout(this.loadDashboardFromServer, wait);
        this.setState({ timer: timer })
      }.bind(this)
    });
    this.setState({ajax: ajax})
  },
  getInitialState: function() {
    var cat = location.pathname.replace(/^\//,"")
    if (cat == "") {
      cat = undefined
    }
    return {
      items: [],
      categories: [],
      index: 0,
      ajax: undefined,
      timer: undefined,
      statusFilter: "",
      currentCategory: cat
    };
  },
  componentDidMount: function() {
    this.loadCategoriesFromServer();
    this.loadDashboardFromServer();
  },
  updateCategory: function(cat) {
    if (this.state.ajax) {
      this.state.ajax.abort()
    }
    location.pathname = "/" + cat
  },
  updateStatusFilter: function(filter) {
    this.setState({ statusFilter: filter });
  },
  render: function() {
    var filter = this.state.statusFilter;
    var items = this.state.items.map(function(item, index) {
      if (filter == "" || item.status == filter) {
        return (
          <Item key={index} item={item} />
        );
      } else {
        return;
      }
    });
    return (

Dashboard <Title category={this.state.currentCategory} />

        <Categories data={this.state.categories} currentCategory={this.state.currentCategory} updateCategory={this.updateCategory}/>
        <StatusSelector status={this.state.statusFilter} updateStatusFilter={this.updateStatusFilter}/>

              node
              address
              key
              timestamp

          {items}

    );
  }
});

React.render(
  <Dashboard pollWait={1000} />,
  document.getElementById('content')
);
<commit_msg>add node filter textbox<commit_after>var StatusSelector = React.createClass({
  handleChange: function(event) {
    this.props.updateStatusFilter(event.target.value)
  },
  handleGrep: function(event) {
    this.props.updateNodeFilter(event.target.value)
  },
  render: function() {
    return (

              <form className="form-inline">
                <button type="button" value="" className="btn btn-default navbar-btn" onClick={this.handleChange}>Any</button>
                <button type="button" value="success" className="btn btn-default navbar-btn alert-success" onClick={this.handleChange}>Success</button>
                <button type="button" value="warning" className="btn btn-default navbar-btn alert-warning" onClick={this.handleChange}>Warning</button>
                <button type="button" value="danger" className="btn btn-default navbar-btn alert-danger" onClick={this.handleChange}>Dagner</button>
                <button type="button" value="info" className="btn btn-default navbar-btn alert-info" onClick={this.handleChange}>Info</button>
                <input type="text" id="nodeFilter" className="form-control" placeholder="nodename"  onKeyUp={this.handleGrep}/>
              </form>

    );
  }
});

var Title = React.createClass({
  render: function() {
    return (
      : {this.props.category}
    );
  }
});

var Category = React.createClass({
  handleClick: function(event) {
    this.props.updateCategory(this.props.name)
  },
  render: function() {
    var active = this.props.currentCategory == this.props.name ? "active" : "";
    return (

{this.props.name}

    );
  }
});

var Categories = React.createClass({
  handleChange: function(cat) {
    this.props.updateCategory(cat)
  },
  render: function() {
    var currentCategory = this.props.currentCategory
    var handleChange = this.handleChange
    var cats = this.props.data.map(function(cat, index) {
      return (
        <Category key={index} name={cat} currentCategory={currentCategory} updateCategory={handleChange}/>
      );
    });
    return (

        {cats}

    );
  }
});

var Item = React.createClass({
  render: function() {
    var item = this.props.item;
    var icon = "glyphicon";
    var status = item.status;
    if (item.status != "success" && item.status != "info") {
      icon += " glyphicon-alert";
      status += " alert-" + item.status;
    }
    return (

           {item.node}
          {item.address}
          {item.key}
          {item.timestamp}

          <ItemBody>{item.data}</ItemBody>

    );
  }
});

var ItemBody = React.createClass({
  handleClick: function() {
    if ( this.state.expanded && window.getSelection().toString() != "" ) {
      return;
    }
    this.setState({ expanded: !this.state.expanded })
  },
  getInitialState: function() {
    return { expanded: false };
  },
  render: function() {
    var classString = "item_body"
    if (this.state.expanded) {
      classString = "item_body_expanded"
    }
    return (

{this.props.children}

    );
  }
});

var Dashboard = React.createClass({
  loadCategoriesFromServer: function() {
    $.ajax({
      url: "/api/?keys",
      dataType: 'json',
      success: function(data, textStatus, request) {
        if (!this.state.currentCategory) {
          location.pathname = "/" + data[0]
        } else {
          this.setState({categories: data})
        }
      }.bind(this),
      error: function(xhr, status, err) {
        console.error("/api/?keys", status, err.toString());
      }.bind(this)
    });
  },
  loadDashboardFromServer: function() {
    if (!this.state.currentCategory) {
        setTimeout(this.loadDashboardFromServer, this.props.pollWait / 5);
        return;
    }
    var statusFilter = this.state.statusFilter;
    var ajax = $.ajax({
      url: "/api/" + this.state.currentCategory + "?recurse&wait=55s&index=" + this.state.index || 0,
      dataType: 'json',
      success: function(data, textStatus, request) {
        var timer = setTimeout(this.loadDashboardFromServer, this.props.pollWait);
        var index = request.getResponseHeader('X-Consul-Index')
        this.setState({
          items: data,
          index: index,
          timer: timer,
        });
      }.bind(this),
      error: function(xhr, status, err) {
        console.log("ajax error:" + err)
        var wait = this.props.pollWait * 5
        if (err == "abort") {
          wait = 0
        }
        var timer = setTimeout(this.loadDashboardFromServer, wait);
        this.setState({ timer: timer })
      }.bind(this)
    });
    this.setState({ajax: ajax})
  },
  getInitialState: function() {
    var cat = location.pathname.replace(/^\//,"")
    if (cat == "") {
      cat = undefined
    }
    return {
      items: [],
      categories: [],
      index: 0,
      ajax: undefined,
      timer: undefined,
      statusFilter: "",
      nodeFilter: "",
      currentCategory: cat
    };
  },
  componentDidMount: function() {
    this.loadCategoriesFromServer();
    this.loadDashboardFromServer();
  },
  updateCategory: function(cat) {
    if (this.state.ajax) {
      this.state.ajax.abort()
    }
    location.pathname = "/" + cat
  },
  updateStatusFilter: function(filter) {
    this.setState({ statusFilter: filter });
  },
  updateNodeFilter: function(filter) {
    this.setState({ nodeFilter: filter });
  },
  render: function() {
    var statusFilter = this.state.statusFilter;
    var nodeFilter = this.state.nodeFilter;
    var items = this.state.items.map(function(item, index) {
      if ((statusFilter == "" || item.status == statusFilter) && (nodeFilter == "" || item.node.indexOf(nodeFilter) != -1 )) {
        return (
          <Item key={index} item={item} />
        );
      } else {
        return;
      }
    });
    return (

Dashboard <Title category={this.state.currentCategory} />

        <Categories data={this.state.categories} currentCategory={this.state.currentCategory} updateCategory={this.updateCategory}/>
        <StatusSelector status={this.state.statusFilter} updateStatusFilter={this.updateStatusFilter} updateNodeFilter={this.updateNodeFilter}/>

              node
              address
              key
              timestamp

          {items}

    );
  }
});

React.render(
  <Dashboard pollWait={1000} />,
  document.getElementById('content')
);
<|endoftext|>


<commit_before>import axios from 'axios'

let fetchNode = (key, whitelist, depth) => {
    return new Promise((resolve, reject) => {
        let params = {}
        if (depth) {
            params.depth = depth
        }
        if (whitelist.url) {
            params.whitelist_url = whitelist.url
        }
        if (whitelist.username) {
            params.whitelist_usernames = whitelist.username
        }

        axios.get(LIQUIO_URL + '/api/nodes/' + encodeURIComponent(key), { params: params }).then((response) => {
            resolve(response.data.data)
        }).catch(e => reject(e))
    })
}

let fetchSearch = (query, whitelist) => {
    return new Promise((resolve, reject) => {
        let params = {}
        if (whitelist.url) {
            params.whitelist_url = whitelist.url
        }
        if (whitelist.username) {
            params.whitelist_usernames = whitelist.username
        }

        axios.get(LIQUIO_URL + '/api/search/' + encodeURIComponent(query), { params: params }).then((response) => {
            resolve(response.data.data)
        }).catch(e => reject(e))
    })
}

export default {
    initialize ({ commit, dispatch, state }) {
        window.addEventListener('sign-anything-response', (e) => {
            let data = e.detail
            if (data.request_name === 'whitelist') {
                this.username = data.username
                this.whitelistUrl = data.url
                commit('SET_WHITELIST', {
                    username: data.username,
                    url: data.url
                })
                dispatch('updateNodes')
            } else if (data.request_name === 'sign') {
                 // TODO get refresh titles from store
                let currentTitle = state.currentTitle
                let currentReferenceTitle = state.currentReferenceTitle
                setTimeout(() => {
                    dispatch('loadNode', { key: state.currentPage })
                    if (currentTitle)
                        dispatch('loadNode', { key: currentTitle })
                    if (currentReferenceTitle)
                        dispatch('loadNode', { key: currentReferenceTitle })
                }, 500)
            }
        })
    },
    setCurrentPage ({ state, commit, dispatch }, payload) {
        commit('SET_CURRENT_PAGE', payload)
        dispatch('loadNode', { key: payload, refresh: true })
    },
    setCurrentTitle ({ state, commit, dispatch }, payload) {
        commit('SET_IS_VOTING_DISABLED', false)
        commit('SET_CURRENT_TITLE', payload)
        commit('ADD_TO_HISTORY')
        dispatch('loadNode', { key: payload, refresh: true })
    },
    setCurrentReferenceTitle ({ state, commit, dispatch }, payload) {
        commit('SET_CURRENT_REFERENCE_TITLE', payload)
        if (payload) {
            commit('ADD_TO_HISTORY')
            dispatch('loadNode', { key: payload, refresh: true })
        }
    },
    disableVoting ({ state, commit }) {
        commit('SET_IS_VOTING_DISABLED', true)
    },
    navigateBack ({ state, commit }) {
        if (state.historyIndex > 0) {
            commit('GO_TO_HISTORY_INDEX', state.historyIndex - 1)
        }
    },
    updateNodes ({ state, commit }) {
        let promises = state.refreshKeys.map(key => fetchNode(key, state.whitelist, 2))
        axios.all(promises).then(response => {
            for (let node of response) {
                commit('SET_NODE', node)
            }
        }).catch(() => {})
    },
    search ({ state }, query) {
        return fetchSearch(query, state.whitelist)
    },
    vote ({ commit }, { messages, messageKeys }) {
        let data = {
            name: 'sign',
            messages: messages,
            messageKeys: messageKeys
        }
        let event = new CustomEvent('sign-anything', { detail: data })
        window.dispatchEvent(event)
    },
    loadNode ({ state, commit }, { key, refresh }) {
        let transformReference = (reference) => {
            return {
                title: reference.title,
                referenceResults: reference.reference_results,
                byTitle: reference.referencing_title
            }
        }

        let flattenNode = (node) => {
            let nodes = []
            let existingNode = state.nodesByKey[node.title] || {}
            nodes.push({
                title: node.title,
                results: node.results,
                references: node.references === null ? existingNode.references : node.references.map(transformReference),
                inverseReferences: node.inverse_references === null ? existingNode.inverseReferences : node.inverse_references.map(transformReference)
            })

            if (node.references)
                for (let reference of node.references)
                    nodes = nodes.concat(flattenNode(reference))

            if (node.inverse_references)
                for (let inverseReference of node.inverse_references)
                    nodes = nodes.concat(flattenNode(inverseReference))

            return nodes
        }

        return new Promise((resolve, reject) => {
            if (refresh) {
                commit('ADD_REFRESH_KEY', key)
            }
            fetchNode(key, state.whitelist, 2).then(node => {
                for (let flatNode of flattenNode(node))
                    commit('SET_NODE', flatNode)
                resolve(node)
            }).catch(() => {})
        })
    }
}
<commit_msg>each message has its own keys<commit_after>import axios from 'axios'

let fetchNode = (key, whitelist, depth) => {
    return new Promise((resolve, reject) => {
        let params = {}
        if (depth) {
            params.depth = depth
        }
        if (whitelist.url) {
            params.whitelist_url = whitelist.url
        }
        if (whitelist.username) {
            params.whitelist_usernames = whitelist.username
        }

        axios.get(LIQUIO_URL + '/api/nodes/' + encodeURIComponent(key), { params: params }).then((response) => {
            resolve(response.data.data)
        }).catch(e => reject(e))
    })
}

let fetchSearch = (query, whitelist) => {
    return new Promise((resolve, reject) => {
        let params = {}
        if (whitelist.url) {
            params.whitelist_url = whitelist.url
        }
        if (whitelist.username) {
            params.whitelist_usernames = whitelist.username
        }

        axios.get(LIQUIO_URL + '/api/search/' + encodeURIComponent(query), { params: params }).then((response) => {
            resolve(response.data.data)
        }).catch(e => reject(e))
    })
}

export default {
    initialize ({ commit, dispatch, state }) {
        window.addEventListener('sign-anything-response', (e) => {
            let data = e.detail
            if (data.request_name === 'whitelist') {
                this.username = data.username
                this.whitelistUrl = data.url
                commit('SET_WHITELIST', {
                    username: data.username,
                    url: data.url
                })
                dispatch('updateNodes')
            } else if (data.request_name === 'sign') {
                 // TODO get refresh titles from store
                let currentTitle = state.currentTitle
                let currentReferenceTitle = state.currentReferenceTitle
                setTimeout(() => {
                    dispatch('loadNode', { key: state.currentPage })
                    if (currentTitle)
                        dispatch('loadNode', { key: currentTitle })
                    if (currentReferenceTitle)
                        dispatch('loadNode', { key: currentReferenceTitle })
                }, 500)
            }
        })
    },
    setCurrentPage ({ state, commit, dispatch }, payload) {
        commit('SET_CURRENT_PAGE', payload)
        dispatch('loadNode', { key: payload, refresh: true })
    },
    setCurrentTitle ({ state, commit, dispatch }, payload) {
        commit('SET_IS_VOTING_DISABLED', false)
        commit('SET_CURRENT_TITLE', payload)
        commit('ADD_TO_HISTORY')
        dispatch('loadNode', { key: payload, refresh: true })
    },
    setCurrentReferenceTitle ({ state, commit, dispatch }, payload) {
        commit('SET_CURRENT_REFERENCE_TITLE', payload)
        if (payload) {
            commit('ADD_TO_HISTORY')
            dispatch('loadNode', { key: payload, refresh: true })
        }
    },
    disableVoting ({ state, commit }) {
        commit('SET_IS_VOTING_DISABLED', true)
    },
    navigateBack ({ state, commit }) {
        if (state.historyIndex > 0) {
            commit('GO_TO_HISTORY_INDEX', state.historyIndex - 1)
        }
    },
    updateNodes ({ state, commit }) {
        let promises = state.refreshKeys.map(key => fetchNode(key, state.whitelist, 2))
        axios.all(promises).then(response => {
            for (let node of response) {
                commit('SET_NODE', node)
            }
        }).catch(() => {})
    },
    search ({ state }, query) {
        return fetchSearch(query, state.whitelist)
    },
    vote ({ commit }, { messages, messageKeys }) {
        let data = {
            name: 'sign',
            messages: messages.map(x => {
                return { ...x, keys: messageKeys }
            })
        }
        let event = new CustomEvent('sign-anything', { detail: data })
        window.dispatchEvent(event)
    },
    loadNode ({ state, commit }, { key, refresh }) {
        let transformReference = (reference) => {
            return {
                title: reference.title,
                referenceResults: reference.reference_results,
                byTitle: reference.referencing_title
            }
        }

        let flattenNode = (node) => {
            let nodes = []
            let existingNode = state.nodesByKey[node.title] || {}
            nodes.push({
                title: node.title,
                results: node.results,
                references: node.references === null ? existingNode.references : node.references.map(transformReference),
                inverseReferences: node.inverse_references === null ? existingNode.inverseReferences : node.inverse_references.map(transformReference)
            })

            if (node.references)
                for (let reference of node.references)
                    nodes = nodes.concat(flattenNode(reference))

            if (node.inverse_references)
                for (let inverseReference of node.inverse_references)
                    nodes = nodes.concat(flattenNode(inverseReference))

            return nodes
        }

        return new Promise((resolve, reject) => {
            if (refresh) {
                commit('ADD_REFRESH_KEY', key)
            }
            fetchNode(key, state.whitelist, 2).then(node => {
                for (let flatNode of flattenNode(node))
                    commit('SET_NODE', flatNode)
                resolve(node)
            }).catch(() => {})
        })
    }
}
<|endoftext|>


<commit_before>"use strict";

Cu.import("resource://gre/modules/Services.jsm", this);
Cu.import("resource://shield-recipe-client/lib/Heartbeat.jsm", this);
Cu.import("resource://shield-recipe-client/lib/SandboxManager.jsm", this);

/**
 * Assert an array is in non-descending order, and that every element is a number
 */
function assertOrdered(arr) {
  for (let i = 0; i < arr.length; i++) {
    Assert.equal(typeof arr[i], "number", `element ${i} is type "number"`);
  }
  for (let i = 0; i < arr.length - 1; i++) {
    Assert.lessOrEqual(arr[i], arr[i + 1],
      `element ${i} is less than or equal to element ${i + 1}`);
  }
}

/* Close every notification in a target window and notification box */
function closeAllNotifications(targetWindow, notificationBox) {
  if (notificationBox.allNotifications.length === 0) {
    return Promise.resolve();
  }

  return new Promise(resolve => {
    const notificationSet = new Set(notificationBox.allNotifications);

    const observer = new targetWindow.MutationObserver(mutations => {
      for (const mutation of mutations) {
        for (let i = 0; i < mutation.removedNodes.length; i++) {
          const node = mutation.removedNodes.item(i);
          if (notificationSet.has(node)) {
            notificationSet.delete(node);
          }
        }
      }
      if (notificationSet.size === 0) {
        Assert.equal(notificationBox.allNotifications.length, 0, "No notifications left");
        observer.disconnect();
        resolve();
      }
    });

    observer.observe(notificationBox, {childList: true});

    for (const notification of notificationBox.allNotifications) {
      notification.close();
    }
  });
}

/* Check that the correct telemetry was sent */
function assertTelemetrySent(hb, eventNames) {
  return new Promise(resolve => {
    hb.eventEmitter.once("TelemetrySent", payload => {
      const events = [0];
      for (const name of eventNames) {
        Assert.equal(typeof payload[name], "number", `payload field ${name} is a number`);
        events.push(payload[name]);
      }
      events.push(Date.now());

      assertOrdered(events);
      resolve();
    });
  });
}

const sandboxManager = new SandboxManager();
sandboxManager.addHold("test running");

// Several of the behaviors of heartbeat prompt are mutually exclusive, so checks are broken up
// into three batches.

/* Batch #1 - General UI, Stars, and telemetry data */
add_task(async function() {
  const targetWindow = Services.wm.getMostRecentWindow("navigator:browser");
  const notificationBox = targetWindow.document.querySelector("#high-priority-global-notificationbox");

  const preCount = notificationBox.childElementCount;
  const hb = new Heartbeat(targetWindow, sandboxManager, {
    testing: true,
    flowId: "test",
    message: "test",
    engagementButtonLabel: undefined,
    learnMoreMessage: "Learn More",
    learnMoreUrl: "https://example.org/learnmore",
  });

  // Check UI
  const learnMoreEl = hb.notice.querySelector(".text-link");
  const messageEl = targetWindow.document.getAnonymousElementByAttribute(hb.notice, "anonid", "messageText");
  Assert.equal(notificationBox.childElementCount, preCount + 1, "Correct number of notifications open");
  Assert.equal(hb.notice.querySelectorAll(".star-x").length, 5, "Correct number of stars");
  Assert.equal(hb.notice.querySelectorAll(".notification-button").length, 0, "Engagement button not shown");
  Assert.equal(learnMoreEl.href, "https://example.org/learnmore", "Learn more url correct");
  Assert.equal(learnMoreEl.value, "Learn More", "Learn more label correct");
  Assert.equal(messageEl.textContent, "test", "Message is correct");

  // Check that when clicking the learn more link, a tab opens with the right URL
  const tabOpenPromise = BrowserTestUtils.waitForNewTab(targetWindow.gBrowser);
  learnMoreEl.click();
  const tab = await tabOpenPromise;
  const tabUrl = await BrowserTestUtils.browserLoaded(
    tab.linkedBrowser, true, url => url && url !== "about:blank");

  Assert.equal(tabUrl, "https://example.org/learnmore", "Learn more link opened the right url");

  const telemetrySentPromise = assertTelemetrySent(hb, ["offeredTS", "learnMoreTS", "closedTS"]);
  // Close notification to trigger telemetry to be sent
  await closeAllNotifications(targetWindow, notificationBox);
  await telemetrySentPromise;
  await BrowserTestUtils.removeTab(tab);
});

// Batch #2 - Engagement buttons
add_task(async function() {
  const targetWindow = Services.wm.getMostRecentWindow("navigator:browser");
  const notificationBox = targetWindow.document.querySelector("#high-priority-global-notificationbox");
  const hb = new Heartbeat(targetWindow, sandboxManager, {
    testing: true,
    flowId: "test",
    message: "test",
    engagementButtonLabel: "Click me!",
    postAnswerUrl: "https://example.org/postAnswer",
    learnMoreMessage: "Learn More",
    learnMoreUrl: "https://example.org/learnMore",
  });
  const engagementButton = hb.notice.querySelector(".notification-button");

  Assert.equal(hb.notice.querySelectorAll(".star-x").length, 0, "Stars not shown");
  Assert.ok(engagementButton, "Engagement button added");
  Assert.equal(engagementButton.label, "Click me!", "Engagement button has correct label");

  const engagementEl = hb.notice.querySelector(".notification-button");
  const tabOpenPromise = BrowserTestUtils.waitForNewTab(targetWindow.gBrowser);
  engagementEl.click();
  const tab = await tabOpenPromise;
  const tabUrl = await BrowserTestUtils.browserLoaded(
        tab.linkedBrowser, true, url => url && url !== "about:blank");
  // the postAnswer url gets query parameters appended onto the end, so use Assert.startsWith instead of Assert.equal
  Assert.ok(tabUrl.startsWith("https://example.org/postAnswer"), "Engagement button opened the right url");

  const telemetrySentPromise = assertTelemetrySent(hb, ["offeredTS", "engagedTS", "closedTS"]);
  // Close notification to trigger telemetry to be sent
  await closeAllNotifications(targetWindow, notificationBox);
  await telemetrySentPromise;
  await BrowserTestUtils.removeTab(tab);
});

// Batch 3 - Closing the window while heartbeat is open
add_task(async function() {
  const targetWindow = await BrowserTestUtils.openNewBrowserWindow();

  const hb = new Heartbeat(targetWindow, sandboxManager, {
    testing: true,
    flowId: "test",
    message: "test",
  });

  const telemetrySentPromise = assertTelemetrySent(hb, ["offeredTS", "windowClosedTS"]);
  // triggers sending ping to normandy
  await BrowserTestUtils.closeWindow(targetWindow);
  await telemetrySentPromise;
});

// Cleanup
add_task(async function() {
  // Make sure the sandbox is clean.
  sandboxManager.removeHold("test running");
  await sandboxManager.isNuked()
    .then(() => ok(true, "sandbox is nuked"))
    .catch(e => ok(false, "sandbox is nuked", e));
});
<commit_msg>Bug 1416153 - Part 0: Fix tests that uses BrowserTestUtils.waitForNewTab to perform the registration of the next event handler instantly inside the new tab event handler. r=Gijs<commit_after>"use strict";

Cu.import("resource://gre/modules/Services.jsm", this);
Cu.import("resource://shield-recipe-client/lib/Heartbeat.jsm", this);
Cu.import("resource://shield-recipe-client/lib/SandboxManager.jsm", this);

/**
 * Assert an array is in non-descending order, and that every element is a number
 */
function assertOrdered(arr) {
  for (let i = 0; i < arr.length; i++) {
    Assert.equal(typeof arr[i], "number", `element ${i} is type "number"`);
  }
  for (let i = 0; i < arr.length - 1; i++) {
    Assert.lessOrEqual(arr[i], arr[i + 1],
      `element ${i} is less than or equal to element ${i + 1}`);
  }
}

/* Close every notification in a target window and notification box */
function closeAllNotifications(targetWindow, notificationBox) {
  if (notificationBox.allNotifications.length === 0) {
    return Promise.resolve();
  }

  return new Promise(resolve => {
    const notificationSet = new Set(notificationBox.allNotifications);

    const observer = new targetWindow.MutationObserver(mutations => {
      for (const mutation of mutations) {
        for (let i = 0; i < mutation.removedNodes.length; i++) {
          const node = mutation.removedNodes.item(i);
          if (notificationSet.has(node)) {
            notificationSet.delete(node);
          }
        }
      }
      if (notificationSet.size === 0) {
        Assert.equal(notificationBox.allNotifications.length, 0, "No notifications left");
        observer.disconnect();
        resolve();
      }
    });

    observer.observe(notificationBox, {childList: true});

    for (const notification of notificationBox.allNotifications) {
      notification.close();
    }
  });
}

/* Check that the correct telemetry was sent */
function assertTelemetrySent(hb, eventNames) {
  return new Promise(resolve => {
    hb.eventEmitter.once("TelemetrySent", payload => {
      const events = [0];
      for (const name of eventNames) {
        Assert.equal(typeof payload[name], "number", `payload field ${name} is a number`);
        events.push(payload[name]);
      }
      events.push(Date.now());

      assertOrdered(events);
      resolve();
    });
  });
}

const sandboxManager = new SandboxManager();
sandboxManager.addHold("test running");

// Several of the behaviors of heartbeat prompt are mutually exclusive, so checks are broken up
// into three batches.

/* Batch #1 - General UI, Stars, and telemetry data */
add_task(async function() {
  const targetWindow = Services.wm.getMostRecentWindow("navigator:browser");
  const notificationBox = targetWindow.document.querySelector("#high-priority-global-notificationbox");

  const preCount = notificationBox.childElementCount;
  const hb = new Heartbeat(targetWindow, sandboxManager, {
    testing: true,
    flowId: "test",
    message: "test",
    engagementButtonLabel: undefined,
    learnMoreMessage: "Learn More",
    learnMoreUrl: "https://example.org/learnmore",
  });

  // Check UI
  const learnMoreEl = hb.notice.querySelector(".text-link");
  const messageEl = targetWindow.document.getAnonymousElementByAttribute(hb.notice, "anonid", "messageText");
  Assert.equal(notificationBox.childElementCount, preCount + 1, "Correct number of notifications open");
  Assert.equal(hb.notice.querySelectorAll(".star-x").length, 5, "Correct number of stars");
  Assert.equal(hb.notice.querySelectorAll(".notification-button").length, 0, "Engagement button not shown");
  Assert.equal(learnMoreEl.href, "https://example.org/learnmore", "Learn more url correct");
  Assert.equal(learnMoreEl.value, "Learn More", "Learn more label correct");
  Assert.equal(messageEl.textContent, "test", "Message is correct");

  // Check that when clicking the learn more link, a tab opens with the right URL
  let loadedPromise;
  const tabOpenPromise = new Promise(resolve => {
    gBrowser.tabContainer.addEventListener("TabOpen", event => {
      let tab = event.target;
      loadedPromise = BrowserTestUtils.browserLoaded(
        tab.linkedBrowser, true, url => url && url !== "about:blank");
      resolve(tab);
    }, { once: true });
  });
  learnMoreEl.click();
  const tab = await tabOpenPromise;
  const tabUrl = await loadedPromise;

  Assert.equal(tabUrl, "https://example.org/learnmore", "Learn more link opened the right url");

  const telemetrySentPromise = assertTelemetrySent(hb, ["offeredTS", "learnMoreTS", "closedTS"]);
  // Close notification to trigger telemetry to be sent
  await closeAllNotifications(targetWindow, notificationBox);
  await telemetrySentPromise;
  await BrowserTestUtils.removeTab(tab);
});

// Batch #2 - Engagement buttons
add_task(async function() {
  const targetWindow = Services.wm.getMostRecentWindow("navigator:browser");
  const notificationBox = targetWindow.document.querySelector("#high-priority-global-notificationbox");
  const hb = new Heartbeat(targetWindow, sandboxManager, {
    testing: true,
    flowId: "test",
    message: "test",
    engagementButtonLabel: "Click me!",
    postAnswerUrl: "https://example.org/postAnswer",
    learnMoreMessage: "Learn More",
    learnMoreUrl: "https://example.org/learnMore",
  });
  const engagementButton = hb.notice.querySelector(".notification-button");

  Assert.equal(hb.notice.querySelectorAll(".star-x").length, 0, "Stars not shown");
  Assert.ok(engagementButton, "Engagement button added");
  Assert.equal(engagementButton.label, "Click me!", "Engagement button has correct label");

  const engagementEl = hb.notice.querySelector(".notification-button");
  let loadedPromise;
  const tabOpenPromise = new Promise(resolve => {
    gBrowser.tabContainer.addEventListener("TabOpen", event => {
      let tab = event.target;
      loadedPromise = BrowserTestUtils.browserLoaded(
        tab.linkedBrowser, true, url => url && url !== "about:blank");
      resolve(tab);
    }, { once: true });
  });
  engagementEl.click();
  const tab = await tabOpenPromise;
  const tabUrl = await loadedPromise;
  // the postAnswer url gets query parameters appended onto the end, so use Assert.startsWith instead of Assert.equal
  Assert.ok(tabUrl.startsWith("https://example.org/postAnswer"), "Engagement button opened the right url");

  const telemetrySentPromise = assertTelemetrySent(hb, ["offeredTS", "engagedTS", "closedTS"]);
  // Close notification to trigger telemetry to be sent
  await closeAllNotifications(targetWindow, notificationBox);
  await telemetrySentPromise;
  await BrowserTestUtils.removeTab(tab);
});

// Batch 3 - Closing the window while heartbeat is open
add_task(async function() {
  const targetWindow = await BrowserTestUtils.openNewBrowserWindow();

  const hb = new Heartbeat(targetWindow, sandboxManager, {
    testing: true,
    flowId: "test",
    message: "test",
  });

  const telemetrySentPromise = assertTelemetrySent(hb, ["offeredTS", "windowClosedTS"]);
  // triggers sending ping to normandy
  await BrowserTestUtils.closeWindow(targetWindow);
  await telemetrySentPromise;
});

// Cleanup
add_task(async function() {
  // Make sure the sandbox is clean.
  sandboxManager.removeHold("test running");
  await sandboxManager.isNuked()
    .then(() => ok(true, "sandbox is nuked"))
    .catch(e => ok(false, "sandbox is nuked", e));
});
<|endoftext|>


<commit_before>'use strict';

const assert = require('assertthat');
const proxyquire = require('proxyquire');

let consulOptions;
const initialize = proxyquire('../lib/initialize', {
  consul (options) {
    consulOptions = options;

    return {};
  }
});

suite('initialize', () => {
  setup(() => {
    consulOptions = null;
  });

  test('is a function.', async () => {
    assert.that(initialize).is.ofType('function');
  });

  test('throws an error if Consul\'s url is missing.', async () => {
    await assert.that(async () => {
      await initialize({});
    }).is.throwingAsync('Consul url is missing.');
  });

  test('calls consul with the given options.', async () => {
    const context = {};

    await initialize.call(context, { consulUrl: 'http://foo:1234' });

    assert.that(consulOptions).is.equalTo({
      defaults: {
        token: ''
      },
      host: 'foo',
      promisify: true,
      port: 1234,
      secure: true
    });
  });
});
<commit_msg>No secure connection in test.<commit_after>'use strict';

const assert = require('assertthat');
const proxyquire = require('proxyquire');

let consulOptions;
const initialize = proxyquire('../lib/initialize', {
  consul (options) {
    consulOptions = options;

    return {};
  }
});

suite('initialize', () => {
  setup(() => {
    consulOptions = null;
  });

  test('is a function.', async () => {
    assert.that(initialize).is.ofType('function');
  });

  test('throws an error if Consul\'s url is missing.', async () => {
    await assert.that(async () => {
      await initialize({});
    }).is.throwingAsync('Consul url is missing.');
  });

  test('calls consul with the given options.', async () => {
    const context = {};

    await initialize.call(context, { consulUrl: 'http://foo:1234' });

    assert.that(consulOptions).is.equalTo({
      defaults: {
        token: ''
      },
      host: 'foo',
      promisify: true,
      port: 1234
    });
  });
});
<|endoftext|>


<commit_before>var sinon = require('sinon');
var chai = require('chai');
var expect = chai.expect;
var app = require('../app');

describe('Expected events', function () {
  var postContext, postEvent = {};
  var fail_spy, succeed_spy;

  before(function() {
    postContext = {
      fail: function(msg) {
        throw new Error(msg);
      },
      succeed: function(msg) {}
    };
  });

  beforeEach(function() {
    fail_spy = sinon.spy(postContext, 'fail');
    succeed_spy = sinon.spy(postContext, 'succeed');
  })

  afterEach(function () {
    delete postEvent.method;
    fail_spy.restore();
    succeed_spy.restore();
   });

  it('should fail when a POST request occurs', function () {
    // Prepare
    postEvent.method = "POST";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw();
  });

  it('should fail when a PUT request occurs', function () {
    // Prepare
    postEvent.method = "PUT";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw();
  });

  it('should fail when a HEAD request occurs', function () {
    // Prepare
    postEvent.method = "HEAD";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw();
  });

  it('should fail when a PATCH request occurs', function () {
    // Prepare
    postEvent.method = "PATCH";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw();
  });

  it('should fail when a DELETE request occurs', function () {
    // Prepare
    postEvent.method = "DELETE";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw();
  });

  it('should fail when a OPTIONS request occurs', function () {
    // Prepare
    postEvent.method = "OPTIONS";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw();
  });

  it('should fail when "event.method" is not a HTTP verb', function () {
    // Prepare
    postEvent.method = "NOTAVERB";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw();
  });

  it('should fail when "event.size" is undefined', function () {
    // Prepare
    postEvent.method = "GET";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw();
  });

});<commit_msg>exceptions msg<commit_after>var sinon = require('sinon');
var chai = require('chai');
var expect = chai.expect;
var app = require('../app');

describe('Expected events', function () {
  var postContext, postEvent = {};
  var fail_spy, succeed_spy;

  before(function() {
    postContext = {
      fail: function(msg) {
        throw new Error(msg);
      },
      succeed: function(msg) {}
    };
  });

  beforeEach(function() {
    fail_spy = sinon.spy(postContext, 'fail');
    succeed_spy = sinon.spy(postContext, 'succeed');
  })

  afterEach(function () {
    delete postEvent.method;
    fail_spy.restore();
    succeed_spy.restore();
   });

  it('should fail when a POST request occurs', function () {
    // Prepare
    postEvent.method = "POST";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw('Unsuported method');
  });

  it('should fail when a PUT request occurs', function () {
    // Prepare
    postEvent.method = "PUT";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw('Unsuported method');
  });

  it('should fail when a HEAD request occurs', function () {
    // Prepare
    postEvent.method = "HEAD";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw('Unsuported method');
  });

  it('should fail when a PATCH request occurs', function () {
    // Prepare
    postEvent.method = "PATCH";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw('Unsuported method');
  });

  it('should fail when a DELETE request occurs', function () {
    // Prepare
    postEvent.method = "DELETE";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw('Unsuported method');
  });

  it('should fail when a OPTIONS request occurs', function () {
    // Prepare
    postEvent.method = "OPTIONS";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw('Unsuported method');
  });

  it('should fail when "event.method" is not a HTTP verb', function () {
    // Prepare
    postEvent.method = "NOTAVERB";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw('Unsuported method');
  });

  it('should fail when "event.size" is undefined', function () {
    // Prepare
    postEvent.method = "GET";
    // Call & Assert
    expect(function () {
      app.handler(postEvent, postContext);
    }).to.throw('Missing parameter: size');
  });

});<|endoftext|>


<commit_before>'use strict';
var BaseEvent = require('broker').events.ApplicationEvent;
var logger = require('hoist-logger');
var util = require('util');
var BBPromise = require('bluebird');
var Model = require('hoist-model');
var Session = Model.Session;
var AppUser = Model.AppUser;
var Organisation = Model.Organisation;
var Application = Model.Application;
var path = require('path');
var _ = require('lodash');
var kueProxy = require('../kue_proxy');
var moment = require('moment');

function ApplicationEvent(properties) {
  BaseEvent.call(this, properties);
  _.bindAll(this);
}

util.inherits(ApplicationEvent, BaseEvent);

ApplicationEvent.QueueName = 'application_event';
ApplicationEvent.prototype.getModuleDescription = function (moduleName, application) {
  return BBPromise.try(function () {
    var module = null;
    var settings = application.settings[this.environment];
    if (settings) {
      module = _.find(settings.modules, function (moduleDesc) {
        return moduleDesc.name === moduleName;
      });
    }
    return module;
  }, [], this);
};
ApplicationEvent.prototype.getContext = function (application) {
  var context = {};
  var pipeline = [];
  context.applicationId = this.applicationId;
  context.environment = this.environment;
  if (this.sessionId) {
    pipeline.push(Session.findOneAsync({
        _id: this.sessionId
      })
      .then(function (session) {
        if (session) {
          context.sessionId = session._id;
          if (session.appUser) {
            return AppUser.findOneAsync({
              _id: session.appUser
            }).then(function (appUser) {
              if (appUser) {
                context.user = appUser.toObject();
              }
            });
          }
        }
      }));
  }

  context.application = application.toObject();

  return BBPromise.all(pipeline).then(function () {
    return context;
  });
};
ApplicationEvent.prototype.getEventDescription = function (application) {
  var environment = this.environment || 'live';
  var settings = application.settings[environment];
  return settings.on[this.eventName];
};
ApplicationEvent.prototype.registerJobComplete = function (id) {
  if (this.timeouts[id]) {
    this.decrementJob(id);
    require('kue').Job.get(id, function (err, job) {
      if (err) {
        return;
      }
      job.remove(function (err) {
        if (err) {
          throw err;
        }
        logger.info(util.format('removed completed job #%d', job.id));
      });
    });
  }
};
ApplicationEvent.prototype.registerJobFailed = function (id) {
  console.log('job failed', arguments);
  if (this.timeouts[id]) {
    this.decrementJob(id);
    require('kue').Job.log(id, function (err, logs) {
      console.log(logs);
    });
  }
};
ApplicationEvent.prototype.decrementJob = function (id) {
  clearTimeout(this.timeouts[id]);
  this.executionCount--;
  if (this.executionCount < 1) {
    clearInterval(this.pingInterval);
    kueProxy.get().removeListener('job failed', this.registerJobFailed);
    kueProxy.get().removeListener('job complete', this.registerJobComplete);
    this.emit('done');
  }
};
ApplicationEvent.prototype.process = function (callback) {
  var log = new Model.ExecutionLogEvent({
    application: this.applicationId,
    environment: this.environment,
    moduleName: this.eventName,
    message: 'event ' + this.eventName + ' started processing'
  });
  log.saveAsync();
  return Application.findOneAsync({
      _id: this.applicationId
    })
    .bind(this)
    .then(function (application) {
      return Organisation.findOneAsync({
        _id: application.organisation
      }).bind(this).then(function (org) {
        var eventDescription = this.getEventDescription(application);
        if (!eventDescription) {
          this.emit('done');
          return;
        }
        var modules = eventDescription.modules;
        if (!modules || modules.length < 1) {
          this.emit('done');
          return;
        }
        this.timeouts = {};
        this.pingInterval = setInterval(_.bind(function () {
          logger.debug('emitting ping');
          this.emit('ping');
        }, this), 30000);
        this.executionCount = modules.length;
        kueProxy.get().on('job failed', this.registerJobFailed);
        kueProxy.get().on('job complete', this.registerJobComplete);
        return BBPromise.all(_.map(modules, _.bind(function (moduleName) {
            return this.getModuleDescription(moduleName, application);
          }, this)))
          .bind(this)
          .then(function (moduleDescriptions) {
            var lastDeployTimestamp = moment(application.lastDeploy[this.environment]);
            var applicationDeployFolder = path.join(org.gitFolder, application.gitRepo, lastDeployTimestamp.format('X'));
            return BBPromise.all(_.map(moduleDescriptions, _.bind(function (moduleDescription) {
              return this.getContext(application)
                .bind(this)
                .then(function (context) {
                  var log = new Model.ExecutionLogEvent({
                    application: this.applicationId,
                    environment: this.environment,
                    moduleName: moduleDescription.name,
                    message: 'module ' + moduleDescription.name + ' queued'
                  });
                  log.saveAsync();
                  var jobData = {
                    application: context.application,
                    user: context.user,
                    environment: context.environment,
                    event: this.toJSON(),
                    applicationPath: applicationDeployFolder,
                    modulePath: moduleDescription.src,
                    moduleName: moduleDescription.name,
                    module: moduleDescription,
                    title: 'running module ' + moduleDescription.name
                  };
                  var job = kueProxy.get().create('RunModule', jobData)
                    .save(_.bind(function (err) {
                      if (err) {
                        logger.alert(err);
                        logger.error(err, 'unable to save execution job');
                      }
                      //execution should be done in two mins
                      this.timeouts[job.id] = setTimeout(_.bind(function () {
                        var delayedError = new Error('RunModule job seems to be stuck on queue');
                        logger.alert(delayedError, this.applicationId, {
                          jobId: job.id,
                          event: this.toJSON()
                        });
                        logger.error(delayedError);
                      }, this), 120000);
                    }, this));

                });
            }, this)));

          });

      });
    }).then(function () {
      var log = new Model.ExecutionLogEvent({
        application: this.applicationId,
        environment: this.environment,
        moduleName: this.eventName,
        message: 'event ' + this.eventName + ' processed'
      });
      log.saveAsync();
    }).nodeify(callback);
};
module.exports = ApplicationEvent;
<commit_msg>remove listeners for job status<commit_after>'use strict';
var BaseEvent = require('broker').events.ApplicationEvent;
var logger = require('hoist-logger');
var util = require('util');
var BBPromise = require('bluebird');
var Model = require('hoist-model');
var Session = Model.Session;
var AppUser = Model.AppUser;
var Organisation = Model.Organisation;
var Application = Model.Application;
var path = require('path');
var _ = require('lodash');
var kueProxy = require('../kue_proxy');
var moment = require('moment');

function ApplicationEvent(properties) {
  BaseEvent.call(this, properties);
  _.bindAll(this);
}

util.inherits(ApplicationEvent, BaseEvent);

ApplicationEvent.QueueName = 'application_event';
ApplicationEvent.prototype.getModuleDescription = function (moduleName, application) {
  return BBPromise.try(function () {
    var module = null;
    var settings = application.settings[this.environment];
    if (settings) {
      module = _.find(settings.modules, function (moduleDesc) {
        return moduleDesc.name === moduleName;
      });
    }
    return module;
  }, [], this);
};
ApplicationEvent.prototype.getContext = function (application) {
  var context = {};
  var pipeline = [];
  context.applicationId = this.applicationId;
  context.environment = this.environment;
  if (this.sessionId) {
    pipeline.push(Session.findOneAsync({
        _id: this.sessionId
      })
      .then(function (session) {
        if (session) {
          context.sessionId = session._id;
          if (session.appUser) {
            return AppUser.findOneAsync({
              _id: session.appUser
            }).then(function (appUser) {
              if (appUser) {
                context.user = appUser.toObject();
              }
            });
          }
        }
      }));
  }

  context.application = application.toObject();

  return BBPromise.all(pipeline).then(function () {
    return context;
  });
};
ApplicationEvent.prototype.getEventDescription = function (application) {
  var environment = this.environment || 'live';
  var settings = application.settings[environment];
  return settings.on[this.eventName];
};
ApplicationEvent.prototype.process = function (callback) {
  var log = new Model.ExecutionLogEvent({
    application: this.applicationId,
    environment: this.environment,
    moduleName: this.eventName,
    message: 'event ' + this.eventName + ' started processing'
  });
  log.saveAsync();
  return Application.findOneAsync({
      _id: this.applicationId
    })
    .bind(this)
    .then(function (application) {
      return Organisation.findOneAsync({
        _id: application.organisation
      }).bind(this).then(function (org) {
        var eventDescription = this.getEventDescription(application);
        if (!eventDescription) {
          this.emit('done');
          return;
        }
        var modules = eventDescription.modules;
        if (!modules || modules.length < 1) {
          this.emit('done');
          return;
        }
        this.timeouts = {};
        this.pingInterval = setInterval(_.bind(function () {
          logger.debug('emitting ping');
          this.emit('ping');
        }, this), 30000);
        this.executionCount = modules.length;
        return BBPromise.all(_.map(modules, _.bind(function (moduleName) {
            return this.getModuleDescription(moduleName, application);
          }, this)))
          .bind(this)
          .then(function (moduleDescriptions) {
            var lastDeployTimestamp = moment(application.lastDeploy[this.environment]);
            var applicationDeployFolder = path.join(org.gitFolder, application.gitRepo, lastDeployTimestamp.format('X'));
            return BBPromise.all(_.map(moduleDescriptions, _.bind(function (moduleDescription) {
              return this.getContext(application)
                .bind(this)
                .then(function (context) {
                  var log = new Model.ExecutionLogEvent({
                    application: this.applicationId,
                    environment: this.environment,
                    moduleName: moduleDescription.name,
                    message: 'module ' + moduleDescription.name + ' queued'
                  });
                  log.saveAsync();
                  var jobData = {
                    application: context.application,
                    user: context.user,
                    environment: context.environment,
                    event: this.toJSON(),
                    applicationPath: applicationDeployFolder,
                    modulePath: moduleDescription.src,
                    moduleName: moduleDescription.name,
                    module: moduleDescription,
                    title: 'running module ' + moduleDescription.name
                  };
                  kueProxy.get().create('RunModule', jobData)
                    .save(_.bind(function (err) {
                      if (err) {
                        logger.alert(err);
                        logger.error(err, 'unable to save execution job');
                      }
                    }, this));

                });
            }, this)));

          });

      });
    }).then(function () {
      var log = new Model.ExecutionLogEvent({
        application: this.applicationId,
        environment: this.environment,
        moduleName: this.eventName,
        message: 'event ' + this.eventName + ' processed'
      });
      log.saveAsync();
      clearInterval(this.pingInterval);
      this.emit('done');
    }).nodeify(callback);
};
module.exports = ApplicationEvent;
<|endoftext|>


<commit_before>/**
 * mashape-tools
 * https://github.com/magdev/node-mashape-tools
 *
 * Copyright (c) 2014 Marco Grätsch
 * Licensed under the MIT license.
 */

'use strict';

var request = require('supertest'),
    express = require('express'),
    mashape = require('../'),

    DEBUG = true,

    allowedIps = [
        '107.23.255.128'
    ];

/**
 * Test ipFilter()
 */
describe('ipFilter()', function() {
    it('allow valid ip', function(done) {
        var app = express();

        app.use(mashape.ipFilter({
            iplist: ['127.0.0.1', '::ffff:127.0.0.1'],
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .expect(200, done);
    });

    it('deny invalid ip', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: ['10.2.2.2'],
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.1')
            .expect(403, done);
    });

    it('allow whitelisted ip', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG,
            whitelist: ['10.2.2.1']
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.1')
            .expect(200, done);
    });

    it('deny non-whitelisted ip', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG,
            whitelist: ['10.2.2.1']
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.2')
            .expect(403, done);
    });

    it('allow valid proxy (single ip)', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '107.23.255.128')
            .expect(200, done);
    });

    it('deny invalid proxy (single ip)', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.20')
            .expect(403, done);
    });

    it('allow valid proxy (multiple ips)', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.20,107.23.255.128')
            .expect(200, done);
    });

    it('deny invalid proxy (multiple ips)', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.20,10.2.2.22')
            .expect(403, done);
    });
});

<commit_msg>disabled debug<commit_after>/**
 * mashape-tools
 * https://github.com/magdev/node-mashape-tools
 *
 * Copyright (c) 2014 Marco Grätsch
 * Licensed under the MIT license.
 */

'use strict';

var request = require('supertest'),
    express = require('express'),
    mashape = require('../'),

    DEBUG = false,

    allowedIps = [
        '107.23.255.128'
    ];

/**
 * Test ipFilter()
 */
describe('ipFilter()', function() {
    it('allow valid ip', function(done) {
        var app = express();

        app.use(mashape.ipFilter({
            iplist: ['127.0.0.1', '::ffff:127.0.0.1'],
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .expect(200, done);
    });

    it('deny invalid ip', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: ['10.2.2.2'],
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.1')
            .expect(403, done);
    });

    it('allow whitelisted ip', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG,
            whitelist: ['10.2.2.1']
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.1')
            .expect(200, done);
    });

    it('deny non-whitelisted ip', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG,
            whitelist: ['10.2.2.1']
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.2')
            .expect(403, done);
    });

    it('allow valid proxy (single ip)', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '107.23.255.128')
            .expect(200, done);
    });

    it('deny invalid proxy (single ip)', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.20')
            .expect(403, done);
    });

    it('allow valid proxy (multiple ips)', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.20,107.23.255.128')
            .expect(200, done);
    });

    it('deny invalid proxy (multiple ips)', function(done) {
        var app = express();
        app.set('trust proxy', true);

        app.use(mashape.ipFilter({
            iplist: allowedIps,
            strict: false,
            log: false,
            debug: DEBUG
        }));

        app.get('/', function(req, res){
            res.send(200);
        });

        request(app)
            .get('/')
            .set('x-forwarded-for', '10.2.2.20,10.2.2.22')
            .expect(403, done);
    });
});

<|endoftext|>


<commit_before>import assert from 'assert';
import gpuMock from 'gpu-mock.js';
import Input from '../../src/layer/input';
import Multiply, { predict, compareFromX, compareFromY } from '../../src/layer/multiply';
import Random from '../../src/layer/random';

describe('Multiply Layer', () => {
  describe('.predict (forward propagation)', () => {
    it('can multiply a simple matrix', () => {
      const inputs1 = [
        [1, 2, 3],
        [4, 5, 6]
      ];
      const inputs2 = [
        [7, 8],
        [9, 10],
        [11, 12]
      ];
      const results = gpuMock(predict, {
        output: [2, 2],
        constants: {
          size: inputs2.length,
        }
      })(inputs1, inputs2);

      assert.deepEqual(results, [
        [58, 64],
        [139, 154]
      ]);
    });
  });
  describe('.compareFromX (back propagation)', () => {
    it('can multiply a simple matrix', () => {
      const m1 = [
        [3, 3],
        [3, 3]
      ];
      const m2 = [
        [3, 3],
        [3, 3]
      ];
      const deltas = [
        [3, 3],
        [3, 3]
      ];
      const result = gpuMock(compareFromX, {
        output: [2, 2],
        constants: {
          size: 2
        }
      })(deltas, m1, m2);
      assert.deepEqual(result, [[21, 21], [21, 21]]);
    });
    it('test with Garrett, to be named', () => {
      const deltas = [ [ -0.002445658488246267 ],
        [ 0.002188939203621896 ],
        [ 0.0026931707597484585 ] ];
      const inputDeltas = [ [ 0, 0 ],
        [ 0, 0 ],
        [ 0, 0 ] ];
      const inputWeight = [ [ 0 ], [ 0 ] ];
      const result = gpuMock(compareFromX, {
        output: [2, 3],
        constants: {
          size: 1
        }
      })(deltas, inputDeltas, inputWeight);
    });
  });
  describe('.compareFromY (back propagation)', () => {
    it('can multiply a simple matrix', () => {
      const m1 = [
        [3, 3],
        [3, 3]
      ];
      const m2 = [
        [3, 3],
        [3, 3]
      ];
      const deltas = [
        [3, 3],
        [3, 3]
      ];
      const result = gpuMock(compareFromY, {
        output: [2, 2],
        constants: {
          size: 2
        }
      })(deltas, m1, m2);
      assert.deepEqual(result, [[21, 21], [21, 21]]);
    });
  });
  describe('.validate', () => {
    context('when dimension are incompatible', () => {
      it('throws error', () => {
        assert.throws(() => {
          Multiply.prototype.validate.call({
            inputLayers: [
              { width: 1 },
              { height: 2 }
            ]
          });
        }, Error);
      });
    });
    context('when dimension are compatible', () => {
      it('validates', () => {
        Multiply.prototype.validate.call({
          inputLayers: [
            { width: 1 },
            { height: 1 }
          ]
        });
      });
    });
  });
  describe('instance', () => {
    describe('.predict method', () => {
      it('validates, multiplies, and sets .weights', () => {
        const inputLayer1 = {
          width: 3,
          height: 2,
          weights: [
            [1, 2, 3],
            [4, 5, 6]
          ]
        };
        const inputLayer2 = {
          width: 2,
          height: 3,
          weights: [
            [7, 8],
            [9, 10],
            [11, 12]
          ]
        };
        const multiplyLayer = new Multiply([inputLayer1, inputLayer2]);
        multiplyLayer.validate();
        multiplyLayer.setupKernels();
        multiplyLayer.predict();

        assert.deepEqual(multiplyLayer.weights, [
          [58, 64],
          [139, 154]
        ]);
      });
    });
    context('when used with Input layer', () => {
      it('is compatible', () => {
        const random = new Random({ height: 3, width: 2 });
        const input = new Input({ width: 2 });
        const multiply = new Multiply([random, input]);

        random.validate();
        random.setupKernels();

        input.validate();
        input.setupKernels();

        multiply.validate();
        multiply.setupKernels();

        input.predict([0, 1]);
        random.predict();
        multiply.predict();
        assert.equal(multiply.width, 1);
        assert.equal(multiply.height, 3);
      });
    });
  })
});<commit_msg>unit test simple example<commit_after>import assert from 'assert';
import gpuMock from 'gpu-mock.js';
import Input from '../../src/layer/input';
import Multiply, { predict, compareFromX, compareFromY } from '../../src/layer/multiply';
import Random from '../../src/layer/random';

describe('Multiply Layer', () => {
  describe('.predict (forward propagation)', () => {
    it('can multiply a simple matrix', () => {
      const inputs1 = [
        [1, 2, 3],
        [4, 5, 6]
      ];
      const inputs2 = [
        [7, 8],
        [9, 10],
        [11, 12]
      ];
      const results = gpuMock(predict, {
        output: [2, 2],
        constants: {
          size: inputs2.length,
        }
      })(inputs1, inputs2);

      assert.deepEqual(results, [
        [58, 64],
        [139, 154]
      ]);
    });
  });
  describe('.compareFromX (back propagation)', () => {
    it('can multiply a simple matrix', () => {
      const m1 = [
        [3, 3],
        [3, 3]
      ];
      const m2 = [
        [3, 3],
        [3, 3]
      ];
      const deltas = [
        [3, 3],
        [3, 3]
      ];
      const result = gpuMock(compareFromX, {
        output: [2, 2],
        constants: {
          size: 2
        }
      })(deltas, m1, m2);
      assert.deepEqual(result, [[21, 21], [21, 21]]);
    });
    it('can compare a simple matrix', () => {
      const deltas = [
        [ 1 ],
        [ 2 ],
        [ 3 ]
      ];
      const inputDeltas = [
        [ 1, 2 ],
        [ 3, 4 ],
        [ 5, 6 ]
      ];
      const inputWeights = [
        [ 1 ],
        [ 2 ]
      ];
      const result = gpuMock(compareFromX, {
        output: [2, 3],
        constants: {
          size: 1
        }
      })(deltas, inputDeltas, inputWeights);
      assert.deepEqual(result, [ [ 2, 4 ], [ 5, 8 ], [ 8, 12 ] ]);
    });
  });
  describe('.compareFromY (back propagation)', () => {
    it('can multiply a simple matrix', () => {
      const m1 = [
        [3, 3],
        [3, 3]
      ];
      const m2 = [
        [3, 3],
        [3, 3]
      ];
      const deltas = [
        [3, 3],
        [3, 3]
      ];
      const result = gpuMock(compareFromY, {
        output: [2, 2],
        constants: {
          size: 2
        }
      })(deltas, m1, m2);
      assert.deepEqual(result, [[21, 21], [21, 21]]);
    });
    it('can compare a simple matrix', () => {
      const deltas = [
        [ 1 ],
        [ 2 ],
        [ 3 ]
      ];
      const inputDeltas = [
        [ 1 ],
        [ 2 ]
      ];
      const inputWeights = [
        [ 1, 2 ],
        [ 3, 4 ],
        [ 5, 6 ]
      ];
      const result = gpuMock(compareFromY, {
        output: [1, 2],
        constants: {
          size: 3
        }
      })(deltas, inputDeltas, inputWeights);
      assert.deepEqual(result, [ [ 23], [ 30 ] ]);
    });
  });
  describe('.validate', () => {
    context('when dimension are incompatible', () => {
      it('throws error', () => {
        assert.throws(() => {
          Multiply.prototype.validate.call({
            inputLayers: [
              { width: 1 },
              { height: 2 }
            ]
          });
        }, Error);
      });
    });
    context('when dimension are compatible', () => {
      it('validates', () => {
        Multiply.prototype.validate.call({
          inputLayers: [
            { width: 1 },
            { height: 1 }
          ]
        });
      });
    });
  });
  describe('instance', () => {
    describe('.predict method', () => {
      it('validates, multiplies, and sets .weights', () => {
        const inputLayer1 = {
          width: 3,
          height: 2,
          weights: [
            [1, 2, 3],
            [4, 5, 6]
          ]
        };
        const inputLayer2 = {
          width: 2,
          height: 3,
          weights: [
            [7, 8],
            [9, 10],
            [11, 12]
          ]
        };
        const multiplyLayer = new Multiply([inputLayer1, inputLayer2]);
        multiplyLayer.validate();
        multiplyLayer.setupKernels();
        multiplyLayer.predict();

        assert.deepEqual(multiplyLayer.weights, [
          [58, 64],
          [139, 154]
        ]);
      });
    });
    context('when used with Input layer', () => {
      it('is compatible', () => {
        const random = new Random({ height: 3, width: 2 });
        const input = new Input({ width: 2 });
        const multiply = new Multiply([random, input]);

        random.validate();
        random.setupKernels();

        input.validate();
        input.setupKernels();

        multiply.validate();
        multiply.setupKernels();

        input.predict([0, 1]);
        random.predict();
        multiply.predict();
        assert.equal(multiply.width, 1);
        assert.equal(multiply.height, 3);
      });
    });
  })
});<|endoftext|>


<commit_before>'use strict';
// test deps
var vargscb = require('vargs-callback');
var config = require('config');
var client = require('../client.js').client;
var nav = require('../nav/navigation.js')(client, config);
var noop = function(){};

/**
 * Browser actions for authenticating with MICIS
 * @param client {webdriverioClient} The browser client to perform actions on
 */
module.exports = function(client) {

    var me = {};
    Object.defineProperty(me, 'loggedOn', {
        get: function () { return client._loggedOnMicis; },
        set: function (x) { client._loggedOnMicis = x; }
    });

    /**
     * log out of COINS
     * @param done {function} a mochajs function to call when login is successful
     */
    me.logout = function(done) {
        me.loggedOn = false;
        return client.url('https://' + config.origin + '/micis/logout.php');
    };

    /**
     * log onto COINS
     * @param url {string} The string to navigate to (should redirect to a CAS login page).
     * @param done {function} a mochajs function to call when login is successful
     * TODO update to be compatible with portals as well
     */
    me.logon = vargscb(function(url, done) {
        done = done || noop;
        //set default params
        url = url || 'https://' + config.origin + '/micis/index.php';

        client.url(url);
        if (!me.loggedOn) {
            client
                .waitFor('#coins-logon-widget-1')
                .setValue('#coins-logon-widget-1', config.auth.un)
                .setValue('#coins-logon-widget-0', config.auth.pw)
                .click('#coins-logon-widget button[type=submit]') //TODO: update to use data-selector instead
                .waitForPaginationComplete()
                .getCookie('MICIS', function(err, cookie) {
                    if (cookie) {
                        me.loggedOn = cookie;
                    } else {
                        throw new Error('micis cookie not found');
                    }
                });
        }
        return nav
            .disableNavigationAlert()
            .call(done);

    });

    return me;
};
<commit_msg>Update MICIS authentication process.<commit_after>'use strict';
// test deps
var vargscb = require('vargs-callback');
var config = require('config');
var client = require('../client.js').client;
var nav = require('../nav/navigation.js')(client, config);
var noop = function(){};

/**
 * Browser actions for authenticating with MICIS
 * @param client {webdriverioClient} The browser client to perform actions on
 */
module.exports = function(client) {

    var me = {};
    Object.defineProperty(me, 'loggedOn', {
        get: function () { return client._loggedOnMicis; },
        set: function (x) { client._loggedOnMicis = x; }
    });

    /**
     * log out of COINS
     * @param done {function} a mochajs function to call when login is successful
     */
    me.logout = function(done) {
        me.loggedOn = false;
        return client.url('https://' + config.origin + '/micis/logout.php');
    };

    /**
     * log onto COINS
     * @param url {string} The string to navigate to (should redirect to a CAS login page).
     * @param done {function} a mochajs function to call when login is successful
     * TODO update to be compatible with portals as well
     */
    me.logon = vargscb(function(url, done) {
        done = done || noop;
        //set default params
        url = url || 'https://' + config.origin + '/micis/index.php';

        client.url(url);
        if (!me.loggedOn) {
            client
                .waitFor('.coins-logon-widget-form')
                .setValue(
                    '.coins-logon-widget-form input[name=username]',
                    config.auth.un
                )
                .setValue(
                    '.coins-logon-widget-form input[name=password]',
                    config.auth.pw
                )
                .click('.coins-logon-widget-form button[type=submit]') //TODO: update to use data-selector instead
                .waitForPaginationComplete()
                .getCookie('MICIS', function(err, cookie) {
                    if (cookie) {
                        me.loggedOn = cookie;
                    } else {
                        throw new Error('micis cookie not found');
                    }
                });
        }
        return nav
            .disableNavigationAlert()
            .call(done);

    });

    return me;
};
<|endoftext|>