From 49be07545a644a433a25f1d776ad1de038893e17 Mon Sep 17 00:00:00 2001 From: Anatoliy Chakkaev Date: Tue, 26 Mar 2013 23:33:11 +0400 Subject: [PATCH 01/13] Rewriting tests --- test/basic-querying.test.js | 194 ++++++++++++++++++++++++++++++++++++ test/common.batch.js | 1 + test/common_test.js | 83 --------------- test/manipulation.test.js | 112 +++++++++++++++++++++ 4 files changed, 307 insertions(+), 83 deletions(-) create mode 100644 test/basic-querying.test.js create mode 100644 test/common.batch.js create mode 100644 test/manipulation.test.js diff --git a/test/basic-querying.test.js b/test/basic-querying.test.js new file mode 100644 index 00000000..2e3735af --- /dev/null +++ b/test/basic-querying.test.js @@ -0,0 +1,194 @@ +var db, User, should = require('should'); + +describe('basic-querying', function() { + + before(function() { + db = getSchema(); + + User = db.define('User', { + name: String, + email: {type: String, index: true}, + role: {type: String, index: true}, + order: {type: Number, index: true} + }); + + }); + + + describe('find', function() { + + before(function(done) { + User.destroyAll(done); + }); + + it('should query by id: not found', function(done) { + User.find(1, function(err, u) { + should.not.exist(u); + should.not.exist(err); + done(); + }); + }); + + it('should query by id: found', function(done) { + User.create(function(err, u) { + should.exist(u.id); + User.find(u.id, function(err, u) { + should.exist(u); + should.not.exist(err); + u.should.be.an.instanceOf(User); + done(); + }); + }); + }); + + }); + + describe('all', function() { + + before(seed); + + it('should query collection', function(done) { + User.all(function(err, users) { + should.exists(users); + should.not.exists(err); + users.should.have.lengthOf(6); + done(); + }); + }); + + it('should query filtered collection', function(done) { + User.all({where: {role: 'lead'}}, function(err, users) { + should.exists(users); + should.not.exists(err); + users.should.have.lengthOf(2); + done(); + }); + }); + + it('should query collection sorted by numeric field', function(done) { + User.all({order: 'order'}, function(err, users) { + should.exists(users); + should.not.exists(err); + users.forEach(function(u, i) { + u.order.should.eql(i + 1); + }); + done(); + }); + }); + + it('should query collection desc sorted by numeric field', function(done) { + User.all({order: 'order DESC'}, function(err, users) { + should.exists(users); + should.not.exists(err); + users.forEach(function(u, i) { + u.order.should.eql(users.length - i); + }); + done(); + }); + }); + + it('should query collection sorted by string field', function(done) { + User.all({order: 'name'}, function(err, users) { + should.exists(users); + should.not.exists(err); + users.shift().name.should.equal('George Harrison'); + users.shift().name.should.equal('John Lennon'); + users.pop().name.should.equal('Stuart Sutcliffe'); + done(); + }); + }); + + it('should query collection desc sorted by string field', function(done) { + User.all({order: 'name DESC'}, function(err, users) { + should.exists(users); + should.not.exists(err); + users.pop().name.should.equal('George Harrison'); + users.pop().name.should.equal('John Lennon'); + users.shift().name.should.equal('Stuart Sutcliffe'); + done(); + }); + }); + + }); + + describe('count', function() { + + before(seed); + + it('should query total count', function(done) { + User.count(function(err, n) { + should.not.exist(err); + should.exist(n); + n.should.equal(6); + done(); + }); + }); + + it('should query filtered count', function(done) { + User.count({role: 'lead'}, function(err, n) { + should.not.exist(err); + should.exist(n); + n.should.equal(2); + done(); + }); + }); + }); + + describe('exists', function() { + + before(seed); + + it('should check whether record exist', function(done) { + User.exists(1, function(err, exists) { + should.not.exist(err); + should.exist(exists); + exists.should.be.true; + done(); + }); + }); + + it('should check whether record not exist', function(done) { + User.destroyAll(function() { + User.exists(42, function(err, exists) { + should.not.exist(err); + exists.should.be.false; + done(); + }); + }); + }); + + }); + +}); + +function seed(done) { + var count = 0; + var beatles = [ + { id: 1, + name: 'John Lennon', + mail: 'john@b3atl3s.co.uk', + role: 'lead', + order: 2 + }, { + name: 'Paul McCartney', + mail: 'paul@b3atl3s.co.uk', + role: 'lead', + order: 1 + }, + {name: 'George Harrison', order: 5}, + {name: 'Ringo Starr', order: 6}, + {name: 'Pete Best', order: 4}, + {name: 'Stuart Sutcliffe', order: 3} + ]; + User.destroyAll(function() { + beatles.forEach(function(beatle) { + User.create(beatle, ok); + }); + }); + + function ok() { + if (++count === beatles.length) { + done(); + } + } +} diff --git a/test/common.batch.js b/test/common.batch.js new file mode 100644 index 00000000..777562f5 --- /dev/null +++ b/test/common.batch.js @@ -0,0 +1 @@ +require('./basic-querying.test.js'); diff --git a/test/common_test.js b/test/common_test.js index f6b085c0..dad73c18 100644 --- a/test/common_test.js +++ b/test/common_test.js @@ -209,42 +209,6 @@ function testOrm(schema) { test.done(); }); - it('should be exported to JSON', function (test) { - var outString = '{"title":"hello, json","date":1,"published":false,"likes":[],"related":[],"id":1}' - if (schema.name === 'nano') - outString = '{"title":"hello, json","subject":null,"content":null,"date":1,"published":false,"likes":[],"related":[],"_rev":null,"id":1,"userId":null}' - - test.equal(JSON.stringify(new Post({id: 1, title: 'hello, json', date: 1})),outString); - test.done(); - }); - - it('should create object', function (test) { - Post.create(function (err, post) { - if (err) throw err; - test.ok(post.id, 'Id present'); - test.ok(!post.title, 'Title is blank'); - Post.exists(post.id, function (err, exists) { - if (err) throw err; - test.ok(exists); - test.done(); - }); - }); - }); - - it('should create object without callback', function (test) { - var uniqueTitle = 'Unique title ' + Date.now(); - Post.create({title: uniqueTitle}); - - setTimeout(delayedCallback, 100); - - function delayedCallback() { - Post.all({where: {title: uniqueTitle}}, function (err, posts) { - test.equal(posts.length, 1); - test.done(); - }); - } - }); - it('should save object', function (test) { var title = 'Initial title', title2 = 'Hello world', date = new Date; @@ -420,53 +384,6 @@ function testOrm(schema) { }); }); - it('should fetch count of records in collection', function (test) { - Post.count(function (err, count) { - console.log(countOfposts, count); - test.equal(countOfposts, count, 'unfiltered count'); - Post.count({title: 'title'}, function (err, count) { - console.log(countOfpostsFiltered, count, 'filtered count'); - test.equal(countOfpostsFiltered, count, 'filtered count'); - test.done(); - }); - }); - }); - - it('should find filtered set of records', function (test) { - var wait = 1; - - // exact match with string - Post.all({where: {title: 'New title'}}, function (err, res) { - var pass = true; - res.forEach(function (r) { - if (r.title != 'New title') pass = false; - }); - test.ok(res.length > 0, 'Exact match with string returns dataset'); - test.ok(pass, 'Exact match with string'); - done(); - }); - - // matching null - // Post.all({where: {title: null}}, function (err, res) { - - // var pass = true; - // res.forEach(function (r) { - // if (r.title != null) pass = false; - // }); - // test.ok(res.length > 0, 'Matching null returns dataset'); - // test.ok(pass, 'Matching null'); - // done(); - // }); - - function done() { - if (--wait === 0) { - test.done(); - } - } - - }); - - it('should find records filtered with multiple attributes', function (test) { var d = new Date; Post.create({title: 'title', content: 'content', published: true, date: d}, function (err, post) { diff --git a/test/manipulation.test.js b/test/manipulation.test.js new file mode 100644 index 00000000..f0b4052f --- /dev/null +++ b/test/manipulation.test.js @@ -0,0 +1,112 @@ +var db, Person, should = require('should'); + +describe('manipulation', function() { + + before(function(done) { + db = getSchema(); + + Person = db.define('Person', { + name: String, + gender: String, + married: Boolean, + age: {type: Number, index: true}, + dob: Date, + createdAt: {type: Number, default: Date.now} + }); + + db.automigrate(done); + + }); + + describe('create', function() { + + before(function(done) { + Person.destroyAll(done); + }); + + it('should create instance', function(done) { + Person.create({name: 'Anatoliy'}, function(err, p) { + p.name.should.equal('Anatoliy'); + should.not.exist(err); + should.exist(p); + Person.find(p.id, function(err, person) { + person.id.should.equal(p.id); + person.name.should.equal('Anatoliy'); + done(); + }); + }); + }); + + it('should work when called without callback', function(done) { + Person.afterCreate = function(next) { + this.should.be.an.instanceOf(Person); + this.name.should.equal('Nickolay'); + should.exist(this.id); + Person.afterCreate = null; + next(); + setTimeout(done, 10); + }; + Person.create({name: 'Nickolay'}); + }); + + it('should create instance with blank data', function(done) { + Person.create(function(err, p) { + should.not.exist(err); + should.exist(p); + should.not.exists(p.name); + Person.find(p.id, function(err, person) { + person.id.should.equal(p.id); + should.not.exists(person.name); + done(); + }); + }); + }); + + it('should work when called with no data and callback', function(done) { + Person.afterCreate = function(next) { + this.should.be.an.instanceOf(Person); + should.not.exist(this.name); + should.exist(this.id); + Person.afterCreate = null; + next(); + setTimeout(done, 10); + }; + Person.create(); + }); + }); + + describe('save', function() { + it('should save new object'); + it('should save existing object'); + it('should save invalid object (skipping validation)'); + it('should save throw error on validation'); + }); + + describe('destroy', function() { + it('should destroy record'); + it('should destroy all records'); + it('should destroy filtered set of records'); + }); + + describe('initialize', function() { + it('should initialize object properly', function() { + var hw = 'Hello word', + now = Date.now(), + person = new Person({name: hw}); + + person.name.should.equal(hw); + person.propertyChanged('name').should.be.false; + person.name = 'Goodbye, Lenin'; + person.name_was.should.equal(hw); + person.propertyChanged('name').should.be.true; + (person.createdAt >= now).should.be.true; + person.isNewRecord().should.be.true; + }); + + it('should work when constructor called as function', function() { + var p = Person({name: 'John Resig'}); + p.should.be.an.instanceOf(Person); + p.name.should.equal('John Resig'); + }); + }); +}); From 58e23495753cbfebee1d0b6520d0590fe16d1deb Mon Sep 17 00:00:00 2001 From: Anatoliy Chakkaev Date: Tue, 26 Mar 2013 23:33:40 +0400 Subject: [PATCH 02/13] Fix memory adapter to support lowercase desc order --- lib/adapters/memory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/adapters/memory.js b/lib/adapters/memory.js index fbd748cc..45caa32f 100644 --- a/lib/adapters/memory.js +++ b/lib/adapters/memory.js @@ -87,7 +87,7 @@ Memory.prototype.all = function all(model, filter, callback) { var m = key.match(/\s+(A|DE)SC$/i); if (m) { key = key.replace(/\s+(A|DE)SC/i, ''); - if (m[1] === 'DE') reverse = -1; + if (m[1].toLowerCase() === 'de') reverse = -1; } orders[i] = {"key": key, "reverse": reverse}; }); From 5e24bd960f997d2c28001048d8165bafc599ff0a Mon Sep 17 00:00:00 2001 From: Anatoliy Chakkaev Date: Tue, 26 Mar 2013 23:34:01 +0400 Subject: [PATCH 03/13] Beautify things --- Makefile | 2 +- docs/footer.html | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 179ec182..157e86c4 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ docs/man/%.3: docs/%.md scripts/doc.sh docs/html/%.3.html: docs/%.md scripts/doc.sh docs/footer.html scripts/doc.sh $< $@ -docs/html/index.html: docs/jugglingdb.md scripts/doc.sh +docs/html/index.html: docs/jugglingdb.md scripts/doc.sh docs/footer.html scripts/doc.sh $< $@ man: $(MAN_DOCS) diff --git a/docs/footer.html b/docs/footer.html index 288bd0a8..4703a0d8 100644 --- a/docs/footer.html +++ b/docs/footer.html @@ -1,15 +1,17 @@