<commit_before>'use strict';

angular.module('asc.racing', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/racing', {
    templateUrl: 'racing/racing.html',
    conroller: 'RacingCtrl'
  });
}])

.controller('RacingCtrl', ['$scope', function($scope) {
    $scope.links = [
        { name: 'Schedule', templatePath: 'racing/articles/race-schedule.html' },
        { name: 'Results', templatePath: 'racing/articles/race-results.html' },
        { name: 'Camps', templatePath: 'racing/articles/race-camps.html' },
        { name: 'Sponsors', templatePath: 'racing/articles/race-sponsors.html' },
        { name: 'Gatekeeper Training', templatePath: 'racing/articles/race-gatekeeping.html' },
        { name: 'Waiver', templatePath: 'forms/Crescent_Racing_Liability_Waiver.pdf' }
    ];

    $scope.changeSelected = function (link) {
        $scope.selectedPath = link.templatePath;
        for (var i = 0; i < $scope.links.length; i++) {
            $scope.links[i].selected = false;
        }
        link.selected = true;
    };

    function onLoad() {
        $scope.changeSelected($scope.links[0]);
    }

    onLoad();
}])

.controller('RacingScheduleCtrl', ['$scope', function($scope) {
    $scope.schedule = [
        { date: 'December 19 - 20', place: 'Appalachian Mt, NC', time: '9:30 am'},
        { date: 'January 9 - 10', place: 'Sugar Mt, NC', time: '9:00 am'},
        { date: 'January 16 - 23', place: 'Crescent Ski Council Ski Week', time: ''},
        { date: 'January 30 - 31', place: 'Appalachian Mt, NC', time: '9:30 am'},
        { date: 'February 1', place: 'Cupp Run Challenge at Snowshoe, WV', time: ''},
        { date: 'February 6 - 7', place: 'Beech Mt, NC', time: '10:00 am'},
        { date: 'February 20 - 21', place: 'Sugar Mt, NC', time: '9:00 am'},
        { date: 'March TBA', place: 'Governor’s Cup Race at Timberline, WV', time: ''},
        { date: 'March TBA', place: 'Dick Trundy/Sugar Cup GS Sugar Mt', time: '9:00 am'},
        { date: 'March 4 - 6', place: 'Crescent Cup, SilverCreek, WV', time: '8:45 am'},
        { date: 'March TBA', place: 'Rich Mead', time: ''},
    ];
}])

.controller('RacingCampsCtrl', ['$scope', function($scope) {
    $scope.camps = [
        { date: 'December 5 - 12', place: 'Steamboat Race Camp', info: 'Sports Am.Tours: 800-876-8551'},
        { date: 'December', place: 'Killington Race Camp', info: '800-621-6867'},
        { date: 'December 6', place: 'CSC Development Training at Appalachian', info: '9:46 am - 3:00 pm'},
        { date: 'December 11 - 13', place: 'Sugar Mt. Race Camp', info: 'Kim Jöchl: 828-898-4521 x224'},
        { date: 'December', place: 'Timberline, WV  Ski School', info: '304-866-4801, Multiple sessions'}
    ];
}])

.controller('RacingSponsorsCtrl', ['$scope', function($scope) {
    $scope.sponsors = [
        { img: 'img/sponsors/aspen-snowmass-logo.png', link: '' },
        { img: 'img/sponsors/dynastar-logo.png', link: '' },
        { img: 'img/sponsors/jackson-hole-logo.gif', link: '' },
        { img: 'img/sponsors/bayou-logo.png', link: '' },
        { img: 'img/sponsors/copper-logo.png', link: '' },
        { img: 'img/sponsors/saucer-wax-logo.png', link: '' },
        { img: 'img/sponsors/alpine-ski-center-logo.png', link: '' },
        { img: 'img/sponsors/samuel-adams-logo.jpg', link: '' },
        { img: 'img/sponsors/canaan-valley-logo.png', link: '' },
        { img: 'img/sponsors/steamboat-logo.jpg', link: '' },
        { img: 'img/sponsors/wolfridge-resort-logo.png', link: '' },
        { img: 'img/sponsors/telluride-logo.png', link: '' },
        { img: 'img/sponsors/whitefish-logo.gif', link: '' },
        { img: 'img/sponsors/banana-boat-logo.png', link: '' },
        { img: 'img/sponsors/sports-america-logo.png', link: '' },
        { img: 'img/sponsors/steamboat-resorts-logo.png', link: '' },
        { img: 'img/sponsors/podium-wax-logo.gif', link: '' },
        { img: 'img/sponsors/leki-logo.png', link: '' },
        { img: 'img/sponsors/polarmax-logo.png', link: '' },
        { img: 'img/sponsors/snowmass-village-logo.jpg', link: '' },
        { img: 'img/sponsors/point6-logo.jpg', link: '' },
        { img: 'img/sponsors/descente-logo.png', link: '' },
        { img: 'img/sponsors/sportube-logo.jpg', link: '' },
        { img: 'img/sponsors/artech-logo.jpg', link: '' },
        { img: 'img/sponsors/ski-country-sports-logo.jpg', link: '' },
        { img: 'img/sponsors/snowshoe-logo.png', link: '' },
        { img: 'img/sponsors/peet-dryer-logo.png', link: '' },
        { img: 'img/sponsors/head-logo.png', link: '' },
        { img: 'img/sponsors/red-bull-logo.png', link: '' },
        { img: 'img/sponsors/cataloochee-logo.jpg', link: '' },
        { img: 'img/sponsors/skigroup-logo.png', link: '' },
        { img: 'img/sponsors/winter-park-logo.jpg', link: '' },
        { img: 'img/sponsors/taos-logo.png', link: '' },
        { img: 'img/sponsors/atomic-logo.png', link: '' },
        { img: 'img/sponsors/clif-bar-logo.png', link: '' },
        { img: 'img/sponsors/zardoz-logo.png', link: '' },
        { img: 'img/sponsors/ski-banff-logo.jpg', link: '' },
        { img: 'img/sponsors/spyder-logo.jpg', link: '' },
        { img: 'img/sponsors/holidaze-logo.jpg', link: '' }
    ];
}])
;<commit_msg>Added links for sponsors<commit_after>'use strict';

angular.module('asc.racing', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/racing', {
    templateUrl: 'racing/racing.html',
    conroller: 'RacingCtrl'
  });
}])

.controller('RacingCtrl', ['$scope', function($scope) {
    $scope.links = [
        { name: 'Schedule', templatePath: 'racing/articles/race-schedule.html' },
        { name: 'Results', templatePath: 'racing/articles/race-results.html' },
        { name: 'Camps', templatePath: 'racing/articles/race-camps.html' },
        { name: 'Sponsors', templatePath: 'racing/articles/race-sponsors.html' },
        { name: 'Gatekeeper Training', templatePath: 'racing/articles/race-gatekeeping.html' },
        { name: 'Waiver', templatePath: 'forms/Crescent_Racing_Liability_Waiver.pdf' }
    ];

    $scope.changeSelected = function (link) {
        $scope.selectedPath = link.templatePath;
        for (var i = 0; i < $scope.links.length; i++) {
            $scope.links[i].selected = false;
        }
        link.selected = true;
    };

    function onLoad() {
        $scope.changeSelected($scope.links[0]);
    }

    onLoad();
}])

.controller('RacingScheduleCtrl', ['$scope', function($scope) {
    $scope.schedule = [
        { date: 'December 19 - 20', place: 'Appalachian Mt, NC', time: '9:30 am'},
        { date: 'January 9 - 10', place: 'Sugar Mt, NC', time: '9:00 am'},
        { date: 'January 16 - 23', place: 'Crescent Ski Council Ski Week', time: ''},
        { date: 'January 30 - 31', place: 'Appalachian Mt, NC', time: '9:30 am'},
        { date: 'February 1', place: 'Cupp Run Challenge at Snowshoe, WV', time: ''},
        { date: 'February 6 - 7', place: 'Beech Mt, NC', time: '10:00 am'},
        { date: 'February 20 - 21', place: 'Sugar Mt, NC', time: '9:00 am'},
        { date: 'March TBA', place: 'Governor’s Cup Race at Timberline, WV', time: ''},
        { date: 'March TBA', place: 'Dick Trundy/Sugar Cup GS Sugar Mt', time: '9:00 am'},
        { date: 'March 4 - 6', place: 'Crescent Cup, SilverCreek, WV', time: '8:45 am'},
        { date: 'March TBA', place: 'Rich Mead', time: ''},
    ];
}])

.controller('RacingCampsCtrl', ['$scope', function($scope) {
    $scope.camps = [
        { date: 'December 5 - 12', place: 'Steamboat Race Camp', info: 'Sports Am.Tours: 800-876-8551'},
        { date: 'December', place: 'Killington Race Camp', info: '800-621-6867'},
        { date: 'December 6', place: 'CSC Development Training at Appalachian', info: '9:46 am - 3:00 pm'},
        { date: 'December 11 - 13', place: 'Sugar Mt. Race Camp', info: 'Kim Jöchl: 828-898-4521 x224'},
        { date: 'December', place: 'Timberline, WV  Ski School', info: '304-866-4801, Multiple sessions'}
    ];
}])

