<commit_before>"use strict";
var async = require("async"),
    mongoose = require("mongoose"),
    errors = require("../../errors.js").ERRORS;

module.exports = function(UserSchema) {
    // request access to the data of another user
    UserSchema.methods.makeRequest = function(email, callback) {
        // check an email address has been specified
        if (typeof email === "undefined" || email === null || email.length === 0)
            return callback(errors.EMAIL_REQUIRED);

        // check we haven't already requested access from that user
        var existing = this.requested.filter(function(request) {
            return request.email === email;
        });
        if (existing.length > 0) return callback(errors.ALREADY_REQUESTED);

        // check we not requesting share with yourself
        if (email === this.email) return callback(errors.CANT_REQUEST_YOURSELF);

        // find the user the request is being made to
        this.constructor.findOne({
            email: email
        }, function(err, user) {
            if (err) return callback(err);
            if (!user) return callback(errors.INVALID_EMAIL); // no user found for that email

            // store request in that user (in _requests_ array)
            user.requests.push({
                email: this.email,
                status: "pending"
            });
            // and in this user (in _requested_ array)
            // create Request instance before pushing so we can return request
            // with its id
            var Request = mongoose.model("Request");
            var request = new Request({
                email: user.email,
                status: "pending"
            });
            request.getId(function(err) { // add numeric ID to request
                if (err) return callback(err);
                this.requested.push(request);

                // save both users
                user.markModified("requests");
                this.markModified("requested");
                async.parallel({
                    me: function(cb) {
                        this.save(cb);
                    }.bind(this),
                    other: function(cb) {
                        user.save(cb);
                    }
                }, function(err) {
                    if (err) return callback(err);

                    // if everything went successfully, send the user to whom the request
                    // was made a notification
                    // notify is asynchronous but we don't care about waiting for the result
                    user.notify({
                        template: "request_opened",
                        data: {
                            requestor: this,
                            requestee: user
                        }
                    });

                    callback(null, request);
                }.bind(this));
            }.bind(this));
        }.bind(this));
    };

    // cancel a pending request made by this user
    UserSchema.methods.cancelRequest = function(requestId, callback) {
        // try and find request in this user
        var requested = this.requested.id(requestId);
        if (!requested) return callback(errors.INVALID_REQUEST_ID);

        // find request in the other user
        this.constructor.findOne({
            email: requested.email
        }, function(err, user) {
            if (err) return callback(err);
            if (!user) return callback(errors.INVALID_REQUEST_ID); // should never occur

            var request = user.requests.filter(function(req) {
                return req.email === this.email;
            }.bind(this))[0];
            if (typeof request === "undefined" || request === null || requested.status !== "pending")
                return callback(errors.INVALID_REQUEST_ID); // should never occur

            // update both requests to change status
            request.status = "cancelled";
            requested.status = "cancelled";

            var _ = require("lodash");

            _.remove(this.requested, function(el) {
                console.log(">>> ", el.id,requestId);
                return el.id === requestId
            });

            _.remove(user.requests, function(el) {
                console.log("<<< ", el.id,request.id);
                return el.id === request.id
            });

            console.log(">>> ", this.requested);
            console.log("<<<", user.requests);
            console.log(">>> ", this);
            console.log("<<<", user);

            // save both users
            user.markModified("requests");
            this.markModified("requested");

            async.parallel({
                me: function(cb) {
                    console.log("save this", this);
                    this.save(cb);
                    console.log("save this done");
                }.bind(this),
                other: function(cb) {
                    console.log("save user", user);
                    user.save(cb);
                    console.log("save user done");
                }
            }, function(err) {
                console.log("ERR ",err);
                if (err) return callback(err);

                // if everything went successfully, send the user to whom the request was made
                // a notification (email or SMS) letting them know the request has been
                // cancelled
                // notify is asynchronous but we don't care about waiting for the result
                user.notify({
                    template: "request_cancelled",
                    data: {
                        requestor: this,
                        requestee: user
                    }
                });

                callback(null, null);
            }.bind(this));

        }.bind(this));

        console.log("cancel request done");
    };

    // close (either accepted or rejected) a pending request made *to* this user
    UserSchema.methods.closeRequest = function(requestId, status, callback) {
        // try and find request in this user
        var request = this.requests.id(requestId);
        if (!request) return callback(errors.INVALID_REQUEST_ID);

        // find request in the other user
        this.constructor.findOne({
            email: request.email
        }, function(err, user) {
            if (err) return callback(err);
            if (!user) return callback(errors.INVALID_REQUEST_ID); // should never occur

            var requested = user.requested.filter(function(req) {
                return req.email === this.email;
            }.bind(this))[0];
            if (typeof requested === "undefined" || requested === null || requested.status !== "pending")
                return callback(errors.INVALID_REQUEST_ID); // should never occur

            // update both requests
            request.status = status;
            requested.status = status;

            // save both users
            user.markModified("requests");
            this.markModified("requested");
            async.parallel({
                me: function(cb) {
                    this.save(cb);
                }.bind(this),
                other: function(cb) {
                    user.save(cb);
                }
            }, function(err) {
                if (err) return callback(err);

                // if everything went successfully, send the user that made the request a
                // notification (either email or SMS) letting them know the status
                // notify is asynchronous but we don't care about waiting for the result
                user.notify({
                    template: "request_closed",
                    data: {
                        requestor: user,
                        requestee: this,
                        action: status
                    }
                });

                callback(null, request);
            }.bind(this));

        }.bind(this));
    };
};
<commit_msg>Remove cancelled requests with native mongoose methods<commit_after>"use strict";
var async = require("async"),
    mongoose = require("mongoose"),
    errors = require("../../errors.js").ERRORS;

module.exports = function(UserSchema) {
    // request access to the data of another user
    UserSchema.methods.makeRequest = function(email, callback) {
        // check an email address has been specified
        if (typeof email === "undefined" || email === null || email.length === 0)
            return callback(errors.EMAIL_REQUIRED);

        // check we haven't already requested access from that user
        var existing = this.requested.filter(function(request) {
            return request.email === email;
        });
        if (existing.length > 0) return callback(errors.ALREADY_REQUESTED);

        // check we not requesting share with yourself
        if (email === this.email) return callback(errors.CANT_REQUEST_YOURSELF);

        // find the user the request is being made to
        this.constructor.findOne({
            email: email
        }, function(err, user) {
            if (err) return callback(err);
            if (!user) return callback(errors.INVALID_EMAIL); // no user found for that email

            // store request in that user (in _requests_ array)
            user.requests.push({
                email: this.email,
                status: "pending"
            });
            // and in this user (in _requested_ array)
            // create Request instance before pushing so we can return request
            // with its id
            var Request = mongoose.model("Request");
            var request = new Request({
                email: user.email,
                status: "pending"
            });
            request.getId(function(err) { // add numeric ID to request
                if (err) return callback(err);
                this.requested.push(request);

                // save both users
                user.markModified("requests");
                this.markModified("requested");
                async.parallel({
                    me: function(cb) {
                        this.save(cb);
                    }.bind(this),
                    other: function(cb) {
                        user.save(cb);
                    }
                }, function(err) {
                    if (err) return callback(err);

                    // if everything went successfully, send the user to whom the request
                    // was made a notification
                    // notify is asynchronous but we don't care about waiting for the result
                    user.notify({
                        template: "request_opened",
                        data: {
                            requestor: this,
                            requestee: user
                        }
                    });

                    callback(null, request);
                }.bind(this));
            }.bind(this));
        }.bind(this));
    };

    // cancel a pending request made by this user
    UserSchema.methods.cancelRequest = function(requestId, callback) {
        // try and find request in this user
        var requested = this.requested.id(requestId);
        if (!requested) return callback(errors.INVALID_REQUEST_ID);

        // find request in the other user
        this.constructor.findOne({
            email: requested.email
        }, function(err, user) {
            if (err) return callback(err);
            if (!user) return callback(errors.INVALID_REQUEST_ID); // should never occur

            var request = user.requests.filter(function(req) {
                return req.email === this.email;
            }.bind(this))[0];
            if (typeof request === "undefined" || request === null || requested.status !== "pending")
                return callback(errors.INVALID_REQUEST_ID); // should never occur

            // remove both requests
            request.remove();
            requested.remove();

            // save both users
            user.markModified("requests");
            this.markModified("requested");

            async.parallel({
                me: function(cb) {
                    this.save(cb);
                }.bind(this),
                other: function(cb) {
                    user.save(cb);
                }
            }, function(err) {
                if (err) return callback(err);

                // if everything went successfully, send the user to whom the request was made
                // a notification (email or SMS) letting them know the request has been
                // cancelled
                // notify is asynchronous but we don't care about waiting for the result
                user.notify({
                    template: "request_cancelled",
                    data: {
                        requestor: this,
                        requestee: user
                    }
                });

                callback(null, null);
            }.bind(this));

        }.bind(this));
    };

    // close (either accepted or rejected) a pending request made *to* this user
    UserSchema.methods.closeRequest = function(requestId, status, callback) {
        // try and find request in this user
        var request = this.requests.id(requestId);
        if (!request) return callback(errors.INVALID_REQUEST_ID);

        // find request in the other user
        this.constructor.findOne({
            email: request.email
        }, function(err, user) {
            if (err) return callback(err);
            if (!user) return callback(errors.INVALID_REQUEST_ID); // should never occur

            var requested = user.requested.filter(function(req) {
                return req.email === this.email;
            }.bind(this))[0];
            if (typeof requested === "undefined" || requested === null || requested.status !== "pending")
                return callback(errors.INVALID_REQUEST_ID); // should never occur

            // update both requests
            request.status = status;
            requested.status = status;

            // save both users
            user.markModified("requests");
            this.markModified("requested");
            async.parallel({
                me: function(cb) {
                    this.save(cb);
                }.bind(this),
                other: function(cb) {
                    user.save(cb);
                }
            }, function(err) {
                if (err) return callback(err);

                // if everything went successfully, send the user that made the request a
                // notification (either email or SMS) letting them know the status
                // notify is asynchronous but we don't care about waiting for the result
                user.notify({
                    template: "request_closed",
                    data: {
                        requestor: user,
                        requestee: this,
                        action: status
                    }
                });

                callback(null, request);
            }.bind(this));

        }.bind(this));
    };
};
<|endoftext|>


