<commit_before>/* eslint-env node */
/* eslint-disable camelcase */ // for uglify options
/**
 * module.exports ... is required for things to work
 * @param {Object} grunt instance of Grunt.
 */
module.exports = function (grunt) {
  'use strict';

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-exec');
  grunt.loadNpmTasks('grunt-mocha');
  grunt.loadNpmTasks('grunt-contrib-connect');

  grunt.initConfig({

    clean: {
      build: {
        src: ['build', 'forms/locales/**/i18n.js']
      }
    },

    exec: {
      messageformat: {
        cmd: 'node node_modules/messageformat/bin/messageformat.js -l en forms/locales/en forms/locales/en/i18n.js'
      }
    },

    requirejs: {
      compile: {
        options: {
          baseUrl: '.',
          fileExclusionRegExp: /(^\.)|build|css|docs|eslint|grunt|lodash|parts|phantomjs|test|(\.json$)|(\.md$)|(\.txt$)/,
          dir: 'build',
          skipDirOptimize: false,
//          optimize: 'uglify2',
          optimize: 'none',
          uglify: {
            max_line_length: 80
          },
          uglify2: {
            output: {
              max_line_len: 80
            },
            warnings: false
          },
          paths: {
            // exclude these from the build (load from CDN)
            backbone: 'empty:',
            bluebird: 'empty:',
            jquery: 'empty:',
            jquerymobile: 'empty:',
            underscore: 'empty:',
            signaturepad: 'empty:',
            // libraries to be built-in
            '@blinkmobile/cast-property-types': 'node_modules/@blinkmobile/cast-property-types/dist/index',
            '@blinkmobile/geolocation': 'node_modules/@blinkmobile/geolocation/geolocation',
            '@blinkmobile/html-class-data': 'node_modules/@blinkmobile/html-class-data/dist/index',
            '@blinkmobile/jqpromise': 'node_modules/@blinkmobile/jqpromise/dist/index',
            '@blinkmobile/varied-definition': 'node_modules/@blinkmobile/varied-definition/dist/index',
            'typed-errors': 'node_modules/js-typed-errors/dist/typed-errors',
            'classnames': 'node_modules/classnames/index',
            moment: 'node_modules/moment/min/moment.min',
            picker: 'node_modules/pickadate/lib/picker',
            'picker.date': 'node_modules/pickadate/lib/picker.date',
            'picker.time': 'node_modules/pickadate/lib/picker.time',
            'poll-until': 'node_modules/poll-until/poll-until',
            'queue-async': 'node_modules/queue-async/queue',
            uuid: 'node_modules/node-uuid/uuid',
            // Require.JS plugins
            text: 'node_modules/text/text'
          },
          modules: [
            {
              name: 'forms/jqm',
              include: [
                'moment',
                'picker.date',
                'picker.time'
              ],
              insertRequire: ['forms/jqm']
            }
          ],
          wrap: {
            startFile: [
              // 'parts/00-start.frag',
              // 'parts/01-jquery.frag'
            ],
            endFile: [
              'parts/99-end.frag',
              'forms/locales/en/i18n.js'
            ]
          }
        }
      }
    },

    uglify: {
      'Forms3+jQM': {
        options: {
          sourceMap: true,
          sourceMapName: 'build/forms3jqm.js.map',
          sourceMapIncludeSources: true,
          beautify: {
            width: 80,
            max_line_len: 80
          }
        },
        files: {
          'build/forms3jqm.min.js': [
            'build/forms/jqm.js'
          ]
        }
      }
    },

    mocha: {
      all: {
        src: ['test/*/index.html'],
        options: {
          run: false,
          timeout: 10000,
          log: true
        }
      }
    },

    connect: {
      server: {
        options: {
          hostname: '*',
          port: 8000,
          base: '.',
          keepalive: true
        }
      }
    },

    watch: {
      i18n: {
        files: [
          '!forms/locales/**/*',
          '!forms/locales/**/i18n.js'
        ],
        tasks: 'messageformat'
      },
      src: {
        files: [
          'Gruntfile.js',
          'forms/**/*',
          'forms/locales/**/i18n.js',
          '!build/**/*',
          'parts/*'
        ],
        tasks: [
          'clean',
          'requirejs',
          'uglify',
          'connect'
        ],
        options: {
          atBegin: true
        }
      },
      tests: {
        files: [
          'test/**/*'
        ],
        tasks: ['eslint', 'mocha']
      },
      options: {
        interrupt: true
      }
    }

  });

  grunt.registerTask('default', ['test']);

  grunt.registerTask('build', [
    'clean',
    'exec:messageformat',
    'requirejs',
    'uglify'
  ]);

  grunt.registerTask('test', [
    'build',
    'mocha'
  ]);
};
<commit_msg>(chore) tests get source maps; grunt cleanup<commit_after>/* eslint-env node */
/* eslint-disable camelcase */ // for uglify options
/**
 * module.exports ... is required for things to work
 * @param {Object} grunt instance of Grunt.
 */
module.exports = function (grunt) {
  'use strict';

  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-exec');
  grunt.loadNpmTasks('grunt-mocha');
  grunt.loadNpmTasks('grunt-contrib-connect');

  grunt.initConfig({

    clean: {
      build: {
        src: ['build', 'forms/locales/**/i18n.js']
      }
    },

    exec: {
      messageformat: {
        cmd: 'node node_modules/messageformat/bin/messageformat.js -l en forms/locales/en forms/locales/en/i18n.js'
      }
    },

    requirejs: {
      compile: {
        options: {
          baseUrl: '.',
          fileExclusionRegExp: /(^\.)|build|css|docs|eslint|grunt|lodash|parts|phantomjs|test|(\.json$)|(\.md$)|(\.txt$)/,
          dir: 'build',
          skipDirOptimize: false,
          generateSourceMaps: true,
          optimize: 'none',
          paths: {
            // exclude these from the build (load from CDN)
            backbone: 'empty:',
            bluebird: 'empty:',
            jquery: 'empty:',
            jquerymobile: 'empty:',
            underscore: 'empty:',
            signaturepad: 'empty:',
            // libraries to be built-in
            '@blinkmobile/cast-property-types': 'node_modules/@blinkmobile/cast-property-types/dist/index',
            '@blinkmobile/geolocation': 'node_modules/@blinkmobile/geolocation/geolocation',
            '@blinkmobile/html-class-data': 'node_modules/@blinkmobile/html-class-data/dist/index',
            '@blinkmobile/jqpromise': 'node_modules/@blinkmobile/jqpromise/dist/index',
            '@blinkmobile/varied-definition': 'node_modules/@blinkmobile/varied-definition/dist/index',
            'typed-errors': 'node_modules/js-typed-errors/dist/typed-errors',
            'classnames': 'node_modules/classnames/index',
            moment: 'node_modules/moment/min/moment.min',
            picker: 'node_modules/pickadate/lib/picker',
            'picker.date': 'node_modules/pickadate/lib/picker.date',
            'picker.time': 'node_modules/pickadate/lib/picker.time',
            'poll-until': 'node_modules/poll-until/poll-until',
            'queue-async': 'node_modules/queue-async/queue',
            uuid: 'node_modules/node-uuid/uuid',
            // Require.JS plugins
            text: 'node_modules/text/text'
          },
          modules: [
            {
              name: 'forms/jqm',
              include: [
                'moment',
                'picker.date',
                'picker.time'
              ],
              insertRequire: ['forms/jqm']
            }
          ],
          wrap: {
            startFile: [
              // 'parts/00-start.frag',
              // 'parts/01-jquery.frag'
            ],
            endFile: [
              'parts/99-end.frag',
              'forms/locales/en/i18n.js'
            ]
          }
        }
      }
    },

    uglify: {
      'Forms3+jQM': {
        options: {
          sourceMap: true,
          sourceMapName: 'build/forms3jqm.js.map',
          sourceMapIncludeSources: true,
          beautify: {
            width: 80,
            max_line_len: 80
          }
        },
        files: {
          'build/forms3jqm.min.js': [
            'build/forms/jqm.js'
          ]
        }
      }
    },

    mocha: {
      all: {
        src: ['test/*/index.html'],
        options: {
          run: false,
          timeout: 10000,
          log: true
        }
      }
    },

    connect: {
      server: {
        options: {
          hostname: '*',
          port: 8000,
          base: '.',
          keepalive: true
        }
      }
    },

    watch: {
      i18n: {
        files: [
          '!forms/locales/**/*',
          '!forms/locales/**/i18n.js'
        ],
        tasks: 'messageformat'
      },
      src: {
        files: [
          'Gruntfile.js',
          'forms/**/*',
          'forms/locales/**/i18n.js',
          '!build/**/*',
          'parts/*'
        ],
        tasks: [
          'clean',
          'requirejs',
          'uglify',
          'connect'
        ],
        options: {
          atBegin: true
        }
      },
      tests: {
        files: [
          'test/**/*'
        ],
        tasks: ['eslint', 'mocha']
      },
      options: {
        interrupt: true
      }
    }

  });

  grunt.registerTask('default', ['test']);

  grunt.registerTask('build', [
    'clean',
    'exec:messageformat',
    'requirejs',
    'uglify'
  ]);

  grunt.registerTask('test', [
    'build',
    'mocha'
  ]);
};
<|endoftext|>


<commit_before>var assert = require("assert");

var Spawner = require("../src/spawner").spawner,
	Crawler = require("../src/crawler").crawler,
	spawner = new Spawner(),
	crawler = new Crawler();

// Our leto setups
var test_move_leto = 	 require( __dirname + "/test_letos/test_move_leto.json" ),
	test_change_leto = 	 require( __dirname + "/test_letos/test_change_leto.json" ),
	test_replace_leto =  require( __dirname + "/test_letos/test_replace_leto.json" ),
	test_execute_leto =  require( __dirname + "/test_letos/test_execute_leto.json" ),
	test_crawl_leto =  require( __dirname + "/test_letos/test_crawl_leto.json" ),
	test_template_leto = require( __dirname + "/test_letos/test_template_leto.json" );

// Set some fake sources for our letos, these would be set by the server otherwise
test_move_leto.__source		 = process.cwd();
test_change_leto.__source	 = process.cwd();
test_replace_leto.__source 	 = process.cwd();
test_execute_leto.__source   = process.cwd();
test_crawl_leto.__source   = process.cwd();
test_template_leto.__source  = process.cwd();

