From d586af7250673ee711bccac2dc073e0f740f5997 Mon Sep 17 00:00:00 2001 From: Simon Ho Date: Sat, 28 Nov 2015 22:00:23 -0800 Subject: [PATCH 1/2] Cleanup - Remove console.log from unit test --- test/memory.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/memory.test.js b/test/memory.test.js index e8244392f..1b397a386 100644 --- a/test/memory.test.js +++ b/test/memory.test.js @@ -345,7 +345,6 @@ describe('Memory connector', function() { } }, function (err, users) { should.not.exist(err); - console.log(users); users.length.should.be.equal(5); done(); }); From 5d987f67f289c599c5c64e296d28f65d6e4d4df8 Mon Sep 17 00:00:00 2001 From: Simon Ho Date: Sat, 28 Nov 2015 22:14:39 -0800 Subject: [PATCH 2/2] Add model definition ObjectId support --- Makefile | 64 +++++++++++++++++++++--------------- lib/objectid.js | 12 +++++++ lib/types.js | 4 ++- package.json | 9 +++-- test/datatype.test.js | 25 +++++++++++++- test/e2e/model-definition.js | 59 +++++++++++++++++++++++++++++++++ test/objectid.test.js | 62 ++++++++++++++++++++++++++++++++++ 7 files changed, 204 insertions(+), 31 deletions(-) create mode 100644 lib/objectid.js create mode 100644 test/e2e/model-definition.js create mode 100644 test/objectid.test.js diff --git a/Makefile b/Makefile index 01f9cce2d..b430bf8c7 100644 --- a/Makefile +++ b/Makefile @@ -1,43 +1,55 @@ TESTER = ./node_modules/.bin/mocha OPTS = --growl TESTS = test/*.test.js +E2E_TEST_DIR = test/e2e/*.js -default: help +# Default target -.PHONY: clean -clean: - rm -rf $(CURDIR)/node_modules - -.PHONY: help -help: +.PHONY: help h +help h: @echo 'Usage: make [target]' @echo 'Targets:' - @echo ' clean Delete `node_modules`' - @echo ' help Print help (this message)' - @echo ' refresh Delete `node_modules` and run `npm install`' - @echo ' test Run tests in silent mode' - @echo ' test-verbose Run tests in verbose mode' - @echo ' testing Run tests continuously' - -.PHONY: refresh -refresh: clean - npm install - -.PHONY: test -test: + @echo ' e e2e Run end-to-end tests' + @echo ' h help Print help (this message)' + @echo ' t test[s] Run unit tests and e2e tests' + @echo ' u unit Run unit tests in silent mode' + @echo ' uv unit-verbose Run unit tests in verbose mode' + @echo ' uw unit-watch Run unit tests in watch (--watch) mode' + +# Targets + +.PHONY: e2e e +e2e e: + $(TESTER) --reporter spec $(E2E_TEST_DIR) + +.PHONY: test tests t +test tests t: unit e2e + +.PHONY: unit u +unit u: NO_DEPRECATION=loopback-datasource-juggler $(TESTER) $(OPTS) $(TESTS) -.PHONY: test-verbose -test-verbose: +.PHONY: unit-verbose uv +unit-verbose uv: $(TESTER) $(OPTS) --reporter spec $(TESTS) -.PHONY: testing -testing: +.PHONY: unit-watch uw +unit-watch uw: $(TESTER) $(OPTS) --watch $(TESTS) -# Deprecated targets +# Deprecated targest (left for backwards compat) .PHONY: about-testing about-testing: @echo 'DEPRECATED: Use `make help` instead' - make help + $(MAKE) help + +.PHONY: test-verbose +test-verbose: + @echo 'DEPRECATED: Use `make unit-verbose` instead' + $(MAKE) unit-verbose + +.PHONY: testing +testing: + @echo 'DEPRECATED: Use `make unit-watch` instead' + $(MAKE) unit-watch diff --git a/lib/objectid.js b/lib/objectid.js new file mode 100644 index 000000000..0ad928d5f --- /dev/null +++ b/lib/objectid.js @@ -0,0 +1,12 @@ +var ObjectId; + +try { + ObjectId = require('mongodb').ObjectId; +} catch(e) { + if (e.code === 'MODULE_NOT_FOUND') + throw e; +} + +module.exports = ObjectId; +module.exports.ObjectID = ObjectId; +module.exports.ObjectId = ObjectId; diff --git a/lib/types.js b/lib/types.js index 7c35adcef..e8b1baf27 100644 --- a/lib/types.js +++ b/lib/types.js @@ -36,6 +36,7 @@ Types.Any.prototype.toObject = Types.Any.prototype.toJSON = function () { module.exports = function (modelTypes) { var GeoPoint = require('./geo').GeoPoint; + var ObjectId = require('./objectid'); for(var t in Types) { modelTypes[t] = Types[t]; @@ -62,6 +63,7 @@ module.exports = function (modelTypes) { modelTypes.registerType(Array); modelTypes.registerType(GeoPoint); modelTypes.registerType(Object); + modelTypes.registerType(ObjectId); }; -module.exports.Types = Types; \ No newline at end of file +module.exports.Types = Types; diff --git a/package.json b/package.json index bbc67a7a8..0fc88e129 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,8 @@ "depd": "./lib/browser.depd.js" }, "scripts": { - "clean": "make clean", - "help": "make help", - "refresh": "make refresh", + "e2e": "make e2e", + "unit": "make unit", "test": "make test" }, "engines": [ @@ -30,6 +29,7 @@ ], "devDependencies": { "bluebird": "^2.9.9", + "loopback": "^2.25.0", "mocha": "^2.1.0", "should": "^5.0.0" }, @@ -43,5 +43,8 @@ "qs": "^3.1.0", "traverse": "^0.6.6" }, + "optionalDependencies": { + "mongodb": "^2.0.49" + }, "license": "MIT" } diff --git a/test/datatype.test.js b/test/datatype.test.js index 7dc350e8d..ecf755c9a 100644 --- a/test/datatype.test.js +++ b/test/datatype.test.js @@ -3,7 +3,30 @@ var should = require('./init.js'); var db, Model; -describe('datatypes', function () { +describe('datatypes', function() { + context('ObjectId', function(done) { + var OidModel; + + before(function setup() { + var db = getSchema(); + OidModel = db.define('OidModel', { + id: { + type: 'ObjectId', + id: true + } + }); + db.automigrate('OidModel', done); + }); + + it('should work', function(done) { + OidModel.create({id: 'hello1hello1'}, function(err, inst) { + if (err) return done(err); + inst.id.should.be.type('object'); + inst.id.toString().should.be.type('string').and.have.length(24); + done(); + }); + }); + }); before(function (done) { db = getSchema(); diff --git a/test/e2e/model-definition.js b/test/e2e/model-definition.js new file mode 100644 index 000000000..8169175fe --- /dev/null +++ b/test/e2e/model-definition.js @@ -0,0 +1,59 @@ +var DataSource = require('../..').DataSource; +var ObjectId = require('../../lib/objectid'); +var should = require('should'); + +describe('model definition', function() { + context('ObjectId definition', function() { + var Todo; + + before(function setup() { + var ds = new DataSource(); + Todo = ds.define('Todo', { + id: {type: 'ObjectId', id: true} + }); + }); + + it('should allow 12 byte strings', function() { + var todo = new Todo({id: 'hello1hello1'}); + + todo.id.should.be.an.instanceof(ObjectId); + // 12 byte strings are coerced into 24 character hex strings + todo.id.toString().should.have.length(24); + }); + + it('should allow 24 character hex strings', function() { + var hexStr = '507f191e810c19729de860ea'; + + var todo = new Todo({id: hexStr}); + + todo.id.should.be.an.instanceof(ObjectId); + todo.id.toString().should.equal(hexStr); + }); + + it('should allow ObjectIds', function() { + var objId = new ObjectId(); + + var todo = new Todo({id: objId}); + + todo.id.should.be.an.instanceof(ObjectId); + todo.id.toString().should.equal(objId.toString()); + }); + }); + + context('ObjectID (alias) definition', function() { + var Todo; + + before(function setup() { + var ds = new DataSource(); + Todo = ds.define('Todo', { + id: {type: 'ObjectID', id: true} + }); + }); + + it('should work', function() { + var todo = new Todo({id: 'hello1hello1'}); + + todo.id.should.be.an.instanceof(ObjectId); + }); + }); +}); diff --git a/test/objectid.test.js b/test/objectid.test.js new file mode 100644 index 000000000..6c67ec70a --- /dev/null +++ b/test/objectid.test.js @@ -0,0 +1,62 @@ +var MongoObjId = require('mongodb').ObjectId; +var ObjectId = require('../lib/objectid').ObjectId; + +describe('ObjectId', function() { + context('Constructor', function() { + it('should allow 12 byte strings', function() { + var str = 'hello1hello1'; + + var objId = new ObjectId(str); + + objId.should.be.an.instanceof(ObjectId); + objId.toString().should.be.type('string'); + // 12 byte strings are coerced into 24 character hex strings + objId.toString().should.have.length(24); + }); + + it('should allow 24 character hex strings', function() { + var hexStr = '507f191e810c19729de860ea'; + + var objId = new ObjectId(hexStr); + + objId.should.be.an.instanceof(ObjectId); + objId.toHexString().should.equal(hexStr); + }); + + it('should allow ObjectId', function() { + var existingObjId = new ObjectId(); + + var objId = new ObjectId(existingObjId); + + objId.should.be.an.instanceof(ObjectId); + objId.valueOf().should.equal(existingObjId.valueOf()); + }); + + it('should allow MongoDB ObjectIds', function() { + var objId = new ObjectId(new MongoObjId()); + + objId.should.be.an.instanceof(ObjectId); + }); + + it('should not allow invalid data types', function() { + var fn = function() {}; + [ + true, + {}, + fn + ].forEach(function(invalidDataType) { + (function() { + new ObjectId(invalidDataType); + }).should.throw(); + }); + }); + }); + + context('toString', function() { + it('should be serializable', function() { + var objId = new ObjectId(); + + objId.toString().should.be.type('string'); + }); + }); +});