.controller('RacingSponsorsCtrl', ['$scope', function($scope) {
    $scope.sponsors = [
        { img: 'img/sponsors/aspen-snowmass-logo.png', link: 'https://www.aspensnowmass.com/' },
        { img: 'img/sponsors/dynastar-logo.png', link: 'http://www.dynastar.com/US/US/' },
        { img: 'img/sponsors/jackson-hole-logo.gif', link: 'http://www.jacksonhole.com/' },
        { img: 'img/sponsors/bayou-logo.png', link: 'http://bayousmokehouse.com/#about-us' },
        { img: 'img/sponsors/copper-logo.png', link: 'http://www.coppercolorado.com/winter/index.html' },
        { img: 'img/sponsors/saucer-wax-logo.png', link: 'https://www.saucerwax.net/' },
        { img: 'img/sponsors/alpine-ski-center-logo.png', link: 'https://www.alpineskicenter.com/' },
        { img: 'img/sponsors/samuel-adams-logo.jpg', link: 'https://www.samueladams.com/' },
        { img: 'img/sponsors/canaan-valley-logo.png', link: 'http://canaanresort.com/winter/' },
        { img: 'img/sponsors/steamboat-logo.jpg', link: 'http://www.steamboat.com/' },
        { img: 'img/sponsors/wolfridge-resort-logo.png', link: 'http://www.skiwolfridgenc.com/' },
        { img: 'img/sponsors/telluride-logo.png', link: 'http://www.tellurideskiresort.com/' },
        { img: 'img/sponsors/whitefish-logo.gif', link: 'http://skiwhitefish.com/' },
        { img: 'img/sponsors/banana-boat-logo.png', link: 'http://www.bananaboat.com/' },
        { img: 'img/sponsors/sports-america-logo.png', link: 'https://www.sportsamerica.com/' },
        { img: 'img/sponsors/steamboat-resorts-logo.png', link: 'http://www.steamboat.com/plan-your-trip/lodging/s/steamboat-resorts.aspx' },
        { img: 'img/sponsors/podium-wax-logo.gif', link: 'https://www.podiumwax.com/' },
        { img: 'img/sponsors/leki-logo.png', link: 'http://usa.leki.com/' },
        { img: 'img/sponsors/polarmax-logo.png', link: 'http://www.polarmax.com/' },
        { img: 'img/sponsors/snowmass-village-logo.jpg', link: 'http://www.tosv.com/' },
        { img: 'img/sponsors/point6-logo.jpg', link: 'http://point6.com/' },
        { img: 'img/sponsors/descente-logo.png', link: 'http://www.descente.com/' },
        { img: 'img/sponsors/sportube-logo.jpg', link: 'https://www.sportube.com/' },
        { img: 'img/sponsors/artech-logo.jpg', link: 'http://www.artechski.com/' },
        { img: 'img/sponsors/ski-country-sports-logo.jpg', link: 'https://www.skicountrysports.com/' },
        { img: 'img/sponsors/snowshoe-logo.png', link: 'http://www.snowshoemtn.com/' },
        { img: 'img/sponsors/peet-dryer-logo.png', link: 'http://www.peetdryer.com/' },
        { img: 'img/sponsors/head-logo.png', link: 'http://www.head.com/us/home/' },
        { img: 'img/sponsors/red-bull-logo.png', link: 'http://www.redbull.com/us/en' },
        { img: 'img/sponsors/cataloochee-logo.jpg', link: 'http://cataloochee.com/' },
        { img: 'img/sponsors/skigroup-logo.png', link: 'http://www.skigroup.net/' },
        { img: 'img/sponsors/winter-park-logo.jpg', link: 'http://www.winterparkresort.com/' },
        { img: 'img/sponsors/taos-logo.png', link: 'http://www.skitaos.org/' },
        { img: 'img/sponsors/atomic-logo.png', link: 'https://www.atomic.com/en-us' },
        { img: 'img/sponsors/clif-bar-logo.png', link: 'http://www.clifbar.com/' },
        { img: 'img/sponsors/zardoz-logo.png', link: 'http://www.zardoznotwax.com/' },
        { img: 'img/sponsors/ski-banff-logo.jpg', link: 'http://www.skibanff.com/' },
        { img: 'img/sponsors/spyder-logo.jpg', link: 'http://www.spyder.com/' },
        { img: 'img/sponsors/holidaze-logo.jpg', link: 'http://holidaze.com/' }
    ];
}])
;<|endoftext|>


<commit_before>app.repo("IdeaRepo", function IdeaRepo(WsApi, Idea, ServiceRepo, TableFactory) {

    var ideaRepo = this;

    ideaRepo.fetchById = function (ideaId) {
        var idea = new Idea();
        angular.extend(ideaRepo.mapping.instantiate, {
            'method': ideaId
        });
        idea.fetch();
        return idea;
    };

    ideaRepo.getPageSettings = function () {
        return table.getPageSettings();
    };

    ideaRepo.getTableParams = function () {
        return table.getTableParams();
    };

    ideaRepo.fetchPage = function (pageSettings) {
        angular.extend(ideaRepo.mapping.page, {
            'data': pageSettings ? pageSettings : table.getPageSettings()
        });
        return WsApi.fetch(ideaRepo.mapping.page);
    };

    ideaRepo.reject = function (idea) {
        angular.extend(ideaRepo.mapping.reject, {
            'data': idea
        });
        return WsApi.fetch(ideaRepo.mapping.reject);
    };

    ideaRepo.sendToHelpdesk = function (idea) {
        angular.extend(ideaRepo.mapping.sendToHelpdesk, {
            'data': idea
        });
        return WsApi.fetch(ideaRepo.mapping.sendToHelpdesk);
    };

    var table = TableFactory.buildTable({
        pageNumber: sessionStorage.getItem('ideas-page') ? sessionStorage.getItem('ideas-page') : 1,
        pageSize: sessionStorage.getItem('ideas-size') ? sessionStorage.getItem('ideas-size') : 10,
        filters: {},
        counts: [5, 10, 25, 50, 100],
        name: 'ideas',
        repo: ideaRepo
    });

    var updateIdea = function (idea) {
        var ideas = ideaRepo.getContents();
        for (var i in ideas) {
            if (ideas[i].id === idea.id) {
                angular.extend(ideas[i], idea);
                return;
            }
        }
    };

    WsApi.listen(ideaRepo.mapping.createListen).then(null, null, function (response) {
        ServiceRepo.addIdea(new Idea(angular.fromJson(response.body).payload.Idea));
        table.getTableParams().reload();
    });

    WsApi.listen(ideaRepo.mapping.updateListen).then(null, null, function (response) {
        var idea = new Idea(angular.fromJson(response.body).payload.Idea);
        ServiceRepo.updateIdea(idea);
        updateIdea(idea);
        table.getTableParams().reload();
    });

    WsApi.listen(ideaRepo.mapping.deleteListen).then(null, null, function (response) {
        ServiceRepo.removeIdeaById(angular.fromJson(response.body).payload.Long);
        table.getTableParams().reload();
    });

    return ideaRepo;

});<commit_msg>Issue 174: 401 when viewing service and a feature proposal for that service is edited in another browser<commit_after>app.repo("IdeaRepo", function IdeaRepo(WsApi, Idea, ServiceRepo, TableFactory, UserService) {

    var ideaRepo = this;

    ideaRepo.fetchById = function (ideaId) {
        var idea = new Idea();
        angular.extend(ideaRepo.mapping.instantiate, {
            'method': ideaId
        });
        idea.fetch();
        return idea;
    };

    ideaRepo.getPageSettings = function () {
        return table.getPageSettings();
    };

    ideaRepo.getTableParams = function () {
        return table.getTableParams();
    };

    ideaRepo.fetchPage = function (pageSettings) {
        angular.extend(ideaRepo.mapping.page, {
            'data': pageSettings ? pageSettings : table.getPageSettings()
        });
        return WsApi.fetch(ideaRepo.mapping.page);
    };

    ideaRepo.reject = function (idea) {
        angular.extend(ideaRepo.mapping.reject, {
            'data': idea
        });
        return WsApi.fetch(ideaRepo.mapping.reject);
    };

    ideaRepo.sendToHelpdesk = function (idea) {
        angular.extend(ideaRepo.mapping.sendToHelpdesk, {
            'data': idea
        });
        return WsApi.fetch(ideaRepo.mapping.sendToHelpdesk);
    };

    var table = TableFactory.buildTable({
        pageNumber: sessionStorage.getItem('ideas-page') ? sessionStorage.getItem('ideas-page') : 1,
        pageSize: sessionStorage.getItem('ideas-size') ? sessionStorage.getItem('ideas-size') : 10,
        filters: {},
        counts: [5, 10, 25, 50, 100],
        name: 'ideas',
        repo: ideaRepo
    });

    var updateIdea = function (idea) {
        var ideas = ideaRepo.getContents();
        for (var i in ideas) {
            if (ideas[i].id === idea.id) {
                angular.extend(ideas[i], idea);
                return;
            }
        }
    };

    var canAccess = function () {
        var user = UserService.getCurrentUser();
        var access = false;

        if (user.role === undefined || user.role === null || user.anonymous) {
            access = false;
        }
        else if (user.role === 'ROLE_ADMIN') {
            access = true;
        } else if (user.role === 'ROLE_SERVICE_ADMIN') {
            access = true;
        } else if (user.role === 'ROLE_SERVICE_MANAGER') {
            access = true;
        }

        return access;
    };

    UserService.userReady().then(function () {
        if (canAccess()) {

            WsApi.listen(ideaRepo.mapping.createListen).then(null, null, function (response) {
                ServiceRepo.addIdea(new Idea(angular.fromJson(response.body).payload.Idea));
                table.getTableParams().reload();
            });

            WsApi.listen(ideaRepo.mapping.updateListen).then(null, null, function (response) {
                var idea = new Idea(angular.fromJson(response.body).payload.Idea);
                ServiceRepo.updateIdea(idea);
                updateIdea(idea);
                table.getTableParams().reload();
            });

            WsApi.listen(ideaRepo.mapping.deleteListen).then(null, null, function (response) {
                ServiceRepo.removeIdeaById(angular.fromJson(response.body).payload.Long);
                table.getTableParams().reload();
            });
        }
    });

    return ideaRepo;

});
<|endoftext|>


<commit_before>var rels = require('zetta-rels');
var MediaType = require('api-media-type');
var querystring = require('querystring');
var Query = require('calypso').Query;
var rel = require('zetta-rels');

var RootResource = module.exports = function(server) {
  this.server = server;
};

RootResource.prototype.init = function(config) {
  config
    .path('/')
    .produces(MediaType.SIREN)
    .consumes(MediaType.FORM_URLENCODED)
    .get('/', this.list);
};

RootResource.prototype.shouldProxy = function(serverId) {
  return this.server.id !== serverId;
};

RootResource.prototype.proxy = function(env, next) {
  return this.server.httpServer.proxyToPeer(env, next);
};

RootResource.prototype.list = function(env, next) {
  var self = this;
  var params = env.route.query;
  if (params.ql) {
    var ql = params.ql;
    var server = params.server || this.server.id;

    if (server === '*') {
      this.server.peerRegistry.find(Query.of('peers'), function(err, peers) {
        if (err) {
          env.response.statusCode = 500;
          return next(env);
        }

        var href = '/servers/{{peerName}}';
        var qs ='?' + querystring.stringify({ql: params.ql});
        env.request.templateUrl = href + qs;

        var httpServer = self.server.httpServer;

        httpServer.proxyToPeers(peers, env, function(err, results, messageId) {
          var entities = results.map(function(obj) {
            if (obj.err) {
              return [];
            }

            var response = obj.res;
            var body = obj.body;

            var id = response.headers['zetta-message-id'];

            if (!messageId) {
              messageId = id;
            }

            var res = httpServer.clients[id];

            if (!res) {
              return [];
            }

            Object.keys(response.headers).forEach(function(header) {
              if (header !== 'zetta-message-id') {
                res.setHeader(header, response.headers[header]);
              }
            });

            res.statusCode = response.statusCode;

            if (body) {
              body = JSON.parse(body.toString());
              return body && body.entities ? body.entities : [];
            } else {
              return [];
            }
          }).reduce(function(prev, curr) {
            return prev.concat(curr);
          }, []);

          self.server.runtime.registry.find(params.ql, function(err, results) {
            var localEntities = (!!err || !results) ? [] : results.map(function(device){
              var deviceOnRuntime = self.server.runtime._jsDevices[device.id];
              if (deviceOnRuntime) {
                var model = deviceOnRuntime;
                var loader = {path: '/servers/' + encodeURI(self.server.id)}
                var server = self.server;
                var properties = model.properties();
                var entity = {
                  class: ['device', properties.type],
                  rel: [rel.device],
                  properties: properties,
                  links: [{ rel: ['self'], href: env.helpers.url.path(loader.path + '/devices/' + model.id) },
                          { title: server._name, rel: ['up', rel.server], href: env.helpers.url.path(loader.path) }]
                };
                return entity;
              }
            }).filter(function(entity) { return entity !== null });

            var res = httpServer.clients[messageId];
            var obj = {
              class: ['root', 'search-results'],
              properties: {
                server: '*',
                ql: params.ql
              },
              entities: localEntities.concat(entities),
              links: [
                { rel: ['self'], href: env.helpers.url.current() }
              ]
            }

            var queryTopic = querystring.stringify({topic: 'query/'+params.ql, since: new Date().getTime()});
            obj.links.push({ rel: [rel.query], href: env.helpers.url.path('/events').replace(/^http/, 'ws') + '?' + queryTopic });

            res.body = JSON.stringify(obj);
            delete httpServer.clients[messageId];
            next(env);
          });
        });
      });
    } else if (this.shouldProxy(server)) {
      this.server.peerRegistry.get(server, function(err, peer) {
        if(err) {
          env.response.statusCode = 500;
          return next(env);
        }

        var href = '/servers/' + encodeURI(peer.id);
        var qs ='?' + querystring.stringify({ql: params.ql});
        env.request.url = href + qs;
        self.proxy(env, next);
      });
    } else {
      this._queryDevices(env, next);
    }
  } else {
    this._renderRoot(env, next);
  }
};