describe('spawner', function() {
	describe('#spawn()', function() {

		it('should move some files', function(done) {
			spawner.spawn( __dirname, test_move_leto, {}, {}, function() {
				// Make sure the file was moved
				var movedMovingPlan = require( __dirname + "/_TEST/test_moving_plan.json" );
				if( movedMovingPlan != undefined ) {
				    done();
				} else {
					done( "File not moved" );
				}
			});
		});

		it('should change some stuff', function(done) {
			var contents = {
				templateFunctionName: "bestRuleName"
			};

			spawner.spawn( __dirname, test_change_leto, {}, contents, function() {

				var Thing = require( __dirname + "/_TEST/TestChangerSource" ).ChangerThing;

				var thing = new Thing();

				if( thing === undefined ) {
					done( "Failed to move our file into place to setup our 'change' test" );
				}

				if( thing.changeTest() != 444 ) {
					done( "Failed to change line" );
				} else if( thing.insertTest() != 5 ) {
					done( "Failed to insert line" );
				} else if( thing[contents.templateFunctionName]() != 16 ) {
					done( "Failed to templatize ruleset contents" );
				} else {
					done();
				}
			});
		});

		it('should build template files', function(done) {
			var contents = {
				testFolder: "_TEST",
				contents: "return 'poop';"
			};

			// Generate a node module and call the function thgat it exports
			spawner.spawn( __dirname, test_template_leto, {}, contents, function() {
				// Call the function from the module we just generated
				if( require(__dirname + "/_TEST/templatedScript").test() == "poop" ) {
				    done();
				} else {
					done( "File not moved" );
				}
			});
		});

		it('should do batch replace on files inside of a dir', function(done) {
			var contents = {
				testClassName: "MyGeneratedClass"
			};

			spawner.spawn( __dirname+"/_TEST/", test_replace_leto, {}, contents, function() {
				try {
					// If this file loads with the name we're passing through
					// contents, it proves that we're replacing names in file paths
					var MyGeneratedClass = require( __dirname + "/_TEST/MyGeneratedClass" ).MyGeneratedClass;
				} catch( error ) {
					done( "Error loading file with templated name: " + error );
				}

				var myObject = new MyGeneratedClass();

				// This proves that we've loaded the file and changed its contents
				if( myObject.test() == "poop" ) {
				    done();
				} else {
					done( "File not moved" );
				}
			});
		});

		it('should execute a command', function(done) {
			spawner.spawn( __dirname, test_execute_leto, {}, {}, function() {
				// Make sure the file was moved
				if( require('path').existsSync( __dirname + "/_TEST/test.txt") ) {
				    done();
				} else {
					done( "Command not executed" );
				}
			});
		});
	});	// end describe spawn()
}); // end describe spawner

describe('crawler', function() {

	describe('#crawl()', function() {

		crawler.crawl( __dirname, test_crawl_leto, function() {

			it('should create a leto_params.json file', function(done) {
				// Make sure the file was moved
				if( require(__dirname + "/leto_params.json") != undefined ) {
				    done();
				} else {
					done( "Can't load leto_params.json" );
				}
			});

			it('should remove params from the crawl list when they have been overridden', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams["executeParam"] == undefined ) {
				    done();
				} else {
					done( "Param listed in our params when it shouldn't be" );
				}
			});

			it('should load params from our functions file', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams["functionParam"] != undefined ) {
				    done();
				} else {
					done( "Failed to load param from functions override file" );
				}
			});

			it('should load params from "template" steps destination paths', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams["templateDestParam"] != undefined ) {
				    done();
				} else {
					done( "Can't load params from 'template' destination paths" );
				}
			});

			it('should load params from "template" steps template files', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams.contents != undefined ) {
				    done();
				} else {
					done( "Can't load params from template file contents" );
				}
			});

			it('should load params from "replace" steps keywords', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams["replaceKeyword1"] != undefined && templateParams["replaceKeyword2"] != undefined ) {
				    done();
				} else {
					done( "Replace params not properly setup" );
				}
			});

		});

	});	// end describe crawl()

}); // end describe crawler<commit_msg>Unit test for recursive templating<commit_after>var assert = require("assert");

var Spawner = require("../src/spawner").spawner,
	Crawler = require("../src/crawler").crawler,
	spawner = new Spawner(),
	crawler = new Crawler();

// Our leto setups
var test_move_leto = 	  require( __dirname + "/test_letos/test_move_leto.json" ),
	test_change_leto = 	  require( __dirname + "/test_letos/test_change_leto.json" ),
	test_replace_leto =   require( __dirname + "/test_letos/test_replace_leto.json" ),
	test_execute_leto =   require( __dirname + "/test_letos/test_execute_leto.json" ),
	test_crawl_leto =     require( __dirname + "/test_letos/test_crawl_leto.json" ),
	test_template_leto =  require( __dirname + "/test_letos/test_template_leto.json" ),
	test_recursive_leto = require( __dirname + "/test_letos/test_recursive_leto.json" );

// Set some fake sources for our letos, these would be set by the server otherwise
test_move_leto.__source		 = process.cwd();
test_change_leto.__source	 = process.cwd();
test_replace_leto.__source 	 = process.cwd();
test_execute_leto.__source   = process.cwd();
test_crawl_leto.__source     = process.cwd();
test_template_leto.__source  = process.cwd();
test_recursive_leto.__source = process.cwd();

describe('spawner', function() {
	describe('#spawn()', function() {

		it('should move some files', function(done) {
			spawner.spawn( __dirname, test_move_leto, {}, {}, function() {
				// Make sure the file was moved
				var movedMovingPlan = require( __dirname + "/_TEST/test_moving_plan.json" );
				if( movedMovingPlan != undefined ) {
				    done();
				} else {
					done( "File not moved" );
				}
			});
		});

		it('should change some stuff', function(done) {
			var contents = {
				templateFunctionName: "bestRuleName"
			};

			spawner.spawn( __dirname, test_change_leto, {}, contents, function() {

				var Thing = require( __dirname + "/_TEST/TestChangerSource" ).ChangerThing;

				var thing = new Thing();

				if( thing === undefined ) {
					done( "Failed to move our file into place to setup our 'change' test" );
				}

				if( thing.changeTest() != 444 ) {
					done( "Failed to change line" );
				} else if( thing.insertTest() != 5 ) {
					done( "Failed to insert line" );
				} else if( thing[contents.templateFunctionName]() != 16 ) {
					done( "Failed to templatize ruleset contents" );
				} else {
					done();
				}
			});
		});

		it('should build template files', function(done) {
			var contents = {
				testFolder: "_TEST",
				contents: "return 'poop';",
				outputScript: "templatedScript"
			};

			// Generate a node module and call the function that it exports
			spawner.spawn( __dirname, test_template_leto, {}, contents, function() {
				// Call the function from the module we just generated
				if( require(__dirname + "/_TEST/templatedScript").test() == "poop" ) {
				    done();
				} else {
					done( "File not moved" );
				}
			});
		});

		it('should spawn templates recursively', function(done) {
			var contents = {
				testFolder: "_TEST",
				contents: "return 'doop';",
				outputScript: "recursiveOutput"
			};

			// Spawn a template recursively
			spawner.spawn( __dirname, test_recursive_leto, {}, contents, function() {
				var childPath = __dirname + "/_TEST/recursiveOutput";

				try {
					var scriptTestOutput = require(childPath).test();
				} catch(err) {
					return done( "File didn't exist at " + childPath );
				}

				// Call the function from the module we just generated
				if( scriptTestOutput == "doop" ) {
				    done();
				} else {
					done( "Failed to do the stuff in the child template" );
				}
			});
		});

		it('should do batch replace on files inside of a dir', function(done) {
			var contents = {
				testClassName: "MyGeneratedClass"
			};

			spawner.spawn( __dirname+"/_TEST/", test_replace_leto, {}, contents, function() {
				try {
					// If this file loads with the name we're passing through
					// contents, it proves that we're replacing names in file paths
					var MyGeneratedClass = require( __dirname + "/_TEST/MyGeneratedClass" ).MyGeneratedClass;
				} catch( error ) {
					done( "Error loading file with templated name: " + error );
				}

				var myObject = new MyGeneratedClass();

				// This proves that we've loaded the file and changed its contents
				if( myObject.test() == "poop" ) {
				    done();
				} else {
					done( "File not moved" );
				}
			});
		});

		it('should execute a command', function(done) {
			spawner.spawn( __dirname, test_execute_leto, {}, {}, function() {
				// Make sure the file was moved
				if( require('path').existsSync( __dirname + "/_TEST/test.txt") ) {
				    done();
				} else {
					done( "Command not executed" );
				}
			});
		});
	});	// end describe spawn()
}); // end describe spawner

describe('crawler', function() {

	describe('#crawl()', function() {

		crawler.crawl( __dirname, test_crawl_leto, function() {

			it('should create a leto_params.json file', function(done) {
				// Make sure the file was moved
				if( require(__dirname + "/leto_params.json") != undefined ) {
				    done();
				} else {
					done( "Can't load leto_params.json" );
				}
			});

			it('should remove params from the crawl list when they have been overridden', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams["executeParam"] == undefined ) {
				    done();
				} else {
					done( "Param listed in our params when it shouldn't be" );
				}
			});

			it('should load params from our functions file', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams["functionParam"] != undefined ) {
				    done();
				} else {
					done( "Failed to load param from functions override file" );
				}
			});

			it('should load params from "template" steps destination paths', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams["templateDestParam"] != undefined ) {
				    done();
				} else {
					done( "Can't load params from 'template' destination paths" );
				}
			});

			it('should load params from "template" steps template files', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams.contents != undefined ) {
				    done();
				} else {
					done( "Can't load params from template file contents" );
				}
			});

			it('should load params from "replace" steps keywords', function(done) {
				var templateParams = require(__dirname + "/leto_params.json");

				if( templateParams["replaceKeyword1"] != undefined && templateParams["replaceKeyword2"] != undefined ) {
				    done();
				} else {
					done( "Replace params not properly setup" );
				}
			});

		});

	});	// end describe crawl()

}); // end describe crawler//<|endoftext|>


<commit_before>var expect = require('chai').expect;
var Emitter = require('../emitter.js');

describe('Emitter(obj)', function () {
    it('can work as a mixin', function () {
        var obj = {};
        var foo = function foo() {};
        Emitter(obj);
        obj.on('foo', foo);
        expect(obj._registry).to.eql({'foo': [foo]});
    });
});

