<commit_before>var FieldValueRenderer = function () {

	function EmptyValueRenderer() {
		this.render = function () {
			return ' ';
		}
	}

	function UnknownTypeValueRenderer() {
		this.render = function ( fieldValue ) {
			return fieldValue;
		}
	}

	function StringValueRenderer() {
		this.render = function ( dataValue ) {
			if ( dataValue.length == 0 ) {
				return ' ';
			}
			return $.trim( dataValue );
		}
	}

	function NumericValueRenderer() {
		this.render = function ( dataValue ) {
			return dataValue;
		}
	}

	function BooleanValueRenderer() {
		this.render = function ( fieldValue ) {
			return fieldValue ? 'Yes' : 'No';
		}
	}

	function ArrayValueRenderer() {
		this.render = function ( fieldValue ) {
			var items = '';
			for ( var arrayIndex in fieldValue ) {
				var arrayItem = fieldValue[arrayIndex];
				if ( arrayItem['stringRepresentation'] !== undefined ) {
					items += arrayItem['stringRepresentation'] + '
';
				}
			}
			return items.length != 0 ? items : ' ';
		}
	}

	function DomainObjectValueRenderer() {
		this.render = function ( dataValue ) {
			var stringRepresentation = dataValue['stringRepresentation'];

			if ( dataValue['links'] === undefined ) {
				return stringRepresentation;
			}

			return "" + stringRepresentation + "";
		}
	}

	function isDomainObject( fieldValue ) {
		return typeof fieldValue === 'object' && fieldValue['stringRepresentation'] !== undefined;
	}

	function createRenderer( fieldValue ) {
		if ( $.isPlainObject( fieldValue ) ) {
			if ( fieldValue instanceof Array ) {
				return new ArrayValueRenderer();
			}
			if ( isDomainObject( fieldValue ) ) {
				return new DomainObjectValueRenderer();
			}

			return new UnknownTypeValueRenderer();
		}

		if ( typeof fieldValue == 'string' ) {
			return new StringValueRenderer();
		}

		if ( typeof fieldValue == 'number' ) {
			return new NumericValueRenderer();
		}

		if ( typeof fieldValue == 'boolean' ) {
			return new BooleanValueRenderer();
		}

		return new UnknownTypeValueRenderer();
	}

	return {
		render: function ( fieldValue ) {
			if ( fieldValue == null ) {
				return new EmptyValueRenderer().render();
			}

			return createRenderer( fieldValue ).render( fieldValue );
		}
	};
}();<commit_msg>Selenium test fixed [Broken array field type rendering].<commit_after>var FieldValueRenderer = function () {

	function EmptyValueRenderer() {
		this.render = function () {
			return ' ';
		}
	}

	function UnknownTypeValueRenderer() {
		this.render = function ( fieldValue ) {
			return fieldValue;
		}
	}

	function StringValueRenderer() {
		this.render = function ( dataValue ) {
			if ( dataValue.length == 0 ) {
				return ' ';
			}
			return $.trim( dataValue );
		}
	}

	function NumericValueRenderer() {
		this.render = function ( dataValue ) {
			return dataValue;
		}
	}

	function BooleanValueRenderer() {
		this.render = function ( fieldValue ) {
			return fieldValue ? 'Yes' : 'No';
		}
	}

	function ArrayValueRenderer() {
		this.render = function ( fieldValue ) {
			var items = '';
			for ( var arrayIndex in fieldValue ) {
				var arrayItem = fieldValue[arrayIndex];
				if ( arrayItem['stringRepresentation'] !== undefined ) {
					items += arrayItem['stringRepresentation'] + '
';
				}
			}
			return items.length != 0 ? items : ' ';
		}
	}

	function DomainObjectValueRenderer() {
		this.render = function ( dataValue ) {
			var stringRepresentation = dataValue['stringRepresentation'];

			if ( dataValue['links'] === undefined ) {
				return stringRepresentation;
			}

			return "" + stringRepresentation + "";
		}
	}

	function isDomainObject( fieldValue ) {
		return typeof fieldValue === 'object' && fieldValue['stringRepresentation'] !== undefined;
	}

	function createRenderer( fieldValue ) {
		if ( fieldValue instanceof Array ) {
			return new ArrayValueRenderer();
		}

		if ( $.isPlainObject( fieldValue ) && isDomainObject( fieldValue ) ) {
			return new DomainObjectValueRenderer();
		}

		if ( typeof fieldValue == 'string' ) {
			return new StringValueRenderer();
		}

		if ( typeof fieldValue == 'number' ) {
			return new NumericValueRenderer();
		}

		if ( typeof fieldValue == 'boolean' ) {
			return new BooleanValueRenderer();
		}

		return new UnknownTypeValueRenderer();
	}

	return {
		render: function ( fieldValue ) {
			if ( fieldValue == null ) {
				return new EmptyValueRenderer().render();
			}

			return createRenderer( fieldValue ).render( fieldValue );
		}
	};
}();<|endoftext|>


<commit_before>
'use strict';

var fs = require('fs');
var path = require('path');

var supertest = require('supertest');
var expect = require('thehelp-test').expect;
var util = require('./util');

var WORKER_STARTUP = 1500; // milliseconds

var winston;

try {
  winston = require('winston');
}
catch (e) {}

describe('winston creates expected log files', function() {
  var agent, child, logFiles;

  before(function(done) {
    agent = supertest.agent('http://localhost:3000');

    util.emptyDir(util.logsDir, function(err) {
      if (err) {
        throw err;
      }

      child = util.startProcess(
        path.join(__dirname, '../../scenarios/end_to_end_cluster.js'));

      setTimeout(done, 1000);
    });
  });

  after(function(done) {
    this.timeout(10000);

    child.on('close', function() {

      // let's also validate that the master process was logging
      var contents = fs.readFileSync(path.join(util.logsDir, logFiles[0]));
      contents = contents.toString();
      expect(contents).to.match(/Master calling all provided pre-exit check functions/);

      done();
    });

    child.kill();
  });

  it('creates two log files on startup', function(done) {
    if (!winston) {
      return done();
    }

    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      expect(files).to.have.length(2);

      files = files.sort();
      expect(files).to.have.deep.property('0').that.match(/master/);
      expect(files).to.have.deep.property('1').that.match(/worker/);

      logFiles = files;

      done();
    });
  });

  it('root returns', function(done) {
    agent
      .get('/')
      .expect('X-Worker', '1')
      .expect('Connection', 'close')
      .expect(200, done);
  });

  it('on async error, gets response with \'close connection\' header', function(done) {
    agent
      .get('/error')
      .expect('Connection', 'close')
      .expect('Content-Type', /text\/plain/)
      .expect('X-Worker', '1')
      .expect(/^error\!/)
      .expect(500, function(err) {
        if (err) {
          throw err;
        }

        setTimeout(done, WORKER_STARTUP);
      });
  });

  it('starts up another node', function(done) {
    this.timeout(5000);

    agent
      .get('/')
      .expect('X-Worker', '2')
      .expect('Connection', 'close')
      .expect(200, done);
  });

  it('three log files now in directory', function(done) {
    if (!winston) {
      return done();
    }

    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      expect(files).to.have.length(3);

      files = files.sort();
      expect(files).to.have.deep.property('0', logFiles[0]);
      expect(files).to.have.deep.property('1', logFiles[1]);
      expect(files).to.have.deep.property('2').that.match(/worker/);

      logFiles = files;

      done();
    });
  });

});
<commit_msg>Increase startup timeout/delay for logging test<commit_after>
'use strict';

var fs = require('fs');
var path = require('path');

var supertest = require('supertest');
var expect = require('thehelp-test').expect;
var util = require('./util');

var WORKER_STARTUP = 1500; // milliseconds

var winston;

try {
  winston = require('winston');
}
catch (e) {}

describe('winston creates expected log files', function() {
  var agent, child, logFiles;

  before(function(done) {
    this.timeout(5000);

    agent = supertest.agent('http://localhost:3000');

    util.emptyDir(util.logsDir, function(err) {
      if (err) {
        throw err;
      }

      child = util.startProcess(
        path.join(__dirname, '../../scenarios/end_to_end_cluster.js'));

      setTimeout(done, 2000);
    });
  });

  after(function(done) {
    this.timeout(10000);

    child.on('close', function() {

      // let's also validate that the master process was logging
      var contents = fs.readFileSync(path.join(util.logsDir, logFiles[0]));
      contents = contents.toString();
      expect(contents).to.match(/Master calling all provided pre-exit check functions/);

      done();
    });

    child.kill();
  });

  it('creates two log files on startup', function(done) {
    if (!winston) {
      return done();
    }

    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      files = files.sort();
      logFiles = files;

      expect(files).to.have.length(2);

      expect(files).to.have.deep.property('0').that.match(/master/);
      expect(files).to.have.deep.property('1').that.match(/worker/);

      done();
    });
  });

  it('root returns', function(done) {
    agent
      .get('/')
      .expect('X-Worker', '1')
      .expect('Connection', 'close')
      .expect(200, done);
  });

  it('on async error, gets response with \'close connection\' header', function(done) {
    agent
      .get('/error')
      .expect('Connection', 'close')
      .expect('Content-Type', /text\/plain/)
      .expect('X-Worker', '1')
      .expect(/^error\!/)
      .expect(500, function(err) {
        if (err) {
          throw err;
        }

        setTimeout(done, WORKER_STARTUP);
      });
  });

  it('starts up another node', function(done) {
    this.timeout(5000);

    agent
      .get('/')
      .expect('X-Worker', '2')
      .expect('Connection', 'close')
      .expect(200, done);
  });

  it('three log files now in directory', function(done) {
    if (!winston) {
      return done();
    }

    fs.readdir(util.logsDir, function(err, files) {
      if (err) {
        throw err;
      }

      expect(files).to.have.length(3);

      files = files.sort();
      expect(files).to.have.deep.property('0', logFiles[0]);
      expect(files).to.have.deep.property('1', logFiles[1]);
      expect(files).to.have.deep.property('2').that.match(/worker/);

      logFiles = files;

      done();
    });
  });

});
<|endoftext|>


