<commit_before>/*
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of fiware-iotagent-lib
 *
 * fiware-iotagent-lib 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.
 *
 * fiware-iotagent-lib 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 fiware-iotagent-lib.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::[contacto@tid.es]
 */
'use strict';

var iotAgentLib = require('../../'),
    utils = require('../tools/utils'),
    should = require('should'),
    request = require('request'),
    nock = require('nock'),
    contextBrokerMock,
    iotAgentConfig = {
        logLevel: 'FATAL',
        contextBroker: {
            host: '192.168.1.1',
            port: '1026'
        },
        server: {
            port: 4041
        },
        types: {},
        service: 'smartGondor',
        subservice: 'gardens',
        providerUrl: 'http://smartGondor.com',
        deviceRegistrationDuration: 'P1M',
        throttling: 'PT5S'
    };

describe('Subscription tests', function() {
    beforeEach(function(done) {
        var optionsProvision = {
            url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices',
            method: 'POST',
            json: utils.readExampleFile('./test/unit/deviceProvisioningRequests/provisionMinimumDevice.json'),
            headers: {
                'fiware-service': 'smartGondor',
                'fiware-servicepath': '/gardens'
            }
        };

        nock.cleanAll();

        iotAgentLib.activate(iotAgentConfig, function() {
            contextBrokerMock = nock('http://192.168.1.1:1026')
                .matchHeader('fiware-service', 'smartGondor')
                .matchHeader('fiware-servicepath', '/gardens')
                .post('/v1/updateContext',
                    utils.readExampleFile('./test/unit/contextRequests/createMinimumProvisionedDevice.json'))
                .reply(200,
                    utils.readExampleFile('./test/unit/contextResponses/createProvisionedDeviceSuccess.json'));

            contextBrokerMock = nock('http://192.168.1.1:1026')
                .matchHeader('fiware-service', 'smartGondor')
                .matchHeader('fiware-servicepath', '/gardens')
                .post('/v1/subscribeContext',
                    utils.readExampleFile('./test/unit/subscriptionRequests/simpleSubscriptionRequest.json'))
                .reply(200,
                    utils.readExampleFile('./test/unit/subscriptionResponses/simpleSubscriptionSuccess.json'));

            iotAgentLib.clearAll(function() {
                request(optionsProvision, function(error) {
                    done();
                });
            });
        });
    });

    afterEach(function(done) {
        nock.cleanAll();
        iotAgentLib.setNotificationHandler();
        iotAgentLib.clearAll(function() {
            iotAgentLib.deactivate(done);
        });
    });

    describe('When a client invokes the subscribe() function for device', function() {
        it('should send the appropriate request to the Context Broker', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    should.not.exist(error);

                    contextBrokerMock.done();

                    done();
                });
            });
        });
        it('should store the subscription ID in the Device Registry', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    iotAgentLib.getDevice('MicroLight1', function(error, device) {
                        should.not.exist(error);
                        should.exist(device);
                        should.exist(device.subscriptions);
                        device.subscriptions.length.should.equal(1);
                        device.subscriptions[0].id.should.equal('51c0ac9ed714fb3b37d7d5a8');
                        device.subscriptions[0].triggers[0].should.equal('attr_name');
                        done();
                    });
                });
            });
        });
    });
    describe('When a client invokes the unsubscribe() function for an entity', function() {
        beforeEach(function(done) {
            contextBrokerMock = nock('http://192.168.1.1:1026')
                .matchHeader('fiware-service', 'smartGondor')
                .matchHeader('fiware-servicepath', '/gardens')
                .post('/v1/updateContextSubscription',
                    utils.readExampleFile('./test/unit/subscriptionRequests/simpleSubscriptionUpdate.json'))
                .reply(200,
                    utils.readExampleFile('./test/unit/subscriptionResponses/simpleSubscriptionSuccess.json'));

            done();
        });
        it('should change the expiration date of the subscription to 0s', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    iotAgentLib.unsubscribe(device, '51c0ac9ed714fb3b37d7d5a8', function(error) {
                        iotAgentLib.getDevice('MicroLight1', function(error, device) {
                            contextBrokerMock.done();
                            done();
                        });
                    });
                });
            });
        });
        it('should remove the id from the subscriptions array', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    iotAgentLib.unsubscribe(device, '51c0ac9ed714fb3b37d7d5a8', function(error) {
                        iotAgentLib.getDevice('MicroLight1', function(error, device) {
                            should.not.exist(error);
                            should.exist(device);
                            should.exist(device.subscriptions);
                            device.subscriptions.length.should.equal(0);
                            done();
                        });
                    });
                });
            });
        });
    });
    describe('When a client removes a device from the registry', function() {
        beforeEach(function(done) {
            contextBrokerMock = nock('http://192.168.1.1:1026')
                .matchHeader('fiware-service', 'smartGondor')
                .matchHeader('fiware-servicepath', '/gardens')
                .post('/v1/updateContextSubscription',
                    utils.readExampleFile('./test/unit/subscriptionRequests/simpleSubscriptionUpdate.json'))
                .reply(200,
                    utils.readExampleFile('./test/unit/subscriptionResponses/simpleSubscriptionSuccess.json'));

            done();
        });

        it('should change the expiration dates of all its subscriptions to 0s', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    iotAgentLib.unregister(device.id, function(error) {
                        contextBrokerMock.done();
                        done();
                    });
                });
            });
        });
    });
    describe('When a new notification comes to the IoTAgent', function() {
        beforeEach(function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    done();
                });
            });
        });

        it('should invoke the user defined callback', function(done) {
            var notificationOptions = {
                    url: 'http://localhost:' + iotAgentConfig.server.port + '/notify',
                    method: 'POST',
                    json: utils.readExampleFile('./test/unit/subscriptionRequests/simpleNotification.json'),
                    headers: {
                        'fiware-service': 'smartGondor',
                        'fiware-servicepath': '/gardens'
                    }
                },

                executedHandler = false;

            function mockedHandler(device, notification, callback) {
                executedHandler = true;
                callback();
            }

            iotAgentLib.setNotificationHandler(mockedHandler);

            request(notificationOptions, function(error, response, body) {
                should.not.exist(error);
                executedHandler.should.equal(true);

                done();
            });
        });
        it('should get the correspondent device information');
    });
    describe('When a new notification arrives to the IOTA with a non-200 code', function() {
        it('should not call the handler');
    });
});
<commit_msg>ADD Test for handler parameter contents<commit_after>/*
 * Copyright 2016 Telefonica Investigación y Desarrollo, S.A.U
 *
 * This file is part of fiware-iotagent-lib
 *
 * fiware-iotagent-lib 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.
 *
 * fiware-iotagent-lib 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 fiware-iotagent-lib.
 * If not, seehttp://www.gnu.org/licenses/.
 *
 * For those usages not covered by the GNU Affero General Public License
 * please contact with::[contacto@tid.es]
 */
'use strict';

var iotAgentLib = require('../../'),
    utils = require('../tools/utils'),
    should = require('should'),
    request = require('request'),
    nock = require('nock'),
    contextBrokerMock,
    iotAgentConfig = {
        logLevel: 'FATAL',
        contextBroker: {
            host: '192.168.1.1',
            port: '1026'
        },
        server: {
            port: 4041
        },
        types: {},
        service: 'smartGondor',
        subservice: 'gardens',
        providerUrl: 'http://smartGondor.com',
        deviceRegistrationDuration: 'P1M',
        throttling: 'PT5S'
    };