RootResource.prototype._queryDevices = function(env, next) {
  var params = env.route.query;
  var self = this;

  if(!params.ql) {
    env.response.statusCode = 404;
    return next(env);
  } else {
    self.server.runtime.registry.find(params.ql, function(err, results) {
      if (err) {
        env.response.statusCode = 500;
        return next(env);
      }

      var devices = {};

      results.forEach(function(device){
        var deviceOnRuntime = self.server.runtime._jsDevices[device.id];
        if (deviceOnRuntime) {
          devices[device.id] = deviceOnRuntime;
        }
      });

      var context = {
        server: self.server,
        devices: devices,
        loader: {path: '/servers/' + encodeURI(self.server.id)},
        env: env,
        classes:['search-results'],
        query: params.ql
      };

      env.format.render('server', context);
      next(env);
    });
  }
};
//This is called when ql and server isn't supplied
RootResource.prototype._renderRoot = function(env, next) {
  env.response.body = {
    class: ['root'],
    links: [
      {
        rel: [rels.self],
        href: env.helpers.url.current()
      },
      {
        title: this.server._name,
        rel: [rels.server],
        href: env.helpers.url.path('/servers/' + encodeURI(this.server.id) )
      }
    ],
    actions: [
      {
        name: 'query-devices',
        method: 'GET',
        href: env.helpers.url.current(),
        type: 'application/x-www-form-urlencoded',
        fields: [
          {
            name: 'server',
            type: 'text'
          },
          {
            name: 'ql',
            type: 'text'
          }
        ]
      }
    ]
  };

  var peerQuery = Query.of('peers').ql('where direction = "acceptor" and status = "connected"');
  this.server.peerRegistry.find(peerQuery, function(err, results) {
    if (results) {
      results.forEach(function(peer) {
        env.response.body.links.push({
          title: peer.id,
          rel: [rels.peer],
          href: env.helpers.url.path('/servers/' + encodeURI(peer.id))
        });
      });
    }

    env.response.body.links.push({
      rel: [rels.peerManagement],
      href: env.helpers.url.path('/peer-management')
    });

    next(env);
  });

};
<commit_msg>added link rel for server to all connected peers.<commit_after>var rels = require('zetta-rels');
var MediaType = require('api-media-type');
var querystring = require('querystring');
var Query = require('calypso').Query;
var rel = require('zetta-rels');

var RootResource = module.exports = function(server) {
  this.server = server;
};

RootResource.prototype.init = function(config) {
  config
    .path('/')
    .produces(MediaType.SIREN)
    .consumes(MediaType.FORM_URLENCODED)
    .get('/', this.list);
};

RootResource.prototype.shouldProxy = function(serverId) {
  return this.server.id !== serverId;
};

RootResource.prototype.proxy = function(env, next) {
  return this.server.httpServer.proxyToPeer(env, next);
};

RootResource.prototype.list = function(env, next) {
  var self = this;
  var params = env.route.query;
  if (params.ql) {
    var ql = params.ql;
    var server = params.server || this.server.id;

    if (server === '*') {
      this.server.peerRegistry.find(Query.of('peers'), function(err, peers) {
        if (err) {
          env.response.statusCode = 500;
          return next(env);
        }

        var href = '/servers/{{peerName}}';
        var qs ='?' + querystring.stringify({ql: params.ql});
        env.request.templateUrl = href + qs;

        var httpServer = self.server.httpServer;

        httpServer.proxyToPeers(peers, env, function(err, results, messageId) {
          var entities = results.map(function(obj) {
            if (obj.err) {
              return [];
            }

            var response = obj.res;
            var body = obj.body;

            var id = response.headers['zetta-message-id'];

            if (!messageId) {
              messageId = id;
            }

            var res = httpServer.clients[id];

            if (!res) {
              return [];
            }

            Object.keys(response.headers).forEach(function(header) {
              if (header !== 'zetta-message-id') {
                res.setHeader(header, response.headers[header]);
              }
            });

            res.statusCode = response.statusCode;

            if (body) {
              body = JSON.parse(body.toString());
              return body && body.entities ? body.entities : [];
            } else {
              return [];
            }
          }).reduce(function(prev, curr) {
            return prev.concat(curr);
          }, []);

          self.server.runtime.registry.find(params.ql, function(err, results) {
            var localEntities = (!!err || !results) ? [] : results.map(function(device){
              var deviceOnRuntime = self.server.runtime._jsDevices[device.id];
              if (deviceOnRuntime) {
                var model = deviceOnRuntime;
                var loader = {path: '/servers/' + encodeURI(self.server.id)}
                var server = self.server;
                var properties = model.properties();
                var entity = {
                  class: ['device', properties.type],
                  rel: [rel.device],
                  properties: properties,
                  links: [{ rel: ['self'], href: env.helpers.url.path(loader.path + '/devices/' + model.id) },
                          { title: server._name, rel: ['up', rel.server], href: env.helpers.url.path(loader.path) }]
                };
                return entity;
              }
            }).filter(function(entity) { return entity !== null });

            var res = httpServer.clients[messageId];
            var obj = {
              class: ['root', 'search-results'],
              properties: {
                server: '*',
                ql: params.ql
              },
              entities: localEntities.concat(entities),
              links: [
                { rel: ['self'], href: env.helpers.url.current() }
              ]
            }

            var queryTopic = querystring.stringify({topic: 'query/'+params.ql, since: new Date().getTime()});
            obj.links.push({ rel: [rel.query], href: env.helpers.url.path('/events').replace(/^http/, 'ws') + '?' + queryTopic });

            res.body = JSON.stringify(obj);
            delete httpServer.clients[messageId];
            next(env);
          });
        });
      });
    } else if (this.shouldProxy(server)) {
      this.server.peerRegistry.get(server, function(err, peer) {
        if(err) {
          env.response.statusCode = 500;
          return next(env);
        }

        var href = '/servers/' + encodeURI(peer.id);
        var qs ='?' + querystring.stringify({ql: params.ql});
        env.request.url = href + qs;
        self.proxy(env, next);
      });
    } else {
      this._queryDevices(env, next);
    }
  } else {
    this._renderRoot(env, next);
  }
};

RootResource.prototype._queryDevices = function(env, next) {
  var params = env.route.query;
  var self = this;

  if(!params.ql) {
    env.response.statusCode = 404;
    return next(env);
  } else {
    self.server.runtime.registry.find(params.ql, function(err, results) {
      if (err) {
        env.response.statusCode = 500;
        return next(env);
      }

      var devices = {};

      results.forEach(function(device){
        var deviceOnRuntime = self.server.runtime._jsDevices[device.id];
        if (deviceOnRuntime) {
          devices[device.id] = deviceOnRuntime;
        }
      });

      var context = {
        server: self.server,
        devices: devices,
        loader: {path: '/servers/' + encodeURI(self.server.id)},
        env: env,
        classes:['search-results'],
        query: params.ql
      };

      env.format.render('server', context);
      next(env);
    });
  }
};
//This is called when ql and server isn't supplied
RootResource.prototype._renderRoot = function(env, next) {
  env.response.body = {
    class: ['root'],
    links: [
      {
        rel: [rels.self],
        href: env.helpers.url.current()
      },
      {
        title: this.server._name,
        rel: [rels.server],
        href: env.helpers.url.path('/servers/' + encodeURI(this.server.id) )
      }
    ],
    actions: [
      {
        name: 'query-devices',
        method: 'GET',
        href: env.helpers.url.current(),
        type: 'application/x-www-form-urlencoded',
        fields: [
          {
            name: 'server',
            type: 'text'
          },
          {
            name: 'ql',
            type: 'text'
          }
        ]
      }
    ]
  };

  var peerQuery = Query.of('peers').ql('where direction = "acceptor" and status = "connected"');
  this.server.peerRegistry.find(peerQuery, function(err, results) {
    if (results) {
      results.forEach(function(peer) {
        env.response.body.links.push({
          title: peer.id,
          rel: [rels.peer, rels.server],
          href: env.helpers.url.path('/servers/' + encodeURI(peer.id))
        });
      });
    }

    env.response.body.links.push({
      rel: [rels.peerManagement],
      href: env.helpers.url.path('/peer-management')
    });

    next(env);
  });

};
<|endoftext|>


<commit_before>'use strict';

const _sinon = require('sinon');
const _chai = require('chai');
_chai.use(require('sinon-chai'));
_chai.use(require('chai-as-promised'));
const expect = _chai.expect;

const _clone = require('clone');
const LambdaContext = require('./lambda-context');
const ConfigMockBuilder = require('../config-mock-builder');
const LoggerMockBuilder = require('../logger-mock-builder');

/**
 * Class that provides a wrapper around lambda handlers, and exposes utility
 * methods that can be used during testing.
 */
class LambdaWrapper {
    /**
     * @param {Object} handler Reference to the lambda handler.
     * @param {Object} [event={}] The event object to pass to the handler
     *        when invoked.
     * @param {Object} [contextProps = {
     *            functionName: "__lambda_function_name__",
     *            alias: null
     *        } ] Additional context info that will be used to generate the
     *        lambda context. If omitted, a default object will be generated.
     *        If the functionName property begins with "arn:", it will be
     *        used as specified. Otherwise, the name will be appended to an
     *        autogenerated arn prefix.
     * @param {Object} [configProps={}] Optional config parameters passed to the
     *        lambda as a part of the mock config object
     */
    constructor(handler, event, contextProps, configProps) {
        if(typeof handler !== 'function') {
            throw new Error('Invalid handler specified (arg #1)');
        }
        if(!event || typeof event !== 'object') {
            event = {};
        }
        if(!contextProps || contextProps instanceof Array ||
            typeof contextProps !== 'object') {
            contextProps = {};
        }
        if(!configProps || configProps instanceof Array ||
            typeof configProps !== 'object') {
            configProps = {};
        }
        this._handler = handler;
        this._event = _clone(event);
        this._contextProps = _clone(contextProps);
        this._configProps = _clone(configProps);

        const wrapper = {
            _callback: function() {}
        }
        this._invokePromise = new Promise((resolve, reject) => {
            this._callback = _sinon.stub(wrapper, '_callback', (err, data) => {
                if(err) {
                    reject(err);
                    return;
                }
                resolve(data);
            });
        });
    }