<commit_before>/* global describe, it */

'use strict';

(function () {

  var expect = require('chai').expect;
  var stub = require('sinon').stub;

  var collect = require('../src/collect');
  var Command = require('../src/command');
  var KWArg = require('../src/kwarg');
  var Flag = require('../src/flag');
  var Arg = require('../src/arg');
  var utils = require('../src/utils');

  describe('collect.js', function () {

    it('should exist', function () {
      expect(collect).to.be.ok;
      expect(typeof collect).to.equal('function');
    });

    it('should return an arg tree when no args provided', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', []);

      // Without tree
      var result = boundCollect(
        Command(
          'install'
        )
      );

      expect(result).to.eql({
        command: null,
        kwargs: {},
        flags: {},
        args: {}
      });

    });

    it('should return an arg tree when no schema provided', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', []);

      // Without tree
      var result = boundCollect();

      expect(result).to.eql({
        command: null,
        kwargs: {},
        flags: {},
        args: {}
      });

    });

    it('should return an arg tree for single command schema', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', ['install']);

      // With single node
      var result = boundCollect(
        Command(
          'install'
        )
      );

      expect(result).to.eql({
        command: {
          name: 'install',
          command: null,
          kwargs: {},
          flags: {},
          args: {}
        },
        kwargs: {},
        flags: {},
        args: {}
      });

    });

    it('should return an arg tree with nested schema', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', ['install', 'jargs']);

      // With nested nodes
      var result = boundCollect(
        Command(
          'install',
          null,
          Arg(
            'lib'
          )
        )
      );

      expect(result).to.eql({
        command: {
          name: 'install',
          command: null,
          kwargs: {},
          flags: {},
          args: {
            lib: 'jargs'
          }
        },
        kwargs: {},
        flags: {},
        args: {}
      });
    });

    it('should return an arg tree with nested schema and flags', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', ['install', 'jargs', '--save']);

      // With nested nodes
      var result = boundCollect(
        Command(
          'install',
          null,
          Arg(
            'lib'
          ),
          Flag(
            'save'
          )
        )
      );

      expect(result).to.eql({
        command: {
          name: 'install',
          command: null,
          kwargs: {},
          flags: {
            save: true
          },
          args: {
            lib: 'jargs'
          }
        },
        kwargs: {},
        flags: {},
        args: {}
      });
    });

    it('should return an arg tree with kwargs, flags, and args', function () {
      var boundCollect = collect.bind(null, 'node', 'browserify',
        ['--transform', 'babelify', '--verbose', '--outfile=build/index.js', 'src/index.js']);

      // With nested nodes
      var result = boundCollect(
        Arg(
          'input'
        ),
        Flag(
          'verbose'
        ),
        KWArg(
          'outfile'
        ),
        KWArg(
          'transform'
        )
      );

      expect(result).to.eql({
        command: null,
        kwargs: {
          transform: 'babelify',
          outfile: 'build/index.js'
        },
        flags: {
          verbose: true
        },
        args: {
          input: 'src/index.js'
        }
      });
    });

    it('should return an arg tree from aliases', function () {
      var boundCollect = collect.bind(null, 'node', 'browserify',
        ['b', '-t', 'babelify', '-v', '-o=build/index.js', 'src/index.js']);

      // With nested nodes
      var result = boundCollect(
        Command(
          'build',
          {alias: 'b'},
          Arg(
            'input'
          ),
          Flag(
            'verbose',
            {alias: 'v'}
          ),
          KWArg(
            'outfile',
            {alias: 'o'}
          ),
          KWArg(
            'transform',
            {alias: 't'}
          )
        )
      );

      expect(result).to.eql({
        command: {
          name: 'build',
          command: null,
          kwargs: {
            transform: 'babelify',
            outfile: 'build/index.js'
          },
          flags: {
            verbose: true
          },
          args: {
            input: 'src/index.js'
          }
        },
        kwargs: {},
        flags: {},
        args: {}
      });
    });

    it('should throw an error for duplicate kwargs', function () {
      var throwErrorStub = stub(utils, 'throwError');
      var anError = /duplicate/i;

      var boundCollect = collect.bind(null, 'node', 'test',
        ['--kwarg=correct', '--kwarg=incorrect', 'correct', 'incorrect']);

      // With nested nodes
      boundCollect(
        Arg(
          'arg'
        ),
        KWArg(
          'kwarg'
        )
      );

      expect(throwErrorStub).to.have.been.calledWithMatch(anError);

      throwErrorStub.restore();
    });

    it('should throw an error for duplicate flags', function () {
      var throwErrorStub = stub(utils, 'throwError');
      var anError = /duplicate/i;

      var boundCollect = collect.bind(null, 'node', 'test',
        ['--flag', '--flag', 'correct', 'incorrect']);

      // With nested nodes
      boundCollect(
        Arg(
          'arg'
        ),
        Flag(
          'flag'
        )
      );

      expect(throwErrorStub).to.have.been.calledWithMatch(anError);

      throwErrorStub.restore();
    });

  });

})();
<commit_msg>Add test for unknown flags / kwargs<commit_after>/* global describe, it */

'use strict';

(function () {

  var expect = require('chai').expect;
  var stub = require('sinon').stub;

  var collect = require('../src/collect');
  var Command = require('../src/command');
  var KWArg = require('../src/kwarg');
  var Flag = require('../src/flag');
  var Arg = require('../src/arg');
  var utils = require('../src/utils');

  describe('collect.js', function () {

    it('should exist', function () {
      expect(collect).to.be.ok;
      expect(typeof collect).to.equal('function');
    });

    it('should return an arg tree when no args provided', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', []);

      // Without tree
      var result = boundCollect(
        Command(
          'install'
        )
      );

      expect(result).to.eql({
        command: null,
        kwargs: {},
        flags: {},
        args: {}
      });

    });

    it('should return an arg tree when no schema provided', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', []);

      // Without tree
      var result = boundCollect();

      expect(result).to.eql({
        command: null,
        kwargs: {},
        flags: {},
        args: {}
      });

    });

    it('should return an arg tree for single command schema', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', ['install']);

      // With single node
      var result = boundCollect(
        Command(
          'install'
        )
      );

      expect(result).to.eql({
        command: {
          name: 'install',
          command: null,
          kwargs: {},
          flags: {},
          args: {}
        },
        kwargs: {},
        flags: {},
        args: {}
      });

    });

    it('should return an arg tree with nested schema', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', ['install', 'jargs']);

      // With nested nodes
      var result = boundCollect(
        Command(
          'install',
          null,
          Arg(
            'lib'
          )
        )
      );

      expect(result).to.eql({
        command: {
          name: 'install',
          command: null,
          kwargs: {},
          flags: {},
          args: {
            lib: 'jargs'
          }
        },
        kwargs: {},
        flags: {},
        args: {}
      });
    });

    it('should return an arg tree with nested schema and flags', function () {
      var boundCollect = collect.bind(null, 'node', 'npm', ['install', 'jargs', '--save']);

      // With nested nodes
      var result = boundCollect(
        Command(
          'install',
          null,
          Arg(
            'lib'
          ),
          Flag(
            'save'
          )
        )
      );

      expect(result).to.eql({
        command: {
          name: 'install',
          command: null,
          kwargs: {},
          flags: {
            save: true
          },
          args: {
            lib: 'jargs'
          }
        },
        kwargs: {},
        flags: {},
        args: {}
      });
    });

    it('should return an arg tree with kwargs, flags, and args', function () {
      var boundCollect = collect.bind(null, 'node', 'browserify',
        ['--transform', 'babelify', '--verbose', '--outfile=build/index.js', 'src/index.js']);

      // With nested nodes
      var result = boundCollect(
        Arg(
          'input'
        ),
        Flag(
          'verbose'
        ),
        KWArg(
          'outfile'
        ),
        KWArg(
          'transform'
        )
      );

      expect(result).to.eql({
        command: null,
        kwargs: {
          transform: 'babelify',
          outfile: 'build/index.js'
        },
        flags: {
          verbose: true
        },
        args: {
          input: 'src/index.js'
        }
      });
    });

    it('should return an arg tree from aliases', function () {
      var boundCollect = collect.bind(null, 'node', 'browserify',
        ['b', '-t', 'babelify', '-v', '-o=build/index.js', 'src/index.js']);

      // With nested nodes
      var result = boundCollect(
        Command(
          'build',
          {alias: 'b'},
          Arg(
            'input'
          ),
          Flag(
            'verbose',
            {alias: 'v'}
          ),
          KWArg(
            'outfile',
            {alias: 'o'}
          ),
          KWArg(
            'transform',
            {alias: 't'}
          )
        )
      );

      expect(result).to.eql({
        command: {
          name: 'build',
          command: null,
          kwargs: {
            transform: 'babelify',
            outfile: 'build/index.js'
          },
          flags: {
            verbose: true
          },
          args: {
            input: 'src/index.js'
          }
        },
        kwargs: {},
        flags: {},
        args: {}
      });
    });

    it('should throw an error for duplicate kwargs', function () {
      var throwErrorStub = stub(utils, 'throwError');
      var anError = /duplicate/i;

      var boundCollect = collect.bind(null, 'node', 'test',
        ['--kwarg=correct', '--kwarg=incorrect']);

      // With nested nodes
      boundCollect(
        Arg(
          'arg'
        ),
        KWArg(
          'kwarg'
        )
      );

      expect(throwErrorStub).to.have.been.calledWithMatch(anError);

      throwErrorStub.restore();
    });

    it('should throw an error for duplicate flags', function () {
      var throwErrorStub = stub(utils, 'throwError');
      var anError = /duplicate/i;

      var boundCollect = collect.bind(null, 'node', 'test',
        ['--flag', '--flag']);

      // With nested nodes
      boundCollect(
        Arg(
          'arg'
        ),
        Flag(
          'flag'
        )
      );

      expect(throwErrorStub).to.have.been.calledWithMatch(anError);

      throwErrorStub.restore();
    });

    it('should throw an error for unknown flags / kwargs', function () {
      var throwErrorStub = stub(utils, 'throwError');
      var anError = /unknown/i;

      var boundCollect = collect.bind(null, 'node', 'test',
        ['--version']);

      // With nested nodes
      boundCollect(
        Arg(
          'arg'
        ),
        Flag(
          'flag'
        ),
        KWArg(
          'kwarg'
        )
      );

      expect(throwErrorStub).to.have.been.calledWithMatch(anError);

      throwErrorStub.restore();
    });

  });

})();
<|endoftext|>