<commit_before>
var models = require('../')
  , async = require('async')

// done(err)
module.exports = {
  ensure: ensure,
  isNeeded: isNeeded,
  upgrade: upgrade
}

var upgrades = {
  0: require('./from0to1')
}

function ensure(version, done) {
  isNeeded(version, function (err, needed, oldv, newv, config) {
    if (err) return done(err)
    if (!needed) return done()
    if (process.env.STRIDER_DB_UPGRADE !== 'yes') {
      console.log("Your Strider database needs to be upgraded.")
      console.log("Please make sure you take a backup and then re-run with environment variable STRIDER_DB_UPGRADE=yes")
      process.exit(0)
    } else {
      console.log("STRIDER_DB_UPGRADE is set to yes")
      console.log('Updating database from version %d to %d', oldv, newv)
      upgrade(oldv, newv, function (err) {
        if (err) return done(err)
        config.save(done)
      })
    }
  })
}

function upgrade(oldv, newv, done) {
  var tasks = []
  for (var i=oldv; i<newv; i++) {
    tasks.push(upgrades[i])
  }
  async.series(tasks, done)
}

function isNeeded(version, done) {
  models.Config.find({}, function (err, configs) {
    if (err) return done(err)
    if (configs && configs.length > 1) {
      return done(new Error('Multiple `Config`s found in the database. Only one is allowed'))
    }
    var config
      , oldversion
    if (!configs || configs.length === 0) {
      config = new models.Config({version: 0})
    } else {
      config = configs[0]
    }
    if (config.version >= version) {
      return done(null, false)
    }
    oldversion = config.version
    config.version = version
    done(err, true, oldversion, version, config)
  })
}

<commit_msg>improve upgrade msg<commit_after>
var models = require('../')
  , async = require('async')

// done(err)
module.exports = {
  ensure: ensure,
  isNeeded: isNeeded,
  upgrade: upgrade
}

var upgrades = {
  0: require('./from0to1')
}

function ensure(version, done) {
  isNeeded(version, function (err, needed, oldv, newv, config) {
    if (err) return done(err)
    if (!needed) return done()
    if (process.env.STRIDER_DB_UPGRADE !== 'yes') {
      console.error("Your Strider database needs to be upgraded!\n")
      console.log("Please:")
      console.log("1) Backup your database")
      console.log("2) Re-run setting environment variable:\n")
      console.log("STRIDER_DB_UPGRADE=yes")
      console.log("e.g. $ env STRIDER_DB_UPGRADE=yes npm start")
      process.exit(0)
    } else {
      console.log("STRIDER_DB_UPGRADE is set to yes")
      console.log('Updating database from version %d to %d', oldv, newv)
      upgrade(oldv, newv, function (err) {
        if (err) return done(err)
        config.save(done)
      })
    }
  })
}

function upgrade(oldv, newv, done) {
  var tasks = []
  for (var i=oldv; i<newv; i++) {
    tasks.push(upgrades[i])
  }
  async.series(tasks, done)
}

function isNeeded(version, done) {
  models.Config.find({}, function (err, configs) {
    if (err) return done(err)
    if (configs && configs.length > 1) {
      return done(new Error('Multiple `Config`s found in the database. Only one is allowed'))
    }
    var config
      , oldversion
    if (!configs || configs.length === 0) {
      config = new models.Config({version: 0})
    } else {
      config = configs[0]
    }
    if (config.version >= version) {
      return done(null, false)
    }
    oldversion = config.version
    config.version = version
    done(err, true, oldversion, version, config)
  })
}

<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var expect  = require('expect.js');
var extend = require('extend');
var rimraf = require('rimraf');
var lockfile = require('../');

var lockfileContents = fs.readFileSync(__dirname + '/../index.js').toString();
var tmpFile = path.join(__dirname, 'tmp');

describe('.lock()', function () {
    beforeEach(function () {
        fs.writeFileSync(tmpFile, '');
        rimraf.sync(tmpFile + '_symlink');
    });

    afterEach(function (next) {
        rimraf.sync(tmpFile + '_symlink');

        if (!fs.existsSync(tmpFile + '.lock')) {
            return next();
        }

        lockfile.remove(tmpFile, next);
    });

    it('should fail if the file does not exist', function (next) {
        lockfile.lock('filethatwillneverexist', function (err) {
            expect(err).to.be.an(Error);
            expect(err.code).to.be('ENOENT');

            next();
        }, next);
    });

    it('should create the lock file', function (next) {
        lockfile.lock(tmpFile, function (err, unlock, lockfile) {
            expect(err).to.not.be.ok();
            expect(unlock).to.be.a('function');
            expect(lockfile).to.equal(tmpFile + '.lock');
            expect(fs.existsSync(tmpFile + '.lock')).to.be(true);

            next();
        }, next);
    });

    it('should fail if already locked', function (next) {
        lockfile.lock(tmpFile, function (err) {
            expect(err).to.not.be.ok();

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.be.an(Error);
                expect(err.code).to.be('ELOCK');
                expect(err.file).to.be(tmpFile);

                next();
            }, next);
        }, next);
    });

    it('should use the custom fs', function (next) {
        var customFs = extend({}, fs);

        customFs.realpath = function (path, callback) {
            customFs.realpath = fs.realpath;
            callback(new Error('foo'));
        };

        lockfile.lock(tmpFile, { fs: customFs }, function (err) {
            expect(err).to.be.an(Error);
            expect(err.message).to.be('foo');

            next();
        }, next);
    });

    it('should update the lock mtime automatically', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 5000 }, function (err, unlock, lockfile) {
            var mtime;

            expect(err).to.not.be.ok();

            setTimeout(function () {
                mtime = fs.statSync(lockfile).mtime;
            }, 1000);

            // First update occurs at 2500ms
            setTimeout(function () {
                var stat = fs.statSync(lockfile);
                expect(stat.mtime.getTime()).to.be.greaterThan(mtime.getTime());
                mtime = stat.mtime;
            }, 3000);

            // Second update occurs at 5000ms
            setTimeout(function () {
                var stat = fs.statSync(lockfile);
                expect(stat.mtime.getTime()).to.be.greaterThan(mtime.getTime());
                mtime = stat.mtime;

                next();
            }, 6000);
        }, next);
    });

    it('should call the compromised function if unable to update the lock mtime', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 5000 }, function (err, unlock, lockfile) {
            expect(err).to.not.be.ok();

            fs.unlinkSync(lockfile);
        }, function (err) {
            expect(err).to.be.an(Error);
            expect(err.code).to.be('ENOENT');
            expect(err.message).to.contain('utime');

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.not.be.ok();

                next();
            }, next);
        }, next);
    });

    it('should call the compromised function if the watcher notifies the lockfile was deleted', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 0, watch: true }, function (err, unlock, lockfile) {
            expect(err).to.not.be.ok();

            setTimeout(function () {
                fs.unlinkSync(lockfile);
            }, 2000);
        }, function (err) {
            expect(err).to.be.an(Error);
            expect(err.code).to.be('ENOENT');

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.not.be.ok();

                next();
            }, next);
        });
    });

    it('should resolve to a canonical path', function (next) {
        // Create a symlink to the tmp file
        fs.symlinkSync(tmpFile, tmpFile + '_symlink');

        lockfile.lock(tmpFile + '_symlink', function (err) {
            expect(err).to.not.be.ok();

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.be.an(Error);
                expect(err.code).to.be('ELOCK');

                next();
            }, next);
        }, next);
    });

    it('should release the lock after calling the provided unlock function', function (next) {
        lockfile.lock(tmpFile, function (err, unlock) {
            expect(err).to.not.be.ok();

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.be.an(Error);
                expect(err.code).to.be('ELOCK');

                unlock(function (err) {
                    expect(err).to.not.be.ok();

                    lockfile.lock(tmpFile, function (err) {
                        expect(err).to.not.be.ok();

                        next();
                    }, next);
                });
            }, next);
        }, next);
    });
});

describe('.remove()', function () {
    beforeEach(function () {
        fs.writeFileSync(tmpFile, '');
        rimraf.sync(tmpFile + '_symlink');
    });

    afterEach(function (next) {
        rimraf.sync(tmpFile + '_symlink');

        if (!fs.existsSync(tmpFile + '.lock')) {
            return next();
        }

        lockfile.remove(tmpFile, next);
    });

    it('should succeed if not locked', function (next) {
        lockfile.remove(tmpFile, function (err) {
            expect(err).to.not.be.ok();

            next();
        });
    });

    it('should remove the lock file', function (next) {
        fs.writeFileSync(tmpFile + '.lock', '');

        lockfile.remove(tmpFile, function (err) {
            expect(err).to.not.be.ok();
            expect(fs.existsSync(tmpFile + '.lock')).to.be(false);

            next();
        }, next);
    });

    it('should stop updating the lock file mtime', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 5000 }, function (err) {
            expect(err).to.not.be.ok();

            lockfile.remove(tmpFile, function (err) {
                expect(err).to.not.be.ok();

                // First update occurs at 2500ms
                setTimeout(next, 3000);
            }, next);
        }, next);
    });

    it('should stop updating the lock file mtime (slow fs)', function (next) {
        var customFs = extend({}, fs);

        customFs.utimes = function (path, atime, mtime, callback) {
            setTimeout(fs.utimes.bind(fs, path, atime, mtime, callback), 2000);
        };

        this.timeout(10000);

        lockfile.lock(tmpFile, { fs: customFs, stale: 5000 }, function (err) {
            expect(err).to.not.be.ok();

            setTimeout(function () {
                lockfile.remove(tmpFile, function (err) {
                    expect(err).to.not.be.ok();
                });
            }, 3000);

            setTimeout(next, 7000);
        }, next);
    });

    it('should stop updating the lock file mtime (slow fs + new lock)', function (next) {
        var customFs = extend({}, fs);

        customFs.utimes = function (path, atime, mtime, callback) {
            setTimeout(fs.utimes.bind(fs, path, atime, mtime, callback), 2000);
        };

        this.timeout(10000);

        lockfile.lock(tmpFile, { fs: customFs, stale: 5000 }, function (err) {
            expect(err).to.not.be.ok();

            setTimeout(function () {
                lockfile.remove(tmpFile, function (err) {
                    expect(err).to.not.be.ok();

                    lockfile.lock(tmpFile, function (err) {
                        expect(err).to.not.be.ok();
                    });
                });
            }, 3000);

            setTimeout(next, 7000);
        }, next);
    });

    it('should stop watching the lock file', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 0, watch: true }, function (err, unlock, lockfile) {
            expect(err).to.not.be.ok();

            fs.unlinkSync(lockfile);

            // Wait a bit
            setTimeout(next, 5000);
        }, next);
    });

    it('should resolve to a canonical path', function (next) {
        // Create a symlink to the tmp file
        fs.symlinkSync(tmpFile, tmpFile + '_symlink');

        fs.writeFileSync(tmpFile + '.lock', '');

        lockfile.remove(tmpFile, function (err) {
            expect(err).to.not.be.ok();
            expect(fs.existsSync(tmpFile + '.lock')).to.be(false);

            next();
        }, next);
    });

    it('should use the custom fs', function (next) {
        var customFs = extend({}, fs);

        customFs.realpath = function (path, callback) {
            customFs.realpath = fs.realpath;
            callback(new Error('foo'));
        };

        lockfile.remove(tmpFile, { fs: customFs }, function (err) {
            expect(err).to.be.an(Error);
            expect(err.message).to.be('foo');

            next();
        }, next);
    });
});