    /**
     * Initializes the extension object.
     *
     * @private
     *
     * @param {Object} [props={}] Optional config props object that can be used
     *        to set properties for the lambda.
     * @param {String} env Environment string to use for the extension object.
     */
    _initExt(configProps, env) {
        const logger = (new LoggerMockBuilder()).mock;
        const config = (new ConfigMockBuilder(configProps)).mock;

        // These methods are injected by the lambda wrapper

        // Special method to log extractable metrics
        logger.metrics = _sinon.spy();

        // Special method to log duration of specific events
        logger.timespan = _sinon.spy();

        return {
            logger,
            config,
            env
        };
    }

    /**
     * Appends the specified properties to the existing input (event) object.
     * Any existing properties in the input with the same name will be
     * overwritten.
     *
     * @param {Object} properties A map of input properties be added to the
     *        existing event object.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    addEventProperties(properties) {
        if(!properties || (properties instanceof Array) || typeof properties !== 'object') {
            throw new Error('Invalid event properties specified (arg #1)');
        }

        this._event = Object.assign(this._event, _clone(properties));
        return this;
    }

    /**
     * Adds a config property to the wrapper. These properties will be
     * accessible to the lambda via the ext.config object. Any existing
     * properties with the same name will be overwritten.
     *
     * @param {Object} properties A map of input properties be added to the
     *        existing input object.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    addConfigProperties(properties) {
        if(!properties || (properties instanceof Array) || typeof properties !== 'object') {
            throw new Error('Invalid config properties specified (arg #1)');
        }

        this._configProps = Object.assign(this._configProps, _clone(properties));
        return this;
    }

    /**
     * Adds a context property to the wrapper. Any existing properties with the
     * same name will be overwritten.
     *
     * @param {Object} properties A map of input properties be added to the
     *        existing input object.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    addContextProperties(properties) {
        if(!properties || (properties instanceof Array) || typeof properties !== 'object') {
            throw new Error('Invalid context properties specified (arg #1)');
        }

        this._contextProps = Object.assign(this._contextProps, _clone(properties));
        return this;
    }

    /**
     * Sets the name of the lambda function. This value is passed to the
     * handler via the lambda context argument. Not setting the function name
     * will result in a default function name being used, which should be ok
     * for most use cases.
     *
     * @param {String} functionName The name of the function to assign. If a
     *        valid ARN string not passed, a default ARN will be generated
     *        using the function name. Note that if an ARN is used, the alias
     *        must not be specified with the function name.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    setFunctionName(functionName) {
        if(typeof functionName !== 'string' || functionName.length <= 0) {
            throw new Error('Invalid function name specified (arg #1)');
        }

        this._contextProps.functionName = functionName;
        return this;
    }

    /**
     * Sets the environment for the lambda function. The lambda handler derives
     * environment values from the function alias, and this property will be
     * set as the function alias so that handler derives the environment
     * string correctly.
     *
     * @param {String} env The environment string that will be used as the
     *        function alias when the lambda function is invoked.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    setEnvironment(env) {
        if(typeof env !== 'string' || env.length <= 0) {
            throw new Error('Invalid environment string specified (arg #1)');
        }

        this._contextProps.alias = env;
        return this;
    }

    /**
     * Returns a reference to the callback spy that is passed to the lambda
     * function.
     */
    get callback() {
        return this._callback;
    }

    /**
     * Returns a reference to the raw context properties that will be used to
     * generate the lambda function context.
     */
    get contextProps() {
        return this._contextProps;
    }

    /**
     * Returns a reference to the raw config properties that will be passed to
     * the lambda function as the config object at invocation time.
     */
    get configProps() {
        return this._configProps;
    }

    /**
     * Returns a reference to the event object that is passed to the lambda
     * function.
     */
    get event() {
        return this._event;
    }

    /**
     * Returns a reference to the lambda function handler.
     */
    get handler() {
        return this._handler;
    }

    /**
     * Invokes the lamdba function with predefined event, context and callback
     * values.
     */
    invoke() {
        const context = new LambdaContext(this.contextProps);
        const ext = this._initExt(this.configProps, context.env);
        this.handler(this.event, context.context, this.callback, ext);
        return this._invokePromise;
    }

    /**
     * Invokes the lamdba function, and evaluates the callback function for
     * invocation with specific errors.
     *
     * @param {Object} error Reference to the expected error when the lambda
     *        function is invoked. This could be a string, a RegExp object, or
     *        an error type.
     * @param {Object} [message] An optional error message which will only be
     *        considered if the previous argument is an error type.
     *
     * @param {Object} errorArg The error argument received from the callback.
     */
    testError(error, message) {
        this.callback.reset();
        this.invoke().catch((ex) => {
            //Handle the rejection without errors. Assertion checks
            //will work regardless.
        });

        expect(this.callback).to.have.been.calledOnce;

        const errorMessage = (typeof error === 'function')? message:error;
        const errorType = (typeof error === 'function')? error:Error;

        const errorArg = this.callback.args[0][0];
        expect(errorArg).to.be.an.instanceof(errorType);

        if(errorMessage instanceof RegExp) {
            expect(errorArg.message).to.match(errorMessage);
        } else {
            expect(errorArg.message).to.equal(errorMessage);
        }

        return errorArg;
    }

    /**
     * Invokes the lamdba function, and pauses for some async action to take
     * place. Once the async action is completed, evaluates the callback
     * function for invocation with specific errors.
     *
     * @param {Object} error Reference to the expected error when the lambda
     *        function is invoked.
     * @param {Object} [message] An optional error message which will only be
     *        considered if the previous argument is an error type.
     *
     * @param {Object} errorArg The error argument received from the callback.
     */
    *testErrorAsync(error, message) {
        this.callback.reset();

        yield this.invoke().catch((ex) => {
            //Handle the rejection without errors. Assertion checks
            //will work regardless.
        });

        expect(this.callback).to.have.been.calledOnce;

        const errorMessage = (typeof error === 'function')? message:error;
        const errorType = (typeof error === 'function')? error:Error;

        const errorArg = this.callback.args[0][0];
        expect(errorArg).to.be.an.instanceof(errorType);

        if(errorMessage instanceof RegExp) {
            expect(errorArg.message).to.match(errorMessage);
        } else {
            expect(errorArg.message).to.equal(errorMessage);
        }

        return errorArg;
    }

    /**
     * Invokes the lamdba function, and evaluates the callback function for
     * successful invocation.
     *
     * @param {Object} error Reference to the expected error when the lambda
     *        function is invoked.
     *
     * @return {Object} The data returned by the callback.
     */
    testSuccess() {
        this.callback.reset();
        this.invoke();

        expect(this.callback).to.have.been.calledOnce;

        const errorArg = this.callback.args[0][0];
        expect(errorArg).to.be.null;

        const data = this.callback.args[0][1];
        return data;
    }

    /**
     * Invokes the lamdba function, and pauses for some async action to take
     * place. Once the async action is completed, evaluates the callback
     * function for successful invocation.
     *
     * @param {Object} error Reference to the expected error when the lambda
     *        function is invoked.
     *
     * @return {Object} The data returned by the callback.
     */
    *testSuccessAsync() {
        this.callback.reset();

        yield this.invoke();

        expect(this.callback).to.have.been.calledOnce;

        const errorArg = this.callback.args[0][0];
        expect(errorArg).to.be.null;

        const data = this.callback.args[0][1];
        return data;
    }
}

module.exports = LambdaWrapper;
<commit_msg>Ensure that the actual promise is returned on async error tests<commit_after>'use strict';

const _sinon = require('sinon');
const _chai = require('chai');
_chai.use(require('sinon-chai'));
_chai.use(require('chai-as-promised'));
const expect = _chai.expect;

const _clone = require('clone');
const LambdaContext = require('./lambda-context');
const ConfigMockBuilder = require('../config-mock-builder');
const LoggerMockBuilder = require('../logger-mock-builder');

/**
 * Class that provides a wrapper around lambda handlers, and exposes utility
 * methods that can be used during testing.
 */
class LambdaWrapper {
    /**
     * @param {Object} handler Reference to the lambda handler.
     * @param {Object} [event={}] The event object to pass to the handler
     *        when invoked.
     * @param {Object} [contextProps = {
     *            functionName: "__lambda_function_name__",
     *            alias: null
     *        } ] Additional context info that will be used to generate the
     *        lambda context. If omitted, a default object will be generated.
     *        If the functionName property begins with "arn:", it will be
     *        used as specified. Otherwise, the name will be appended to an
     *        autogenerated arn prefix.
     * @param {Object} [configProps={}] Optional config parameters passed to the
     *        lambda as a part of the mock config object
     */
    constructor(handler, event, contextProps, configProps) {
        if(typeof handler !== 'function') {
            throw new Error('Invalid handler specified (arg #1)');
        }
        if(!event || typeof event !== 'object') {
            event = {};
        }
        if(!contextProps || contextProps instanceof Array ||
            typeof contextProps !== 'object') {
            contextProps = {};
        }
        if(!configProps || configProps instanceof Array ||
            typeof configProps !== 'object') {
            configProps = {};
        }
        this._handler = handler;
        this._event = _clone(event);
        this._contextProps = _clone(contextProps);
        this._configProps = _clone(configProps);

        const wrapper = {
            _callback: function() {}
        }
        this._invokePromise = new Promise((resolve, reject) => {
            this._callback = _sinon.stub(wrapper, '_callback', (err, data) => {
                if(err) {
                    reject(err);
                    return;
                }
                resolve(data);
            });
        });
    }

    /**
     * Initializes the extension object.
     *
     * @private
     *
     * @param {Object} [props={}] Optional config props object that can be used
     *        to set properties for the lambda.
     * @param {String} env Environment string to use for the extension object.
     */
    _initExt(configProps, env) {
        const logger = (new LoggerMockBuilder()).mock;
        const config = (new ConfigMockBuilder(configProps)).mock;

        // These methods are injected by the lambda wrapper

        // Special method to log extractable metrics
        logger.metrics = _sinon.spy();

        // Special method to log duration of specific events
        logger.timespan = _sinon.spy();

        return {
            logger,
            config,
            env
        };
    }