<commit_before>/* eslint-disable no-param-reassign */

// MAX_WIDTH of Bootstrap is 12 columns.
const MAX_WIDTH = 12;

// Maximum level.
const MAX_LEVEL = 4;

// Use date as key to database.
let dateKey = "";

/* JSON-formated data of daily goal lists.
 * Format:
 * [
 *   {
 *     value: xxx,
 *     children: [
 *       {value: xxx; children: [...]}
 *       ...
 *     ]
 *   },
 *   ...
 * ]
 */
let dailyGoalData = [];

// Localforage module is local simple database.
const localforage = require('localforage');

// Sprintf module is same as printf in C.
const sprintf = require('sprintf-js').sprintf;

// jQuery.
const $ = require('jquery');

const loadDailyGoalList = function loadDailyGoalList() {
  // Remove all daily goal lists.
  $('.container').find('.dg-lists').remove();

  // Render to front end.
  addDailyGoalToElement(
    $('.container'),
    dailyGoalData,
    []);
};

const loadDailyGoalListFromDatabase = function loadDailyGoalListFromDatabase(key) {
  // Load daily goal data from database, then render to front end.
  localforage.getItem(key).then((value) => {
    // If the value is empty or null, then leave it as empty list.
    if (!value) {
      dailyGoalData = [];
    } else {
      dailyGoalData = value;
    }

    loadDailyGoalList();
  }).catch((err) => {
    console.log(err);
  });
};

/**
 * When click a wait element, turn into active.
 *
 * `element` should be a jQuery element.
 */
const bindDailyGoalElementAction = function bindDailyGoalElementAction(element) {
  element.click(() => {
    if (!element.hasClass('dg-focus')) {
      element.toggleClass('dg-focus');
    }
  });
};

const bindDailyGoalSaveButton = function bindDailyGoalSaveButton(button, id, input) {
  button.click(() => {
    // Path to desired JSON node.
    const path = id.split('-').map(num => parseInt(num, 10));

    // Route to the node.
    let node = dailyGoalData;
    for (let level = 0; level < path.length; level += 1) {
      // At level `level`, the childIdx-th child.
      const childIdx = path[level];
      if (level !== path.length - 1) {
        node = node[childIdx].children;
      } else if (childIdx !== node.length) {
        node = node[childIdx];
      } else {
        node.push({ value: '', children: [] });
        node = node[childIdx];
      }
    }

    node.value = input.val();

    // Refresh content.
    loadDailyGoalList();
  });
};

const getWidthByLevel = function getWidthByLevel(level) {
  return MAX_WIDTH - level;
};

const getOffsetByLevel = function getOffsetByLevel(level) {
  return level;
};

/**
 * Make a daily goal element.
 *
 * level: level of each sub-list, control indentation
 * value: content in this sub-list
 * traverse: How to route to this list/node from root.
 */
const makeDailyGoalElement = function makeDailyGoalElement(level, value, traverse) {
  let placeholder = '';
  if (!value) {
    placeholder = 'Add a daily goal...';
    // Value could be undefined etc.
    value = '';
  }

  const id = traverse.join('-');

  const dailyGoalElement = $(
    `

        <input class='form-control mb-2 col-${getWidthByLevel(level)} offset-${getOffsetByLevel(level)}' type='text' placeholder='${placeholder}' value='${value}'>
        <button type='button' class='btn btn-success col-2 offset-${getOffsetByLevel(level)} mr-2'>Save</button>
        <button type='button' class='btn btn-warning col-2 mr-2'>Cancel</button>
        <button type='button' class='btn btn-danger col-2'>Delete</button>

`);

  bindDailyGoalElementAction(dailyGoalElement.find('div.row').first());

  bindDailyGoalSaveButton(
    dailyGoalElement.find('button.btn-success').first(),
    id,
    dailyGoalElement.find('input'));

  return dailyGoalElement;
};

/**
 * Recursively add all items in `dgList` to `containerElement`,
 * with indentation set by `level`.
 */
const addDailyGoalToElement = function addDailyGoalToElement(
  containerElement,
  dgList,
  traverse,
  level = 0) {
  for (let i = 0; i < dgList.length; i += 1) {
    // Add traverse route.
    traverse[level] = i;

    // For each direct child in the same level, append to `containerElement`.
    const dg = dgList[i];
    const dgElement = makeDailyGoalElement(level, dg.value, traverse);
    containerElement.append(dgElement);

    // For children in next level, recursively call `addDailyGoalToElement` to
    // attach children to this element.
    if (level < MAX_LEVEL - 1) {
      addDailyGoalToElement(dgElement, dg.children, traverse, level + 1);
      // Remove last number as it is only used in children level.
      traverse.pop();
    }
  }

  // Reserve one line to add new list.
  traverse[level] = dgList.length;
  containerElement.append(makeDailyGoalElement(level, null, traverse));
};

const getCurrentDateKey = function getCurrentDateKey() {
  // Use YYYY-MM-dd as primary key in database.
  const date = new Date();
  const key = sprintf('%d%02d%02d', date.getFullYear(), date.getMonth(), date.getDate());
  return key;
};

/**
 * Load database for daily goal list.
 */
const init = function init() {
  dateKey = getCurrentDateKey();
  loadDailyGoalListFromDatabase(dateKey);
};

$(document).ready(init);
<commit_msg>Show empty list only at top level.<commit_after>/* eslint-disable no-param-reassign */

// MAX_WIDTH of Bootstrap is 12 columns.
const MAX_WIDTH = 12;

// Maximum level.
const MAX_LEVEL = 4;

// Use date as key to database.
let dateKey = "";

/* JSON-formated data of daily goal lists.
 * Format:
 * [
 *   {
 *     value: xxx,
 *     children: [
 *       {value: xxx; children: [...]}
 *       ...
 *     ]
 *   },
 *   ...
 * ]
 */
let dailyGoalData = [];

// Localforage module is local simple database.
const localforage = require('localforage');

// Sprintf module is same as printf in C.
const sprintf = require('sprintf-js').sprintf;

// jQuery.
const $ = require('jquery');

const loadDailyGoalList = function loadDailyGoalList() {
  // Remove all daily goal lists.
  $('.container').find('.dg-lists').remove();

  // Render to front end.
  addDailyGoalToElement(
    $('.container'),
    dailyGoalData,
    []);
};

const loadDailyGoalListFromDatabase = function loadDailyGoalListFromDatabase(key) {
  // Load daily goal data from database, then render to front end.
  localforage.getItem(key).then((value) => {
    // If the value is empty or null, then leave it as empty list.
    if (!value) {
      dailyGoalData = [];
    } else {
      dailyGoalData = value;
    }

    loadDailyGoalList();
  }).catch((err) => {
    console.log(err);
  });
};

/**
 * When click a wait element, turn into active.
 *
 * `element` should be a jQuery element.
 */
