<commit_before>describe("LinkListView", function() {
  $a = window.beats;
  var models, network, begin, end, scen;

  beforeEach(function() {
    loadFixtures('context.menu.view.fixture.html');
    network = $a.models.get('networkset').get('network')[0];
    models = $a.models.links();
    spyOn($a.LinkListView.prototype, 'addAndRender').andCallThrough();
    spyOn($a.LinkListView.prototype, 'createAndDrawLink').andCallThrough();
    spyOn($a.LinkListView.prototype, 'removeLink').andCallThrough();
    spyOn($a.LinkListView.prototype, 'setStrokeWeight').andCallThrough();
    this.lColl = new $a.LinkListCollection(models, network);
    this.view = new $a.LinkListView(this.lColl, network);
    begin = models[0].begin_node();
    end = models[0].end_node();
    scen = scenarioAndFriends();
  });

  describe("Instantiation", function() {
           it("sets all its collection and network attributes", function() {
              expect(this.view.collection).not.toBeNull();
              expect(this.view.network).not.toBeNull();
            });

            it("should be watching addAndRender", function() {
                l = scen.link1
                args = {begin:l.begin_node(),end:l.end_node(),path:l.geometry(), parallel:true};
                link = this.lColl.addLink(args);
                expect($a.LinkListView.prototype.addAndRender).toHaveBeenCalled();
                this.lColl.removeLink(link.cid);
            });

           it("should be watching createAndDrawLink", function() {
             $a.broker.trigger('map:draw_link', scen.link1);
             expect($a.LinkListView.prototype.createAndDrawLink).toHaveBeenCalled();
           });

           it("should be watching removeLink", function() {
             this.lColl.trigger('remove', models[0]);
             expect($a.LinkListView.prototype.removeLink).toHaveBeenCalled();
           });
           it("should be watching setStrokeWeight", function() {
             $a.map.setZoom(9)
             expect($a.LinkListView.prototype.setStrokeWeight).toHaveBeenCalled();
           });
           it("should call getLinkGeometry, create GoogleRouteHandler", function() {
             expect(this.view.routeHandler).not.toBeNull();
           });
     });

   describe("createAndDrawLink", function() {
     it("should create MapLinkViews for link", function() {
       mlv = this.view.createAndDrawLink(scen.link1);
       expect(mlv).not.toBeNull();
       expect(mlv.link.getMap()).toEqual($a.map);
     });
   });

   describe("addAndRender", function() {
     it("should create a MapNodeView and render it", function() {
       newLink = simpleLink(1, begin, end);
       link = this.view.addAndRender(newLink, true);
       expect(link.get('linkgeometry')).not.toBeNull();
     });
   });

  describe("removeLink", function() {
    afterEach(function() {
      this.view.createAndDrawLink(scen.link1);
    });
    it("should remove the MapLinkView from views array", function() {
      this.view.createAndDrawLink(scen.link1);
      var lengthBefore = this.view.views.length;
      this.view.removeLink(scen.link1);
      expect(this.view.views.length).toEqual(lengthBefore - 1);
    });
  });
   describe("setStrokeWeight", function() {
    it("should set link stroke weight dependent on zoom level", function() {
      this.view.createAndDrawLink(scen.link1);
      googleMap();
      $a.map.setZoom(18);
      this.view.setStrokeWeight();
      var l =  this.view.views[0].link
      var weight  = l.get('strokeWeight');
      expect(weight).toEqual(3);
    });
  });
});<commit_msg>LinkListViewSpec tests re-positioning of node<commit_after>describe("LinkListView", function() {
  $a = window.beats;
  var models, network, begin, end, scen;

  beforeEach(function() {
    loadFixtures('context.menu.view.fixture.html');
    network = $a.models.get('networkset').get('network')[0];
    models = $a.models.links();
    spyOn($a.LinkListView.prototype, 'addAndRender').andCallThrough();
    spyOn($a.LinkListView.prototype, 'createAndDrawLink').andCallThrough();
    spyOn($a.LinkListView.prototype, 'resetPath').andCallThrough();
    spyOn($a.LinkListView.prototype, 'removeLink').andCallThrough();
    spyOn($a.LinkListView.prototype, 'setStrokeWeight').andCallThrough();
    this.lColl = new $a.LinkListCollection(models, network);
    this.view = new $a.LinkListView(this.lColl, network);
    begin = models[0].begin_node();
    end = models[0].end_node();
    scen = scenarioAndFriends();
  });

  describe("Instantiation", function() {
           it("sets all its collection and network attributes", function() {
              expect(this.view.collection).not.toBeNull();
              expect(this.view.network).not.toBeNull();
            });

            it("should be watching addAndRender", function() {
                l = scen.link1
                args = {begin:l.begin_node(),end:l.end_node(),path:l.geometry(), parallel:true};
                link = this.lColl.addLink(args);
                args = {begin:l.begin_node(),end:l.end_node(),path:l.geometry(), parallel:true};
                link = this.lColl.addLink(args);
                expect($a.LinkListView.prototype.addAndRender).toHaveBeenCalled();
                this.lColl.removeLink(link.cid);
            });

            it("should be watching resetPath", function() {
              link = this.lColl.models[0];
              latLng = new google.maps.LatLng(37.8579, -122.2995);
              link.begin_node().updatePosition(latLng);
              expect($a.LinkListView.prototype.resetPath).toHaveBeenCalled();
              this.lColl.removeLink(link.cid);
            });
           it("should be watching createAndDrawLink", function() {
             $a.broker.trigger('map:draw_link', scen.link1);
             expect($a.LinkListView.prototype.createAndDrawLink).toHaveBeenCalled();
           });

           it("should be watching removeLink", function() {
             this.lColl.trigger('remove', models[0]);
             expect($a.LinkListView.prototype.removeLink).toHaveBeenCalled();
           });
           it("should be watching setStrokeWeight", function() {
             $a.map.setZoom(9)
             expect($a.LinkListView.prototype.setStrokeWeight).toHaveBeenCalled();
           });
           it("should call getLinkGeometry, create GoogleRouteHandler", function() {
             expect(this.view.routeHandler).not.toBeNull();
           });
     });

   describe("createAndDrawLink", function() {
     it("should create MapLinkViews for link", function() {
       mlv = this.view.createAndDrawLink(scen.link1);
       expect(mlv).not.toBeNull();
       expect(mlv.link.getMap()).toEqual($a.map);
     });
   });

   describe("addAndRender", function() {
     it("should create a MapNodeView and render it", function() {
       newLink = simpleLink(1, begin, end);
       link = this.view.addAndRender(newLink, true);
       expect(link.get('linkgeometry')).not.toBeNull();
     });
   });

  describe("removeLink", function() {
    afterEach(function() {
      this.view.createAndDrawLink(scen.link1);
    });
    it("should remove the MapLinkView from views array", function() {
      this.view.createAndDrawLink(scen.link1);
      var lengthBefore = this.view.views.length;
      this.view.removeLink(scen.link1);
      expect(this.view.views.length).toEqual(lengthBefore - 1);
    });
  });
   describe("setStrokeWeight", function() {
    it("should set link stroke weight dependent on zoom level", function() {
      this.view.createAndDrawLink(scen.link1);
      googleMap();
      $a.map.setZoom(18);
      this.view.setStrokeWeight();
      var l =  this.view.views[0].link
      var weight  = l.get('strokeWeight');
      expect(weight).toEqual(3);
    });
  });
});<|endoftext|>


<commit_before>var geocoder;
var map;

var codefellows = {lat: 47.618248, lng: -122.351871};

/**
 * The CenterControl adds a control to the map that recenters the map on
 * codefellows.
 * This constructor takes the control DIV as an argument.
 * @constructor
 */
function CenterControl(controlDiv, map) {

  // Set CSS for the control border.
  var controlUI = document.createElement('div');
  controlUI.style.backgroundColor = '#A874D4';
  controlUI.style.borderRadius = '3px';
  controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
  controlUI.style.cursor = 'pointer';
  controlUI.style.marginBottom = '22px';
  controlUI.style.marginTop = '22px';
  controlUI.style.textAlign = 'center';
  controlUI.title = 'Click to add toilet';
  controlDiv.appendChild(controlUI);

  // Set CSS for the control interior.
  var controlText = document.createElement('div');
  controlText.style.color = 'white';
  controlText.style.fontFamily = 'Delius Unicase', 'cursive';
  controlText.style.fontSize = '16px';
  controlText.style.lineHeight = '38px';
  controlText.style.paddingLeft = '5px';
  controlText.style.paddingRight = '5px';
  controlText.innerHTML = 'Add Toilet';
  controlUI.appendChild(controlText);

  // Setup the click event listeners: simply set the map to Codefellows.
  controlUI.addEventListener('click', function() {
    $('.mainContent').hide();
    $('.aboutUsAll').hide();
    $('.toilet-form').fadeIn();
  });

}

//initializing google map
function initMap() {
  var geocoder = new google.maps.Geocoder();
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 15,
    center: codefellows,
    icon: "/css/images/code_fellows/png"
  });

  // Create the DIV to hold the control and call the CenterControl()
  // constructor passing in this DIV.
  var centerControlDiv = document.createElement('div');
  var centerControl = new CenterControl(centerControlDiv, map);
  var marker = new google.maps.Marker({
          position: codefellows,
          map: map,
        });
  var script = document.createElement('script');
  script.src='../../data/toiletsRawData.json';
  document.getElementsByTagName('head')[0].appendChild(script);

  centerControlDiv.index = 1;
  map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlDiv);
}