    /**
     * Appends the specified properties to the existing input (event) object.
     * Any existing properties in the input with the same name will be
     * overwritten.
     *
     * @param {Object} properties A map of input properties be added to the
     *        existing event object.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    addEventProperties(properties) {
        if(!properties || (properties instanceof Array) || typeof properties !== 'object') {
            throw new Error('Invalid event properties specified (arg #1)');
        }

        this._event = Object.assign(this._event, _clone(properties));
        return this;
    }

    /**
     * Adds a config property to the wrapper. These properties will be
     * accessible to the lambda via the ext.config object. Any existing
     * properties with the same name will be overwritten.
     *
     * @param {Object} properties A map of input properties be added to the
     *        existing input object.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    addConfigProperties(properties) {
        if(!properties || (properties instanceof Array) || typeof properties !== 'object') {
            throw new Error('Invalid config properties specified (arg #1)');
        }

        this._configProps = Object.assign(this._configProps, _clone(properties));
        return this;
    }

    /**
     * Adds a context property to the wrapper. Any existing properties with the
     * same name will be overwritten.
     *
     * @param {Object} properties A map of input properties be added to the
     *        existing input object.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    addContextProperties(properties) {
        if(!properties || (properties instanceof Array) || typeof properties !== 'object') {
            throw new Error('Invalid context properties specified (arg #1)');
        }

        this._contextProps = Object.assign(this._contextProps, _clone(properties));
        return this;
    }

    /**
     * Sets the name of the lambda function. This value is passed to the
     * handler via the lambda context argument. Not setting the function name
     * will result in a default function name being used, which should be ok
     * for most use cases.
     *
     * @param {String} functionName The name of the function to assign. If a
     *        valid ARN string not passed, a default ARN will be generated
     *        using the function name. Note that if an ARN is used, the alias
     *        must not be specified with the function name.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    setFunctionName(functionName) {
        if(typeof functionName !== 'string' || functionName.length <= 0) {
            throw new Error('Invalid function name specified (arg #1)');
        }

        this._contextProps.functionName = functionName;
        return this;
    }

    /**
     * Sets the environment for the lambda function. The lambda handler derives
     * environment values from the function alias, and this property will be
     * set as the function alias so that handler derives the environment
     * string correctly.
     *
     * @param {String} env The environment string that will be used as the
     *        function alias when the lambda function is invoked.
     *
     * @return {Object} A reference to the wrapper object - can be used to chain
     *         calls.
     */
    setEnvironment(env) {
        if(typeof env !== 'string' || env.length <= 0) {
            throw new Error('Invalid environment string specified (arg #1)');
        }

        this._contextProps.alias = env;
        return this;
    }

    /**
     * Returns a reference to the callback spy that is passed to the lambda
     * function.
     */
    get callback() {
        return this._callback;
    }

    /**
     * Returns a reference to the raw context properties that will be used to
     * generate the lambda function context.
     */
    get contextProps() {
        return this._contextProps;
    }

    /**
     * Returns a reference to the raw config properties that will be passed to
     * the lambda function as the config object at invocation time.
     */
    get configProps() {
        return this._configProps;
    }

    /**
     * Returns a reference to the event object that is passed to the lambda
     * function.
     */
    get event() {
        return this._event;
    }

    /**
     * Returns a reference to the lambda function handler.
     */
    get handler() {
        return this._handler;
    }

    /**
     * Invokes the lamdba function with predefined event, context and callback
     * values.
     */
    invoke() {
        const context = new LambdaContext(this.contextProps);
        const ext = this._initExt(this.configProps, context.env);
        this.handler(this.event, context.context, this.callback, ext);
        return this._invokePromise;
    }

    /**
     * Invokes the lamdba function, and evaluates the callback function for
     * invocation with specific errors.
     *
     * @param {Object} error Reference to the expected error when the lambda
     *        function is invoked. This could be a string, a RegExp object, or
     *        an error type.
     * @param {Object} [message] An optional error message which will only be
     *        considered if the previous argument is an error type.
     *
     * @param {Object} errorArg The error argument received from the callback.
     */
    testError(error, message) {
        this.callback.reset();
        this.invoke().catch((ex) => {
            //Handle the rejection without errors. Assertion checks
            //will work regardless.
        });

        expect(this.callback).to.have.been.calledOnce;

        const errorMessage = (typeof error === 'function')? message:error;
        const errorType = (typeof error === 'function')? error:Error;

        const errorArg = this.callback.args[0][0];
        expect(errorArg).to.be.an.instanceof(errorType);

        if(errorMessage instanceof RegExp) {
            expect(errorArg.message).to.match(errorMessage);
        } else {
            expect(errorArg.message).to.equal(errorMessage);
        }

        return errorArg;
    }

    /**
     * Invokes the lamdba function, and pauses for some async action to take
     * place. Once the async action is completed, evaluates the callback
     * function for invocation with specific errors.
     *
     * @param {Object} error Reference to the expected error when the lambda
     *        function is invoked.
     * @param {Object} [message] An optional error message which will only be
     *        considered if the previous argument is an error type.
     *
     * @param {Object} errorArg The error argument received from the callback.
     */
    *testErrorAsync(error, message) {
        this.callback.reset();

        const promise = this.invoke();
        promise.catch((ex) => {
            //Handle the rejection without errors. Assertion checks
            //will work regardless.
        });
        yield promise;

        expect(this.callback).to.have.been.calledOnce;

        const errorMessage = (typeof error === 'function')? message:error;
        const errorType = (typeof error === 'function')? error:Error;

        const errorArg = this.callback.args[0][0];
        expect(errorArg).to.be.an.instanceof(errorType);

        if(errorMessage instanceof RegExp) {
            expect(errorArg.message).to.match(errorMessage);
        } else {
            expect(errorArg.message).to.equal(errorMessage);
        }

        return errorArg;
    }

    /**
     * Invokes the lamdba function, and evaluates the callback function for
     * successful invocation.
     *
     * @param {Object} error Reference to the expected error when the lambda
     *        function is invoked.
     *
     * @return {Object} The data returned by the callback.
     */
    testSuccess() {
        this.callback.reset();
        this.invoke();

        expect(this.callback).to.have.been.calledOnce;

        const errorArg = this.callback.args[0][0];
        expect(errorArg).to.be.null;

        const data = this.callback.args[0][1];
        return data;
    }

    /**
     * Invokes the lamdba function, and pauses for some async action to take
     * place. Once the async action is completed, evaluates the callback
     * function for successful invocation.
     *
     * @param {Object} error Reference to the expected error when the lambda
     *        function is invoked.
     *
     * @return {Object} The data returned by the callback.
     */
    *testSuccessAsync() {
        this.callback.reset();

        yield this.invoke();

        expect(this.callback).to.have.been.calledOnce;

        const errorArg = this.callback.args[0][0];
        expect(errorArg).to.be.null;

        const data = this.callback.args[0][1];
        return data;
    }
}

module.exports = LambdaWrapper;
<|endoftext|>


<commit_before>/* jshint node: true */
/*
  Credit goes to ember-cli/babel-plugin-feature-flags: https://github.com/ember-cli/babel-plugin-feature-flags
 */
'use strict';
module.exports = function(options) {
  options = options || {};
  options.features = options.features || {};
  options.import = options.import || {};
  options.import.name = options.import.name || 'default';

  if (typeof options.import.module !== 'string') {
    throw new Error("options.import.module must be the name of a module, e.g. 'my-app/features'");
  }

  Object.keys(options.features).forEach(function(feature) {
    var value = options.features[feature];

    if (typeof value === 'string') {
      if (value === 'enabled') {
        options.features[feature] = true;
      } else if (value === 'disabled') {
        options.features[feature] = false;
      } else if (value === 'dynamic') {
        options.features[feature] = null;
      } else {
        throw new Error("An unknown feature state '" + value + "' was detected for '" + feature + "'. Valid values are 'enabled', 'disabled' and 'dynamic'");
      }
    }
  });

  return function(babel) {
    function acceptFeatureCall(callExpression, ifStatement, invert, file) {
      var callee = callExpression.get('callee');

      if (callee.referencesImport(options.import.module, options.import.name)) {
        var feature;
        var value;
        if (callExpression.node.arguments[0].elements) {
          feature = callExpression.node.arguments[0].elements[0].value;
        } else {
          feature = callExpression.node.arguments[0].value;
          file.log.warn("You should use featureFlag(['feature']) instead of featureFlag('feature') or the function won't run at runtime");
        }
        if (feature in options.features) {
          value = options.features[feature];
        } else {
          value = false;
          file.log.warn("An unknown feature '" + feature + "'' was encountered and removed");
        }
        if (value === !invert) {
          var consequent = ifStatement.node.consequent;
          ifStatement.replaceWithMultiple(consequent.body);
        } else if (value === !!invert) {
          var alternate = ifStatement.node.alternate;
          if (alternate) {
            ifStatement.replaceWithMultiple(alternate.body);
          } else {
            ifStatement.dangerouslyRemove();
          }
        }
      }
    }

    return new babel.Transformer('babel-plugin-feature-flags', {
      IfStatement: function(node, parent, scope, file) {
        var test = this.get('test');
        if (test.isUnaryExpression() && test.node.operator === '!') {
          var argument = test.get('argument');
          if (argument.isCallExpression()) {
            acceptFeatureCall(argument, this, true, file);
          }
        } else if (test.isCallExpression()) {
          acceptFeatureCall(test, this, false, file);
        }
      }
    });
  };
};
<commit_msg>Update babel-defeatureify.js<commit_after>/* jshint node: true */
/*
  Credit goes to ember-cli/babel-plugin-feature-flags: https://github.com/ember-cli/babel-plugin-feature-flags
 */
'use strict';
module.exports = function(options) {
  options = options || {};
  options.features = options.features || {};
  options.import = options.import || {};
  options.import.name = options.import.name || 'default';

  if (typeof options.import.module !== 'string') {
    throw new Error("options.import.module must be the name of a module, e.g. 'my-app/features'");
  }

  Object.keys(options.features).forEach(function(feature) {
    var value = options.features[feature];

    if (typeof value === 'string') {
      if (value === 'enabled') {
        options.features[feature] = true;
      } else if (value === 'disabled') {
        options.features[feature] = false;
      } else if (value === 'dynamic') {
        options.features[feature] = null;
      } else {
        throw new Error("An unknown feature state '" + value + "' was detected for '" + feature + "'. Valid values are 'enabled', 'disabled' and 'dynamic'");
      }
    }
  });

  return function(babel) {
    function acceptFeatureCall(callExpression, ifStatement, invert, file) {
      var callee = callExpression.get('callee');

      if (callee.referencesImport(options.import.module, options.import.name)) {
        var feature;
        var value;
        if (callExpression.node.arguments[0].elements) {
          feature = callExpression.node.arguments[0].elements[0].value;
        } else {
          feature = callExpression.node.arguments[0].value;
          file.log.warn("You should use featureFlag(['feature']) instead of featureFlag('feature') or the function won't run at runtime");
        }
        if (feature in options.features) {
          value = options.features[feature];
        } else {
          value = false;
          file.log.warn("An unknown feature '" + feature + "' was encountered and removed");
        }
        if (value === !invert) {
          var consequent = ifStatement.node.consequent;
          ifStatement.replaceWithMultiple(consequent.body);
        } else if (value === !!invert) {
          var alternate = ifStatement.node.alternate;
          if (alternate) {
            ifStatement.replaceWithMultiple(alternate.body);
          } else {
            ifStatement.dangerouslyRemove();
          }
        }
      }
    }

    return new babel.Transformer('babel-plugin-feature-flags', {
      IfStatement: function(node, parent, scope, file) {
        var test = this.get('test');
        if (test.isUnaryExpression() && test.node.operator === '!') {
          var argument = test.get('argument');
          if (argument.isCallExpression()) {
            acceptFeatureCall(argument, this, true, file);
          }
        } else if (test.isCallExpression()) {
          acceptFeatureCall(test, this, false, file);
        }
      }
    });
  };
};
<|endoftext|>