const bindDailyGoalElementAction = function bindDailyGoalElementAction(element) {
  element.click(() => {
    if (!element.hasClass('dg-focus')) {
      element.toggleClass('dg-focus');
    }
  });
};

const bindDailyGoalSaveButton = function bindDailyGoalSaveButton(button, id, input) {
  button.click(() => {
    // Path to desired JSON node.
    const path = id.split('-').map(num => parseInt(num, 10));

    // Route to the node.
    let node = dailyGoalData;
    for (let level = 0; level < path.length; level += 1) {
      // At level `level`, the childIdx-th child.
      const childIdx = path[level];
      if (level !== path.length - 1) {
        node = node[childIdx].children;
      } else if (childIdx !== node.length) {
        node = node[childIdx];
      } else {
        node.push({ value: '', children: [] });
        node = node[childIdx];
      }
    }

    node.value = input.val();

    // Refresh content.
    loadDailyGoalList();
  });
};

const getWidthByLevel = function getWidthByLevel(level) {
  return MAX_WIDTH - level;
};

const getOffsetByLevel = function getOffsetByLevel(level) {
  return level;
};

/**
 * Make a daily goal element.
 *
 * level: level of each sub-list, control indentation
 * value: content in this sub-list
 * traverse: How to route to this list/node from root.
 */
const makeDailyGoalElement = function makeDailyGoalElement(level, value, traverse) {
  let placeholder = '';
  if (!value) {
    placeholder = 'Add a daily goal...';
    // Value could be undefined etc.
    value = '';
  }

  const id = traverse.join('-');

  const dailyGoalElement = $(
    `

        <input class='form-control mb-2 col-${getWidthByLevel(level)} offset-${getOffsetByLevel(level)}' type='text' placeholder='${placeholder}' value='${value}'>
        <button type='button' class='btn btn-success col-2 offset-${getOffsetByLevel(level)} mr-2'>Save</button>
        <button type='button' class='btn btn-info col-2 mr-2'>Add sub-list</button>
        <button type='button' class='btn btn-warning col-2 mr-2'>Cancel</button>
        <button type='button' class='btn btn-danger col-2'>Delete</button>

`);

  bindDailyGoalElementAction(dailyGoalElement.find('div.row').first());

  bindDailyGoalSaveButton(
    dailyGoalElement.find('button.btn-success').first(),
    id,
    dailyGoalElement.find('input'));

  return dailyGoalElement;
};

/**
 * Recursively add all items in `dgList` to `containerElement`,
 * with indentation set by `level`.
 */
const addDailyGoalToElement = function addDailyGoalToElement(
  containerElement,
  dgList,
  traverse,
  level = 0) {
  for (let i = 0; i < dgList.length; i += 1) {
    // Add traverse route.
    traverse[level] = i;

    // For each direct child in the same level, append to `containerElement`.
    const dg = dgList[i];
    const dgElement = makeDailyGoalElement(level, dg.value, traverse);
    containerElement.append(dgElement);

    // For children in next level, recursively call `addDailyGoalToElement` to
    // attach children to this element.
    if (level < MAX_LEVEL - 1) {
      addDailyGoalToElement(dgElement, dg.children, traverse, level + 1);
      // Remove last number as it is only used in children level.
      traverse.pop();
    }
  }

  // Reserve one line to add new list, only if this is the top level.
  if (level === 0) {
    traverse[level] = dgList.length;
    containerElement.append(makeDailyGoalElement(level, null, traverse));
  }
};

const getCurrentDateKey = function getCurrentDateKey() {
  // Use YYYY-MM-dd as primary key in database.
  const date = new Date();
  const key = sprintf('%d%02d%02d', date.getFullYear(), date.getMonth(), date.getDate());
  return key;
};

/**
 * Load database for daily goal list.
 */
const init = function init() {
  dateKey = getCurrentDateKey();
  loadDailyGoalListFromDatabase(dateKey);
};

$(document).ready(init);
<|endoftext|>


<commit_before>/*
    PixelServer.js hosts the server that saves the painted pixel data
        and broadcasts it to all clients

    CREDITS
        Brandon Asuncion <me@brandonasuncion.tech>

    SETUP:
        $ npm install

    RUNNING:
        $ npm start

*/

/* Port for WebSocket server to listen on */
const PORT = process.env.PORT || 3001;

const MONGODB_URI = process.env.MONGODB_URI || null;

/* Dimensions of the canvas, these values must be the same as the ones
set in the browser's code. */
const CANVAS_WIDTH = process.env.CANVAS_WIDTH || 50;
const CANVAS_HEIGHT = process.env.CANVAS_HEIGHT || 50;

/* Minimum wait time between each draw request, per IP address (in seconds) */
const USER_PAINT_LIMIT = process.env.USER_PAINT_LIMIT || 60;

/*  !!!!! DONT EDIT ANYTHING AFTER THIS !!!!!  */
var http = require("http");
var express = require("express");
var app = express();
var MongoClient = require('mongodb').MongoClient;

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

var server = http.createServer(app);
server.listen(PORT);

var WebSocket = require('ws');
var WebSocketServer = WebSocket.Server;

var timestamps = {};

var pixels = new Array(CANVAS_WIDTH);
for (var i = 0; i < CANVAS_WIDTH; i++)
    pixels[i] = Array(CANVAS_HEIGHT);

// Reset pixel array
function resetPixels() {
    for (var x = 0; x < CANVAS_WIDTH; x++) {
        for (var y = 0; y < CANVAS_HEIGHT; y++) {
            pixels[x][y] = { x, y, colorID: 0 };
        }
    }
}

console.log("Pixel Server Initializing");

let ws, mongoclient, pixelCollection;
resetPixels();

if (MONGODB_URI) {
    MongoClient.connect(MONGODB_URI, function(err, db) {
        mongoclient = db;
        pixelCollection = mongoclient.collection('pixels');
        if (pixelCollection) {
            var dbPixels = pixelCollection.find().toArray(function(err, dbPixels) {
                for (var i = 0; i < dbPixels.length; i++)
                    pixels[dbPixels[i].x][dbPixels[i].y].colorID = dbPixels[i].colorID;

                console.log("Loaded", dbPixels.length, "pixels from MongoDB");
            });
        } else {
            mongoclient.createCollection('pixels');
            console.log("Creating MongoDB collection");
        }
    });
} else {
    console.log("No MongoDB connection, all pixels will be stored in RAM");
}

ws = new WebSocketServer({ server });

ws.on("connection", function(socket) {
    var remoteIP = socket._socket.remoteAddress;

    var log = function(text) {
        //console.log("[" + (new Date()).toLocaleString() + "] [" + remoteIP + "] ->\t" + text);
        console.log("[Client " + remoteIP + "] ->\t" + text);
    };

    function sendPixelUpdate(x, y, receiver = socket) {
        receiver.send(JSON.stringify({
            "action": "updatePixel",
            x,
            y,
            'colorID': pixels[x][y].colorID
        }));
    }

    function sendTimer(type, time) {
        socket.send(JSON.stringify({
            "action": "timer",
            type,
            time
        }));
    }

    log("New client connected\t(" + ws.clients.size + " total)");

    socket.send(JSON.stringify({
        "action": "canvasInfo",
        "width": CANVAS_WIDTH,
        "height": CANVAS_HEIGHT
    }));

    socket.on("message", function(rawdata) {
        var message_timestamp = new Date();

        var data;
        try {
            data = JSON.parse(rawdata);
        } catch (e) {}
        var action = (data && data.action) ? data.action : rawdata;

        switch (action) {
            /*
            case "clearCanvas":
                log("CLEARED CANVAS")
                resetPixels();
                break;
            */
            case "ping":
                socket.send('{"action":"pong"}');
                break;

            case "refreshPixels":
                log("Client requested pixel refresh");

                var pixelArray = new Uint8Array(CANVAS_WIDTH * CANVAS_HEIGHT);
                for (var x = 0; x < CANVAS_WIDTH; x++) {
                    for (var y = 0; y < CANVAS_HEIGHT; y++) {
                        pixelArray[x + y * CANVAS_WIDTH] = pixels[x][y]["colorID"];
                    }
                }
                socket.send(pixelArray);
                break;

            case "paint":

                // Check rate limits
                // if (remoteIP in timestamps) {
                //     if (message_timestamp - timestamps[remoteIP] < USER_PAINT_LIMIT * 1000) {
                //         sendTimer('toofast', USER_PAINT_LIMIT * 1000 - (message_timestamp - timestamps[remoteIP]));
                //         sendPixelUpdate(data.x, data.y);
                //         break;
                //     }
                // }

                if (data.x >= 0 && data.y >= 0 && data.x < CANVAS_WIDTH && data.y < CANVAS_HEIGHT) {

                    log("PAINT (" + data.x + ", " + data.y + ") " + data.colorID);
                    pixels[data.x][data.y]["colorID"] = data.colorID;
                    timestamps[remoteIP] = message_timestamp;
                    sendTimer("paintsuccess", USER_PAINT_LIMIT * 1000);

                    // Update MongoDB document, if collection is available
                    if (pixelCollection) {
                        pixelCollection.findOneAndUpdate({ "x": data.x, "y": data.y }, { $set: { colorID: data.colorID } }, { upsert: true });
                    }

                    var broadcastPacket = JSON.stringify({
                        "action": "updatePixel",
                        'x': data.x,
                        'y': data.y,
                        'colorID': pixels[data.x][data.y].colorID
                    });
                    ws.clients.forEach(function(client) {
                        if ((client !== socket) && (client.readyState === WebSocket.OPEN)) {
                            client.send(broadcastPacket);
                        }
                    });

                } else {
                    log("Invalid paint request");
                }
                break;

            case "getPixel":
                log("GETPIXEL (" + data.x + ", " + data.y + ")");
                sendPixelUpdate(data.x, data.y);
                break;

            default:
                log("Invalid message");
                break;
        }
    });

    socket.on("error", function(exception) {
        log("Error encountered");
        log(exception);
    });

    socket.on("close", function() {
        log("Client disconnected (" + ws.clients.size + " total)");
    });
});

