Added UsergridUser class and re-worked entity > user subclassing
diff --git a/.travis.yml b/.travis.yml
index b960342..8b981a0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,7 @@
- 'npm install'
- 'npm -g install mocha'
script:
-- 'mocha tests'
+- 'grunt'
notifications:
email:
on_failure: change
diff --git a/helpers/mutability.js b/helpers/mutability.js
index 4d51dcc..9800e1d 100644
--- a/helpers/mutability.js
+++ b/helpers/mutability.js
@@ -1,15 +1,40 @@
+'use strict'
+
+var ok = require('objectkit')
+
function setReadOnly(obj, key) {
- if (typeof obj[key] === 'object') {
+ if (typeof obj[key] === 'array') {
+ return obj[key].forEach(function(k) {
+ setReadOnly(obj, k)
+ })
+ } else if (typeof obj[key] === 'object') {
return Object.freeze(obj[key])
} else if (typeof obj === 'object' && key === undefined) {
return Object.freeze(obj)
+ } else if (ok(obj).has(key)) {
+ return Object.defineProperty(obj, key, {
+ configurable: false,
+ writable: false
+ })
} else {
- return Object.defineProperty(obj, key, { configurable: false, writable: false })
+ return obj
}
}
function setWritable(obj, key) {
- return Object.defineProperty(obj, key, { configurable: true, writable: true })
+ // Note that once Object.freeze is called on an object, it cannot be unfrozen
+ if (typeof obj[key] === 'array') {
+ return obj[key].forEach(function(k) {
+ setWritable(obj, k)
+ })
+ } else if (ok(obj).has(key)) {
+ return Object.defineProperty(obj, key, {
+ configurable: true,
+ writable: true
+ })
+ } else {
+ return obj
+ }
}
module.exports = {
diff --git a/lib/appAuth.js b/lib/appAuth.js
index 875d0ac..02d32fc 100644
--- a/lib/appAuth.js
+++ b/lib/appAuth.js
@@ -3,14 +3,14 @@
var UsergridAuth = require('./auth'),
util = require('util')
-var UsergridAppAuth = function(options) {
+var UsergridAppAuth = function(opts) {
var self = this
if (arguments.length === 3) {
- options = arguments
+ opts = arguments
}
- self.clientId = (options.length === 3) ? options[0] : options.clientId
- self.clientSecret = (options.length === 3) ? options[1] : options.clientSecret
- self.tokenTtl = (options.length === 3) ? options[2] : options.tokenTtl
+ self.clientId = (opts.length === 3) ? opts[0] : opts.clientId
+ self.clientSecret = (opts.length === 3) ? opts[1] : opts.clientSecret
+ self.tokenTtl = (opts.length === 3) ? opts[2] : opts.tokenTtl
UsergridAuth.call(self)
return self
}
diff --git a/lib/entity.js b/lib/entity.js
index d7af669..2ba4efb 100644
--- a/lib/entity.js
+++ b/lib/entity.js
@@ -1,10 +1,27 @@
'use strict'
-var _ = require('underscore')
+var _ = require('underscore'),
+ helpers = require('../helpers'),
+ ok = require('objectkit')
var UsergridEntity = function(object) {
var self = this
_.extend(self, object)
+
+ Object.defineProperty(self, 'isUser', {
+ get: function() {
+ return (self.type.toLowerCase() === 'user')
+ }
+ })
+
+ Object.defineProperty(self, 'hasAsset', {
+ get: function() {
+ return ok(self).has(['file', 'file-metadata'])
+ }
+ })
+
+ helpers.setReadOnly(self, ['uuid', 'name', 'type', 'created', 'modified', 'file', 'file-metadata'])
+
return self
}
diff --git a/lib/query.js b/lib/query.js
index 2169803..dcdad93 100644
--- a/lib/query.js
+++ b/lib/query.js
@@ -10,9 +10,8 @@
var query = '',
queryString,
- sort
-
- var __nextIsNot = false
+ sort,
+ __nextIsNot = false
// builder pattern
var self = {
diff --git a/lib/response.js b/lib/response.js
index 4d8a2d2..ef4a7c1 100644
--- a/lib/response.js
+++ b/lib/response.js
@@ -2,6 +2,7 @@
var ok = require('objectkit'),
UsergridEntity = require('./entity.js'),
+ UsergridUser = require('./user.js'),
UsergridResponseError = require('./responseError.js'),
helpers = require('../helpers'),
_ = require('underscore')
@@ -10,44 +11,25 @@
function UsergridResponse(response) {
if (ok(response.body).has('entities')) {
- var entities = response.body.entities.map(function(entity) {
- return new UsergridEntity(entity)
+ var entities = response.body.entities.map(function(en) {
+ var entity = new UsergridEntity(en)
+ return (entity.isUser) ? new UsergridUser(entity) : entity
})
_.extend(response, {
metadata: _.map(response.body, _.clone),
entities: entities
})
+ delete response.metadata.entities
response.first = _.first(entities) || undefined
response.entity = response.first
response.last = _.last(entities) || undefined
- delete response.metadata.entities
- helpers.setReadOnly(response.metadata)
-
- entities.forEach(function(entity) {
- // set uuid immutable
- helpers.setReadOnly(entity, 'uuid')
-
- // set type immutable
- helpers.setReadOnly(entity, 'type')
-
- // if not type user, set name immutable
- if (!(_(entity.type.toLowerCase()).startsWith('user'))) {
- helpers.setReadOnly(entity, 'name')
- }
- })
-
- // if response contains users, add UsergridUser references
- if (response.first !== undefined && (_(response.first.type.toLowerCase()).startsWith('user'))) {
- if (response.entities.length === 1) {
- response.user = response.first
- } else {
- response.users = function() {
- return this.entities
- }
- }
+ if (ok(response).has('first.isUser') === true) {
+ response.user = response.first
+ response.users = response.entities
}
- response.entities = entities
+
+ helpers.setReadOnly(response.metadata)
} else {
response.error = new UsergridResponseError(response.body)
}
diff --git a/lib/user.js b/lib/user.js
index e69de29..36b0253 100644
--- a/lib/user.js
+++ b/lib/user.js
@@ -0,0 +1,25 @@
+'use strict'
+
+var UsergridEntity = require('./entity'),
+ helpers = require('../helpers'),
+ ok = require('objectkit'),
+ _ = require('underscore'),
+ util = require('util')
+
+var UsergridUser = function(object) {
+
+ if (!ok(object).has('email') && !ok(object).has('username')) {
+ // This is not a user entity
+ return object
+ }
+
+ var self = this
+ _.extend(self, object, UsergridEntity)
+ UsergridEntity.call(self)
+ helpers.setWritable(self, 'name')
+ return self
+}
+
+util.inherits(UsergridUser, UsergridEntity)
+
+module.exports = UsergridUser
\ No newline at end of file
diff --git a/tests/lib/client.test.js b/tests/lib/client.test.js
index dde8507..69e0013 100644
--- a/tests/lib/client.test.js
+++ b/tests/lib/client.test.js
@@ -5,7 +5,6 @@
UsergridClient = require('../../lib/client'),
UsergridAppAuth = require('../../lib/appAuth')
-var _collection = config.tests.collection
var _uuid = null
describe('initialization', function() {
@@ -45,7 +44,7 @@
var response, client
before(function(done) {
client = new UsergridClient()
- client.GET(_collection, function(err, usergridResponse) {
+ client.GET(config.tests.collection, function(err, usergridResponse) {
response = usergridResponse
done()
})
@@ -53,7 +52,7 @@
it('should not fail when a callback function is not passed', function() {
// note: this test will NOT fail gracefully inside the Mocha event chain
- client.GET(_collection)
+ client.GET(config.tests.collection)
})
it('should return a 200 ok', function() {
@@ -85,7 +84,7 @@
var response, client
before(function(done) {
client = new UsergridClient()
- client.POST(_collection, {
+ client.POST(config.tests.collection, {
author: 'Sir Arthur Conan Doyle'
}, function(err, usergridResponse) {
response = usergridResponse
@@ -96,7 +95,7 @@
it('should not fail when a callback function is not passed', function() {
// note: this test will NOT fail gracefully inside the Mocha event chain
- client.POST(_collection, {})
+ client.POST(config.tests.collection, {})
})
it('should return a 200 ok', function() {
@@ -124,7 +123,7 @@
var response, client
before(function(done) {
client = new UsergridClient()
- client.PUT(_collection, _uuid, {
+ client.PUT(config.tests.collection, _uuid, {
narrator: 'Peter Doyle'
}, function(err, usergridResponse) {
response = usergridResponse
@@ -134,7 +133,7 @@
it('should not fail when a callback function is not passed', function() {
// note: this test will NOT fail gracefully inside the Mocha event chain
- client.PUT(_collection, _uuid)
+ client.PUT(config.tests.collection, _uuid)
})
it('should return a 200 ok', function() {
@@ -162,8 +161,8 @@
var response, client
before(function(done) {
client = new UsergridClient()
- client.DELETE(_collection, _uuid, function() {
- client.GET(_collection, _uuid, function(err, usergridResponse) {
+ client.DELETE(config.tests.collection, _uuid, function() {
+ client.GET(config.tests.collection, _uuid, function(err, usergridResponse) {
response = usergridResponse
done()
})
@@ -172,7 +171,7 @@
it('should not fail when a callback function is not passed', function() {
// note: this test will NOT fail gracefully inside the Mocha event chain
- client.DELETE(_collection, _uuid)
+ client.DELETE(config.tests.collection, _uuid)
})
it('should return a 200 ok', function() {
@@ -220,7 +219,7 @@
})
})
-describe('appAuth / setAppAuth()', function() {
+describe('appAuth, setAppAuth()', function() {
it('should initialize by passing a list of arguments', function() {
var client = new UsergridClient()
client.setAppAuth(config.usergrid.clientId, config.usergrid.clientSecret, config.usergrid.tokenTtl)
diff --git a/tests/lib/response.test.js b/tests/lib/response.test.js
index 26c062e..381a743 100644
--- a/tests/lib/response.test.js
+++ b/tests/lib/response.test.js
@@ -4,10 +4,10 @@
config = require('../../config.json'),
UsergridClient = require('../../lib/client'),
UsergridEntity = require('../../lib/entity'),
+ UsergridUser = require('../../lib/user'),
UsergridResponseError = require('../../lib/responseError'),
_ = require('underscore')
-var _collection = config.tests.collection
var client = new UsergridClient()
var _response
@@ -17,7 +17,7 @@
this.slow(1000)
this.timeout(6000)
- client.GET(_collection, function(err, usergridResponse) {
+ client.GET(config.tests.collection, function(err, usergridResponse) {
_response = usergridResponse
done()
})
@@ -51,9 +51,37 @@
this.slow(1000)
this.timeout(6000)
- client.GET(_collection, 'BADNAMEORUUID', function(err, usergridResponse) {
- usergridResponse.statusCode.should.not.equal(200)
- usergridResponse.error.should.be.an.instanceof(UsergridResponseError).with.keys(['name', 'description', 'exception'])
+ client.GET(config.tests.collection, 'BADNAMEORUUID', function(err, usergridResponse) {
+ usergridResponse.error.should.be.an.instanceof(UsergridResponseError)
+ done()
+ })
+ })
+})
+
+describe('users', function() {
+
+ this.slow(1000)
+ this.timeout(6000)
+
+ it('response.users should be an array of UsergridUser objects', function(done) {
+ client.GET('users', function(err, usergridResponse) {
+ usergridResponse.users.should.be.an.Array()
+ usergridResponse.users.forEach(function(user) {
+ user.should.be.an.instanceof(UsergridUser)
+ })
+ done()
+ })
+ })
+})
+
+describe('user', function() {
+
+ this.slow(1000)
+ this.timeout(6000)
+
+ it('response.user should be a UsergridUser object and have a valid uuid matching the first object in response.users', function(done) {
+ client.GET('users', function(err, usergridResponse) {
+ usergridResponse.user.should.be.an.instanceof(UsergridUser).with.property('uuid').equal(_.first(usergridResponse.users).uuid)
done()
})
})
@@ -68,7 +96,7 @@
})
})
-describe('first / entity', function() {
+describe('first, entity', function() {
it('response.first should be a UsergridEntity object and have a valid uuid matching the first object in response.entities', function() {
_response.first.should.be.an.instanceof(UsergridEntity).with.property('uuid').equal(_.first(_response.entities).uuid)
})
diff --git a/tests/lib/responseError.test.js b/tests/lib/responseError.test.js
new file mode 100644
index 0000000..d44071e
--- /dev/null
+++ b/tests/lib/responseError.test.js
@@ -0,0 +1,33 @@
+'use strict'
+
+var should = require('should'),
+ config = require('../../config.json'),
+ UsergridClient = require('../../lib/client'),
+ UsergridResponseError = require('../../lib/responseError')
+
+var client = new UsergridClient()
+
+var _response
+
+describe('name, description, exception', function() {
+
+ before(function(done) {
+
+ this.slow(1000)
+ this.timeout(6000)
+
+ client.GET(config.tests.collection, 'BADNAMEORUUID', function(err, usergridResponse) {
+ _response = usergridResponse
+ done()
+ })
+ })
+
+ it('response should have a status code greater than or equal to 400', function() {
+ _response.statusCode.should.be.greaterThanOrEqual(400)
+ })
+
+ it('response.error should be a UsergridResponseError object with name, description, and exception keys', function() {
+ _response.statusCode.should.not.equal(200)
+ _response.error.should.be.an.instanceof(UsergridResponseError).with.keys(['name', 'description', 'exception'])
+ })
+})
\ No newline at end of file
diff --git a/tests/main.test.js b/tests/main.test.js
index 324d305..32f2890 100644
--- a/tests/main.test.js
+++ b/tests/main.test.js
@@ -1,17 +1,21 @@
'use strict'
-describe.skip('Usergrid', function() {
+describe('Usergrid', function() {
return require('./lib/usergrid.test')
})
-describe.skip('UsergridClient', function() {
+describe('UsergridClient', function() {
return require('./lib/client.test')
})
-describe.skip('UsergridQuery', function() {
+describe('UsergridQuery', function() {
return require('./lib/query.test')
})
describe('UsergridResponse', function() {
return require('./lib/response.test')
+})
+
+describe('UsergridResponseError', function() {
+ return require('./lib/responseError.test')
})
\ No newline at end of file