describe('misc', function () {
    it('should not contain suspicious nodejs native fs calls', function () {
        expect(/\s+fs\.[a-z]+/i.test(lockfileContents)).to.be(false);
    });

    it('should work on stress conditions');
});
<commit_msg>Add more tests (pending).<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var expect  = require('expect.js');
var extend = require('extend');
var rimraf = require('rimraf');
var lockfile = require('../');

var lockfileContents = fs.readFileSync(__dirname + '/../index.js').toString();
var tmpFile = path.join(__dirname, 'tmp');

describe('.lock()', function () {
    beforeEach(function () {
        fs.writeFileSync(tmpFile, '');
        rimraf.sync(tmpFile + '_symlink');
    });

    afterEach(function (next) {
        rimraf.sync(tmpFile + '_symlink');

        if (!fs.existsSync(tmpFile + '.lock')) {
            return next();
        }

        lockfile.remove(tmpFile, next);
    });

    it('should fail if the file does not exist', function (next) {
        lockfile.lock('filethatwillneverexist', function (err) {
            expect(err).to.be.an(Error);
            expect(err.code).to.be('ENOENT');

            next();
        }, next);
    });

    it('should create the lock file', function (next) {
        lockfile.lock(tmpFile, function (err, unlock, lockfile) {
            expect(err).to.not.be.ok();
            expect(unlock).to.be.a('function');
            expect(lockfile).to.equal(tmpFile + '.lock');
            expect(fs.existsSync(tmpFile + '.lock')).to.be(true);

            next();
        }, next);
    });

    it('should fail if already locked', function (next) {
        lockfile.lock(tmpFile, function (err) {
            expect(err).to.not.be.ok();

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.be.an(Error);
                expect(err.code).to.be('ELOCK');
                expect(err.file).to.be(tmpFile);

                next();
            }, next);
        }, next);
    });

    it('should use the custom fs', function (next) {
        var customFs = extend({}, fs);

        customFs.realpath = function (path, callback) {
            customFs.realpath = fs.realpath;
            callback(new Error('foo'));
        };

        lockfile.lock(tmpFile, { fs: customFs }, function (err) {
            expect(err).to.be.an(Error);
            expect(err.message).to.be('foo');

            next();
        }, next);
    });

    it('should pass over stale locks');

    it('should update the lock mtime automatically', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 5000 }, function (err, unlock, lockfile) {
            var mtime;

            expect(err).to.not.be.ok();

            setTimeout(function () {
                mtime = fs.statSync(lockfile).mtime;
            }, 1000);

            // First update occurs at 2500ms
            setTimeout(function () {
                var stat = fs.statSync(lockfile);
                expect(stat.mtime.getTime()).to.be.greaterThan(mtime.getTime());
                mtime = stat.mtime;
            }, 3000);

            // Second update occurs at 5000ms
            setTimeout(function () {
                var stat = fs.statSync(lockfile);
                expect(stat.mtime.getTime()).to.be.greaterThan(mtime.getTime());
                mtime = stat.mtime;

                next();
            }, 6000);
        }, next);
    });

    it('should call the compromised function if unable to update the lock mtime', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 5000 }, function (err, unlock, lockfile) {
            expect(err).to.not.be.ok();

            fs.unlinkSync(lockfile);
        }, function (err) {
            expect(err).to.be.an(Error);
            expect(err.code).to.be('ENOENT');
            expect(err.message).to.contain('utime');

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.not.be.ok();

                next();
            }, next);
        }, next);
    });

    it('should call the compromised function if the watcher notifies the lockfile was deleted', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 0, watch: true }, function (err, unlock, lockfile) {
            expect(err).to.not.be.ok();

            setTimeout(function () {
                fs.unlinkSync(lockfile);
            }, 2000);
        }, function (err) {
            expect(err).to.be.an(Error);
            expect(err.code).to.be('ENOENT');

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.not.be.ok();

                next();
            }, next);
        });
    });

    it('should resolve to a canonical path', function (next) {
        // Create a symlink to the tmp file
        fs.symlinkSync(tmpFile, tmpFile + '_symlink');

        lockfile.lock(tmpFile + '_symlink', function (err) {
            expect(err).to.not.be.ok();

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.be.an(Error);
                expect(err.code).to.be('ELOCK');

                next();
            }, next);
        }, next);
    });

    it('should release the lock after calling the provided unlock function', function (next) {
        lockfile.lock(tmpFile, function (err, unlock) {
            expect(err).to.not.be.ok();

            lockfile.lock(tmpFile, function (err) {
                expect(err).to.be.an(Error);
                expect(err.code).to.be('ELOCK');

                unlock(function (err) {
                    expect(err).to.not.be.ok();

                    lockfile.lock(tmpFile, function (err) {
                        expect(err).to.not.be.ok();

                        next();
                    }, next);
                });
            }, next);
        }, next);
    });
});

describe('.remove()', function () {
    beforeEach(function () {
        fs.writeFileSync(tmpFile, '');
        rimraf.sync(tmpFile + '_symlink');
    });

    afterEach(function (next) {
        rimraf.sync(tmpFile + '_symlink');

        if (!fs.existsSync(tmpFile + '.lock')) {
            return next();
        }

        lockfile.remove(tmpFile, next);
    });

    it('should succeed if not locked', function (next) {
        lockfile.remove(tmpFile, function (err) {
            expect(err).to.not.be.ok();

            next();
        });
    });

    it('should remove the lock file', function (next) {
        fs.writeFileSync(tmpFile + '.lock', '');

        lockfile.remove(tmpFile, function (err) {
            expect(err).to.not.be.ok();
            expect(fs.existsSync(tmpFile + '.lock')).to.be(false);

            next();
        }, next);
    });

    it('should stop updating the lock file mtime', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 5000 }, function (err) {
            expect(err).to.not.be.ok();

            lockfile.remove(tmpFile, function (err) {
                expect(err).to.not.be.ok();

                // First update occurs at 2500ms
                setTimeout(next, 3000);
            }, next);
        }, next);
    });

    it('should stop updating the lock file mtime (slow fs)', function (next) {
        var customFs = extend({}, fs);

        customFs.utimes = function (path, atime, mtime, callback) {
            setTimeout(fs.utimes.bind(fs, path, atime, mtime, callback), 2000);
        };

        this.timeout(10000);

        lockfile.lock(tmpFile, { fs: customFs, stale: 5000 }, function (err) {
            expect(err).to.not.be.ok();

            setTimeout(function () {
                lockfile.remove(tmpFile, function (err) {
                    expect(err).to.not.be.ok();
                });
            }, 3000);

            setTimeout(next, 7000);
        }, next);
    });

    it('should stop updating the lock file mtime (slow fs + new lock)', function (next) {
        var customFs = extend({}, fs);

        customFs.utimes = function (path, atime, mtime, callback) {
            setTimeout(fs.utimes.bind(fs, path, atime, mtime, callback), 2000);
        };

        this.timeout(10000);

        lockfile.lock(tmpFile, { fs: customFs, stale: 5000 }, function (err) {
            expect(err).to.not.be.ok();

            setTimeout(function () {
                lockfile.remove(tmpFile, function (err) {
                    expect(err).to.not.be.ok();

                    lockfile.lock(tmpFile, function (err) {
                        expect(err).to.not.be.ok();
                    });
                });
            }, 3000);

            setTimeout(next, 7000);
        }, next);
    });

    it('should stop watching the lock file', function (next) {
        this.timeout(10000);

        lockfile.lock(tmpFile, { stale: 0, watch: true }, function (err, unlock, lockfile) {
            expect(err).to.not.be.ok();

            fs.unlinkSync(lockfile);

            // Wait a bit
            setTimeout(next, 5000);
        }, next);
    });

    it('should resolve to a canonical path', function (next) {
        // Create a symlink to the tmp file
        fs.symlinkSync(tmpFile, tmpFile + '_symlink');

        fs.writeFileSync(tmpFile + '.lock', '');

        lockfile.remove(tmpFile, function (err) {
            expect(err).to.not.be.ok();
            expect(fs.existsSync(tmpFile + '.lock')).to.be(false);

            next();
        }, next);
    });

    it('should use the custom fs', function (next) {
        var customFs = extend({}, fs);

        customFs.realpath = function (path, callback) {
            customFs.realpath = fs.realpath;
            callback(new Error('foo'));
        };

        lockfile.remove(tmpFile, { fs: customFs }, function (err) {
            expect(err).to.be.an(Error);
            expect(err.message).to.be('foo');

            next();
        }, next);
    });
});

describe('misc', function () {
    it('should not contain suspicious nodejs native fs calls', function () {
        expect(/\s+fs\.[a-z]+/i.test(lockfileContents)).to.be(false);
    });

    it('should remove open locks if the process crashes');

    it('should work on stress conditions');
});
<|endoftext|>


