<commit_before>import React from 'react'
import { Table, Column, Cell } from 'fixed-data-table-2'
import SpinKitCube from './SpinKitCube.js'
import moment from 'moment'

const renderValue = (input, fieldMeta) => {
  if (input === null || input === undefined) {
    return null
  } else if (input === true || input === false) {
    return input.toString()
  } else if (fieldMeta.datatype === 'date') {
    return moment.utc(input).format('MM/DD/YYYY HH:mm:ss')
  } else if (typeof input === 'object') {
    return JSON.stringify(input, null, 2)
  } else {
    return input
  }
}

// NOTE: PureComponent's shallow compare works for this component
// because the isRunning prop will toggle with each query execution
// It would otherwise not rerender on change of prop.queryResult alone
class QueryResultDataTable extends React.PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      gridWidth: 0,
      gridHeight: 0,
      columnWidths: {}
    }
    // This binding is necessary to make `this` work in the callback
    this.handleResize = this.handleResize.bind(this)
    this.handleColumnResizeEnd = this.handleColumnResizeEnd.bind(this)
  }

  handleResize(e) {
    const resultGrid = document.getElementById('result-grid')
    if (resultGrid) {
      this.setState({
        gridHeight: resultGrid.clientHeight,
        gridWidth: resultGrid.clientWidth
      })
    }
  }

  handleColumnResizeEnd(newColumnWidth, columnKey) {
    this.setState(({ columnWidths }) => ({
      columnWidths: {
        ...columnWidths,
        [columnKey]: newColumnWidth
      }
    }))
  }

  componentDidMount() {
    window.addEventListener('resize', this.handleResize)
    this.handleResize()
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize)
  }

  render() {
    if (this.props.isRunning) {
      return (

          <SpinKitCube />

      )
    } else if (this.props.queryError) {
      return (

          {this.props.queryError}

      )
    } else if (this.props.queryResult && this.props.queryResult.rows) {
      const { columnWidths } = this.state
      const queryResult = this.props.queryResult
      const columnNodes = queryResult.fields.map(function(field) {
        const fieldMeta = queryResult.meta[field]
        let valueLength = fieldMeta.maxValueLength

        if (field.length > valueLength) {
          valueLength = field.length
        }
        let columnWidthGuess = valueLength * 20
        if (columnWidthGuess < 200) {
          columnWidthGuess = 200
        } else if (columnWidthGuess > 350) {
          columnWidthGuess = 350
        }
        const cellWidth = columnWidthGuess - 10

        const columnWidth = columnWidths[field] || columnWidthGuess

        return (
          <Column
            columnKey={field}
            key={field}
            isResizable
            header={<Cell>{field}</Cell>}
            cell={({ rowIndex }) => {
              const value = queryResult.rows[rowIndex][field]
              let barStyle
              let numberBar
              if (fieldMeta.datatype === 'number') {
                const valueNumber = Number(value)
                const range =
                  fieldMeta.max - (fieldMeta.min < 0 ? fieldMeta.min : 0)
                let left = 0
                if (fieldMeta.min < 0 && valueNumber < 0) {
                  left =
                    Math.abs(fieldMeta.min - valueNumber) / range * 100 + '%'
                } else if (fieldMeta.min < 0 && valueNumber >= 0) {
                  left = Math.abs(fieldMeta.min) / range * 100 + '%'
                }
                barStyle = {
                  position: 'absolute',
                  left: left,
                  top: 0,
                  bottom: 0,
                  width: Math.abs(valueNumber) / range * 100 + '%',
                  backgroundColor: '#bae6f7'
                }
                numberBar =

              }
              return (
                <Cell>
                  {numberBar}

                    {renderValue(value, fieldMeta)}

                </Cell>
              )
            }}
            width={columnWidth}
          />
        )
      })
      return (

            {columnNodes}

      )
    } else {
      return

    }
  }
}

export default QueryResultDataTable
<commit_msg>Minimize data table markings for numbers (#245)<commit_after>import React from 'react'
import { Table, Column, Cell } from 'fixed-data-table-2'
import SpinKitCube from './SpinKitCube.js'
import moment from 'moment'

const renderValue = (input, fieldMeta) => {
  if (input === null || input === undefined) {
    return null
  } else if (input === true || input === false) {
    return input.toString()
  } else if (fieldMeta.datatype === 'date') {
    return moment.utc(input).format('MM/DD/YYYY HH:mm:ss')
  } else if (typeof input === 'object') {
    return JSON.stringify(input, null, 2)
  } else {
    return input
  }
}

// NOTE: PureComponent's shallow compare works for this component
// because the isRunning prop will toggle with each query execution
// It would otherwise not rerender on change of prop.queryResult alone
class QueryResultDataTable extends React.PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      gridWidth: 0,
      gridHeight: 0,
      columnWidths: {}
    }
    // This binding is necessary to make `this` work in the callback
    this.handleResize = this.handleResize.bind(this)
    this.handleColumnResizeEnd = this.handleColumnResizeEnd.bind(this)
  }

  handleResize(e) {
    const resultGrid = document.getElementById('result-grid')
    if (resultGrid) {
      this.setState({
        gridHeight: resultGrid.clientHeight,
        gridWidth: resultGrid.clientWidth
      })
    }
  }

  handleColumnResizeEnd(newColumnWidth, columnKey) {
    this.setState(({ columnWidths }) => ({
      columnWidths: {
        ...columnWidths,
        [columnKey]: newColumnWidth
      }
    }))
  }

  componentDidMount() {
    window.addEventListener('resize', this.handleResize)
    this.handleResize()
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleResize)
  }

  render() {
    if (this.props.isRunning) {
      return (

          <SpinKitCube />

      )
    } else if (this.props.queryError) {
      return (

          {this.props.queryError}

      )
    } else if (this.props.queryResult && this.props.queryResult.rows) {
      const { columnWidths } = this.state
      const queryResult = this.props.queryResult
      const columnNodes = queryResult.fields.map(function(field) {
        const fieldMeta = queryResult.meta[field]
        let valueLength = fieldMeta.maxValueLength

        if (field.length > valueLength) {
          valueLength = field.length
        }
        let columnWidthGuess = valueLength * 20
        if (columnWidthGuess < 200) {
          columnWidthGuess = 200
        } else if (columnWidthGuess > 350) {
          columnWidthGuess = 350
        }
        const cellWidth = columnWidthGuess - 10

        const columnWidth = columnWidths[field] || columnWidthGuess

        return (
          <Column
            columnKey={field}
            key={field}
            isResizable
            header={<Cell>{field}</Cell>}
            cell={({ rowIndex }) => {
              const value = queryResult.rows[rowIndex][field]
              let barStyle
              let numberBar
              if (fieldMeta.datatype === 'number') {
                const valueNumber = Number(value)
                const range =
                  fieldMeta.max - (fieldMeta.min < 0 ? fieldMeta.min : 0)
                let left = 0
                if (fieldMeta.min < 0 && valueNumber < 0) {
                  left =
                    Math.abs(fieldMeta.min - valueNumber) / range * 100 + '%'
                } else if (fieldMeta.min < 0 && valueNumber >= 0) {
                  left = Math.abs(fieldMeta.min) / range * 100 + '%'
                }
                barStyle = {
                  position: 'absolute',
                  left: left,
                  bottom: 0,
                  height: '2px',
                  width: Math.abs(valueNumber) / range * 100 + '%',
                  backgroundColor: '#555'
                }
                numberBar =

              }
              return (
                <Cell>
                  {numberBar}

                    {renderValue(value, fieldMeta)}

                </Cell>
              )
            }}
            width={columnWidth}
          />
        )
      })
      return (

            {columnNodes}

      )
    } else {
      return

    }
  }
}

export default QueryResultDataTable
<|endoftext|>


<commit_before>// Copyright (c) 2015, Evan Summers (twitter.com/evanxsummers)
// ISC license, see http://github.com/evanx/redexutil/LICENSE

// a more explicit promisification for redis client

// also see more automated attempt using es6-promisify:
// https://github.com/evanx/redex/blob/master/lib/redisPromisified.js

//console.log(module.filename);

import redis from 'redis';
import lodash from 'lodash';

import Loggers from './Loggers';

const logger = Loggers.create(module.filename, 'info');

const state = {
   clients: new Set()
};

function createClient() {
   let redisClient = redis.createClient();
   state.clients.add(redisClient);
   redisClient.on('error', err => {
      logger.error('redis error:', err);
   });
   return redisClient;
}

function createCallback(resolve, reject) {
   return (err, reply) => {
      if (err) {
         logger.debug('redis reject error:', err);
         reject(err);
      } else {
         logger.debug('redis resolve:', reply);
         resolve(reply);
      }
   };
}

function createPromise(fn) {
   return new Promise((resolve, reject) => fn(createCallback(resolve, reject)));
}

export default class Redis {

   // @param client
   // client maybe null e.g. if constructed with empty options object i.e. {}
   // if no options, then client is created

   constructor(options) {
      if (options) {
         if (options.client) {
            this.client = createClient();
         } else {
         }
      } else {
         this.client = createClient();
      }
      logger.info('construct', state.clients.size, {options});
   }

   init() {
      if (!this.client) {
         this.client = createClient();
      }
   }

   end() {
      if (this.client) {
         if (state.clients.size > 0) {
            state.clients.delete(this.client);
            logger.info('end: remaining client connections:', state.clients.size);
         } else {
            logger.error('end');
         }
         this.client.end();
         this.client = null;
      }
   }

   time() {
      return createPromise(cb => this.client.time(cb));
   }

   timeSeconds() {
      return this.time().then(time => {
         return parseInt(time[0]);
      });
   }

   set(key, value) {
      //logger.debug('set', key, value);
      return createPromise(cb => this.client.set(key, value, cb));
   }

   get(key) {
      return createPromise(cb => this.client.get(key, cb));
   }

   mget(keys) {
      return createPromise(cb => this.client.mget(keys, cb));
   }

   del(key) {
      return createPromise(cb => this.client.del(key, cb));
   }

   expire(key, seconds) {
      return createPromise(cb => this.client.expire(key, seconds, cb));
   }

   sadd(key, member) {
      //logger.debug('sadd', key, member);
      return createPromise(cb => this.client.sadd(key, member, cb));
   }

   sismember(key, member) {
      return createPromise(cb => this.client.sismember(key, member, cb));
   }

   smembers(key, member) {
      return createPromise(cb => this.client.smembers(key, cb));
   }

   srem(key, member) {
      return createPromise(cb => this.client.srem(key, member, cb));
   }

