<commit_before>var mongoose  = require('mongoose')
  , elastical = require('elastical')
  , should    = require('should')
  , config    = require('./config')
  , Schema    = mongoose.Schema
  , ObjectId  = Schema.ObjectId
  , esClient  = new(require('elastical').Client)
  , mongoosastic = require('../lib/mongoosastic')
  , Tweet = require('./models/tweet');

// -- Only index specific field
var TalkSchema = new Schema({
    speaker: String
  , year: {type: Number, es_indexed:true}
  , title: {type:String, es_indexed:true}
  , abstract: {type:String, es_indexed:true}
  , bio: String
});
TalkSchema.plugin(mongoosastic)

var Talk = mongoose.model("Talk", TalkSchema);

var PersonSchema = new Schema({
    name: {type:String, es_indexed:true}
  , phone: {type:String, es_indexed:true}
  , address: String
});
PersonSchema.plugin(mongoosastic, {
  index:'people'
, type: 'dude'
, hydrate: true
, hydrateOptions: {lean: true, sort: '-name', select: 'address name'}
});

var Person = mongoose.model("Person", PersonSchema);

// -- alright let's test this shiznit!
describe('indexing', function(){
  before(function(done){
    mongoose.connect(config.mongoUrl, function(){
      Tweet.remove(function(){
        config.deleteIndexIfExists(['tweets', 'talks', 'people', 'public_tweets'], done)
      });
    });
  });

  after(function(done){
    Tweet.remove(function(){
      mongoose.disconnect();
      done();
    });
  });

  describe('Creating Index', function(){
    it('should create index if none exists', function(done){
      Tweet.createMapping(function(err, response){
        response.should.not.have.property('error');
        done();
      });
    });
    it('should update index if one already exists', function(done){
      Tweet.createMapping(function(err, response){
        response.should.not.have.property('error');
        done();
      });
    });

    after(function(done){
      config.deleteIndexIfExists(['tweets', 'talks', 'people'], done)
    });
  });

  describe('Default plugin', function(){
    before(function(done){
      config.createModelAndEnsureIndex(Tweet, {
          user: 'jamescarr'
        , userId: 1
        , message: "I like Riak better"
        , post_date: new Date()
      }, done);
    });
    it("should use the model's id as ES id", function(done){
      Tweet.findOne({message:"I like Riak better"}, function(err, doc){
        esClient.get('tweets', doc._id.toString(), function(err, res){
          res.message.should.eql(doc.message);
          done()
        });
      });
    });

    it('should be able to execute a simple query', function(done){
      Tweet.search({query:'Riak'}, function(err, results) {
        results.hits.total.should.eql(1)
        results.hits.hits[0]._source.message.should.eql('I like Riak better')
        done();
      });
    });
    it('should be able to execute a simple query', function(done){
      Tweet.search({query:'jamescarr'}, function(err, results) {
        results.hits.total.should.eql(1)
        results.hits.hits[0]._source.message.should.eql('I like Riak better')
        done()
      });
    });
    it('should report errors', function(done){
      Tweet.search({queriez:'jamescarr'}, function(err, results) {
        err.message.should.match(/SearchPhaseExecutionException/);
        should.not.exist(results)
        done()
      });
    });
  });
  describe('Removing', function(){
    var tweet = null;
    beforeEach(function(done){
      tweet = new Tweet({
        user:'jamescarr'
      , message: 'Saying something I shouldnt'
      });
      config.createModelAndEnsureIndex(Tweet, tweet, done);
    });
    it('should remove from index when model is removed', function(done){
      tweet.remove(function(){
          setTimeout(function(){
            Tweet.search({query:'shouldnt'}, function(err, res){
              res.hits.total.should.eql(0);
              done();
            });
          }, 1100);
      });
    });
    it('should remove only index', function(done){
      tweet.on('es-removed', function(err, res){
        setTimeout(function(){
          Tweet.search({query:'shouldnt'}, function(err, res){
            res.hits.total.should.eql(0);
            done();
          });
        }, 1100);
      });
      tweet.unIndex()
    });

    it('should queue for later removal if not in index', function(done){
      // behavior here is to try 3 times and then give up.
      var tweet = new Tweet({
        user:'jamescarr'
      , message: 'ABBA'
      });

      tweet.save(function(){
        tweet.remove();
      });
      tweet.on('es-removed', done);
    });

  });
  describe('Isolated Models', function(){
    before(function(done){
      var talk = new Talk({
          speaker: ''
        , year: 2013
        , title: "Dude"
        , abstract: ""
        , bio: ''
      });
      var tweet = new Tweet({
          user: 'Dude'
        , message: "Go see the big lebowski"
        , post_date: new Date()
      });
      tweet.save(function(){
        talk.save(function(){
          talk.on('es-indexed', function(err, res){
            setTimeout(done, 1000);
          });
        });
      });
    });

    it('should only find models of type Tweet', function(done){
      Tweet.search({query:'Dude'}, function(err, res){
        res.hits.total.should.eql(1);
        res.hits.hits[0]._source.user.should.eql('Dude');
        done();
      });
    });
    it('should only find models of type Talk', function(done){
      Talk.search({query:'Dude'}, function(err, res){
        res.hits.total.should.eql(1);
        res.hits.hits[0]._source.title.should.eql('Dude');
        done();
      });
    });
  });

  describe('Always hydrate', function(){
    before(function(done){
      config.createModelAndEnsureIndex(Person, {
          name: 'James Carr'
        , address: "Exampleville, MO"
        , phone: '(555)555-5555'
      }, done);
    });

    it('when gathering search results while respecting default hydrate options', function(done){
      Person.search({query:'James'}, function(err, res) {
        res.hits[0].address.should.eql('Exampleville, MO');
        res.hits[0].name.should.eql('James Carr');
        res.hits[0].should.not.have.property('phone');
        res.hits[0].should.not.be.an.instanceof(Person);
        done();
      });
    });
  });
  describe('Subset of Fields', function(){
    before(function(done){
      config.createModelAndEnsureIndex(Talk,{
          speaker: 'James Carr'
        , year: 2013
        , title: "Node.js Rocks"
        , abstract: "I told you node.js was cool. Listen to me!"
        , bio: 'One awesome dude.'
      }, done);
    });

    it('should only return indexed fields', function(done){
      Talk.search({query:'cool'}, function(err, res) {
        res.hits.total.should.eql(1);

        var talk = res.hits.hits[0]._source;
        talk.should.have.property('title');
        talk.should.have.property('year');
        talk.should.have.property('abstract');
        talk.should.not.have.property('speaker');
        talk.should.not.have.property('bio');
        done();
      });
    });

    it('should hydrate returned documents if desired', function(done){
      Talk.search({query:'cool'}, {hydrate:true}, function(err, res) {
        res.total.should.eql(1)

        var talk = res.hits[0]
        talk.should.have.property('title')
        talk.should.have.property('year');
        talk.should.have.property('abstract')
        talk.should.have.property('speaker')
        talk.should.have.property('bio')
        talk.should.be.an.instanceof(Talk);
        done();
      });
    });

    it('should allow extra query options when hydrating', function(done){
      Talk.search({query:'cool'}, {hydrate:true, hydrateOptions: {lean: true}}, function(err, res) {
        res.total.should.eql(1)

        var talk = res.hits[0]
        talk.should.have.property('title')
        talk.should.have.property('year');
        talk.should.have.property('abstract')
        talk.should.have.property('speaker')
        talk.should.have.property('bio')
        talk.should.not.be.an.instanceof(Talk);
        done();
      });
    });

  });

  describe('Existing Index', function(){
    before(function(done){
      config.deleteIndexIfExists(['ms_sample'], function(){
        esClient.createIndex('ms_sample', {mappings:{
          bum:{
            properties: {
              name: {type:'string'}
            }
          }
        }}, done);
      });
    });

    it('should just work', function(done){
      var BumSchema = new Schema({
        name: String
      });
      BumSchema.plugin(mongoosastic, {
          index: 'ms_sample'
        , type: 'bum'
      });
      var Bum = mongoose.model('bum', BumSchema);
      config.createModelAndEnsureIndex(Bum, {name:'Roger Wilson'}, function(){
        Bum.search({query:'Wilson'}, function(err, results){
          results.hits.total.should.eql(1);
          done();
        });
      });
    });
  });

});

<commit_msg>Add in index test to make sure that sub-objects are being indexed properly.<commit_after>var mongoose  = require('mongoose')
  , elastical = require('elastical')
  , should    = require('should')
  , config    = require('./config')
  , Schema    = mongoose.Schema
  , ObjectId  = Schema.ObjectId
  , esClient  = new(require('elastical').Client)
  , mongoosastic = require('../lib/mongoosastic')
  , Tweet = require('./models/tweet');

// -- Only index specific field
var TalkSchema = new Schema({
    speaker: String
  , year: {type: Number, es_indexed:true}
  , title: {type:String, es_indexed:true}
  , abstract: {type:String, es_indexed:true}
  , bio: String
});
TalkSchema.plugin(mongoosastic)

var Talk = mongoose.model("Talk", TalkSchema);

var PersonSchema = new Schema({
    name: {type:String, es_indexed:true}
  , phone: {type:String, es_indexed:true}
  , address: String
  , life: {
      born: {type: Number, es_indexed:true}
    , died: {type: Number, es_indexed:true}
  }
});
PersonSchema.plugin(mongoosastic, {
  index:'people'
, type: 'dude'
, hydrate: true
, hydrateOptions: {lean: true, sort: '-name', select: 'address name life'}
});

var Person = mongoose.model("Person", PersonSchema);