window.eqfeed_callback = function(results) {
  for (var i = 0; i < results.features.length; i++) {
    var coords = results.features[i].geometry.coordinates;
    var latLng = new google.maps.LatLng(coords[1],coords[0]);
    var marker = new google.maps.Marker({
      position: latLng,
      map: map
    });
  }
}

function addMarker(coords, toilet){
  var marker = new google.maps.Marker({
        map: map,
        position: coords,
        icon: "/css/images/rainbowShit.png"
      });
  var infoWindow = new google.maps.InfoWindow({
    content: `
${toilet.location}

Overall Quality: ${toilet.overallQuality}

TP Quality: ${toilet.tpQuality}

Overall Quality: ${toilet.overallQuality}

Free To Use or Pay: ${toilet.usage}

Single or Multiple occupancy: ${toilet.occupancy}

Gender Neutral Friendly: ${toilet.genderNeutral}

Gel Soap or Foam Soap: ${toilet.soap}

Paper Towels or Air Dry: ${toilet.drying}

Comments: ${toilet.comments}
`
  });
  marker.addListener('mouseover', function() {
    infoWindow.open(map, marker);
  });
  marker.addListener('mouseout', function() {
    infoWindow.close(map,marker);
  });
}

function loadMarkers(){
  app.Toilet.all.forEach(toilet => toilet.geocode(addMarker));
}

function initIndexPage(){
  app.Toilet.fetchData(loadMarkers);
}
<commit_msg>updated map<commit_after>var geocoder;
var map;

var codefellows = {lat: 47.618248, lng: -122.351871};

/**
 * The CenterControl adds a control to the map that recenters the map on
 * codefellows.
 * This constructor takes the control DIV as an argument.
 * @constructor
 */
function CenterControl(controlDiv, map) {

  // Set CSS for the control border.
  var controlUI = document.createElement('div');
  controlUI.style.backgroundColor = '#A874D4';
  controlUI.style.borderRadius = '3px';
  controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
  controlUI.style.cursor = 'pointer';
  controlUI.style.marginBottom = '22px';
  controlUI.style.marginTop = '22px';
  controlUI.style.textAlign = 'center';
  controlUI.title = 'Click to add toilet';
  controlDiv.appendChild(controlUI);

  // Set CSS for the control interior.
  var controlText = document.createElement('div');
  controlText.style.color = 'white';
  controlText.style.fontFamily = 'Delius Unicase', 'cursive';
  controlText.style.fontSize = '16px';
  controlText.style.lineHeight = '38px';
  controlText.style.paddingLeft = '5px';
  controlText.style.paddingRight = '5px';
  controlText.innerHTML = 'Add Toilet';
  controlUI.appendChild(controlText);

  // Setup the click event listeners: simply set the map to Codefellows.
  controlUI.addEventListener('click', function() {
    $('.mainContent').hide();
    $('.aboutUsAll').hide();
    $('.toilet-form').fadeIn();
  });

}

//initializing google map
function initMap() {
  var geocoder = new google.maps.Geocoder();
  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 15,
    center: codefellows,
    icon: "/css/images/code_fellows.png"
  });

  // Create the DIV to hold the control and call the CenterControl()
  // constructor passing in this DIV.
  var centerControlDiv = document.createElement('div');
  var centerControl = new CenterControl(centerControlDiv, map);
  var marker = new google.maps.Marker({
          position: codefellows,
          map: map,
        });
  var script = document.createElement('script');
  script.src='../../data/toiletsRawData.json';
  document.getElementsByTagName('head')[0].appendChild(script);

  centerControlDiv.index = 1;
  map.controls[google.maps.ControlPosition.TOP_CENTER].push(centerControlDiv);
}

window.eqfeed_callback = function(results) {
  for (var i = 0; i < results.features.length; i++) {
    var coords = results.features[i].geometry.coordinates;
    var latLng = new google.maps.LatLng(coords[1],coords[0]);
    var marker = new google.maps.Marker({
      position: latLng,
      map: map
    });
  }
}

function addMarker(coords, toilet){
  var marker = new google.maps.Marker({
        map: map,
        position: coords,
        icon: "/css/images/rainbowShit.png"
      });
  var infoWindow = new google.maps.InfoWindow({
    content: `
${toilet.location}

Overall Quality: ${toilet.overallQuality}

TP Quality: ${toilet.tpQuality}

Overall Quality: ${toilet.overallQuality}

Free To Use or Pay: ${toilet.usage}

Single or Multiple occupancy: ${toilet.occupancy}

Gender Neutral Friendly: ${toilet.genderNeutral}

Gel Soap or Foam Soap: ${toilet.soap}

Paper Towels or Air Dry: ${toilet.drying}

Comments: ${toilet.comments}
`
  });
  marker.addListener('mouseover', function() {
    infoWindow.open(map, marker);
  });
  marker.addListener('mouseout', function() {
    infoWindow.close(map,marker);
  });
}

function loadMarkers(){
  app.Toilet.all.forEach(toilet => toilet.geocode(addMarker));
}

function initIndexPage(){
  app.Toilet.fetchData(loadMarkers);
}
<|endoftext|>


<commit_before>/**
Hook is executed when plugin is added to the project.
It will check all necessary module dependencies and install the missing ones locally.
*/

var exec = require('child_process').exec,
  path = require('path'),
  fs = require('fs'),
  logger = require('./lib/logger.js'),
  modules = ['read-package-json'],
  INSTALLATION_FLAG_FILE_NAME = '.installed',
  packageJsonFilePath;

// region NPM specific

/**
 * Discovers module dependencies in plugin's package.json and installs them.
 */
function installModulesFromPackageJson() {
  var readJson = require('read-package-json');
  readJson(packageJsonFilePath, console.error, false, function(err, data) {
    if (err) {
      logger.error('Can\'t read package.json file: ' + err);
      return;
    }

    var dependencies = data['dependencies'];
    if (dependencies) {
      for (var module in dependencies) {
        modules.push(module);
      }
      installRequiredNodeModules(function() {
        logger.info('All dependency modules are installed.');
      });
    }
  });
}

/**
 * Check if node package is installed.
 *
 * @param {String} moduleName
 * @return {Boolean} true if package already installed
 */
function isNodeModuleInstalled(moduleName) {
  var installed = true;
  try {
    var module = require(moduleName);
  } catch (err) {
    installed = false;
  }

  return installed;
}

/**
 * Install node module locally.
 * Basically, it runs 'npm install module_name'.
 *
 * @param {String} moduleName
 * @param {Callback(error)} callback
 */
function installNodeModule(moduleName, callback) {
  if (isNodeModuleInstalled(moduleName)) {
    callback(null);
    return;
  }
  logger.info('Can\'t find module ' + moduleName + ', running npm install');

  var cmd = 'npm install -D ' + moduleName;
  exec(cmd, function(err, stdout, stderr) {
    callback(err);
  });
}

/**
 * Install all required node packages.
 */
function installRequiredNodeModules(callback) {
  if (modules.length == 0) {
    callback();
    return;
  }

  var moduleName = modules.shift();
  installNodeModule(moduleName, function(err) {
    if (err) {
      logger.error('Failed to install module ' + moduleName + ':' + err);
      return;
    }

    logger.info('Module ' + moduleName + ' is installed');
    installRequiredNodeModules(callback);
  });
}

// endregion

// region Private API

/**
 * Perform initialization before any execution.
 *
 * @param {Object} ctx - cordova context object
 */
function init(ctx) {
  packageJsonFilePath = path.join(ctx.opts.projectRoot, 'plugins', ctx.opts.plugin.id, 'package.json');
}

/**
 * Check if we already executed this hook.
 *
 * @param {Object} ctx - cordova context
 * @return {Boolean} true if already executed; otherwise - false
 */
function isInstallationAlreadyPerformed(ctx) {
  var pathToInstallFlag = path.join(ctx.opts.projectRoot, 'plugins', ctx.opts.plugin.id, INSTALLATION_FLAG_FILE_NAME),
    isInstalled = false;
  try {
    var content = fs.readFileSync(pathToInstallFlag);
    isInstalled = true;
  } catch (err) {
  }

  return isInstalled;
}

/**
 * Create empty file - indicator, that we tried to install dependency modules after installation.
 * We have to do that, or this hook is gonna be called on any plugin installation.
 */
function createPluginInstalledFlag(ctx) {
  var pathToInstallFlag = path.join(ctx.opts.projectRoot, 'plugins', ctx.opts.plugin.id, INSTALLATION_FLAG_FILE_NAME);

  fs.closeSync(fs.openSync(pathToInstallFlag, 'w'));
}

// endregion

module.exports = function(ctx) {
  // exit if we already executed this hook once
  if (isInstallationAlreadyPerformed(ctx)) {
    return;
  }

  logger.header('CHCP Local Dev add-on checking dependencies:');

  init(ctx);
  installRequiredNodeModules(installModulesFromPackageJson);

  createPluginInstalledFlag(ctx);
};
<commit_msg>Fixed after_plugin_add hook<commit_after>/**
Hook is executed when plugin is added to the project.
It will check all necessary module dependencies and install the missing ones locally.
*/

var exec = require('child_process').exec,
  path = require('path'),
  fs = require('fs'),
  modules = ['read-package-json'],
  INSTALLATION_FLAG_FILE_NAME = '.installed',
  packageJsonFilePath;