describe('Subscription tests', function() {
    beforeEach(function(done) {
        var optionsProvision = {
            url: 'http://localhost:' + iotAgentConfig.server.port + '/iot/devices',
            method: 'POST',
            json: utils.readExampleFile('./test/unit/deviceProvisioningRequests/provisionMinimumDevice.json'),
            headers: {
                'fiware-service': 'smartGondor',
                'fiware-servicepath': '/gardens'
            }
        };

        nock.cleanAll();

        iotAgentLib.activate(iotAgentConfig, function() {
            contextBrokerMock = nock('http://192.168.1.1:1026')
                .matchHeader('fiware-service', 'smartGondor')
                .matchHeader('fiware-servicepath', '/gardens')
                .post('/v1/updateContext',
                    utils.readExampleFile('./test/unit/contextRequests/createMinimumProvisionedDevice.json'))
                .reply(200,
                    utils.readExampleFile('./test/unit/contextResponses/createProvisionedDeviceSuccess.json'));

            contextBrokerMock = nock('http://192.168.1.1:1026')
                .matchHeader('fiware-service', 'smartGondor')
                .matchHeader('fiware-servicepath', '/gardens')
                .post('/v1/subscribeContext',
                    utils.readExampleFile('./test/unit/subscriptionRequests/simpleSubscriptionRequest.json'))
                .reply(200,
                    utils.readExampleFile('./test/unit/subscriptionResponses/simpleSubscriptionSuccess.json'));

            iotAgentLib.clearAll(function() {
                request(optionsProvision, function(error) {
                    done();
                });
            });
        });
    });

    afterEach(function(done) {
        nock.cleanAll();
        iotAgentLib.setNotificationHandler();
        iotAgentLib.clearAll(function() {
            iotAgentLib.deactivate(done);
        });
    });

    describe('When a client invokes the subscribe() function for device', function() {
        it('should send the appropriate request to the Context Broker', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    should.not.exist(error);

                    contextBrokerMock.done();

                    done();
                });
            });
        });
        it('should store the subscription ID in the Device Registry', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    iotAgentLib.getDevice('MicroLight1', function(error, device) {
                        should.not.exist(error);
                        should.exist(device);
                        should.exist(device.subscriptions);
                        device.subscriptions.length.should.equal(1);
                        device.subscriptions[0].id.should.equal('51c0ac9ed714fb3b37d7d5a8');
                        device.subscriptions[0].triggers[0].should.equal('attr_name');
                        done();
                    });
                });
            });
        });
    });
    describe('When a client invokes the unsubscribe() function for an entity', function() {
        beforeEach(function(done) {
            contextBrokerMock = nock('http://192.168.1.1:1026')
                .matchHeader('fiware-service', 'smartGondor')
                .matchHeader('fiware-servicepath', '/gardens')
                .post('/v1/updateContextSubscription',
                    utils.readExampleFile('./test/unit/subscriptionRequests/simpleSubscriptionUpdate.json'))
                .reply(200,
                    utils.readExampleFile('./test/unit/subscriptionResponses/simpleSubscriptionSuccess.json'));

            done();
        });
        it('should change the expiration date of the subscription to 0s', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    iotAgentLib.unsubscribe(device, '51c0ac9ed714fb3b37d7d5a8', function(error) {
                        iotAgentLib.getDevice('MicroLight1', function(error, device) {
                            contextBrokerMock.done();
                            done();
                        });
                    });
                });
            });
        });
        it('should remove the id from the subscriptions array', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    iotAgentLib.unsubscribe(device, '51c0ac9ed714fb3b37d7d5a8', function(error) {
                        iotAgentLib.getDevice('MicroLight1', function(error, device) {
                            should.not.exist(error);
                            should.exist(device);
                            should.exist(device.subscriptions);
                            device.subscriptions.length.should.equal(0);
                            done();
                        });
                    });
                });
            });
        });
    });
    describe('When a client removes a device from the registry', function() {
        beforeEach(function(done) {
            contextBrokerMock = nock('http://192.168.1.1:1026')
                .matchHeader('fiware-service', 'smartGondor')
                .matchHeader('fiware-servicepath', '/gardens')
                .post('/v1/updateContextSubscription',
                    utils.readExampleFile('./test/unit/subscriptionRequests/simpleSubscriptionUpdate.json'))
                .reply(200,
                    utils.readExampleFile('./test/unit/subscriptionResponses/simpleSubscriptionSuccess.json'));

            done();
        });

        it('should change the expiration dates of all its subscriptions to 0s', function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    iotAgentLib.unregister(device.id, function(error) {
                        contextBrokerMock.done();
                        done();
                    });
                });
            });
        });
    });
    describe('When a new notification comes to the IoTAgent', function() {
        beforeEach(function(done) {
            iotAgentLib.getDevice('MicroLight1', function(error, device) {
                iotAgentLib.subscribe(device, ['attr_name'], null, function(error) {
                    done();
                });
            });
        });

        it('should invoke the user defined callback', function(done) {
            var notificationOptions = {
                    url: 'http://localhost:' + iotAgentConfig.server.port + '/notify',
                    method: 'POST',
                    json: utils.readExampleFile('./test/unit/subscriptionRequests/simpleNotification.json'),
                    headers: {
                        'fiware-service': 'smartGondor',
                        'fiware-servicepath': '/gardens'
                    }
                },

                executedHandler = false;

            function mockedHandler(device, notification, callback) {
                executedHandler = true;
                callback();
            }

            iotAgentLib.setNotificationHandler(mockedHandler);

            request(notificationOptions, function(error, response, body) {
                should.not.exist(error);
                executedHandler.should.equal(true);

                done();
            });
        });
        it('should get the correspondent device information', function(done) {
            var notificationOptions = {
                    url: 'http://localhost:' + iotAgentConfig.server.port + '/notify',
                    method: 'POST',
                    json: utils.readExampleFile('./test/unit/subscriptionRequests/simpleNotification.json'),
                    headers: {
                        'fiware-service': 'smartGondor',
                        'fiware-servicepath': '/gardens'
                    }
                },
                rightFields = false;

            function mockedHandler(device, data, callback) {
                if (device && device.id === 'MicroLight1' && device.name === 'FirstMicroLight' &&
                    data && data.length === 1 && data[0].name === 'attr_name') {
                    rightFields = true;
                }

                callback();
            }

            iotAgentLib.setNotificationHandler(mockedHandler);

            request(notificationOptions, function(error, response, body) {
                should.not.exist(error);
                rightFields.should.equal(true);

                done();
            });
        });
    });
    describe('When a new notification arrives to the IOTA with a non-200 code', function() {
        it('should not call the handler');
    });
});
<|endoftext|>


<commit_before>"use strict";

var _ = require('lodash');
var Remotes = require('strong-remoting');
var SharedClass = Remotes.SharedClass;

module.exports = function (/*registry*/) {

    return {
        define: function (Model, name, properties, settings) {
            Model.sharedClass = new SharedClass(name, Model, settings['remoting']);

            buildSharedCtor(Model);

            Model.expose = function (name, options) {
                options = options || {};
                if (options.isStatic === undefined) {
                    options.isStatic = true;
                }
                standartize(options);
                this.sharedClass.defineMethod(name, options);
            };

            Model.exposeCrud = function (methods) {
                exposeCrud(Model, methods);
            };

            // setup a remoting type converter for this model
            Remotes.convert(name, function (val) {
                return val ? new Model(val) : val;
            });

            if (settings['crud']) {
                Model.exposeCrud(settings['crud']);
            }
        }
    }
};

function buildSharedCtor(Model) {

    // support remoting prototype methods
    Model.sharedCtor = function (data, id, fn) {
        var Model = this;

        if(typeof data === 'function') {
            fn = data;
            data = null;
            id = null;
        } else if (typeof id === 'function') {
            fn = id;

            if(typeof data !== 'object') {
                id = data;
                data = null;
            } else {
                id = null;
            }
        }

        if(id && data) {
            var model = new Model(data);
            model.id = id;
            fn(null, model);
        } else if(data) {
            fn(null, new Model(data));
        } else if(id) {
            Model.findById(id, function (err, model) {
                if(err) {
                    fn(err);
                } else if(model) {
                    fn(null, model);
                } else {
                    err = new Error('could not find a model with id ' + id);
                    err.statusCode = 404;

                    fn(err);
                }
            });
        } else {
            fn(new Error('must specify an id or data'));
        }
    };

    var idDesc = Model.modelName + ' id';
    Model.sharedCtor.accepts = [
        {arg: 'id', type: 'any', required: true, http: {source: 'path'},
            description: idDesc}
        // {arg: 'instance', type: 'object', http: {source: 'body'}}
    ];

    Model.sharedCtor.http = [
        {path: '/:id'}
    ];

    Model.sharedCtor.returns = {root: true};
}

function standartize(options) {
    var accepts = options.accepts;

    if (accepts) {
        // for explorer generating gui
        if (Array.isArray(accepts)) {
            accepts.forEach(function (accept) {
                httperize(accept);
            })
        } else {
            httperize(accepts);
        }
    }

    return options;

}

function httperize(accept) {
    if (!accept || !accept.source) return;
    if (!accept.http && typeof accept.source === 'function') {
        accept.http = accept.source;
    } else {
        accept.http = accept.http || {};
        accept.http.source = accept.source === 'payload' ? 'body' : accept.source;
    }
}

function exposeCrud(Model, methods) {
    if (methods === false || methods === 'false') {
        return;
    }

    if (!methods || methods === true || methods === 'true' || methods === 'all') {
        methods = true
    } else if (!Array.isArray(methods)) {
        methods = [methods];
    }

    var modelType = Model.modelName;

    function expose(scope, name, options) {
        var fn = scope[name];
        fn._delegate = true;
        options.isStatic = scope === Model;
        Model.expose(name, options);
    }

    function enabled(method) {
        return methods === true || _.contains(methods, method);
    }

    /*!
     * Convert null callbacks to 404 error objects.
     * @param  {HttpContext} ctx
     * @param  {Function} cb
     */

    function convertNullToNotFoundError(ctx, cb) {
        if (ctx.result !== null) return cb();
        notFoundError(ctx, cb);
    }

    function notFoundError(ctx, cb) {
        var modelName = ctx.method.sharedClass.name;
        var id = ctx.req.param('id');
        var msg = 'Unknown "' + modelName + '" id "' + id + '".';
        var error = new Error(msg);
        error.statusCode = error.status = 404;
        cb(error);
    }

    enabled('create') && expose(Model, 'create', {
        description: 'Create a new instance of the model and persist it into the data source',
        accepts: {arg: 'data', type: 'object', source: 'body', description: 'Model instance data'},
        returns: {arg: 'data', type: modelType, root: true},
        http: {verb: 'post', path: '/'}
    });

    // update ~ remoting attributes
    enabled('updateById') && expose(Model, 'updateById', {
        description: 'Update attributes for a model instance and persist it into the database',
        accepts: [
            {arg: 'id', type: 'any', required: true, description: 'Model id'},
            {arg: 'data', type: 'object', source: 'body', description: 'An object of model property name/value pairs'}
        ],
        returns: {arg: 'data', type: modelType, root: true},
        http: {verb: 'put', path: '/:id'}
    });

    // upsert ~ remoting attributes
    enabled('upsert') && expose(Model, 'upsert', {
        description: 'Update an existing model instance or insert a new one into the data source',
        accepts: {arg: 'data', type: 'object', source: 'body', description: 'Model instance data'},
        returns: {arg: 'data', type: modelType, root: true},
        http: {verb: 'put', path: '/'}
    });

    // exists ~ remoting attributes
    enabled('exists') && expose(Model, 'exists', {
        description: 'Check whether a model instance exists in the data source',
        accepts: {arg: 'id', type: 'any', required: true, description: 'Model id'},
        returns: {arg: 'exists', type: 'boolean'},
        http: [
            {verb: 'get', path: '/:id/exists'},
            {verb: 'head', path: '/:id'}
        ],
        rest: { after: function (ctx, cb) { // After hook to map exists to 200/404 for HEAD
            if (ctx.result.exists) return cb();
            notFoundError(ctx, cb);
        } }
    });

    // find ~ remoting attributes
    enabled('findById') && expose(Model, 'findById', {
        description: 'Find a model instance by id from the data source',
        accepts: {arg: 'id', type: 'any', required: true, description: 'Model id'},
        returns: {arg: 'data', type: modelType, root: true},
        http: {verb: 'get', path: '/:id'},
        rest: {after: convertNullToNotFoundError}
    });

    // all ~ remoting attributes
    enabled('all') && expose(Model, 'all', {
        description: 'Find all instances of the model matched by filter from the data source',
        accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, orderBy, offset, and limit'},
        returns: {arg: 'data', type: [modelType], root: true},
        http: {verb: 'get', path: '/'}
    });

    enabled('one') && expose(Model, 'one', {
        description: 'Find first instance of the model matched by filter from the data source',
        accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, orderBy, offset, and limit'},
        returns: {arg: 'data', type: 'object', root: true},
        http: {verb: 'get', path: '/one'},
        rest: {after: convertNullToNotFoundError}
    });

    // deleteById ~ remoting attributes
    enabled('deleteById') && expose(Model, 'deleteById', {
        description: 'Delete a model instance by id from the data source',
        accepts: {arg: 'id', type: 'any', required: true, description: 'Model id'},
        http: {verb: 'del', path: '/:id'}
    });

    // count ~ remoting attributes
    enabled('count') && expose(Model, 'count', {
        description: 'Count instances of the model matched by where from the data source',
        accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
        returns: {arg: 'count', type: 'number'},
        http: {verb: 'get', path: '/count'}
    });
}<commit_msg>added sharedCtor for model<commit_after>"use strict";