   scard(key) {
      return createPromise(cb => this.client.scard(key, cb));
   }

   hset(key, field, value) {
      return createPromise(cb => this.client.hset(key, field, value, cb));
   }

   hmset(key, value) {
      return createPromise(cb => this.client.hmset(key, value, cb));
   }

   hget(key, field) {
      return createPromise(cb => this.client.hget(key, field, cb));
   }

   hgetall(key) {
      return createPromise(cb => this.client.hgetall(key, cb));
   }

   lindex(key, index) {
      return createPromise(cb => this.client.lindex(key, index, cb));
   }

   lset(key, index, value) {
      return createPromise(cb => this.client.lset(key, index, value, cb));
   }

   llen(key) {
      return createPromise(cb => this.client.llen(key, cb));
   }

   ltrim(key, start, stop) {
      return createPromise(cb => this.client.ltrim(key, start, stop, cb));
   }

   lrange(key, start, stop) {
      return createPromise(cb => this.client.lrange(key, start, stop, cb));
   }

   lpush(key, value) {
      return createPromise(cb => this.client.lpush(key, value, cb));
   }

   rpush(key, value) {
      return createPromise(cb => this.client.rpush(key, value, cb));
   }

   lpop(key) {
      return createPromise(cb => this.client.lpop(key, cb));
   }

   rpop(key) {
      return createPromise(cb => this.client.rpop(key, cb));
   }

   blpop(key, timeout) {
      return createPromise(cb => this.client.blpop(key, timeout, cb));
   }

   brpop(key, timeout) {
      return createPromise(cb => this.client.brpop(key, timeout, cb));
   }

   rpoplpush(source, destination) {
      return createPromise(cb => this.client.rpoplpush(source, destination, cb));
   }

   brpoplpush(source, destination, timeout) {
      return createPromise(cb => this.client.brpoplpush(source, destination, timeout, cb));
   }

   zrange(key, start, stop) {
      return createPromise(cb => this.client.zrange(key, start, stop, cb));
   }

   zrevrange(key, start, stop) {
      return createPromise(cb => this.client.zrevrange(key, start, stop, cb));
   }

   // TODO all the rest, see https://github.com/mranney/node_redis/blob/master/lib/commands.js

   multi() {
      let multi = this.client.multi();
      multi.execCallback = multi.exec;
      multi.execPromise = () => {
         return createPromise(cb => multi.execCallback(cb));
      };
      multi.exec = multi.execPromise;
      return multi;
   }

}

// see test: https://github.com/evanx/redex/blob/master/test/redisPromised.js
<commit_msg>update<commit_after>// Copyright (c) 2015, Evan Summers (twitter.com/evanxsummers)
// ISC license, see http://github.com/evanx/redexutil/LICENSE

// a more explicit promisification for redis client

// also see more automated attempt using es6-promisify:
// https://github.com/evanx/redex/blob/master/lib/redisPromisified.js

//console.log(module.filename);

import redis from 'redis';
import lodash from 'lodash';

import Loggers from './Loggers';

const logger = Loggers.create(module.filename, 'info');

const state = {
   clients: new Set()
};

function createClient() {
   let redisClient = redis.createClient();
   state.clients.add(redisClient);
   redisClient.on('error', err => {
      logger.error('redis error:', err);
   });
   return redisClient;
}

function createCallback(resolve, reject) {
   return (err, reply) => {
      if (err) {
         logger.debug('redis reject error:', err);
         reject(err);
      } else {
         logger.debug('redis resolve:', reply);
         resolve(reply);
      }
   };
}

function createPromise(fn) {
   return new Promise((resolve, reject) => fn(createCallback(resolve, reject)));
}

export default class Redis {

   // @param client
   // client maybe null e.g. if constructed with empty options object i.e. {}
   // if no options, then client is created

   constructor(options) {
      if (options) {
         if (options.client) {
            this.client = createClient();
         } else {
         }
      } else {
         this.client = createClient();
      }
      logger.info('construct', state.clients.size);
   }

   init() {
      if (!this.client) {
         this.client = createClient();
      }
   }

   end() {
      if (this.client) {
         if (state.clients.size > 0) {
            state.clients.delete(this.client);
            logger.info('end: remaining client connections:', state.clients.size);
         } else {
            logger.error('end');
         }
         this.client.end();
         this.client = null;
      }
   }

   time() {
      return createPromise(cb => this.client.time(cb));
   }

   timeSeconds() {
      return this.time().then(time => {
         return parseInt(time[0]);
      });
   }

   set(key, value) {
      //logger.debug('set', key, value);
      return createPromise(cb => this.client.set(key, value, cb));
   }

   get(key) {
      return createPromise(cb => this.client.get(key, cb));
   }

   mget(keys) {
      return createPromise(cb => this.client.mget(keys, cb));
   }

   del(key) {
      return createPromise(cb => this.client.del(key, cb));
   }

   expire(key, seconds) {
      return createPromise(cb => this.client.expire(key, seconds, cb));
   }

   sadd(key, member) {
      //logger.debug('sadd', key, member);
      return createPromise(cb => this.client.sadd(key, member, cb));
   }

   sismember(key, member) {
      return createPromise(cb => this.client.sismember(key, member, cb));
   }

   smembers(key, member) {
      return createPromise(cb => this.client.smembers(key, cb));
   }

   srem(key, member) {
      return createPromise(cb => this.client.srem(key, member, cb));
   }

   scard(key) {
      return createPromise(cb => this.client.scard(key, cb));
   }

   hset(key, field, value) {
      return createPromise(cb => this.client.hset(key, field, value, cb));
   }

   hmset(key, value) {
      return createPromise(cb => this.client.hmset(key, value, cb));
   }

   hget(key, field) {
      return createPromise(cb => this.client.hget(key, field, cb));
   }

   hgetall(key) {
      return createPromise(cb => this.client.hgetall(key, cb));
   }

   lindex(key, index) {
      return createPromise(cb => this.client.lindex(key, index, cb));
   }

   lset(key, index, value) {
      return createPromise(cb => this.client.lset(key, index, value, cb));
   }

   llen(key) {
      return createPromise(cb => this.client.llen(key, cb));
   }

   ltrim(key, start, stop) {
      return createPromise(cb => this.client.ltrim(key, start, stop, cb));
   }

   lrange(key, start, stop) {
      return createPromise(cb => this.client.lrange(key, start, stop, cb));
   }

   lpush(key, value) {
      return createPromise(cb => this.client.lpush(key, value, cb));
   }

   rpush(key, value) {
      return createPromise(cb => this.client.rpush(key, value, cb));
   }

   lpop(key) {
      return createPromise(cb => this.client.lpop(key, cb));
   }

   rpop(key) {
      return createPromise(cb => this.client.rpop(key, cb));
   }

   blpop(key, timeout) {
      return createPromise(cb => this.client.blpop(key, timeout, cb));
   }

   brpop(key, timeout) {
      return createPromise(cb => this.client.brpop(key, timeout, cb));
   }

   rpoplpush(source, destination) {
      return createPromise(cb => this.client.rpoplpush(source, destination, cb));
   }

   brpoplpush(source, destination, timeout) {
      return createPromise(cb => this.client.brpoplpush(source, destination, timeout, cb));
   }

   zrange(key, start, stop) {
      return createPromise(cb => this.client.zrange(key, start, stop, cb));
   }

   zrevrange(key, start, stop) {
      return createPromise(cb => this.client.zrevrange(key, start, stop, cb));
   }

   // TODO all the rest, see https://github.com/mranney/node_redis/blob/master/lib/commands.js

   multi() {
      let multi = this.client.multi();
      multi.execCallback = multi.exec;
      multi.execPromise = () => {
         return createPromise(cb => multi.execCallback(cb));
      };
      multi.exec = multi.execPromise;
      return multi;
   }

}

// see test: https://github.com/evanx/redex/blob/master/test/redisPromised.js
<|endoftext|>


<commit_before>"use strict";