// region NPM specific

/**
 * Discovers module dependencies in plugin's package.json and installs them.
 */
function installModulesFromPackageJson() {
  var readJson = require('read-package-json');
  readJson(packageJsonFilePath, console.error, false, function(err, data) {
    if (err) {
      printMsg('Can\'t read package.json file: ' + err);
      return;
    }

    var dependencies = data['dependencies'];
    if (dependencies) {
      for (var module in dependencies) {
        modules.push(module);
      }
      installRequiredNodeModules(function() {
        printMsg('All dependency modules are installed.');
      });
    }
  });
}

/**
 * Check if node package is installed.
 *
 * @param {String} moduleName
 * @return {Boolean} true if package already installed
 */
function isNodeModuleInstalled(moduleName) {
  var installed = true;
  try {
    var module = require(moduleName);
  } catch (err) {
    installed = false;
  }

  return installed;
}

/**
 * Install node module locally.
 * Basically, it runs 'npm install module_name'.
 *
 * @param {String} moduleName
 * @param {Callback(error)} callback
 */
function installNodeModule(moduleName, callback) {
  if (isNodeModuleInstalled(moduleName)) {
    callback(null);
    return;
  }
  printMsg('Can\'t find module ' + moduleName + ', running npm install');

  var cmd = 'npm install -D ' + moduleName;
  exec(cmd, function(err, stdout, stderr) {
    callback(err);
  });
}

/**
 * Install all required node packages.
 */
function installRequiredNodeModules(callback) {
  if (modules.length == 0) {
    callback();
    return;
  }

  var moduleName = modules.shift();
  installNodeModule(moduleName, function(err) {
    if (err) {
      printMsg('Failed to install module ' + moduleName + ':' + err);
      return;
    }

    printMsg('Module ' + moduleName + ' is installed');
    installRequiredNodeModules(callback);
  });
}

// endregion

// region Logging

function printHeader(msg) {
  console.log(msg);
}

function printMsg(msg) {
  console.log('    ' + msg);
}

// endregion

// region Private API

/**
 * Perform initialization before any execution.
 *
 * @param {Object} ctx - cordova context object
 */
function init(ctx) {
  packageJsonFilePath = path.join(ctx.opts.projectRoot, 'plugins', ctx.opts.plugin.id, 'package.json');
}

/**
 * Check if we already executed this hook.
 *
 * @param {Object} ctx - cordova context
 * @return {Boolean} true if already executed; otherwise - false
 */
function isInstallationAlreadyPerformed(ctx) {
  var pathToInstallFlag = path.join(ctx.opts.projectRoot, 'plugins', ctx.opts.plugin.id, INSTALLATION_FLAG_FILE_NAME),
    isInstalled = false;
  try {
    var content = fs.readFileSync(pathToInstallFlag);
    isInstalled = true;
  } catch (err) {
  }

  return isInstalled;
}

/**
 * Create empty file - indicator, that we tried to install dependency modules after installation.
 * We have to do that, or this hook is gonna be called on any plugin installation.
 */
function createPluginInstalledFlag(ctx) {
  var pathToInstallFlag = path.join(ctx.opts.projectRoot, 'plugins', ctx.opts.plugin.id, INSTALLATION_FLAG_FILE_NAME);

  fs.closeSync(fs.openSync(pathToInstallFlag, 'w'));
}

// endregion

module.exports = function(ctx) {
  // exit if we already executed this hook once
  if (isInstallationAlreadyPerformed(ctx)) {
    return;
  }

  printHeader('CHCP Local Dev add-on checking dependencies:');

  init(ctx);
  installRequiredNodeModules(installModulesFromPackageJson);

  createPluginInstalledFlag(ctx);
};
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import DocumentTitle from 'react-document-title'
import { isArray, forEach } from 'lodash'
import { browserHistory } from 'react-router'

import Datasets from '../../components/Datasets/Datasets'

const DISABLED_FILTERS = [ 'q', 'page', 'offset', 'limit' ]

export function _extractFilters(query) {
  let filters = []
  forEach(query, function(value, key) {
    if (DISABLED_FILTERS.includes(key)) {
      return
    }

    if (isArray(value)) {
      forEach(value, function(current) {
        filters.push({name: key, value: current})
      })
    } else {
      filters.push({name: key, value})
    }
  })

  return filters
}

export function parseQuery(query) {
  return {
    textInput: query.q,
    page: query.page || 1,
    filters: _extractFilters(query),
  }
}

function handleLocation(location) {
  console.log({ query: parseQuery(location.query), pathname: location.pathname })
  return { query: parseQuery(location.query), pathname: location.pathname }
}

class WrappedDatasets extends Component {
  constructor(props) {
    super(props)
    this.state = handleLocation(props.location)
  }

  componentDidMount() {
    this.handle = browserHistory.listen(location => {
      if (location.pathname !== '/datasets' && location.pathname !== '/records') return;
      if (location.action !== 'POP') return
      this.setState(handleLocation(location))
    })
  }

  componentWillUnmount() {
    this.handle()
  }

  render() {
    const { query, pathname } = this.state
    return (
      <DocumentTitle title={'Recherche jeu de données'}>
        <Datasets pathname={pathname} query={query}/>
      </DocumentTitle>
    )
  }
}

export default WrappedDatasets
<commit_msg>Remove console.log<commit_after>import React, { Component } from 'react'
import DocumentTitle from 'react-document-title'
import { isArray, forEach } from 'lodash'
import { browserHistory } from 'react-router'

import Datasets from '../../components/Datasets/Datasets'

const DISABLED_FILTERS = [ 'q', 'page', 'offset', 'limit' ]

export function _extractFilters(query) {
  let filters = []
  forEach(query, function(value, key) {
    if (DISABLED_FILTERS.includes(key)) {
      return
    }

    if (isArray(value)) {
      forEach(value, function(current) {
        filters.push({name: key, value: current})
      })
    } else {
      filters.push({name: key, value})
    }
  })

  return filters
}

export function parseQuery(query) {
  return {
    textInput: query.q,
    page: query.page || 1,
    filters: _extractFilters(query),
  }
}

function handleLocation(location) {
  return { query: parseQuery(location.query), pathname: location.pathname }
}

class WrappedDatasets extends Component {
  constructor(props) {
    super(props)
    this.state = handleLocation(props.location)
  }

  componentDidMount() {
    this.handle = browserHistory.listen(location => {
      if (location.pathname !== '/datasets' && location.pathname !== '/records') return;
      if (location.action !== 'POP') return
      this.setState(handleLocation(location))
    })
  }

  componentWillUnmount() {
    this.handle()
  }

  render() {
    const { query, pathname } = this.state
    return (
      <DocumentTitle title={'Recherche jeu de données'}>
        <Datasets pathname={pathname} query={query}/>
      </DocumentTitle>
    )
  }
}

export default WrappedDatasets
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at https://raw.github.com/mozilla/butter/master/LICENSE */