// -- alright let's test this shiznit!
describe('indexing', function(){
  before(function(done){
    mongoose.connect(config.mongoUrl, function(){
      Tweet.remove(function(){
        config.deleteIndexIfExists(['tweets', 'talks', 'people', 'public_tweets'], done)
      });
    });
  });

  after(function(done){
    Tweet.remove(function(){
      mongoose.disconnect();
      done();
    });
  });

  describe('Creating Index', function(){
    it('should create index if none exists', function(done){
      Tweet.createMapping(function(err, response){
        response.should.not.have.property('error');
        done();
      });
    });
    it('should update index if one already exists', function(done){
      Tweet.createMapping(function(err, response){
        response.should.not.have.property('error');
        done();
      });
    });

    after(function(done){
      config.deleteIndexIfExists(['tweets', 'talks', 'people'], done)
    });
  });

  describe('Default plugin', function(){
    before(function(done){
      config.createModelAndEnsureIndex(Tweet, {
          user: 'jamescarr'
        , userId: 1
        , message: "I like Riak better"
        , post_date: new Date()
      }, done);
    });
    it("should use the model's id as ES id", function(done){
      Tweet.findOne({message:"I like Riak better"}, function(err, doc){
        esClient.get('tweets', doc._id.toString(), function(err, res){
          res.message.should.eql(doc.message);
          done()
        });
      });
    });

    it('should be able to execute a simple query', function(done){
      Tweet.search({query:'Riak'}, function(err, results) {
        results.hits.total.should.eql(1)
        results.hits.hits[0]._source.message.should.eql('I like Riak better')
        done();
      });
    });
    it('should be able to execute a simple query', function(done){
      Tweet.search({query:'jamescarr'}, function(err, results) {
        results.hits.total.should.eql(1)
        results.hits.hits[0]._source.message.should.eql('I like Riak better')
        done()
      });
    });
    it('should report errors', function(done){
      Tweet.search({queriez:'jamescarr'}, function(err, results) {
        err.message.should.match(/SearchPhaseExecutionException/);
        should.not.exist(results)
        done()
      });
    });
  });
  describe('Removing', function(){
    var tweet = null;
    beforeEach(function(done){
      tweet = new Tweet({
        user:'jamescarr'
      , message: 'Saying something I shouldnt'
      });
      config.createModelAndEnsureIndex(Tweet, tweet, done);
    });
    it('should remove from index when model is removed', function(done){
      tweet.remove(function(){
          setTimeout(function(){
            Tweet.search({query:'shouldnt'}, function(err, res){
              res.hits.total.should.eql(0);
              done();
            });
          }, 1100);
      });
    });
    it('should remove only index', function(done){
      tweet.on('es-removed', function(err, res){
        setTimeout(function(){
          Tweet.search({query:'shouldnt'}, function(err, res){
            res.hits.total.should.eql(0);
            done();
          });
        }, 1100);
      });
      tweet.unIndex()
    });

    it('should queue for later removal if not in index', function(done){
      // behavior here is to try 3 times and then give up.
      var tweet = new Tweet({
        user:'jamescarr'
      , message: 'ABBA'
      });

      tweet.save(function(){
        tweet.remove();
      });
      tweet.on('es-removed', done);
    });

  });
  describe('Isolated Models', function(){
    before(function(done){
      var talk = new Talk({
          speaker: ''
        , year: 2013
        , title: "Dude"
        , abstract: ""
        , bio: ''
      });
      var tweet = new Tweet({
          user: 'Dude'
        , message: "Go see the big lebowski"
        , post_date: new Date()
      });
      tweet.save(function(){
        talk.save(function(){
          talk.on('es-indexed', function(err, res){
            setTimeout(done, 1000);
          });
        });
      });
    });

    it('should only find models of type Tweet', function(done){
      Tweet.search({query:'Dude'}, function(err, res){
        res.hits.total.should.eql(1);
        res.hits.hits[0]._source.user.should.eql('Dude');
        done();
      });
    });
    it('should only find models of type Talk', function(done){
      Talk.search({query:'Dude'}, function(err, res){
        res.hits.total.should.eql(1);
        res.hits.hits[0]._source.title.should.eql('Dude');
        done();
      });
    });
  });

  describe('Always hydrate', function(){
    before(function(done){
      config.createModelAndEnsureIndex(Person, {
          name: 'James Carr'
        , address: "Exampleville, MO"
        , phone: '(555)555-5555'
      }, done);
    });

    it('when gathering search results while respecting default hydrate options', function(done){
      Person.search({query:'James'}, function(err, res) {
        res.hits[0].address.should.eql('Exampleville, MO');
        res.hits[0].name.should.eql('James Carr');
        res.hits[0].should.not.have.property('phone');
        res.hits[0].should.not.be.an.instanceof(Person);
        done();
      });
    });
  });
  describe('Subset of Fields', function(){
    before(function(done){
      config.createModelAndEnsureIndex(Talk,{
          speaker: 'James Carr'
        , year: 2013
        , title: "Node.js Rocks"
        , abstract: "I told you node.js was cool. Listen to me!"
        , bio: 'One awesome dude.'
      }, done);
    });

    it('should only return indexed fields', function(done){
      Talk.search({query:'cool'}, function(err, res) {
        res.hits.total.should.eql(1);

        var talk = res.hits.hits[0]._source;
        talk.should.have.property('title');
        talk.should.have.property('year');
        talk.should.have.property('abstract');
        talk.should.not.have.property('speaker');
        talk.should.not.have.property('bio');
        done();
      });
    });

    it('should hydrate returned documents if desired', function(done){
      Talk.search({query:'cool'}, {hydrate:true}, function(err, res) {
        res.total.should.eql(1)

        var talk = res.hits[0]
        talk.should.have.property('title')
        talk.should.have.property('year');
        talk.should.have.property('abstract')
        talk.should.have.property('speaker')
        talk.should.have.property('bio')
        talk.should.be.an.instanceof(Talk);
        done();
      });
    });

    describe('Sub-object Fields', function(){
      before(function(done){
        config.createModelAndEnsureIndex(Person, {
            name: 'Bob Carr'
          , address: "Exampleville, MO"
          , phone: '(555)555-5555'
          , life: { born: 1950, other: 2000 }
        }, done);
      });

      it('should only return indexed fields and have indexed sub-objects', function(done){
        Person.search({query:'Bob'}, function(err, res) {
          res.hits[0].address.should.eql('Exampleville, MO');
          res.hits[0].name.should.eql('Bob Carr');
          res.hits[0].should.have.property('life');
          res.hits[0].life.born.should.eql(1950);
          res.hits[0].life.should.not.have.property('died');
          res.hits[0].life.should.not.have.property('other');
          res.hits[0].should.not.have.property('phone');
          res.hits[0].should.not.be.an.instanceof(Person);
          done();
        });
      });
    });

    it('should allow extra query options when hydrating', function(done){
      Talk.search({query:'cool'}, {hydrate:true, hydrateOptions: {lean: true}}, function(err, res) {
        res.total.should.eql(1)

        var talk = res.hits[0]
        talk.should.have.property('title')
        talk.should.have.property('year');
        talk.should.have.property('abstract')
        talk.should.have.property('speaker')
        talk.should.have.property('bio')
        talk.should.not.be.an.instanceof(Talk);
        done();
      });
    });

  });

  describe('Existing Index', function(){
    before(function(done){
      config.deleteIndexIfExists(['ms_sample'], function(){
        esClient.createIndex('ms_sample', {mappings:{
          bum:{
            properties: {
              name: {type:'string'}
            }
          }
        }}, done);
      });
    });

    it('should just work', function(done){
      var BumSchema = new Schema({
        name: String
      });
      BumSchema.plugin(mongoosastic, {
          index: 'ms_sample'
        , type: 'bum'
      });
      var Bum = mongoose.model('bum', BumSchema);
      config.createModelAndEnsureIndex(Bum, {name:'Roger Wilson'}, function(){
        Bum.search({query:'Wilson'}, function(err, results){
          results.hits.total.should.eql(1);
          done();
        });
      });
    });
  });

});

<|endoftext|>


<commit_before>/* eslint-env mocha */
var chai = require('chai')
var listEndpoints = require('../src/index')
var express = require('express')
var expect = chai.expect

chai.should()

function checkResults (endpoints) {
  describe('should retrieve an array', function () {
    // eslint-disable-next-line no-unused-expressions
    endpoints.should.not.be.empty
    endpoints.should.be.an('array')
    endpoints.should.have.length(2)

    it('of objects', function () {
      endpoints.forEach(function (endpoint) {
        // eslint-disable-next-line no-unused-expressions
        endpoint.should.not.be.empty
        endpoint.should.be.an('object')
      })
    })

    describe('with the app endpoints', function () {
      endpoints.forEach(function (endpoint) {
        describe('containing', function () {
          describe('the path', function () {
            it('as a string', function () {
              // eslint-disable-next-line no-unused-expressions
              endpoint.path.should.not.be.empty
              endpoint.path.should.be.a('string')
            })

            it('with the slashs', function () {
              endpoint.path.should.contains('/')
            })
          })

          describe('the methods', function () {
            it('as an array', function () {
              // eslint-disable-next-line no-unused-expressions
              endpoint.methods.should.not.be.empty
              endpoint.methods.should.be.an('array')
            })

            endpoint.methods.forEach(function (method) {
              it('of strings', function () {
                // eslint-disable-next-line no-unused-expressions
                method.should.not.be.empty
                method.should.be.a('string')
              })

              it('in uppercase', function () {
                expect(method).to.be.equal(method.toUpperCase())
              })

              it('excluding the _all ones', function () {
                expect(method).to.not.be.equal('_ALL')
              })
            })
          })
        })
      })
    })
  })
}