var _ = require('lodash');
var Remotes = require('strong-remoting');
var SharedClass = Remotes.SharedClass;

module.exports = function (/*registry*/) {

    return {
        define: function (Model, name, properties, settings) {
            buildSharedCtor(Model);

            Model.sharedClass = new SharedClass(name, Model, settings['remoting']);

            Model.expose = function (name, options) {
                options = options || {};
                if (options.isStatic === undefined) {
                    options.isStatic = true;
                }
                standartize(options);
                this.sharedClass.defineMethod(name, options);
            };

            Model.exposeCrud = function (methods) {
                exposeCrud(Model, methods);
            };

            // setup a remoting type converter for this model
            Remotes.convert(name, function (val) {
                return val ? new Model(val) : val;
            });

            if (settings['crud']) {
                Model.exposeCrud(settings['crud']);
            }
        }
    }
};

function buildSharedCtor(Model) {

    // support remoting prototype methods
    Model.sharedCtor = function (data, id, fn) {
        var Model = this;

        if(typeof data === 'function') {
            fn = data;
            data = null;
            id = null;
        } else if (typeof id === 'function') {
            fn = id;

            if(typeof data !== 'object') {
                id = data;
                data = null;
            } else {
                id = null;
            }
        }

        if(id && data) {
            var model = new Model(data);
            model.id = id;
            fn(null, model);
        } else if(data) {
            fn(null, new Model(data));
        } else if(id) {
            Model.findById(id, function (err, model) {
                if(err) {
                    fn(err);
                } else if(model) {
                    fn(null, model);
                } else {
                    err = new Error('could not find a model with id ' + id);
                    err.statusCode = 404;

                    fn(err);
                }
            });
        } else {
            fn(new Error('must specify an id or data'));
        }
    };

    var idDesc = Model.modelName + ' id';
    Model.sharedCtor.accepts = [
        {arg: 'id', type: 'any', required: true, http: {source: 'path'},
            description: idDesc}
        // {arg: 'instance', type: 'object', http: {source: 'body'}}
    ];

    Model.sharedCtor.http = [
        {path: '/:id'}
    ];

    Model.sharedCtor.returns = {root: true};
}

function standartize(options) {
    var accepts = options.accepts;

    if (accepts) {
        // for explorer generating gui
        if (Array.isArray(accepts)) {
            accepts.forEach(function (accept) {
                httperize(accept);
            })
        } else {
            httperize(accepts);
        }
    }

    return options;

}

function httperize(accept) {
    if (!accept || !accept.source) return;
    if (!accept.http && typeof accept.source === 'function') {
        accept.http = accept.source;
    } else {
        accept.http = accept.http || {};
        accept.http.source = accept.source === 'payload' ? 'body' : accept.source;
    }
}

function exposeCrud(Model, methods) {
    if (methods === false || methods === 'false') {
        return;
    }

    if (!methods || methods === true || methods === 'true' || methods === 'all') {
        methods = true
    } else if (!Array.isArray(methods)) {
        methods = [methods];
    }

    var modelType = Model.modelName;

    function expose(scope, name, options) {
        var fn = scope[name];
        fn._delegate = true;
        options.isStatic = scope === Model;
        Model.expose(name, options);
    }

    function enabled(method) {
        return methods === true || _.contains(methods, method);
    }

    /*!
     * Convert null callbacks to 404 error objects.
     * @param  {HttpContext} ctx
     * @param  {Function} cb
     */

    function convertNullToNotFoundError(ctx, cb) {
        if (ctx.result !== null) return cb();
        notFoundError(ctx, cb);
    }

    function notFoundError(ctx, cb) {
        var modelName = ctx.method.sharedClass.name;
        var id = ctx.req.param('id');
        var msg = 'Unknown "' + modelName + '" id "' + id + '".';
        var error = new Error(msg);
        error.statusCode = error.status = 404;
        cb(error);
    }

    enabled('create') && expose(Model, 'create', {
        description: 'Create a new instance of the model and persist it into the data source',
        accepts: {arg: 'data', type: 'object', source: 'body', description: 'Model instance data'},
        returns: {arg: 'data', type: modelType, root: true},
        http: {verb: 'post', path: '/'}
    });

    // update ~ remoting attributes
    enabled('updateById') && expose(Model, 'updateById', {
        description: 'Update attributes for a model instance and persist it into the database',
        accepts: [
            {arg: 'id', type: 'any', required: true, description: 'Model id'},
            {arg: 'data', type: 'object', source: 'body', description: 'An object of model property name/value pairs'}
        ],
        returns: {arg: 'data', type: modelType, root: true},
        http: {verb: 'put', path: '/:id'}
    });

    // upsert ~ remoting attributes
    enabled('upsert') && expose(Model, 'upsert', {
        description: 'Update an existing model instance or insert a new one into the data source',
        accepts: {arg: 'data', type: 'object', source: 'body', description: 'Model instance data'},
        returns: {arg: 'data', type: modelType, root: true},
        http: {verb: 'put', path: '/'}
    });

    // exists ~ remoting attributes
    enabled('exists') && expose(Model, 'exists', {
        description: 'Check whether a model instance exists in the data source',
        accepts: {arg: 'id', type: 'any', required: true, description: 'Model id'},
        returns: {arg: 'exists', type: 'boolean'},
        http: [
            {verb: 'get', path: '/:id/exists'},
            {verb: 'head', path: '/:id'}
        ],
        rest: { after: function (ctx, cb) { // After hook to map exists to 200/404 for HEAD
            if (ctx.result.exists) return cb();
            notFoundError(ctx, cb);
        } }
    });

    // find ~ remoting attributes
    enabled('findById') && expose(Model, 'findById', {
        description: 'Find a model instance by id from the data source',
        accepts: {arg: 'id', type: 'any', required: true, description: 'Model id'},
        returns: {arg: 'data', type: modelType, root: true},
        http: {verb: 'get', path: '/:id'},
        rest: {after: convertNullToNotFoundError}
    });

    // all ~ remoting attributes
    enabled('all') && expose(Model, 'all', {
        description: 'Find all instances of the model matched by filter from the data source',
        accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, orderBy, offset, and limit'},
        returns: {arg: 'data', type: [modelType], root: true},
        http: {verb: 'get', path: '/'}
    });

    enabled('one') && expose(Model, 'one', {
        description: 'Find first instance of the model matched by filter from the data source',
        accepts: {arg: 'filter', type: 'object', description: 'Filter defining fields, where, orderBy, offset, and limit'},
        returns: {arg: 'data', type: 'object', root: true},
        http: {verb: 'get', path: '/one'},
        rest: {after: convertNullToNotFoundError}
    });

    // deleteById ~ remoting attributes
    enabled('deleteById') && expose(Model, 'deleteById', {
        description: 'Delete a model instance by id from the data source',
        accepts: {arg: 'id', type: 'any', required: true, description: 'Model id'},
        http: {verb: 'del', path: '/:id'}
    });

    // count ~ remoting attributes
    enabled('count') && expose(Model, 'count', {
        description: 'Count instances of the model matched by where from the data source',
        accepts: {arg: 'where', type: 'object', description: 'Criteria to match model instances'},
        returns: {arg: 'count', type: 'number'},
        http: {verb: 'get', path: '/count'}
    });
}<|endoftext|>


<commit_before>'use strict';

var
FP          = require('filepath'),
Promise     = require('./promise'),
U           = require('./u'),
errors      = require('./errors'),
application = require('./application');

exports.load = function () {
  var
  promises,
  app         = application.create(),
  appRoot     = FP.create().resolve(process.argv[1]).dirname(),
  pluginsDir  = appRoot.append('plugins'),
  pluginFiles = [];

  if (pluginsDir.isDirectory()) {
    pluginFiles = pluginsDir.list();
  }

  promises = U.compact(pluginFiles.map(U.partial(loadPlugin, app)));
  return Promise.all(promises);
};

function loadPlugin(app, path) {
  var plugin;

  if (path.isFile()) {
    path = path.toString();
    plugin = require(path);

    if (typeof plugin !== 'function') {
      throw new errors.ArgumentError('Plugin exports must be a function: '+ path);
    }

    return Promise.resolve(plugin(app));
  }

  return null;
}
<commit_msg>WIP on application_loader.<commit_after>'use strict';

var
FP          = require('filepath'),
Promise     = require('./promise'),
U           = require('./u'),
errors      = require('./errors'),
application = require('./application'),

packageJSONLoader  = require('./package_json_loader'),
clArgsLoader       = require('./cl_args_loader'),
configsFilesLoader = require('./configs_files_loader');

exports.DEFAULTS = {
  ENVIRONMENT: 'development'
};