define( [ "core/eventmanager", "core/media", "util/sanitizer" ],
        function( EventManager, Media, Sanitizer ) {

  var __butterStorage = window.localStorage;

  function Project( butter ) {

    var _this = this,
        _id, _name, _template, _description, _dataObject,
        _publishUrl, _iframeUrl, _remixedFrom, _remixedFromUrl, _makeid,

        _tags = [],

        // Whether or not a save to server is required (project data has changed)
        _isDirty = false,

        // Whether or not a backup to storage is required (project data has changed)
        _needsBackup = false,

        // Whether or not the project is saved to the db and published.
        // The notion of "saving" to consumers of this code is unware of
        // the save vs. publish distinction. As such, we use isSaved externally
        // and isPublished internally, where Publish follows Save and is
        // more correct.
        _isPublished = false,

        // How often to backup data in ms. If 0, no backups are done.
        _backupIntervalMS = butter.config.value( "backupInterval" )|0,

        // Interval for backups, starts first time user clicks Save.
        _backupInterval = -1,

        _thumbnail = location.protocol + "//" + location.host + "/resources/icons/fb-logo.png";

    function invalidate() {
      // Project is dirty, needs save, backup
      _isDirty = true;
      _needsBackup = true;

      // If the project has an id (if it was saved), start backups again
      // since they may have been stopped if LocalStorage size limits were
      // exceeded.
      if ( _id ) {
        startBackups();
      }

      // Let consumers know that the project changed
      _this.dispatch( "projectchanged" );
    }

    // Manage access to project properties.  Some we only want
    // to be read (and managed by db/butter), others we want to
    // affect save logic.
    Object.defineProperties( _this, {
      "id": {
        get: function() {
          return _id;
        },
        enumerable: true
      },

      "name": {
        get: function() {
          return _name;
        },
        set: function( value ) {
          if ( value !== _name ) {
            _name = value;
            invalidate();
          }
        },
        enumerable: true
      },

      "template": {
        get: function() {
          return _template;
        },
        set: function( value ) {
          if ( value !== _template ) {
            _template = value;
            invalidate();
          }
        },
        enumerable: true
      },

      "description": {
        get: function() {
          return _description;
        },
        set: function( value ) {
          if ( value !== _description ) {
            _description = value;
            invalidate();
          }
        },
        enumerable: true
      },

      "thumbnail": {
        set: function( val ) {
          _thumbnail = val;
          invalidate();
        },
        get: function() {
          return _thumbnail;
        },
        enumerable: true
       },

      "tags": {
        set: function( val ) {
          _tags = val.split( "," ).map(function( v ) {
            return v.trim();
          });
          invalidate();
        },
        get: function() {
          return _tags;
        },
        enumerable: true
      },

      "makeid": {
        get: function() {
          return _makeid;
        },
        enumerable: true
      },

      "data": {
        get: function() {
          // Memoize value, since it doesn't always change
          if ( !_dataObject || _isDirty ) {
            var exportJSONMedia = [];
            for ( var i = 0; i < butter.media.length; ++i ) {
              exportJSONMedia.push( butter.media[ i ].json );
            }
            _dataObject = {
              targets: butter.serializeTargets(),
              media: exportJSONMedia
            };
          }
          return _dataObject;
        },
        enumerable: true
      },

      "publishUrl": {
        get: function() {
          return _publishUrl;
        },
        enumerable: true
      },

      "remixedFromUrl": {
        get: function() {
          return _remixedFromUrl;
        },
        enumerable: true
      },

      "iframeUrl": {
        get: function() {
          return _iframeUrl;
        },
        enumerable: true
      },

      // Have changes made it to the db and been published?
      "isSaved": {
        get: function() {
          return _isPublished && !_isDirty;
        },
        enumerable: true
      }

    });

    EventManager.extend( _this );

    // Once saved data is loaded, and media is ready, we start to care about
    // the app's data states changing, and want to track.
    butter.listen( "mediaready", function mediaReady() {
      butter.unlisten( "mediaready", mediaReady );

      // Listen for changes in the project data so we know when to save.
      [ "mediacontentchanged",
        "mediaclipadded",
        "mediaclipremoved",
        "mediatargetchanged",
        "trackadded",
        "trackremoved",
        "tracktargetchanged",
        "trackeventadded",
        "trackeventremoved",
        "trackeventupdated"
      ].forEach( function( event ) {
        butter.listen( event, invalidate );
      });
    });

    function startBackups() {
      if ( _backupInterval === -1 && _backupIntervalMS > 0 ) {
        _needsBackup = true;
        _backupInterval = setInterval( backupData, _backupIntervalMS );
        // Do a backup now so we don't miss anything
        backupData();
      }
    }

    // Import project data from JSON (i.e., created with project.export())
    _this.import = function( json ) {
      var oldTarget, targets, targetData,
          mediaData, media, m, i, l;
      // If JSON, convert to Object
      if ( typeof json === "string" ) {
        try {
          json = JSON.parse( json );
        } catch( e ) {
          return;
        }
      }

      if ( json.projectID ) {
        _id = json.projectID;
        _isPublished = true;
      }

      if ( json.name ) {
        // replace HTML entities ("&", etc), possibly introduced by
        // templating rules being applied to project metadata, with
        // their plain form counterparts ("&", etc).
        _name = Sanitizer.reconstituteHTML( json.name );
      }

      if ( json.template ) {
        _template = json.template;
      }

      if ( json.makeid ) {
        _makeid = json.makeid;
      }

      if ( json.description ) {
        _description = json.description;
      }

      if ( json.tags ) {
        _tags = json.tags;
      }

      if ( json.thumbnail ) {
        _thumbnail = json.thumbnail;
      }

      if ( json.publishUrl ) {
        _publishUrl = json.publishUrl;
      }

      if ( json.iframeUrl ) {
        _iframeUrl = json.iframeUrl;
      }

      if ( json.remixedFrom ) {
        _remixedFrom = json.remixedFrom;
      }

      _remixedFromUrl = json.remixedFromUrl;

      targets = json.targets;
      if ( targets && Array.isArray( targets ) ) {
        for ( i = 0, l = targets.length; i < l; ++i ) {
          targetData = targets[ i ];
          oldTarget = butter.getTargetByType( "elementID", targetData.element );
          // Only add target if it's not already added.
          if ( !oldTarget ) {
            butter.addTarget( targetData );
          } else {
            // If it was already added, just update its json.
            oldTarget.json = targetData;
          }
        }
      } else if ( console ) {
        console.warn( "Ignored imported target data. Must be in an Array." );
      }

      media = json.media;
      if ( media && Array.isArray( media ) ) {
        for ( i = 0, l = media.length; i < l; ++i ) {
          mediaData = media[ i ];
          m = butter.getMediaByType( "target", mediaData.target );

          if ( !m ) {
            m = new Media();
            m.json = mediaData;
            butter.addMedia( m );
          } else {
            m.json = mediaData;
          }
        }
      } else if ( console ) {
        console.warn( "Ignored imported media data. Must be in an Array." );
      }

      // If this is a restored backup, restart backups now (vs. on first save)
      // since the user indicated they want it.
      if( json.backupDate ) {
        startBackups();
      }

    };

    // Export project data as JSON string (e.g., for use with project.import())
    _this.export = function() {
      return JSON.stringify( _this.data );
    };

    // Expose backupData() to make testing possible
    var backupData = _this.backupData = function() {
      // If the project isn't different from last time, or if it's known
      // to not fit in storage, don't bother trying.
      if ( !_needsBackup ) {
        return;
      }
      // Save everything but the project id
      var data = _this.data;
      data.name = _name;
      data.template = _template;
      data.author = butter.cornfield.username();
      data.description = _description;
      data.tags = _tags.join( "," );
      data.thumbnail = _thumbnail;
      data.backupDate = Date.now();
      try {
        __butterStorage.setItem( "butter-backup-project", JSON.stringify( data ) );
        _needsBackup = false;
      } catch ( e ) {
        // Deal with QUOTA_EXCEEDED_ERR when localStorage is full.
        // Stop the backup loop because we know we can't save anymore until the
        // user changes something about the project.
        clearInterval( _backupInterval );
        _backupInterval = -1;

        // Purge the saved project, since it won't be complete.
        __butterStorage.removeItem( "butter-backup-project" );

        console.warn( "Warning: Popcorn Maker LocalStorage quota exceeded. Stopping automatic backup. Will be restarted when project changes again." );
      }
    };

    // Save and Publish a project.  Saving only happens if project data needs
    // to be saved (i.e., it has been changed since last save, or was never
    // saved before).
    _this.save = function( callback ) {
      if ( !callback ) {
        callback = function() {};
      }

      // Don't save if there is nothing new to save.
      if ( _this.isSaved ) {
        callback({ error: "okay" });
        return;
      }

      var projectData = {
        id: _id,
        name: _name,
        template: _template,
        author: butter.cornfield.username(),
        description: _description,
        thumbnail: _thumbnail,
        data: _this.data,
        tags: _this.tags,
        remixedFrom: _remixedFrom,
        makeid: _makeid
      };

      // Save to local storage first in case network is down.
      backupData();

      // Save to db, then publish
      butter.cornfield.save( _id, projectData, function( e ) {
        if ( e.error === "okay" ) {
          // Since we've now fully saved, blow away autosave backup
          _isDirty = false;
          __butterStorage.removeItem( "butter-backup-project" );

          // Start keeping backups in storage, if not already started
          startBackups();

          // Keep any URLs generated from store in sync with the project.
          if ( e.project ) {
            _thumbnail = e.project.thumbnail;
          }

          // If this was a first save, grab id generated by server and store
          if ( !_id ) {
            _id = e.projectId;
          }

          // Now Publish and get URLs for embed
          butter.cornfield.publish( _id, function( e ) {
            if ( e.error === "okay" ) {
              // Save + Publish is OK
              _isPublished = true;
              _publishUrl = e.publishUrl;
              _iframeUrl = e.iframeUrl;
            }

            // Let consumers know that the project is now saved;
            _this.dispatch( "projectsaved" );

            if ( window.history.replaceState ) {
              window.history.replaceState({}, "", "/editor/" + _id + "/edit" );
            }

            callback( e );
          });
        } else {
          callback( e );
        }
      });
    };
  }

  // Check for an existing project that was autosaved but not saved.
  // Returns project backup data as JS object if found, otherwise null.
  // NOTE: caller must create a new Project object and call import.
  Project.checkForBackup = function( butter, callback ) {
    // See if we already have a project autosaved from another session.
    var projectBackup, backupDate;

    // For testing purposes, we can skip backup recovery
    if ( butter.config.value( "recover" ) === "purge" ) {
      callback( null, null );
      return;
    }

    try {
      projectBackup = __butterStorage.getItem( "butter-backup-project" );
      projectBackup = JSON.parse( projectBackup );

      // Delete since user can save if he/she wants.
      __butterStorage.removeItem( "butter-backup-project" );

      if ( projectBackup ) {
        backupDate = projectBackup.backupDate;
      }
    } catch( e ) { }

    callback( projectBackup, backupDate );
  };

  return Project;
});
<commit_msg>Fix Bug 884541 - Force old projects into a dirty state to encourage a republish for new embed content<commit_after>/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at https://raw.github.com/mozilla/butter/master/LICENSE */