<commit_before>'use strict';

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

var expected = "['ha', 'ha', 'ha'];"; // jshint ignore: line

describe('broccoli-livescript', function() {
  it('should compile LiveScript to JavaScript', function(done) {
    fs.readFile('test/actual/simple.js', function(err, data) {
      if (err) done(err);
      assert.strictEqual(data.toString(), expected);
      done();
    });
  });
});
<commit_msg>return immediately if file reading failed<commit_after>'use strict';

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

var expected = "['ha', 'ha', 'ha'];"; // jshint ignore: line

describe('broccoli-livescript', function() {
  it('should compile LiveScript to JavaScript', function(done) {
    fs.readFile('test/actual/simple.js', function(err, data) {
      if (err) {
        done(err);
        return;
      }
      assert.strictEqual(data.toString(), expected);
      done();
    });
  });
});
<|endoftext|>


<commit_before>Mutil.modules = Mutil.modules || {};
if(!Mutil.modules.events) {
    /**
     * Provide helper functions and a unified API interface for browser event
     * handling.
     *
     * @todo add proper documentation
     */
    Mutil.modules.events = function(app) {
        /**
         * Simple wrapper around native events that is branched at init-time
         * to provide a unified API to different browser implementations of
         * events.
         *
         * @constructor
         * @todo test the implementation details and branching.
         * @param <Event> e native browser event, if available (defaults to
         *   #window.event, which IE uses)
         * @return <Mutil.Event> wrapped event.
         */
        Mutil.Event = function(e) {

            this.original_event = e || window.event;
            this.target = e.target || e.srcElement;

            return {
                target: this.target,

                /**
                 * Stop event propagation.
                 */
                stopPropagation: (function() {
                    if(e.stopPropagation) {
                        return function() { e.stopPropagation(); };
                    } else {
                        return function() { e.cancelBubble = true; };
                    }
                }))(),

                /**
                 * Prevent the default event behaviour.
                 */
                preventDefault: (function() {
                    if(e.preventDefault) {
                        return function() { e.preventDefault(); };
                    } else {
                        return function() { e.returnValue = false; };
                    }
                })(),

                /**
                 * Shortcut to both stop propagation and prevent default
                 * action for an event.
                 */
                halt: function() {
                    this.stopPropagation();
                    this.preventDefault();
                }
            };
        };

        /**
         * Helper function for #bind that is branched at init-time for adding
         * event listeners to an object.
         *
         * It uses #addEventListener when available, falls back to IE-specific
         * #attachEvent and as a last resort uses a raw on[event] property.
         *
         * @param <Node> element is the DOM node to watch.
         * @param <String> event_name is the event to act on.
         * @param <Function> fn is the callback function to fire on trigger.
         */
        var bindEvent = (function() {
            if(document.addEventListener) {
                return function(element, event_name, fn) {
                    element.addEventListener(event_name, fn);
                };
            } else if(document.attachEvent) {
                return function(element, event_name, fn) {
                    element.attachEvent(event_name, fn);
                };
            } else {
                return function(el, name) {
                    el['on' + name] = fn;
                };
            }
        })();

        /**
         * Bind a callback function to an event on an element.
         *
         * @param <Node> element is the DOM node to watch.
         * @param <String> event_name is the event to act on.
         * @param <Function> fn is the callback function to fire on trigger.
         */
        app.bind = function(element, event_name, fn) {
            if(!element.isElement()) {
                throw new Mutil.Error('Events can only be bound to DOM elements.');
            }
            if(!event_name.isString()) {
                throw new Mutil.Error('Specify an event name to listen to as a string.');
            }
            if(!fn.isFunction()) {
                throw new Mutil.Error('Specify a valid callback function to bind to the event.');
            }
            bindEvent(element, event_name, fn);
        };

        /**
         * Use event delegation on a root element, using a selector to filter
         * desired child nodes to handle the event on.
         *
         * This relieves regular callback functions from filtering out
         * unwanted child nodes that trigger the event.
         *
         * @example Use event delegation to catch clicks on a menu
         * bindDelegator(
         *   document.getElementsByTagName('nav')[0],
         *   'li > a',
         *   'click',
         *   function() {
         *     console.log("Menu item was clicked");
         *   }
         * )
         *
         * @param <Node> element is the DOM root to watch. All its children
         *   will trigger the event.
         * @param <String> selector is a selector string specifying to which
         *   child nodes of element the callback function will be applied.
         * @param <String> event_name is the event to watch.
         * @param <Function> fn is the callback function to fire on the event.
         */
        app.bindDelegator = function(element, selector, event_name, fn) {
            app.bind(element, event_name, delegatedCallback(selector, fn));
        }

        /**
         * Helper function to create a callback that is only fired when the
         * target of an incoming event matches a selector.
         *
         * @param <String> selector to determine wither the event target
         *   qualifies for the callback.
         * @param <Function> fn is the original callback function to fire.
         */
        function delegatedCallback(selector, fn) {
            return function(e) {}
                if(app.Query.matches(e.target, selector)) {
                    fn(e);
                }
            };
        }

        /**
         * Trigger an event on an element.
         *
         * @param <Node> element is the DOM element to use
         * @param <String> event_name is the name of the event to fire.
         */
        app.trigger = function(element, event_name) {
            if(element[event_name] && element[event_name].isFunction()) {
                element[event_name]();
            }
        };

        // todo: implement decorating like this
        // This should add a method to the sandbox Collection 'class' to
        // quickly bind an event to all elements in the collection.
        app.Collection.prototype.bind = function() {
            this.forEach(function() {
                app.bind.apply(this, arguments.toArray());
            });
            return this;
        };

        // todo: implement decorating like this
        // This should add a method to the sandbox Collection 'class' to
        // quickly bind an event to all elements in the collection.
        app.Collection.prototype.bindDelegator = function() {
            this.forEach(function() {
                app.bindDelegator.apply(this, arguments.toArray());
            });
            return this;
        };
    };
}
<commit_msg>few minor bug fixes<commit_after>Mutil.modules = Mutil.modules || {};
if(!Mutil.modules.events) {
    /**
     * Provide helper functions and a unified API interface for browser event
     * handling.
     *
     * @todo add proper documentation
     */
    Mutil.modules.events = function(app) {
        /**
         * Simple wrapper around native events that is branched at init-time
         * to provide a unified API to different browser implementations of
         * events.
         *
         * @constructor
         * @todo test the implementation details and branching.
         * @param <Event> e native browser event, if available (defaults to
         *   #window.event, which IE uses)
         * @return <Mutil.Event> wrapped event.
         */
        app.Event = function(e) {

            this.original_event = e || window.event;
            this.target = e.target || e.srcElement;

            return {
                target: this.target,

                /**
                 * Stop event propagation.
                 */
                stopPropagation: (function() {
                    if(e.stopPropagation) {
                        return function() { e.stopPropagation(); };
                    } else {
                        return function() { e.cancelBubble = true; };
                    }
                })(),

                /**
                 * Prevent the default event behaviour.
                 */
                preventDefault: (function() {
                    if(e.preventDefault) {
                        return function() { e.preventDefault(); };
                    } else {
                        return function() { e.returnValue = false; };
                    }
                })(),

                /**
                 * Shortcut to both stop propagation and prevent default
                 * action for an event.
                 */
                halt: function() {
                    this.stopPropagation();
                    this.preventDefault();
                }
            };
        };

        /**
         * Helper function for #bind that is branched at init-time for adding
         * event listeners to an object.
         *
         * It uses #addEventListener when available, falls back to IE-specific
         * #attachEvent and as a last resort uses a raw on[event] property.
         *
         * @param <Node> element is the DOM node to watch.
         * @param <String> event_name is the event to act on.
         * @param <Function> fn is the callback function to fire on trigger.
         */
        var bindEvent = (function() {
            if(document.addEventListener) {
                return function(element, event_name, fn) {
                    element.addEventListener(event_name, fn);
                };
            } else if(document.attachEvent) {
                return function(element, event_name, fn) {
                    element.attachEvent(event_name, fn);
                };
            } else {
                return function(el, name) {
                    el['on' + name] = fn;
                };
            }
        })();

        /**
         * Bind a callback function to an event on an element.
         *
         * @param <Node> element is the DOM node to watch.
         * @param <String> event_name is the event to act on.
         * @param <Function> fn is the callback function to fire on trigger.
         */
        app.bind = function(element, event_name, fn) {
            if(!element.isElement()) {
                throw new Mutil.Error('Events can only be bound to DOM elements.');
            }
            if(!event_name.isString()) {
                throw new Mutil.Error('Specify an event name to listen to as a string.');
            }
            if(!fn.isFunction()) {
                throw new Mutil.Error('Specify a valid callback function to bind to the event.');
            }
            bindEvent(element, event_name, function(e) {
                return fn(new app.Event(e));
            });
        };

        /**
         * Use event delegation on a root element, using a selector to filter
         * desired child nodes to handle the event on.
         *
         * This relieves regular callback functions from filtering out
         * unwanted child nodes that trigger the event.
         *
         * @example Use event delegation to catch clicks on a menu
         * bindDelegator(
         *   document.getElementsByTagName('nav')[0],
         *   'li > a',
         *   'click',
         *   function() {
         *     console.log("Menu item was clicked");
         *   }
         * )
         *
         * @param <Node> element is the DOM root to watch. All its children
         *   will trigger the event.
         * @param <String> selector is a selector string specifying to which
         *   child nodes of element the callback function will be applied.
         * @param <String> event_name is the event to watch.
         * @param <Function> fn is the callback function to fire on the event.
         */
        app.bindDelegator = function(element, selector, event_name, fn) {
            app.bind(element, event_name, delegatedCallback(selector, fn));
        };

        /**
         * Helper function to create a callback that is only fired when the
         * target of an incoming event matches a selector.
         *
         * @param <String> selector to determine wither the event target
         *   qualifies for the callback.
         * @param <Function> fn is the original callback function to fire.
         */
        function delegatedCallback(selector, fn) {
            return function(e) {
                if(app.Query.matches(e.target, selector)) {
                    fn(e);
                }
            };
        }

        /**
         * Trigger an event on an element.
         *
         * @param <Node> element is the DOM element to use
         * @param <String> event_name is the name of the event to fire.
         */
        app.trigger = function(element, event_name) {
            if(element[event_name] && element[event_name].isFunction()) {
                element[event_name]();
            }
        };

        // todo: implement decorating like this
        // This should add a method to the sandbox Collection 'class' to
        // quickly bind an event to all elements in the collection.
        app.Collection.prototype.bind = function() {
            this.forEach(function() {
                app.bind.apply(this, arguments.toArray());
            });
            return this;
        };

        // todo: implement decorating like this
        // This should add a method to the sandbox Collection 'class' to
        // quickly bind an event to all elements in the collection.
        app.Collection.prototype.bindDelegator = function() {
            this.forEach(function() {
                app.bindDelegator.apply(this, arguments.toArray());
            });
            return this;
        };
    };
}
<|endoftext|>