mcgApp.controller('ColorGeneratorCtrl',
function ($scope, $mdDialog)
{
	$scope.init = function ()
	{
		// Define base palette
		$scope.palette = {
			colors: [],
			orig  : [],
			base  : '#26a69a',
			json  : '',
			name  : ''
		};

		// Define palettes
		$scope.palettes = [];

		// Add base palette
		$scope.addBasePalette();

		// Define theme defaults
		$scope.theme = {
			name: '',
            palettes: $scope.palettes
		};
	};

	// Function to add a palette to palettes.
	$scope.addBasePalette = function(){
		$scope.palettes.push(angular.copy($scope.palette));
		$scope.calcPalette($scope.palettes.length-1);

		// GA Event Track
		ga('send', 'event', 'mcg', 'add_palette');
	};

	// Function to calculate all colors for all palettes
	$scope.calcPalettes = function(){
		for(var i = 0; i < $scope.palettes.length; i++){
			$scope.calcPalette(i);
		}
	};

	// Function to delete a palette when passed it's key.
	$scope.deletePalette = function(key){
		$scope.palettes.remove(key);
		// GA Event Track
		ga('send', 'event', 'mcg', 'remove_palette');
	};

	// Function to assign watchers to all bases
	$scope.calcPalette = function(key){
		$scope.palettes[key].orig = $scope.computeColors($scope.palettes[key].base);
		$scope.palettes[key].colors = $scope.palettes[key].orig;
	};

	// Function to make the definePalette code for a palette.
	$scope.createDefinePalette = function(palette){
		return '$mdThemingProvider.definePalette(\'' + palette.name + '\', ' + $scope.makeColorsJson(palette.colors) + ');';
	};

	// Function to make an exportable json array for themes.
	$scope.makeColorsJson = function(colors){
		var exportable = {};
		angular.forEach(colors, function(value, key){
			exportable[value.name] = value.hex;
		});
		return JSON.stringify(exportable, null, 4);
	};

	// Function to calculate all colors from base
	$scope.computeColors = function(color)
	{
		// Return array of color objects.
		return [
			{
				hex: shadeColor(color, 0.9),
				name : '50'
			},
			{
				hex: shadeColor(color, 0.7),
				name : '100'
			},
			{
				hex: shadeColor(color, 0.5),
				name : '200'
			},
			{
				hex: shadeColor(color, 0.333),
				name : '300'
			},
			{
				hex: shadeColor(color, 0.166),
				name : '400'
			},
			{
				hex: shadeColor(color, 0),
				name : '500'
			},
			{
				hex : shadeColor(color, -0.125),
				name: '600'
			},
			{
				hex : shadeColor(color, -0.25),
				name: '700'
			},
			{
				hex : shadeColor(color, -0.375),
				name: '800'
			},
			{
				hex : shadeColor(color, -0.5),
				name: '900'
			},
			{
				hex : shadeColor(color, 0.7),
				name: 'A100'
			},
			{
				hex : shadeColor(color, 0.5),
				name: 'A200'
			},
			{
				hex : shadeColor(color, 0.166),
				name: 'A400'
			},
			{
				hex : shadeColor(color, -0.25),
				name: 'A700'
			}
		];
	};

    // Function to show theme's full code
    $scope.showThemeCode = function()
    {
	    // Check to see that a theme name and palette names are set.
	    if(
		    typeof $scope.theme.name === 'undefined' || $scope.theme.name.length < 1 ||
		    typeof $scope.palettes[0] === 'undefined' || typeof $scope.palettes[0].name === 'undefined' || $scope.palettes[0].name.length < 1 ||
		    typeof $scope.palettes[1] === 'undefined' || typeof $scope.palettes[1].name === 'undefined' || $scope.palettes[1].name.length < 1
	    ){
		    alert('To generate the code for a theme you must provide a theme name and at least two palettes with names.');
		    return false;
	    }

        // Init return string
        var themeCodeString = '';

        // For each palette, add it's declaration
        for(var i = 0; i < $scope.palettes.length; i++){
            themeCodeString = themeCodeString+$scope.createDefinePalette($scope.palettes[i])+'\n\r';
        }

        // Add theme configuration
        themeCodeString = themeCodeString +
        '$mdThemingProvider.theme(\'' + $scope.theme.name + '\')\n\r\t'+
        '.primaryPalette(\''+$scope.palettes[0].name+'\')\n\r\t'+
        '.accentPalette(\''+$scope.palettes[1].name+'\');'
        +'\n\r';

        // Show clipboard with theme code
        $scope.showClipboard(themeCodeString);

	    // GA Event Track
	    ga('send', 'event', 'mcg', 'copy_code_theme');
    };

	// Function to regenerate json and show dialog for palette.
	$scope.showPaletteCode = function(palette)
	{
		// Check to see that this palette has a name
		if (
			typeof palette === 'undefined' ||
			typeof palette.name === 'undefined' ||
			palette.name.length < 1
		) {
			alert('To generate the code for a palette the palette must have a name.');
			return false;
		}

		// Generate palette's code
		palette.json = $scope.createDefinePalette(palette);

		// Show code
		$scope.showClipboard(palette.json);

		// GA Event Track
		ga('send', 'event', 'mcg', 'copy_code_palette');
	};

    // Function to show export json for loading carts later
    $scope.showExport = function(){
        $scope.showClipboard(JSON.stringify($scope.theme, null, 2));
    };

	// Function to show generic clipboard alert dialog
	$scope.showClipboard = function(code){
		$mdDialog.show({
			template   : '<md-dialog aria-label="Clipboard dialog">' +
			'  <md-content>' +
			'
{{code}}' +
			'
' +
			'  </md-content>' +
			'
' +
			'    <md-button ng-click="closeDialog()">' +
			'      Close' +
			'    </md-button>' +
			'
' +
			'</md-dialog>',
			locals     : {
				code: code
			},
			controller : ClipboardDialogController
		});

		// GA Event Track
		ga('send', 'event', 'mcg', 'copy_code');

		function ClipboardDialogController(scope, $mdDialog, code) {
			scope.code = code;
			scope.closeDialog = function () {
				$mdDialog.hide();
			}
		}
	};

    // Function to darken a palette's color.
    $scope.darkenPaletteItem = function(color){
        color.hex = shadeColor(color.hex, -0.1);
    };

    // Function to lighten a palette's color.
    $scope.lightenPaletteItem = function(color){
        color.hex = shadeColor(color.hex, 0.1);
    };

	// Init controller
	$scope.init();
});<commit_msg>Tidy up the exported JSON.<commit_after>"use strict";

mcgApp.controller('ColorGeneratorCtrl',
function ($scope, $mdDialog)
{
	$scope.init = function ()
	{
		// Define base palette
		$scope.palette = {
			colors: [],
			orig  : [],
			base  : '#26a69a',
			json  : '',
			name  : ''
		};

		// Define palettes
		$scope.palettes = [];

		// Add base palette
		$scope.addBasePalette();

		// Define theme defaults
		$scope.theme = {
			name: '',
            palettes: $scope.palettes
		};
	};

	// Function to add a palette to palettes.
	$scope.addBasePalette = function(){
		$scope.palettes.push(angular.copy($scope.palette));
		$scope.calcPalette($scope.palettes.length-1);

		// GA Event Track
		ga('send', 'event', 'mcg', 'add_palette');
	};

	// Function to calculate all colors for all palettes
	$scope.calcPalettes = function(){
		for(var i = 0; i < $scope.palettes.length; i++){
			$scope.calcPalette(i);
		}
	};

	// Function to delete a palette when passed it's key.
	$scope.deletePalette = function(key){
		$scope.palettes.remove(key);
		// GA Event Track
		ga('send', 'event', 'mcg', 'remove_palette');
	};

	// Function to assign watchers to all bases
	$scope.calcPalette = function(key){
		$scope.palettes[key].orig = $scope.computeColors($scope.palettes[key].base);
		$scope.palettes[key].colors = $scope.palettes[key].orig;
	};

	// Function to make the definePalette code for a palette.
	$scope.createDefinePalette = function(palette){
		return '$mdThemingProvider.definePalette(\'' + palette.name + '\', ' + $scope.makeColorsJson(palette.colors) + ');';
	};

	// Function to make an exportable json array for themes.
	$scope.makeColorsJson = function(colors){
		var exportable = {};
		angular.forEach(colors, function(value, key){
			exportable[value.name] = value.hex;
		});
		return angular.toJson(exportable, null, 4);
	};

	// Function to calculate all colors from base
	$scope.computeColors = function(color)
	{
		// Return array of color objects.
		return [
			{
				hex: shadeColor(color, 0.9),
				name : '50'
			},
			{
				hex: shadeColor(color, 0.7),
				name : '100'
			},
			{
				hex: shadeColor(color, 0.5),
				name : '200'
			},
			{
				hex: shadeColor(color, 0.333),
				name : '300'
			},
			{
				hex: shadeColor(color, 0.166),
				name : '400'
			},
			{
				hex: shadeColor(color, 0),
				name : '500'
			},
			{
				hex : shadeColor(color, -0.125),
				name: '600'
			},
			{
				hex : shadeColor(color, -0.25),
				name: '700'
			},
			{
				hex : shadeColor(color, -0.375),
				name: '800'
			},
			{
				hex : shadeColor(color, -0.5),
				name: '900'
			},
			{
				hex : shadeColor(color, 0.7),
				name: 'A100'
			},
			{
				hex : shadeColor(color, 0.5),
				name: 'A200'
			},
			{
				hex : shadeColor(color, 0.166),
				name: 'A400'
			},
			{
				hex : shadeColor(color, -0.25),
				name: 'A700'
			}
		];
	};

    // Function to show theme's full code
    $scope.showThemeCode = function()
    {
	    // Check to see that a theme name and palette names are set.
	    if(
		    typeof $scope.theme.name === 'undefined' || $scope.theme.name.length < 1 ||
		    typeof $scope.palettes[0] === 'undefined' || typeof $scope.palettes[0].name === 'undefined' || $scope.palettes[0].name.length < 1 ||
		    typeof $scope.palettes[1] === 'undefined' || typeof $scope.palettes[1].name === 'undefined' || $scope.palettes[1].name.length < 1
	    ){
		    alert('To generate the code for a theme you must provide a theme name and at least two palettes with names.');
		    return false;
	    }

        // Init return string
        var themeCodeString = '';

        // For each palette, add it's declaration
        for(var i = 0; i < $scope.palettes.length; i++){
            themeCodeString = themeCodeString+$scope.createDefinePalette($scope.palettes[i])+'\n\r';
        }

        // Add theme configuration
        themeCodeString = themeCodeString +
        '$mdThemingProvider.theme(\'' + $scope.theme.name + '\')\n\r\t'+
        '.primaryPalette(\''+$scope.palettes[0].name+'\')\n\r\t'+
        '.accentPalette(\''+$scope.palettes[1].name+'\');'
        +'\n\r';

        // Show clipboard with theme code
        $scope.showClipboard(themeCodeString);

	    // GA Event Track
	    ga('send', 'event', 'mcg', 'copy_code_theme');
    };

	// Function to regenerate json and show dialog for palette.
	$scope.showPaletteCode = function(palette)
	{
		// Check to see that this palette has a name
		if (
			typeof palette === 'undefined' ||
			typeof palette.name === 'undefined' ||
			palette.name.length < 1
		) {
			alert('To generate the code for a palette the palette must have a name.');
			return false;
		}

		// Generate palette's code
		palette.json = $scope.createDefinePalette(palette);

		// Show code
		$scope.showClipboard(palette.json);

		// GA Event Track
		ga('send', 'event', 'mcg', 'copy_code_palette');
	};

    // Function to show export json for loading carts later
    $scope.showExport = function(){
        $scope.showClipboard(angular.toJson($scope.theme, null, 2));
    };

	// Function to show generic clipboard alert dialog
	$scope.showClipboard = function(code){
		$mdDialog.show({
			template   : '<md-dialog aria-label="Clipboard dialog">' +
			'  <md-content>' +
			'
{{code}}' +
			'
' +
			'  </md-content>' +
			'
' +
			'    <md-button ng-click="closeDialog()">' +
			'      Close' +
			'    </md-button>' +
			'
' +
			'</md-dialog>',
			locals     : {
				code: code
			},
			controller : ClipboardDialogController
		});

		// GA Event Track
		ga('send', 'event', 'mcg', 'copy_code');

		function ClipboardDialogController(scope, $mdDialog, code) {
			scope.code = code;
			scope.closeDialog = function () {
				$mdDialog.hide();
			}
		}
	};

    // Function to darken a palette's color.
    $scope.darkenPaletteItem = function(color){
        color.hex = shadeColor(color.hex, -0.1);
    };

    // Function to lighten a palette's color.
    $scope.lightenPaletteItem = function(color){
        color.hex = shadeColor(color.hex, 0.1);
    };

	// Init controller
	$scope.init();
});
<|endoftext|>


<commit_before>var fs = require('fs');
var crypto = require('crypto');
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var bncode = require('bncode');
var Magnet = require('magnet-uri');
var TorrentContext = require('./lib/torrent_context');

process.on('uncaughtException', function(e) {
    console.error(e.stack);
});