define( [ "core/eventmanager", "core/media", "util/sanitizer" ],
        function( EventManager, Media, Sanitizer ) {

  var __butterStorage = window.localStorage;

  function Project( butter ) {

    var _this = this,
        _id, _name, _template, _description, _dataObject,
        _publishUrl, _iframeUrl, _remixedFrom, _remixedFromUrl, _makeid,

        _tags = [],

        // Whether or not a save to server is required (project data has changed)
        _isDirty = false,

        // Whether or not a backup to storage is required (project data has changed)
        _needsBackup = false,

        // Whether or not the project is saved to the db and published.
        // The notion of "saving" to consumers of this code is unware of
        // the save vs. publish distinction. As such, we use isSaved externally
        // and isPublished internally, where Publish follows Save and is
        // more correct.
        _isPublished = false,

        // How often to backup data in ms. If 0, no backups are done.
        _backupIntervalMS = butter.config.value( "backupInterval" )|0,

        // Interval for backups, starts first time user clicks Save.
        _backupInterval = -1,

        _thumbnail = location.protocol + "//" + location.host + "/resources/icons/fb-logo.png";

    function invalidate() {
      // Project is dirty, needs save, backup
      _isDirty = true;
      _needsBackup = true;

      // If the project has an id (if it was saved), start backups again
      // since they may have been stopped if LocalStorage size limits were
      // exceeded.
      if ( _id ) {
        startBackups();
      }

      // Let consumers know that the project changed
      _this.dispatch( "projectchanged" );
    }

    // Manage access to project properties.  Some we only want
    // to be read (and managed by db/butter), others we want to
    // affect save logic.
    Object.defineProperties( _this, {
      "id": {
        get: function() {
          return _id;
        },
        enumerable: true
      },

      "name": {
        get: function() {
          return _name;
        },
        set: function( value ) {
          if ( value !== _name ) {
            _name = value;
            invalidate();
          }
        },
        enumerable: true
      },

      "template": {
        get: function() {
          return _template;
        },
        set: function( value ) {
          if ( value !== _template ) {
            _template = value;
            invalidate();
          }
        },
        enumerable: true
      },

      "description": {
        get: function() {
          return _description;
        },
        set: function( value ) {
          if ( value !== _description ) {
            _description = value;
            invalidate();
          }
        },
        enumerable: true
      },

      "thumbnail": {
        set: function( val ) {
          _thumbnail = val;
          invalidate();
        },
        get: function() {
          return _thumbnail;
        },
        enumerable: true
       },

      "tags": {
        set: function( val ) {
          _tags = val.split( "," ).map(function( v ) {
            return v.trim();
          });
          invalidate();
        },
        get: function() {
          return _tags;
        },
        enumerable: true
      },

      "makeid": {
        get: function() {
          return _makeid;
        },
        enumerable: true
      },

      "data": {
        get: function() {
          // Memoize value, since it doesn't always change
          if ( !_dataObject || _isDirty ) {
            var exportJSONMedia = [];
            for ( var i = 0; i < butter.media.length; ++i ) {
              exportJSONMedia.push( butter.media[ i ].json );
            }
            _dataObject = {
              targets: butter.serializeTargets(),
              media: exportJSONMedia
            };
          }
          return _dataObject;
        },
        enumerable: true
      },

      "publishUrl": {
        get: function() {
          return _publishUrl;
        },
        enumerable: true
      },

      "remixedFromUrl": {
        get: function() {
          return _remixedFromUrl;
        },
        enumerable: true
      },

      "iframeUrl": {
        get: function() {
          return _iframeUrl;
        },
        enumerable: true
      },

      // Have changes made it to the db and been published?
      "isSaved": {
        get: function() {
          return _isPublished && !_isDirty;
        },
        enumerable: true
      }

    });

    EventManager.extend( _this );

    // Once saved data is loaded, and media is ready, we start to care about
    // the app's data states changing, and want to track.
    butter.listen( "mediaready", function mediaReady() {
      butter.unlisten( "mediaready", mediaReady );

      // Listen for changes in the project data so we know when to save.
      [ "mediacontentchanged",
        "mediaclipadded",
        "mediaclipremoved",
        "mediatargetchanged",
        "trackadded",
        "trackremoved",
        "tracktargetchanged",
        "trackeventadded",
        "trackeventremoved",
        "trackeventupdated"
      ].forEach( function( event ) {
        butter.listen( event, invalidate );
      });
    });

    function startBackups() {
      if ( _backupInterval === -1 && _backupIntervalMS > 0 ) {
        _needsBackup = true;
        _backupInterval = setInterval( backupData, _backupIntervalMS );
        // Do a backup now so we don't miss anything
        backupData();
      }
    }

    // Import project data from JSON (i.e., created with project.export())
    _this.import = function( json ) {
      var oldTarget, targets, targetData,
          mediaData, media, m, i, l;
      // If JSON, convert to Object
      if ( typeof json === "string" ) {
        try {
          json = JSON.parse( json );
        } catch( e ) {
          return;
        }
      }

      if ( json.projectID ) {
        _id = json.projectID;
        _isPublished = true;
      }

      if ( json.name ) {
        // replace HTML entities ("&", etc), possibly introduced by
        // templating rules being applied to project metadata, with
        // their plain form counterparts ("&", etc).
        _name = Sanitizer.reconstituteHTML( json.name );
      }

      if ( json.template ) {
        _template = json.template;
      }

      if ( json.makeid ) {
        _makeid = json.makeid;
      }

      if ( json.description ) {
        _description = json.description;
      }

      if ( json.tags ) {
        _tags = json.tags;
      }

      if ( json.thumbnail ) {
        _thumbnail = json.thumbnail;
      }

      if ( json.publishUrl ) {
        _publishUrl = json.publishUrl;
      }

      if ( json.iframeUrl ) {
        _iframeUrl = json.iframeUrl;
      }

      if ( json.remixedFrom ) {
        _remixedFrom = json.remixedFrom;
      }

      _remixedFromUrl = json.remixedFromUrl;

      targets = json.targets;
      if ( targets && Array.isArray( targets ) ) {
        for ( i = 0, l = targets.length; i < l; ++i ) {
          targetData = targets[ i ];
          oldTarget = butter.getTargetByType( "elementID", targetData.element );
          // Only add target if it's not already added.
          if ( !oldTarget ) {
            butter.addTarget( targetData );
          } else {
            // If it was already added, just update its json.
            oldTarget.json = targetData;
          }
        }
      } else if ( console ) {
        console.warn( "Ignored imported target data. Must be in an Array." );
      }

      media = json.media;
      if ( media && Array.isArray( media ) ) {
        for ( i = 0, l = media.length; i < l; ++i ) {
          mediaData = media[ i ];
          m = butter.getMediaByType( "target", mediaData.target );

          if ( !m ) {
            m = new Media();
            m.json = mediaData;
            butter.addMedia( m );
          } else {
            m.json = mediaData;
          }
        }
      } else if ( console ) {
        console.warn( "Ignored imported media data. Must be in an Array." );
      }

      // If this is a restored backup, restart backups now (vs. on first save)
      // since the user indicated they want it.
      if ( json.backupDate ) {
        startBackups();
      }

      // This is an old project. Force it into a dirty state to encourage resaving.
      if ( _isPublished && !_makeid ) {
        _isDirty = true;
      }

    };

    // Export project data as JSON string (e.g., for use with project.import())
    _this.export = function() {
      return JSON.stringify( _this.data );
    };

    // Expose backupData() to make testing possible
    var backupData = _this.backupData = function() {
      // If the project isn't different from last time, or if it's known
      // to not fit in storage, don't bother trying.
      if ( !_needsBackup ) {
        return;
      }
      // Save everything but the project id
      var data = _this.data;
      data.name = _name;
      data.template = _template;
      data.author = butter.cornfield.username();
      data.description = _description;
      data.tags = _tags.join( "," );
      data.thumbnail = _thumbnail;
      data.backupDate = Date.now();
      try {
        __butterStorage.setItem( "butter-backup-project", JSON.stringify( data ) );
        _needsBackup = false;
      } catch ( e ) {
        // Deal with QUOTA_EXCEEDED_ERR when localStorage is full.
        // Stop the backup loop because we know we can't save anymore until the
        // user changes something about the project.
        clearInterval( _backupInterval );
        _backupInterval = -1;

        // Purge the saved project, since it won't be complete.
        __butterStorage.removeItem( "butter-backup-project" );

        console.warn( "Warning: Popcorn Maker LocalStorage quota exceeded. Stopping automatic backup. Will be restarted when project changes again." );
      }
    };

    // Save and Publish a project.  Saving only happens if project data needs
    // to be saved (i.e., it has been changed since last save, or was never
    // saved before).
    _this.save = function( callback ) {
      if ( !callback ) {
        callback = function() {};
      }

      // Don't save if there is nothing new to save.
      if ( _this.isSaved ) {
        callback({ error: "okay" });
        return;
      }

      var projectData = {
        id: _id,
        name: _name,
        template: _template,
        author: butter.cornfield.username(),
        description: _description,
        thumbnail: _thumbnail,
        data: _this.data,
        tags: _this.tags,
        remixedFrom: _remixedFrom,
        makeid: _makeid
      };

      // Save to local storage first in case network is down.
      backupData();

      // Save to db, then publish
      butter.cornfield.save( _id, projectData, function( e ) {
        if ( e.error === "okay" ) {
          // Since we've now fully saved, blow away autosave backup
          _isDirty = false;
          __butterStorage.removeItem( "butter-backup-project" );

          // Start keeping backups in storage, if not already started
          startBackups();

          // Keep any URLs generated from store in sync with the project.
          if ( e.project ) {
            _thumbnail = e.project.thumbnail;
          }

          // If this was a first save, grab id generated by server and store
          if ( !_id ) {
            _id = e.projectId;
          }

          // Now Publish and get URLs for embed
          butter.cornfield.publish( _id, function( e ) {
            if ( e.error === "okay" ) {
              // Save + Publish is OK
              _isPublished = true;
              _publishUrl = e.publishUrl;
              _iframeUrl = e.iframeUrl;
            }

            // Let consumers know that the project is now saved;
            _this.dispatch( "projectsaved" );

            if ( window.history.replaceState ) {
              window.history.replaceState({}, "", "/editor/" + _id + "/edit" );
            }

            callback( e );
          });
        } else {
          callback( e );
        }
      });
    };
  }

  // Check for an existing project that was autosaved but not saved.
  // Returns project backup data as JS object if found, otherwise null.
  // NOTE: caller must create a new Project object and call import.
  Project.checkForBackup = function( butter, callback ) {
    // See if we already have a project autosaved from another session.
    var projectBackup, backupDate;

    // For testing purposes, we can skip backup recovery
    if ( butter.config.value( "recover" ) === "purge" ) {
      callback( null, null );
      return;
    }

    try {
      projectBackup = __butterStorage.getItem( "butter-backup-project" );
      projectBackup = JSON.parse( projectBackup );

      // Delete since user can save if he/she wants.
      __butterStorage.removeItem( "butter-backup-project" );

      if ( projectBackup ) {
        backupDate = projectBackup.backupDate;
      }
    } catch( e ) { }

    callback( projectBackup, backupDate );
  };

  return Project;
});
<|endoftext|>