describe('express-list-endpoints', function () {
  describe('when called over an app', function () {
    var app = express()

    app.route('/')
      .get(function (req, res) {
        res.end()
      })
      .all(function (req, res) {
        res.end()
      })
      .post(function (req, res) {
        res.end()
      })

    app.route('/testing')
      .all(function (req, res) {
        res.end()
      })
      .delete(function (req, res) {
        res.end()
      })

    checkResults(listEndpoints(app))
  })

  describe('when called over a router', function () {
    var router = express.Router()

    router.route('/')
      .get(function (req, res) {
        res.end()
      })
      .all(function (req, res) {
        res.end()
      })
      .post(function (req, res) {
        res.end()
      })

    router.route('/testing')
      .all(function (req, res) {
        res.end()
      })
      .delete(function (req, res) {
        res.end()
      })

    checkResults(listEndpoints(router))
  })

  describe('when called over an app with mounted routers', function () {
    var app = express()
    var router = express.Router()

    app.route('/testing')
      .all(function (req, res) {
        res.end()
      })
      .delete(function (req, res) {
        res.end()
      })

    router.route('/')
      .get(function (req, res) {
        res.end()
      })
      .all(function (req, res) {
        res.end()
      })
      .post(function (req, res) {
        res.end()
      })

    app.use('/router', router)

    checkResults(listEndpoints(app))

    describe('and some of the routers has the option `mergeParams`', function () {
      var app = express()
      var router = express.Router({ mergeParams: true })
      var endpoints

      router.get('/:id/friends', function (req, res) {
        res.end()
      })

      app.use('/router', router)

      endpoints = listEndpoints(app)

      it('should parse the endpoints corretly', function () {
        expect(endpoints).to.have.length(1)
        expect(endpoints[0].path).to.be.equal('/router/:id/friends')
      })

      describe('and also has a sub-router on the router', function () {
        var app = express()
        var router = express.Router({ mergeParams: true })
        var subRouter = express.Router()
        var endpoints

        subRouter.get('/', function (req, res) {
          res.end()
        })

        app.use('/router', router)

        router.use('/:postId/sub-router', subRouter)

        endpoints = listEndpoints(app)

        it('should parse the endpoints corretly', function () {
          expect(endpoints).to.have.length(1)
          expect(endpoints[0].path).to.be.equal('/router/:postId/sub-router')
        })
      })
    })
  })

  describe('when the defined routes', function () {
    describe('contains underscores', function () {
      var router = express.Router()
      var endpoints

      router.get('/some_route', function (req, res) {
        res.end()
      })

      router.get('/some_other_router', function (req, res) {
        res.end()
      })

      router.get('/__last_route__', function (req, res) {
        res.end()
      })

      endpoints = listEndpoints(router)

      it('should parse the endpoint corretly', function () {
        endpoints[0].path.should.be.equal('/some_route')
        endpoints[1].path.should.be.equal('/some_other_router')
        endpoints[2].path.should.be.equal('/__last_route__')
      })
    })

    describe('contains hyphens', function () {
      var router = express.Router()
      var endpoints

      router.get('/some-route', function (req, res) {
        res.end()
      })

      router.get('/some-other-router', function (req, res) {
        res.end()
      })

      router.get('/--last-route--', function (req, res) {
        res.end()
      })

      endpoints = listEndpoints(router)

      it('should parse the endpoint corretly', function () {
        endpoints[0].path.should.be.equal('/some-route')
        endpoints[1].path.should.be.equal('/some-other-router')
        endpoints[2].path.should.be.equal('/--last-route--')
      })
    })

    describe('contains dots', function () {
      var router = express.Router()
      var endpoints

      router.get('/some.route', function (req, res) {
        res.end()
      })

      router.get('/some.other.router', function (req, res) {
        res.end()
      })

      router.get('/..last.route..', function (req, res) {
        res.end()
      })

      endpoints = listEndpoints(router)

      it('should parse the endpoint corretly', function () {
        endpoints[0].path.should.be.equal('/some.route')
        endpoints[1].path.should.be.equal('/some.other.router')
        endpoints[2].path.should.be.equal('/..last.route..')
      })
    })

    describe('contains multiple different chars', function () {
      var router = express.Router()
      var endpoints

      router.get('/s0m3_r.oute', function (req, res) {
        res.end()
      })

      router.get('/v1.0.0', function (req, res) {
        res.end()
      })

      router.get('/not_sure.what-1m.d01ng', function (req, res) {
        res.end()
      })

      endpoints = listEndpoints(router)

      it('should parse the endpoint corretly', function () {
        endpoints[0].path.should.be.equal('/s0m3_r.oute')
        endpoints[1].path.should.be.equal('/v1.0.0')
        endpoints[2].path.should.be.equal('/not_sure.what-1m.d01ng')
      })
    })
  })

  describe('when called over a mounted router with only root path', function () {
    var endpoints
    var app = express()
    var router = express.Router()

    router.get('/', function (req, res) {
      res.end()
    })

    app.use('/', router)

    endpoints = listEndpoints(app)

    it('should retrieve the list of endpoints and its methods', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0]).to.have.own.property('path')
      expect(endpoints[0]).to.have.own.property('methods')
      expect(endpoints[0].path).to.be.equal('/')
      expect(endpoints[0].methods[0]).to.be.equal('GET')
    })
  })

  describe('when called over a multi-level base route', function () {
    var endpoints
    var app = express()
    var router = express.Router()

    router.get('/my/path', function (req, res) {
      res.end()
    })

    app.use('/multi/level', router)
    app.use('/super/duper/multi/level', router)

    endpoints = listEndpoints(app)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(2)
      expect(endpoints[0].path).to.be.equal('/multi/level/my/path')
      expect(endpoints[1].path).to.be.equal('/super/duper/multi/level/my/path')
    })

    describe('with params', function () {
      var endpoints
      var app = express()
      var router = express.Router()

      router.get('/users/:id', function (req, res) {
        res.end()
      })

      router.get('/super/users/:id', function (req, res) {
        res.end()
      })

      app.use('/multi/:multiId/level/:levelId', router)

      endpoints = listEndpoints(app)

      it('should retrieve the correct built path', function () {
        expect(endpoints).to.have.length(2)
        expect(endpoints[0].path).to.be.equal('/multi/:multiId/level/:levelId/users/:id')
        expect(endpoints[1].path).to.be.equal('/multi/:multiId/level/:levelId/super/users/:id')
      })
    })

    describe('with params in middle of the pattern', function () {
      var endpoints
      var app = express()
      var router = express.Router()

      router.get('/super/users/:id/friends', function (req, res) {
        res.end()
      })

      app.use('/multi/level', router)

      endpoints = listEndpoints(app)

      it('should retrieve the correct built path', function () {
        expect(endpoints).to.have.length(1)
        expect(endpoints[0].path).to.be.equal('/multi/level/super/users/:id/friends')
      })
    })
  })

  describe('when called over a route with params', function () {
    var endpoints
    var app = express()

    app.get('/users/:id', function (req, res) {
      res.end()
    })

    endpoints = listEndpoints(app)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].path).to.be.equal('/users/:id')
    })
  })

  describe('when called over a route with params in middle of the pattern', function () {
    var endpoints
    var app = express()

    app.get('/users/:id/friends', function (req, res) {
      res.end()
    })

    endpoints = listEndpoints(app)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].path).to.be.equal('/users/:id/friends')
    })
  })

  describe('when called over a route with multiple methods with "/" path defined', () => {
    var endpoints
    var router = express.Router()

    router
      .post('/test', function (req, res) {
        res.end()
      })
      .delete('/test', function (req, res) {
        res.end()
      })

    endpoints = listEndpoints(router)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].path).to.be.equal('/test')
      expect(endpoints[0].methods[0]).to.be.equal('POST')
    })

    it('should retrieve the correct built methods', function () {
      expect(endpoints[0].methods).to.have.length(2)
      expect(endpoints[0].methods[0]).to.be.equal('POST')
      expect(endpoints[0].methods[1]).to.be.equal('DELETE')
    })
  })

  describe('when called with middlewares', () => {
    var endpoints
    var router = express.Router()

    var exampleMiddleware = function () {
      console.log('middleware')
    }

    router
      .post('/test', exampleMiddleware, function (req, res) {
        res.end()
      })

    endpoints = listEndpoints(router)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].path).to.be.equal('/test')
      expect(endpoints[0].methods[0]).to.be.equal('POST')
    })

    it('should retrieve the correct middleware', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].middleware).to.have.length(2)
      expect(endpoints[0].middleware[0]).to.equal('exampleMiddleware')
      expect(endpoints[0].middleware[1]).to.equal('anonymous')
    })
  })
})
<commit_msg>test(general): deprecate the use of var in favor of const or let<commit_after>/* eslint-env mocha */
const chai = require('chai')
const listEndpoints = require('../src/index')
const express = require('express')
const expect = chai.expect

chai.should()

function checkResults (endpoints) {
  describe('should retrieve an array', function () {
    // eslint-disable-next-line no-unused-expressions
    endpoints.should.not.be.empty
    endpoints.should.be.an('array')
    endpoints.should.have.length(2)

    it('of objects', function () {
      endpoints.forEach(function (endpoint) {
        // eslint-disable-next-line no-unused-expressions
        endpoint.should.not.be.empty
        endpoint.should.be.an('object')
      })
    })

    describe('with the app endpoints', function () {
      endpoints.forEach(function (endpoint) {
        describe('containing', function () {
          describe('the path', function () {
            it('as a string', function () {
              // eslint-disable-next-line no-unused-expressions
              endpoint.path.should.not.be.empty
              endpoint.path.should.be.a('string')
            })

            it('with the slashs', function () {
              endpoint.path.should.contains('/')
            })
          })

          describe('the methods', function () {
            it('as an array', function () {
              // eslint-disable-next-line no-unused-expressions
              endpoint.methods.should.not.be.empty
              endpoint.methods.should.be.an('array')
            })

            endpoint.methods.forEach(function (method) {
              it('of strings', function () {
                // eslint-disable-next-line no-unused-expressions
                method.should.not.be.empty
                method.should.be.a('string')
              })

              it('in uppercase', function () {
                expect(method).to.be.equal(method.toUpperCase())
              })

              it('excluding the _all ones', function () {
                expect(method).to.not.be.equal('_ALL')
              })
            })
          })
        })
      })
    })
  })
}