<commit_before>/**
 * Patterns autoscale - scale elements to fit available space
 *
 * Copyright 2012 Humberto Sermeno
 * Copyright 2013 Simplon B.V. - Simplon B.V. - Wichert Akkerman
 */
define([
    "jquery",
    "../registry",
    "../core/parser"
], function($, registry, Parser) {
    var parser = new Parser("auto-scale");
    parser.add_argument("method", "scale", ["scale", "zoom"]);
    parser.add_argument("min-width", 0);
    parser.add_argument("max-width", 1000000);

    var _ = {
        name: "autoscale",
        trigger: ".pat-auto-scale",
        force_method: null,

        _setup: function() {
            if ($.browser.mozilla)
                _.force_method="scale";
            else if ($.browser.msie && parseInt($.browser.version, 10)<10)
                _.force_method="zoom";
            $(window).on("resize.autoscale", _.onResize);
        },

        init: function($el, opts) {
            return $el.each(function() {
                var $el = $(this),
                    options = parser.parse($el, opts);

                if (_.force_method!==null)
                    options.method=_.force_method;

                $el.data("patterns.auto-scale", options);
                _.scale.apply(this, []);
            });
        },

        scale: function() {
            var $el = $(this),
                options = $el.data("patterns.auto-scale"),
                available_space, scale;

            if ($el[0].tagName.toLowerCase()==="body")
                available_space=$(window).width();
            else
                available_space=$el.parent().outerWidth();

            available_space=Math.min(available_space, options.maxWidth);
            available_space=Math.max(available_space, options.minWidth);
            scale=available_space/$el.outerWidth();

            switch (options.method) {
            case "scale":
                $el.css("transform", "scale(" + scale + ")");
                break;
            case "zoom":
                $el.css("zoom", scale);
                break;
            }
            $el.addClass("scaled");
        },

        onResize: function() {
            $(_.trigger).each(_.scale);
        }
    };

    _._setup();
    registry.register(_);
    return _;
});
<commit_msg>Setup resize event after dom ist loaded, debounce.<commit_after>/**
 * Patterns autoscale - scale elements to fit available space
 *
 * Copyright 2012 Humberto Sermeno
 * Copyright 2013 Simplon B.V. - Simplon B.V. - Wichert Akkerman
 */
define([
    "jquery",
    "../registry",
    "../core/parser"
], function($, registry, Parser) {
    var parser = new Parser("auto-scale");
    parser.add_argument("method", "scale", ["scale", "zoom"]);
    parser.add_argument("min-width", 0);
    parser.add_argument("max-width", 1000000);

    var _ = {
        name: "autoscale",
        trigger: ".pat-auto-scale",
        force_method: null,

        _setup: function() {
            if ($.browser.mozilla)
                _.force_method="scale";
            else if ($.browser.msie && parseInt($.browser.version, 10)<10)
                _.force_method="zoom";
            $(document).ready(function() {
                $(window).one("resize.autoscale", _.onResize);
            });
        },

        init: function($el, opts) {
            return $el.each(function() {
                var $el = $(this),
                    options = parser.parse($el, opts);

                if (_.force_method!==null)
                    options.method=_.force_method;

                $el.data("patterns.auto-scale", options);
                _.scale.apply(this, []);
            });
        },

        scale: function() {
            var $el = $(this),
                options = $el.data("patterns.auto-scale"),
                available_space, scale;

            if ($el[0].tagName.toLowerCase()==="body")
                available_space=$(window).width();
            else
                available_space=$el.parent().outerWidth();

            available_space=Math.min(available_space, options.maxWidth);
            available_space=Math.max(available_space, options.minWidth);
            scale=available_space/$el.outerWidth();

            switch (options.method) {
            case "scale":
                $el.css("transform", "scale(" + scale + ")");
                break;
            case "zoom":
                $el.css("zoom", scale);
                break;
            }
            $el.addClass("scaled");
        },

        onResize: function() {
            $(_.trigger).each(_.scale);

            // necassary at least for IE8
            setTimeout(function() {
                $(window).one("resize.autoscale", _.onResize);
            }, 100);
        }
    };

    _._setup();
    registry.register(_);
    return _;
});
<|endoftext|>


<commit_before>function refresh() {
  var list = $('.tasks');
  var template = $('#task-tpl').html();
  $.getJSON('/tasks', function(tasks, status, xhr) {

    if(status = 'success') {
      list.empty();
    }

    $.each(tasks, function(index, task) {
      output = Mustache.render(template, {
        task: {
          id: task._id,
          description: task.description,
          done: task.done,
          class: task.done ? 'done' : 'undone',
          checkbox_attributes: task.done ? 'checked' : ''
        }
      });
      list.append(output);
    });
    list.removeClass('loading');
  });
}

$(function() {

  var errorCallback = function() {
    alert('Something went wrong!');
  }

  refresh();

  $('.list').on('change', '.task .checkbox', function() {
    var id = $(this).parent().data('id');
    $.ajax('/task/update', {
      type: 'POST',
      data: {
        id: id,
        task: {
          done: this.checked
        }
      }
    }).fail(errorCallback).always(refresh);
  });

  $('.list').on('click', '.task .delete', function() {
    var id = $(this).parent().data('id');
    $.ajax('/task/'+ id, {
      type: 'DELETE'
    }).fail(errorCallback).always(refresh);
  });

  $('#new-task').on('keydown', function(e) {
    if(e.keyCode == 13) {
      $.post('/task/new', {
        task: {
          description: this.value,
          done: false
        }
      }).fail(errorCallback).always(refresh);
      this.value = '';
    }
  });

});<commit_msg>Added double-click to mark task as done<commit_after>function refresh() {
  var list = $('.tasks');
  var template = $('#task-tpl').html();
  $.getJSON('/tasks', function(tasks, status, xhr) {

    if(status = 'success') {
      list.empty();
    }

    $.each(tasks, function(index, task) {
      output = Mustache.render(template, {
        task: {
          id: task._id,
          description: task.description,
          done: task.done,
          class: task.done ? 'done' : 'undone',
          checkbox_attributes: task.done ? 'checked' : ''
        }
      });
      list.append(output);
    });
    list.removeClass('loading');
  });
}

$(function() {

  var errorCallback = function() {
    alert('Something went wrong!');
  }

  var update = function(id, checked) {
    alert(id);
    alert(checked);
    $.ajax('/task/update', {
      type: 'POST',
      data: {
        id: id,
        task: {
          done: checked
        }
      }
    }).fail(errorCallback).always(refresh);
  }

  refresh();

  $('.list').on('change', '.task .checkbox', function() {
    var id = $(this).parent().data('id');
    var checked = this.checked;
    update(id, checked);
  });

  $('.list').on('dblclick', '.task', function() {
    var id = $(this).data('id');
    var checkbox = $(this).find('.checkbox')[0];
    update(id, !checkbox.checked);
  });

  $('.list').on('click', '.task .delete', function() {
    var id = $(this).parent().data('id');
    $.ajax('/task/'+ id, {
      type: 'DELETE'
    }).fail(errorCallback).always(refresh);
  });

  $('#new-task').on('keydown', function(e) {
    if(e.keyCode == 13) {
      $.post('/task/new', {
        task: {
          description: this.value,
          done: false
        }
      }).fail(errorCallback).always(refresh);
      this.value = '';
    }
  });

});<|endoftext|>