describe('Emitter', function () {
    var emitter;

    beforeEach(function () {
        emitter = new Emitter();
    });

    describe('.getListeners(event)', function () {
        describe('when there is no event registry', function () {
            it('creates the event registry', function () {
                expect(emitter._registry).to.equal(undefined);
                emitter.getListeners('foo');
                expect(emitter._registry).to.eql({'foo': []});
            });
        });

        describe('when the event has callbacks', function () {
            it('returns an array of callbacks', function () {
                var foo = function foo() {};
                var bar = function bar() {};
                emitter._registry = {'foo': [foo, bar]};
                expect(emitter.getListeners('foo')).to.eql([foo, bar]);
            });
        });

        describe('when the event has no callbacks (i.e., it doesn\'t exist in the registry)', function () {
            it('returns an empty array', function () {
                expect(emitter.getListeners('foo')).to.eql([]);
            });
        });
    });

    describe('.hasListeners(event)', function () {
        describe('when the event has callbacks', function(){
            it('returns true', function(){
                var foo = function foo() {};
                emitter._registry = {'foo': [foo]};
                expect(emitter.hasListeners('foo')).to.equal(true);
            });
        });

        describe('when the event has no callbacks (i.e., it doesn\'t exist in the registry)', function () {
            it('returns false', function () {
                expect(emitter.hasListeners('foo')).to.equal(false);
            });
        });
    });

    describe('.on(event, callback)', function () {
        describe('when the callback is a function', function () {
            it('adds the callback', function () {
                var foo = function foo() {};
                emitter.on('foo', foo);
                expect(emitter._registry['foo']).to.eql([foo]);
            });

            it('does not add the callback if it\'s already registered', function () {
                var foo = function foo() {};
                emitter.on('foo', foo);
                emitter.on('foo', foo);
                expect(emitter._registry['foo']).to.eql([foo]);
            });
        });

        describe('when the callback is not a function', function () {
            // can't get .throw working :(
            it('throws a TypeError');
        });
    });

    describe('.once(event, callback)', function () {
        it('adds a one-off callback', function () {
            var calls = [];
            var foo = function foo() { calls.push('foo'); };
            var bar = function bar() {};
            emitter.once('foo', foo);
            emitter.on('foo', bar);
            emitter.trigger('foo');

            expect(emitter._registry['foo']).to.eql([bar]);
            expect(calls).to.eql(['foo']);
        });

        it('can be removed with `off()`', function () {
            var foo = function foo() {};
            var bar = function bar() {};
            emitter.once('foo', foo);
            emitter.on('foo', bar);
            emitter.off('foo', foo);

            expect(emitter._registry['foo']).to.eql([bar]);
        });
    });

    describe('.off(event, callback)', function () {
        describe('when the callback is a function', function () {
            it('removes the callback', function () {
                var foo = function foo() {};
                var bar = function bar() {};
                emitter._registry = {'foo': [foo, bar]};
                emitter.off('foo', foo);

                expect(emitter._registry['foo']).to.eql([bar]);
            });
        });

        describe('when the callback is not a function', function () {
            // can't get .throw working :(
            it('throws a TypeError');
        });
    });

    describe('.off(event)', function () {
        it('deletes the event (and its callbacks)', function () {
            var foo = function foo() {};
            var bar = function bar() {};
            emitter._registry = {'foo': [foo, bar]};
            emitter.off('foo');

            expect(emitter._registry['foo']).to.equal(undefined);
        });
    });

    describe('.off()', function () {
        it('deletes the registry', function () {
            var foo = function foo() {};
            var bar = function bar() {};
            emitter._registry = {'foo': [foo, bar]};
            emitter.off();

            expect(emitter._registry).to.equal(undefined);
        });
    });

    describe('.trigger(event, args)', function () {
        describe('when the event exists', function () {
            it('fires an event\'s callback', function () {
                var calls = [];
                var foo = function foo() { calls.push('foo'); };

                emitter.on('foo', foo);
                emitter.trigger('foo');

                expect(calls).to.eql(['foo']);
            });

            it('fires an event\'s callback with arguments', function () {
                var calls = [];
                var foo = function foo(arg1, arg2) { calls.push(arg1, arg2); };

                emitter.on('foo', foo);
                emitter.trigger('foo', 1, 2);
                emitter.trigger('foo', 3, 4);

                expect(calls).to.eql([
                    1, 2,
                    3, 4
                ]);
            });

            it('fires all callbacks for an event, in order', function () {
                var calls = [];
                var foo = function foo() { calls.push('foo'); };
                var bar = function foo() { calls.push('bar'); };

                emitter.on('foo', foo);
                emitter.on('foo', bar);
                emitter.trigger('foo');

                expect(calls).to.eql(['foo', 'bar']);
            });

            it('fires all callbacks for an event, after one has been removed', function () {
                var calls = [];
                var foo = function foo() { calls.push('foo'); };
                var bar = function foo() { calls.push('bar'); };
                var baz = function foo() { calls.push('baz'); };

                emitter.on('foo', foo);
                emitter.on('foo', bar);
                emitter.on('foo', baz);
                emitter.off('foo', bar);
                emitter.trigger('foo');

                expect(calls).to.eql(['foo', 'baz']);
            });
        });

        describe('when the event doesn\'t exist', function () {
            // can't get .throw working :(
            it('throws an Error');
        });
    });
});
<commit_msg>Remove an unnecessary test<commit_after>var expect = require('chai').expect;
var Emitter = require('../emitter.js');

describe('Emitter(obj)', function () {
    it('can work as a mixin', function () {
        var obj = {};
        var foo = function foo() {};
        Emitter(obj);
        obj.on('foo', foo);
        expect(obj._registry).to.eql({'foo': [foo]});
    });
});

describe('Emitter', function () {
    var emitter;

    beforeEach(function () {
        emitter = new Emitter();
    });

    describe('.getListeners(event)', function () {
        describe('when there is no event registry', function () {
            it('creates the event registry', function () {
                expect(emitter._registry).to.equal(undefined);
                emitter.getListeners('foo');
                expect(emitter._registry).to.eql({'foo': []});
            });
        });

        describe('when the event has callbacks', function () {
            it('returns an array of callbacks', function () {
                var foo = function foo() {};
                var bar = function bar() {};
                emitter._registry = {'foo': [foo, bar]};
                expect(emitter.getListeners('foo')).to.eql([foo, bar]);
            });
        });

        describe('when the event has no callbacks (i.e., it doesn\'t exist in the registry)', function () {
            it('returns an empty array', function () {
                expect(emitter.getListeners('foo')).to.eql([]);
            });
        });
    });

    describe('.hasListeners(event)', function () {
        describe('when the event has callbacks', function(){
            it('returns true', function(){
                var foo = function foo() {};
                emitter._registry = {'foo': [foo]};
                expect(emitter.hasListeners('foo')).to.equal(true);
            });
        });

        describe('when the event has no callbacks (i.e., it doesn\'t exist in the registry)', function () {
            it('returns false', function () {
                expect(emitter.hasListeners('foo')).to.equal(false);
            });
        });
    });

    describe('.on(event, callback)', function () {
        describe('when the callback is a function', function () {
            it('adds the callback', function () {
                var foo = function foo() {};
                emitter.on('foo', foo);
                expect(emitter._registry['foo']).to.eql([foo]);
            });

            it('does not add the callback if it\'s already registered', function () {
                var foo = function foo() {};
                emitter.on('foo', foo);
                emitter.on('foo', foo);
                expect(emitter._registry['foo']).to.eql([foo]);
            });
        });

        describe('when the callback is not a function', function () {
            // can't get .throw working :(
            it('throws a TypeError');
        });
    });

    describe('.once(event, callback)', function () {
        it('adds a one-off callback', function () {
            var calls = [];
            var foo = function foo() { calls.push('foo'); };
            var bar = function bar() {};
            emitter.once('foo', foo);
            emitter.on('foo', bar);
            emitter.trigger('foo');

            expect(emitter._registry['foo']).to.eql([bar]);
            expect(calls).to.eql(['foo']);
        });

        it('can be removed with `off()`', function () {
            var foo = function foo() {};
            var bar = function bar() {};
            emitter.once('foo', foo);
            emitter.on('foo', bar);
            emitter.off('foo', foo);

            expect(emitter._registry['foo']).to.eql([bar]);
        });
    });

    describe('.off(event, callback)', function () {
        describe('when the callback is a function', function () {
            it('removes the callback', function () {
                var foo = function foo() {};
                var bar = function bar() {};
                emitter._registry = {'foo': [foo, bar]};
                emitter.off('foo', foo);

                expect(emitter._registry['foo']).to.eql([bar]);
            });
        });

        describe('when the callback is not a function', function () {
            // can't get .throw working :(
            it('throws a TypeError');
        });
    });

    describe('.off(event)', function () {
        it('deletes the event (and its callbacks)', function () {
            var foo = function foo() {};
            var bar = function bar() {};
            emitter._registry = {'foo': [foo, bar]};
            emitter.off('foo');

            expect(emitter._registry['foo']).to.equal(undefined);
        });
    });

    describe('.off()', function () {
        it('deletes the registry', function () {
            var foo = function foo() {};
            var bar = function bar() {};
            emitter._registry = {'foo': [foo, bar]};
            emitter.off();

            expect(emitter._registry).to.equal(undefined);
        });
    });

    describe('.trigger(event, args)', function () {
        describe('when the event exists', function () {
            it('fires an event\'s callback', function () {
                var calls = [];
                var foo = function foo() { calls.push('foo'); };

                emitter.on('foo', foo);
                emitter.trigger('foo');

                expect(calls).to.eql(['foo']);
            });

            it('fires an event\'s callback with arguments', function () {
                var calls = [];
                var foo = function foo(arg1, arg2) { calls.push(arg1, arg2); };

                emitter.on('foo', foo);
                emitter.trigger('foo', 1, 2);
                emitter.trigger('foo', 3, 4);

                expect(calls).to.eql([
                    1, 2,
                    3, 4
                ]);
            });

            it('fires all callbacks for an event, in order', function () {
                var calls = [];
                var foo = function foo() { calls.push('foo'); };
                var bar = function foo() { calls.push('bar'); };

                emitter.on('foo', foo);
                emitter.on('foo', bar);
                emitter.trigger('foo');

                expect(calls).to.eql(['foo', 'bar']);
            });
        });

        describe('when the event doesn\'t exist', function () {
            // can't get .throw working :(
            it('throws an Error');
        });
    });
});
<|endoftext|>