describe('express-list-endpoints', function () {
  describe('when called over an app', function () {
    const app = express()

    app.route('/')
      .get(function (req, res) {
        res.end()
      })
      .all(function (req, res) {
        res.end()
      })
      .post(function (req, res) {
        res.end()
      })

    app.route('/testing')
      .all(function (req, res) {
        res.end()
      })
      .delete(function (req, res) {
        res.end()
      })

    checkResults(listEndpoints(app))
  })

  describe('when called over a router', function () {
    const router = express.Router()

    router.route('/')
      .get(function (req, res) {
        res.end()
      })
      .all(function (req, res) {
        res.end()
      })
      .post(function (req, res) {
        res.end()
      })

    router.route('/testing')
      .all(function (req, res) {
        res.end()
      })
      .delete(function (req, res) {
        res.end()
      })

    checkResults(listEndpoints(router))
  })

  describe('when called over an app with mounted routers', function () {
    const app = express()
    const router = express.Router()

    app.route('/testing')
      .all(function (req, res) {
        res.end()
      })
      .delete(function (req, res) {
        res.end()
      })

    router.route('/')
      .get(function (req, res) {
        res.end()
      })
      .all(function (req, res) {
        res.end()
      })
      .post(function (req, res) {
        res.end()
      })

    app.use('/router', router)

    checkResults(listEndpoints(app))

    describe('and some of the routers has the option `mergeParams`', function () {
      const app = express()
      const router = express.Router({ mergeParams: true })

      router.get('/:id/friends', function (req, res) {
        res.end()
      })

      app.use('/router', router)

      const endpoints = listEndpoints(app)

      it('should parse the endpoints correctly', function () {
        expect(endpoints).to.have.length(1)
        expect(endpoints[0].path).to.be.equal('/router/:id/friends')
      })

      describe('and also has a sub-router on the router', function () {
        const app = express()
        const router = express.Router({ mergeParams: true })
        const subRouter = express.Router()

        subRouter.get('/', function (req, res) {
          res.end()
        })

        app.use('/router', router)

        router.use('/:postId/sub-router', subRouter)

        const endpoints = listEndpoints(app)

        it('should parse the endpoints correctly', function () {
          expect(endpoints).to.have.length(1)
          expect(endpoints[0].path).to.be.equal('/router/:postId/sub-router')
        })
      })
    })
  })

  describe('when the defined routes', function () {
    describe('contains underscores', function () {
      const router = express.Router()

      router.get('/some_route', function (req, res) {
        res.end()
      })

      router.get('/some_other_router', function (req, res) {
        res.end()
      })

      router.get('/__last_route__', function (req, res) {
        res.end()
      })

      const endpoints = listEndpoints(router)

      it('should parse the endpoint corretly', function () {
        endpoints[0].path.should.be.equal('/some_route')
        endpoints[1].path.should.be.equal('/some_other_router')
        endpoints[2].path.should.be.equal('/__last_route__')
      })
    })

    describe('contains hyphens', function () {
      const router = express.Router()

      router.get('/some-route', function (req, res) {
        res.end()
      })

      router.get('/some-other-router', function (req, res) {
        res.end()
      })

      router.get('/--last-route--', function (req, res) {
        res.end()
      })

      const endpoints = listEndpoints(router)

      it('should parse the endpoint correctly', function () {
        endpoints[0].path.should.be.equal('/some-route')
        endpoints[1].path.should.be.equal('/some-other-router')
        endpoints[2].path.should.be.equal('/--last-route--')
      })
    })

    describe('contains dots', function () {
      const router = express.Router()

      router.get('/some.route', function (req, res) {
        res.end()
      })

      router.get('/some.other.router', function (req, res) {
        res.end()
      })

      router.get('/..last.route..', function (req, res) {
        res.end()
      })

      const endpoints = listEndpoints(router)

      it('should parse the endpoint correctly', function () {
        endpoints[0].path.should.be.equal('/some.route')
        endpoints[1].path.should.be.equal('/some.other.router')
        endpoints[2].path.should.be.equal('/..last.route..')
      })
    })

    describe('contains multiple different chars', function () {
      const router = express.Router()

      router.get('/s0m3_r.oute', function (req, res) {
        res.end()
      })

      router.get('/v1.0.0', function (req, res) {
        res.end()
      })

      router.get('/not_sure.what-1m.d01ng', function (req, res) {
        res.end()
      })

      const endpoints = listEndpoints(router)

      it('should parse the endpoint correctly', function () {
        endpoints[0].path.should.be.equal('/s0m3_r.oute')
        endpoints[1].path.should.be.equal('/v1.0.0')
        endpoints[2].path.should.be.equal('/not_sure.what-1m.d01ng')
      })
    })
  })

  describe('when called over a mounted router with only root path', function () {
    const app = express()
    const router = express.Router()

    router.get('/', function (req, res) {
      res.end()
    })

    app.use('/', router)

    const endpoints = listEndpoints(app)

    it('should retrieve the list of endpoints and its methods', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0]).to.have.own.property('path')
      expect(endpoints[0]).to.have.own.property('methods')
      expect(endpoints[0].path).to.be.equal('/')
      expect(endpoints[0].methods[0]).to.be.equal('GET')
    })
  })

  describe('when called over a multi-level base route', function () {
    const app = express()
    const router = express.Router()

    router.get('/my/path', function (req, res) {
      res.end()
    })

    app.use('/multi/level', router)
    app.use('/super/duper/multi/level', router)

    const endpoints = listEndpoints(app)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(2)
      expect(endpoints[0].path).to.be.equal('/multi/level/my/path')
      expect(endpoints[1].path).to.be.equal('/super/duper/multi/level/my/path')
    })

    describe('with params', function () {
      const app = express()
      const router = express.Router()

      router.get('/users/:id', function (req, res) {
        res.end()
      })

      router.get('/super/users/:id', function (req, res) {
        res.end()
      })

      app.use('/multi/:multiId/level/:levelId', router)

      const endpoints = listEndpoints(app)

      it('should retrieve the correct built path', function () {
        expect(endpoints).to.have.length(2)
        expect(endpoints[0].path).to.be.equal('/multi/:multiId/level/:levelId/users/:id')
        expect(endpoints[1].path).to.be.equal('/multi/:multiId/level/:levelId/super/users/:id')
      })
    })

    describe('with params in middle of the pattern', function () {
      const app = express()
      const router = express.Router()

      router.get('/super/users/:id/friends', function (req, res) {
        res.end()
      })

      app.use('/multi/level', router)

      const endpoints = listEndpoints(app)

      it('should retrieve the correct built path', function () {
        expect(endpoints).to.have.length(1)
        expect(endpoints[0].path).to.be.equal('/multi/level/super/users/:id/friends')
      })
    })
  })

  describe('when called over a route with params', function () {
    const app = express()

    app.get('/users/:id', function (req, res) {
      res.end()
    })

    const endpoints = listEndpoints(app)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].path).to.be.equal('/users/:id')
    })
  })

  describe('when called over a route with params in middle of the pattern', function () {
    const app = express()

    app.get('/users/:id/friends', function (req, res) {
      res.end()
    })

    const endpoints = listEndpoints(app)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].path).to.be.equal('/users/:id/friends')
    })
  })

  describe('when called over a route with multiple methods with "/" path defined', () => {
    const router = express.Router()

    router
      .post('/test', function (req, res) {
        res.end()
      })
      .delete('/test', function (req, res) {
        res.end()
      })

    const endpoints = listEndpoints(router)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].path).to.be.equal('/test')
      expect(endpoints[0].methods[0]).to.be.equal('POST')
    })

    it('should retrieve the correct built methods', function () {
      expect(endpoints[0].methods).to.have.length(2)
      expect(endpoints[0].methods[0]).to.be.equal('POST')
      expect(endpoints[0].methods[1]).to.be.equal('DELETE')
    })
  })

  describe('when called with middlewares', () => {
    const router = express.Router()

    const exampleMiddleware = function () {
      console.log('middleware')
    }

    router
      .post('/test', exampleMiddleware, function (req, res) {
        res.end()
      })

    const endpoints = listEndpoints(router)

    it('should retrieve the correct built path', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].path).to.be.equal('/test')
      expect(endpoints[0].methods[0]).to.be.equal('POST')
    })

    it('should retrieve the correct middleware', function () {
      expect(endpoints).to.have.length(1)
      expect(endpoints[0].middleware).to.have.length(2)
      expect(endpoints[0].middleware[0]).to.equal('exampleMiddleware')
      expect(endpoints[0].middleware[1]).to.equal('anonymous')
    })
  })
})
<|endoftext|>


<commit_before>/* jshint node: true, mocha: true, esversion: 6 */

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

var lib = require('../');

describe('[index]', () => {
  describe('#one', () => {
    it('returns true', () => {
      expect(lib.one()).to.equal(true);
    });
  });

  describe('#two', () => {
    it('sometimes returns true');

    it('sometimes returns false');
  });

  describe('#three', () => {
    it('return false');
  });
});
<commit_msg>more tests in order to raise coverage<commit_after>/* jshint node: true, mocha: true, esversion: 6 */

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

var lib = require('../');