<commit_before>/*
 * Interface Test
 */
define([ '../../lib/interface' ], function (Interface) {
  QUnit.test("Interface Implementation Validator", function () {
    var intf;

    intf = {
      Interface : {
        validate : function () {
        },
        match : function () {
        }
      }
    };

    QUnit.equal(Interface(intf, Interface, 'fm'), '', 'self-matching');

    intf = {};

    QUnit.notEqual(Interface(intf), '', "empty interface");

    intf = {
      Interface : {}
    };

    QUnit.equal(Interface(intf), '', "minimal interface");

    intf = {
      Interface : []
    };

    // TODO: implement array interfaces
    //
    // QUnit.notEqual(Interface(intf), '', "subminimal array interface");

    intf = {
      Interface : {
        asd : function () {
        },
      }
    };

    QUnit.equal(Interface(intf), '', "interface with function");

    intf = {
      Interface : {
        otherinterface : intf,
        funky : function () {
        }
      }
    };

    QUnit.equal(Interface(intf), '', "nested Interfaces");

    intf.Interface.otherinterface = intf;

    QUnit.equal(Interface(intf), '', "directly infinitely nested Interfaces");

    intf = {
      Interface : {
        otherinterface : {
          Interface : {
            firstinterface : undefined
          }
        },
        funky : function () {
        }
      }
    };

    intf.Interface.otherinterface.Interface.firstinterface = intf;

    QUnit.equal(Interface(intf), '', "second order infinitely nested Interfaces");

    intf.Interface.otherinterface.Interface.error = {};

    QUnit.notEqual(Interface(intf), '', "second order infinitely nested Interfaces with invalid data type");

    intf = {
      Interface : {
        asd : 0
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with number");

    intf = {
      Interface : {
        asd : undefined
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with undefined");

    intf = {
      Interface : {
        asd : "asd"
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with string");

    intf = {
      Interface : {
        asd : /asd/g
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with regexp");

    intf = {
      Interface : {
        asd : true
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with bool");

    intf = {
      Interface : {
        asd : [ 4, 8, 15, 16, 23, 42 ]
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with array");

    intf = {
      Interface : {
        asd : {}
      }
    };

    QUnit.notEqual(Interface(intf), '', "invalid nesting");

    intf = {
      Interface : {
        intf : intf
      }
    };

    QUnit.notEqual(Interface(intf), '', "invalid nesting 2");

    intf = {
      Interface : {},
      ASD : 0
    };

    QUnit.equal(Interface(intf), '', "number constant");

    intf = {
      Interface : {},
      ASd : 0
    };

    QUnit.notEqual(Interface(intf), '', "constant not all caps 1");

    intf = {
      Interface : {},
      asd : 0
    };

    QUnit.notEqual(Interface(intf), '', "constant not all caps 2");

    intf = {
      Interface : {},
      AS_D : 0
    };

    QUnit.notEqual(Interface(intf), '', "constant not all caps 3");

    intf = {
      Interface : {},
      A : "ASD",
      B : true,
      C : [ 0, "dux", {
        F : 5
      } ],
      D : undefined,
      E : /imaregex/
    };

    QUnit.equal(Interface(intf), '', "valid constants");

    intf = {
      Interface : {},
      A : function () {
      }
    };

    QUnit.notEqual(Interface(intf), '', "function as constant");
  });

  QUnit.test("Interface Implementation Matcher", function () {
    var intf, obj, Obj;

    intf = {};
    obj = {};

    QUnit.notEqual(Interface(), '', "missing arguments");
    QUnit.notEqual(Interface.match(intf), '', "missing obj");
    QUnit.notEqual(Interface(undefined, obj), '', "missing intf");

    QUnit.notEqual(Interface(intf, obj, 'i'), '', "interface validator invocation: missing Interface member");
    intf = {
      Interface : {
        asd : undefined
      }
    };
    QUnit.notEqual(Interface(intf, obj, 'i'), '', "interface validator invocation: invalid type");

    intf = {
      Interface : {}
    };

    QUnit.equal(Interface(intf, obj), '', "valid empty interface match");
    QUnit.equal(Interface(intf, obj, 'f'), '', "option 'f'");
    QUnit.equal(Interface(intf, obj, 'm'), '', "option 'm'");
    QUnit.equal(Interface(intf, obj, 'r'), '', "option 'r' without subinterfaces");

    obj = {
      asd : 5
    };

    QUnit.equal(Interface(intf, obj), '', "default option with additional member");
    QUnit.notEqual(Interface(intf, obj, 'm'), '', "option 'm' with member");
    QUnit.equal(Interface(intf, obj, 'f'), '', "option 'f' with member");

    obj = {
      asd : function () {
      }
    };

    QUnit.notEqual(Interface(intf, obj, 'f'), '', "option 'f' with function");
    QUnit.equal(Interface(intf, obj, 'm'), '', "option 'm' with function");

    intf = {
      Interface : {
        asd : function () {
        }
      }
    };

    obj = {};

    console.log("JERE");
    QUnit.notEqual(Interface(intf, obj, 'i'), '', "missing function");
    console.log("HERE");

    obj = {
      asd : function () {
      }
    };

    QUnit.equal(Interface(intf, obj), '', "object with function");

    obj = {
      asd : "5"
    };

    QUnit.notEqual(Interface(intf, obj), '', "object with member of wrong type");

    Obj = function () {
      this.asd = function () {
      };
      return this;
    };

    obj = new Obj();

    QUnit.notEqual(Interface(intf, Obj), '', "class with local function");
    QUnit.equal(Interface(intf, obj), '', "instance with local function");

    Obj = function () {
      return this;
    };
    Obj.prototype.asd = function () {
    };

    obj = new Obj();

    QUnit.equal(Interface(intf, obj), '', "instance with prototype function");
    QUnit.equal(Interface(intf, Obj), '', "class with prototype function");

    intf = {
      Interface : {
        intf : {
          Interface : {
            asd : function () {
            }
          }
        }
      }
    };

    obj = {};

    QUnit.notEqual(Interface(intf, obj), '', "nested interface: missing subinterface");

    obj = {
      intf : {}
    };

    QUnit.equal(Interface(intf, obj, 'i'), '', "nested interface: non-recursive false positive");
    QUnit.equal(Interface(intf, obj, 'i'), '', "nested interface: non-recursive false positive");

    obj.intf.asd = function () {
    };
    QUnit.equal(Interface(intf, obj, 'r'), '', "nested interface: recursive success");

    intf = {
      Interface : {
        sub : undefined
      }
    };
    intf.Interface.sub = intf;

    obj = {
      sub : undefined
    };
    obj.sub = obj;

    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, first order (both)");

    obj.sub = {
      sub : obj
    };

    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, second order (obj)");

    intf.Interface.sub = {
      Interface : {
        sub : intf
      }
    };

    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, second order (both)");

    obj.sub = obj;
    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, second order (intf)");

    intf = {
      Interface : {
        asd : {
          Interface : {
            dsa : undefined
          }
        }
      }
    };
    intf.Interface.asd.Interface.dsa = intf;

    obj = {
      asd : undefined,
      dsa : undefined
    };
    obj.asd = obj.dsa = obj;

    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, multiple interface matching");

    obj.dsa = undefined;
    QUnit.notEqual(Interface(intf, obj, 'r'), '', "infinite recursion, multiple interfaces, nesting depth test");
  });
});
<commit_msg>interface.js: Extends validation tests added<commit_after>/*
 * Interface Test
 */
define([ '../../lib/interface' ], function (Interface) {
  QUnit.test("Interface Implementation Validator", function () {
    var intf;

    intf = {
      Interface : {
        validate : function () {
        },
        match : function () {
        }
      }
    };

    QUnit.equal(Interface(intf, Interface, 'fm'), '', 'self-matching');

    intf = {};

    QUnit.notEqual(Interface(intf), '', "empty interface");

    intf = {
      Interface : {}
    };

    QUnit.equal(Interface(intf), '', "minimal interface");

    intf = {
      Interface : []
    };

    // TODO: implement array interfaces
    //
    // QUnit.notEqual(Interface(intf), '', "subminimal array interface");

    intf = {
      Interface : {
        asd : function () {
        },
      }
    };

    QUnit.equal(Interface(intf), '', "interface with function");

    intf = {
      Interface : {
        otherinterface : intf,
        funky : function () {
        }
      }
    };

    QUnit.equal(Interface(intf), '', "nested Interfaces");

    intf.Interface.otherinterface = intf;

    QUnit.equal(Interface(intf), '', "directly infinitely nested Interfaces");

    intf = {
      Interface : {
        otherinterface : {
          Interface : {
            firstinterface : undefined
          }
        },
        funky : function () {
        }
      }
    };

    intf.Interface.otherinterface.Interface.firstinterface = intf;

    QUnit.equal(Interface(intf), '', "second order infinitely nested Interfaces");

    intf.Interface.otherinterface.Interface.error = {};

    QUnit.notEqual(Interface(intf), '', "second order infinitely nested Interfaces with invalid data type");

    intf = {
      Interface : {
        asd : 0
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with number");

    intf = {
      Interface : {
        asd : undefined
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with undefined");

    intf = {
      Interface : {
        asd : "asd"
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with string");

    intf = {
      Interface : {
        asd : /asd/g
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with regexp");

    intf = {
      Interface : {
        asd : true
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with bool");

    intf = {
      Interface : {
        asd : [ 4, 8, 15, 16, 23, 42 ]
      }
    };

    QUnit.notEqual(Interface(intf), '', "Interface with array");

    intf = {
      Interface : {
        asd : {}
      }
    };

    QUnit.notEqual(Interface(intf), '', "invalid nesting");

    intf = {
      Interface : {
        intf : intf
      }
    };

    QUnit.notEqual(Interface(intf), '', "invalid nesting 2");

    intf = {
      Interface : {},
      ASD : 0
    };

    QUnit.equal(Interface(intf), '', "number constant");

    intf = {
      Interface : {},
      ASd : 0
    };

    QUnit.notEqual(Interface(intf), '', "constant not all caps 1");

    intf = {
      Interface : {},
      asd : 0
    };

    QUnit.notEqual(Interface(intf), '', "constant not all caps 2");

    intf = {
      Interface : {},
      AS_D : 0
    };

    QUnit.notEqual(Interface(intf), '', "constant not all caps 3");

    intf = {
      Interface : {},
      A : "ASD",
      B : true,
      C : [ 0, "dux", {
        F : 5
      } ],
      D : undefined,
      E : /imaregex/
    };

    QUnit.equal(Interface(intf), '', "valid constants");

    intf = {
      Interface : {},
      A : function () {
      }
    };

    QUnit.notEqual(Interface(intf), '', "function as constant");

    intf = {
      Interface : {},
      Extends : {
        Interface : {}
      }
    };

    QUnit.notEqual(Interface(intf), '', 'Extends is no array');

    intf = {
      Interface : {},
      Extends : []
    };

    console.log(Interface(intf));

    QUnit.equal(Interface(intf), '', 'Extends is empty');

    intf = {
      Interface : {},
      Extends : [ {
        Interface : {}
      } ]
    };

    QUnit.equal(Interface(intf), '', 'Extends is minimal');

    intf.Extends.push(intf);
    QUnit.equal(Interface(intf), '', 'Extends is recursively nested');

    intf = {
      Interface : {},
      Extends : [ {} ]
    };

    QUnit.notEqual(Interface(intf), '', 'Extends contains invalid Interface');

  });

  QUnit.test("Interface Implementation Matcher", function () {
    var intf, obj, Obj;

    intf = {};
    obj = {};

    QUnit.notEqual(Interface(), '', "missing arguments");
    QUnit.notEqual(Interface.match(intf), '', "missing obj");
    QUnit.notEqual(Interface(undefined, obj), '', "missing intf");

    QUnit.notEqual(Interface(intf, obj, 'i'), '', "interface validator invocation: missing Interface member");
    intf = {
      Interface : {
        asd : undefined
      }
    };
    QUnit.notEqual(Interface(intf, obj, 'i'), '', "interface validator invocation: invalid type");

    intf = {
      Interface : {}
    };

    QUnit.equal(Interface(intf, obj), '', "valid empty interface match");
    QUnit.equal(Interface(intf, obj, 'f'), '', "option 'f'");
    QUnit.equal(Interface(intf, obj, 'm'), '', "option 'm'");
    QUnit.equal(Interface(intf, obj, 'r'), '', "option 'r' without subinterfaces");

    obj = {
      asd : 5
    };

    QUnit.equal(Interface(intf, obj), '', "default option with additional member");
    QUnit.notEqual(Interface(intf, obj, 'm'), '', "option 'm' with member");
    QUnit.equal(Interface(intf, obj, 'f'), '', "option 'f' with member");

    obj = {
      asd : function () {
      }
    };

    QUnit.notEqual(Interface(intf, obj, 'f'), '', "option 'f' with function");
    QUnit.equal(Interface(intf, obj, 'm'), '', "option 'm' with function");

    intf = {
      Interface : {
        asd : function () {
        }
      }
    };

    obj = {};

    console.log("JERE");
    QUnit.notEqual(Interface(intf, obj, 'i'), '', "missing function");
    console.log("HERE");

    obj = {
      asd : function () {
      }
    };

    QUnit.equal(Interface(intf, obj), '', "object with function");

    obj = {
      asd : "5"
    };

    QUnit.notEqual(Interface(intf, obj), '', "object with member of wrong type");

    Obj = function () {
      this.asd = function () {
      };
      return this;
    };

    obj = new Obj();

    QUnit.notEqual(Interface(intf, Obj), '', "class with local function");
    QUnit.equal(Interface(intf, obj), '', "instance with local function");

    Obj = function () {
      return this;
    };
    Obj.prototype.asd = function () {
    };

    obj = new Obj();

    QUnit.equal(Interface(intf, obj), '', "instance with prototype function");
    QUnit.equal(Interface(intf, Obj), '', "class with prototype function");

    intf = {
      Interface : {
        intf : {
          Interface : {
            asd : function () {
            }
          }
        }
      }
    };

    obj = {};

    QUnit.notEqual(Interface(intf, obj), '', "nested interface: missing subinterface");

    obj = {
      intf : {}
    };

    QUnit.equal(Interface(intf, obj, 'i'), '', "nested interface: non-recursive false positive");
    QUnit.equal(Interface(intf, obj, 'i'), '', "nested interface: non-recursive false positive");

    obj.intf.asd = function () {
    };
    QUnit.equal(Interface(intf, obj, 'r'), '', "nested interface: recursive success");

    intf = {
      Interface : {
        sub : undefined
      }
    };
    intf.Interface.sub = intf;

    obj = {
      sub : undefined
    };
    obj.sub = obj;

    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, first order (both)");

    obj.sub = {
      sub : obj
    };

    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, second order (obj)");

    intf.Interface.sub = {
      Interface : {
        sub : intf
      }
    };

    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, second order (both)");

    obj.sub = obj;
    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, second order (intf)");

    intf = {
      Interface : {
        asd : {
          Interface : {
            dsa : undefined
          }
        }
      }
    };
    intf.Interface.asd.Interface.dsa = intf;

    obj = {
      asd : undefined,
      dsa : undefined
    };
    obj.asd = obj.dsa = obj;

    QUnit.equal(Interface(intf, obj, 'r'), '', "infinite recursion, multiple interface matching");

    obj.dsa = undefined;
    QUnit.notEqual(Interface(intf, obj, 'r'), '', "infinite recursion, multiple interfaces, nesting depth test");
  });
});
<|endoftext|>


<commit_before>/* global describe, it, before */
const host = 'xxx.firebaseio.com';
const authToken = 'xxxxx';

const should = require('should');
const session = require('express-session');
const FirebaseStore = require(__dirname + '/../lib/connect-firebase.js')(session);

describe('FirebaseStore', () => {
  this.timeout(0);

  describe('Instantiation', () => {
    it('should be able to be created', () => {
      const store = new FirebaseStore({
        host: host,
        token: authToken
      });

      store.should.be.an.instanceOf(FirebaseStore);
    });
  });

  describe('Setting', () => {
    it('should store data correctly', done => {
      const store = new FirebaseStore({
        host: host
      });

      store.set('1234_#$[]', {
        cookie: {
          maxAge: 2000
        },
        name: 'tj'
      }, (err, res) => {
        if (err) throw err;

        done();
      });
    });
  });

  describe('Getting', () => {
    before(() => {
      const store = new FirebaseStore({
        host: host
      });

      store.set('1234', {
        cookie: {
          maxAge: 2000
        },
        name: 'tj'
      }, () => {});
    });

    it('should get data correctly', done => {
      const store = new FirebaseStore({
        host: host
      });

      store.get('1234', (err, res) => {
        if (err) throw err;

        res.cookie.should.eql({
          maxAge: 2000
        });
        res.name.should.eql('tj');

        done();
      });
    });
  });

  describe('Destroying', () => {
    before(() => {
      const store = new FirebaseStore({
        host: host
      });

      store.set('12345', {
        cookie: {
          maxAge: 2000
        },
        name: 'tj'
      }, () => {});
    });

    it('should destroy data correctly', done => {
      const store = new FirebaseStore({
        host: host
      });

      store.destroy('12345', (err, res) => {
        if (err) throw err;

        store.get('12345', (err, res) => {
          if (err) throw err;

          should.not.exist(res);

          done();
        });
      });
    });
  });

  describe('Clearing', () => {
    before(() => {
      const store = new FirebaseStore({
        host: host
      });

      store.set('abcd', {
        cookie: {
          maxAge: 2000
        },
        name: 'tj'
      }, () => {});

      store.set('abcdef', {
        cookie: {
          maxAge: 2000
        },
        name: 'tj'
      }, () => {});
    });

    it('should clear sessions correctly', done => {
      const store = new FirebaseStore({
        host: host
      });

      store.clear((err, res) => {
        if (err) throw err;

        store.get('abcd', (err, res) => {
          if (err) throw err;

          should.not.exist(res);

          store.get('abcdef', (err, res) => {
            if (err) throw err;

            should.not.exist(res);

            done();
          });
        });
      });
    });
  });

  describe('Reaping', () => {
    before(done => {
      const store = new FirebaseStore({
        host: host
      });

      store.set('abcd', {
        cookie: {
          maxAge: -2000
        },
        name: 'tj'
      }, done);
    });

    it('should reap data correctly', done => {
      const store = new FirebaseStore({
        host: host
      });

      store.reap((err, res) => {
        if (err) throw err;

        store.get('abcd', (err, res) => {
          if (err) throw err;

          should.not.exist(res);

          done();
        });
      });
    });
  });

  describe('Touching', () => {
    before(done => {
      const store = new FirebaseStore({
        host: host
      });

      store.set('abcd', {
        cookie: {
          maxAge: 2000
        },
        name: 'tj'
      }, done);
    });

    it('should touch data correctly', done => {
      const store = new FirebaseStore({
        host: host
      });

      store.touch('abcd', {
        cookie: {
          maxAge: 3000
        },
        name: 'bn'
      }, function (err) {
        if (err) throw err;

        store.get('abcd', (err, res) => {
          if (err) throw err;

          res.cookie.should.eql({
            maxAge: 3000
          });
          res.name.should.eql('tj');

          done();
        });
      });
    });
  });
});
<commit_msg>Use updated FirebaseStore options<commit_after>/* global describe, it, before */
const path = require('path');
const should = require('should');
const session = require('express-session');
const FirebaseStore = require(path.normalize(`${__dirname}/../lib/connect-session-firebase.js`))(session);

const options = {
  database: {
    serviceAccount: process.env.FIREBASE_SERVICE_ACCOUNT,
    databaseURL: process.env.FIREBASE_DATABASE_URL
  }
};

describe('FirebaseStore', () => {
  describe('Instantiation', () => {
    it('should be able to be created', () => {
      const store = new FirebaseStore(options);

      store.should.be.an.instanceOf(FirebaseStore);
    });
  });

  describe('Setting', () => {
    it('should store data correctly', done => {
      const store = new FirebaseStore(options);

      store.set('1234_#$[]', {
        cookie: {
          maxAge: 2000
        },
        name: 'tj'
      }, (err, res) => {
        if (err) throw err;

        done();
      });
    });
  });

  describe('Getting', () => {
    before(() => {
      const store = new FirebaseStore(options);

      store.set('1234', {
        name: 'tj',
        cookie: {
          maxAge: 2000
        }
      }, () => {});
    });

    it('should get data correctly', done => {
      const store = new FirebaseStore(options);

      store.get('1234', (err, res) => {
        if (err) throw err;

        res.name.should.eql('tj');
        res.cookie.should.eql({
          maxAge: 2000
        });

        done();
      });
    });
  });

  describe('Destroying', () => {
    before(() => {
      const store = new FirebaseStore(options);

      store.set('12345', {
        name: 'tj',
        cookie: {
          maxAge: 2000
        }
      }, () => {});
    });

    it('should destroy data correctly', done => {
      const store = new FirebaseStore(options);

      store.destroy('12345', (err, res) => {
        if (err) throw err;

        store.get('12345', (err, res) => {
          if (err) throw err;

          should.not.exist(res);

          done();
        });
      });
    });
  });

  describe('Clearing', () => {
    before(() => {
      const store = new FirebaseStore(options);

      store.set('abcd', {
        name: 'tj',
        cookie: {
          maxAge: 2000
        }
      }, () => {});

      store.set('abcdef', {
        name: 'tj',
        cookie: {
          maxAge: 2000
        }
      }, () => {});
    });

    it('should clear sessions correctly', done => {
      const store = new FirebaseStore(options);

      store.clear((err, res) => {
        if (err) throw err;

        store.get('abcd', (err, res) => {
          if (err) throw err;

          should.not.exist(res);

          store.get('abcdef', (err, res) => {
            if (err) throw err;

            should.not.exist(res);

            done();
          });
        });
      });
    });
  });

  describe('Reaping', () => {
    before(done => {
      const store = new FirebaseStore(options);

      store.set('abcd', {
        name: 'tj',
        cookie: {
          maxAge: -2000
        }
      }, done);
    });

    it('should reap data correctly', done => {
      const store = new FirebaseStore(options);

      store.reap((err, res) => {
        if (err) throw err;

        store.get('abcd', (err, res) => {
          if (err) throw err;

          should.not.exist(res);

          done();
        });
      });
    });
  });

  describe('Touching', () => {
    before(done => {
      const store = new FirebaseStore(options);

      store.set('abcd', {
        name: 'tj',
        cookie: {
          maxAge: 2000
        }
      }, done);
    });

    it('should touch data correctly', done => {
      const store = new FirebaseStore(options);

      store.touch('abcd', {
        name: 'bn',
        cookie: {
          maxAge: 3000
        }
      }, function (err) {
        if (err) throw err;

        store.get('abcd', (err, res) => {
          if (err) throw err;

          res.name.should.eql('tj');
          res.cookie.should.eql({
            maxAge: 3000
          });

          done();
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>var qlimit = require('..');
var Q = require('q');
var assert = require('assert');

describe('qlimit', function() {
  it('should not exceed the maximum concurrency of one', function(done) {
    var limit = qlimit(1);

    var count = 0;
    return Q.all([1,2,3,4,5,6,7,8,9,10].map(limit(function(i) {
        count++;
        assert.strictEqual(count, 1);
        return Q.delay(1)
          .then(function() {
            count--;
            assert.strictEqual(count, 0);
          });
      })))
      .nodeify(done);
  });

  it('should not exceed the maximum concurrency of two', function(done) {
    var limit = qlimit(2);

    var count = 0;
    return Q.all([1,2,3,4,5,6,7,8,9,10].map(limit(function(i) {
        count++;
        assert(count <= 2, "On iteration " + i + " count was " + count);
        return Q.delay(10)
          .then(function() {
            count--;
            assert(count < 2);
          });
      })))
      .nodeify(done);
  });

  it('should deal with promises failing', function(done) {
    var limit = qlimit(2);

    var rules = [false, false, true, false, false, false, false, false];
    return Q.allSettled(rules.map(limit(function(crash) {
      return Q.fcall(function() {
        if(crash) throw new Error('Crash');
      });
    })))
    .then(function(results) {
      rules.forEach(function(rule, index) {
        if(rule) {
          assert.strictEqual(results[index].state, 'rejected');
        } else {
          assert.strictEqual(results[index].state, 'fulfilled');
        }
      });
    })
    .nodeify(done);

  });

});
<commit_msg>Added a test for limit example<commit_after>var qlimit = require('..');
var Q = require('q');
var assert = require('assert');

describe('qlimit', function() {
  it('should not exceed the maximum concurrency of one', function(done) {
    var limit = qlimit(1);

    var count = 0;
    return Q.all([1,2,3,4,5,6,7,8,9,10].map(limit(function(i) {
        count++;
        assert.strictEqual(count, 1);
        return Q.delay(1)
          .then(function() {
            count--;
            assert.strictEqual(count, 0);
          });
      })))
      .nodeify(done);
  });

  it('should not exceed the maximum concurrency of two', function(done) {
    var limit = qlimit(2);

    var count = 0;
    return Q.all([1,2,3,4,5,6,7,8,9,10].map(limit(function(i) {
        count++;
        assert(count <= 2, "On iteration " + i + " count was " + count);
        return Q.delay(10)
          .then(function() {
            count--;
            assert(count < 2);
          });
      })))
      .nodeify(done);
  });

  it('should deal with promises failing', function(done) {
    var limit = qlimit(2);

    var rules = [false, false, true, false, false, false, false, false];
    return Q.allSettled(rules.map(limit(function(crash) {
      return Q.fcall(function() {
        if(crash) throw new Error('Crash');
      });
    })))
    .then(function(results) {
      rules.forEach(function(rule, index) {
        if(rule) {
          assert.strictEqual(results[index].state, 'rejected');
        } else {
          assert.strictEqual(results[index].state, 'fulfilled');
        }
      });
    })
    .nodeify(done);

  });

  it('should allow specific services to be limited', function(done) {
    var limit = qlimit(1);

    var count = 0;
    var totalCount = 0;
    var limitedFunction = limit(function(c) {
      count++;
      totalCount++;
      assert.strictEqual(count, 1);
      assert.strictEqual(totalCount, c);
      return Q.delay(10)
        .then(function() {
          count--;
          assert.strictEqual(count, 0);
        });
    });

    return Q.all([
        limitedFunction(1),
        limitedFunction(2),
        limitedFunction(3)
      ])
      .nodeify(done);

  });

});
<|endoftext|>