<commit_before>var listUnknownOpenPorts = function (scope, outputFormat) {
    // Prints a list of all "unknown" open ports for each host
    // to prepare for additional efforts to identify services
    //
    // Usage: listUnknownOpenPorts(searchScope, outputFormat)
    // Example: listUnknownOpenPorts('both', 'nmap')
    //    searchScope:
    //      product (search the "product" field)
    //      service (search the "service" field)
    //      both
    //    outputFormat:
    //      list (list of hosts followed by list of all unknown ports)
    //      nmap (individual host nmap cmdline with per-host ports)
    //
    // Created by: Alain Iamburg

    var PROJECT_ID = Session.get('projectId');
    var hostlist = [];
    var tcpports = [];
    var udpports = [];

    // FOR each port of each host
    var hosts = Hosts.find({
        "project_id": PROJECT_ID
    }).fetch();
    hosts.forEach(function (host) {
        var ports = Ports.find({
            "project_id": PROJECT_ID,
            "host_id": host._id
        }).fetch();
        ports.forEach(function (port) {
            if (port.port > 0) {
                if (scope === "product") {
                    if (port.product === "unknown") {
                        hostlist.push(host.string_addr);
                        if (port.protocol === "tcp") {
                            tcpports.push(port.port);
                        } else if (port.protocol === "udp") {
                            udpports.push(port.port);
                        }
                    }
                } else if (scope === "service") {
                    if (port.service === "unknown") {
                        hostlist.push(host.string_addr);
                        if (port.protocol === "tcp") {
                            tcpports.push(port.port);
                        } else if (port.protocol === "udp") {
                            udpports.push(port.port);
                        }
                    }
                } else if (scope === "both") {
                    if (port.service === "unknown" || port.product === "unknown") {
                        hostlist.push(host.string_addr);
                        if (port.protocol === "tcp") {
                            tcpports.push(port.port);
                        } else if (port.protocol === "udp") {
                            udpports.push(port.port);
                        }
                    }
                }
            }
        });

        // Output nmap command line format for each host and its unknown open ports
        if (outputFormat === "nmap") {
            if (tcpports.length > 0 && udpports.length > 0) {
                console.log("nmap -v -sV --version-all -sS -sU " + host.string_addr + " -p T:" + tcpports.toString() + ",U:" + udpports.toString());
            } else if (tcpports.length > 0) {
                console.log("nmap -v -sV --version-all -sS " + host.string_addr + " -p " + tcpports.toString());
            } else if (udpports.length > 0) {
                console.log("nmap -v -sV --version-all -sU " + host.string_addr + " -p " + udpports.toString());
            }
            tcpports = [];
            udpports = [];
        }

    });

    if ((tcpports.length > 0 || udpports.length > 0) && outputFormat === "list") {
        tcpportsUniq = tcpports.filter(function (elem, pos) {
            return tcpports.indexOf(elem) == pos;
        })
        udpportsUniq = udpports.filter(function (elem, pos) {
            return udpports.indexOf(elem) == pos;
        })

        // Output a list of all hosts and unknown open TCP/UDP ports
        console.log("Hosts:");
        console.log(hostlist.toString());
        console.log("TCP Ports:");
        console.log(tcpportsUniq.sort(function (a, b) {
            return a - b
        }).toString());
        console.log("UDP Ports:");
        console.log(udpportsUniq.sort(function (a, b) {
            return a - b
        }).toString());
    }
}<commit_msg>minor cleanup<commit_after>var listUnknownOpenPorts = function (scope, outputFormat) {
    // Prints a list of all 'unknown' open ports for each host
    // to prepare for additional efforts to identify services
    //
    // Usage: listUnknownOpenPorts(searchScope, outputFormat)
    // Example: listUnknownOpenPorts('both', 'nmap')
    //    searchScope:
    //      product (search the 'product' field)
    //      service (search the 'service' field)
    //      both
    //    outputFormat:
    //      list (list of hosts followed by list of all unknown ports)
    //      nmap (individual host nmap cmdline with per-host ports)
    //
    // Created by: Alain Iamburg

    var PROJECT_ID = Session.get('projectId');
    var hostlist = [];
    var tcpports = [];
    var udpports = [];

    // FOR each port of each host
    var hosts = Hosts.find({
        'project_id': PROJECT_ID
    }).fetch();
    hosts.forEach(function (host) {
        var ports = Ports.find({
            'project_id': PROJECT_ID,
            'host_id': host._id
        }).fetch();
        ports.forEach(function (port) {
            if (port.port > 0) {
                if (scope === 'product') {
                    if (port.product === 'unknown') {
                        hostlist.push(host.string_addr);
                        if (port.protocol === 'tcp') {
                            tcpports.push(port.port);
                        } else if (port.protocol === 'udp') {
                            udpports.push(port.port);
                        }
                    }
                } else if (scope === 'service') {
                    if (port.service === 'unknown') {
                        hostlist.push(host.string_addr);
                        if (port.protocol === 'tcp') {
                            tcpports.push(port.port);
                        } else if (port.protocol === 'udp') {
                            udpports.push(port.port);
                        }
                    }
                } else if (scope === 'both') {
                    if (port.service === 'unknown' || port.product === 'unknown') {
                        hostlist.push(host.string_addr);
                        if (port.protocol === 'tcp') {
                            tcpports.push(port.port);
                        } else if (port.protocol === 'udp') {
                            udpports.push(port.port);
                        }
                    }
                }
            }
        });

        // Output nmap command line format for each host and its unknown open ports
        if (outputFormat === 'nmap') {
            if (tcpports.length > 0 && udpports.length > 0) {
                console.log('nmap -v -sV --version-all -sS -sU ' + host.string_addr + ' -p T:' + tcpports.toString() + ',U:' + udpports.toString());
            } else if (tcpports.length > 0) {
                console.log('nmap -v -sV --version-all -sS ' + host.string_addr + ' -p ' + tcpports.toString());
            } else if (udpports.length > 0) {
                console.log('nmap -v -sV --version-all -sU ' + host.string_addr + ' -p ' + udpports.toString());
            }
            tcpports = [];
            udpports = [];
        }

    });

    if ((tcpports.length > 0 || udpports.length > 0) && outputFormat === 'list') {
        tcpportsUniq = tcpports.filter(function (elem, pos) {
            return tcpports.indexOf(elem) == pos;
        });
        udpportsUniq = udpports.filter(function (elem, pos) {
            return udpports.indexOf(elem) == pos;
        });

        // Output a list of all hosts and unknown open TCP/UDP ports
        console.log('Hosts:');
        console.log(hostlist.toString());
        console.log('TCP Ports:');
        console.log(tcpportsUniq.sort(function (a, b) {
            return a - b
        }).toString());
        console.log('UDP Ports:');
        console.log(udpportsUniq.sort(function (a, b) {
            return a - b
        }).toString());
    }
};<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2018, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var expect = require('chai').expect;
var Config = require('../.').Config;
var Controller = require('./RC');
var HazelcastClient = require('../.').Client;
var Promise = require('bluebird');

var dummyConfig = new Config.ClientConfig();
dummyConfig.networkConfig.smartRouting = false;

var smartConfig = new Config.ClientConfig();
smartConfig.networkConfig.smartRouting = true;

var configParams = [
    dummyConfig,
    smartConfig
];

function ManagedObjects() {
    this.managedObjects = [];
}

ManagedObjects.prototype.getObject = function (func, name) {
    var obj = func(name);
    this.managedObjects.push(obj);
    return obj;
};

ManagedObjects.prototype.destroyAll = function () {
    this.managedObjects.forEach(function (obj) {
        obj.destroy();
    });
};

ManagedObjects.prototype.destroy = function (name) {
    this.managedObjects.filter((el) => {
        if (el.getName() == name) {
            el.destroy();
            return false;
        }
        return true;
    });
};