<commit_before>var net = require('net'),
    ntohl = require('network-byte-order').ntohl,
    htonl = require('network-byte-order').htonl,
    logger = require('winston'),
    buffertools = require('buffertools');

var header_props = ["version","payload", "ret", "controlflags", "size", "offset"];

function sendCommandToSocket(options,socket, callback){
    var messages = [];
    var path = options.path;
    var called = false;
    function callbackOnce(error, data){
        if(!called){
            callback(error,data);
            called = true;
        }
    }
    socket.on('error', function(error){
        logger.error(error);
        callbackOnce(error);
    });
    socket.on('end', function(){
        callbackOnce(null,messages);
    });
    socket.on('data', function (data) {
        var i,j=0,chunk = 4;
        var header ={};
        for (i=0; i<24; i+=chunk) {
            var value = ntohl(data,i);
            header[header_props[j]] = value;
            j++;
        }
        var payload = data.slice(24).toString('utf8');
        var message = {
            header: header,
            payload: payload
        };
        logger.log('debug', "Receiving header",header);
        logger.log('debug', "Receiving payload",payload);
        if(header.ret < 0){
            callbackOnce({msg: "Communication Error. Received "+header.ret, header:header, options:options});
        }
        messages.push(message);
    });
    socket.connect(options.port, options.server, function() {
        logger.debug("Sending",options);
        var data_len = 8192;
        var msg = new Buffer(24);
        htonl(msg,0,0);           //version
        htonl(msg,4,path.length+1); //payload length
        htonl(msg,8,options.command);    //type of function call -> http://owfs.org/index.php?page=owserver-message-types
        htonl(msg,12,0x00000020);         //format flags -- 266 for alias upport
        htonl(msg,16,data_len);    //size of data element for read or write
        htonl(msg,20,0);
        var bres = buffertools.concat(msg, path+'\x00');
        socket.end(bres);
    });
}

function sendCommand(options, callback){
    var socket = new net.Socket({type:'tcp4'});
    sendCommandToSocket(options, socket, callback);
}

module.exports.sendCommand = sendCommand;
module.exports.sendCommandToSocket = sendCommandToSocket;<commit_msg>refactored for loop<commit_after>var net = require('net'),
    ntohl = require('network-byte-order').ntohl,
    htonl = require('network-byte-order').htonl,
    logger = require('winston'),
    buffertools = require('buffertools');

var header_props = ["version","payload", "ret", "controlflags", "size", "offset"];

function sendCommandToSocket(options,socket, callback){
    var messages = [];
    var path = options.path;
    var called = false;
    function callbackOnce(error, data){
        if(!called){
            callback(error,data);
            called = true;
        }
    }
    socket.on('error', function(error){
        logger.error(error);
        callbackOnce(error);
    });
    socket.on('end', function(){
        callbackOnce(null,messages);
    });
    socket.on('data', function (data) {
        var header ={};
        for (var i=0; i<header_props.length; i++) {
            var value = ntohl(data,i*4);
            header[header_props[i]] = value;
        }
        var payload = data.slice(24).toString('utf8');
        var message = {
            header: header,
            payload: payload
        };
        logger.log('debug', "Receiving header",header);
        logger.log('debug', "Receiving payload",payload);
        if(header.ret < 0){
            callbackOnce({msg: "Communication Error. Received "+header.ret, header:header, options:options});
        }
        messages.push(message);
    });
    socket.connect(options.port, options.server, function() {
        logger.debug("Sending",options);
        var data_len = 8192;
        var msg = new Buffer(24);
        htonl(msg,0,0);           //version
        htonl(msg,4,path.length+1); //payload length
        htonl(msg,8,options.command);    //type of function call -> http://owfs.org/index.php?page=owserver-message-types
        htonl(msg,12,0x00000020);         //format flags -- 266 for alias upport
        htonl(msg,16,data_len);    //size of data element for read or write
        htonl(msg,20,0);
        var bres = buffertools.concat(msg, path+'\x00');
        socket.end(bres);
    });
}

function sendCommand(options, callback){
    var socket = new net.Socket({type:'tcp4'});
    sendCommandToSocket(options, socket, callback);
}

module.exports.sendCommand = sendCommand;
module.exports.sendCommandToSocket = sendCommandToSocket;<|endoftext|>


<commit_before>/* global require, module */
'use strict';

var p = require('../preprocessors');

var cleanBaseURL = require('../utilities/clean-base-url');

var preprocessJs  = p.preprocessJs;
var preprocessCss = p.preprocessCss;
var isType        = p.isType;

var preprocessTemplates = p.preprocessTemplates;

var preprocessMinifyCss = p.preprocessMinifyCss;

var replace     = require('broccoli-replace');
var compileES6  = require('broccoli-es6-concatenator');
var validateES6 = require('broccoli-es6-import-validate');
var pickFiles   = require('broccoli-static-compiler');
var mergeTrees  = require('broccoli-merge-trees');
var jshintTrees = require('broccoli-jshint');
var concatFiles = require('broccoli-concat');
var moveFile    = require('broccoli-file-mover');

var unwatchedTree    = require('broccoli-unwatched-tree');
var uglifyJavaScript = require('broccoli-uglify-js');

var memoize    = require('lodash-node/modern/functions').memoize;
var assign     = require('lodash-node/modern/objects/assign');
var defaults   = require('lodash-node/modern/objects/defaults');
var path       = require('path');

module.exports = EmberApp;

function EmberApp(options) {
  this.env  = process.env.EMBER_ENV || 'development';
  this.name = options.name;

  var isProduction = this.env === 'production';

  this.tests = this.hinting = !isProduction;

  this.options = defaults(options, {
    wrapInEval: !isProduction,
    minifyCSS: {
      enabled: true,
      options: {}
    },
    loader: 'vendor/loader/loader.js',
    trees: {},
  });

  this.options.trees = defaults(this.options.trees, {
      app:    'app',
      styles: 'app/styles',
      tests:  'tests',
      vendor: unwatchedTree('vendor'),
    });

  this.importWhitelist     = {};
  this.legacyFilesToAppend = [];
  this.vendorStaticStyles  = [];
  this.otherAssetTrees     = [];
  this._importTrees        = [];

  this.trees = this.options.trees;

  this.populateLegacyFiles();
}

EmberApp.prototype.populateLegacyFiles = function () {

  this.import('vendor/jquery/dist/jquery.js');

  this.import({
    development: 'vendor/handlebars/handlebars.js',
    production:  'vendor/handlebars/handlebars.runtime.js'
  });

  this.import({
    development: 'vendor/ember/ember.js',
    production:  'vendor/ember/ember.prod.js'
  });

  this.import('vendor/ember-cli-shims/app-shims.js', {
    ember: ['default']
  });

  this.import('vendor/ember-resolver/dist/modules/ember-resolver.js', {
    'ember/resolver': ['default']
  });

  this.import('vendor/ember-load-initializers/ember-load-initializers.js', {
    'ember/load-initializers': ['default']
  });
};

EmberApp.prototype.index = memoize(function() {
  var files = [
    'index.html'
  ];

  var index = pickFiles(this.trees.app, {
    srcDir: '/',
    files: files,
    destDir: '/'
  });

  return injectENVJson(this.options.getEnvJSON, this.env, index, files);
});

EmberApp.prototype.testIndex = memoize(function() {
  var index = pickFiles(this.trees.tests, {
    srcDir: '/',
    files: ['index.html'],
    destDir: '/tests'
  });

  return injectENVJson(this.options.getEnvJSON, this.env, index, [
      'tests/index.html'
    ]);
});

EmberApp.prototype.publicFolder = function() {
  return 'public';
};

EmberApp.prototype._processedAppTree = memoize(function() {
  return pickFiles(this.trees.app, {
    srcDir: '/',
    destDir: this.name
  });
});

EmberApp.prototype._processedTestsTree = memoize(function() {
  return pickFiles(this.trees.tests, {
    srcDir: '/',
    destDir: this.name + '/tests'
  });
});

EmberApp.prototype._processedVendorTree = memoize(function() {
  var mergedVendor = mergeTrees([this.trees.vendor].concat(this._importTrees), {
    overwrite: true
  });

  return pickFiles(mergedVendor, {
    srcDir: '/',
    destDir: 'vendor/'
  });
});

EmberApp.prototype.appAndDependencies = memoize(function() {
  var app    = this._processedAppTree();
  var vendor = this._processedVendorTree();

  var appAndTemplates = preprocessTemplates(app);

  var sourceTrees = [ vendor ];

  if (this.tests) {
    var tests  = this._processedTestsTree();
    sourceTrees.push(tests);

    if(this.hinting) {
      var jshintedApp = jshintTrees(app);
      var jshintedTests = jshintTrees(tests, {
        jshintrcRoot: this.name + '/tests/',
      });

      jshintedApp = pickFiles(jshintedApp, {
        srcDir: '/',
        destDir: this.name + '/tests/'
      });
      jshintedTests = pickFiles(jshintedTests, {
        srcDir: '/',
        destDir: this.name + '/tests/'
      });
      sourceTrees.push(jshintedApp);
      sourceTrees.push(jshintedTests);
    }
  }

  // js hint should be applied before preprocessing, validateES6 after
  var preprocessedApp = preprocessJs(appAndTemplates, '/', this.name);
  sourceTrees.unshift(preprocessedApp);

  if (this.hinting) {
    var importWhitelist = this.importWhitelist;

    var applicationJs = validateES6(preprocessedApp, {
      whitelist: importWhitelist
    });
    sourceTrees.push(applicationJs);
  }

  return mergeTrees(sourceTrees, {
      overwrite: true
    });
});

EmberApp.prototype.javascript = memoize(function() {
  var applicationJs       = this.appAndDependencies();
  var legacyFilesToAppend = this.legacyFilesToAppend;

  if (this.env !== 'production') {
    this.import('vendor/ember-qunit/dist/named-amd/main.js', {
      'ember-qunit': [
        'globalize',
        'moduleFor',
        'moduleForComponent',
        'moduleForModel',
        'test',
        'setResolver'
      ]
    });

    this.import('vendor/ember-cli-shims/test-shims.js', {
      'qunit': ['default']
    });
  }

  var es6 = compileES6(applicationJs, {
    loaderFile: this.options.loader,
    ignoredModules: Object.keys(this.importWhitelist),
    inputFiles: [
      this.name + '/**/*.js'
    ],
    wrapInEval: this.options.wrapInEval,
    outputFile: '/assets/' + this.name + '.js',
    legacyFilesToAppend: legacyFilesToAppend
  });

  if (this.env === 'production') {
    return uglifyJavaScript(es6, {
      mangle: true,
      compress: true
    });
  } else {
    return es6;
  }
});