<commit_before>(function() {
  'use strict';

  function shuffle(arr) {
    // shuffle() is a Fisher-Yates shuffling function -- it takes an array and returns the same array, shuffled.
    if (typeof arr != 'Array' || arr.length < 1) {
      console.log('Not sure what this "array" is: ' + arr);
      return arr;
    }
    for (var i = arr.length - 1; i > 0; i--) {
      var j = Math.floor(Math.random() * (i + 1));
      var tmp = arr[i];
      arr[i] = arr[j];
      arr[j] = tmp;
    }
    return arr;
  }

  var FortuneFile = function(fortuneFileId, fortunes) {
    // FortuneFile object
    //   represents a fortune file
    //   has => fortuneFileId (string)
    //   has => fortunes (array of strings)
    if (typeof fortuneFileId != 'String' || fortuneFileId.length < 1) {
      console.log('Not sure what this fortuneFileId is: ' + fortuneFIleId);
      return;
    }
    if (typeof fortunes != 'Array' || fortunes.length < 1) {
      console.log('Not sure what this fortunes "array" is: ' + fortunes);
      return;
    }
    this.fortuneFileId = fortuneFileId;
    this.fortunes = fortunes;
  }

  FortuneFile.prototype.loadFortunes = function (fortuneFileId) {
    var self = this;
    return fetch(this.fortuneFileId).then(function (response) {
      if (response.ok) {
        response.text().then(function(text) {
          self.fortunes = text.split('\n%\n'); // XXX do we want to laod it all in mem?
          shuffle(self.fortunes);
        });
      } else {
        console.log('Our response was not ok :('); // XXX
      }
    });
  }

  FortuneFile.prototype.elem = function(position) {
    // fortuneFile.elem() returns the element at a given position
    return this.fortunes[position];
  }

  var Fortunate = function(fortuneFile) {
    // Fortunate object
    //   the controller
    //   has => currentFortuneFile (the currently loaded FortuneFile object)
    //   has => position (integer) - location of the next fortune in the list to display
    this.position = 0;
    this.currentFortuneFile = fortuneFile;
    this.loadFortunes();
  }

  Fortunate.prototype.loadFortunes = function() {
    // fortune.loadFortunes() loads the current fortuneFile's contents into memory
    var self = this;
    this.currentFortuneFile.loadFortunes().then( function () {
      // Reset the position of the current fortune file
      self.position = 0;
    });
  }

  Fortunate.prototype.switchFortuneFile = function (fortuneFile) {
    // fortune.switchFortuneFile() takes a fortuneFile and switches to it
    this.currentFortuneFile = fortuneFile;
    this.loadFortunes();
  }

  Fortunate.prototype.nextFortune = function () {
    // fortune.nextFortune() returns the next fortune in the current fortune file
    this.position++;
    if (this.position >= this.currentFortuneFile.fortunes.length) {
      // if we've hit the end of the fortune file, let's wrap back to the beginning
      this.position = 0;
    }
    return this.currentFortuneFile.elem(this.position);
  }

  function hashToFortune (hash) {
    // hashToFortune(hash) is a utility function that, when given a location.hash value, returns the corresponding fortune file's path
    if (typeof hash != 'string' || hash.length < 1) {
      console.log('Not sure what this location.hash is: ' + hash);
      return;
    }
    var fortune = hash.replace(/^[^#]+?#/, '');
    return '../fortunes/' + fortune + '.fortune';
  }

  window.addEventListener('load', function() {
    var fortuneElement = window.document.getElementById('fortune');

    // build Fortunate controller
    var fortunate = new Fortunate(new FortuneFile(hashToFortune(document.getElementById('default-fortune').href)));

    document.getElementById('content').addEventListener('click', function() {
      // when the is clicked, replace it with a random Fortune
      fortuneElement.innerHTML = fortunate.nextFortune();
    });

    window.addEventListener('onhashchange', function() {
      // switch fortune files
      fortunate.switchFortuneFile(new FortuneFile(hashToFortune(location.hash)));
    });

 });
})();
<commit_msg>fix error checking<commit_after>(function() {
  'use strict';

  function shuffle(arr) {
    // shuffle() is a Fisher-Yates shuffling function -- it takes an array and returns the same array, shuffled.
    if (typeof arr != 'Array' || arr.length < 1) {
      console.log('Not sure what this "array" is: ' + arr);
      return arr;
    }
    for (var i = arr.length - 1; i > 0; i--) {
      var j = Math.floor(Math.random() * (i + 1));
      var tmp = arr[i];
      arr[i] = arr[j];
      arr[j] = tmp;
    }
    return arr;
  }

  var FortuneFile = function(fortuneFileId, fortunes) {
    // FortuneFile object
    //   represents a fortune file
    //   has => fortuneFileId (string)
    //   has => fortunes (array of strings)
    if (typeof fortuneFileId != 'string' || fortuneFileId.length < 1) {
      console.log('Not sure what this fortuneFileId is: ' + fortuneFIleId);
      return;
    }
    if (typeof fortunes != 'Array' || fortunes.length < 1) {
      console.log('Not sure what this fortunes "array" is: ' + fortunes);
      return;
    }
    this.fortuneFileId = fortuneFileId;
    this.fortunes = fortunes;
  }

  FortuneFile.prototype.loadFortunes = function (fortuneFileId) {
    var self = this;
    return fetch(this.fortuneFileId).then(function (response) {
      if (response.ok) {
        response.text().then(function(text) {
          self.fortunes = text.split('\n%\n'); // XXX do we want to laod it all in mem?
          shuffle(self.fortunes);
        });
      } else {
        console.log('Our response was not ok :('); // XXX
      }
    });
  }

  FortuneFile.prototype.elem = function(position) {
    // fortuneFile.elem() returns the element at a given position
    return this.fortunes[position];
  }

  var Fortunate = function(fortuneFile) {
    // Fortunate object
    //   the controller
    //   has => currentFortuneFile (the currently loaded FortuneFile object)
    //   has => position (integer) - location of the next fortune in the list to display
    this.position = 0;
    this.currentFortuneFile = fortuneFile;
    this.loadFortunes();
  }

  Fortunate.prototype.loadFortunes = function() {
    // fortune.loadFortunes() loads the current fortuneFile's contents into memory
    var self = this;
    this.currentFortuneFile.loadFortunes().then( function () {
      // Reset the position of the current fortune file
      self.position = 0;
    });
  }

  Fortunate.prototype.switchFortuneFile = function (fortuneFile) {
    // fortune.switchFortuneFile() takes a fortuneFile and switches to it
    this.currentFortuneFile = fortuneFile;
    this.loadFortunes();
  }

  Fortunate.prototype.nextFortune = function () {
    // fortune.nextFortune() returns the next fortune in the current fortune file
    this.position++;
    if (this.position >= this.currentFortuneFile.fortunes.length) {
      // if we've hit the end of the fortune file, let's wrap back to the beginning
      this.position = 0;
    }
    return this.currentFortuneFile.elem(this.position);
  }

  function hashToFortune (hash) {
    // hashToFortune(hash) is a utility function that, when given a location.hash value, returns the corresponding fortune file's path
    if (typeof hash != 'string' || hash.length < 1) {
      console.log('Not sure what this location.hash is: ' + hash);
      return;
    }
    var fortune = hash.replace(/^[^#]+?#/, '');
    return '../fortunes/' + fortune + '.fortune';
  }

  window.addEventListener('load', function() {
    var fortuneElement = window.document.getElementById('fortune');

    // build Fortunate controller
    var fortunate = new Fortunate(new FortuneFile(hashToFortune(document.getElementById('default-fortune').href)));

    document.getElementById('content').addEventListener('click', function() {
      // when the is clicked, replace it with a random Fortune
      fortuneElement.innerHTML = fortunate.nextFortune();
    });

    window.addEventListener('onhashchange', function() {
      // switch fortune files
      fortunate.switchFortuneFile(new FortuneFile(hashToFortune(location.hash)));
    });

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


<commit_before><commit_msg>feat: Get index of the card rated and display starts in this card<commit_after><|endoftext|>


<commit_before>$(document).ready(function() {
    $('body').prepend('

');
    createLoader('#canvasloader-container');
    $(document).on('submit', 'form.ajax', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $('#canvasloader-container').fadeIn();
        event.preventDefault();
        var update = $(this).attr('update')?$(this).attr('update') : '';
        var form = $(this);
        ajaxFormSubmit(form,update);

        return false;
    });

    $(document).on('click', 'a.ajax', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $('#canvasloader-container').fadeIn();
        event.preventDefault();
        var update = $(this).attr('update') ? $(this).attr('update') : '';
        var link   = $(this).attr('href');
        ajaxLink(link,update);

        return false;
    });
});

function ajaxFormSubmit(form,update) {
    $.ajax({
        url: $(form).attr('action'),
        context: document.body,
        data: $(form).serialize(),
        type: $(form).attr('method'),
        success: function(jsonResponse) {
            ajaxify(jsonResponse, update);
        }
    });
}

function ajaxLink(link,update) {
    $.ajax({
        url: link,
        context: document.body,
        type: "GET",
        success: function(jsonResponse) {
            ajaxify(jsonResponse, update);
        },
        error: function(jsonResponse) {
            alert("Il semble s'êre produit une erreur");
            $('#canvasloader-container').fadeOut();
        }
    });
}

function ajaxify(jsonResponse, update) {
    var effect;
    if (jsonResponse.substring(0,1)=="{" && jsonResponse.substring(jsonResponse.length-1)=="}") {
        var json = eval("("+jsonResponse+")");
        if (json.update != undefined) {
            update = json.update;
        }
        effect = initEffect("#"+update);
        // check if a callback is given in the response
        if (json.hasOwnProperty("callback")) {
            $.post(json.callback,
            {
                params : json.data
                },
            function(data){
                $("#"+update).html(data);
            });
        } else {//if no callback has been given, we put data in the element to update
            $("#"+update).html(json.data);
        }
    } else {
        effect = initEffect("#"+update);
        $("#"+update).html(jsonResponse);
    }
    if(effect != undefined){
        eval('$("#"+update).'+effect+'()');
    }

    $('#canvasloader-container').fadeOut();

}

function initEffect(id) {
    var effect = "show";
    if($(id).html() != undefined){
        if($(id).html() == ""){
            effect = "slideDown";
            if($(id).attr('data-new-effect') != undefined && $(id).attr('data-new-effect') != ""){
                effect = $(id).attr('data-new-effect');
            }
        }else{
            effect = "fadeIn";
            if($(id).attr('data-update-effect') != undefined && $(id).attr('data-update-effect') != ""){
                effect = $(id).attr('data-update-effect');
            }
        }
    }
    $(id).hide();
    console.log(effect);

    return effect;
}
function createLoader(id) {
    $(id).html("");
}
<commit_msg>remove console.log()<commit_after>$(document).ready(function() {
    $('body').prepend('

');
    createLoader('#canvasloader-container');
    $(document).on('submit', 'form.ajax', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $('#canvasloader-container').fadeIn();
        event.preventDefault();
        var update = $(this).attr('update')?$(this).attr('update') : '';
        var form = $(this);
        ajaxFormSubmit(form,update);

        return false;
    });

    $(document).on('click', 'a.ajax', function(event) {
        if($(this).hasClass('confirm') || $(this).hasClass('confirm-waiting')){
            return false;
        }
        $('#canvasloader-container').fadeIn();
        event.preventDefault();
        var update = $(this).attr('update') ? $(this).attr('update') : '';
        var link   = $(this).attr('href');
        ajaxLink(link,update);

        return false;
    });
});

function ajaxFormSubmit(form,update) {
    $.ajax({
        url: $(form).attr('action'),
        context: document.body,
        data: $(form).serialize(),
        type: $(form).attr('method'),
        success: function(jsonResponse) {
            ajaxify(jsonResponse, update);
        }
    });
}

function ajaxLink(link,update) {
    $.ajax({
        url: link,
        context: document.body,
        type: "GET",
        success: function(jsonResponse) {
            ajaxify(jsonResponse, update);
        },
        error: function(jsonResponse) {
            alert("Il semble s'êre produit une erreur");
            $('#canvasloader-container').fadeOut();
        }
    });
}

function ajaxify(jsonResponse, update) {
    var effect;
    if (jsonResponse.substring(0,1)=="{" && jsonResponse.substring(jsonResponse.length-1)=="}") {
        var json = eval("("+jsonResponse+")");
        if (json.update != undefined) {
            update = json.update;
        }
        effect = initEffect("#"+update);
        // check if a callback is given in the response
        if (json.hasOwnProperty("callback")) {
            $.post(json.callback,
            {
                params : json.data
                },
            function(data){
                $("#"+update).html(data);
            });
        } else {//if no callback has been given, we put data in the element to update
            $("#"+update).html(json.data);
        }
    } else {
        effect = initEffect("#"+update);
        $("#"+update).html(jsonResponse);
    }
    if(effect != undefined){
        eval('$("#"+update).'+effect+'()');
    }

    $('#canvasloader-container').fadeOut();

}

function initEffect(id) {
    var effect = "show";
    if($(id).html() != undefined){
        if($(id).html() == ""){
            effect = "slideDown";
            if($(id).attr('data-new-effect') != undefined && $(id).attr('data-new-effect') != ""){
                effect = $(id).attr('data-new-effect');
            }
        }else{
            effect = "fadeIn";
            if($(id).attr('data-update-effect') != undefined && $(id).attr('data-update-effect') != ""){
                effect = $(id).attr('data-update-effect');
            }
        }
    }
    $(id).hide();

    return effect;
}
function createLoader(id) {
    $(id).html("");
}
<|endoftext|>


<commit_before>'use strict';

var settingsFactory = function settingsFactory($rootScope, $state, $log, $firebaseObject, api){

  var employeeDomain = 'pwc.com';

  var profileCheck = function profileCheck(firebaseUserObject){
    var ref = api.getRef('users', firebaseUserObject.uid);
    var profile = $firebaseObject(ref);

    return profile.$loaded(function(){
      if(profile.$value === null){
        return createProfile(profile, firebaseUserObject);
      } else {
        return profile;
      }
    });

  };

  var createProfile = function createProfile(fbo, authInfo){
    fbo.displayName = authInfo.displayName;
    fbo.email = authInfo.email;
    fbo.photoURL = authInfo.photoURL;
    fbo.employee = employeeCheck(authInfo.email);

    return fbo.$save().then(function(){
      return fbo;
    });
  };

  function employeeCheck(email){
    return email.slice(-employeeDomain.length) === employeeDomain;
  }

  return {
    profileCheck: profileCheck,
    createProfile: createProfile
  };
};

module.exports = settingsFactory;
<commit_msg>comment settings factory<commit_after>'use strict';

var settingsFactory = function settingsFactory($rootScope, $state, $log, $firebaseObject, api){

  // domain used to determine employee vs standard user
  var employeeDomain = 'pwc.com';

  /**
   * Checks for the existance of user profile in the database
   * @param  {Object} authObject - firebase authentication object
   * @return {Promise} - resolves with profile FirebaseObject
   */
  var profileCheck = function profileCheck(authObject){
    var ref = api.getRef('users', authObject.uid);
    var profile = $firebaseObject(ref);

    return profile.$loaded(function(){
      if(profile.$value === null){
        return createProfile(profile, authObject);
      } else {
        return profile;
      }
    });

  };

  /**
   * Creates the sinder profile object based on mappings
   * from the user's authentication info
   * @param  {FirebaseObject} profile - firebase profile object
   * @param  {Object} authObject - firebase authentication object
   * @return {Promise} - resolves with profile FirebaseObject
   */
  var createProfile = function createProfile(profile, authObject){
    profile.displayName = authObject.displayName;
    profile.email = authObject.email;
    profile.photoURL = authObject.photoURL;
    profile.employee = employeeCheck(authObject.email);

    return profile.$save().then(function(){
      return profile;
    });
  };

  /**
   * Checks if email belongs to the org
   * @param  {String} email - email address from the auth provider
   * @return {Boolean}
   */
  function employeeCheck(email){
    return email.slice(-employeeDomain.length) === employeeDomain;
  }

  return {
    profileCheck: profileCheck,
    createProfile: createProfile
  };
};

module.exports = settingsFactory;
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of iotagent-manager
 *
 * iotagent-manager is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * iotagent-manager is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with iotagent-manager.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::daniel.moranjimenez@telefonica.com
 */

'use strict';

/*jshint camelcase:false */

var protocols = require('./protocolData'),
    request = require('request'),
    logger = require('logops'),
    errors = require('../errors'),
    _ = require('underscore'),
    async = require('async'),
    context = {
        op: 'IoTAManager.Redirector'
    };

function guessCollection(body) {
    if (body.services) {
        return 'services';
    } else if (body.devices) {
        return 'devices';
    } else {
        return null;
    }
}

function extractProtocols(body) {
    var collectionName = guessCollection(body),
        protocols;

    logger.debug(context, 'Extracting protocols from body for collection [%s]', collectionName);

    function extractProtocol(previous, item) {
        if (item.protocol) {
            if (Array.isArray(item.protocol)) {
                return _.union(previous, item.protocol);
            } else {
                previous.push(item.protocol);

                return _.uniq(previous);
            }
        } else {
            return previous;
        }
    }

    if (collectionName) {
        protocols = body[collectionName].reduce(extractProtocol, []);

        logger.debug(context, 'Protocols found: %j', protocols);

        return protocols;
    } else {
        return null;
    }
}

function queryParamExtractor(req, res, next) {
    if (req.query.protocol) {
        logger.debug(context, 'Protocol found in the query parameters [%s]', req.query.protocol);
        req.protocolId = [req.query.protocol];
    } else if (req.method !== 'GET') {
        req.splitAndRedirect = true;
        req.protocolId = extractProtocols(req.body);
    }

    next();
}

function getProtocols(req, res, next) {
    function addProtocolAsync(previous, item, callback) {
        protocols.get(item, function(error, protocol) {
            if (error) {
                callback(error);
            } else {
                previous[item] = protocol;
                callback(null, previous);
            }
        });
    }

    function addProtocolSync(previous, item) {
        previous[item.protocol] = item;
        return previous;
    }

    function extractId(protocol) {
        return protocol.protocol;
    }

    if (req.protocolId) {
        logger.debug(context, 'Finding objects for the following protocols: %j', req.protocolId);

        async.reduce(req.protocolId, {}, addProtocolAsync, function endReduction(error, result) {
            req.protocolObj = result;
            next(error);
        });
    } else {
        logger.debug(context, 'Finding objects for all the protocols');

        protocols.list(function(error, protocols) {
            if (error) {
                next(error);
            } else {
                req.protocolId = protocols.map(extractId);
                req.protocolObj = protocols.reduce(addProtocolSync, {});
                logger.debug(context, 'Finding objects for this protocol: %j', req.protocolId);
                next();
            }
        });
    }
}

function splitByProtocol(req) {
    var collectionName = guessCollection(req.body),
        collections = {},
        clonedObject;

    for (var i = 0; i < req.body[collectionName].length; i++) {
        if (Array.isArray(req.body[collectionName][i].protocol)) {
            for (var j = 0; j < req.body[collectionName][i].protocol.length; j++) {
                clonedObject = _.clone(req.body[collectionName][i]);

                clonedObject.protocol = req.body[collectionName][i].protocol[j];
                clonedObject.resource = req.protocolObj[clonedObject.protocol].resource;

                if (collections[req.body[collectionName][i].protocol[j]]) {
                    collections[req.body[collectionName][i].protocol[j]][collectionName].push(clonedObject);
                } else {
                    collections[req.body[collectionName][i].protocol[j]] = {};
                    collections[req.body[collectionName][i].protocol[j]][collectionName] = [clonedObject];
                }
            }
        } else {
            clonedObject = _.clone(req.body[collectionName][i]);

            clonedObject.protocol = req.body[collectionName][i].protocol;
            clonedObject.resource = req.protocolObj[clonedObject.protocol].resource;

            collections[req.body[collectionName][i].protocol] = {};
            collections[req.body[collectionName][i].protocol][collectionName] = [_.clone(req.body[collectionName][i])];
        }
    }

    return collections;
}

/**
 * Create the redirected request based on the protocol information and the original request. For backwards compatibility
 * the IoT Agent Manager removes the "/iot" prefix from the protocol address if found.
 *
 * @param {Object} req           Original request object to be forwarded.
 * @param {String} protocol      ID of the protocl where the request will be forwarded
 * @param {Object} body          JSON body of the original request.
 * @return {Object}             Request object prepared to be sent.
 */
function createRequest(req, protocol, body) {
    var options = {
            qs: _.clone(req.query),
            method: req.method,
            headers: req.headers
        },
        protocolObj = req.protocolObj[protocol],
        protocolAddress = protocolObj.iotagent;

    logger.debug(context, 'creating request using protocol:\n\n%j\n', protocolObj);
    delete options.qs.protocol;

    // Save original apikey before be overwrite by apikey from body (probably modified)
    if (req.query.apikey) {
        options.qs.apikeyReq = req.query.apikey;
    }
    if (protocolObj.resource) {
        options.qs.resource = protocolObj.resource;
    }
    if (protocolAddress.substr(-1) === '/') {
        protocolAddress = protocolAddress.slice(0, -1);
    }

    if (protocolAddress.substr(-4) === '/iot') {
        protocolAddress = protocolAddress.slice(0, -4);
    }

    options.uri = protocolAddress + req.path;

    if (body && body.services) {
        body.services = body.services.map(function cleanProtocol(item) {
            delete item.protocol;
            return item;
        });
        // Translate body.services

        if (req.method === 'PUT') {
            body = body.services[0];
        }
    }

    if (req.method === 'PUT' || req.method === 'POST') {
        options.body = JSON.stringify(body);
    }

    delete options.headers['content-length'];
    options.headers.connection = 'close';

    logger.debug(context, 'Forwarding request:\n\n%j\n', options);

    return options;
}

function createRequests(req, res, next) {
    function mapToBody(split, protocol) {
        return createRequest(req, protocol, split[protocol]);
    }

    if (req.splitAndRedirect) {
        var split = splitByProtocol(req);

        logger.debug(context, 'Creating request for multiple elements');

        req.requests = req.protocolId.map(mapToBody.bind(null, split));
    } else {
        logger.debug(context, 'Creating request for redirecting single requests');
        req.requests = [];
        for (var i = 0; i < req.protocolId.length; i++) {
            req.requests.push(createRequest(req, req.protocolId[i], req.body));
        }
    }

    next();
}

function processRequests(req, res, next) {

    function extractStatusCode(result) {
        if (result && result.length === 2 && result[0].statusCode) {
            return result[0].statusCode;
        } else {
            return 0;
        }
    }

    function sendRequest(options, callback) {
        logger.debug(context, 'Sending redirection with following options: %j', options);
        // Use original apikey, not apikey from body
        if (options.qs.apikeyReq) {
            options.qs.apikey = options.qs.apikeyReq;
        }
        request(options, function(error, response, body) {
            if (error) {
                logger.error(context, 'Error found redirecting requests: %j', error);

                callback(new errors.TargetServerError(error));
            } else if (response.statusCode !== 200 &&
                       response.statusCode !== 201 &&
                       response.statusCode !== 204 &&
                       response.statusCode !== 409) {
                logger.error(context, 'Wrong status code detected [%s] and body response [%s] redirecting request',
                             response.statusCode,
                             response.body);
                callback(new errors.TargetServerError(
                    'Wrong status code detected [' + response.statusCode + '] and body response [' + response.body +
                        '] redirecting request'));
            } else if (body && body.length > 0) {
                var parsedBody,
                    parseError;

                try {
                    parsedBody = JSON.parse(body);
                    logger.debug(context, 'Response body from the redirected request parsed: %j', parsedBody);
                } catch (e) {
                    logger.error(context, 'Error parsing response body from the redirected request: %s', e);
                    parseError = new errors.TargetResponseError(e);
                }

                callback(parseError, [response, parsedBody]);
            } else {
                callback(null, [response, null]);
            }
        });
    }

    function combineResults(results) {
        /* jshint camelcase: false */

        var totalCount = 0,
            finalResult = [],
            collectionName,
            resultObj = {};

        if (results[0] && results[0][1]) {
            if (results[0][1].services || results[0][1].apikey) {
                collectionName = 'services';
            } else if (results[0][1].devices || results[0][1].device_id) {
                collectionName = 'devices';
            } else {
                return null;
            }
        } else {
            return null;
        }

        for (var i = 0; i < results.length; i++) {
            if (results[i][1].count && results[i][1].count > 0) {
                totalCount += results[i][1].count;
            }

            if (results[i][1][collectionName]) {
                finalResult = finalResult.concat(results[i][1][collectionName]);
            } else {
                finalResult = finalResult.concat(results[i][1]);
            }
        }
        resultObj.count = totalCount;
        resultObj[collectionName] = finalResult;

        return resultObj;
    }

    function requestHandler(error, results) {
        var combinedResult;

        if (error) {
            logger.error(context, 'The redirection ended up in error: ', error);
            next(error);
        } else {
            logger.debug(context, 'results %j', results);
            var statusCodes = _.uniq(results.map(extractStatusCode));

            if (statusCodes.length === 1) {
                if (req.method === 'POST' || req.method === 'DELETE' || req.method === 'PUT') {
                    res.status(statusCodes[0]).send();
                } else if (results.length >= 1) {
                    combinedResult = combineResults(results);

                    if (combinedResult) {
                        res.status(statusCodes[0]).json(combinedResult);
                    } else {
                        next(new errors.TargetServerError('No valid replies from any IoTAgent'));
                    }
                } else {
                    res.status(statusCodes[0]).json({});
                }
            } else {
                var errorMsg = 'Wrong status code obtained in some of the responses [' +
                    JSON.stringify(statusCodes) + '] redirecting request';

                logger.error(context, errorMsg);

                next(new errors.TargetServerError(errorMsg));
            }
        }
    }

    async.map(req.requests, sendRequest, requestHandler);
}

function loadContextRoutes(router) {
    var middlewareList = [
        queryParamExtractor,
        getProtocols,
        createRequests,
        processRequests
    ];

    router.post('/iot/services', middlewareList);
    router.post('/iot/devices', middlewareList);
    router.put('/iot/services', middlewareList);
    router.delete('/iot/services', middlewareList);
    router.get('/iot/devices', middlewareList);
    router.get('/iot/devices/:id', middlewareList);
    router.put('/iot/devices/:id', middlewareList);
    router.delete('/iot/devices/:id', middlewareList);

}

exports.loadContextRoutes = loadContextRoutes;
<commit_msg>count simple devices in totalcount when combining results<commit_after>/*
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of iotagent-manager
 *
 * iotagent-manager is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * iotagent-manager is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public
 * License along with iotagent-manager.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::daniel.moranjimenez@telefonica.com
 */

'use strict';

/*jshint camelcase:false */

var protocols = require('./protocolData'),
    request = require('request'),
    logger = require('logops'),
    errors = require('../errors'),
    _ = require('underscore'),
    async = require('async'),
    context = {
        op: 'IoTAManager.Redirector'
    };

function guessCollection(body) {
    if (body.services) {
        return 'services';
    } else if (body.devices) {
        return 'devices';
    } else {
        return null;
    }
}

function extractProtocols(body) {
    var collectionName = guessCollection(body),
        protocols;

    logger.debug(context, 'Extracting protocols from body for collection [%s]', collectionName);

    function extractProtocol(previous, item) {
        if (item.protocol) {
            if (Array.isArray(item.protocol)) {
                return _.union(previous, item.protocol);
            } else {
                previous.push(item.protocol);

                return _.uniq(previous);
            }
        } else {
            return previous;
        }
    }

    if (collectionName) {
        protocols = body[collectionName].reduce(extractProtocol, []);

        logger.debug(context, 'Protocols found: %j', protocols);

        return protocols;
    } else {
        return null;
    }
}

function queryParamExtractor(req, res, next) {
    if (req.query.protocol) {
        logger.debug(context, 'Protocol found in the query parameters [%s]', req.query.protocol);
        req.protocolId = [req.query.protocol];
    } else if (req.method !== 'GET') {
        req.splitAndRedirect = true;
        req.protocolId = extractProtocols(req.body);
    }

    next();
}

function getProtocols(req, res, next) {
    function addProtocolAsync(previous, item, callback) {
        protocols.get(item, function(error, protocol) {
            if (error) {
                callback(error);
            } else {
                previous[item] = protocol;
                callback(null, previous);
            }
        });
    }

    function addProtocolSync(previous, item) {
        previous[item.protocol] = item;
        return previous;
    }

    function extractId(protocol) {
        return protocol.protocol;
    }

    if (req.protocolId) {
        logger.debug(context, 'Finding objects for the following protocols: %j', req.protocolId);

        async.reduce(req.protocolId, {}, addProtocolAsync, function endReduction(error, result) {
            req.protocolObj = result;
            next(error);
        });
    } else {
        logger.debug(context, 'Finding objects for all the protocols');

        protocols.list(function(error, protocols) {
            if (error) {
                next(error);
            } else {
                req.protocolId = protocols.map(extractId);
                req.protocolObj = protocols.reduce(addProtocolSync, {});
                logger.debug(context, 'Finding objects for this protocol: %j', req.protocolId);
                next();
            }
        });
    }
}

function splitByProtocol(req) {
    var collectionName = guessCollection(req.body),
        collections = {},
        clonedObject;

    for (var i = 0; i < req.body[collectionName].length; i++) {
        if (Array.isArray(req.body[collectionName][i].protocol)) {
            for (var j = 0; j < req.body[collectionName][i].protocol.length; j++) {
                clonedObject = _.clone(req.body[collectionName][i]);

                clonedObject.protocol = req.body[collectionName][i].protocol[j];
                clonedObject.resource = req.protocolObj[clonedObject.protocol].resource;

                if (collections[req.body[collectionName][i].protocol[j]]) {
                    collections[req.body[collectionName][i].protocol[j]][collectionName].push(clonedObject);
                } else {
                    collections[req.body[collectionName][i].protocol[j]] = {};
                    collections[req.body[collectionName][i].protocol[j]][collectionName] = [clonedObject];
                }
            }
        } else {
            clonedObject = _.clone(req.body[collectionName][i]);

            clonedObject.protocol = req.body[collectionName][i].protocol;
            clonedObject.resource = req.protocolObj[clonedObject.protocol].resource;

            collections[req.body[collectionName][i].protocol] = {};
            collections[req.body[collectionName][i].protocol][collectionName] = [_.clone(req.body[collectionName][i])];
        }
    }

    return collections;
}

/**
 * Create the redirected request based on the protocol information and the original request. For backwards compatibility
 * the IoT Agent Manager removes the "/iot" prefix from the protocol address if found.
 *
 * @param {Object} req           Original request object to be forwarded.
 * @param {String} protocol      ID of the protocl where the request will be forwarded
 * @param {Object} body          JSON body of the original request.
 * @return {Object}             Request object prepared to be sent.
 */
function createRequest(req, protocol, body) {
    var options = {
            qs: _.clone(req.query),
            method: req.method,
            headers: req.headers
        },
        protocolObj = req.protocolObj[protocol],
        protocolAddress = protocolObj.iotagent;

    logger.debug(context, 'creating request using protocol:\n\n%j\n', protocolObj);
    delete options.qs.protocol;

    // Save original apikey before be overwrite by apikey from body (probably modified)
    if (req.query.apikey) {
        options.qs.apikeyReq = req.query.apikey;
    }
    if (protocolObj.resource) {
        options.qs.resource = protocolObj.resource;
    }
    if (protocolAddress.substr(-1) === '/') {
        protocolAddress = protocolAddress.slice(0, -1);
    }

    if (protocolAddress.substr(-4) === '/iot') {
        protocolAddress = protocolAddress.slice(0, -4);
    }

    options.uri = protocolAddress + req.path;

    if (body && body.services) {
        body.services = body.services.map(function cleanProtocol(item) {
            delete item.protocol;
            return item;
        });
        // Translate body.services

        if (req.method === 'PUT') {
            body = body.services[0];
        }
    }

    if (req.method === 'PUT' || req.method === 'POST') {
        options.body = JSON.stringify(body);
    }

    delete options.headers['content-length'];
    options.headers.connection = 'close';

    logger.debug(context, 'Forwarding request:\n\n%j\n', options);

    return options;
}

function createRequests(req, res, next) {
    function mapToBody(split, protocol) {
        return createRequest(req, protocol, split[protocol]);
    }

    if (req.splitAndRedirect) {
        var split = splitByProtocol(req);

        logger.debug(context, 'Creating request for multiple elements');

        req.requests = req.protocolId.map(mapToBody.bind(null, split));
    } else {
        logger.debug(context, 'Creating request for redirecting single requests');
        req.requests = [];
        for (var i = 0; i < req.protocolId.length; i++) {
            req.requests.push(createRequest(req, req.protocolId[i], req.body));
        }
    }

    next();
}

function processRequests(req, res, next) {

    function extractStatusCode(result) {
        if (result && result.length === 2 && result[0].statusCode) {
            return result[0].statusCode;
        } else {
            return 0;
        }
    }

    function sendRequest(options, callback) {
        logger.debug(context, 'Sending redirection with following options: %j', options);
        // Use original apikey, not apikey from body
        if (options.qs.apikeyReq) {
            options.qs.apikey = options.qs.apikeyReq;
        }
        request(options, function(error, response, body) {
            if (error) {
                logger.error(context, 'Error found redirecting requests: %j', error);

                callback(new errors.TargetServerError(error));
            } else if (response.statusCode !== 200 &&
                       response.statusCode !== 201 &&
                       response.statusCode !== 204 &&
                       response.statusCode !== 409) {
                logger.error(context, 'Wrong status code detected [%s] and body response [%s] redirecting request',
                             response.statusCode,
                             response.body);
                callback(new errors.TargetServerError(
                    'Wrong status code detected [' + response.statusCode + '] and body response [' + response.body +
                        '] redirecting request'));
            } else if (body && body.length > 0) {
                var parsedBody,
                    parseError;

                try {
                    parsedBody = JSON.parse(body);
                    logger.debug(context, 'Response body from the redirected request parsed: %j', parsedBody);
                } catch (e) {
                    logger.error(context, 'Error parsing response body from the redirected request: %s', e);
                    parseError = new errors.TargetResponseError(e);
                }

                callback(parseError, [response, parsedBody]);
            } else {
                callback(null, [response, null]);
            }
        });
    }

    function combineResults(results) {
        /* jshint camelcase: false */

        var totalCount = 0,
            finalResult = [],
            collectionName,
            resultObj = {};

        if (results[0] && results[0][1]) {
            if (results[0][1].services || results[0][1].apikey) {
                collectionName = 'services';
            } else if (results[0][1].devices || results[0][1].device_id) {
                collectionName = 'devices';
            } else {
                return null;
            }
        } else {
            return null;
        }

        for (var i = 0; i < results.length; i++) {
            logger.error(context, 'results[%s][1] %j ', i, results[i][1]);
            if (results[i][1].count && results[i][1].count > 0) {
                totalCount += results[i][1].count;
            } else if (results[i][1].devices && results[i][1].devices.length > 0) {
                totalCount += results[i][1].devices.length;
            } else {  // simple device
                totalCount++;
            }

            if (results[i][1][collectionName]) {
                finalResult = finalResult.concat(results[i][1][collectionName]);
            } else {
                finalResult = finalResult.concat(results[i][1]);
            }
        }
        resultObj.count = totalCount;
        resultObj[collectionName] = finalResult;

        return resultObj;
    }

    function requestHandler(error, results) {
        var combinedResult;

        if (error) {
            logger.error(context, 'The redirection ended up in error: ', error);
            next(error);
        } else {
            logger.debug(context, 'results %j', results);
            var statusCodes = _.uniq(results.map(extractStatusCode));

            if (statusCodes.length === 1) {
                if (req.method === 'POST' || req.method === 'DELETE' || req.method === 'PUT') {
                    res.status(statusCodes[0]).send();
                } else if (results.length >= 1) {
                    combinedResult = combineResults(results);

                    if (combinedResult) {
                        res.status(statusCodes[0]).json(combinedResult);
                    } else {
                        next(new errors.TargetServerError('No valid replies from any IoTAgent'));
                    }
                } else {
                    res.status(statusCodes[0]).json({});
                }
            } else {
                var errorMsg = 'Wrong status code obtained in some of the responses [' +
                    JSON.stringify(statusCodes) + '] redirecting request';

                logger.error(context, errorMsg);

                next(new errors.TargetServerError(errorMsg));
            }
        }
    }

    async.map(req.requests, sendRequest, requestHandler);
}

function loadContextRoutes(router) {
    var middlewareList = [
        queryParamExtractor,
        getProtocols,
        createRequests,
        processRequests
    ];

    router.post('/iot/services', middlewareList);
    router.post('/iot/devices', middlewareList);
    router.put('/iot/services', middlewareList);
    router.delete('/iot/services', middlewareList);
    router.get('/iot/devices', middlewareList);
    router.get('/iot/devices/:id', middlewareList);
    router.put('/iot/devices/:id', middlewareList);
    router.delete('/iot/devices/:id', middlewareList);

}

exports.loadContextRoutes = loadContextRoutes;
<|endoftext|>


<commit_before>#!/usr/bin/env node
var path = require("path"),
    fs = require("fs"),
    api = require("./api"),
    bundle = require("./bundle"),
    config = require("./config"),
    logger = require("../../server/logger.js"),
    jshint = require("./jshint_runner"),
    _ =require("underscore");

    require("./fs_extension");

// Copies all Resource files and prepares JS files
function prepare(src, dst, callback) {
  var app_name = config.app_name;
  if (src.match("js$")){
    var src_text = "var __ui = require('/api/UI'), __p = require('/api/PlatformRequire'), __log = require('/api/Log'), "
      + "assert = require('/api/Assert'), L = require('/api/Localisation').fetchString, "
      + "addSpy = require('api/Beach').addSpy;\n"
      + fs.readFileSync(src).toString()
      .replace(/Ti(tanium)?.Filesystem.(resourcesDirectory|getResourcesDirectory\(\))/g, "Ti.Filesystem.applicationDataDirectory + '"+app_name.replace(/ /g,"_")+"/'")
      .replace(/(^|[^\.])require\(/g, "$1__p.require(")
      .replace(/Ti(tanium)?.include\(/g, "__p.include(this,")
      .replace(/Ti(tanium)?.UI.createWindow\(/g, "__ui.createWindow(")
      .replace(/Ti(tanium)?.UI.createTabGroup\(/g, "__ui.createTabGroup(")
      .replace(/Ti.Locale.getString/g, "L")
      .replace(/([ :=\(])(['"])(\/[^'"].*?)(['"])/g, "$1__p.file($2$3$4)") // ignores "/"
      // Replace strings like ".titleid = 'save'" -> "title = L('save')"
      .replace(/\.(title|text)id\s{0,}\=\s{0,}['"](\w+)['"]/g, '.$1 = L(\'$2\')')
      // Replace strings like "titleid: 'save'" -> "title: L('save')"
      .replace(/\b(title|text)id:\s{0,}['"](\w+)['"]/g, '$1: L(\'$2\')')
      .replace(/console./g, "__log.")
      .replace(/\/\/addSpy\(/g,"addSpy(")
      .replace(/Ti(tanium)?.API/g, "__log");
    if (src.match("_spec.js$")) {
      src_text =  "var __jasmine = require('/lib/jasmine');var methods = ['spyOn','it','xit','expect','runs','waits','waitsFor','beforeEach','afterEach','describe','xdescribe','jasmine'];methods.forEach(function(method) {this[method] = __jasmine[method];});"
        +src_text;
    }
    fs.writeFile(dst,src_text, callback);
  } else { // Non-JS file - just pump it
    var  is = fs.createReadStream(src);
    var  os = fs.createWriteStream(dst);
    is.on("end", callback).pipe(os);
  }
}

function prepareFiles(index, file_list, isSpec, callback) {
  if (file_list.files.length === index) {
    callback();
  } else {
    var file = file_list.files[index];
    prepare(path.join(isSpec? config.base : config.resources_path,file), path.join(config.tishadow_src, file), function(){
      index++;
      prepareFiles(index, file_list, isSpec, callback);
    });
  }
}

function finalise(file_list,callback) {
  // Bundle up to go
  var total = file_list.files.length;
  // Send the directories and files (see bundle.zip)
  bundle.pack(file_list.dirs.concat(file_list.files),function(written) {
    logger.info(total+ " file(s) bundled.");
    fs.touch(config.last_updated_file);
    if (config.isBundle) {
      logger.info("Bundle Ready: " + config.bundle_file);
      if (callback) {
        callback();
      }
    } else {
      api.newBundle(config.isPatch?_.filter(file_list.files, function(f) { return f.match(".js$");}):null );
    }
  });
}

module.exports = function(env, callback) {
  if (!fs.existsSync(path.join(config.base,'tiapp.xml'))) {
    logger.error("Script must be executed in the Titanium project's root directory");
    process.exit();
  }

  config.buildPaths(env, function() {
    if (env.jshint) {
      logger.info("Running JSHint");
      jshint.checkPath(config.jshint_path);
    }

    logger.info("Beginning Build Process");
    var file_list,i18n_list,spec_list;
    if( config.isUpdate) {
       var last_stat = fs.statSync(config.last_updated_file);
       file_list = fs.getList(config.resources_path,last_stat.mtime);
       i18n_list = fs.getList(config.i18n_path,last_stat.mtime);
       spec_list = fs.getList(config.spec_path,last_stat.mtime);

       if (file_list.files.length === 0 && i18n_list.files.length === 0 && spec_list.files.length === 0) {
         logger.error("Nothing to update.");
         process.exit();
       }
     } else {
       if (!fs.existsSync(config.build_path)){
         fs.mkdirSync(config.build_path, 0755);
       }
       //Clean Build Directory
       if (fs.existsSync(config.tishadow_build)) {
         fs.rm_rf(config.tishadow_build);
       }
       // Create the tishadow build paths
       fs.mkdirs([config.tishadow_build, config.tishadow_src, config.tishadow_dist]);
       file_list = fs.getList(config.resources_path);
       i18n_list = fs.getList(config.i18n_path);
       spec_list = fs.getList(config.spec_path);
     }

     // Build the required directory structure
     fs.mkdirs(file_list.dirs, config.tishadow_src);
     fs.mkdirs(i18n_list.dirs, config.tishadow_src);
     if(spec_list.files.length > 0) {
       fs.mkdirSync(config.tishadow_spec, 0755);
       fs.mkdirs(spec_list.dirs, config.tishadow_spec);
       spec_list.files = spec_list.files.map(function(file) { return "spec/" + file;});
       spec_list.dirs = ["spec"].concat(spec_list.dirs.map(function(dir) {return "spec/" + dir;}));
     }

     // Just pump out localisation files
     i18n_list.files.forEach(function(file, idx) {
       fs.createReadStream(path.join(config.i18n_path,file)).pipe(fs.createWriteStream(path.join(config.tishadow_src, file)));
     });

     // Process Files
     prepareFiles(0, file_list, false, function() {
       prepareFiles(0, spec_list, true, function() {
          file_list.files = file_list.files.concat(i18n_list.files).concat(spec_list.files);
          file_list.dirs = file_list.dirs.concat(i18n_list.dirs).concat(spec_list.dirs);
          finalise(file_list,callback);
       });
     });
  });
}

<commit_msg>closes #86<commit_after>#!/usr/bin/env node
var path = require("path"),
    fs = require("fs"),
    api = require("./api"),
    bundle = require("./bundle"),
    config = require("./config"),
    logger = require("../../server/logger.js"),
    jshint = require("./jshint_runner"),
    _ =require("underscore");

    require("./fs_extension");

// Copies all Resource files and prepares JS files
function prepare(src, dst, callback) {
  var app_name = config.app_name;
  if (src.match("js$")){
    var src_text = "var __ui = require('/api/UI'), __p = require('/api/PlatformRequire'), __log = require('/api/Log'), "
      + "assert = require('/api/Assert'), L = require('/api/Localisation').fetchString, "
      + "addSpy = require('api/Beach').addSpy;\n"
      + fs.readFileSync(src).toString()
      .replace(/Ti(tanium)?.Filesystem.(resourcesDirectory|getResourcesDirectory\(\))/g, "Ti.Filesystem.applicationDataDirectory + '"+app_name.replace(/ /g,"_")+"/'")
      .replace(/(^|[^\.])require\(/g, "$1__p.require(")
      .replace(/Ti(tanium)?.include\(/g, "__p.include(this,")
      .replace(/Ti(tanium)?.UI.createWindow\(/g, "__ui.createWindow(")
      .replace(/Ti(tanium)?.UI.createTabGroup\(/g, "__ui.createTabGroup(")
      .replace(/Ti.Locale.getString/g, "L")
      .replace(/([ :=\(])(['"])(\/[^'"].*?)(['"])/g, "$1__p.file($2$3$4)") // ignores "/"
      // Replace strings like ".titleid = 'save'" -> "title = L('save')"
      .replace(/\.(title|text)id\s{0,}\=\s{0,}['"](\w+)['"]/g, '.$1 = L(\'$2\')')
      // Replace strings like "titleid: 'save'" -> "title: L('save')"
      .replace(/\b(title|text)id:\s{0,}['"](\w+)['"]/g, '$1: L(\'$2\')')
      .replace(/console\./g, "__log.")
      .replace(/\/\/addSpy\(/g,"addSpy(")
      .replace(/Ti(tanium)?.API/g, "__log");
    if (src.match("_spec.js$")) {
      src_text =  "var __jasmine = require('/lib/jasmine');var methods = ['spyOn','it','xit','expect','runs','waits','waitsFor','beforeEach','afterEach','describe','xdescribe','jasmine'];methods.forEach(function(method) {this[method] = __jasmine[method];});"
        +src_text;
    }
    fs.writeFile(dst,src_text, callback);
  } else { // Non-JS file - just pump it
    var  is = fs.createReadStream(src);
    var  os = fs.createWriteStream(dst);
    is.on("end", callback).pipe(os);
  }
}

function prepareFiles(index, file_list, isSpec, callback) {
  if (file_list.files.length === index) {
    callback();
  } else {
    var file = file_list.files[index];
    prepare(path.join(isSpec? config.base : config.resources_path,file), path.join(config.tishadow_src, file), function(){
      index++;
      prepareFiles(index, file_list, isSpec, callback);
    });
  }
}

function finalise(file_list,callback) {
  // Bundle up to go
  var total = file_list.files.length;
  // Send the directories and files (see bundle.zip)
  bundle.pack(file_list.dirs.concat(file_list.files),function(written) {
    logger.info(total+ " file(s) bundled.");
    fs.touch(config.last_updated_file);
    if (config.isBundle) {
      logger.info("Bundle Ready: " + config.bundle_file);
      if (callback) {
        callback();
      }
    } else {
      api.newBundle(config.isPatch?_.filter(file_list.files, function(f) { return f.match(".js$");}):null );
    }
  });
}

module.exports = function(env, callback) {
  if (!fs.existsSync(path.join(config.base,'tiapp.xml'))) {
    logger.error("Script must be executed in the Titanium project's root directory");
    process.exit();
  }

  config.buildPaths(env, function() {
    if (env.jshint) {
      logger.info("Running JSHint");
      jshint.checkPath(config.jshint_path);
    }

    logger.info("Beginning Build Process");
    var file_list,i18n_list,spec_list;
    if( config.isUpdate) {
       var last_stat = fs.statSync(config.last_updated_file);
       file_list = fs.getList(config.resources_path,last_stat.mtime);
       i18n_list = fs.getList(config.i18n_path,last_stat.mtime);
       spec_list = fs.getList(config.spec_path,last_stat.mtime);

       if (file_list.files.length === 0 && i18n_list.files.length === 0 && spec_list.files.length === 0) {
         logger.error("Nothing to update.");
         process.exit();
       }
     } else {
       if (!fs.existsSync(config.build_path)){
         fs.mkdirSync(config.build_path, 0755);
       }
       //Clean Build Directory
       if (fs.existsSync(config.tishadow_build)) {
         fs.rm_rf(config.tishadow_build);
       }
       // Create the tishadow build paths
       fs.mkdirs([config.tishadow_build, config.tishadow_src, config.tishadow_dist]);
       file_list = fs.getList(config.resources_path);
       i18n_list = fs.getList(config.i18n_path);
       spec_list = fs.getList(config.spec_path);
     }

     // Build the required directory structure
     fs.mkdirs(file_list.dirs, config.tishadow_src);
     fs.mkdirs(i18n_list.dirs, config.tishadow_src);
     if(spec_list.files.length > 0) {
       fs.mkdirSync(config.tishadow_spec, 0755);
       fs.mkdirs(spec_list.dirs, config.tishadow_spec);
       spec_list.files = spec_list.files.map(function(file) { return "spec/" + file;});
       spec_list.dirs = ["spec"].concat(spec_list.dirs.map(function(dir) {return "spec/" + dir;}));
     }

     // Just pump out localisation files
     i18n_list.files.forEach(function(file, idx) {
       fs.createReadStream(path.join(config.i18n_path,file)).pipe(fs.createWriteStream(path.join(config.tishadow_src, file)));
     });

     // Process Files
     prepareFiles(0, file_list, false, function() {
       prepareFiles(0, spec_list, true, function() {
          file_list.files = file_list.files.concat(i18n_list.files).concat(spec_list.files);
          file_list.dirs = file_list.dirs.concat(i18n_list.dirs).concat(spec_list.dirs);
          finalise(file_list,callback);
       });
     });
  });
}

<|endoftext|>


<commit_before>L.Label = L.Popup.extend({
	options: {
		autoPan: false,
		className: '',
		closePopupOnClick: false,
		offset: new L.Point(20, -35)
	},

	onAdd: function (map) {
		this._map = map;

		if (!this._container) {
			this._initLayout();
		}
		this._updateContent();

		var animFade = map.options.fadeAnimation;

		if (animFade) {
			L.DomUtil.setOpacity(this._container, 0);
		}
		map._panes.popupPane.appendChild(this._container);

		map.on('viewreset', this._updatePosition, this);

		if (L.Browser.any3d) {
			map.on('zoomanim', this._zoomAnimation, this);
		}

		this._update();

		if (animFade) {
			L.DomUtil.setOpacity(this._container, 1);
		}
	},

	close: function () {
		var map = this._map;

		if (map) {
			map._label = null;

			map.removeLayer(this);
		}
	},

	_initLayout: function () {
		this._container = L.DomUtil.create('div', 'leaflet-label ' + this.options.className + ' leaflet-zoom-animated');
	},

	_updateContent: function () {
		if (!this._content) { return; }

		if (typeof this._content === 'string') {
			this._container.innerHTML = this._content;
		}
	},

	_updateLayout: function () {
		// Do nothing
	},

	_updatePosition: function () {
		var pos = this._map.latLngToLayerPoint(this._latlng);

		this._setPosition(pos);
	},

	_setPosition: function (pos) {
		pos = pos.add(this.options.offset);

		L.DomUtil.setPosition(this._container, pos);
	},

	_zoomAnimation: function (opt) {
		var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center);

		this._setPosition(pos);
	}
});<commit_msg>Reverted label offset as it messes up the path label. Will approach differently.<commit_after>L.Label = L.Popup.extend({
	options: {
		autoPan: false,
		className: '',
		closePopupOnClick: false,
		offset: new L.Point(20, -15)
	},

	onAdd: function (map) {
		this._map = map;

		if (!this._container) {
			this._initLayout();
		}
		this._updateContent();

		var animFade = map.options.fadeAnimation;

		if (animFade) {
			L.DomUtil.setOpacity(this._container, 0);
		}
		map._panes.popupPane.appendChild(this._container);

		map.on('viewreset', this._updatePosition, this);

		if (L.Browser.any3d) {
			map.on('zoomanim', this._zoomAnimation, this);
		}

		this._update();

		if (animFade) {
			L.DomUtil.setOpacity(this._container, 1);
		}
	},

	close: function () {
		var map = this._map;

		if (map) {
			map._label = null;

			map.removeLayer(this);
		}
	},

	_initLayout: function () {
		this._container = L.DomUtil.create('div', 'leaflet-label ' + this.options.className + ' leaflet-zoom-animated');
	},

	_updateContent: function () {
		if (!this._content) { return; }

		if (typeof this._content === 'string') {
			this._container.innerHTML = this._content;
		}
	},

	_updateLayout: function () {
		// Do nothing
	},

	_updatePosition: function () {
		var pos = this._map.latLngToLayerPoint(this._latlng);

		this._setPosition(pos);
	},

	_setPosition: function (pos) {
		pos = pos.add(this.options.offset);

		L.DomUtil.setPosition(this._container, pos);
	},

	_zoomAnimation: function (opt) {
		var pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center);

		this._setPosition(pos);
	}
});<|endoftext|>


<commit_before>function decode (buffer, maxLength, minimal) {
  maxLength = maxLength || 4
  minimal = minimal === undefined ? true : minimal

  var length = buffer.length
  if (length === 0) return 0
  if (length > maxLength) throw new TypeError('Script number overflow')
  if (minimal) {
    if ((buffer[length - 1] & 0x7f) === 0) {
      if (length <= 1 || (buffer[length - 2] & 0x80) === 0) throw new Error('Non-minimally encoded script number')
    }
  }

  // 32-bit?
  if (length < 5) {
    var result = 0

    for (var i = 0; i < length; ++i) {
      result += buffer[i] << (8 * i)
    }

    if (buffer[length - 1] & 0x80) return -(result & ~(0x80 << (8 * (length - 1))))
    return result
  }

  // 40-bit
  var a = buffer.readUInt32LE(0)
  var b = buffer.readUInt8(4)

  // TODO: refactor
  var neg = false
  if (b & 0x80) {
    b &= ~0x80
    neg = true
  }

  var r = b * 0x100000000 + a

  if (neg) {
    r = -r
  }

  return r
}

function scriptNumSize (i) {
  return i > 0x7fffffff ? 5
  : i > 0x7fffff ? 4
  : i > 0x7fff ? 3
  : i > 0x7f ? 2
  : i > 0x00 ? 1
  : 0
}

function encode (number) {
  var value = Math.abs(number)
  var size = scriptNumSize(value)
  var buffer = new Buffer(size)
  var negative = number < 0

  for (var i = 0; i < size; ++i) {
    buffer.writeUInt8(value & 0xff, i)
    value >>= 8
  }

  if (buffer[size - 1] & 0x80) {
    buffer.writeUInt8(negative ? 0x80 : 0x00, size - 1)
  } else if (negative) {
    buffer[size - 1] |= 0x80
  }

  return buffer
}

module.exports = {
  decode: decode,
  encode: encode
}
<commit_msg>script_number: refactor<commit_after>function decode (buffer, maxLength, minimal) {
  maxLength = maxLength || 4
  minimal = minimal === undefined ? true : minimal

  var length = buffer.length
  if (length === 0) return 0
  if (length > maxLength) throw new TypeError('Script number overflow')
  if (minimal) {
    if ((buffer[length - 1] & 0x7f) === 0) {
      if (length <= 1 || (buffer[length - 2] & 0x80) === 0) throw new Error('Non-minimally encoded script number')
    }
  }

  var result

  // 40-bit
  if (length === 5) {
    var a = buffer.readUInt32LE(0)
    var b = buffer.readUInt8(4)

    if (b & 0x80) return -((b & ~0x80) * 0x100000000 + a)
    return b * 0x100000000 + a

  // 32-bit
  } else if (length === 4) {
    result = buffer.readUInt32LE(0)

  // 24-bit
  } else if (length === 3) {
    result = buffer.readUInt16LE(0)
    result |= buffer.readUInt8(2) << 16

  // 16-bit
  } else if (length === 2) {
    result = buffer.readUInt16LE(0)

  // 8-bit
  } else {
    result = buffer.readUInt8(0)
  }

  if (buffer[length - 1] & 0x80) return -(result & ~(0x80 << (8 * (length - 1))))
  return result
}

function scriptNumSize (i) {
  return i > 0x7fffffff ? 5
  : i > 0x7fffff ? 4
  : i > 0x7fff ? 3
  : i > 0x7f ? 2
  : i > 0x00 ? 1
  : 0
}

function encode (number) {
  var value = Math.abs(number)
  var size = scriptNumSize(value)
  var buffer = new Buffer(size)
  var negative = number < 0

  for (var i = 0; i < size; ++i) {
    buffer.writeUInt8(value & 0xff, i)
    value >>= 8
  }

  if (buffer[size - 1] & 0x80) {
    buffer.writeUInt8(negative ? 0x80 : 0x00, size - 1)
  } else if (negative) {
    buffer[size - 1] |= 0x80
  }

  return buffer
}

module.exports = {
  decode: decode,
  encode: encode
}
<|endoftext|>