configParams.forEach(function (cfg) {
    describe('HazelcastClient', function () {
        this.timeout(4000);
        var cluster;
        var client;
        var managed;

        before(function () {
            return Controller.createCluster(null, null).then(function (res) {
                cluster = res;
                return Controller.startMember(cluster.id);
            }).then(function (member) {
                return HazelcastClient.newHazelcastClient(cfg);
            }).then(function (res) {
                client = res;
            });
        });

        beforeEach(function () {
            managed = new ManagedObjects();
        });

        afterEach(function () {
            managed.destroyAll();
        });

        after(function () {
            client.shutdown();
            return Controller.shutdownCluster(cluster.id);
        });

        it('getDistributedObject returns empty array when there is no distributed object', function () {
            return client.getDistributedObjects().then(function (distributedObjects) {
                return Promise.all([
                    expect(distributedObjects).to.be.an('array'),
                    expect(distributedObjects).to.be.empty
                ]);
            });
        });

        it('getLocalEndpoint returns correct info', function () {
            var info = client.getLocalEndpoint();
            expect(info.localAddress.host).to.equal(client.clusterService.getOwnerConnection().localAddress.host);
            expect(info.localAddress.port).to.equal(client.clusterService.getOwnerConnection().localAddress.port);
            expect(info.uuid).to.equal(client.clusterService.uuid);
            expect(info.type).to.equal('NodeJS');
        });

        it('getDistributedObjects returns all dist objects', function (done) {
            managed.getObject(client.getMap.bind(client, 'map'));
            managed.getObject(client.getSet.bind(client, 'set'));
            setTimeout(function () {
                client.getDistributedObjects().then(function (distObjects) {
                    try {
                        names = distObjects.map((o) => {
                            return o.getName();
                        });
                        expect(names).to.have.members(['map', 'set']);
                        done();
                    } catch (e) {
                        done(e);
                    }
                })
            }, 300);
        });

        it('getDistributedObjects does not return removed object', function (done) {
            managed.getObject(client.getMap.bind(client, 'map1'));
            managed.getObject(client.getMap.bind(client, 'map2'));
            managed.getObject(client.getMap.bind(client, 'map3'));

            setTimeout(function () {
                managed.destroy('map1');
                client.getDistributedObjects().then(function (distObjects) {
                    try {
                        names = distObjects.map(function (o) {
                            return o.getName();
                        });
                        expect(names).to.have.members(['map2', 'map3']);
                        done();
                    } catch (e) {
                        done(e);
                    }
                })
            }, 300);
        });
    });

});
<commit_msg>fix on HazelcastClientTest (#326)<commit_after>/*
 * Copyright (c) 2008-2018, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var expect = require('chai').expect;
var Config = require('../.').Config;
var Controller = require('./RC');
var HazelcastClient = require('../.').Client;
var Promise = require('bluebird');

var dummyConfig = new Config.ClientConfig();
dummyConfig.networkConfig.smartRouting = false;

var smartConfig = new Config.ClientConfig();
smartConfig.networkConfig.smartRouting = true;

var configParams = [
    dummyConfig,
    smartConfig
];

function ManagedObjects() {
    this.managedObjects = [];
}

ManagedObjects.prototype.getObject = function (func, name) {
    var obj = func(name);
    this.managedObjects.push(obj);
    return obj;
};

ManagedObjects.prototype.destroyAll = function () {
    var promises = [];
    this.managedObjects.forEach(function (obj) {
        promises.push(obj.destroy());
    });

    return Promise.all(promises);
};

ManagedObjects.prototype.destroy = function (name) {
    var deferred = Promise.defer();
    this.managedObjects.filter((el) => {
        if (el.getName() === name) {
            el.destroy().then(function () {
                deferred.resolve();
            });
        }
    });
    return deferred.promise;
};

configParams.forEach(function (cfg) {
    describe('HazelcastClient', function () {
        this.timeout(4000);
        var cluster;
        var client;
        var managed;

        before(function () {
            return Controller.createCluster(null, null).then(function (res) {
                cluster = res;
                return Controller.startMember(cluster.id);
            }).then(function (member) {
                return HazelcastClient.newHazelcastClient(cfg);
            }).then(function (res) {
                client = res;
            });
        });

        beforeEach(function () {
            managed = new ManagedObjects();
        });

        afterEach(function () {
            managed.destroyAll();
        });

        after(function () {
            client.shutdown();
            return Controller.shutdownCluster(cluster.id);
        });

        it('getDistributedObject returns empty array when there is no distributed object', function () {
            return client.getDistributedObjects().then(function (distributedObjects) {
                return Promise.all([
                    expect(distributedObjects).to.be.an('array'),
                    expect(distributedObjects).to.be.empty
                ]);
            });
        });

        it('getLocalEndpoint returns correct info', function () {
            var info = client.getLocalEndpoint();
            expect(info.localAddress.host).to.equal(client.clusterService.getOwnerConnection().localAddress.host);
            expect(info.localAddress.port).to.equal(client.clusterService.getOwnerConnection().localAddress.port);
            expect(info.uuid).to.equal(client.clusterService.uuid);
            expect(info.type).to.equal('NodeJS');
        });

        it('getDistributedObjects returns all dist objects', function (done) {
            managed.getObject(client.getMap.bind(client, 'map'));
            managed.getObject(client.getSet.bind(client, 'set'));
            setTimeout(function () {
                client.getDistributedObjects().then(function (distObjects) {
                    try {
                        names = distObjects.map((o) => {
                            return o.getName();
                        });
                        expect(names).to.have.members(['map', 'set']);
                        done();
                    } catch (e) {
                        done(e);
                    }
                })
            }, 300);
        });

        it('getDistributedObjects does not return removed object', function (done) {
            managed.getObject(client.getMap.bind(client, 'map1'));
            managed.getObject(client.getMap.bind(client, 'map2'));
            managed.getObject(client.getMap.bind(client, 'map3'));

            setTimeout(function () {
                managed.destroy('map1').then(function () {
                    client.getDistributedObjects().then(function (distObjects) {
                        try {
                            var names = distObjects.map(function (o) {
                                return o.getName();
                            });
                            expect(names).to.have.members(['map2', 'map3']);
                            done();
                        } catch (e) {
                            done(e);
                        }
                    });
                });
            }, 300);
        });
    });

});
<|endoftext|>


<commit_before>'use strict';

/* global describe */
/* global it */
/* global before */
/*jshint expr: true*/

require('should');

////This is that data set we will be using, normally this is the result of a SQl query
var row = [];

row[0] = {};
row[0].mainID = 123;
row[0].mainName = 'Parent';
row[0].mainProperty = 'Taller than childern';
row[0].childID = 1;
row[0].childName = 'Billie';
row[0].childProperty = 'Fast';
row[0].childType = 'Good';

row[1] = {};
row[1].mainID = 123;
row[1].mainName = 'Parent';
row[1].mainProperty = 'Taller than childern';
row[1].childID = 2;
row[1].childName = 'Suzie';
row[1].childProperty = 'Devious';
row[1].childType = 'Bad';

row[2] = {};
row[2].mainID = 123;
row[2].mainName = 'Parent';
row[2].mainProperty = 'Taller than childern';
row[2].childID =3;
row[2].childName ='Jamie';
row[2].childProperty = 'Stable';
row[2].childType = 'Good';

row[3] = {};
row[3].mainID = 123;
row[3].mainName = 'Parent';
row[3].mainProperty = 'Taller than childern';
row[3].childID =4;
row[3].childName ='Cindy';
row[3].childProperty = 'Fast';
row[3].childType = 'Good';

var Datagram = require('../index').Datagram;
var Dataset = require('../index').Dataset;

// This section creates the data set and datagram objects, normally each of these would be in a sperate file
function Parent() {
	Object.defineProperty(this,'base',{value:Datagram, writable:false,configurable:true,enumerable:false});

	this.base(this);
	this.fieldMap =  {
		id:'mainID',
		name: 'mainName',
		property1: 'mainProperty'
	};

}
Parent.prototype = new Datagram();
Parent.prototype.constructor = Parent;

function Child() {
	Object.defineProperty(this,'base',{value:Datagram, writable:false,configurable:true,enumerable:false});

	this.base(this);
	this.fieldMap =  {
		id:'childID',
		name: 'childName',
		property1: 'childProperty',
		type: 'childType'
	};

}

Child.prototype = new Datagram();
Child.prototype.constructor = Child;

//here is a simple function
Child.prototype.isFast = function() {
	var self = this;
	return self.property1 === 'Fast';
};

function Childern() {
	var childern = new Dataset();
	childern.typeName= 'Childern';

	//I am adding a function to the object
	function getByType(type) {
		var self = this;
		function byType(child) {
			return child.type === type;
		}
		return self.copyReturn(self.filter(byType), new Childern());
	}
	Object.defineProperty(childern,'getByType',{value:getByType,writable:false,configurable:false,enumerable:false});

	function getById(id) {
		var self = this;
		function byID(child) {
			return child.id == id;
		}
		var child = self.filter(byID);
		if(child.length === 0) {
			return null;
		}
		return child[0];
	}

	Object.defineProperty(childern,'getById',{value:getById,writable:false,configurable:false,enumerable:false});

	//Once the definition is complete you must return the object
	return childern;
}

//This is one way to look at the data
var parentWithKids = new Parent();
parentWithKids.fieldMap.kids = new Childern();
parentWithKids.fieldMap.kids.key = 'childID';

parentWithKids.fieldMap.kids.items = function () {
	var child = new Child();
	return child;
};

//This is a different way to look at the same data
var kidsWithParent = new Childern();
kidsWithParent.key = 'childID';
kidsWithParent.items= function() {
	var child = new Child();
	child.fieldMap.parent = new Parent();
	return child;
};

describe('The Throwarm Library', function() {
	describe('parentWithKids', function () {
		before(function() {
			parentWithKids.fill(row);
		});
		it('should have processed the table' ,function() {
			parentWithKids.name.should.equal('Parent');
			parentWithKids.kids.length.should.equal(4);
			parentWithKids.kids[0].id.should.equal(1);
		});
		it('calling getByType should return a subset of Childern maintaing type', function() {
			var goodKids = parentWithKids.kids.getByType('Good');
			goodKids.length.should.equal(3);
			//Can;t really use instance of (since it is an array so check byu callign function)
			goodKids.typeName.should.equal('Childern');
			goodKids.getById(1).should.be.instanceOf(Child);
			goodKids.getById(1).name.should.equal('Billie');
			//since the bad kid was filered out it does not exist;
			(goodKids.getById(2) === null).should.be.true;
		});
		it('The childern should have isFast set', function() {
			parentWithKids.kids[0].isFast().should.be.true;
			parentWithKids.kids[2].isFast().should.be.false;

		});
		it('has for the childern should work', function(){
			parentWithKids.kids.has('Child').should.be.true;
			parentWithKids.kids.has('Parent').should.be.false;
			parentWithKids.kids.has('I Do Not Exist').should.be.false;
		});
		it('has for the parent should work', function(){
			parentWithKids.has('kids', 'Childern').should.be.true;
			parentWithKids.has('NA', 'Childern').should.be.false;
			parentWithKids.has('kids', 'NA').should.be.false;
			parentWithKids.has('NA', 'NA').should.be.false;
		});

	});

	describe('kidsWithParent', function () {
		before(function() {
			kidsWithParent.fill(row);
		});
		it('should have processed the table' ,function() {
			kidsWithParent.length.should.equal(4);
			kidsWithParent[0].name.should.equal('Billie');
			kidsWithParent[0].parent.name.should.equal('Parent');
		});
		it('should return the correct partials', function() {
			var secondKid  = kidsWithParent.getById(2);
			secondKid.isFast().should.be.false;
			secondKid.parent.id.should.equal(123);
		});
	});
});

<commit_msg>Fixed spellign of Children<commit_after>'use strict';

/* global describe */
/* global it */
/* global before */
/*jshint expr: true*/

require('should');

////This is that data set we will be using, normally this is the result of a SQl query
var row = [];

row[0] = {};
row[0].mainID = 123;
row[0].mainName = 'Parent';
row[0].mainProperty = 'Taller than children';
row[0].childID = 1;
row[0].childName = 'Billie';
row[0].childProperty = 'Fast';
row[0].childType = 'Good';

row[1] = {};
row[1].mainID = 123;
row[1].mainName = 'Parent';
row[1].mainProperty = 'Taller than children';
row[1].childID = 2;
row[1].childName = 'Suzie';
row[1].childProperty = 'Devious';
row[1].childType = 'Bad';

row[2] = {};
row[2].mainID = 123;
row[2].mainName = 'Parent';
row[2].mainProperty = 'Taller than children';
row[2].childID =3;
row[2].childName ='Jamie';
row[2].childProperty = 'Stable';
row[2].childType = 'Good';

row[3] = {};
row[3].mainID = 123;
row[3].mainName = 'Parent';
row[3].mainProperty = 'Taller than children';
row[3].childID =4;
row[3].childName ='Cindy';
row[3].childProperty = 'Fast';
row[3].childType = 'Good';

var Datagram = require('../index').Datagram;
var Dataset = require('../index').Dataset;

// This section creates the data set and datagram objects, normally each of these would be in a sperate file
function Parent() {
	Object.defineProperty(this,'base',{value:Datagram, writable:false,configurable:true,enumerable:false});

	this.base(this);
	this.fieldMap =  {
		id:'mainID',
		name: 'mainName',
		property1: 'mainProperty'
	};

}
Parent.prototype = new Datagram();
Parent.prototype.constructor = Parent;

function Child() {
	Object.defineProperty(this,'base',{value:Datagram, writable:false,configurable:true,enumerable:false});

	this.base(this);
	this.fieldMap =  {
		id:'childID',
		name: 'childName',
		property1: 'childProperty',
		type: 'childType'
	};

}

Child.prototype = new Datagram();
Child.prototype.constructor = Child;

//here is a simple function
Child.prototype.isFast = function() {
	var self = this;
	return self.property1 === 'Fast';
};

function Children() {
	var children = new Dataset();
	children.typeName= 'Children';

	//I am adding a function to the object
	function getByType(type) {
		var self = this;
		function byType(child) {
			return child.type === type;
		}
		return self.copyReturn(self.filter(byType), new Children());
	}
	Object.defineProperty(children,'getByType',{value:getByType,writable:false,configurable:false,enumerable:false});

	function getById(id) {
		var self = this;
		function byID(child) {
			return child.id == id;
		}
		var child = self.filter(byID);
		if(child.length === 0) {
			return null;
		}
		return child[0];
	}

	Object.defineProperty(children,'getById',{value:getById,writable:false,configurable:false,enumerable:false});

	//Once the definition is complete you must return the object
	return children;
}

//This is one way to look at the data
var parentWithKids = new Parent();
parentWithKids.fieldMap.kids = new Children();
parentWithKids.fieldMap.kids.key = 'childID';
parentWithKids.fieldMap.kids.items = function () {
	var child = new Child();
	return child;
};

//This is a different way to look at the same data
var kidsWithParent = new Children();
kidsWithParent.key = 'childID';
kidsWithParent.items= function() {
	var child = new Child();
	child.fieldMap.parent = new Parent();
	return child;
};

describe('The Throwarm Library', function() {
	describe('parentWithKids', function () {
		before(function() {
			parentWithKids.fill(row);
		});
		it('should have processed the table' ,function() {
			parentWithKids.name.should.equal('Parent');
			parentWithKids.kids.length.should.equal(4);
			parentWithKids.kids[0].id.should.equal(1);
		});
		it('calling getByType should return a subset of Children maintaing type', function() {
			var goodKids = parentWithKids.kids.getByType('Good');
			goodKids.length.should.equal(3);
			//Can;t really use instance of (since it is an array so check byu callign function)
			goodKids.typeName.should.equal('Children');
			goodKids.getById(1).should.be.instanceOf(Child);
			goodKids.getById(1).name.should.equal('Billie');
			//since the bad kid was filered out it does not exist;
			(goodKids.getById(2) === null).should.be.true;
		});
		it('The children should have isFast set', function() {
			parentWithKids.kids[0].isFast().should.be.true;
			parentWithKids.kids[2].isFast().should.be.false;

		});
		it('has for the children should work', function(){
			parentWithKids.kids.has('Child').should.be.true;
			parentWithKids.kids.has('Parent').should.be.false;
			parentWithKids.kids.has('I Do Not Exist').should.be.false;
		});
		it('has for the parent should work', function(){
			parentWithKids.has('kids', 'Children').should.be.true;
			parentWithKids.has('NA', 'Children').should.be.false;
			parentWithKids.has('kids', 'NA').should.be.false;
			parentWithKids.has('NA', 'NA').should.be.false;
		});

	});

	describe('kidsWithParent', function () {
		before(function() {
			kidsWithParent.fill(row);
		});
		it('should have processed the table' ,function() {
			kidsWithParent.length.should.equal(4);
			kidsWithParent[0].name.should.equal('Billie');
			kidsWithParent[0].parent.name.should.equal('Parent');
		});
		it('should return the correct partials', function() {
			var secondKid  = kidsWithParent.getById(2);
			secondKid.isFast().should.be.false;
			secondKid.parent.id.should.equal(123);
		});
	});
});

<|endoftext|>


<commit_before>/* global window, before, describe, it, document, beforeEach, afterEach */
'use strict'
var $, $div, expect

if (typeof process === 'object') {
  var jsdom = require('mocha-jsdom')
  var rerequire = jsdom.rerequire
  jsdom()
  before(function () {
    $ = rerequire('jquery')
    $.behavior = rerequire('../index')
    expect = require('chai').expect
  })
} else {
  $ = window.jQuery
  expect = window.chai.expect
}

afterEach(function () {
  $div.remove()
  $.behavior.reset()
})

describe('jquery:', function () {
  it('is an working environment', function () {
    $div = $('
').appendTo('body')
    expect($('body')[0].innerHTML).include('hello')
    expect(window.document.body.innerHTML).include('hello')
  })
})

describe('behavior:', function () {
  beforeEach(function () {
    $.behavior('.my-behavior', function () {
      this.innerHTML += '(clicked)'
    })
  })

  beforeEach(function () {
    $div = $('
').appendTo('body')
  })

  it('works', function () {
    $.behavior()
    expect($div.html()).eql('(clicked)')
  })

  it('can be triggered on its own', function () {
    $.behavior('.my-behavior')
    expect($div.html()).eql('(clicked)')
  })

  it('is idempotent', function () {
    $.behavior()
    $.behavior()
    $.behavior()
    expect($div.html()).eql('(clicked)')
  })
})

describe('exiting:', function () {
  beforeEach(function () {
    $.behavior('.their-behavior', function () {
      this.innerHTML += '(loaded)'
    }, function () {
      this.innerHTML += '(unloaded)'
    })
  })

  it('calls the unloader', function () {
    $div = $('
').appendTo('body')
    $.behavior()
    $div.remove()
    $.behavior()

    expect($div.html()).eql('(loaded)(unloaded)')
  })
})

describe('state:', function () {
  var state

  beforeEach(function () {
    $.behavior('.our-behavior', function (b) {
      state = b
      b.number = 10
    }, function (b) {
      b.number++
    })

    $div = $('
').appendTo('body')
    $.behavior()
    $div.remove()
    $.behavior()
  })

  it('has an id', function () {
    expect(state.id).match(/^b\d+$/)
  })

  it('works', function () {
    expect(state.number).eql(11)
  })
})

describe('behavior with role selector:', function () {
  beforeEach(function () {
    $.behavior('[role~="your-behavior"]', function () {
      this.innerHTML += '(clicked)'
    })
  })

  beforeEach(function () {
    $div = $('
').appendTo('body')
  })

  it('works', function () {
    $.behavior()
    expect($div.html()).eql('(clicked)')
  })

  it('can be called', function () {
    $.behavior('[role~="your-behavior"]')
    expect($div.html()).eql('(clicked)')
  })
})

describe('behavior with @role:', function () {
  beforeEach(function () {
    $.behavior('@his-behavior', function () {
      this.innerHTML += '(clicked)'
    })
  })

  beforeEach(function () {
    $div = $('
').appendTo('body')
  })

  it('works', function () {
    $.behavior()
    expect($div.html()).eql('(clicked)')
  })

  it('can be called via @', function () {
    $.behavior('@his-behavior')
    expect($div.html()).eql('(clicked)')
  })

  it('can be called', function () {
    $.behavior('[role~="his-behavior"]')
    expect($div.html()).eql('(clicked)')
  })
})

if (typeof process === 'object') {
  describe('standard', function () {
    it('is conformed to', require('mocha-standard'))
  })
}
<commit_msg>Update tests<commit_after>/* global window, before, describe, it, document, beforeEach, afterEach */
'use strict'
var $, $div, expect

if (typeof process === 'object') {
  var jsdom = require('mocha-jsdom')
  var rerequire = jsdom.rerequire
  jsdom()
  before(function () {
    $ = rerequire('jquery')
    $.behavior = rerequire('../index')
    expect = require('chai').expect
  })
} else {
  $ = window.jQuery
  expect = window.chai.expect
}

afterEach(function () {
  $div.remove()
  $.behavior.reset()
})

describe('jquery:', function () {
  it('is an working environment', function () {
    $div = $('
').appendTo('body')
    expect($('body')[0].innerHTML).include('hello')
    expect(window.document.body.innerHTML).include('hello')
  })
})

describe('behavior:', function () {
  beforeEach(function () {
    $.behavior('.my-behavior', function () {
      this.innerHTML += '(on)'
    })
  })

  beforeEach(function () {
    $div = $('
').appendTo('body')
  })

  it('works', function () {
    $.behavior()
    expect($div.html()).eql('(on)')
  })

  it('can be triggered on its own', function () {
    $.behavior('.my-behavior')
    expect($div.html()).eql('(on)')
  })

  it('is idempotent', function () {
    $.behavior()
    $.behavior()
    $.behavior()
    expect($div.html()).eql('(on)')
  })

  it('functions even without an exit handler', function () {
    $.behavior()
    $div.remove()
    $.behavior()
  })

  it('doesnt get double-applied even when removed', function () {
    $.behavior()
    $div.remove()
    $.behavior()
    $div.appendTo('body')
    $.behavior()
    expect($div.html()).eql('(on)')
  })
})

describe('exiting:', function () {
  beforeEach(function () {
    $.behavior('.their-behavior', function () {
      this.innerHTML += '(on)'
    }, function () {
      this.innerHTML += '(off)'
    })
  })

  it('calls the unloader', function () {
    $div = $('
').appendTo('body')
    $.behavior()
    $div.remove()
    $.behavior()

    expect($div.html()).eql('(on)(off)')
  })

  it('will intentionally get double applied when removed', function () {
    $div.remove()
    $.behavior()
    $div.appendTo('body')
    $.behavior()
    expect($div.html()).eql('(on)(off)(on)')
  })
})

describe('state:', function () {
  var state

  beforeEach(function () {
    $.behavior('.our-behavior', function (b) {
      state = b
      b.number = 10
    }, function (b) {
      b.number++
    })

    $div = $('
').appendTo('body')
    $.behavior()
    $div.remove()
    $.behavior()
  })

  it('has an id', function () {
    expect(state.id).match(/^b\d+$/)
  })

  it('works', function () {
    expect(state.number).eql(11)
  })
})

describe('behavior with role selector:', function () {
  beforeEach(function () {
    $.behavior('[role~="your-behavior"]', function () {
      this.innerHTML += '(on)'
    })
  })

  beforeEach(function () {
    $div = $('
').appendTo('body')
  })

  it('works', function () {
    $.behavior()
    expect($div.html()).eql('(on)')
  })

  it('can be called', function () {
    $.behavior('[role~="your-behavior"]')
    expect($div.html()).eql('(on)')
  })
})

describe('behavior with @role:', function () {
  beforeEach(function () {
    $.behavior('@his-behavior', function () {
      this.innerHTML += '(on)'
    })
  })

  beforeEach(function () {
    $div = $('
').appendTo('body')
  })

  it('works', function () {
    $.behavior()
    expect($div.html()).eql('(on)')
  })

  it('can be called via @', function () {
    $.behavior('@his-behavior')
    expect($div.html()).eql('(on)')
  })

  it('can be called', function () {
    $.behavior('[role~="his-behavior"]')
    expect($div.html()).eql('(on)')
  })
})

if (typeof process === 'object') {
  describe('standard', function () {
    it('is conformed to', require('mocha-standard'))
  })
}
<|endoftext|>