describe('[index]', () => {
  describe('#one', () => {
    it('returns true', () => {
      expect(lib.one()).to.equal(true);
    });
  });

  describe('#two', () => {
    it('sometimes returns true', () => {
      expect(lib.two(1)).to.equal(true);
    });

    it('sometimes returns false');
  });

  describe('#three', () => {
    it('return false');
  });
});
<|endoftext|>


<commit_before>/* eslint no-underscore-dangle: 0 */
const test = require('ava').test;
const Promise = require('bluebird');
const mongoose = require('mongoose');

const stringColleciton = require('../');

mongoose.Promise = Promise;
const db = mongoose.createConnection('localhost');
const getModel = (schema) => {
  const collectionId = mongoose.Types.ObjectId().toString();
  const collectionName = `tmp${collectionId}`;

  return db.model(collectionName, schema);
};
const minimalValidate = (t, pathOption) => {
  t.is(pathOption.instance, 'Array');
  t.is(pathOption.caster.instance, 'String');
};

test.after.always('clean up tmp collection', () => {
  const dropCollection = collectionName => Promise.fromNode((callback) => {
    db.db.dropCollection(collectionName, callback);
  });

  return Promise.fromNode(callback => db.db.listCollections({ name: /^tmp/ }).toArray(callback))
    .map(collection => collection.name)
    .map(dropCollection);
});

test('fieldName: should exists target filed name', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  minimalValidate(t, pathOption);
  t.false(pathOption.caster.options.index);
});

test('fieldName: should index in caster field', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isIndex: true });
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  t.true(pathOption.caster.options.index);
});

test('fieldName: should use input field name', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { fieldName: 't' });
  const pathOption = schema.path('t');

  minimalValidate(t, pathOption);
});

test('get: should success get collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  return model.create({ tags: ['t3'] })
    .then(doc => model.getTags({ _id: doc._id }))
    .then((tags) => {
      t.deepEqual(tags, ['t3']);
    });
});

test('get: should still get tags withou input', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  return model.create({ tags: ['t3'] })
    .then(() => model.getTags())
    .then(tags => t.deepEqual(tags, ['t3']));
});

test('add: should success add to collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['test'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['test2']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['test', 'test2']));
});

test('add: should success add to collection with unique opions', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isUnique: false });
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t1']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['t', 't1', 't1']));
});

test('add: should success add to collection with unique opions', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isUnique: true });
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t1']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);

      return model.findById(bus.docId);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);
    });
});

test('add: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.addTags();
  await t.throws(promise, 'query should not be empty');
});

test('replace: should success replace original collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.replaceTags({ _id: doc._id }, ['t2']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t2']);

      return model.findById(doc._id);
    })
    .then(doc => t.deepEqual(doc.tags, ['t2']));
});

test('replace: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.replaceTags();
  await t.throws(promise, 'query should not be empty');
});

test('batchReplace: should success batchReplace original collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.batchReplaceTags({ _id: doc._id }, ['t2']);
    })
    .then(({ nModified }) => {
      t.is(nModified, 1);

      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, ['t2']));
});

test('batchReplace: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.batchReplaceTags();
  await t.throws(promise, 'query should not be empty');
});
<commit_msg>test(elementOptions): tests on default options<commit_after>/* eslint no-underscore-dangle: 0 */
const test = require('ava').test;
const Promise = require('bluebird');
const mongoose = require('mongoose');

const stringColleciton = require('../');

mongoose.Promise = Promise;
const db = mongoose.createConnection('localhost');
const getModel = (schema) => {
  const collectionId = mongoose.Types.ObjectId().toString();
  const collectionName = `tmp${collectionId}`;

  return db.model(collectionName, schema);
};
const minimalValidate = (t, pathOption, casterType = 'String') => {
  t.is(pathOption.instance, 'Array');
  t.is(pathOption.caster.instance, casterType);
};

test.after.always('clean up tmp collection', () => {
  const dropCollection = collectionName => Promise.fromNode((callback) => {
    db.db.dropCollection(collectionName, callback);
  });

  return Promise.fromNode(callback => db.db.listCollections({ name: /^tmp/ }).toArray(callback))
    .map(collection => collection.name)
    .map(dropCollection);
});

test('elementOptions: should override default element options', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, {
    elementOptions: {
      index: true,
    },
  });
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  minimalValidate(t, pathOption);
  t.true(pathOption.caster.options.index);
});

test('fieldName: should exists target filed name', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  minimalValidate(t, pathOption);
  t.false(pathOption.caster.options.index);
});

test('fieldName: should index in caster field', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isIndex: true });
  const pathOption = schema.path('tags');

  t.truthy(pathOption);
  t.true(pathOption.caster.options.index);
});

test('fieldName: should use input field name', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { fieldName: 't' });
  const pathOption = schema.path('t');

  minimalValidate(t, pathOption);
});

test('get: should success get collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  return model.create({ tags: ['t3'] })
    .then(doc => model.getTags({ _id: doc._id }))
    .then((tags) => {
      t.deepEqual(tags, ['t3']);
    });
});

test('get: should still get tags withou input', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  return model.create({ tags: ['t3'] })
    .then(() => model.getTags())
    .then(tags => t.deepEqual(tags, ['t3']));
});

test('add: should success add to collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['test'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['test2']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['test', 'test2']));
});

test('add: should success add to collection with unique opions', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isUnique: false });
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t1']);
    })
    .then(() => model.findById(bus.docId))
    .then(doc => t.deepEqual(doc.tags, ['t', 't1', 't1']));
});

test('add: should success add to collection with unique opions', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton, { isUnique: true });
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.addTags({ _id: doc._id }, ['t1']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);

      return model.findById(bus.docId);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t', 't1']);
    });
});

test('add: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.addTags();
  await t.throws(promise, 'query should not be empty');
});

test('replace: should success replace original collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.replaceTags({ _id: doc._id }, ['t2']);
    })
    .then((doc) => {
      t.deepEqual(doc.tags, ['t2']);

      return model.findById(doc._id);
    })
    .then(doc => t.deepEqual(doc.tags, ['t2']));
});

test('replace: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.replaceTags();
  await t.throws(promise, 'query should not be empty');
});

test('batchReplace: should success batchReplace original collection', (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const bus = {};
  return model.create({ tags: ['t', 't1'] })
    .then((doc) => {
      t.truthy(doc);
      bus.docId = doc._id;

      return model.batchReplaceTags({ _id: doc._id }, ['t2']);
    })
    .then(({ nModified }) => {
      t.is(nModified, 1);

      return model.findById(bus.docId);
    })
    .then(doc => t.deepEqual(doc.tags, ['t2']));
});

test('batchReplace: should reject emtpy query error', async (t) => {
  const schema = new mongoose.Schema();
  schema.plugin(stringColleciton);
  const model = getModel(schema);

  const promise = model.batchReplaceTags();
  await t.throws(promise, 'query should not be empty');
});
<|endoftext|>


<commit_before>'use strict';

const { Menu, ipcMain, powerSaveBlocker, app } = require('electron');

class IpcManager {
    constructor(window) {
        this.window = window;
        this.instance = {};
    }

    bindEvents() {

        ipcMain.on('tracksListContextMenu', (event, data) => {

            const options = JSON.parse(data);
            let playlistTemplate;

            if(options.playlists) {

                playlistTemplate = [
                    {
                        label: 'Create new playlist...',
                        click: () => {
                            event.sender.send('tracksListContextMenuReply', 'createPlaylist');
                        }
                    }
                ];

                if(options.playlists.length > 0) {
                    playlistTemplate.push(
                        {
                            type: 'separator'
                        }
                    );
                }

                options.playlists.forEach((elem) => {
                    playlistTemplate.push({
                        label: elem.name,
                        click: () => {
                            event.sender.send('tracksListContextMenuReply', 'addToPlaylist', { playlistId: elem._id });
                        }
                    });
                });

            } else {

                playlistTemplate = [
                    {
                        label: 'Create new playlist...',
                        click: () => {
                            event.sender.send('tracksListContextMenuReply', 'createPlaylist');
                        }
                    },
                    {
                        type: 'separator'
                    },
                    {
                        label: 'No playlist',
                        enabled: false
                    }
                ];
            }

            const template = [
                {
                    label: options.selectedCount > 1 ? `${options.selectedCount} tracks selected` : `${options.selectedCount} track selected`,
                    enabled: false
                },
                {
                    type: 'separator'
                },
                {
                    label: 'Add to queue',
                    click: () => {
                        event.sender.send('tracksListContextMenuReply', 'addToQueue');
                    }
                },
                {
                    label: 'Play next',
                    click: () => {
                        event.sender.send('tracksListContextMenuReply', 'playNext');
                    }
                },
                {
                    type: 'separator'
                },
                {
                    label: 'Add to playlist',
                    submenu: playlistTemplate
                }
            ];

            if(options.type === 'playlist') template.push({
                label: 'Remove from playlist',
                click: () => {
                    event.sender.send('tracksListContextMenuReply', 'removeFromPlaylist');
                }
            });

            const context = Menu.buildFromTemplate(template);

            context.popup(this.window); // Let it appear
        });

        ipcMain.on('playlistContextMenu', (event, _id) => {

            const template = [
                {
                    label: 'Delete',
                    click: () => {
                        event.sender.send('playlistContextMenuReply', 'delete', _id);
                    }
                },
                {
                    label: 'Rename',
                    click: () => {
                        event.sender.send('playlistContextMenuReply', 'rename', _id);
                    }
                }
            ];

            const context = Menu.buildFromTemplate(template);

            context.popup(this.window); // Let it appear
        });

        ipcMain.on('toggleSleepBlocker', (event, toggle, mode) => {

            if(toggle) {
                this.instance.sleepBlockerId = powerSaveBlocker.start(mode);
            } else {
                powerSaveBlocker.stop(this.instance.sleepBlockerId);
                delete(this.instance.sleepBlockerId);
            }
        });

        ipcMain.on('appReady', () => {
            this.window.show();
        });

        ipcMain.on('appRestart', () => {
            app.relaunch({args: process.argv.slice(1) + ['--relaunch']})
            app.exit(0)
        });

        this.window.on('closed', () => {
            // Dereference the window object
            this.window = null;
        });
    }
}