console.log("Pixel Server Listening on port " + PORT);
<commit_msg>Uncommented code<commit_after>/*
    PixelServer.js hosts the server that saves the painted pixel data
        and broadcasts it to all clients

    CREDITS
        Brandon Asuncion <me@brandonasuncion.tech>

    SETUP:
        $ npm install

    RUNNING:
        $ npm start

*/

/* Port for WebSocket server to listen on */
const PORT = process.env.PORT || 3001;

const MONGODB_URI = process.env.MONGODB_URI || null;

/* Dimensions of the canvas, these values must be the same as the ones
set in the browser's code. */
const CANVAS_WIDTH = process.env.CANVAS_WIDTH || 50;
const CANVAS_HEIGHT = process.env.CANVAS_HEIGHT || 50;

/* Minimum wait time between each draw request, per IP address (in seconds) */
const USER_PAINT_LIMIT = process.env.USER_PAINT_LIMIT || 60;

/*  !!!!! DONT EDIT ANYTHING AFTER THIS !!!!!  */
var http = require("http");
var express = require("express");
var app = express();
var MongoClient = require('mongodb').MongoClient;

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

var server = http.createServer(app);
server.listen(PORT);

var WebSocket = require('ws');
var WebSocketServer = WebSocket.Server;

var timestamps = {};

var pixels = new Array(CANVAS_WIDTH);
for (var i = 0; i < CANVAS_WIDTH; i++)
    pixels[i] = Array(CANVAS_HEIGHT);

// Reset pixel array
function resetPixels() {
    for (var x = 0; x < CANVAS_WIDTH; x++) {
        for (var y = 0; y < CANVAS_HEIGHT; y++) {
            pixels[x][y] = { x, y, colorID: 0 };
        }
    }
}

console.log("Pixel Server Initializing");

let ws, mongoclient, pixelCollection;
resetPixels();

if (MONGODB_URI) {
    MongoClient.connect(MONGODB_URI, function(err, db) {
        mongoclient = db;
        pixelCollection = mongoclient.collection('pixels');
        if (pixelCollection) {
            var dbPixels = pixelCollection.find().toArray(function(err, dbPixels) {
                for (var i = 0; i < dbPixels.length; i++)
                    pixels[dbPixels[i].x][dbPixels[i].y].colorID = dbPixels[i].colorID;

                console.log("Loaded", dbPixels.length, "pixels from MongoDB");
            });
        } else {
            mongoclient.createCollection('pixels');
            console.log("Creating MongoDB collection");
        }
    });
} else {
    console.log("No MongoDB connection, all pixels will be stored in RAM");
}

ws = new WebSocketServer({ server });

ws.on("connection", function(socket) {
    var remoteIP = socket._socket.remoteAddress;

    var log = function(text) {
        //console.log("[" + (new Date()).toLocaleString() + "] [" + remoteIP + "] ->\t" + text);
        console.log("[Client " + remoteIP + "] ->\t" + text);
    };

    function sendPixelUpdate(x, y, receiver = socket) {
        receiver.send(JSON.stringify({
            "action": "updatePixel",
            x,
            y,
            'colorID': pixels[x][y].colorID
        }));
    }

    function sendTimer(type, time) {
        socket.send(JSON.stringify({
            "action": "timer",
            type,
            time
        }));
    }

    log("New client connected\t(" + ws.clients.size + " total)");

    socket.send(JSON.stringify({
        "action": "canvasInfo",
        "width": CANVAS_WIDTH,
        "height": CANVAS_HEIGHT
    }));

    socket.on("message", function(rawdata) {
        var message_timestamp = new Date();

        var data;
        try {
            data = JSON.parse(rawdata);
        } catch (e) {}
        var action = (data && data.action) ? data.action : rawdata;

        switch (action) {
            /*
            case "clearCanvas":
                log("CLEARED CANVAS")
                resetPixels();
                break;
            */
            case "ping":
                socket.send('{"action":"pong"}');
                break;

            case "refreshPixels":
                log("Client requested pixel refresh");

                var pixelArray = new Uint8Array(CANVAS_WIDTH * CANVAS_HEIGHT);
                for (var x = 0; x < CANVAS_WIDTH; x++) {
                    for (var y = 0; y < CANVAS_HEIGHT; y++) {
                        pixelArray[x + y * CANVAS_WIDTH] = pixels[x][y]["colorID"];
                    }
                }
                socket.send(pixelArray);
                break;

            case "paint":

                // Check rate limits
                if (remoteIP in timestamps) {
                    if (message_timestamp - timestamps[remoteIP] < USER_PAINT_LIMIT * 1000) {
                        sendTimer('toofast', USER_PAINT_LIMIT * 1000 - (message_timestamp - timestamps[remoteIP]));
                        sendPixelUpdate(data.x, data.y);
                        break;
                    }
                }

                if (data.x >= 0 && data.y >= 0 && data.x < CANVAS_WIDTH && data.y < CANVAS_HEIGHT) {

                    log("PAINT (" + data.x + ", " + data.y + ") " + data.colorID);
                    pixels[data.x][data.y]["colorID"] = data.colorID;
                    timestamps[remoteIP] = message_timestamp;
                    sendTimer("paintsuccess", USER_PAINT_LIMIT * 1000);

                    // Update MongoDB document, if collection is available
                    if (pixelCollection) {
                        pixelCollection.findOneAndUpdate({ "x": data.x, "y": data.y }, { $set: { colorID: data.colorID } }, { upsert: true });
                    }

                    var broadcastPacket = JSON.stringify({
                        "action": "updatePixel",
                        'x': data.x,
                        'y': data.y,
                        'colorID': pixels[data.x][data.y].colorID
                    });
                    ws.clients.forEach(function(client) {
                        if ((client !== socket) && (client.readyState === WebSocket.OPEN)) {
                            client.send(broadcastPacket);
                        }
                    });

                } else {
                    log("Invalid paint request");
                }
                break;

            case "getPixel":
                log("GETPIXEL (" + data.x + ", " + data.y + ")");
                sendPixelUpdate(data.x, data.y);
                break;

            default:
                log("Invalid message");
                break;
        }
    });

    socket.on("error", function(exception) {
        log("Error encountered");
        log(exception);
    });

    socket.on("close", function() {
        log("Client disconnected (" + ws.clients.size + " total)");
    });
});

console.log("Pixel Server Listening on port " + PORT);
<|endoftext|>


<commit_before>'use strict';

var log = require('db-migrate-shared').log;
var assert = require('assert');

function executeDB (internals, config, callback) {
  var index = require('../../connect');

  if (internals.argv._.length > 0) {
    internals.argv.dbname = internals.argv._.shift().toString();
  } else {
    log.info('Error: You must enter a database name!');
    return;
  }

  index.driver(config.getCurrent().settings, function (err, db) {
    assert.ifError(err);

    if (internals.mode === 'create') {
      db.createDatabase(
        internals.argv.dbname,
        {
          ifNotExists: true
        },
        function (err) {
          if (err) {
            if (err.error) err = err.error;
            log.error('Error: Failed to create database!', err);
          } else {
            log.info('Created database "' + internals.argv.dbname + '"');
          }

          db.close();
          if (typeof callback === 'function') callback(err);
          else process.exit(1);
        }
      );
    } else if (internals.mode === 'drop') {
      db.dropDatabase(
        internals.argv.dbname,
        {
          ifExists: true
        },
        function (err) {
          if (err) {
            if (err.error) err = err.error;
            log.error('Error: Failed to drop database!', err);
          } else {
            log.info('Deleted database "' + internals.argv.dbname + '"');
          }

          db.close();
          if (typeof callback === 'function') callback(err);
          process.exit(1);
        }
      );
    }
  });
}

module.exports = executeDB;
<commit_msg>fix(db): set exit code as 1 only on error<commit_after>'use strict';

var log = require('db-migrate-shared').log;
var assert = require('assert');