EmberApp.prototype.styles = memoize(function() {
  var vendor = this._processedVendorTree();
  var styles = pickFiles(this.trees.styles, {
    srcDir: '/',
    destDir: '/app/styles'
  });

  var stylesAndVendor = mergeTrees([vendor, styles]);

  var processedStyles = preprocessCss(stylesAndVendor, '/app/styles', '/assets');
  var vendorStyles    = concatFiles(stylesAndVendor, {
    inputFiles: this.vendorStaticStyles,
    outputFile: '/assets/vendor.css'
  });

  if (this.env === 'production' && this.options.minifyCSS.enabled === true) {
    var options = this.options.minifyCSS.options || {};
    processedStyles = preprocessMinifyCss(processedStyles, options);
    vendorStyles    = preprocessMinifyCss(vendorStyles, options);
  }

  return mergeTrees([processedStyles, vendorStyles]);
});

EmberApp.prototype.testFiles = memoize(function() {
  var qunitFiles = pickFiles(this.trees.vendor, {
      srcDir: '/qunit/qunit',
      files: [
        'qunit.css', 'qunit.js'
      ],
      destDir: '/assets/'
    });

  var notificationsFile = moveFile(this.trees.vendor, {
    srcFile: '/qunit-notifications/index.js',
    destFile: '/assets/qunit-notifications.js'
  });

  qunitFiles = mergeTrees([qunitFiles, notificationsFile], {
    overwrite: true
  });

  var testemPath = path.join(__dirname, 'testem');
  testemPath = path.dirname(testemPath);

  var testemTree = pickFiles(testemPath, {
      files: ['testem.js'],
      srcDir: '/',
      destDir: '/'
    });

  var iconsPath = 'vendor/ember-qunit-notifications';

  var iconsTree = pickFiles(iconsPath, {
    files: ['passed.png', 'failed.png'],
    srcDir: '/',
    destDir: '/assets/'
  });

  var sourceTrees = [qunitFiles, testemTree, iconsTree];

  return mergeTrees(sourceTrees, {
      overwrite: true
    });
});

EmberApp.prototype.otherAssets = memoize(function() {
  return mergeTrees(this.otherAssetTrees);
});