module.exports = IpcManager;
<commit_msg>Fix eslint<commit_after>'use strict';

const { Menu, ipcMain, powerSaveBlocker, app } = require('electron');

class IpcManager {
    constructor(window) {
        this.window = window;
        this.instance = {};
    }

    bindEvents() {

        ipcMain.on('tracksListContextMenu', (event, data) => {

            const options = JSON.parse(data);
            let playlistTemplate;

            if(options.playlists) {

                playlistTemplate = [
                    {
                        label: 'Create new playlist...',
                        click: () => {
                            event.sender.send('tracksListContextMenuReply', 'createPlaylist');
                        }
                    }
                ];

                if(options.playlists.length > 0) {
                    playlistTemplate.push(
                        {
                            type: 'separator'
                        }
                    );
                }

                options.playlists.forEach((elem) => {
                    playlistTemplate.push({
                        label: elem.name,
                        click: () => {
                            event.sender.send('tracksListContextMenuReply', 'addToPlaylist', { playlistId: elem._id });
                        }
                    });
                });

            } else {

                playlistTemplate = [
                    {
                        label: 'Create new playlist...',
                        click: () => {
                            event.sender.send('tracksListContextMenuReply', 'createPlaylist');
                        }
                    },
                    {
                        type: 'separator'
                    },
                    {
                        label: 'No playlist',
                        enabled: false
                    }
                ];
            }

            const template = [
                {
                    label: options.selectedCount > 1 ? `${options.selectedCount} tracks selected` : `${options.selectedCount} track selected`,
                    enabled: false
                },
                {
                    type: 'separator'
                },
                {
                    label: 'Add to queue',
                    click: () => {
                        event.sender.send('tracksListContextMenuReply', 'addToQueue');
                    }
                },
                {
                    label: 'Play next',
                    click: () => {
                        event.sender.send('tracksListContextMenuReply', 'playNext');
                    }
                },
                {
                    type: 'separator'
                },
                {
                    label: 'Add to playlist',
                    submenu: playlistTemplate
                }
            ];

            if(options.type === 'playlist') template.push({
                label: 'Remove from playlist',
                click: () => {
                    event.sender.send('tracksListContextMenuReply', 'removeFromPlaylist');
                }
            });

            const context = Menu.buildFromTemplate(template);

            context.popup(this.window); // Let it appear
        });

        ipcMain.on('playlistContextMenu', (event, _id) => {

            const template = [
                {
                    label: 'Delete',
                    click: () => {
                        event.sender.send('playlistContextMenuReply', 'delete', _id);
                    }
                },
                {
                    label: 'Rename',
                    click: () => {
                        event.sender.send('playlistContextMenuReply', 'rename', _id);
                    }
                }
            ];

            const context = Menu.buildFromTemplate(template);

            context.popup(this.window); // Let it appear
        });

        ipcMain.on('toggleSleepBlocker', (event, toggle, mode) => {

            if(toggle) {
                this.instance.sleepBlockerId = powerSaveBlocker.start(mode);
            } else {
                powerSaveBlocker.stop(this.instance.sleepBlockerId);
                delete(this.instance.sleepBlockerId);
            }
        });

        ipcMain.on('appReady', () => {
            this.window.show();
        });

        ipcMain.on('appRestart', () => {
            app.relaunch({ args: process.argv.slice(1) + ['--relaunch'] });
            app.exit(0);
        });

        this.window.on('closed', () => {
            // Dereference the window object
            this.window = null;
        });
    }
}

module.exports = IpcManager;
<|endoftext|>


<commit_before>import test from 'ava';

test.todo('');
<commit_msg>Delete test/index.test.js<commit_after><|endoftext|>


<commit_before>import F from '../funcifyr.js';
import {expect, assert} from 'chai';

describe('andify', () => {
  it('should return true if arg passed to pred funcs evaluates to true', () => {

    let isString = (a) => typeof a === 'string';
    let isLongerThanSix = (b) => b.length > 6;
    let testIfStringANDOverSix = F.andify(isString, isLongerThanSix)('funcify all the things');

    expect(testIfStringANDOverSix).to.be.true;

  });
});

describe('arrayify', () => {
  it('should turn an array-like collection into a real array', () => {

    // Can't test a DOM collection so we'll run test on arguments object
    let returnArgs = () => arguments;
    let argumentsObjectToArray = F.arrayify(returnArgs('string', 3));
    let testIfArray = Array.isArray(argumentsObjectToArray);

    expect(testIfArray).to.be.true;

  });
});

describe('composify', () => {
  it('should return a function', () => {

    let actual = typeof F.composify();
    let expected = 'function';

    assert.equal(actual, expected);

  });
});

describe('currify', () => {
  it('should return a function', () => {

    let actual = typeof F.currify();
    let expected = 'function';

    assert.equal(actual, expected);

  });
});

describe('currify', () => {
  it('should return a function that takes a function as an argument', () => {

    let add = (a, b) => a + b;
    let curredFunction = F.currify(add);

    let actual = typeof curredFunction;
    let expected = 'function';

    assert.equal(actual, expected);

  });
});

describe('currify', () => {
  it('should return the result of a curried function', () => {

    let add = (a, b) => a + b;
    let curriedAdd = F.currify(add);
    let add5 = curriedAdd(5);

    let actual = add5(6);
    let expected = 11;

    assert.equal(actual, expected);

  });
});

describe('defuncify', () => {
  it('should create a method property from a regular function...', () => {

    class Person {}

    let reverseString = str => str.split('').reverse().join('');
    Person.prototype.reverseString = F.defuncify(reverseString);

    expect('reverseString' in Person.prototype).to.be.true;

  });
});

describe('defuncify', () => {
  it('...and property should be a function', () => {

    class Person {}

    let reverseString = str => str.split('').reverse().join('');
    Person.prototype.reverseString = F.defuncify(reverseString);

    let actual = typeof Person.prototype.reverseString;
    let expected = 'function';

    assert.equal(actual, expected);

  });
});

describe('falsify', () => {
  it('Should return a predicate function that is the opposite of original function', () => {

    let isTrue = () => true;
    let isFalse = F.falsify(isTrue);

    expect(isFalse() === !isTrue()).to.be.true;

  });
});
<commit_msg>Add tests for flattify<commit_after>import F from '../funcifyr.js';
import {expect, assert} from 'chai';

describe('andify', () => {
  it('should return true if arg passed to pred funcs evaluates to true', () => {

    let isString = (a) => typeof a === 'string';
    let isLongerThanSix = (b) => b.length > 6;
    let testIfStringANDOverSix = F.andify(isString, isLongerThanSix)('funcify all the things');

    expect(testIfStringANDOverSix).to.be.true;

  });
});

describe('arrayify', () => {
  it('should turn an array-like collection into a real array', () => {

    // Can't test a DOM collection so we'll run test on arguments object
    let returnArgs = () => arguments;
    let argumentsObjectToArray = F.arrayify(returnArgs('string', 3));
    let testIfArray = Array.isArray(argumentsObjectToArray);

    expect(testIfArray).to.be.true;

  });
});

describe('composify', () => {
  it('should return a function', () => {

    let actual = typeof F.composify();
    let expected = 'function';

    assert.equal(actual, expected);

  });
});

describe('currify', () => {
  it('should return a function', () => {

    let actual = typeof F.currify();
    let expected = 'function';

    assert.equal(actual, expected);

  });
});

describe('currify', () => {
  it('should return a function that takes a function as an argument', () => {

    let add = (a, b) => a + b;
    let curredFunction = F.currify(add);

    let actual = typeof curredFunction;
    let expected = 'function';

    assert.equal(actual, expected);

  });
});

describe('currify', () => {
  it('should return the result of a curried function', () => {

    let add = (a, b) => a + b;
    let curriedAdd = F.currify(add);
    let add5 = curriedAdd(5);

    let actual = add5(6);
    let expected = 11;

    assert.equal(actual, expected);

  });
});

describe('defuncify', () => {
  it('should create a method property from a regular function...', () => {

    class Person {}

    let reverseString = str => str.split('').reverse().join('');
    Person.prototype.reverseString = F.defuncify(reverseString);

    expect('reverseString' in Person.prototype).to.be.true;

  });
});

describe('defuncify', () => {
  it('...and property should be a function', () => {

    class Person {}

    let reverseString = str => str.split('').reverse().join('');
    Person.prototype.reverseString = F.defuncify(reverseString);

    let actual = typeof Person.prototype.reverseString;
    let expected = 'function';

    assert.equal(actual, expected);

  });
});

describe('falsify', () => {
  it('Should return a predicate function that is the opposite of original function', () => {

    let isTrue = () => true;
    let isFalse = F.falsify(isTrue);

    expect(isFalse() === !isTrue()).to.be.true;

  });
});

// todo: fillify

describe('flattify', () => {
  it('Should return an array', () => {

    let arr = [1, 2, ['3'], true, [[false, 'a'], 'b'], 'c'];
    let flattenedArray = F.flattify(arr);

    expect(Array.isArray(flattenedArray)).to.be.true;

  });
});

describe('flattify', () => {
  it('Should return a flattened array that contains no nested arrays', () => {

    let arr = [1, 2, ['3'], true, [[false, 'a'], 'b'], 'c'];
    let flattenedArray = F.flattify(arr);

    let containsNoNestedArrays = flattenedArray.every(v => !Array.isArray(v));

    expect(containsNoNestedArrays).to.be.true;

  });
});
<|endoftext|>