// args.usageString
// args.helpString
// args.options
// args.appdir = FP.create().resolve(process.argv[1]).dirname();
// args.sysconfigsdir
// args.name
// args.version
// args.environment
exports.load = function (args) {
  var
  packageJSON, argv, environment, configs, app;

  packageJSON = packageJSONLoader.readPackageJSON({
    appdir: args.appdir
  });

  argv = clArgsLoader.loadArgv({
    usageString : args.usageString,
    helpString  : args.helpString,
    options     : args.options,
    argv        : process.argv
  });

  environment = argv.environment ||
                process.env.ENVIRONMENT ||
                process.env.NODE_ENV ||
                args.environment ||
                exports.DEFAULTS.ENVIRONMENT;

  configs = configsFilesLoader.loadConfigs({
    environment   : environment,
    appdir        : args.appdir,
    sysconfigsdir : args.sysconfigsdir
  });

  app = application.create({
    name          : packageJSON.name || args.name,
    version       : packageJSON.version || args.version,
    appdir        : args.appdir,
    sysconfigsdir : args.sysconfigsdir,
    packageJSON   : packageJSON,
    environment   : environment,
    configs       : configs,
    argv          : argv
  });
};

function loadInitializers(app) {
  var
  promises,
  pluginsDir  = app.appdir.append('initializers'),
  pluginFiles = [];

  if (pluginsDir.isDirectory()) {
    pluginFiles = pluginsDir.list();
  }

  promises = U.compact(pluginFiles.map(U.partial(loadPlugin, app)));
  return Promise.all(promises);
}

function loadInitializer(app, path) {
  var plugin;

  if (path.isFile()) {
    path = path.toString();
    plugin = require(path);

    if (typeof plugin !== 'function') {
      throw new errors.ArgumentError('Initializer exports must be a function: '+ path);
    }

    return Promise.resolve(plugin(app));
  }

  return null;
}
<|endoftext|>


<commit_before>var do_encrypt_selectors = [
   "._552m",
    "._1rv"
];

var textareaUsernameGetters = {
    '_552m' : function($textarea) {
        var $anchor = $textarea.closest('.fbNubFlyoutFooter')
                    .siblings('.titlebar').find('.titlebarText');
        if ($anchor.hasClass('noLink')) {
            var userInputs = $anchor.closest('.fbNubFlyoutTitlebar')
                .siblings('.fbNubFlyoutHeader').find('input[name="participants[]"]');
            return userInputs.map(function(index, elm) {
                return elm.value;
            });
        }
        return textareaUsernameGetters.fromAnchor($anchor);
    },
    '_1rv' : function() {
        var $anchor = $('#webMessengerHeaderName').find('a');
        return textareaUsernameGetters.fromAnchor($anchor);
    },
    'fromAnchor' : function($anchor) {
        var user_id = getURLParameter($anchor.attr('href'), 'id');
        if (user_id !== "null") return user_id;

        var friendUrl = $anchor.attr('href').split('/');
        return [friendUrl[friendUrl.length - 1]];
    }
}

$(function() {
    $($('textarea')[0]).focus().trigger('keydown');
    makeOverlays();
    $('#u_0_x').click(function() {
    	replyHandler();
    });
});

function replyHandler() {
	$encryptedArea = $($('textarea')[0]);
	$encryptedArea.focus().trigger('keydown');
}

function makeOverlays() {
    $('textarea').each(function() {
        if ($(this).data('checkedOverlay')) {
            return;
        }

        var classes = $(this).attr('class').split(' ');
        var encryptClasses = classes.filter(function(elm) {
            return do_encrypt_selectors.indexOf('.' + elm) >= 0;
        });
        if (encryptClasses.length == 0) {
            $(this).data('checkedOverlay', true);
            return;
        }
        $(this).data('checkedOverlay', true);
        $(this).data('usernames', textareaUsernameGetters[encryptClasses[0]]($(this)) );

        //need a function to check if will_encrypt for usernames
        makeOverlay($(this));
        $($('textarea')[0]).hide();
    });
}

function makeOverlay($textarea) {
    // if (!$textarea.is(':visible')) {
    //     return;
    // }
    var $fakeblockArea = $textarea.clone();
    $textarea.after($fakeblockArea);
    // $textarea.hide();
    $fakeblockArea.data('encryptedArea', $textarea);

    $fakeblockArea.keyup(function() {
        encryptHandler($(this));
    });
    // $textarea.focus(function() {
    // 	$fakeblockArea.focus()
    // });
}

function requestEncrypt($unencryptedArea, message) {
	var $encryptedArea = $unencryptedArea.data('encryptedArea');
    sendMessage({
        "action" : "encrypt",
        "message" : message,
        "usernames" : $encryptedArea.data('usernames')
    }, function(response) {
        var res = $.parseJSON(response).res;
        var msg;
        $encryptedArea.show().focus().trigger("keydown");
        setTimeout(function(){
            $encryptedArea.hide()
        }, 5);
        if (typeof res === "string") {
            msg = res;
        } else {
            msg = "|fakeblock|" +
                encodeString(JSON.stringify(res)) +
                "|endfakeblock|"
        }
        $encryptedArea.val(msg);
        $unencryptedArea.focus();
    });
}

function encryptHandler($unencryptedArea) {
    var message = $unencryptedArea.val();

    requestEncrypt($unencryptedArea, message);
}

function getURLParameter(url, name) {
    return decodeURI(
        (RegExp(name + '=' + '(.+?)(&|$)').exec(url)||[,null])[1]
    );
}
<commit_msg>Sexy button<commit_after>var do_encrypt_selectors = [
   "._552m",
    "._1rv"
];

var textareas = [];

var textareaUsernameGetters = {
    '_552m' : function($textarea) {
        var $anchor = $textarea.closest('.fbNubFlyoutFooter')
                    .siblings('.titlebar').find('.titlebarText');
        if ($anchor.hasClass('noLink')) {
            var userInputs = $anchor.closest('.fbNubFlyoutTitlebar')
                .siblings('.fbNubFlyoutHeader').find('input[name="participants[]"]');
            return userInputs.map(function(index, elm) {
                return elm.value;
            });
        }
        return textareaUsernameGetters.fromAnchor($anchor);
    },
    '_1rv' : function() {
        var $anchor = $('#webMessengerHeaderName').find('a');
        return textareaUsernameGetters.fromAnchor($anchor);
    },
    'fromAnchor' : function($anchor) {
        var user_id = getURLParameter($anchor.attr('href'), 'id');
        if (user_id !== "null") return user_id;

        var friendUrl = $anchor.attr('href').split('/');
        return [friendUrl[friendUrl.length - 1]];
    }
}

$(function() {
    $($('textarea')[0]).focus().trigger('keydown');
    makeOverlays();
    $('#u_0_x').click(function() {
    	replyHandler();
    });
});

function replyHandler() {
	$('.lastEdited').val('').focus();
}

function makeOverlays() {
    $('textarea').each(function() {
        if ($(this).data('checkedOverlay')) {
            return;
        }

        var classes = $(this).attr('class').split(' ');
        var encryptClasses = classes.filter(function(elm) {
            return do_encrypt_selectors.indexOf('.' + elm) >= 0;
        });
        if (encryptClasses.length == 0) {
            $(this).data('checkedOverlay', true);
            return;
        }
        $(this).data('checkedOverlay', true);
        $(this).data('usernames', textareaUsernameGetters[encryptClasses[0]]($(this)) );

        //need a function to check if will_encrypt for usernames
        makeOverlay($(this));
        $($('textarea')[0]).hide();
    });
}

function makeOverlay($textarea) {
    // if (!$textarea.is(':visible')) {
    //     return;
    // }
    var $fakeblockArea = $textarea.clone();
    $textarea.after($fakeblockArea);
    // $textarea.hide();
    $fakeblockArea.data('encryptedArea', $textarea);

    $fakeblockArea.keyup(function(e) {
    	if (e.which == 13 && $('._1ri').css('marginLeft') === "15px") {
			console.log("firing enter event");
			$('#u_0_x').click();
    	}
        encryptHandler($(this));
    });
    textareas.push($fakeblockArea);
    // $textarea.focus(function() {
    // 	$fakeblockArea.focus()
    // });
}

function requestEncrypt($unencryptedArea, message) {
	var $encryptedArea = $unencryptedArea.data('encryptedArea');
    sendMessage({
        "action" : "encrypt",
        "message" : message,
        "usernames" : $encryptedArea.data('usernames')
    }, function(response) {
        var res = $.parseJSON(response).res;
        var msg;
        $encryptedArea.show().focus().trigger("keydown");
        if (typeof res === "string") {
            msg = res;
        } else {
            msg = "|fakeblock|" +
                encodeString(JSON.stringify(res)) +
                "|endfakeblock|"
        }
        $encryptedArea.val(msg);
        $unencryptedArea.focus();
        $encryptedArea.hide();
    });
}

function encryptHandler($unencryptedArea) {
    var message = $unencryptedArea.val();
    for (var i=0; i < textareas.length; i++) {
    	textareas[i].removeClass('lastEdited');
    }
    $unencryptedArea.addClass('lastEdited');

    requestEncrypt($unencryptedArea, message);
}

function getURLParameter(url, name) {
    return decodeURI(
        (RegExp(name + '=' + '(.+?)(&|$)').exec(url)||[,null])[1]
    );
}
<|endoftext|>


<commit_before>// given a current color, return the next color
function addColor(currentColor) {
  if (currentColor == "bracket_default") {
    return "bracket_yellow";
  } else if (currentColor == "bracket_yellow") {
    return "bracket_blue";
  } else if (currentColor == "bracket_blue") {
    return "bracket_red";
  } else if (currentColor == "bracket_red") {
    return "bracket_default";
  }
}

// given an element, return the color class it is currently assigned.
function getColorFromClasses(elem) {
  var k;
  var classes_array = elem.attr('class').split(/\s+/);
  for (k = 0; k < classes_array.length; k++) {
    if ($.inArray(classes_array[k], colors) >= 0) {
      return classes_array[k];
    }
  };
  return "bracket_default";
}

// first get the current color class, remove it, then add new one
function changeColorOnClick(elem) {
  var currColorClass = getColorFromClasses(elem);
  elem.removeClass(currColorClass)
      .addClass(addColor(currColorClass));
}

// select the row, then color the row in order
function colorEachRow() {
  for (var j = 0; j < verticalTiles; j++) {
    $(".row" + j).each(function(index) {
      $(this).addClass(colors[index % colors.length]);
    });
  }
}