function parseTorrent(data) {
    var torrent = bncode.decode(data);
    console.log("decoded", torrent);
    var info = torrent.info;
    var announceList =
        torrent['announce-list'] ||
        [[torrent['announce']]];
    var sha1 = crypto.createHash('sha1');
    sha1.update(bncode.encode(info));
    return {
        info: info,
        infoHash: sha1.digest('hex'),
        announce: announceList
    };
}

var ctxs = {};

function loadUrl(url, cb) {
    var parsed;
    if (/^magnet:/.test(url)) {
        parsed = Magnet(url);
        var infoHash = parsed && parsed.infoHash;

        if (infoHash && !ctxs.hasOwnProperty(infoHash)) {
            var ctx = ctxs[infoHash] = new TorrentContext(infoHash);
            parsed.tr.forEach(function(t) {
                ctx.addTrackerGroup([t]);
            });

            // ctx.on('end', function() {
            //     delete ctxs[parsed.infoHash];
            // });

            cb(null, infoHash);

        } else if (ctxs.hasOwnProperty(infoHash)) {
            cb(null, infoHash);
        } else {
            console.log("Ignoring magnet link", parsed.xt);
            cb(new Error("Ignored"));
        }
    } else if (/^https?:\/\//.test(url)) {
        request({
            url: url,
            encoding: null
        }, function(err, res, body) {
            if (err) {
                return cb(err);
            }
            if (res.statusCode == 200) {
                var infoHash;
                try {
                    parsed = parseTorrent(body);
                    infoHash = parsed.infoHash;

                    if (infoHash && !ctxs.hasOwnProperty(infoHash)) {
                        var ctx = ctxs[infoHash] = new TorrentContext(infoHash, parsed.info);
                        parsed.announce.forEach(function(ts) {
                            var urls = ts.map(function(t) {
                                return t.toString();
                            });
                            ctx.addTrackerGroup(urls);
                        });

                        // ctx.on('end', function() {
                        //     delete ctxs[parsed.infoHash];
                        // });

                    } else if (infoHash) {
                        /* Ignore existing */
                    } else {
                        throw new Error("No infoHash");
                    }
                } catch (e) {
                    return cb(e);
                }
                cb(null, infoHash);
            } else {
                cb(new Error("HTTP " + res.statusCode));
            }
        });
    } else {
        cb(new Error("Invalid URL"));
    }
}

var app = express();
app.use(bodyParser());

app.use(express.static(__dirname + '/public'));

app.post('/torrents', function(req, res) {
    var url = req.body.url;
    loadUrl(url, function(err, infoHash) {
        if (err) {
            console.error(err.stack || err);
            res.status(500);
            res.send(err.message);
            return;
        }

        res.json({
            infoHash: infoHash
        });
    });

});

app.get('/torrents', function(req, res) {
    res.json(Object.keys(ctxs));
});

app.get('/torrents/:infoHash', function(req, res) {
    var infoHash = req.params.infoHash;

    if (infoHash && ctxs.hasOwnProperty(infoHash)) {
        var ctx = ctxs[infoHash];
        var result = {
            downloadSpeed: ctx.swarm.downloadSpeed(),
            uploadSpeed: ctx.swarm.uploadSpeed()
        };
        result.name =
            (ctx.info && ctx.info.name) ?
            ctx.info.name.toString() :
            infoHash;
        if (ctx.validator) {
            result.left = ctx.validator.getBytesLeft();
        }
        if (ctx.storage) {
            result.totalLength = ctx.totalLength;
        }
        res.json(result);
    } else {
        res.status(500);
        res.send("No such torrent");
    }
});

app.get('/torrents/:infoHash/files', function(req, res) {
    var infoHash = req.params.infoHash;

    if (infoHash && ctxs.hasOwnProperty(infoHash)) {
        var ctx = ctxs[infoHash];
        var files =
            (ctx.storage ? ctx.storage.files : [])
            .map(function(file) {
                file.href = '/torrents/' + infoHash + '/files/' + encodeURIComponent(file.name);
                return file;
            });
        res.json(files);
    } else {
        res.status(404);
        res.send("No such torrent");
    }
});

app.get('/torrents/:infoHash/files/:fileName*', function(req, res) {
    var infoHash = req.params.infoHash;
    var fileName = req.params.fileName;
    console.log("fileName", fileName);

    var offset = 0;
    var length;
    var range = req.headers.range;
    var m;
    if (range &&
        (m = range.match(/^bytes=(\d+)-(\d+)/))) {
        offset = parseInt(m[1], 10);
        length = parseInt(m[2], 10) - offset + 1;
    } else if (range &&
               (m = range.match(/^bytes=(\d+)/))) {
        offset = parseInt(m[1], 10);
    }
    console.log("range", range, "offset", offset, "length", length);

    if (infoHash && ctxs.hasOwnProperty(infoHash)) {
        var ctx = ctxs[infoHash];
        var stream = ctx.streamFile(fileName, offset, length);

        if (stream) {
            if (!range || (offset === 0 && isNaN(length))) {
                res.writeHead(200, {
                    'Content-Type': stream.mime,
                    'Content-Length': stream.fileLength,
                    'Accept-Ranges': 'bytes'
                });
            } else {
                res.writeHead(206, {
                    'Content-Type': stream.mime,
                    'Content-Range': offset + "-" + (offset + stream.length - 1) + "/" + stream.fileLength,
                    'Accept-Ranges': 'bytes'
                });
            }
            /* Flush header */
            // res.write("");
            /* Begin streaming */
            stream.pipe(res);
        } else {
            res.status(404);
            res.send("No such file in torrent");
        }
    } else {
        res.status(404);
        res.send("No such torrent");
    }
});

app.listen(4000);
<commit_msg>fix range streaming<commit_after>var fs = require('fs');
var crypto = require('crypto');
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var bncode = require('bncode');
var Magnet = require('magnet-uri');
var TorrentContext = require('./lib/torrent_context');

process.on('uncaughtException', function(e) {
    console.error(e.stack);
});

function parseTorrent(data) {
    var torrent = bncode.decode(data);
    console.log("decoded", torrent);
    var info = torrent.info;
    var announceList =
        torrent['announce-list'] ||
        [[torrent['announce']]];
    var sha1 = crypto.createHash('sha1');
    sha1.update(bncode.encode(info));
    return {
        info: info,
        infoHash: sha1.digest('hex'),
        announce: announceList
    };
}

var ctxs = {};

function loadUrl(url, cb) {
    var parsed;
    if (/^magnet:/.test(url)) {
        parsed = Magnet(url);
        var infoHash = parsed && parsed.infoHash;

        if (infoHash && !ctxs.hasOwnProperty(infoHash)) {
            var ctx = ctxs[infoHash] = new TorrentContext(infoHash);
            parsed.tr.forEach(function(t) {
                ctx.addTrackerGroup([t]);
            });

            // ctx.on('end', function() {
            //     delete ctxs[parsed.infoHash];
            // });

            cb(null, infoHash);

        } else if (ctxs.hasOwnProperty(infoHash)) {
            cb(null, infoHash);
        } else {
            console.log("Ignoring magnet link", parsed.xt);
            cb(new Error("Ignored"));
        }
    } else if (/^https?:\/\//.test(url)) {
        request({
            url: url,
            encoding: null
        }, function(err, res, body) {
            if (err) {
                return cb(err);
            }
            if (res.statusCode == 200) {
                var infoHash;
                try {
                    parsed = parseTorrent(body);
                    infoHash = parsed.infoHash;

                    if (infoHash && !ctxs.hasOwnProperty(infoHash)) {
                        var ctx = ctxs[infoHash] = new TorrentContext(infoHash, parsed.info);
                        parsed.announce.forEach(function(ts) {
                            var urls = ts.map(function(t) {
                                return t.toString();
                            });
                            ctx.addTrackerGroup(urls);
                        });

                        // ctx.on('end', function() {
                        //     delete ctxs[parsed.infoHash];
                        // });

                    } else if (infoHash) {
                        /* Ignore existing */
                    } else {
                        throw new Error("No infoHash");
                    }
                } catch (e) {
                    return cb(e);
                }
                cb(null, infoHash);
            } else {
                cb(new Error("HTTP " + res.statusCode));
            }
        });
    } else {
        cb(new Error("Invalid URL"));
    }
}

var app = express();
app.use(bodyParser());

app.use(express.static(__dirname + '/public'));

app.post('/torrents', function(req, res) {
    var url = req.body.url;
    loadUrl(url, function(err, infoHash) {
        if (err) {
            console.error(err.stack || err);
            res.status(500);
            res.send(err.message);
            return;
        }

        res.json({
            infoHash: infoHash
        });
    });

});

app.get('/torrents', function(req, res) {
    res.json(Object.keys(ctxs));
});

app.get('/torrents/:infoHash', function(req, res) {
    var infoHash = req.params.infoHash;

    if (infoHash && ctxs.hasOwnProperty(infoHash)) {
        var ctx = ctxs[infoHash];
        var result = {
            downloadSpeed: ctx.swarm.downloadSpeed(),
            uploadSpeed: ctx.swarm.uploadSpeed()
        };
        result.name =
            (ctx.info && ctx.info.name) ?
            ctx.info.name.toString() :
            infoHash;
        if (ctx.validator) {
            result.left = ctx.validator.getBytesLeft();
        }
        if (ctx.storage) {
            result.totalLength = ctx.totalLength;
        }
        res.json(result);
    } else {
        res.status(500);
        res.send("No such torrent");
    }
});

app.get('/torrents/:infoHash/files', function(req, res) {
    var infoHash = req.params.infoHash;

    if (infoHash && ctxs.hasOwnProperty(infoHash)) {
        var ctx = ctxs[infoHash];
        var files =
            (ctx.storage ? ctx.storage.files : [])
            .map(function(file) {
                file.href = '/torrents/' + infoHash + '/files/' + encodeURIComponent(file.name);
                return file;
            });
        res.json(files);
    } else {
        res.status(404);
        res.send("No such torrent");
    }
});