function executeDB (internals, config, callback) {
  var index = require('../../connect');

  if (internals.argv._.length > 0) {
    internals.argv.dbname = internals.argv._.shift().toString();
  } else {
    log.info('Error: You must enter a database name!');
    return;
  }

  index.driver(config.getCurrent().settings, function (err, db) {
    assert.ifError(err);

    if (internals.mode === 'create') {
      db.createDatabase(
        internals.argv.dbname,
        {
          ifNotExists: true
        },
        function (err) {
          if (err) {
            if (err.error) err = err.error;
            log.error('Error: Failed to create database!', err);
          } else {
            log.info('Created database "' + internals.argv.dbname + '"');
          }

          db.close();
          if (typeof callback === 'function') callback(err);
          else process.exit(err ? 1 : 0);
        }
      );
    } else if (internals.mode === 'drop') {
      db.dropDatabase(
        internals.argv.dbname,
        {
          ifExists: true
        },
        function (err) {
          if (err) {
            if (err.error) err = err.error;
            log.error('Error: Failed to drop database!', err);
          } else {
            log.info('Deleted database "' + internals.argv.dbname + '"');
          }

          db.close();
          if (typeof callback === 'function') callback(err);
          else process.exit(err ? 1 : 0);
        }
      );
    }
  });
}

module.exports = executeDB;
<|endoftext|>


<commit_before>require('../../lib/Object/serialize');

const Namespace = Jymfony.Component.Autoloader.Namespace;
const expect = require('chai').expect;
const path = require('path');

global.UtilFixtures = new Namespace(__jymfony.autoload, 'UtilFixtures', [
    path.join(__dirname, '..', '..', 'fixtures'),
]);

describe('Serialize', function () {
    it('should serialize undefined', () => {
        expect(__jymfony.serialize(undefined)).to.be.equal('U');
    });

    it('should serialize null', () => {
        expect(__jymfony.serialize(null)).to.be.equal('N');
    });

    it('should serialize booleans', () => {
        expect(__jymfony.serialize(true)).to.be.equal('B:1');
        expect(__jymfony.serialize(false)).to.be.equal('B:0');
    });

    it('should serialize numbers', () => {
        expect(__jymfony.serialize(0)).to.be.equal('D(1):0');
        expect(__jymfony.serialize(42)).to.be.equal('D(2):42');
        expect(__jymfony.serialize(47.3)).to.be.equal('D(4):47.3');
    });

    it('should serialize strings', () => {
        expect(__jymfony.serialize('')).to.be.equal('S(2):""');
        expect(__jymfony.serialize('hello world')).to.be.equal('S(13):"hello world"');
    });

    it('should serialize arrays', () => {
        expect(__jymfony.serialize([ 1, 1.1, 'hallo', null, true, [] ]))
            .to.be.equal('A(6):{0:D(1):1;1:D(3):1.1;2:S(7):"hallo";3:N;4:B:1;5:A(0):{};}');
    });

    it('should serialize object literals', () => {
        expect(__jymfony.serialize({a: 1, b: 1.1, c: 'hallo', d: null, e: true, f: []}))
            .to.be.equal('O(6):{S(3):"a":D(1):1;S(3):"b":D(3):1.1;S(3):"c":S(7):"hallo";S(3):"d":N;S(3):"e":B:1;S(3):"f":A(0):{};}');
    });

    it('should serialize objects', () => {
        expect(__jymfony.serialize(new UtilFixtures.BarClass()))
            .to.be.equal('C[UtilFixtures.BarClass]:{S(7):"hello":S(7):"world";}');

        const foo = new UtilFixtures.FooClass();
        expect(__jymfony.serialize(foo))
            .to.be.equal('C[UtilFixtures.FooClass]:{S(3):"a":S(7):"hello";S(3):"c":S(7):"world";}');
        expect(foo.sleepCalled).to.be.true;
    });
});
<commit_msg>[util] add tests for unserialize<commit_after>require('../../lib/Object/serialize');

const Namespace = Jymfony.Component.Autoloader.Namespace;
const expect = require('chai').expect;
const path = require('path');

global.UtilFixtures = new Namespace(__jymfony.autoload, 'UtilFixtures', [
    path.join(__dirname, '..', '..', 'fixtures'),
]);

describe('Serialize', function () {
    it('should serialize undefined', () => {
        expect(__jymfony.serialize(undefined)).to.be.equal('U');
    });

    it('should serialize null', () => {
        expect(__jymfony.serialize(null)).to.be.equal('N');
    });

    it('should serialize booleans', () => {
        expect(__jymfony.serialize(true)).to.be.equal('B:1');
        expect(__jymfony.serialize(false)).to.be.equal('B:0');
    });

    it('should serialize numbers', () => {
        expect(__jymfony.serialize(0)).to.be.equal('D(1):0');
        expect(__jymfony.serialize(42)).to.be.equal('D(2):42');
        expect(__jymfony.serialize(47.3)).to.be.equal('D(4):47.3');
    });

    it('should serialize strings', () => {
        expect(__jymfony.serialize('')).to.be.equal('S(2):""');
        expect(__jymfony.serialize('hello world')).to.be.equal('S(13):"hello world"');
    });

    it('should serialize arrays', () => {
        expect(__jymfony.serialize([ 1, 1.1, 'hallo', null, true, [] ]))
            .to.be.equal('A(6):{0:D(1):1;1:D(3):1.1;2:S(7):"hallo";3:N;4:B:1;5:A(0):{};}');
    });

    it('should serialize object literals', () => {
        expect(__jymfony.serialize({a: 1, b: 1.1, c: 'hallo', d: null, e: true, f: []}))
            .to.be.equal('O(6):{S(3):"a":D(1):1;S(3):"b":D(3):1.1;S(3):"c":S(7):"hallo";S(3):"d":N;S(3):"e":B:1;S(3):"f":A(0):{};}');
    });

    it('should serialize objects', () => {
        expect(__jymfony.serialize(new UtilFixtures.BarClass()))
            .to.be.equal('C[UtilFixtures.BarClass]:{S(7):"hello":S(7):"world";}');

        const foo = new UtilFixtures.FooClass();
        expect(__jymfony.serialize(foo))
            .to.be.equal('C[UtilFixtures.FooClass]:{S(3):"a":S(7):"hello";S(3):"c":S(7):"world";}');
        expect(foo.sleepCalled).to.be.true;
    });
});

describe('Unerialize', function () {
    it('should unserialize undefined', () => {
        expect(__jymfony.unserialize('U')).to.be.undefined;
    });

    it('should unserialize null', () => {
        expect(__jymfony.unserialize('N')).to.be.null;
    });

    it('should unserialize booleans', () => {
        expect(__jymfony.unserialize('B:1')).to.be.true;
        expect(__jymfony.unserialize('B:0')).to.be.false;
    });

    it('should unserialize numbers', () => {
        expect(__jymfony.unserialize('D(1):0')).to.be.equal(0);
        expect(__jymfony.unserialize('D(2):42')).to.be.equal(42);
        expect(__jymfony.unserialize('D(4):47.3')).to.be.equal(47.3);
    });

    it('should unserialize strings', () => {
        expect(__jymfony.unserialize('S(2):""')).to.be.equal('');
        expect(__jymfony.unserialize('S(13):"hello world"')).to.be.equal('hello world');
    });

    it('should unserialize arrays', () => {
        expect(__jymfony.unserialize('A(6):{0:D(1):1;1:D(3):1.1;2:S(7):"hallo";3:N;4:B:1;5:A(0):{};}'))
            .to.be.deep.equal([ 1, 1.1, 'hallo', null, true, [] ]);
    });

    it('should unserialize object literals', () => {
        expect(__jymfony.unserialize('O(6):{S(3):"a":D(1):1;S(3):"b":D(3):1.1;S(3):"c":S(7):"hallo";S(3):"d":N;S(3):"e":B:1;S(3):"f":A(0):{};}'))
            .to.be.deep.equal({a: 1, b: 1.1, c: 'hallo', d: null, e: true, f: []});
    });

    it('should unserialize objects', () => {
        const obj = __jymfony.unserialize('C[UtilFixtures.BarClass]:{S(7):"hello":S(7):"world";}');
        expect(obj).to.be.instanceOf(UtilFixtures.BarClass);
        expect(obj.hello).to.be.equal('world');

        const foo = __jymfony.unserialize('C[UtilFixtures.FooClass]:{S(3):"a":S(7):"hello";S(3):"c":S(7):"world";}');
        expect(foo).to.be.instanceOf(UtilFixtures.FooClass);
        expect(foo.a).to.be.equal('hello');
        expect(foo.b).to.be.undefined;
        expect(foo.c).to.be.equal('world');
        expect(foo.d).to.be.undefined;
        expect(foo.wakeupCalled).to.be.true;
    });
});
<|endoftext|>


<commit_before>/*
 Copyright (c) 2011, 2014 Jessica González
 @license http://www.mozilla.org/MPL/MPL-1.1.html
*/

