不要怂,就是干,撸起袖子干!

promise.spec.js 8.78 KB
var buster    = require("buster")
  , Helpers   = require('./buster-helpers')
  , DataTypes = require(__dirname + "/../lib/data-types")
  , dialect   = Helpers.getTestDialect()
  , _         = require('lodash')

buster.spec.expose()
buster.testRunner.timeout = 1000

describe(Helpers.getTestDialectTeaser("Promise"), function () {
  var sequelize = Helpers.createSequelizeInstance({dialect: dialect})
    , User = sequelize.define('User', {
      username:  { type: DataTypes.STRING },
      touchedAt: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },
      aNumber:   { type: DataTypes.INTEGER },
      bNumber:   { type: DataTypes.INTEGER },

      validateTest: {
        type: DataTypes.INTEGER,
        allowNull: true,
        validate: {isInt: true}
      },
      validateCustom: {
        type: DataTypes.STRING,
        allowNull: true,
        validate: {len: {msg: 'Length failed.', args: [1, 20]}}
      },

      dateAllowNullTrue: {
        type: DataTypes.DATE,
        allowNull: true
      }
    })

  before(function(done) {
    var self = this
    self.sequelize = sequelize
    self.User      = User
    Helpers.clearDatabase(this.sequelize, function(){
      self.User.sync({ force: true }).then(function() {done()}, done)
    })
  })

  describe('increment', function () {
    before(function(done) {
      this.User.create({ id: 1, aNumber: 0, bNumber: 0 }).done(done)
    });

    it('with array', function(done) {
      var self = this
      // Select something
      this.User.find(1).then(function(user1) {
        return user1.increment(['aNumber'], 2)
      }).then(function(user2) {
        return self.User.find(1)
      }).then(function(user3) {
        expect(user3.aNumber).toBe(2)
        done()
      }, done)
    });

    it('should still work right with other concurrent updates', function(done) {
      var self = this
      // Select something
      this.User.find(1).then(function (user1) {
        // Select the user again (simulating a concurrent query)
        return self.User.find(1).then(function (user2) {
          return user2.updateAttributes({
            aNumber: user2.aNumber + 1
          }).then(function() {
            return user1.increment(['aNumber'], 2)
          }).then(function() {
            return self.User.find(1)
          }).then(function(user5) {
            expect(user5.aNumber).toBe(3)
            done()
          }, done)
        })
      })
    })

    it('with key value pair', function(done) {
      var self = this
      // Select something
      this.User.find(1).then(function(user1) {
        return user1.increment({ 'aNumber': 1, 'bNumber': 2})
      }).then(function () {
        return self.User.find(1)
      }).then(function (user3) {
        expect(user3.aNumber).toBe(1)
        expect(user3.bNumber).toBe(2)
        done()
      }, done)
    });
  });

  describe('decrement', function () {
    before(function (done) {
      this.User.create({ id: 1, aNumber: 0, bNumber: 0 }).done(done)
    });

    it('with array', function(done) {
      var self = this
      // Select something
      this.User.find(1).then(function(user1) {
        return user1.decrement(['aNumber'], 2)
      }).then(function(user2) {
        return self.User.find(1)
      }).then(function(user3) {
        expect(user3.aNumber).toBe(-2)
        done()
      }, done)
    });

    it('with single field', function(done) {
      var self = this
      // Select something
      this.User.find(1).then(function(user1) {
        return user1.decrement(['aNumber'], 2)
      }).then(function(user3) {
        return self.User.find(1)
      }).then(function (user3) {
        expect(user3.aNumber).toBe(-2)
        done()
      }, done)
    });

    it('should still work right with other concurrent decrements', function(done) {
      var self = this
      // Select something
      this.User.find(1).then(function(user1) {
        var _done = _.after(3, function() {
          self.User.find(1).then(function(user2) {
            expect(user2.aNumber).toEqual(-6)
            done()
          })
        })

        user1.decrement(['aNumber'], 2).done(_done)
        user1.decrement(['aNumber'], 2).done(_done)
        user1.decrement(['aNumber'], 2).done(_done)
      })
    })
  })

  describe('reload', function () {
    it("should return a reference to the same DAO instead of creating a new one", function(done) {
      this.User.create({ username: 'John Doe' }).then(function(originalUser) {
        return originalUser.updateAttributes({ username: 'Doe John' }).then(function () {
          return originalUser.reload()
        }).then(function(updatedUser) {
          expect(originalUser === updatedUser).toBeTrue()
          done()
        }, done)
      })
    })

    it("should update the values on all references to the DAO", function(done) {
      var self = this
      this.User.create({ username: 'John Doe' }).then(function(originalUser) {
        return self.User.find(originalUser.id).then(function(updater) {
          return updater.updateAttributes({ username: 'Doe John' })
        }).then(function () {
          // We used a different reference when calling updateAttributes, so originalUser is now out of sync
          expect(originalUser.username).toEqual('John Doe')
          return originalUser.reload()
        }).then(function(updatedUser) {
          expect(originalUser.username).toEqual('Doe John')
          expect(updatedUser.username).toEqual('Doe John')
          done()
        }, done)
      })
    })


    it("should update the associations as well", function (done) {
      var Book = this.sequelize.define('Book', { title:   Helpers.Sequelize.STRING })
        , Page = this.sequelize.define('Page', { content: Helpers.Sequelize.TEXT })

      Book.hasMany(Page)
      Page.belongsTo(Book)

      Book.sync({ force: true }).then(function() {
        Page.sync({ force: true }).then(function() {
          return Book.create({ title: 'A very old book' })
        }).then(function (book) {
          return Page.create({ content: 'om nom nom' }).then(function(page) {
            return book.setPages([ page ]).then(function() {
              return Book.find({
                where: (dialect === 'postgres' ? '"Books"."id"=' : '`Books`.`id`=') + book.id,
                include: [Page]
              }).then(function (leBook) {
                return page.updateAttributes({ content: 'something totally different' }).then(function (page) {
                  expect(leBook.pages[0].content).toEqual('om nom nom')
                  expect(page.content).toEqual('something totally different')

                  return leBook.reload().then(function (leBook) {
                    expect(leBook.pages[0].content).toEqual('something totally different')
                    expect(page.content).toEqual('something totally different')

                    done()
                  })
                })
              })
            })
          })
        }, done)
      })
    })
  })

  describe('complete', function () {
    it("gets triggered if an error occurs", function(done) {
      this.User.find({ where: "asdasdasd" }).then(null, function(err) {
        expect(err).toBeDefined()
        expect(err.message).toBeDefined()
        done()
      })
    })

    it("gets triggered if everything was ok", function(done) {
      this.User.count().then(function(result) {
        expect(result).toBeDefined()
        done()
      })
    })
  })

  describe('save', function () {
    it('should fail a validation upon creating', function(done) {
      this.User.create({aNumber: 0, validateTest: 'hello'}).then(null, function(err) {
        expect(err).toBeDefined()
        expect(err).toBeObject()
        expect(err.validateTest).toBeArray()
        expect(err.validateTest[0]).toBeDefined()
        expect(err.validateTest[0].indexOf('Invalid integer')).toBeGreaterThan(-1)
        done()
      });
    })

    it('should fail a validation upon building', function(done) {
      this.User.build({aNumber: 0, validateCustom: 'aaaaaaaaaaaaaaaaaaaaaaaaaa'}).save()
      .then(null, function(err) {
        expect(err).toBeDefined()
        expect(err).toBeObject()
        expect(err.validateCustom).toBeDefined()
        expect(err.validateCustom).toBeArray()
        expect(err.validateCustom[0]).toBeDefined()
        expect(err.validateCustom[0]).toEqual('Length failed.')
        done()
      })
    })

    it('should fail a validation when updating', function(done) {
      this.User.create({aNumber: 0}).then(function (user) {
        return user.updateAttributes({validateTest: 'hello'})
      }).then(null, function(err) {
        expect(err).toBeDefined()
        expect(err).toBeObject()
        expect(err.validateTest).toBeDefined()
        expect(err.validateTest).toBeArray()
        expect(err.validateTest[0]).toBeDefined()
        expect(err.validateTest[0].indexOf('Invalid integer:')).toBeGreaterThan(-1)
        done()
      })
    })
  })
})