app.get('/torrents/:infoHash/files/:fileName*', function(req, res) {
    var infoHash = req.params.infoHash;
    var fileName = req.params.fileName;
    console.log("fileName", fileName);

    var offset = 0;
    var length;
    var range = req.headers.range;
    var m;
    if (range &&
        (m = range.match(/^bytes=(\d+)-(\d+)/))) {
        offset = parseInt(m[1], 10);
        length = parseInt(m[2], 10) - offset + 1;
    } else if (range &&
               (m = range.match(/^bytes=(\d+)/))) {
        offset = parseInt(m[1], 10);
    }
    console.log("range", range, "offset", offset, "length", length);

    if (infoHash && ctxs.hasOwnProperty(infoHash)) {
        var ctx = ctxs[infoHash];
        var stream = ctx.streamFile(fileName, offset, length);

        if (stream) {
            if (!range || (offset === 0 && isNaN(length))) {
                res.writeHead(200, {
                    'Content-Type': stream.mime,
                    'Content-Length': stream.length,
                    'Accept-Ranges': 'bytes'
                });
            } else {
                res.writeHead(206, {
                    'Content-Type': stream.mime,
                    'Content-Length': stream.length,
                    'Content-Range': 'bytes ' + offset + "-" + (offset + stream.length - 1) + "/" + stream.fileLength
                });
            }
            /* Flush header */
            // res.write("");
            /* Begin streaming */
            stream.pipe(res);
        } else {
            res.status(404);
            res.send("No such file in torrent");
        }
    } else {
        res.status(404);
        res.send("No such torrent");
    }
});

app.listen(4000);
<|endoftext|>


<commit_before>define(['app',
 'text!./locale.html',
  'css!./locale',
  'scbd-angularjs-services/locale',
  'scbd-angularjs-services/authentication',
],
function(app, template, $) {
     app.directive('localeHeader', function() {
         return { restrict: 'E' ,
                  priority: 0,// child of header
                  scope: {
                       ngModel: '=',
                     },
                  template: template,
                  controller: ['$scope', '$window', '$location','authentication', 'locale',
                  function($scope, $window, $location,authentication, locale) {
                  // code for seling locale
                      $scope.currentLanguage = locale;
                      $scope.changeLanguage = function(lang){

                          $location.search({ returnUrl: $location.url() });
                          $location.path('/lang/'+ lang);
                      }

                  }],//controller
        };//return
     });//directive
});
<commit_msg>add id for css styling and reuse<commit_after>define(['app',
 'text!./locale.html',
  'css!./locale',
  'scbd-angularjs-services/locale',
  'scbd-angularjs-services/authentication',
],
function(app, template, $) {
     app.directive('localeHeader', function() {
         return { restrict: 'ECA' ,
                  priority: 0,// child of header
                  scope: {
                       idname: '=id',
                       ngModel: '=',
                     },
                  template: template,
                  controller: ['$scope', '$window', '$location','authentication', 'locale',
                  function($scope, $window, $location,authentication, locale) {
                      if(!$scope.idname)
                         $scope.idname ="CBD-Branding";
                   // code for seling locale
                      $scope.currentLanguage = locale;
                      $scope.changeLanguage = function(lang){

                          $location.search({ returnUrl: $location.url() });
                          $location.path('/lang/'+ lang);
                      }

                  }],//controller
        };//return
     });//directive
});
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */
var EventEmitter = require('events').EventEmitter
  , amqp = require('amqp')
  , util = require('util')
  , Message = require('./message')
  , debug = require('debug')('crane-amqp');

/**
 * Message delivery mode constants.
 */
var NONPERSISTENT_MODE = 1;
var PERSISTENT_MODE = 2;

/**
 * `Broker` constructor.
 *
 * @api public
 */
function Broker() {
  EventEmitter.call(this);
  this._exchange = null;
  this._queues = {};
  this._ctags = {};
}

/**
 * Inherit from `EventEmitter`.
 */
util.inherits(Broker, EventEmitter);

/**
 * Connect to AMQP server.
 *
 * For AMQP brokers, `options` argument should be an object that specifies the
 * following parameters:
 *
 *   - `port`  port the client should connect to, defaults to 5672
 *   - `host`  host the client should connect to, defaults to localhost
 *
 * Examples:
 *
 *     broker.connect({ host: '127.0.0.1', port: 5672 }, function() {
 *       console.log('ready');
 *     });
 *
 *     broker.connect({ host: '127.0.0.1', port: 5672, exchange: 'amq.topic' }, function() {
 *       console.log('ready');
 *     });
 *
 *     broker.connect({ host: '127.0.0.1', port: 5672,
 *                      exchange: {
 *                        name: 'app1.topic',
 *                        options: { type: 'topic', confirm: false }
 *                      } },
 *       function() {
 *         console.log('ready');
 *       });
 *
 * @param {Object} options
 * @param {Function} readyListener
 * @api public
 */