$(function() {

	// Fires up the load more thingy
	if (breeze.currentSettings.load_more){

		var numberOfEvents = 0;

		// Hide the normal pagination.
		$('.pagesection').hide();

		showMoarButton();
	}

	function showMoarButton(){

	// Don't show anything if there isn't enough items to display...
	// if (breeze.pagination.totalItems <= breeze.pagination.maxIndex)
		// return false;

		// Add a nice button...
		$('<button/>', {
			id: 'loadMoar',
			text: breeze.text.load_more,
			click: function () {
				numberOfEvents++;

				$('<ul/>', {
					id: 'tempDIV_'+ numberOfEvents,
					class: 'breeze_status',
					style: ''
				}).appendTo('#breezeAppendTo').hide();

				// Append some more data to breeze.pagination.
				breeze.pagination.numberTimes = numberOfEvents;
				breeze.pagination.comingFrom = breeze.tools.comingFrom;

				$.ajax({
					// Send the data and oh boy there's a lot of it!
					url: smf_scripturl + '?action=breezeajax;sa=fetch;js=1;' + smf_session_var + '=' + smf_session_id,
					data : breeze.pagination,
					cache: false,
					dataType: 'json',
					success: function(html)
					{
						// The server response as a JSON object
						if(html.type == 'info'){

							// Append the html to our temp DIV.
							if (html.data != 'end'){

								// Create a unique UL for this very own status, isn't it great?
								$('#tempDIV_'+ numberOfEvents).append(html.data).fadeIn('slow', 'linear', function(){});
							}

							// No more data:(
							else{
								noty({
									text: breeze.text.page_loading_end,
									timeout: 3500,
									theme: 'relax',
									type: 'success'
								});
								$('#loadMoar').fadeOut('slow');
								return;
							}
						}

						else if(html.type == 'error'){
							breeze.tools.showNoti(html);
						}
					},
					error: function (html){
						breeze.tools.showNoti(html);
					}
				});
			}
		}).appendTo('#tab-wall');
	}
});

<commit_msg>breezeLoadMore totally untested code, of course it will work wonderfully so no need to actually test this at all no sr.. no need...<commit_after>/*
 Copyright (c) 2011, 2014 Jessica González
 @license http://www.mozilla.org/MPL/MPL-1.1.html
*/

var breezeLoadMore = function(oOptions) {
	this.options = oOptions;

	this.numberOfEvents = 0;

	// Magic!
	this.showMoarButton();
};

breezeLoadMore.prototype.showMoarButton()
{
	// Don't show anything if there isn't enough items to display... this actually should never happen but better be safe...
	if (this.options.pagination.totalItems <= this.options.pagination.maxIndex)
		return false;

	// Replacing any pagination div?
	if (this.options.paginationClass)
		$(this.options.paginationClass).hide();

	// The rest is pretty straight forward...
	$('<button/>', {
		id: this.options.button.id,
		text: this.options.button.text,
		click: this.clickButton()
	}).appendTo(this.options.button.appendTo);
}

breezeLoadMore.prototype.clickButton()
{
	// Add one to the number of iterations, pretty important!
	this.numberOfEvents++;

	// Need to keep a reference...
	var = oObject = this;

	$('<ul/>', {
		id: 'tempDIV_'+ this.numberOfEvents,
		class: this.options.target.css,
		style: ''
	}).appendTo(this.options.target.appendTo).hide();

	// Let us pass some data to the server.
	passingData = {
		numberTimes : this.numberOfEvents,
		comingFrom : breeze.tools.comingFrom,
};
	// And fill the rest with options.pagination object.
	$.extend(passingData, this.options.pagination);

	$.ajax({
		// Send the data and oh boy there's a lot of it!
		url: smf_scripturl + '?action=breezeajax;sa=fetch;js=1;' + smf_session_var + '=' + smf_session_id,
		data : passingData,
		cache: false,
		dataType: 'json',
		success: function(html)
		{
			oObject.onSuccess(html);
		},
		error: function (html){
			breeze.tools.showNoti(html);
		}
	});
}

breezeLoadMore.prototype.onSuccess(html)
{
	// The server response as a JSON object
	if(html.type == 'info'){

		// Append the html to our temp DIV.
		if (html.data != 'end'){

			// Create a unique UL for this very own status, isn't it great?
			$('#tempDIV_'+ this.numberOfEvents).append(html.data).fadeIn('slow', 'linear', function(){});
		}

		// No more data:(
		else{
			noty({
				text: this.options.endText,
				timeout: 3500,
				theme: 'relax',
				type: 'success'
			});
			$('#loadMoar').fadeOut('slow');
			return;
		}
	}

	else if(html.type == 'error'){
		breeze.tools.showNoti(html);
	}
}

<|endoftext|>


<commit_before>var Promise = require('es6-promise').Promise;
var either  = require('./index').either;
var expect  = require('chai').expect;

module.exports = function genericPromiseChain(methods, myPrototype, options) {

  options = options || {};

  var defaultAction = typeof options.action === 'function' ? options.action : canonical;
  var transform     = options.transform;

  function GenericPromiseChain (operand) {
    "use strict";

    var self = this;

    this._operand = operand;
    this._promise = typeof operand === 'function' ? operand() : operand;
  }

  GenericPromiseChain.prototype = Object.create(myPrototype);

  [ 'then', 'catch' ].forEach(function (name) {

    GenericPromiseChain.prototype[name] = function () {
      "use strict";
      this._promise = this._promise[name].apply(this._promise, arguments);
      return this;
    };

  });

  GenericPromiseChain.prototype.always = function (callback) {
    "use strict";

    return this.then(function (result) { callback(null, result) }, callback);
  };

  GenericPromiseChain.prototype.sleep = function (timeout) {
    "use strict";

    var self = this;
    return self.then(function () {
      return new Promise(function (resolve) {
        setTimeout(resolve, timeout);
      });
    });
  };

  GenericPromiseChain.prototype.expectError = function (callback) {
    "use strict";

    var pattern = '';

    if (typeof callback === 'string') {
      pattern  = callback;
      callback = function (err) { expect(err.message).to.contain(pattern) }
    } else if (callback instanceof RegExp) {
      pattern  = callback;
      callback = function (err) { expect(err.message).to.match(pattern) }
    } else if (callback === undefined) { // noop
      callback = function () {};

    } else if (typeof callback !== 'function') {
      throw new Error('argument for expectError must be a string, RegExp or a function');
    }

    var self = this;

    return self.then(function () {
      throw new Error('error was not thrown');
    }, function (err) {
      expect(err).to.be.instanceof(Error);
      callback(err);
    });
  };

  GenericPromiseChain.prototype.noWait = function () {
    "use strict";

    return new GenericPromiseChain(this._operand);
  };

  GenericPromiseChain.prototype.branch = function () {
    "use strict";

    return new GenericPromiseChain(this._operand, this._promise);
  };

  GenericPromiseChain.prototype.yet = function (code, args) {
    "use strict";

    var args = Array.prototype.slice.call(arguments, 0);
    var self = this;
    //--------------------------------
    return self.catch(function (err) {
      return self.noWait().execute(code, args).then(function (errMessage) {
        throw new Error(err.message + ' ' + errMessage);
      });
    });
  };

  GenericPromiseChain.prototype.methods = methods.concat([
    '__custom__',
    'catch',
    'then',
    'always',
    'sleep',
    'expectError',
    'noWait',
    'branch',
    'yet',
  ]);

  GenericPromiseChain.prototype.__custom__ = function (action, onFail) {
    var self = this;

    // this function should either rethrow the error or call the retry function (passed as the second argument)
    onFail = onFail || function (err) { throw err };

    self._promise = Promise.all([
      typeof self._operand === 'function' ? self._operand() : self._operand, self._promise
    ]).then(function (all) {

      return new Promise(function (resolve, reject) {
        var operand = all[0];
        if (!operand || typeof operand !== 'object') {
          reject(new Error('GenericPromiseChain: invalid operand'));
        }

        if (transform) {
          action = transform(action);
        }

        (function doAction(retryCount) {
          action.call({}, operand, either(function (err) {
            var retryUsed = false;
            function retry (repair) {
              retryUsed = true;
              // if nothing is provided, use a noop repair function
              repair = repair || function (operand, done) { setTimeout(done); }
              repair.call({}, operand, either(reject).or(function () {
                doAction(retryCount + 1);
              }));
            }
            retry.count = retryCount;
            try {
              onFail(err, retry);
            } catch (err) {
              return reject(err); // stop here
            }
            if (!retryUsed) {
              reject(new Error('The onFail callback should either throw an error or call the `retry` routine immediately.'));
            }
          }).or(resolve));
        })(0);

      });
    });
    return self;
  };

  methods.forEach(function (name) {
    "use strict";

    /**
     * Update the current promise and return this to allow chaining.
     */
    GenericPromiseChain.prototype[name] = function () {
      var args = Array.prototype.slice.call(arguments, 0);
      return this.__custom__(function (operand, done) {
        defaultAction(operand, name, args, done);
      });
    };

  });

  function canonical (operand, name, args, done) {
    if (!operand[name]) {
      done(new Error('GenericPromiseChain: operand does not implement method: ' + name));
    } else {
      args.push(done);
      operand[name].apply(operand, args);
    }
  }

  return GenericPromiseChain;

}

function cleanError(reject) {
  return function (err) {
    if (err && !(err instanceof Error)) {
      err = new Error(err.message || err.toString());
    }
    reject(err);
  }
}
<commit_msg>Added missing clean error<commit_after>var Promise = require('es6-promise').Promise;
var either  = require('./index').either;
var expect  = require('chai').expect;