<commit_before>/* eslint-env mocha */
'use strict'

const expect = require('chai').expect
const BlockService = require('ipfs-blocks').BlockService
const ipld = require('ipld')
const multihash = require('multihashing')
const async = require('async')

const IPLDService = require('../src').IPLDService
const resolve = require('../src').resolve

module.exports = (repo) => {
  const bs = new BlockService(repo)
  const ipldService = new IPLDService(bs)

  describe('IPLDService', () => {
    it('throws when not passed a repo', () => {
      expect(() => new IPLDService()).to.throw(/requires a BlockService/)
    })

    it('adds an ipld node', (done) => {
      const node = {
        name: 'hello.txt',
        size: 11
      }

      ipldService.add(node, (err) => {
        expect(err).to.not.exist
        done()
      })
    })

    it('gets an ipld node', (done) => {
      const node = {
        name: 'world.txt',
        size: 11
      }

      ipldService.add(node, (err) => {
        expect(err).to.not.exist

        const mh = multihash(ipld.marshal(node), 'sha2-256')

        ipldService.get(mh, (err, fetchedNode) => {
          expect(err).to.not.exist
          expect(node).to.deep.equal(fetchedNode)
          done()
        })
      })
    })

    it('get ipld nodes recursively', (done) => {
      // 1 -> 2 -> 3
      const node1 = {data: '1'}
      const node2 = {data: '2'}
      const node3 = {data: '3'}

      node2.ref = {
        '@link': ipld.multihash(ipld.marshal(node3))
      }

      node1.ref = {
        '@link': ipld.multihash(ipld.marshal(node2))
      }

      async.series([
        (cb) => ipldService.add(node1, cb),
        (cb) => ipldService.add(node2, cb),
        (cb) => ipldService.add(node3, cb),
        (cb) => {
          const mh = multihash(ipld.marshal(node1), 'sha2-256')
          ipldService.getRecursive(mh, (err, nodes) => {
            expect(err).to.not.exist
            expect(nodes.length).to.equal(3)
            cb()
          })
        }
      ], (err) => {
        expect(err).to.not.exist
        done()
      })
    })

    it('removes and ipld node', (done) => {
      const node = {data: 'short lived node'}

      ipldService.add(node, (err) => {
        expect(err).to.not.exist
        const mh = multihash(ipld.marshal(node), 'sha2-256')

        ipldService.get(mh, (err, fetchedNode) => {
          expect(err).to.not.exist

          ipldService.remove(mh, (err) => {
            expect(err).to.not.exist

            ipldService.get(mh, (err) => {
              expect(err).to.exist
              done()
            })
          })
        })
      })
    })
  })

  describe('resolve', () => {
    describe('inside a single object', (done) => {
      const node = {
        string: 'hello',
        number: 42,
        object: {
          title: 'world'
        },
        numbers: [0, 1, 2],
        objects: [{
          title: 'test'
        }],
        multiple: {
          levels: {
            down: 'all good!'
          }
        }
      }
      const mh = ipld.multihash(ipld.marshal(node))

      before((done) => {
        ipldService.add(node, done)
      })

      it('resolves direct leaves of type string', (done) => {
        resolve(ipldService, `${mh}/string`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql('hello')
          done()
        })
      })

      it('resolves direct leaves of type number', (done) => {
        resolve(ipldService, `${mh}/number`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(42)
          done()
        })
      })

      it('resolves direct leaves of type object', (done) => {
        resolve(ipldService, `${mh}/object`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql({
            title: 'world'
          })
          done()
        })
      })

      it('resolves subpaths', (done) => {
        resolve(ipldService, `${mh}/multiple/levels/down`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql('all good!')
          done()
        })
      })

      it('resolves arrays of primitives', (done) => {
        resolve(ipldService, `${mh}/numbers/1`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(1)
          done()
        })
      })

      it('resolves arrays of objects', (done) => {
        resolve(ipldService, `${mh}/objects/0/title`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql('test')
          done()
        })
      })
    })

    describe('links are hashes', () => {
      const aliceName = 'Alice'
      const aliceAbout = {
        age: 22
      }
      const bob = {
        name: 'Bob'
      }
      const alice = {
        name: {
          '@link': ipld.multihash(aliceName)
        },
        about: {
          '@link': ipld.multihash(ipld.marshal(aliceAbout))
        },
        friends: [{
          '@link': ipld.multihash(ipld.marshal(bob))
        }]
      }
      const mh = ipld.multihash(ipld.marshal(alice))

      before((done) => {
        async.series([
          (cb) => ipldService.add(aliceName, cb),
          (cb) => ipldService.add(aliceAbout, cb),
          (cb) => ipldService.add(alice, cb),
          (cb) => ipldService.add(bob, cb)
        ], done)
      })

      it('resolves link to string', (done) => {
        resolve(ipldService, `${mh}/name`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(aliceName)
          done()
        })
      })

      it('resolves link to object', (done) => {
        resolve(ipldService, `${mh}/about`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(aliceAbout)
          done()
        })
      })

      it('resolves link to property in a different object', (done) => {
        resolve(ipldService, `${mh}/about/age`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(aliceAbout.age)
          done()
        })
      })

      it('resolves link to an element in array', (done) => {
        resolve(ipldService, `${mh}/friends/0`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(bob)
          done()
        })
      })

      it('resolves link to property in an element in array', (done) => {
        resolve(ipldService, `${mh}/friends/0/name`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(bob.name)
          done()
        })
      })
    })

    describe('links are merkle paths', () => {
      const draft = {
        title: 'Title of the blogpost'
      }

      const alice = {
        name: 'Alice'
      }

      const author = {
        name: {
          '@link': `/${ipld.multihash(ipld.marshal(alice))}/name`
        }
      }

      const blogpost = {
        title: {
          '@link': `/${ipld.multihash(ipld.marshal(draft))}/title`
        },
        author: {
          '@link': `/ipfs/${ipld.multihash(ipld.marshal(author))}`
        }
      }

      const mh = ipld.multihash(ipld.marshal(blogpost))

      before((done) => {
        async.series([
          (cb) => ipldService.add(draft, cb),
          (cb) => ipldService.add(alice, cb),
          (cb) => ipldService.add(author, cb),
          (cb) => ipldService.add(blogpost, cb)
        ], done)
      })

      it('merkle-link pointing to a string', (done) => {
        resolve(ipldService, `${mh}/title`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(draft.title)
          done()
        })
      })

      it('merkle-link pointing to an object', (done) => {
        resolve(ipldService, `${mh}/author`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(author)
          done()
        })
      })

      it('merkle-link pointing to link to an object', (done) => {
        resolve(ipldService, `${mh}/author/name`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(alice.name)
          done()
        })
      })

      it('ipfs merkle-link to an object', (done) => {
        resolve(ipldService, `/ipfs/${mh}/author`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(author)
          done()
        })
      })
    })
  })
}
<commit_msg>test(resolve): Drop string test<commit_after>/* eslint-env mocha */
'use strict'

const expect = require('chai').expect
const BlockService = require('ipfs-blocks').BlockService
const ipld = require('ipld')
const multihash = require('multihashing')
const async = require('async')

const IPLDService = require('../src').IPLDService
const resolve = require('../src').resolve