Broker.prototype.connect = function(options, readyListener) {
  if (readyListener) { this.once('ready', readyListener); }

  debug('connecting %s:%s', options.host || 'localhost', options.port || 5672);

  var self = this;
  this._connection = amqp.createConnection(options);
  this._connection.once('ready', function() {
    var exchange = options.exchange;
    if (!exchange) {
      debug('default exchange');

      // Get the default exchange, which is a direct exchange, and thus suitable
      // for use as a task queue.
      self._exchange = self._connection.exchange();
      // TODO: Emit ready after callback to `exchange()`.
      return self.emit('ready');
    } else {
      var name = exchange
        , opts = {};
      if (typeof exchange == 'object') {
        name = exchange.name;
        opts = exchange.options;
      }

      // AMQP uses period ('.') separators rather than slash ('/')
      name = name.replace(/\//g, '.');
      if (name.indexOf('amq.') !== 0) {
        opts.type = (opts.type === undefined) ? 'direct' : opts.type;
        opts.durable = (opts.durable === undefined) ? true : opts.durable;
        opts.autoDelete = (opts.autoDelete === undefined) ? false : opts.autoDelete;
        opts.confirm = (opts.confirm === undefined) ? true : opts.confirm;
      } else {
        // Options for built-in exchanges can not be overridden.
        opts = {};
      }

      debug('exchange %s %s', name);
      self._exchange = self._connection.exchange(name, opts, function(exchange) {
        return self.emit('ready');
      });
      self._exchange.on('error', function(err) {
        // NOTE: This will occur if an exchange is redeclared with different
        //       properties.
        //
        //       For example, the underlying `amqp` emits an error with the
        //       following properties:
        //         - message: PRECONDITION_FAILED - cannot redeclare exchange
        //                    'foo' in vhost '/' with different type, durable,
        //                    internal or autodelete value
        //         - code: 406
        return self.emit('error', err);
      });
    }
  });

  this._connection.on('error', this.emit.bind(this, 'error'));
}

/**
 * Publish a message to the exchange.
 *
 * In AMQP, publishing a message to an exchange has the effect of enqueuing that
 * message on all queues that are bound to the exchange with a routing key that
 * matches the topic.
 *
 * Examples:
 *
 *     broker.enqueue('tasks/mail', { to: 'bob@example.com', body: 'Welcome!' }, function(err) {
 *       if (err) { throw err; }
 *       ...
 *     });
 *
 *     broker.enqueue('metrics/cpu', { timestamp: 1396288552169, value: 32 });
 *
 * @param {String} topic
 * @param {Mixed} msg
 * @param {Object} options
 * @param {Function} cb
 * @api public
 */
Broker.prototype.enqueue = function(topic, msg, options, cb) {
  if (typeof options == 'function') {
    cb = options;
    options = undefined;
  }
  options = options || {};

  // AMQP uses period ('.') separators rather than slash ('/')
  topic = topic.replace(/\//g, '.');
  options.deliveryMode = (options.deliveryMode === undefined) ? PERSISTENT_MODE : options.deliveryMode;
  // TODO: This option appears to have no effect. Investigate why.
  //options.mandatory = (options.mandatory === undefined) ? true : options.mandatory;

  if (this._exchange.options && this._exchange.options.confirm) {
    debug('publish %s (confirm)', topic);
    this._exchange.publish(topic, msg, options, function(hadError, err) {
      if (hadError) {
        err = err || new Error('Failed to publish message to topic "' + topic + '"');
        return cb(err);
      }
      return cb();
    });
  } else {
    debug('publish %s', topic);
    this._exchange.publish(topic, msg, options);
    if (cb) { return process.nextTick(cb); }
  }
}

/**
 * Subscribe to messages enqueued in a queue.
 *
 * Once subscribed, messages will be delivered and emitted in `message` events.
 * A Crane application can be registered as a listener for these events,
 * allowing worker processes to be developed in a style similar to that of
 * Express applications.
 *
 * Examples:
 *
 *     broker.subscribe('tasks/mail', function(err) {
 *       if (err) { throw err; }
 *       ...
 *     });
 *
 *     broker.subscribe('tasks/serial', { exclusive: true }, function(err) {
 *       if (err) { throw err; }
 *       ...
 *     });
 *
 * @param {String} queue
 * @param {Object} options
 * @param {Function} cb
 * @api public
 */
Broker.prototype.subscribe = function(queue, options, cb) {
  if (typeof options == 'function') {
    cb = options;
    options = undefined;
  }
  options = options || {};

  // AMQP uses period ('.') separators rather than slash ('/')
  queue = queue.replace(/\//g, '.');
  options.ack = (options.ack === undefined) ? true : options.ack;

  var self = this
    , q = this._queues[queue];

  var onError = function(err) {
    return cb && cb(err);
  };

  debug('subscribe %s', queue);
  q.subscribe(options, function(message, headers, deliveryInfo) {
    var m = new Message(q, message, headers, deliveryInfo);
    m.broker = self;

    self.emit('message', m);
  }).addCallback(function(ok) {
    // This callback is invoked when the subscription was successful, and is
    // equivalent to the registering a listener for the queue's `basicConsumeOk`
    // event.
    q.removeListener('error', onError);

    self._ctags[queue] = ok.consumerTag;
    return cb && cb();
  }).addErrback(function(err) {
    // NOTE: Promise errbacks are not properly invoked by the underlying `amqp`
    //       module.  As a workaround, a listener is explicitly registered for
    //       the queue's `error` event.
  });

  // NOTE: This will occur if an attempt is made to subscribe to a queue that
  //       already has an exclusive subscription.
  //
  //       For example, the underlying `amqp` emits an error with the following
  //       properties:
  //         - message: ACCESS_REFUSED - queue 'foo' in vhost '/' in exclusive
  //                    use
  //         - code: 403
  q.once('error', onError);
}

Broker.prototype.declare = function(name, options, cb) {
  if (typeof options == 'function') {
    cb = options;
    options = undefined;
  }
  options = options || {};

  // AMQP uses period ('.') separators rather than slash ('/')
  name = name.replace(/\//g, '.');

  // Task queues are declared as durable, by default.  This ensures that tasks
  // are not lost in the event that that server is stopped or crashes.
  options.durable = (options.durable === undefined) ? true : options.durable;
  options.autoDelete = (options.autoDelete === undefined) ? false : options.autoDelete;

  var q = this._connection.queue(name, options, function(q) {
    q.removeListener('error', onQueueDeclareError);

    var exchange = options.bind;
    if (exchange) {
      // AMQP uses period ('.') separators rather than slash ('/')
      exchange = exchange.replace(/\//g, '.');

      // TODO: support binding to multiple topics
      var topic = options.topic || name;
      topic = topic.replace(/\//g, '.');

      q.bind(exchange, topic, function(q) {
        q.removeListener('error', onQueueBindError);
        return cb && cb();
      });

      // Listen for events that indicate that the queue failed to be bound.
      var onQueueBindError = function(err) {
        return cb && cb(err);
      };
      q.once('error', onQueueBindError);
    } else {
      return cb && cb();
    }
  });
  this._queues[name] = q;

  // Listen for events that indicate that the queue failed to be declared.
  var onQueueDeclareError = function(err) {
    return cb && cb(err);
  };
  q.once('error', onQueueDeclareError);
}

Broker.prototype.unsubscribe = function(queue, options, cb) {
  if (typeof options == 'function') {
    cb = options;
    options = undefined;
  }
  options = options || {};
  options.close = (options.close === undefined) ? true : options.close;

  // AMQP uses period ('.') separators rather than slash ('/')
  queue = queue.replace(/\//g, '.');

  var self = this
    , q = this._queues[queue]
    , ctag = this._ctags[queue];

  q.unsubscribe(ctag)
    .addCallback(function(ok) {
      delete self._ctags[queue];

      if (options.close) {
        q.close();
        return cb();
      } else {
        return cb();
      }
    })
    .addErrback(function(err) {
      // TODO: Handle this (figure out how to force this in a real-world scenario, invalid ctag???)
    });
}

/**
 * Expose `Broker`.
 */
module.exports = Broker;
<commit_msg>Rearrange code.<commit_after>/**
 * Module dependencies.
 */
var EventEmitter = require('events').EventEmitter
  , amqp = require('amqp')
  , util = require('util')
  , Message = require('./message')
  , debug = require('debug')('crane-amqp');

/**
 * Message delivery mode constants.
 */
var NONPERSISTENT_MODE = 1;
var PERSISTENT_MODE = 2;

/**
 * `Broker` constructor.
 *
 * @api public
 */
function Broker() {
  EventEmitter.call(this);
  this._exchange = null;
  this._queues = {};
  this._ctags = {};
}

/**
 * Inherit from `EventEmitter`.
 */
util.inherits(Broker, EventEmitter);

/**
 * Connect to AMQP server.
 *
 * For AMQP brokers, `options` argument should be an object that specifies the
 * following parameters:
 *
 *   - `port`  port the client should connect to, defaults to 5672
 *   - `host`  host the client should connect to, defaults to localhost
 *
 * Examples:
 *
 *     broker.connect({ host: '127.0.0.1', port: 5672 }, function() {
 *       console.log('ready');
 *     });
 *
 *     broker.connect({ host: '127.0.0.1', port: 5672, exchange: 'amq.topic' }, function() {
 *       console.log('ready');
 *     });
 *
 *     broker.connect({ host: '127.0.0.1', port: 5672,
 *                      exchange: {
 *                        name: 'app1.topic',
 *                        options: { type: 'topic', confirm: false }
 *                      } },
 *       function() {
 *         console.log('ready');
 *       });
 *
 * @param {Object} options
 * @param {Function} readyListener
 * @api public
 */
Broker.prototype.connect = function(options, readyListener) {
  if (readyListener) { this.once('ready', readyListener); }

  debug('connecting %s:%s', options.host || 'localhost', options.port || 5672);

  var self = this;
  this._connection = amqp.createConnection(options);
  this._connection.once('ready', function() {
    var exchange = options.exchange;
    if (!exchange) {
      debug('default exchange');

      // Get the default exchange, which is a direct exchange, and thus suitable
      // for use as a task queue.
      self._exchange = self._connection.exchange();
      // TODO: Emit ready after callback to `exchange()`.
      return self.emit('ready');
    } else {
      var name = exchange
        , opts = {};
      if (typeof exchange == 'object') {
        name = exchange.name;
        opts = exchange.options;
      }

      // AMQP uses period ('.') separators rather than slash ('/')
      name = name.replace(/\//g, '.');
      if (name.indexOf('amq.') !== 0) {
        opts.type = (opts.type === undefined) ? 'direct' : opts.type;
        opts.durable = (opts.durable === undefined) ? true : opts.durable;
        opts.autoDelete = (opts.autoDelete === undefined) ? false : opts.autoDelete;
        opts.confirm = (opts.confirm === undefined) ? true : opts.confirm;
      } else {
        // Options for built-in exchanges can not be overridden.
        opts = {};
      }

      debug('exchange %s %s', name);
      self._exchange = self._connection.exchange(name, opts, function(exchange) {
        return self.emit('ready');
      });
      self._exchange.on('error', function(err) {
        // NOTE: This will occur if an exchange is redeclared with different
        //       properties.
        //
        //       For example, the underlying `amqp` emits an error with the
        //       following properties:
        //         - message: PRECONDITION_FAILED - cannot redeclare exchange
        //                    'foo' in vhost '/' with different type, durable,
        //                    internal or autodelete value
        //         - code: 406
        return self.emit('error', err);
      });
    }
  });

  this._connection.on('error', this.emit.bind(this, 'error'));
}

/**
 * Publish a message to the exchange.
 *
 * In AMQP, publishing a message to an exchange has the effect of enqueuing that
 * message on all queues that are bound to the exchange with a routing key that
 * matches the topic.
 *
 * Examples:
 *
 *     broker.enqueue('tasks/mail', { to: 'bob@example.com', body: 'Welcome!' }, function(err) {
 *       if (err) { throw err; }
 *       ...
 *     });
 *
 *     broker.enqueue('metrics/cpu', { timestamp: 1396288552169, value: 32 });
 *
 * @param {String} topic
 * @param {Mixed} msg
 * @param {Object} options
 * @param {Function} cb
 * @api public
 */
Broker.prototype.enqueue = function(topic, msg, options, cb) {
  if (typeof options == 'function') {
    cb = options;
    options = undefined;
  }
  options = options || {};

  // AMQP uses period ('.') separators rather than slash ('/')
  topic = topic.replace(/\//g, '.');
  options.deliveryMode = (options.deliveryMode === undefined) ? PERSISTENT_MODE : options.deliveryMode;
  // TODO: This option appears to have no effect. Investigate why.
  //options.mandatory = (options.mandatory === undefined) ? true : options.mandatory;

  if (this._exchange.options && this._exchange.options.confirm) {
    debug('publish %s (confirm)', topic);
    this._exchange.publish(topic, msg, options, function(hadError, err) {
      if (hadError) {
        err = err || new Error('Failed to publish message to topic "' + topic + '"');
        return cb(err);
      }
      return cb();
    });
  } else {
    debug('publish %s', topic);
    this._exchange.publish(topic, msg, options);
    if (cb) { return process.nextTick(cb); }
  }
}

/**
 * Subscribe to messages enqueued in a queue.
 *
 * Once subscribed, messages will be delivered and emitted in `message` events.
 * A Crane application can be registered as a listener for these events,
 * allowing worker processes to be developed in a style similar to that of
 * Express applications.
 *
 * Examples:
 *
 *     broker.subscribe('tasks/mail', function(err) {
 *       if (err) { throw err; }
 *       ...
 *     });
 *
 *     broker.subscribe('tasks/serial', { exclusive: true }, function(err) {
 *       if (err) { throw err; }
 *       ...
 *     });
 *
 * @param {String} queue
 * @param {Object} options
 * @param {Function} cb
 * @api public
 */
Broker.prototype.subscribe = function(queue, options, cb) {
  if (typeof options == 'function') {
    cb = options;
    options = undefined;
  }
  options = options || {};

  // AMQP uses period ('.') separators rather than slash ('/')
  queue = queue.replace(/\//g, '.');
  options.ack = (options.ack === undefined) ? true : options.ack;

  var self = this
    , q = this._queues[queue];

  var onError = function(err) {
    return cb && cb(err);
  };

  debug('subscribe %s', queue);
  q.subscribe(options, function(message, headers, deliveryInfo) {
    var m = new Message(q, message, headers, deliveryInfo);
    m.broker = self;

    self.emit('message', m);
  }).addCallback(function(ok) {
    // This callback is invoked when the subscription was successful, and is
    // equivalent to the registering a listener for the queue's `basicConsumeOk`
    // event.
    q.removeListener('error', onError);

    self._ctags[queue] = ok.consumerTag;
    return cb && cb();
  }).addErrback(function(err) {
    // NOTE: Promise errbacks are not properly invoked by the underlying `amqp`
    //       module.  As a workaround, a listener is explicitly registered for
    //       the queue's `error` event.
  });

  // NOTE: This will occur if an attempt is made to subscribe to a queue that
  //       already has an exclusive subscription.
  //
  //       For example, the underlying `amqp` emits an error with the following
  //       properties:
  //         - message: ACCESS_REFUSED - queue 'foo' in vhost '/' in exclusive
  //                    use
  //         - code: 403
  q.once('error', onError);
}

Broker.prototype.unsubscribe = function(queue, options, cb) {
  if (typeof options == 'function') {
    cb = options;
    options = undefined;
  }
  options = options || {};
  options.close = (options.close === undefined) ? true : options.close;

  // AMQP uses period ('.') separators rather than slash ('/')
  queue = queue.replace(/\//g, '.');

  var self = this
    , q = this._queues[queue]
    , ctag = this._ctags[queue];

  q.unsubscribe(ctag)
    .addCallback(function(ok) {
      delete self._ctags[queue];

      if (options.close) {
        q.close();
        return cb();
      } else {
        return cb();
      }
    })
    .addErrback(function(err) {
      // TODO: Handle this (figure out how to force this in a real-world scenario, invalid ctag???)
    });
}

Broker.prototype.declare = function(name, options, cb) {
  if (typeof options == 'function') {
    cb = options;
    options = undefined;
  }
  options = options || {};

  // AMQP uses period ('.') separators rather than slash ('/')
  name = name.replace(/\//g, '.');

  // Task queues are declared as durable, by default.  This ensures that tasks
  // are not lost in the event that that server is stopped or crashes.
  options.durable = (options.durable === undefined) ? true : options.durable;
  options.autoDelete = (options.autoDelete === undefined) ? false : options.autoDelete;

  var q = this._connection.queue(name, options, function(q) {
    q.removeListener('error', onQueueDeclareError);

    var exchange = options.bind;
    if (exchange) {
      // AMQP uses period ('.') separators rather than slash ('/')
      exchange = exchange.replace(/\//g, '.');

      // TODO: support binding to multiple topics
      var topic = options.topic || name;
      topic = topic.replace(/\//g, '.');

      q.bind(exchange, topic, function(q) {
        q.removeListener('error', onQueueBindError);
        return cb && cb();
      });

      // Listen for events that indicate that the queue failed to be bound.
      var onQueueBindError = function(err) {
        return cb && cb(err);
      };
      q.once('error', onQueueBindError);
    } else {
      return cb && cb();
    }
  });
  this._queues[name] = q;

  // Listen for events that indicate that the queue failed to be declared.
  var onQueueDeclareError = function(err) {
    return cb && cb(err);
  };
  q.once('error', onQueueDeclareError);
}

/**
 * Expose `Broker`.
 */
module.exports = Broker;
<|endoftext|>


<commit_before>require('../support')
import { mount } from 'enzyme'
import React from 'react'
import CommunityPosts from '../../../src/containers/community/CommunityPosts'
import { configureStore } from '../../../src/store'

const community = {
  id: '1',
  slug: 'foomunity',
  name: 'Foom Unity',
  beta_access_code: 'foom',
  description: 'Social cohesion in the face of AI hard takeoff'
}

const currentUser = {
  id: '5',
  memberships: {
    [community.slug]: {
      community_id: community.id
    }
  }
}

describe('CommunityPosts', () => {
  var store

  beforeEach(() => {
    store = configureStore({
      communities: {[community.slug]: community}
    }).store
    window.FEATURE_FLAGS = {
      REQUEST_TO_JOIN_COMMUNITY: 'on',
      COMMUNITY_SETUP_CHECKLIST: 'on'
    }
  })

  it('renders without errors', () => {
    const props = {
      params: {id: community.slug},
      location: {}
    }

    const node = mount(<CommunityPosts {...props}/>, {
      context: {store, currentUser},
      childContextTypes: {currentUser: React.PropTypes.object}
    })

    expect(node.find('.community-setup').length).to.equal(1)

    expect(node.find('.post-editor').length).to.equal(1)

    expect(node.find('.no-results').length).to.equal(1)
  })

  it('displays request to join and no PostEditor, when not a member', () => {
    const props = {
      params: {id: community.slug},
      location: {}
    }

    const node = mount(<CommunityPosts {...props}/>, {
      context: {store, currentUser: {id: 6}},
      childContextTypes: {currentUser: React.PropTypes.object}
    })

    expect(node.find('.post-editor').length).to.equal(0)

    expect(node.find('.request-to-join').text())
    .to.equal('You are not a member of this community. Request to Join')
  })
})
<commit_msg>fix test<commit_after>require('../support')
import { mount } from 'enzyme'
import React from 'react'
import CommunityPosts from '../../../src/containers/community/CommunityPosts'
import { configureStore } from '../../../src/store'
import { MemberRole } from '../../../src/models/community'

const community = {
  id: '1',
  slug: 'foomunity',
  name: 'Foom Unity',
  beta_access_code: 'foom',
  description: 'Social cohesion in the face of AI hard takeoff'
}

const currentUser = {
  id: '5',
  memberships: {
    [community.slug]: {
      community_id: community.id,
      role: MemberRole.MODERATOR
    }
  }
}

describe('CommunityPosts', () => {
  var store

  beforeEach(() => {
    store = configureStore({
      communities: {[community.slug]: community}
    }).store
    window.FEATURE_FLAGS = {
      REQUEST_TO_JOIN_COMMUNITY: 'on',
      COMMUNITY_SETUP_CHECKLIST: 'on'
    }
  })

  it('renders without errors', () => {
    const props = {
      params: {id: community.slug},
      location: {}
    }

    const node = mount(<CommunityPosts {...props}/>, {
      context: {store, currentUser},
      childContextTypes: {currentUser: React.PropTypes.object}
    })

    expect(node.find('.community-setup').length).to.equal(1)

    expect(node.find('.post-editor').length).to.equal(1)

    expect(node.find('.no-results').length).to.equal(1)
  })

  it('displays request to join and no PostEditor, when not a member', () => {
    const props = {
      params: {id: community.slug},
      location: {}
    }

    const node = mount(<CommunityPosts {...props}/>, {
      context: {store, currentUser: {id: 6}},
      childContextTypes: {currentUser: React.PropTypes.object}
    })

    expect(node.find('.post-editor').length).to.equal(0)

    expect(node.find('.request-to-join').text())
    .to.equal('You are not a member of this community. Request to Join')
  })
})
<|endoftext|>


<commit_before>/*
 * Project: Tyval
 * Version: 1.0.0
 * Author: delvedor
 * Twitter: @delvedor
 * License: MIT
 * GitHub: https://github.com/delvedor/Tyval
 */

'use strict'

// Tyval Constructor
function tyval (variable, planned) {
  return new tyval.Init(variable, planned)
}

tyval.prototype = {
  // Checks if the variable is a string
  isString: function () {
    this.check &= this.type === 'string'
    return this.plan()
  },

  // Checks if the variable is a number
  isNumber: function () {
    this.check &= this.type === 'number'
    return this.plan()
  },

  // Checks if the variable is null
  isNull: function () {
    this.check &= this.type === 'null'
    return this.plan()
  },

  // Checks if the variable is undefined
  isUndefined: function () {
    this.check &= this.type === 'undefined'
    return this.plan()
  },

  // Checks if the variable is a boolean
  isBoolean: function () {
    this.check &= this.type === 'boolean'
    return this.plan()
  },

  // Checks if the variable is an object
  isObject: function () {
    this.check &= this.type === 'object'
    return this.plan()
  },

  // Checks if the variable is a function
  isFunction: function () {
    this.check &= this.type === 'function'
    return this.plan()
  },

  // Checks if the variable is lower than the passed max value
  max: function (max = 0) {
    switch (this.type) {
      case 'number':
        this.check &= this.variable <= max
        break
      case 'string':
        this.check &= this.variable.length <= max
        break
      default:
        this.check = false
    }
    return this.plan()
  },

  // Checks if the variable is higher than the passed min value
  min: function (min = 0) {
    switch (this.type) {
      case 'number':
        this.check &= this.variable >= min
        break
      case 'string':
        this.check &= this.variable.length >= min
        break
      default:
        this.check = false
    }
    return this.plan()
  },

  positive: function () {
    this.check &= this.variable > 0
    return this.plan()
  },

  negative: function () {
    this.check &= this.variable < 0
    return this.plan()
  },

  // Checks if the Number is an Integer
  integer: function () {
    this.check &= Number.isInteger(this.variable)
    return this.plan()
  },

  // Checks if the Number is a Float
  float: function () {
    this.check &= !Number.isInteger(this.variable)
    return this.plan()
  },

  // Checks if the Number is a safe Integer
  safeInteger: function () {
    this.check &= Number.isSafeInteger(this.variable)
    return this.plan()
  },

  // Checks if the Number is finite
  finite: function () {
    this.check &= Number.isFinite(this.variable)
    return this.plan()
  },

  // Adds a new function to Tyval
  extend: function (func) {
    tyval.prototype[func.name] = func
    return this.plan()
  },

  // Checks if all the planned tests are over
  plan: function () {
    return this.planned === ++this.passed ? !!this.check : this
  }
}

// Trick borrowed from jQuery
tyval.Init = function (variable, planned) {
  if (!(this instanceof tyval.Init)) return new tyval.Init(variable, planned)
  // Binary validator
  tyval.prototype.check = 1
  // Variable passed as input
  tyval.prototype.variable = variable
  // Type of the variable
  // the conditional operator because typeof null = 'object'
  tyval.prototype.type = variable === null ? 'null' : typeof variable
  // planned validation test
  tyval.prototype.planned = planned
  // how many test are over
  tyval.prototype.passed = 0
}

tyval.Init.prototype = tyval.prototype

module.exports = tyval
<commit_msg>Added alphanum and regex<commit_after>/*
 * Project: Tyval
 * Version: 1.0.0
 * Author: delvedor
 * Twitter: @delvedor
 * License: MIT
 * GitHub: https://github.com/delvedor/Tyval
 */

'use strict'

// Tyval Constructor
function tyval (variable, planned) {
  return new tyval.Init(variable, planned)
}

tyval.prototype = {
  // Checks if the variable is a string
  isString: function () {
    this.check &= this.type === 'string'
    return this.plan()
  },

  // Checks if the variable is a number
  isNumber: function () {
    this.check &= this.type === 'number'
    return this.plan()
  },

  // Checks if the variable is null
  isNull: function () {
    this.check &= this.type === 'null'
    return this.plan()
  },

  // Checks if the variable is undefined
  isUndefined: function () {
    this.check &= this.type === 'undefined'
    return this.plan()
  },

  // Checks if the variable is a boolean
  isBoolean: function () {
    this.check &= this.type === 'boolean'
    return this.plan()
  },

  // Checks if the variable is an object
  isObject: function () {
    this.check &= this.type === 'object'
    return this.plan()
  },

  // Checks if the variable is a function
  isFunction: function () {
    this.check &= this.type === 'function'
    return this.plan()
  },

  // Checks if the string is alphanumeric
  alphanum: function () {
    const reg = /((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+[0-9a-z]+$/i
    this.check &= reg.test(this.variable)
    return this.plan()
  },

  // Tests the regex passed as input
  regex: function (reg) {
    this.check &= reg.test(this.variable)
    return this.plan()
  },

  // Checks if the variable is lower than the passed max value
  max: function (max = 0) {
    switch (this.type) {
      case 'number':
        this.check &= this.variable <= max
        break
      case 'string':
        this.check &= this.variable.length <= max
        break
      default:
        this.check = false
    }
    return this.plan()
  },

  // Checks if the variable is higher than the passed min value
  min: function (min = 0) {
    switch (this.type) {
      case 'number':
        this.check &= this.variable >= min
        break
      case 'string':
        this.check &= this.variable.length >= min
        break
      default:
        this.check = false
    }
    return this.plan()
  },

  positive: function () {
    this.check &= this.variable > 0
    return this.plan()
  },

  negative: function () {
    this.check &= this.variable < 0
    return this.plan()
  },

  // Checks if the Number is an Integer
  integer: function () {
    this.check &= Number.isInteger(this.variable)
    return this.plan()
  },

  // Checks if the Number is a Float
  float: function () {
    this.check &= !Number.isInteger(this.variable)
    return this.plan()
  },

  // Checks if the Number is a safe Integer
  safeInteger: function () {
    this.check &= Number.isSafeInteger(this.variable)
    return this.plan()
  },

  // Checks if the Number is finite
  finite: function () {
    this.check &= Number.isFinite(this.variable)
    return this.plan()
  },

  // Adds a new function to Tyval
  extend: function (func) {
    tyval.prototype[func.name] = func
    return this.plan()
  },

  // Checks if all the planned tests are over
  plan: function () {
    return this.planned === ++this.passed ? !!this.check : this
  }
}

// Trick borrowed from jQuery
tyval.Init = function (variable, planned) {
  if (!(this instanceof tyval.Init)) return new tyval.Init(variable, planned)
  // Binary validator
  tyval.prototype.check = 1
  // Variable passed as input
  tyval.prototype.variable = variable
  // Type of the variable
  // the conditional operator because typeof null = 'object'
  tyval.prototype.type = variable === null ? 'null' : typeof variable
  // planned validation test
  tyval.prototype.planned = planned
  // how many test are over
  tyval.prototype.passed = 0
}

tyval.Init.prototype = tyval.prototype

module.exports = tyval
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const EventEmitter = require('events').EventEmitter;
const ProxyReporter = require('../../../../lib/runner/mocha-runner/proxy-reporter');

describe('mocha-runner/proxy-reporter', () => {
    const sandbox = sinon.sandbox.create();

    let runner;
    let emit;

    const createReporter_ = (browserProps) => {
        browserProps = _.defaults(browserProps || {}, {
            sessionId: 'default-session-id',
            id: 'default-browser'
        });

        const getBrowser = sinon.stub().returns(browserProps);
        return new ProxyReporter(emit, getBrowser, runner);
    };

    const testTranslateEvent_ = (from, to) => {
        it(`should translate event "${from}" to event "${to}"`, () => {
            createReporter_();

            runner.emit(from, {slow: sinon.stub()}); // slow will be called by Mocha.BaseReporter inside

            assert.calledWith(emit, to);
        });
    };

    beforeEach(() => {
        runner = new EventEmitter();
        emit = sandbox.stub().named('emit');
    });

    afterEach(() => sandbox.restore());

    testTranslateEvent_('suite', 'beginSuite');
    testTranslateEvent_('suite end', 'endSuite');
    testTranslateEvent_('test', 'beginTest');
    testTranslateEvent_('test end', 'endTest');
    testTranslateEvent_('pass', 'passTest');
    testTranslateEvent_('pending', 'pendingTest');

    describe('"pending" event', () => {
        beforeEach(() => createReporter_());

        it('should not translate "pending" event if an entity was skipped silently', () => {
            runner.emit('pending', {silentSkip: true});

            assert.notCalled(emit);
        });

        it('should not translate "pending" event if a parent of an entity was skipped silently', () => {
            runner.emit('pending', {parent: {parent: {silentSkip: true}}});

            assert.notCalled(emit);
        });

        it('should translate "pending" event if an entity was not skipped silently', () => {
            runner.emit('pending', {foo: 'bar'});

            assert.calledWithMatch(emit, 'pending', {foo: 'bar'});
        });
    });

    it('should translate `fail` event from test to `failTest`', () => {
        createReporter_();

        runner.emit('fail', {type: 'test'}, {message: 'foo'});

        assert.calledWithMatch(emit, 'failTest', {
            err: {message: 'foo'}
        });
    });

    it('should translate `fail` event from after* hook to `err`', () => {
        createReporter_();

        const hook = {
            type: 'hook',
            title: '"after each" hook for "some test"',
            originalTitle: '"after each" hook',
            ctx: {
                currentTest: {
                    title: 'some test'
                }
            }
        };

        runner.emit('fail', hook, {message: 'foo'});

        assert.calledWithMatch(emit, 'err',
            {message: 'foo'},
            hook
        );
    });

    it('should translate `fail` event from hook without currentTest to `err`', () => {
        createReporter_();

        const hook = {
            type: 'hook',
            title: '"before All" hook',
            ctx: {}
        };

        runner.emit('fail', hook, {message: 'foo'});

        assert.calledWithMatch(emit, 'err',
            {message: 'foo'},
            hook
        );
    });

    it('should translate `fail` event from other source to `err`', () => {
        createReporter_();

        runner.emit('fail', {title: 'some-title'}, {message: 'foo'});

        assert.calledWithMatch(emit, 'err',
            {message: 'foo'},
            {title: 'some-title'}
        );
    });

    it('should translate test data from mocha', () => {
        createReporter_();

        runner.emit('suite', {foo: 'bar'});

        assert.calledWithMatch(emit, 'beginSuite', {
            foo: 'bar'
        });
    });

    it('should add `browserId` and `sessionId`', () => {
        createReporter_({id: 'browserId', sessionId: 'mySessionId'});

        runner.emit('suite', {foo: 'bar'});

        assert.calledWithMatch(emit, 'beginSuite', {
            browserId: 'browserId',
            sessionId: 'mySessionId'
        });
    });

    it('should add meta info copy', () => {
        const meta = {url: '/some/url'};
        createReporter_({meta});

        runner.emit('pass', {slow: sinon.stub()});

        assert.calledWithMatch(emit, 'passTest', {meta});
        assert.notStrictEqual(emit.firstCall.args[1].meta, meta);
    });
});
<commit_msg>refactor: tests on 'ProxyReporter'<commit_after>'use strict';

const _ = require('lodash');
const EventEmitter = require('events').EventEmitter;
const ProxyReporter = require('../../../../lib/runner/mocha-runner/proxy-reporter');

describe('mocha-runner/proxy-reporter', () => {
    const sandbox = sinon.sandbox.create();

    let runner;
    let emit;

    const createReporter_ = (browserProps) => {
        browserProps = _.defaults(browserProps || {}, {
            sessionId: 'default-session-id',
            id: 'default-browser'
        });

        const getBrowser = sinon.stub().returns(browserProps);
        return new ProxyReporter(emit, getBrowser, runner);
    };

    const testTranslateEvent_ = (from, to) => {
        it(`should translate event "${from}" to event "${to}"`, () => {
            createReporter_();

            runner.emit(from, {slow: sinon.stub()}); // slow will be called by Mocha.BaseReporter inside

            assert.calledWith(emit, to);
        });
    };

    beforeEach(() => {
        runner = new EventEmitter();
        emit = sandbox.stub().named('emit');
    });

    afterEach(() => sandbox.restore());

    testTranslateEvent_('suite', 'beginSuite');
    testTranslateEvent_('suite end', 'endSuite');
    testTranslateEvent_('test', 'beginTest');
    testTranslateEvent_('test end', 'endTest');
    testTranslateEvent_('pass', 'passTest');
    testTranslateEvent_('pending', 'pendingTest');

    describe('"pending" event', () => {
        beforeEach(() => createReporter_());

        it('should not translate "pending" event if an entity was skipped silently', () => {
            runner.emit('pending', {silentSkip: true});

            assert.notCalled(emit);
        });

        it('should not translate "pending" event if a parent of an entity was skipped silently', () => {
            runner.emit('pending', {parent: {parent: {silentSkip: true}}});

            assert.notCalled(emit);
        });

        it('should translate "pending" event if an entity was not skipped silently', () => {
            runner.emit('pending', {foo: 'bar'});

            assert.calledWithMatch(emit, 'pending', {foo: 'bar'});
        });
    });

    describe('"fail" event', () => {
        beforeEach(() => createReporter_());

        it('should translate `fail` event from test to `failTest`', () => {
            runner.emit('fail', {type: 'test'}, {message: 'foo'});

            assert.calledWithMatch(emit, 'failTest', {
                err: {message: 'foo'}
            });
        });

        it('should translate `fail` event from after* hook to `err`', () => {
            const hook = {
                type: 'hook',
                title: '"after each" hook for "some test"',
                originalTitle: '"after each" hook',
                ctx: {
                    currentTest: {
                        title: 'some test'
                    }
                }
            };

            runner.emit('fail', hook, {message: 'foo'});

            assert.calledWithMatch(emit, 'err',
                {message: 'foo'},
                hook
            );
        });

        it('should translate `fail` event from hook without currentTest to `err`', () => {
            const hook = {
                type: 'hook',
                title: '"before All" hook',
                ctx: {}
            };

            runner.emit('fail', hook, {message: 'foo'});

            assert.calledWithMatch(emit, 'err',
                {message: 'foo'},
                hook
            );
        });

        it('should translate `fail` event from other source to `err`', () => {
            runner.emit('fail', {title: 'some-title'}, {message: 'foo'});

            assert.calledWithMatch(emit, 'err',
                {message: 'foo'},
                {title: 'some-title'}
            );
        });
    });

    it('should translate test data from mocha', () => {
        createReporter_();

        runner.emit('suite', {foo: 'bar'});

        assert.calledWithMatch(emit, 'beginSuite', {
            foo: 'bar'
        });
    });

    it('should add `browserId` and `sessionId`', () => {
        createReporter_({id: 'browserId', sessionId: 'mySessionId'});

        runner.emit('suite', {foo: 'bar'});

        assert.calledWithMatch(emit, 'beginSuite', {
            browserId: 'browserId',
            sessionId: 'mySessionId'
        });
    });

    it('should add meta info copy', () => {
        const meta = {url: '/some/url'};
        createReporter_({meta});

        runner.emit('pass', {slow: sinon.stub()});

        assert.calledWithMatch(emit, 'passTest', {meta});
        assert.notStrictEqual(emit.firstCall.args[1].meta, meta);
    });
});
<|endoftext|>


<commit_before>import expect from 'expect';
import RAFTimer from '../src/index';

describe('RAFTimer', function(){
  it('exists', function(){
    expect(RAFTimer).toExist();
  });

  it('can be intantiated', function(){
    const instance = new RAFTimer();
    expect(instance).toExist();
    expect(instance).toBeA(RAFTimer);
  });
});
<commit_msg>test the step function<commit_after>import expect from 'expect';
import RAFTimer from '../src/index';

describe('RAFTimer', function(){
  it('exists', function(){
    expect(RAFTimer).toExist();
  });

  it('can be intantiated', function(){
    const instance = new RAFTimer();
    expect(instance).toExist();
    expect(instance).toBeA(RAFTimer);
  });

  describe('#step', function(){
    it('increments the time(ms) by the delta(s)', function(done) {
      const timer = new RAFTimer();
      const previousTime = timer.time;
      process.nextTick(function(){
        timer.step();
        const newTime = timer.time;

        expect(previousTime).toBeLessThan(newTime);
        expect(newTime - previousTime).toEqual(timer.delta * 1000);

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