// find out when the arrow starts!
function getStart(j) {
  if ( j < 2 ) {
    return 2 - j;
  } else if ( j >= 2 && j <= 3 ){
    return 0;
  } else {
    return j - 3;
  }
}

// find out if a given index (hor, vert) is inside the default color arrow
function isOutsideArrow(i,j) {
  var start = getStart(j);
  return (i < start + padding) || (i > start + padding + arrowWidth);
}

//
// originalColor: #2C5CA7, colors: [ yellow: #F9D164, accent_blue: #69D0E6, red: #F8654E ]
//
var originalColor = "bracket_default";
var colors = ["bracket_yellow", "bracket_blue", "bracket_red"];

var tiledWall = $(".tiled_wall");
var firstTile = $(".one_tile:first");
var headerWidth = tiledWall.width();
var headerHeight = tiledWall.height();
var tileWidth = firstTile.width() + 6;
var tileHeight = firstTile.height();
var horizontalTiles = Math.ceil(headerWidth / tileWidth) + 2;
var arrowWidth = Math.floor(600 / tileWidth);
var padding = Math.floor(($(window).width() - 960) / 2 / tileWidth) + 2;
var verticalTiles = Math.floor(headerHeight / tileHeight);
var $startTile = firstTile.remove();

// the tiling process
for (var i = 0; i < horizontalTiles; i++) {
  for (var j = 0; j < verticalTiles; j++) {
    var $clone = $startTile.clone();
    $clone.css({ left: tileWidth * i, top: tileHeight * j });
    if ( !isOutsideArrow(i, j) ) {
      $clone.addClass("insideArrow row" + j);
    } else {
      $clone.addClass("bracket_default");
    }
    if ( j < verticalTiles / 2 ) {
      $clone.addClass('openBracket');
    }
    tiledWall.append($clone);
  }
}

// apply colors to the original arrow
colorEachRow();

// make the top half 'open brackets'
var openBrackets = $('.openBracket');
openBrackets.each(function() {
  $(this).html(function(i, html) {
    return html.replace("/", "/");
  });
});

// find the last tile, so we can replace the tiles before it
var lastTile = $('.insideArrow:last');
// the last row
var lastRowTiles = $('.one_tile').filter( function() {
  return lastTile.offset().top == $(this).offset().top;
});

var lastTileIndex = lastRowTiles.index(lastTile);
// find the tilesToBeReplaced, and the width of those tiles
var tilesToBeReplaced = lastRowTiles.filter(":gt(" + (lastTileIndex - 5) + ")").filter(":lt(4)");
var widthOfTilesToBeReplaced = tilesToBeReplaced.length * tileWidth;
// anchor on the tile BEFORE the tiles that need replacing
var tileBeforeReplacement = tilesToBeReplaced.first().prev();
tilesToBeReplaced.remove();