EmberApp.prototype.import = function(asset, modules) {
  var assetPath;

  if (typeof asset === 'object') {
    assetPath = asset[this.env];
  } else {
    assetPath = asset;
  }

  var directory = path.dirname(assetPath);
  var extension = path.extname(assetPath);
  var basename  = path.basename(assetPath);

  if (!extension) {
    throw new Error('You must pass a file to `EmberApp::import`. For directories specify them to the constructor under the `trees` option.');
  }

  var assetTree = pickFiles(directory, {
    srcDir: '/',
    destDir: directory.replace(/^vendor\//, '')
  });

  this._importTrees.push(assetTree);

  if (isType(assetPath, 'js')) {
    this.legacyFilesToAppend.push(assetPath);

    this.importWhitelist = assign(this.importWhitelist, modules || {});
  } else if (extension === '.css') {
    this.vendorStaticStyles.push(assetPath);
  } else {
    var otherAssetTree = pickFiles(this.trees.vendor, {
      srcDir: directory,
      files: [basename],
      destDir: directory
    });

    this.otherAssetTrees.push(otherAssetTree);
  }
};

EmberApp.prototype.toArray = function() {
  var sourceTrees = [
    this.index(),
    this.javascript(),
    this.publicFolder(),
    this.styles(),
    this.otherAssets()
  ];

  if (this.tests) {
    sourceTrees = sourceTrees.concat(this.testIndex(), this.testFiles());
  }

  return sourceTrees;
};

EmberApp.prototype.toTree = memoize(function() {
  return mergeTrees(this.toArray(), {
    overwrite: true
  });
});

function injectENVJson(fn, env, tree, files) {
  // TODO: real templating
  var envJsonString = function(){
    return JSON.stringify(fn(env));
  };

  var baseTag = function(){
    var envJSON      = fn(env);
    var baseURL      = cleanBaseURL(envJSON.baseURL);
    var locationType = envJSON.locationType;

    if (locationType === 'hash' || locationType === 'none') {
      return '';
    }

    if (baseURL) {
      return '<base href="' + baseURL + '" />';
    } else {
      return '';
    }
  };

  return replace(tree, {
    files: files,
    patterns: [{
      match: /\{\{ENV\}\}/g,
      replacement: envJsonString
    },
    {
      match: /\{\{BASE_TAG\}\}/g,
      replacement: baseTag
    }]
  });
}
<commit_msg>Fixes CoffeeScript test files not being preprocessed<commit_after>/* global require, module */
'use strict';

var p = require('../preprocessors');

var cleanBaseURL = require('../utilities/clean-base-url');

var preprocessJs  = p.preprocessJs;
var preprocessCss = p.preprocessCss;
var isType        = p.isType;

var preprocessTemplates = p.preprocessTemplates;

var preprocessMinifyCss = p.preprocessMinifyCss;

var replace     = require('broccoli-replace');
var compileES6  = require('broccoli-es6-concatenator');
var validateES6 = require('broccoli-es6-import-validate');
var pickFiles   = require('broccoli-static-compiler');
var mergeTrees  = require('broccoli-merge-trees');
var jshintTrees = require('broccoli-jshint');
var concatFiles = require('broccoli-concat');
var moveFile    = require('broccoli-file-mover');

var unwatchedTree    = require('broccoli-unwatched-tree');
var uglifyJavaScript = require('broccoli-uglify-js');

var memoize    = require('lodash-node/modern/functions').memoize;
var assign     = require('lodash-node/modern/objects/assign');
var defaults   = require('lodash-node/modern/objects/defaults');
var path       = require('path');

module.exports = EmberApp;

function EmberApp(options) {
  this.env  = process.env.EMBER_ENV || 'development';
  this.name = options.name;

  var isProduction = this.env === 'production';

  this.tests = this.hinting = !isProduction;

  this.options = defaults(options, {
    wrapInEval: !isProduction,
    minifyCSS: {
      enabled: true,
      options: {}
    },
    loader: 'vendor/loader/loader.js',
    trees: {},
  });

  this.options.trees = defaults(this.options.trees, {
      app:    'app',
      styles: 'app/styles',
      tests:  'tests',
      vendor: unwatchedTree('vendor'),
    });

  this.importWhitelist     = {};
  this.legacyFilesToAppend = [];
  this.vendorStaticStyles  = [];
  this.otherAssetTrees     = [];
  this._importTrees        = [];

  this.trees = this.options.trees;

  this.populateLegacyFiles();
}

EmberApp.prototype.populateLegacyFiles = function () {

  this.import('vendor/jquery/dist/jquery.js');

  this.import({
    development: 'vendor/handlebars/handlebars.js',
    production:  'vendor/handlebars/handlebars.runtime.js'
  });

  this.import({
    development: 'vendor/ember/ember.js',
    production:  'vendor/ember/ember.prod.js'
  });

  this.import('vendor/ember-cli-shims/app-shims.js', {
    ember: ['default']
  });

  this.import('vendor/ember-resolver/dist/modules/ember-resolver.js', {
    'ember/resolver': ['default']
  });

  this.import('vendor/ember-load-initializers/ember-load-initializers.js', {
    'ember/load-initializers': ['default']
  });
};

EmberApp.prototype.index = memoize(function() {
  var files = [
    'index.html'
  ];

  var index = pickFiles(this.trees.app, {
    srcDir: '/',
    files: files,
    destDir: '/'
  });

  return injectENVJson(this.options.getEnvJSON, this.env, index, files);
});

EmberApp.prototype.testIndex = memoize(function() {
  var index = pickFiles(this.trees.tests, {
    srcDir: '/',
    files: ['index.html'],
    destDir: '/tests'
  });

  return injectENVJson(this.options.getEnvJSON, this.env, index, [
      'tests/index.html'
    ]);
});

EmberApp.prototype.publicFolder = function() {
  return 'public';
};

EmberApp.prototype._processedAppTree = memoize(function() {
  return pickFiles(this.trees.app, {
    srcDir: '/',
    destDir: this.name
  });
});

EmberApp.prototype._processedTestsTree = memoize(function() {
  return pickFiles(this.trees.tests, {
    srcDir: '/',
    destDir: this.name + '/tests'
  });
});

EmberApp.prototype._processedVendorTree = memoize(function() {
  var mergedVendor = mergeTrees([this.trees.vendor].concat(this._importTrees), {
    overwrite: true
  });

  return pickFiles(mergedVendor, {
    srcDir: '/',
    destDir: 'vendor/'
  });
});

EmberApp.prototype.appAndDependencies = memoize(function() {
  var app    = this._processedAppTree();
  var vendor = this._processedVendorTree();

  var appAndTemplates = preprocessTemplates(app);

  var sourceTrees = [ vendor ];

  if (this.tests) {
    var tests  = this._processedTestsTree();
    var preprocessedTests = preprocessJs(tests, '/tests', this.name);
    sourceTrees.push(preprocessedTests);

    if(this.hinting) {
      var jshintedApp = jshintTrees(app);
      var jshintedTests = jshintTrees(tests, {
        jshintrcRoot: this.name + '/tests/',
      });

      jshintedApp = pickFiles(jshintedApp, {
        srcDir: '/',
        destDir: this.name + '/tests/'
      });
      jshintedTests = pickFiles(jshintedTests, {
        srcDir: '/',
        destDir: this.name + '/tests/'
      });
      sourceTrees.push(jshintedApp);
      sourceTrees.push(jshintedTests);
    }
  }

  // js hint should be applied before preprocessing, validateES6 after
  var preprocessedApp = preprocessJs(appAndTemplates, '/', this.name);
  sourceTrees.unshift(preprocessedApp);

  if (this.hinting) {
    var importWhitelist = this.importWhitelist;

    var applicationJs = validateES6(preprocessedApp, {
      whitelist: importWhitelist
    });
    sourceTrees.push(applicationJs);
  }

  return mergeTrees(sourceTrees, {
      overwrite: true
    });
});

EmberApp.prototype.javascript = memoize(function() {
  var applicationJs       = this.appAndDependencies();
  var legacyFilesToAppend = this.legacyFilesToAppend;

  if (this.env !== 'production') {
    this.import('vendor/ember-qunit/dist/named-amd/main.js', {
      'ember-qunit': [
        'globalize',
        'moduleFor',
        'moduleForComponent',
        'moduleForModel',
        'test',
        'setResolver'
      ]
    });

    this.import('vendor/ember-cli-shims/test-shims.js', {
      'qunit': ['default']
    });
  }

  var es6 = compileES6(applicationJs, {
    loaderFile: this.options.loader,
    ignoredModules: Object.keys(this.importWhitelist),
    inputFiles: [
      this.name + '/**/*.js'
    ],
    wrapInEval: this.options.wrapInEval,
    outputFile: '/assets/' + this.name + '.js',
    legacyFilesToAppend: legacyFilesToAppend
  });

  if (this.env === 'production') {
    return uglifyJavaScript(es6, {
      mangle: true,
      compress: true
    });
  } else {
    return es6;
  }
});

EmberApp.prototype.styles = memoize(function() {
  var vendor = this._processedVendorTree();
  var styles = pickFiles(this.trees.styles, {
    srcDir: '/',
    destDir: '/app/styles'
  });

  var stylesAndVendor = mergeTrees([vendor, styles]);

  var processedStyles = preprocessCss(stylesAndVendor, '/app/styles', '/assets');
  var vendorStyles    = concatFiles(stylesAndVendor, {
    inputFiles: this.vendorStaticStyles,
    outputFile: '/assets/vendor.css'
  });

  if (this.env === 'production' && this.options.minifyCSS.enabled === true) {
    var options = this.options.minifyCSS.options || {};
    processedStyles = preprocessMinifyCss(processedStyles, options);
    vendorStyles    = preprocessMinifyCss(vendorStyles, options);
  }

  return mergeTrees([processedStyles, vendorStyles]);
});

EmberApp.prototype.testFiles = memoize(function() {
  var qunitFiles = pickFiles(this.trees.vendor, {
      srcDir: '/qunit/qunit',
      files: [
        'qunit.css', 'qunit.js'
      ],
      destDir: '/assets/'
    });

  var notificationsFile = moveFile(this.trees.vendor, {
    srcFile: '/qunit-notifications/index.js',
    destFile: '/assets/qunit-notifications.js'
  });

  qunitFiles = mergeTrees([qunitFiles, notificationsFile], {
    overwrite: true
  });

  var testemPath = path.join(__dirname, 'testem');
  testemPath = path.dirname(testemPath);

  var testemTree = pickFiles(testemPath, {
      files: ['testem.js'],
      srcDir: '/',
      destDir: '/'
    });

  var iconsPath = 'vendor/ember-qunit-notifications';

  var iconsTree = pickFiles(iconsPath, {
    files: ['passed.png', 'failed.png'],
    srcDir: '/',
    destDir: '/assets/'
  });

  var sourceTrees = [qunitFiles, testemTree, iconsTree];

  return mergeTrees(sourceTrees, {
      overwrite: true
    });
});

EmberApp.prototype.otherAssets = memoize(function() {
  return mergeTrees(this.otherAssetTrees);
});

EmberApp.prototype.import = function(asset, modules) {
  var assetPath;

  if (typeof asset === 'object') {
    assetPath = asset[this.env];
  } else {
    assetPath = asset;
  }

  var directory = path.dirname(assetPath);
  var extension = path.extname(assetPath);
  var basename  = path.basename(assetPath);

  if (!extension) {
    throw new Error('You must pass a file to `EmberApp::import`. For directories specify them to the constructor under the `trees` option.');
  }

  var assetTree = pickFiles(directory, {
    srcDir: '/',
    destDir: directory.replace(/^vendor\//, '')
  });

  this._importTrees.push(assetTree);

  if (isType(assetPath, 'js')) {
    this.legacyFilesToAppend.push(assetPath);

    this.importWhitelist = assign(this.importWhitelist, modules || {});
  } else if (extension === '.css') {
    this.vendorStaticStyles.push(assetPath);
  } else {
    var otherAssetTree = pickFiles(this.trees.vendor, {
      srcDir: directory,
      files: [basename],
      destDir: directory
    });

    this.otherAssetTrees.push(otherAssetTree);
  }
};

EmberApp.prototype.toArray = function() {
  var sourceTrees = [
    this.index(),
    this.javascript(),
    this.publicFolder(),
    this.styles(),
    this.otherAssets()
  ];

  if (this.tests) {
    sourceTrees = sourceTrees.concat(this.testIndex(), this.testFiles());
  }

  return sourceTrees;
};

EmberApp.prototype.toTree = memoize(function() {
  return mergeTrees(this.toArray(), {
    overwrite: true
  });
});

function injectENVJson(fn, env, tree, files) {
  // TODO: real templating
  var envJsonString = function(){
    return JSON.stringify(fn(env));
  };

  var baseTag = function(){
    var envJSON      = fn(env);
    var baseURL      = cleanBaseURL(envJSON.baseURL);
    var locationType = envJSON.locationType;

    if (locationType === 'hash' || locationType === 'none') {
      return '';
    }

    if (baseURL) {
      return '<base href="' + baseURL + '" />';
    } else {
      return '';
    }
  };

  return replace(tree, {
    files: files,
    patterns: [{
      match: /\{\{ENV\}\}/g,
      replacement: envJsonString
    },
    {
      match: /\{\{BASE_TAG\}\}/g,
      replacement: baseTag
    }]
  });
}
<|endoftext|>


<commit_before>import 'babel/polyfill';
import expect from 'expect.js';
import sinon from 'sinon';
import Individual from '../../../core/individual';
import TournamentParentSelection
    from '../../../core/parent-selections/tournament';

function createPopulation(size = 5) {
    var population = [];
    for (let i = 0; i < size; i++) {
        var fitness = sinon.stub().returns(Math.random());
        population.push({ fitness: fitness });
    }
    return population;
}

describe('TournamentParentSelection', () => {
    describe('select(population)', () => {
        it('should return parents with same size as given population', () => {
            var population = createPopulation();
            var selection = new TournamentParentSelection(3);
            var parents = selection.select(population);
            expect(parents.length).to.be(population.length);
        });

        it('should return fittest parents from their groups', () => {
            var population = createPopulation();
            var selection = new TournamentParentSelection(3);
            var group = sinon.stub(selection, 'group');
            var p = population;
            group.onCall(0).returns([p[0], p[3], p[2]]);
            group.onCall(1).returns([p[4], p[1], p[3]]);
            group.onCall(2).returns([p[1], p[3], p[1]]);
            group.onCall(3).returns([p[1], p[0], p[3]]);
            group.onCall(4).returns([p[1], p[2], p[2]]);
            var parents = selection.select(population);
            group.restore();
            expect(parents.map(parent => parent.fitness()))
                .to.eql([p[3], p[4], p[3], p[3], p[2]].map(a => a.fitness()));
        });

        it('should not modify the given population', () => {
            var population = createPopulation();
            var backupPopulation = [...population];
            var selection = new TournamentParentSelection(3);
            var parents = selection.select(population);
            expect(population.map(a => a.fitness()))
                .to.eql(backupPopulation.map(a => a.fitness()));
        });
    });

    describe('group(population)', () => {
        it('should return a group with the correct size', () => {
            var population = createPopulation();
            var selection = new TournamentParentSelection(3);
            var group = selection.group(population);
            expect(group.length).to.be(3);
        });

        it('should be called with the given population', () => {
            var population = createPopulation();
            var selection = new TournamentParentSelection(3);
            var group = sinon.spy(selection, 'group');
            var parents = selection.select(population);
            group.restore();
            expect(group.alwaysCalledWith(population)).to.be(true);
        });
    });

    describe('rank(population, order)', () => {
        it('should rank the population by increasing fitness', () => {
            var population = createPopulation(5);
            var selection = new TournamentParentSelection(3);
            var ranked = selection.rank(population, 1);
            for (let i = 1; i < ranked.length; i++) {
                expect(ranked[i].fitness())
                    .to.be.above(ranked[i - 1].fitness());
            }
        });

        it('should rank the population by decreasing fitness', () => {
            var population = createPopulation(5);
            var selection = new TournamentParentSelection(3);
            var ranked = selection.rank(population, -1);
            for (let i = 1; i < ranked.length; i++) {
                expect(ranked[i].fitness())
                    .to.be.below(ranked[i - 1].fitness());
            }
        });

        it('should not modify the given population', () => {
            var population = createPopulation(5);
            var backupPopulation = [...population];
            var selection = new TournamentParentSelection(3);
            var ranked = selection.rank(population, 1);
            expect(population.map(a => a.fitness()))
                .to.eql(backupPopulation.map(a => a.fitness()));
        });
    });
});
<commit_msg>corrected tests for tournament parent selection<commit_after>import 'babel/polyfill';
import expect from 'expect.js';
import sinon from 'sinon';
import Individual from '../../../core/individual';
import TournamentParentSelection
    from '../../../core/parent-selections/tournament';

function createPopulation(size = 5) {
    var population = [];
    for (let i = 0; i < size; i++) {
        var fitness = sinon.stub().returns(Math.random());
        population.push({ fitness: fitness });
    }
    return population;
}

describe('TournamentParentSelection', () => {
    describe('select(population)', () => {
        it('should return parents with same size as given population', () => {
            var population = createPopulation();
            var selection = new TournamentParentSelection(3);
            var parents = selection.select(population);
            expect(parents.length).to.be(population.length);
        });

        it('should return fittest parents from their groups', () => {
            var population = createPopulation();
            var selection = new TournamentParentSelection(3);
            var group = sinon.stub(selection, 'group');
            var p = population;
            group.onCall(0).returns([p[0], p[3], p[2]]);
            group.onCall(1).returns([p[4], p[1], p[3]]);
            group.onCall(2).returns([p[1], p[3], p[1]]);
            group.onCall(3).returns([p[1], p[0], p[3]]);
            group.onCall(4).returns([p[1], p[2], p[2]]);
            var parents = selection.select(population);
            group.restore();
            var expected = [
                Math.max(...[p[0], p[3], p[2]].map(a => a.fitness())),
                Math.max(...[p[4], p[1], p[3]].map(a => a.fitness())),
                Math.max(...[p[1], p[3], p[1]].map(a => a.fitness())),
                Math.max(...[p[1], p[0], p[3]].map(a => a.fitness())),
                Math.max(...[p[1], p[2], p[2]].map(a => a.fitness()))
            ];
            expect(parents.map(parent => parent.fitness())).to.eql(expected);
        });

        it('should not modify the given population', () => {
            var population = createPopulation();
            var backupPopulation = [...population];
            var selection = new TournamentParentSelection(3);
            var parents = selection.select(population);
            expect(population.map(a => a.fitness()))
                .to.eql(backupPopulation.map(a => a.fitness()));
        });
    });

    describe('group(population)', () => {
        it('should return a group with the correct size', () => {
            var population = createPopulation();
            var selection = new TournamentParentSelection(3);
            var group = selection.group(population);
            expect(group.length).to.be(3);
        });

        it('should be called with the given population', () => {
            var population = createPopulation();
            var selection = new TournamentParentSelection(3);
            var group = sinon.spy(selection, 'group');
            var parents = selection.select(population);
            group.restore();
            expect(group.alwaysCalledWith(population)).to.be(true);
        });
    });

    describe('rank(population, order)', () => {
        it('should rank the population by increasing fitness', () => {
            var population = createPopulation(5);
            var selection = new TournamentParentSelection(3);
            var ranked = selection.rank(population, 1);
            for (let i = 1; i < ranked.length; i++) {
                expect(ranked[i].fitness())
                    .to.be.above(ranked[i - 1].fitness());
            }
        });

        it('should rank the population by decreasing fitness', () => {
            var population = createPopulation(5);
            var selection = new TournamentParentSelection(3);
            var ranked = selection.rank(population, -1);
            for (let i = 1; i < ranked.length; i++) {
                expect(ranked[i].fitness())
                    .to.be.below(ranked[i - 1].fitness());
            }
        });

        it('should not modify the given population', () => {
            var population = createPopulation(5);
            var backupPopulation = [...population];
            var selection = new TournamentParentSelection(3);
            var ranked = selection.rank(population, 1);
            expect(population.map(a => a.fitness()))
                .to.eql(backupPopulation.map(a => a.fitness()));
        });
    });
});
<|endoftext|>