module.exports = function genericPromiseChain(methods, myPrototype, options) {

  options = options || {};

  var defaultAction = typeof options.action === 'function' ? options.action : canonical;
  var transform     = options.transform;

  function GenericPromiseChain (operand) {
    "use strict";

    var self = this;

    this._operand = operand;
    this._promise = typeof operand === 'function' ? operand() : operand;
  }

  GenericPromiseChain.prototype = Object.create(myPrototype);

  [ 'then', 'catch' ].forEach(function (name) {

    GenericPromiseChain.prototype[name] = function () {
      "use strict";
      this._promise = this._promise[name].apply(this._promise, arguments);
      return this;
    };

  });

  GenericPromiseChain.prototype.always = function (callback) {
    "use strict";

    return this.then(function (result) { callback(null, result) }, callback);
  };

  GenericPromiseChain.prototype.sleep = function (timeout) {
    "use strict";

    var self = this;
    return self.then(function () {
      return new Promise(function (resolve) {
        setTimeout(resolve, timeout);
      });
    });
  };

  GenericPromiseChain.prototype.expectError = function (callback) {
    "use strict";

    var pattern = '';

    if (typeof callback === 'string') {
      pattern  = callback;
      callback = function (err) { expect(err.message).to.contain(pattern) }
    } else if (callback instanceof RegExp) {
      pattern  = callback;
      callback = function (err) { expect(err.message).to.match(pattern) }
    } else if (callback === undefined) { // noop
      callback = function () {};

    } else if (typeof callback !== 'function') {
      throw new Error('argument for expectError must be a string, RegExp or a function');
    }

    var self = this;

    return self.then(function () {
      throw new Error('error was not thrown');
    }, function (err) {
      expect(err).to.be.instanceof(Error);
      callback(err);
    });
  };

  GenericPromiseChain.prototype.noWait = function () {
    "use strict";

    return new GenericPromiseChain(this._operand);
  };

  GenericPromiseChain.prototype.branch = function () {
    "use strict";

    return new GenericPromiseChain(this._operand, this._promise);
  };

  GenericPromiseChain.prototype.yet = function (code, args) {
    "use strict";

    var args = Array.prototype.slice.call(arguments, 0);
    var self = this;
    //--------------------------------
    return self.catch(function (err) {
      return self.noWait().execute(code, args).then(function (errMessage) {
        throw new Error(err.message + ' ' + errMessage);
      });
    });
  };

  GenericPromiseChain.prototype.methods = methods.concat([
    '__custom__',
    'catch',
    'then',
    'always',
    'sleep',
    'expectError',
    'noWait',
    'branch',
    'yet',
  ]);

  GenericPromiseChain.prototype.__custom__ = function (action, onFail) {
    var self = this;

    // this function should either rethrow the error or call the retry function (passed as the second argument)
    onFail = onFail || function (err) { throw err };

    self._promise = Promise.all([
      typeof self._operand === 'function' ? self._operand() : self._operand, self._promise
    ]).then(function (all) {

      return new Promise(function (resolve, reject) {
        var operand = all[0];
        if (!operand || typeof operand !== 'object') {
          reject(new Error('GenericPromiseChain: invalid operand'));
        }

        if (transform) {
          action = transform(action);
        }

        (function doAction(retryCount) {
          action.call({}, operand, either(function (err) {
            var retryUsed = false;
            function retry (repair) {
              retryUsed = true;
              // if nothing is provided, use a noop repair function
              repair = repair || function (operand, done) { setTimeout(done); }
              repair.call({}, operand, either(reject).or(function () {
                doAction(retryCount + 1);
              }));
            }
            retry.count = retryCount;
            try {
              onFail(err, retry);
            } catch (err) {
              return cleanError(reject)(err); // stop here
            }
            if (!retryUsed) {
              reject(new Error('The onFail callback should either throw an error or call the `retry` routine immediately.'));
            }
          }).or(resolve));
        })(0);

      });
    });
    return self;
  };

  methods.forEach(function (name) {
    "use strict";

    /**
     * Update the current promise and return this to allow chaining.
     */
    GenericPromiseChain.prototype[name] = function () {
      var args = Array.prototype.slice.call(arguments, 0);
      return this.__custom__(function (operand, done) {
        defaultAction(operand, name, args, done);
      });
    };

  });

  function canonical (operand, name, args, done) {
    if (!operand[name]) {
      done(new Error('GenericPromiseChain: operand does not implement method: ' + name));
    } else {
      args.push(done);
      operand[name].apply(operand, args);
    }
  }

  return GenericPromiseChain;

}

function cleanError(reject) {
  return function (err) {
    if (err && !(err instanceof Error)) {
      err = new Error(err.message || err.toString());
    }
    reject(err);
  }
}
<|endoftext|>


<commit_before>

/**
  * @desc shuffles an array using the Fisher-Yates shuffle algorithm
  * @param {array} array - The array to be shuffled
  * @return {array} array - Returns the shuffled array, even though this is not necessary, since it's shuffled in place
*/
function shuffle(array) {
	var l = array.length;
    var temp;
    var i;

    // While there remain elements to be shuffled
    while(l) {
        // Pick a remaining element…
        i = Math.floor(Math.random() * l--);
        // And swap it with the current element.
        temp = array[l];
        array[l] = array[i];
        array[i] = temp;
    }

    return array;
}<commit_msg>Added high-low functions<commit_after>"use strict";

/**
  * @desc shuffles an array using the Fisher-Yates shuffle algorithm
  * @param {array} array - The array to be shuffled
  * @return {array} array - Returns the shuffled array, even though this is not necessary, since it's shuffled in place
*/
function shuffle(array) {
	var l = array.length;
    var temp;
    var i;

    // While there remain elements to be shuffled
    while(l) {
        // Pick a remaining element…
        i = Math.floor(Math.random() * l--);
        // And swap it with the current element.
        temp = array[l];
        array[l] = array[i];
        array[i] = temp;
    }

    return array;
}

/*
 * ITEMS
 */

/**
  * @desc given a number (between 0 and 9) returns whether the number is HIGH or LOW, where HIGH denotes numbers 5-9 and LOW denotes numbers 0-4
  * @param {number} intInput - The input number (should be between 0 and 9)
  * @return {string} strOutput - Returns an string of type HIGH, LOW
*/

function highLow(number) {
    if(Number.isInteger(number)) {
        if(number >= 0 && number <= 4) {
            return "LOW";
        } else if (number >= 5 && number <= 9) {
            return "HIGH";
        } else {
            throw new Error("integer not in range 0-9");
        }
    } else {
        throw new Error("not an integer");
    }
}

/**
  * @desc given an array of numbers between 0 and 9 return an array of entries of type HIGH, LOW where HIGH denotes numbers 5-9 and LOW denotes numbers 0-4
  * @param {array} arrInput - The input array containing numbers selected from the range 0-9
  * @return {array} arrOutput - Returns an array of same length as input array with entries of the type HIGH, LOW
*/

function highLowArray(arrInput) {
    if(Array.isArray(arrInput)) {
        return arrInput.map(highLow);
    } else {
        throw new Error("not an array");
    }
}
<|endoftext|>


<commit_before>'use strict';

const assert = require('assert');
const app = require('../../../src/app');
const mockAws = require('./aws/s3.mock');
const mockery = require('mockery');

describe('fileStorage service', function () {

	before(function (done) {
		// Enable mockery to mock objects
		mockery.enable({
			warnOnUnregistered: false
		});

		mockery.registerMock('aws-sdk', mockAws);

		delete require.cache[require.resolve('../../../src/services/fileStorage/strategies/awsS3')];
		done();
	});

	after(function () {
		mockery.deregisterAll();
		mockery.disable();
	});

	it('registered the fileStorage service', () => {
		assert.ok(app.service('fileStorage'));
	});

	it('should has a properly worked creation function', () => {
		assert.ok(app.service('fileStorage').create({schoolId: '0000d186816abba584714c5f'}));
	});
});
<commit_msg>add some tests<commit_after>'use strict';

const assert = require('assert');
const app = require('../../../src/app');
const mockAws = require('./aws/s3.mock');
const mockery = require('mockery');

describe('fileStorage service', function () {

	before(function (done) {
		// Enable mockery to mock objects
		mockery.enable({
			warnOnUnregistered: false
		});

		mockery.registerMock('aws-sdk', mockAws);

		delete require.cache[require.resolve('../../../src/services/fileStorage/strategies/awsS3')];
		done();
	});

	after(function () {
		mockery.deregisterAll();
		mockery.disable();
	});

	it('registered the fileStorage service', () => {
		assert.ok(app.service('fileStorage'));
	});

	it('registered the fileModel service', () => {
		assert.ok(app.service('files'));
	});

	it('registered the directoryModel service', () => {
		assert.ok(app.service('directories'));
	});

	it('should has a properly worked creation function', () => {
		assert.ok(app.service('fileStorage').create({schoolId: '0000d186816abba584714c5f'}));
	});

	it('should has a properly worked find function', () => {
		assert.ok(app.service('fileStorage').find({qs: {path: 'users/0000d213816abba584714c0a/'}}));
	});
});
<|endoftext|>