//
// now we insert the replacement and style it
//
var $lefty = $("
</
");
var $righty = $("
>
");
var $middly = $("
wistia.developers
");
var $sickWrapper = $("

");
$sickWrapper.append($lefty).append($middly).append($righty);
tileBeforeReplacement.after($sickWrapper);
$middly.width($middly.width() + widthOfTilesToBeReplaced - $sickWrapper.width());
$sickWrapper.css({
  left: parseInt(tileBeforeReplacement.css('left'), 10),
  top: parseInt(tileBeforeReplacement.css('top'), 10) + tileHeight
});

// bump the 'nerds' subtitle to line up
var subtitleOffset = parseInt($sickWrapper.css('left'), 10) + $lefty.width();
$('#devhq_subtitle').css('left', subtitleOffset);

// these buggers change color on click
$('.one_tile').on('click', function() {
  changeColorOnClick($(this));
});
<commit_msg>Clear button put in place<commit_after>// given a current color, return the next color
function addColor(currentColor) {
  if (currentColor == "bracket_default") {
    return "bracket_yellow";
  } else if (currentColor == "bracket_yellow") {
    return "bracket_blue";
  } else if (currentColor == "bracket_blue") {
    return "bracket_red";
  } else if (currentColor == "bracket_red") {
    return "bracket_default";
  }
}

function clearAllColors(tile_array) {
  tile_array.each(function() {
    $this = $(this);
    $this.removeClass(getColorFromClasses($this));
    $this.addClass("bracket_default");
  });
}

// given an element, return the color class it is currently assigned.
function getColorFromClasses(elem) {
  var k;
  var classes_array = elem.attr('class').split(/\s+/);
  for (k = 0; k < classes_array.length; k++) {
    if ($.inArray(classes_array[k], colors) >= 0) {
      return classes_array[k];
    }
  };
  return "bracket_default";
}

// first get the current color class, remove it, then add new one
function changeColorOnClick(elem) {
  var currColorClass = getColorFromClasses(elem);
  elem.removeClass(currColorClass)
      .addClass(addColor(currColorClass));
}

// select the row, then color the row in order
function colorEachRow() {
  for (var j = 0; j < verticalTiles; j++) {
    $(".row" + j).each(function(index) {
      $(this).addClass(colors[index % colors.length]);
    });
  }
}

// find out when the arrow starts!
function getStart(j) {
  if ( j < 2 ) {
    return 2 - j;
  } else if ( j >= 2 && j <= 3 ){
    return 0;
  } else {
    return j - 3;
  }
}

// find out if a given index (hor, vert) is inside the default color arrow
function isOutsideArrow(i,j) {
  var start = getStart(j);
  return (i < start + padding) || (i > start + padding + arrowWidth);
}

//
// originalColor: #2C5CA7, colors: [ yellow: #F9D164, accent_blue: #69D0E6, red: #F8654E ]
//
var originalColor = "bracket_default";
var colors = ["bracket_yellow", "bracket_blue", "bracket_red"];
var colorsCleared = false;

var tiledWall = $(".tiled_wall");
var firstTile = $(".one_tile:first");
var headerWidth = tiledWall.width();
var headerHeight = tiledWall.height();
var tileWidth = firstTile.width() + 6;
var tileHeight = firstTile.height();
var horizontalTiles = Math.ceil(headerWidth / tileWidth) + 2;
var arrowWidth = Math.floor(600 / tileWidth);
var padding = Math.floor(($(window).width() - 960) / 2 / tileWidth) + 2;
var verticalTiles = Math.floor(headerHeight / tileHeight);
var $startTile = firstTile.remove();

// the tiling process
for (var i = 0; i < horizontalTiles; i++) {
  for (var j = 0; j < verticalTiles; j++) {
    var $clone = $startTile.clone();
    $clone.css({ left: tileWidth * i, top: tileHeight * j });
    if ( !isOutsideArrow(i, j) ) {
      $clone.addClass("insideArrow row" + j);
    } else {
      $clone.addClass("bracket_default");
    }
    if ( j < verticalTiles / 2 ) {
      $clone.addClass('openBracket');
    }
    tiledWall.append($clone);
  }
}

// apply colors to the original arrow
colorEachRow();

// make the top half 'open brackets'
var openBrackets = $('.openBracket');
openBrackets.each(function() {
  $(this).html(function(i, html) {
    return html.replace("/", "/");
  });
});

// find the last tile, so we can replace the tiles before it
var lastTile = $('.insideArrow:last');
// the last row
var lastRowTiles = $('.one_tile').filter( function() {
  return lastTile.offset().top == $(this).offset().top;
});

var lastTileIndex = lastRowTiles.index(lastTile);
// find the tilesToBeReplaced, and the width of those tiles
var tilesToBeReplaced = lastRowTiles.filter(":gt(" + (lastTileIndex - 5) + ")").filter(":lt(4)");
var widthOfTilesToBeReplaced = tilesToBeReplaced.length * tileWidth;
// anchor on the tile BEFORE the tiles that need replacing
var tileBeforeReplacement = tilesToBeReplaced.first().prev();
tilesToBeReplaced.remove();

//
// now we insert the replacement and style it
//
var $lefty = $("
</
");
var $righty = $("
>
");
var $middly = $("
wistia.developers
");
var $sickWrapper = $("

");
$sickWrapper.append($lefty).append($middly).append($righty);
tileBeforeReplacement.after($sickWrapper);
$middly.width($middly.width() + widthOfTilesToBeReplaced - $sickWrapper.width());
$sickWrapper.css({
  left: parseInt(tileBeforeReplacement.css('left'), 10),
  top: parseInt(tileBeforeReplacement.css('top'), 10) + tileHeight
});

// bump the 'nerds' subtitle to line up
var subtitleOffset = parseInt($sickWrapper.css('left'), 10) + $lefty.width();
$('#devhq_subtitle').css('left', subtitleOffset);

// these buggers change color on click
$('.one_tile').on('click', function() {
  changeColorOnClick($(this));
});

$('.sick_wrapper').on('click', function() {
  if (!colorsCleared) {
    clearAllColors($('.one_tile'));
    colorsCleared = true;
  } else {
    colorEachRow();
    colorsCleared = false;
  }
});
<|endoftext|>


<commit_before>/*
* Application entry point.
*
* Loads core modules and plugins.
*/

import './lib/intersection-observer.js';
import * as plugins from './plugins';
import { ImageLoader, DocumentLoader, Modal, loadPlugin } from './core';

(function() {
  loadCoreModules();
  loadPlugins();
})();

function loadCoreModules() {
  ImageLoader.enable();
  DocumentLoader.enable();
  Modal.enable();
}

function loadPlugins() {
  document.addEventListener('DOMContentLoaded', function() {
    for (const plugin of Object.values(plugins)) {
      loadPlugin(plugin);
    }
  });
}
<commit_msg>Document app.js<commit_after>/**
 * Application entry point.
 *
 * Loads core modules and plugins.
 */

import './lib/intersection-observer.js';
import * as plugins from './plugins';
import { ImageLoader, DocumentLoader, Modal, loadPlugin } from './core';

/**
 * An Immediately Invoked Function Expression, called like that because it’s
 * immediately executed when a JavaScript file like this is sourced.
 *
 * Starts the engines for SlideHub.
 */
(function() {
  loadCoreModules();
  loadPlugins();
})();

/**
 * Loads core modules.
 */
function loadCoreModules() {
  ImageLoader.enable();
  DocumentLoader.enable();
  Modal.enable();
}

/**
 * Loads all plugins from the ./plugins directory.
 */
function loadPlugins() {
  document.addEventListener('DOMContentLoaded', function() {
    for (const plugin of Object.values(plugins)) {
      loadPlugin(plugin);
    }
  });
}
<|endoftext|>


<commit_before>
var fs = require('fs');
var Path = require('path');
var should = require('should');
var Canvas = require('canvas');
var ImageToSlices = require('../lib/index');
var utils = require('../lib/utils');

var pngImagePath = './example/images/building.png';
var exportDir = './example/';
var deleteTempFile = true;

var lineXArray;
var lineYArray;

ImageToSlices.configure({
  clipperOptions: {
    canvas: require('canvas')
  }
});

describe('image-to-slices', function() {
  it('saveToDir works', function(done) {
    lineXArray = [100, 200];
    lineYArray = [100, 200];

    ImageToSlices(pngImagePath, lineXArray, lineYArray, {
      saveToDir: exportDir
    }, function() {
      fs.existsSync(exportDir + 'section-1.png').should.equal(true);
      deleteTempFile && deleteAllFile(exportDir);
      done();
    });
  });

  it('middleBoundaryMode works', function(done) {
    lineXArray = [100, 200];
    lineYArray = [100, 200, 250];

    ImageToSlices(pngImagePath, lineXArray, lineYArray, {
      saveToDir: exportDir,
      middleBoundaryMode: true
    }, function() {
      fs.existsSync(exportDir + 'section-1.png').should.equal(true);
      deleteTempFile && deleteAllFile(exportDir);
      done();
    });
  });

  it('clipperOptions works', function(done) {
    lineXArray = [100, 200];
    lineYArray = [100, 200, 250];

    ImageToSlices(pngImagePath, lineXArray, lineYArray, {
      saveToDir: exportDir,
      middleBoundaryMode: true,
      clipperOptions: {
        quality: 20
      }
    }, function() {
      fs.existsSync(exportDir + 'section-1.png').should.equal(true);
      deleteTempFile && deleteAllFile(exportDir);
      done();
    });
  });

  it('throws when both save directory and saveToDataUrl does not be specified', function(done) {
    try {
      ImageToSlices(pngImagePath, lineXArray, lineYArray, {
        saveToDir: null,
        saveToDataUrl: false
      }, function() {
        true.should.equal(false);
        done();
      });
    } catch(e) {
      e.message.should.equal('Either saveToDir or saveToDataUrl must be specified');
      done();
    }
  });

  it('throws when lineXArray and lineYArray is empty', function(done) {
    lineXArray = [];
    lineYArray = [];

    try {
      ImageToSlices(pngImagePath, lineXArray, lineYArray, {
        saveToDir: exportDir,
        middleBoundaryMode: true,
        clipperOptions: {
          quality: 20
        }
      }, function() {
        true.should.equal(false);
        done();
      });
    } catch(e) {
      e.message.should.equal('At least one reference line');
      done();
    }
  });
});

describe('utils', function() {
  it('sortAndUnique() works', function() {
    var arr = [223, 1, 8863, 223, 1, 9];
    should(utils.sortAndUnique(arr)).eql([1, 9, 223, 8863]);

    arr = [87, 0, 2, 13, 87, 9, 1, 9, 10];
    should(utils.sortAndUnique(arr)).eql([0, 1, 2, 9, 10, 13, 87]);
  });
});

function deleteAllFile(dir) {
  fs.readdir(dir, function(err, files) {
    files.forEach(function(fileName) {
      var filePath = Path.join(dir, fileName);
      if (/^section/.test(fileName)) {
        deleteFile(filePath);
      }
    });
  });
}

function deleteFile(path) {
  fs.unlink(path, function(err) {
    if (err) throw err;
  });
}<commit_msg>update test case<commit_after>
var fs = require('fs');
var Path = require('path');
var should = require('should');
var imageToSlices = require('../lib/index');
var utils = require('../lib/utils');

var pngImagePath = './example/images/building.png';
var exportDir = './example/';
var deleteTempFile = true;

var lineXArray;
var lineYArray;

imageToSlices.configure({
  clipperOptions: {
    canvas: require('canvas')
  }
});

describe('image-to-slices', function() {
  it('saveToDir works', function(done) {
    lineXArray = [100, 200];
    lineYArray = [100, 200];

    imageToSlices(pngImagePath, lineXArray, lineYArray, {
      saveToDir: exportDir
    }, function() {
      fs.existsSync(exportDir + 'section-1.png').should.equal(true);
      deleteTempFile && deleteAllFile(exportDir);
      done();
    });
  });

  it('middleBoundaryMode works', function(done) {
    lineXArray = [100, 200];
    lineYArray = [100, 200, 250];

    imageToSlices(pngImagePath, lineXArray, lineYArray, {
      saveToDir: exportDir,
      middleBoundaryMode: true
    }, function() {
      fs.existsSync(exportDir + 'section-1.png').should.equal(true);
      deleteTempFile && deleteAllFile(exportDir);
      done();
    });
  });

  it('clipperOptions works', function(done) {
    lineXArray = [100, 200];
    lineYArray = [100, 200, 250];

    imageToSlices(pngImagePath, lineXArray, lineYArray, {
      saveToDir: exportDir,
      middleBoundaryMode: true,
      clipperOptions: {
        quality: 20
      }
    }, function() {
      fs.existsSync(exportDir + 'section-1.png').should.equal(true);
      deleteTempFile && deleteAllFile(exportDir);
      done();
    });
  });

  it('throws when both save directory and saveToDataUrl does not be specified', function(done) {
    try {
      imageToSlices(pngImagePath, lineXArray, lineYArray, {
        saveToDir: null,
        saveToDataUrl: false
      }, function() {
        true.should.equal(false);
        done();
      });
    } catch(e) {
      e.message.should.equal('Either saveToDir or saveToDataUrl must be specified');
      done();
    }
  });

  it('throws when lineXArray and lineYArray is empty', function(done) {
    lineXArray = [];
    lineYArray = [];

    try {
      imageToSlices(pngImagePath, lineXArray, lineYArray, {
        saveToDir: exportDir,
        middleBoundaryMode: true,
        clipperOptions: {
          quality: 20
        }
      }, function() {
        true.should.equal(false);
        done();
      });
    } catch(e) {
      e.message.should.equal('At least one reference line');
      done();
    }
  });
});

describe('utils', function() {
  it('sortAndUnique() works', function() {
    var arr = [223, 1, 8863, 223, 1, 9];
    should(utils.sortAndUnique(arr)).eql([1, 9, 223, 8863]);

    arr = [87, 0, 2, 13, 87, 9, 1, 9, 10];
    should(utils.sortAndUnique(arr)).eql([0, 1, 2, 9, 10, 13, 87]);
  });
});

function deleteAllFile(dir) {
  fs.readdir(dir, function(err, files) {
    files.forEach(function(fileName) {
      var filePath = Path.join(dir, fileName);
      if (/^section/.test(fileName)) {
        deleteFile(filePath);
      }
    });
  });
}

function deleteFile(path) {
  fs.unlink(path, function(err) {
    if (err) throw err;
  });
}<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */

var _ = require('lodash');
var extend = _.extend;
var resolve = require('resolve-dep');
var utils = require('../utils');

/**
 * Resolve and load helpers defined on the config.
 *
 * @param  {Object} `options`
 * @return {[type]}
 */

function helpers (value) {
  switch(utils.typeOf(value)) {
    case 'object':
      return helpers.fromObj(value);
    case 'string':
      return helpers.fromStr(value);
    case 'function':
      return helpers.fromFn(value);
    case 'array':
      return helpers.fromArr(value);
    default:
      return {};
  }
}

/**
 * Resolve the `name`d npm module name, filepath or glob pattern, passing
 * the results to `helpers()`.
 *
 * @method `fromStr`
 * @param {String} `name` NPM module name, file path or glob pattern to resolve.
 * @return {Object} object of key/value helper pairs.
 * @api private
 */

helpers.fromStr = function (str) {
  var resolved = resolve(str);
  var results = {};

  resolved.forEach(function (filepath) {
    var helper = require(filepath);
    if (utils.typeOf(helper) === 'object') {
      extend(results, helper);
    } else {
      extend(results, helpers(helper));
    }
  });
  return results;
};

/**
 * noop, just return the `helper` object.
 *
 * @method `fromObj`
 * @param {Object} `helper` A helper object.
 * @param {Object} object of key/value helper pairs.
 * @api private
 */

helpers.fromObj = function (helper) {
  return helper;
};

/**
 * Execute the function and if the result is an Object, return that
 * Otherwise pass the results back through `helpers`
 *
 * @method `fromFn`
 * @param {Function} `fn`
 * @return {Object} object of key/value helper pairs.
 * @api private
 */

helpers.fromFn = function (fn) {
  var helper = fn.call();
  if (utils.typeOf(helper) === 'object') {
    return helper;
  }
  return helpers(helper);
};

/**
 * Loop over the array and call `helpers` for each item.
 *
 * @method `fromArr`
 * @param {Array} `arr`
 * @return {Object} object of key/value helper pairs.
 * @api private
 */

helpers.fromArr = function (arr) {
  var res = {};
  _.unique(arr).forEach(function (helper) {
    extend(res, helpers(helper));
  });
  return res;
};

/**
 * Export `helpers`
 */

module.exports = helpers;<commit_msg>if `value` is falsey just return it<commit_after>'use strict';

/**
 * Module dependencies.
 */

var _ = require('lodash');
var resolve = require('resolve-dep');
var utils = require('../utils');
var extend = _.extend;

/**
 * Resolve and load helpers defined on the config.
 *
 * @param  {Object} `options`
 * @return {[type]}
 */

function helpers (value) {
  if (!value) {
    return value;
  }

  switch(utils.typeOf(value)) {
    case 'object':
      return helpers.fromObj(value);
    case 'string':
      return helpers.fromStr(value);
    case 'function':
      return helpers.fromFn(value);
    case 'array':
      return helpers.fromArr(value);
    default:
      return {};
  }
}

/**
 * Resolve the `name`d npm module name, filepath or glob pattern, passing
 * the results to `helpers()`.
 *
 * @method `fromStr`
 * @param {String} `name` NPM module name, file path or glob pattern to resolve.
 * @return {Object} object of key/value helper pairs.
 * @api private
 */

helpers.fromStr = function (str) {
  var resolved = resolve(str);
  var results = {};

  resolved.forEach(function (filepath) {
    var helper = require(filepath);
    if (utils.typeOf(helper) === 'object') {
      extend(results, helper);
    } else {
      extend(results, helpers(helper));
    }
  });
  return results;
};

/**
 * noop, just return the `helper` object.
 *
 * @method `fromObj`
 * @param {Object} `helper` A helper object.
 * @param {Object} object of key/value helper pairs.
 * @api private
 */

helpers.fromObj = function (helper) {
  return helper;
};

/**
 * Execute the function and if the result is an Object, return that
 * Otherwise pass the results back through `helpers`
 *
 * @method `fromFn`
 * @param {Function} `fn`
 * @return {Object} object of key/value helper pairs.
 * @api private
 */

helpers.fromFn = function (fn) {
  var helper = fn.call();
  if (utils.typeOf(helper) === 'object') {
    return helper;
  }
  return helpers(helper);
};

/**
 * Loop over the array and call `helpers` for each item.
 *
 * @method `fromArr`
 * @param {Array} `arr`
 * @return {Object} object of key/value helper pairs.
 * @api private
 */

helpers.fromArr = function (arr) {
  var res = {};
  _.unique(arr).forEach(function (helper) {
    extend(res, helpers(helper));
  });
  return res;
};

/**
 * Export `helpers`
 */

module.exports = helpers;<|endoftext|>


<commit_before>// Code goes here

var myApp = angular.module('myApp', ['angularUtils.directives.dirPagination']);

function MyController($scope, $http) {

  $scope.currentPage = 1;
  $scope.pageSize = 20;
  $scope.items = [];
 $http.get("level2.json")
    .then(function(response) {
        $scope.items = response.data;
    });
 $http.get("level1.json")
    .then(function(response) {
        $scope.level1 = response.data;
    });

  $scope.pageChangeHandler = function(num) {

  };
}

function OtherController($scope) {
  $scope.pageChangeHandler = function(num) {

  };
}

myApp.controller('MyController', MyController);
myApp.controller('OtherController', OtherController);
<commit_msg>Update app.js<commit_after>// Code goes here

var myApp = angular.module('myApp', ['angularUtils.directives.dirPagination']);

function MyController($scope, $http) {

  $scope.currentPage = 1;
  $scope.pageSize = 20;
  $scope.items = [];
 $http.get("level2.json")
    .then(function(response) {
        $scope.items = response.data;
    });
 $http.get("level.json")
    .then(function(response) {
        $scope.level = response.data;
    });

  $scope.pageChangeHandler = function(num) {

  };
}

function OtherController($scope) {
  $scope.pageChangeHandler = function(num) {

  };
}

myApp.controller('MyController', MyController);
myApp.controller('OtherController', OtherController);
<|endoftext|>


<commit_before>var assert = require('assert'),
    proxyquire = require('proxyquire'),
    mockCsvRaw;

mockCsvRaw = "Name,Github,Email,Committer,Reviewer\n" +
"Matthew Taylor,rhyolight,matt@numenta.org,1,1\n" +
"Rahul Agarwal,rahul1,ragarwal@numenta.com,1,0\n" +
"Scott Purdy,scottpurdy,scott@numenta.org,1,1\n" +
"Subutai Ahmad,subutai,subutai@numenta.org,1,1\n" +
"Arlo Breault,arlolra,arlolra@gmail.com,0,0\n" +
"Austin Marshall,oxtopus,oxtopus@gmail.com,1,1\n" +
"Ron Marianetti,rmarianetti,rmarianetti@groksolutions.com,1,1\n" +
"Ian Danforth,iandanforth,idanforth@embodiedai.com,0,0\n" +
"Ziv Rosen,zivrosen,zrosen@groksolutions.com,1,0\n" +
"Vitaly Kruglikov,vitaly-krugl,vkruglikov@numenta.com,1,1\n" +
"Brev Patterson,brev,bpatterson@groksolutions.com,0,0\n" +
"Stewart Mackenzie,sjmackenzie,setori88@gmail.com,0,0\n" +
"Matthew O'Connor,mattroid,mattroid@gmail.com,0,0\n" +
"Thomas Yu,tyu-grok,tyu@groksolutions.com,1,0\n" +
"Il Memming Park,memming,memming@gmail.com,0,0\n" +
"Henry Pan,hpan1984,henryjpan@gmail.com,0,0\n" +
"Jordan Dea-Mattson,jordandm,jdm@dea-mattson.com,1,0\n" +
"David Ragazzi,DavidRagazzi,david_ragazzi@hotmail.com,0,0\n" +
"Peter Hunt,petehunt,floydophone@gmail.com,0,0\n" +
"Patrick Higgins,pat-man,patman@cybermesa.com,0,0\n" +
"Erik Blas,ravaa,erik.blas@gmail.com,0,0\n" +
"Bertie Wheen,Duta,wheen.b@gmail.com,0,0\n" +
"Joe Block,unixorn,jpb@groksolutions.com,0,0\n" +
"David Brody,dbrody,dbrody@gmail.com,1,0\n" +
"Will Perkins,willperkins,hello@willperkins.com,0,0\n" +
"Marek Otahal,breznak,markotahal@gmail.com,1,0\n" +
"Christopher Lee Simons,csimons,christopherleesimons@gmail.com,0,0\n" +
"Kenneth Hammett,BubbaRich,rich.hammett@gmail.com,0,0\n" +
"Manish Bhattarai,merolaagi,merolaagi@gmail.com,0,0\n" +
"Alexander Stepanov,sysmaker,alexander.a.stepanov@gmail.com,0,0\n" +
"Ellery Wulczyn,ewulczyn,ewulczyn@groksolutions.com,0,0\n" +
"Craig Collins,KI-VEK,Craig.m.collins@comcast.net,0,0\n" +
"Jared Casner,jcasner,jcasner@gmail.com,0,0\n" +
"Gary Follett,garyfollett,gary@follett.com.au,0,0\n" +
"Fergal Byrne,fergbyrne,fergal.byrne@examsupport.ie,0,0\n" +
"David Petrillo,dpetrillo740,david.petrillo@gmail.com,0,0\n" +
"Gil Shotan,gilsho,gilsho@cs.stanford.edu,0,0\n" +
"Rob de Bliek,rdebliek,rdebliek@gmail.com,0,0\n" +
"Luiz Scheinkman,lscheinkman,lscheinkman@groksolutions.com,0,0\n" +
"Ari Kamlani,akamlani,akamlani@gmail.com,0,0\n" +
"Karthikeyan Subbaraj,karthiks,karthispeaks@gmail.com,0,0\n" +
"Matt Keith,keithcom,keith@keithcom.com,0,0\n" +
"Hideaki Suzuki,h2suzuki,h2suzuki@gmail.com,0,0\n" +
"Paulo Reis Rodrigues,khamael,paulo@mint-labs.com,0,0\n" +
"Mattias Eriksson,mattiaseriksson,eriksson.mattias@gmail.com,0,0\n" +
"Chetan Surpur,chetan51,hetan51@gmail.com,0,0\n" +
"Ramesh Ganesan,info2ram,info2ram@gmail.com,0,0\n" +
"Marc Girardot,mgirardo,mgirardo@cisco.com,0,0\n" +
"Rakesh Kumar,gopchandani,gopchandani@gmail.com,0,0\n" +
"Paolo Gavazzi,pgavazzi,pgavazzi@softcactus.com,0,0\n" +
"Aseem Hegshetye,aseem-hegshetye,axh118830@utdallas.edu,0,0\n" +
"Carl Friess,carlfriess,carl.friess@me.com,0,0\n" +
"Papa Niang,pniang,Opendatageek@gmail.com,0,0\n" +
"Azat Nurmagambetov,azatnur,azat_n@yahoo.com,0,0\n" +
"Sergey Milanov,smilanov,s_milanov@yahoo.com,0,0\n" +
"Aidan Rocke,AidanRocke,aidan.rocke@gmail.com,0,0\n" +
"Timothy McNamara,timClicks,paperless@timmcnamara.co.nz,0,0\n" +
"Zac Kohn,zackohn,zackohn@yahoo.com,0,0\n" +
"Mark Ellul,mark-ellul,mark@iplusd.net,0,0\n" +
"Greg Slepak,taoeffect,contact@taoeffect.com,0,0\n" +
"Max Lapan,shmuma,max.lapan@gmail.com,0,0\n" +
"Wei Wang,tskatom,tskatom@gmail.com,0,0\n" +
"Jason Poovey,sirpoovey,japoovey@gmail.com,0,0\n" +
"Joseph-Anthony Perez,BlueConstellation,joe.perez@gmx.de,0,0\n" +
"Jordan Miller,LegitMiller,jordan.kay@gmail.com,0,0\n" +
"Grant Wright,grant-wright,grant.wright@yahoo.com,0,0\n" +
"Takashi Yamamoto,TakashiYamamoto,takashi@caelum.co.jp,0,0\n" +
"Alexander Powell,alexaltair,alexanderaltair@gmail.com,0,0\n" +
"Timothy Farley,trfarley,t.farley@loma.k12.ca.us,0,0\n" +
"Jacques Ludik,jludik,jludik@gmail.com,0,0\n" +
"Thomas Macrina,macrintr,thomas.macrina@gmail.com,0,0\n" +
"Dominik Lach,asele,pogromcaowiec@student.uksw.edu.pl,0,0\n" +
"Valter Heger,heger-valter,heger.valter@gmail.com,0,0\n" +
"Jeffrey Thompson,jkthompson,jeffreykeatingthompson@gmail.com,0,0\n" +
"Brad Bowman,bowman,brad.bowman@gmail.com,0,0\n";

describe('contributors utilities', function() {
    describe('after fetching CSV data from URL', function() {
        var mockRequestLib = function(url, cb) {
            assert.equal(url, 'url-to-csv', 'wrong csv url used for fetching contributors');
            cb(null, null, mockCsvRaw);
        };
        it('returns proper data structure', function() {
            var contributorsUtils = proxyquire('../../utils/contributors', {
                request: mockRequestLib
            });
            contributorsUtils.getAll('url-to-csv', function(err, contributors) {
                assert(err == undefined, 'received error from csv reader');
                console.log(contributors);
                assert.equal(75, contributors.length, 'Bad length of contributors listing');
                var subutai = contributors[3];
                var ian = contributors[7];
                ['Github', 'Name', 'Email'].forEach(function(key) {
                    assert(subutai[key], 'Contributor entry for subutai missing "' + key + '" key');
                    assert(ian[key], 'Contributor entry for ian missing "' + key + '" key');
                });
                assert.equal('Subutai Ahmad', subutai.Name);
                assert.equal('subutai', subutai.Github);
                assert.equal('subutai@numenta.org', subutai.Email);
                assert.equal(1, subutai.Committer, 'Subutai should be a Committer');
                assert.equal(1, subutai.Reviewer, 'Subutai should be a Reviewer');
                assert.equal(0, ian.Committer, 'Ian should not be a Committer');
                assert.equal(0, ian.Reviewer, 'Ian should not be a Reviewer');
            });
        });
    });
});<commit_msg>Removing console log<commit_after>var assert = require('assert'),
    proxyquire = require('proxyquire'),
    mockCsvRaw;

mockCsvRaw = "Name,Github,Email,Committer,Reviewer\n" +
"Matthew Taylor,rhyolight,matt@numenta.org,1,1\n" +
"Rahul Agarwal,rahul1,ragarwal@numenta.com,1,0\n" +
"Scott Purdy,scottpurdy,scott@numenta.org,1,1\n" +
"Subutai Ahmad,subutai,subutai@numenta.org,1,1\n" +
"Arlo Breault,arlolra,arlolra@gmail.com,0,0\n" +
"Austin Marshall,oxtopus,oxtopus@gmail.com,1,1\n" +
"Ron Marianetti,rmarianetti,rmarianetti@groksolutions.com,1,1\n" +
"Ian Danforth,iandanforth,idanforth@embodiedai.com,0,0\n" +
"Ziv Rosen,zivrosen,zrosen@groksolutions.com,1,0\n" +
"Vitaly Kruglikov,vitaly-krugl,vkruglikov@numenta.com,1,1\n" +
"Brev Patterson,brev,bpatterson@groksolutions.com,0,0\n" +
"Stewart Mackenzie,sjmackenzie,setori88@gmail.com,0,0\n" +
"Matthew O'Connor,mattroid,mattroid@gmail.com,0,0\n" +
"Thomas Yu,tyu-grok,tyu@groksolutions.com,1,0\n" +
"Il Memming Park,memming,memming@gmail.com,0,0\n" +
"Henry Pan,hpan1984,henryjpan@gmail.com,0,0\n" +
"Jordan Dea-Mattson,jordandm,jdm@dea-mattson.com,1,0\n" +
"David Ragazzi,DavidRagazzi,david_ragazzi@hotmail.com,0,0\n" +
"Peter Hunt,petehunt,floydophone@gmail.com,0,0\n" +
"Patrick Higgins,pat-man,patman@cybermesa.com,0,0\n" +
"Erik Blas,ravaa,erik.blas@gmail.com,0,0\n" +
"Bertie Wheen,Duta,wheen.b@gmail.com,0,0\n" +
"Joe Block,unixorn,jpb@groksolutions.com,0,0\n" +
"David Brody,dbrody,dbrody@gmail.com,1,0\n" +
"Will Perkins,willperkins,hello@willperkins.com,0,0\n" +
"Marek Otahal,breznak,markotahal@gmail.com,1,0\n" +
"Christopher Lee Simons,csimons,christopherleesimons@gmail.com,0,0\n" +
"Kenneth Hammett,BubbaRich,rich.hammett@gmail.com,0,0\n" +
"Manish Bhattarai,merolaagi,merolaagi@gmail.com,0,0\n" +
"Alexander Stepanov,sysmaker,alexander.a.stepanov@gmail.com,0,0\n" +
"Ellery Wulczyn,ewulczyn,ewulczyn@groksolutions.com,0,0\n" +
"Craig Collins,KI-VEK,Craig.m.collins@comcast.net,0,0\n" +
"Jared Casner,jcasner,jcasner@gmail.com,0,0\n" +
"Gary Follett,garyfollett,gary@follett.com.au,0,0\n" +
"Fergal Byrne,fergbyrne,fergal.byrne@examsupport.ie,0,0\n" +
"David Petrillo,dpetrillo740,david.petrillo@gmail.com,0,0\n" +
"Gil Shotan,gilsho,gilsho@cs.stanford.edu,0,0\n" +
"Rob de Bliek,rdebliek,rdebliek@gmail.com,0,0\n" +
"Luiz Scheinkman,lscheinkman,lscheinkman@groksolutions.com,0,0\n" +
"Ari Kamlani,akamlani,akamlani@gmail.com,0,0\n" +
"Karthikeyan Subbaraj,karthiks,karthispeaks@gmail.com,0,0\n" +
"Matt Keith,keithcom,keith@keithcom.com,0,0\n" +
"Hideaki Suzuki,h2suzuki,h2suzuki@gmail.com,0,0\n" +
"Paulo Reis Rodrigues,khamael,paulo@mint-labs.com,0,0\n" +
"Mattias Eriksson,mattiaseriksson,eriksson.mattias@gmail.com,0,0\n" +
"Chetan Surpur,chetan51,hetan51@gmail.com,0,0\n" +
"Ramesh Ganesan,info2ram,info2ram@gmail.com,0,0\n" +
"Marc Girardot,mgirardo,mgirardo@cisco.com,0,0\n" +
"Rakesh Kumar,gopchandani,gopchandani@gmail.com,0,0\n" +
"Paolo Gavazzi,pgavazzi,pgavazzi@softcactus.com,0,0\n" +
"Aseem Hegshetye,aseem-hegshetye,axh118830@utdallas.edu,0,0\n" +
"Carl Friess,carlfriess,carl.friess@me.com,0,0\n" +
"Papa Niang,pniang,Opendatageek@gmail.com,0,0\n" +
"Azat Nurmagambetov,azatnur,azat_n@yahoo.com,0,0\n" +
"Sergey Milanov,smilanov,s_milanov@yahoo.com,0,0\n" +
"Aidan Rocke,AidanRocke,aidan.rocke@gmail.com,0,0\n" +
"Timothy McNamara,timClicks,paperless@timmcnamara.co.nz,0,0\n" +
"Zac Kohn,zackohn,zackohn@yahoo.com,0,0\n" +
"Mark Ellul,mark-ellul,mark@iplusd.net,0,0\n" +
"Greg Slepak,taoeffect,contact@taoeffect.com,0,0\n" +
"Max Lapan,shmuma,max.lapan@gmail.com,0,0\n" +
"Wei Wang,tskatom,tskatom@gmail.com,0,0\n" +
"Jason Poovey,sirpoovey,japoovey@gmail.com,0,0\n" +
"Joseph-Anthony Perez,BlueConstellation,joe.perez@gmx.de,0,0\n" +
"Jordan Miller,LegitMiller,jordan.kay@gmail.com,0,0\n" +
"Grant Wright,grant-wright,grant.wright@yahoo.com,0,0\n" +
"Takashi Yamamoto,TakashiYamamoto,takashi@caelum.co.jp,0,0\n" +
"Alexander Powell,alexaltair,alexanderaltair@gmail.com,0,0\n" +
"Timothy Farley,trfarley,t.farley@loma.k12.ca.us,0,0\n" +
"Jacques Ludik,jludik,jludik@gmail.com,0,0\n" +
"Thomas Macrina,macrintr,thomas.macrina@gmail.com,0,0\n" +
"Dominik Lach,asele,pogromcaowiec@student.uksw.edu.pl,0,0\n" +
"Valter Heger,heger-valter,heger.valter@gmail.com,0,0\n" +
"Jeffrey Thompson,jkthompson,jeffreykeatingthompson@gmail.com,0,0\n" +
"Brad Bowman,bowman,brad.bowman@gmail.com,0,0\n";

describe('contributors utilities', function() {
    describe('after fetching CSV data from URL', function() {
        var mockRequestLib = function(url, cb) {
            assert.equal(url, 'url-to-csv', 'wrong csv url used for fetching contributors');
            cb(null, null, mockCsvRaw);
        };
        it('returns proper data structure', function() {
            var contributorsUtils = proxyquire('../../utils/contributors', {
                request: mockRequestLib
            });
            contributorsUtils.getAll('url-to-csv', function(err, contributors) {
                assert(err == undefined, 'received error from csv reader');
                assert.equal(75, contributors.length, 'Bad length of contributors listing');
                var subutai = contributors[3];
                var ian = contributors[7];
                ['Github', 'Name', 'Email'].forEach(function(key) {
                    assert(subutai[key], 'Contributor entry for subutai missing "' + key + '" key');
                    assert(ian[key], 'Contributor entry for ian missing "' + key + '" key');
                });
                assert.equal('Subutai Ahmad', subutai.Name);
                assert.equal('subutai', subutai.Github);
                assert.equal('subutai@numenta.org', subutai.Email);
                assert.equal(1, subutai.Committer, 'Subutai should be a Committer');
                assert.equal(1, subutai.Reviewer, 'Subutai should be a Reviewer');
                assert.equal(0, ian.Committer, 'Ian should not be a Committer');
                assert.equal(0, ian.Reviewer, 'Ian should not be a Reviewer');
            });
        });
    });
});<|endoftext|>