module.exports = (repo) => {
  const bs = new BlockService(repo)
  const ipldService = new IPLDService(bs)

  describe('IPLDService', () => {
    it('throws when not passed a repo', () => {
      expect(() => new IPLDService()).to.throw(/requires a BlockService/)
    })

    it('adds an ipld node', (done) => {
      const node = {
        name: 'hello.txt',
        size: 11
      }

      ipldService.add(node, (err) => {
        expect(err).to.not.exist
        done()
      })
    })

    it('gets an ipld node', (done) => {
      const node = {
        name: 'world.txt',
        size: 11
      }

      ipldService.add(node, (err) => {
        expect(err).to.not.exist

        const mh = multihash(ipld.marshal(node), 'sha2-256')

        ipldService.get(mh, (err, fetchedNode) => {
          expect(err).to.not.exist
          expect(node).to.deep.equal(fetchedNode)
          done()
        })
      })
    })

    it('get ipld nodes recursively', (done) => {
      // 1 -> 2 -> 3
      const node1 = {data: '1'}
      const node2 = {data: '2'}
      const node3 = {data: '3'}

      node2.ref = {
        '@link': ipld.multihash(ipld.marshal(node3))
      }

      node1.ref = {
        '@link': ipld.multihash(ipld.marshal(node2))
      }

      async.series([
        (cb) => ipldService.add(node1, cb),
        (cb) => ipldService.add(node2, cb),
        (cb) => ipldService.add(node3, cb),
        (cb) => {
          const mh = multihash(ipld.marshal(node1), 'sha2-256')
          ipldService.getRecursive(mh, (err, nodes) => {
            expect(err).to.not.exist
            expect(nodes.length).to.equal(3)
            cb()
          })
        }
      ], (err) => {
        expect(err).to.not.exist
        done()
      })
    })

    it('removes and ipld node', (done) => {
      const node = {data: 'short lived node'}

      ipldService.add(node, (err) => {
        expect(err).to.not.exist
        const mh = multihash(ipld.marshal(node), 'sha2-256')

        ipldService.get(mh, (err, fetchedNode) => {
          expect(err).to.not.exist

          ipldService.remove(mh, (err) => {
            expect(err).to.not.exist

            ipldService.get(mh, (err) => {
              expect(err).to.exist
              done()
            })
          })
        })
      })
    })
  })

  describe('resolve', () => {
    describe('inside a single object', (done) => {
      const node = {
        string: 'hello',
        number: 42,
        object: {
          title: 'world'
        },
        numbers: [0, 1, 2],
        objects: [{
          title: 'test'
        }],
        multiple: {
          levels: {
            down: 'all good!'
          }
        }
      }
      const mh = ipld.multihash(ipld.marshal(node))

      before((done) => {
        ipldService.add(node, done)
      })

      it('resolves direct leaves of type string', (done) => {
        resolve(ipldService, `${mh}/string`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql('hello')
          done()
        })
      })

      it('resolves direct leaves of type number', (done) => {
        resolve(ipldService, `${mh}/number`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(42)
          done()
        })
      })

      it('resolves direct leaves of type object', (done) => {
        resolve(ipldService, `${mh}/object`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql({
            title: 'world'
          })
          done()
        })
      })

      it('resolves subpaths', (done) => {
        resolve(ipldService, `${mh}/multiple/levels/down`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql('all good!')
          done()
        })
      })

      it('resolves arrays of primitives', (done) => {
        resolve(ipldService, `${mh}/numbers/1`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(1)
          done()
        })
      })

      it('resolves arrays of objects', (done) => {
        resolve(ipldService, `${mh}/objects/0/title`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql('test')
          done()
        })
      })
    })

    describe('links are hashes', () => {
      const aliceAbout = {
        age: 22
      }
      const bob = {
        name: 'Bob'
      }
      const alice = {
        name: 'Alice',
        about: {
          '@link': ipld.multihash(ipld.marshal(aliceAbout))
        },
        friends: [{
          '@link': ipld.multihash(ipld.marshal(bob))
        }]
      }
      const mh = ipld.multihash(ipld.marshal(alice))

      before((done) => {
        async.series([
          (cb) => ipldService.add(aliceAbout, cb),
          (cb) => ipldService.add(alice, cb),
          (cb) => ipldService.add(bob, cb)
        ], done)
      })

      it('link to object', (done) => {
        resolve(ipldService, `${mh}/about`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(aliceAbout)
          done()
        })
      })

      it('link to property in a different object', (done) => {
        resolve(ipldService, `${mh}/about/age`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(aliceAbout.age)
          done()
        })
      })

      it('link to an element in array', (done) => {
        resolve(ipldService, `${mh}/friends/0`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(bob)
          done()
        })
      })

      it('link to property in an element in array', (done) => {
        resolve(ipldService, `${mh}/friends/0/name`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(bob.name)
          done()
        })
      })
    })

    describe('links are merkle paths', () => {
      const draft = {
        title: 'Title of the blogpost'
      }

      const alice = {
        name: 'Alice'
      }

      const author = {
        name: {
          '@link': `/${ipld.multihash(ipld.marshal(alice))}/name`
        }
      }

      const blogpost = {
        title: {
          '@link': `/${ipld.multihash(ipld.marshal(draft))}/title`
        },
        author: {
          '@link': `/ipfs/${ipld.multihash(ipld.marshal(author))}`
        }
      }

      const mh = ipld.multihash(ipld.marshal(blogpost))

      before((done) => {
        async.series([
          (cb) => ipldService.add(draft, cb),
          (cb) => ipldService.add(alice, cb),
          (cb) => ipldService.add(author, cb),
          (cb) => ipldService.add(blogpost, cb)
        ], done)
      })

      it('merkle-link pointing to a string', (done) => {
        resolve(ipldService, `${mh}/title`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(draft.title)
          done()
        })
      })

      it('merkle-link pointing to an object', (done) => {
        resolve(ipldService, `${mh}/author`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(author)
          done()
        })
      })

      it('merkle-link pointing to link to an object', (done) => {
        resolve(ipldService, `${mh}/author/name`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(alice.name)
          done()
        })
      })

      it('ipfs merkle-link to an object', (done) => {
        resolve(ipldService, `/ipfs/${mh}/author`, (err, res) => {
          expect(err).to.not.exist
          expect(res).to.be.eql(author)
          done()
        })
      })
    })
  })
}
<|endoftext|>


<commit_before>import * as RA from '../src';
import eq from './shared/eq';

describe('isNotArray', function() {
  it('tests a value for complement of `Array`', function() {
    eq(RA.isNotArray([]), false);
    eq(RA.isNotArray([1]), false);
    eq(RA.isNotArray(new Array()), false);
    eq(RA.isNotArray(Array.prototype), false);

    eq(RA.isNotArray(void 0), true);
    eq(RA.isNotArray({}), true);
    eq(RA.isNotArray(null), true);
    eq(RA.isNotArray(undefined), true);
    eq(RA.isNotArray(17), true);
    eq(RA.isNotArray('Array'), true);
    eq(RA.isNotArray(true), true);
    eq(RA.isNotArray(true), true);
    eq(RA.isNotArray({ __proto__: Array.prototype }), true);
  });
});
<commit_msg>test(isNotArray): make tests consitent<commit_after>import * as R from 'ramda';
import { assert } from 'chai';

import * as RA from '../src';

describe('isNotArray', function() {
  context('given non array value', function() {
    specify('should return true', function() {
      assert.isTrue(RA.isNotArray(void 0));
      assert.isTrue(RA.isNotArray({}));
      assert.isTrue(RA.isNotArray(null));
      assert.isTrue(RA.isNotArray(undefined));
      assert.isTrue(RA.isNotArray(17));
      assert.isTrue(RA.isNotArray('Array'));
      assert.isTrue(RA.isNotArray(true));
      assert.isTrue(RA.isNotArray(true));
      assert.isTrue(RA.isNotArray({ __proto__: Array.prototype }));
    });
  });

  context('given array value', function() {
    specify('should return false', function() {
      assert.isFalse(RA.isNotArray([]));
      assert.isFalse(RA.isNotArray([1]));
      assert.isFalse(RA.isNotArray(new Array()));
      assert.isFalse(RA.isNotArray(Array.prototype));
    });
  });

  it('should support placeholder to specify "gaps"', function() {
    const isNotArray = RA.isNotArray(R.__);

    assert.isTrue(isNotArray(-1));
  });
});
<|endoftext|>


<commit_before><commit_msg>docs(ngAnimate): fix typo<commit_after><|endoftext|>


<commit_before>import * as RA from '../src';
import eq from './shared/eq';

describe('isNotEmpty', function() {
  it('returns true for null', function() {
    eq(RA.isNotEmpty(null), true);
  });

  it('returns true for undefined', function() {
    eq(RA.isNotEmpty(undefined), true);
  });

  it('returns false for empty string', function() {
    eq(RA.isNotEmpty(''), false);
    eq(RA.isNotEmpty(' '), true);
  });

  it('returns false for empty array', function() {
    eq(RA.isNotEmpty([]), false);
    eq(RA.isNotEmpty([[]]), true);
  });

  it('returns false for empty object', function() {
    eq(RA.isNotEmpty({}), false);
    eq(RA.isNotEmpty({ x: 0 }), true);
  });

  it('returns false for empty arguments object', function() {
    eq(
      RA.isNotEmpty(
        (function() {
          return arguments;
        })()
      ),
      false
    );
    eq(
      RA.isNotEmpty(
        (function() {
          return arguments;
        })(0)
      ),
      true
    );
  });

  it('returns true for every other value', function() {
    eq(RA.isNotEmpty(0), true);
    eq(RA.isNotEmpty(NaN), true);
    eq(RA.isNotEmpty(['']), true);
  });
});
<commit_msg>test(isNotEmpty): make tests consistent<commit_after>import { assert } from 'chai';
import * as R from 'ramda';

import * as RA from '../src';

describe('isNotEmpty', function() {
  context('given null', function() {
    specify('should return true', function() {
      assert.isTrue(RA.isNotEmpty(null));
    });
  });

  context('given undefined', function() {
    specify('should return true', function() {
      assert.isTrue(RA.isNotEmpty(undefined));
    });
  });

  context('given string', function() {
    context('and the string is empty', function() {
      specify('should return false', function() {
        assert.isFalse(RA.isNotEmpty(''));
      });
    });

    context('and the string contains empty spaces', function() {
      specify('should return true', function() {
        assert.isTrue(RA.isNotEmpty(' '));
      });
    });
  });

  context('given array', function() {
    context('and the array is empty', function() {
      specify('should return false', function() {
        assert.isFalse(RA.isNotEmpty([]));
      });
    });

    context('and the array contains another empty array', function() {
      specify('should return true', function() {
        assert.isTrue(RA.isNotEmpty([[]]));
      });
    });
  });

  context('given object', function() {
    context('and the object is empty', function() {
      specify('should return false', function() {
        assert.isFalse(RA.isNotEmpty({}));
      });
    });

    context('and the object contains property', function() {
      specify('should return true', function() {
        assert.isTrue(RA.isNotEmpty({ x: 0 }));
      });
    });
  });

  context('given arguments object', function() {
    context('and arguments objects is empty', function() {
      specify('should return false', function() {
        assert.isFalse(
          RA.isNotEmpty(
            (function() {
              return arguments;
            })()
          )
        );
      });
    });

    context('and arguments object is not empty', function() {
      specify('should return true', function() {
        assert.isTrue(
          RA.isNotEmpty(
            (function() {
              return arguments;
            })(0)
          )
        );
      });
    });
  });

  context('given some non empty values', function() {
    specify('should return true', function() {
      assert.isTrue(RA.isNotEmpty(0));
      assert.isTrue(RA.isNotEmpty(NaN));
      assert.isTrue(RA.isNotEmpty(['']));
    });
  });

  it('should support placeholder to specify "gaps"', function() {
    const isNotEmpty = RA.isNotEmpty(R.__);

    assert.isTrue(isNotEmpty(-1));
  });
});
<|endoftext|>


<commit_before><commit_msg>add prinzipien page<commit_after><|endoftext|>