Added almost all Entity convenience methods

All but asset handling is now done for UsergridEntity
Improved stability for several functions
Bug fixes to mutability
Added rc1 tag for npm
diff --git a/helpers/build.js b/helpers/build.js
index af17953..39d062f 100644
--- a/helpers/build.js
+++ b/helpers/build.js
@@ -9,11 +9,11 @@
     _ = require('lodash')
 
 module.exports = {
-    url: function(options) {
+    url: function(client, options) {
         return urljoin(
             config.baseUrl,
-            options.client.orgId,
-            options.client.appId,
+            client.orgId,
+            client.appId,
             options.type,
             _.isString(options.uuidOrName) ? options.uuidOrName : ""
         )
@@ -56,6 +56,10 @@
             return (property)
         }))
 
+        options.entity = _.first([options.entity, args[0]].filter(function(property) {
+            return (property instanceof UsergridEntity)
+        }))
+
         return options
     },
     PUT: function(client, args) {
@@ -105,6 +109,10 @@
             return (property instanceof UsergridQuery)
         }))
 
+        options.entity = _.first([options.entity, args[0]].filter(function(property) {
+            return (property instanceof UsergridEntity)
+        }))
+
         return options
     },
     POST: function(client, args) {
@@ -178,6 +186,7 @@
         options.entity = _.first([options.entity, args[0]].filter(function(property) {
             return (property instanceof UsergridEntity)
         }))
+
         options.query = _.first([options.query, args[0]].filter(function(property) {
             return (property instanceof UsergridQuery)
         }))
@@ -249,7 +258,9 @@
         }
 
         options.entity.uuidOrName = _.first([options.entity.uuidOrName, options.entity.uuid, options.entity.name, args[1]].filter(_.isString))
-        options.entity.type = _.first([options.entity.type, args[0]].filter(_.isString))
+        if (!options.entity.type) {
+            options.entity.type = _.first([options.entity.type, args[0]].filter(_.isString))
+        }
         options.relationship = _.first([options.relationship, args[2]].filter(_.isString))
 
         if (_.isString(args[3]) && !_.isUuid(args[3]) && _.isString(args[4])) {
@@ -257,7 +268,7 @@
         } else if (_.isString(args[2]) && !_.isUuid(args[2]) && _.isString(args[3]) && _.isObject(args[0]) && !_.isFunction(args[0])) {
             options.to.type = args[2]
         }
-        
+
         options.to.uuidOrName = _.first([options.to.uuidOrName, options.to.uuid, options.to.name, args[4], args[3], args[2]].filter(function(u) {
             return (_.isString(options.to.type) && _.isString(u) || _.isUuid(u))
         }))
diff --git a/helpers/cb.js b/helpers/cb.js
index 08206ef..21ed2f7 100644
--- a/helpers/cb.js
+++ b/helpers/cb.js
@@ -1,3 +1,5 @@
+'use strict'
+
 var _ = require('lodash')
 
 module.exports = function(callback) {
diff --git a/helpers/client.js b/helpers/client.js
new file mode 100644
index 0000000..d91849e
--- /dev/null
+++ b/helpers/client.js
@@ -0,0 +1,19 @@
+'use strict'
+
+var UsergridClient = require('../lib/client')
+var Usergrid = require('../usergrid')
+
+module.exports = {
+    validate: function(args) {
+        var client
+        if (args[0] instanceof UsergridClient) {
+            client = args[0]
+            args.shift()
+        } else if (Usergrid.isInitialized) {
+            client = Usergrid
+        } else {
+            throw new Error("This method requires a valid UsergridClient instance (or the Usergrid shared instance) to be initialized")
+        } 
+        return client
+    }
+}
\ No newline at end of file
diff --git a/helpers/index.js b/helpers/index.js
index aaa05a1..dfc3376 100644
--- a/helpers/index.js
+++ b/helpers/index.js
@@ -1,16 +1,20 @@
-var mutability = require('./mutability'),
+'use strict'
+
+var client = require('./client'),
     cb = require('./cb'),
     build = require('./build'),
     userAgent = require('./userAgent'),
     query = require('./query'),
     config = require('./config'),
     time = require('./time'),
+    mutability = require('./mutability'),
     _ = require('lodash')
 
-// By mixing this in here, lodash-uuid is available everywhere lodash is used.
+// by mixing this in here, lodash-uuid is available everywhere lodash is used.
 _.mixin(require('lodash-uuid'))
 
 module.exports = _.assign(module.exports, {
+    client: client,
     cb: cb,
     build: build,
     userAgent: userAgent,
diff --git a/helpers/mutability.js b/helpers/mutability.js
index 69c06f7..1762264 100644
--- a/helpers/mutability.js
+++ b/helpers/mutability.js
@@ -1,20 +1,20 @@
 'use strict'
 
-var ok = require('objectkit')
+var ok = require('objectkit'),
+    _ = require('lodash')
 
 module.exports = {
     setReadOnly: function(obj, key) {
-        if (typeof obj[key] === 'array') {
-            return obj[key].forEach(function(k) {
-                setReadOnly(obj, k)
+        if (_.isArray(key)) {
+            return key.forEach(function(k) {
+                module.exports.setReadOnly(obj, k)
             })
-        } else if (typeof obj[key] === 'object') {
+        } else if (_.isPlainObject(obj[key])) {
             return Object.freeze(obj[key])
-        } else if (typeof obj === 'object' && key === undefined) {
+        } else if (_.isPlainObject(obj) && key === undefined) {
             return Object.freeze(obj)
         } else if (ok(obj).has(key)) {
             return Object.defineProperty(obj, key, {
-                configurable: false,
                 writable: false
             })
         } else {
@@ -22,14 +22,17 @@
         }
     },
     setWritable: function(obj, key) {
-        // 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)
+        if (_.isArray(key)) {
+            return key.forEach(function(k) {
+                module.exports.setWritable(obj, k)
             })
+        // Note that once Object.freeze is called on an object, it cannot be unfrozen, so we need to clone it
+        } else if (_.isPlainObject(obj[key])) {
+            return _.clone(obj[key])
+        } else if (_.isPlainObject(obj) && key === undefined) {
+            return _.clone(obj)
         } else if (ok(obj).has(key)) {
             return Object.defineProperty(obj, key, {
-                configurable: true,
                 writable: true
             })
         } else {
diff --git a/lib/auth.js b/lib/auth.js
index db67944..b54f3c8 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -20,7 +20,7 @@
         configurable: true
     })
 
-    Object.defineProperty(self, "isTokenValid", {
+    Object.defineProperty(self, "isValid", {
         get: function() {
             return (!self.isExpired && self.hasToken)
         },
diff --git a/lib/client.js b/lib/client.js
index a705cdc..d97a014 100644
--- a/lib/client.js
+++ b/lib/client.js
@@ -4,6 +4,7 @@
     request = require('request'),
     helpers = require('../helpers'),
     UsergridResponse = require('./response'),
+    UsergridResponseError = require('./responseError'),
     UsergridAppAuth = require('./appAuth'),
     UsergridUserAuth = require('./userAuth'),
     _ = require('lodash')
@@ -16,9 +17,6 @@
 var defaultOptions = {
     baseUrl: 'https://api.usergrid.com',
     authFallback: AuthFallback.NONE,
-    paginationPreloadPages: 0, // number of pages to preload
-    paginationCacheTimeout: 300 * 1000, // default: 300 seconds
-    paginationCursors: [] // array of pagination cursors
 }
 
 var UsergridClient = function(options) {
@@ -71,6 +69,10 @@
         DIRECTION_OUT: "OUT"
     },
     connect: function() {
+        var Usergrid = require('../usergrid')
+        if (this === Usergrid && !Usergrid.isInitialized) {
+            throw new Error('The Usergrid shared instance has not been initialized')
+        }
         var options = helpers.build.connection(this, Array.prototype.slice.call(arguments))
         request({
             uri: options.uri,
@@ -107,7 +109,7 @@
         })
     },
     setAppAuth: function(options) {
-        this.appAuth = (typeof options === 'string') ? _.values(arguments) : options
+        this.appAuth = (typeof options === 'string') ? Array.prototype.slice.call(arguments) : options
     },
     authenticateApp: function(options, callback) {
         var self = this
@@ -122,9 +124,9 @@
         }
 
         options.type = 'token'
-        options.client = self
+
         request({
-            uri: helpers.build.url(options),
+            uri: helpers.build.url(self, options),
             headers: helpers.userAgent,
             body: {
                 grant_type: 'client_credentials',
@@ -138,6 +140,8 @@
                 self.appAuth.token = body.access_token
                 self.appAuth.expiry = helpers.time.expiry(body.expires_in)
                 self.appAuth.tokenTtl = body.expires_in
+            } else {
+                error = new UsergridResponseError(response.body)
             }
             callback(error, response, body.access_token)
         })
@@ -155,7 +159,7 @@
         options.type = 'token'
         options.client = self
         request({
-            uri: helpers.build.url(options),
+            uri: helpers.build.url(self, options),
             headers: helpers.userAgent,
             body: options.username ? {
                 grant_type: 'password',
@@ -176,6 +180,8 @@
                 self.currentUser.auth.token = body.access_token
                 self.currentUser.auth.expiry = helpers.time.expiry(body.expires_in)
                 self.currentUser.auth.tokenTtl = body.expires_in
+            } else {
+                error = new UsergridResponseError(response.body)
             }
             callback(error, response, body.access_token)
         })
diff --git a/lib/entity.js b/lib/entity.js
index 654673b..a8b63a6 100644
--- a/lib/entity.js
+++ b/lib/entity.js
@@ -5,14 +5,21 @@
     ok = require('objectkit'),
     _ = require('lodash')
 
-var UsergridEntity = function(obj) {
+var UsergridEntity = function() {
     var self = this
 
-    if (!obj) {
+    var args = Array.prototype.slice.call(arguments)
+
+    if (!args[0]) {
         throw new Error('A UsergridEntity object was initialized using an empty argument')
     }
 
-    _.assign(self, obj)
+    if (_.isObject(args[0])) {
+        _.assign(self, args[0])
+    } else {
+        self.type = _.isString(args[0]) ? args[0] : undefined
+        self.name = _.isString(args[1]) ? args[1] : undefined
+    }
 
     if (!_.isString(self.type)) {
         throw new Error('"type" (or "collection") parameter is required when initializing a UsergridEntity object')
@@ -30,26 +37,93 @@
         }
     })
 
-    helpers.setReadOnly(self, ['uuid', 'name', 'type', 'created', 'modified', 'file', 'file-metadata'])
+    helpers.setReadOnly(self, ['uuid', 'name', 'type', 'created'])
 
     return self
 }
 
 UsergridEntity.prototype = {
+    putProperty: function(key, value) {
+        this[key] = value
+    },
+    putProperties: function(obj) {
+        _.assign(this, obj)
+    },
+    removeProperty: function(key) {
+        this.removeProperties([key])
+    },
+    removeProperties: function(keys) {
+        var self = this
+        keys.forEach(function(key) {
+            delete self[key]
+        })
+    },
+    insert: function(key, value, idx) {
+        if (!_.isArray(this[key])) {
+            this[key] = this[key] ? [this[key]] : []
+        }
+        this[key].splice.apply(this[key], [idx, 0].concat(value))
+    },
+    append: function(key, value) {
+        this.insert(key, value, Number.MAX_SAFE_INTEGER)
+    },
+    prepend: function(key, value) {
+        this.insert(key, value, 0)
+    },
+    pop: function(key) {
+        if (_.isArray(this[key])) {
+            this[key].pop()
+        }
+    },
+    shift: function(key) {
+        if (_.isArray(this[key])) {
+            this[key].shift()
+        }
+    },
+    reload: function(callback) {
+        var client = helpers.client.validate(Array.prototype.slice.call(arguments))
+        client.GET(this, function(err, usergridResponse) {
+            helpers.setWritable(this, ['uuid', 'name', 'type', 'created'])
+            _.assign(this, usergridResponse.entity)
+            helpers.setReadOnly(this, ['uuid', 'name', 'type', 'created'])
+            callback(err || usergridResponse.error, usergridResponse, this)
+        }.bind(this))
+    },
+    save: function(callback) {
+        var client = helpers.client.validate(Array.prototype.slice.call(arguments))
+        client.PUT(this, function(err, usergridResponse) {
+            helpers.setWritable(this, ['uuid', 'name', 'type', 'created'])
+            _.assign(this, usergridResponse.entity)
+            helpers.setReadOnly(this, ['uuid', 'name', 'type', 'created'])
+            callback(err || usergridResponse.error, usergridResponse, this)
+        }.bind(this))
+    },
+    remove: function(callback) {
+        var client = helpers.client.validate(Array.prototype.slice.call(arguments))
+        client.DELETE(this, function(err, usergridResponse) {
+            callback(err || usergridResponse.error, usergridResponse, this)
+        }.bind(this))
+    },
+    attachAsset: function() {},
+    uploadAsset: function() {},
+    downloadAsset: function() {},
     connect: function() {
         var args = Array.prototype.slice.call(arguments)
+        var client = helpers.client.validate(args)
         args.unshift(this)
-        return Usergrid.connect.apply(Usergrid, args)
+        return client.connect.apply(client, args)
     },
     disconnect: function() {
         var args = Array.prototype.slice.call(arguments)
+        var client = helpers.client.validate(args)
         args.unshift(this)
-        return Usergrid.disconnect.apply(Usergrid, args)
+        return client.disconnect.apply(client, args)
     },
     getConnections: function() {
         var args = Array.prototype.slice.call(arguments)
+        var client = helpers.client.validate(args)
         args.splice(1, 0, this)
-        return Usergrid.getConnections.apply(Usergrid, args)
+        return client.getConnections.apply(client, args)
     }
 }
 
diff --git a/lib/request.js b/lib/request.js
index 2a8160a..1eb2223 100644
--- a/lib/request.js
+++ b/lib/request.js
@@ -8,20 +8,18 @@
     _ = require('lodash')
 
 var UsergridRequest = function(options) {
-    options.callback = helpers.cb(options.callback)
-
     if (!_.isString(options.type)) {
         throw new Error('"type" (collection name) parameter is required when making a request')
     }
 
     var headers = helpers.userAgent
 
-    if (options.client.appAuth && options.client.appAuth.isTokenValid) {
+    if (options.client.appAuth && options.client.appAuth.isValid) {
         _.assign(headers, {
             authorization: util.format("Bearer %s", options.client.appAuth.token)
         })
     }
-    request(helpers.build.url(options), {
+    request(helpers.build.url(options.client, options), {
         headers: headers,
         body: options.body,
         json: true,
@@ -32,9 +30,8 @@
         } : undefined
     }, function(error, response) {
         var usergridResponse = new UsergridResponse(response)
-        options.callback(error, usergridResponse, usergridResponse.entities)
+        options.callback(error || usergridResponse.error, usergridResponse, usergridResponse.entities)
     })
-
 }
 
 module.exports = UsergridRequest
\ No newline at end of file
diff --git a/lib/response.js b/lib/response.js
index 5e8240b..31273db 100644
--- a/lib/response.js
+++ b/lib/response.js
@@ -11,7 +11,7 @@
     } else if (ok(response.body).has('entities')) {
         var UsergridEntity = require('./entity.js'),
             UsergridUser = require('./user.js')
-            
+
         var entities = response.body.entities.map(function(en) {
             var entity = new UsergridEntity(en)
             if (entity.isUser) {
diff --git a/package.json b/package.json
index 0d392fc..d795630 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,10 @@
         "mocha": "latest",
         "should": "latest"
     },
+    "repository": {
+        "type": "git",
+        "url": "git://github.com/r3mus/usergrid-nodejs.git"
+    },
     "keywords": [],
     "license": "MIT",
     "main": "app.js",
@@ -23,5 +27,5 @@
         "start": "node app.js",
         "test": "mocha tests"
     },
-    "version": "2.0.0"
+    "version": "2.0.0-rc.1"
 }
\ No newline at end of file
diff --git a/tests/lib/client.test.js b/tests/lib/client.test.js
index f78ad1d..eddc43b 100644
--- a/tests/lib/client.test.js
+++ b/tests/lib/client.test.js
@@ -500,8 +500,8 @@
 
 describe('connect()', function() {
 
-    this.slow(_slow)
-    this.timeout(_timeout)
+    this.slow(_slow + 1000)
+    this.timeout(_timeout + 4000)
 
     var response,
         entity1,
@@ -638,8 +638,8 @@
 
 describe('getConnections()', function() {
 
-    this.slow(_slow)
-    this.timeout(_timeout)
+    this.slow(_slow + 1000)
+    this.timeout(_timeout + 4000)
 
     var response,
         client = new UsergridClient(),
@@ -694,8 +694,8 @@
 
 describe('disconnect()', function() {
 
-    this.slow(_slow)
-    this.timeout(_timeout)
+    this.slow(_slow + 1000)
+    this.timeout(_timeout + 4000)
 
     var response,
         client = new UsergridClient(),
@@ -839,8 +839,8 @@
         client.appAuth.should.have.property('token').equal(token)
     })
 
-    it('client.appAuth.isTokenValid should be true', function() {
-        client.appAuth.should.have.property('isTokenValid').which.is.true()
+    it('client.appAuth.isValid should be true', function() {
+        client.appAuth.should.have.property('isValid').which.is.true()
     })
 
     it('client.appAuth.expiry should be set to a future date', function() {
@@ -885,8 +885,8 @@
         client.currentUser.auth.should.have.property('token').equal(token)
     })
 
-    it('client.currentUser.auth.isTokenValid should be true', function() {
-        client.currentUser.auth.should.have.property('isTokenValid').which.is.true()
+    it('client.currentUser.auth.isValid should be true', function() {
+        client.currentUser.auth.should.have.property('isValid').which.is.true()
     })
 
     it('client.currentUser.auth.expiry should be set to a future date', function() {
diff --git a/tests/lib/entity.test.js b/tests/lib/entity.test.js
index ea5b5b0..ad447e6 100644
--- a/tests/lib/entity.test.js
+++ b/tests/lib/entity.test.js
@@ -4,18 +4,345 @@
     urljoin = require('url-join'),
     config = require('../../helpers').config,
     UsergridClient = require('../../lib/client'),
+    UsergridEntity = require('../../lib/entity'),
     UsergridQuery = require('../../lib/query'),
     _ = require('lodash')
 
 _.mixin(require('lodash-uuid'))
 
-var _slow = 800,
+var _slow = 1500,
     _timeout = 4000
 
+describe('putProperty()', function() {
+    it('should set the value for a given key if the key does not exist', function() {
+        var entity = new UsergridEntity('cat', 'Cosmo')
+        entity.putProperty('foo', ['bar'])
+        entity.should.have.property('foo').deepEqual(['bar'])
+    })
+
+    it('should overwrite the value for a given key if the key exists', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'baz'
+        })
+        entity.putProperty('foo', 'bar')
+        entity.should.have.property('foo').deepEqual('bar')
+    })
+
+    it('should not be able to set the name key (name is immutable)', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'baz'
+        })
+        should(function() {
+            entity.putProperty('name', 'Bazinga')
+        }).throw()
+    })
+})
+
+describe('putProperties()', function() {
+    it('should set properties for a given object, overwriting properties that exist and creating those that don\'t', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'bar'
+        })
+        entity.putProperties({
+            foo: 'baz',
+            qux: 'quux',
+            barray: [1, 2, 3, 4]
+        })
+        entity.should.containEql({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'baz',
+            qux: 'quux',
+            barray: [1, 2, 3, 4]
+        })
+    })
+
+    it('should not be able to set properties for immutable keys', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'baz'
+        })
+        entity.putProperties({
+            name: 'Bazinga',
+            uuid: 'BadUuid',
+            bar: 'qux'
+        })
+        entity.should.containEql({
+            type: 'cat',
+            name: 'Cosmo',
+            bar: 'qux',
+            foo: 'baz'
+        })
+    })
+})
+
+describe('removeProperty()', function() {
+    it('should remove a given property if it exists', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'baz'
+        })
+        entity.removeProperty('foo')
+        entity.should.not.have.property('foo')
+    })
+
+    it('should fail gracefully when removing an undefined property', function() {
+        var entity = new UsergridEntity('cat', 'Cosmo')
+        entity.removeProperty('foo')
+        entity.should.not.have.property('foo')
+    })
+})
+
+describe('removeProperties()', function() {
+    it('should remove an array of properties for a given object, failing gracefully for undefined properties', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'bar',
+            baz: 'qux'
+        })
+        entity.removeProperties(['foo', 'baz'])
+        entity.should.containEql({
+            type: 'cat',
+            name: 'Cosmo'
+        })
+    })
+})
+
+describe('insert()', function() {
+    it('should insert a single value into an existing array at the specified index', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: [1, 2, 3, 5, 6]
+        })
+        entity.insert('foo', 4, 3)
+        entity.should.have.property('foo').deepEqual([1, 2, 3, 4, 5, 6])
+    })
+
+    it('should merge an array of values into an existing array at the specified index', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: [1, 2, 3, 7, 8]
+        })
+        entity.insert('foo', [4, 5, 6], 3)
+        entity.should.have.property('foo').deepEqual([1, 2, 3, 4, 5, 6, 7, 8])
+    })
+
+    it('should convert an existing value into an array when inserting a second value', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'bar'
+        })
+        entity.insert('foo', 'baz', 1)
+        entity.should.have.property('foo').deepEqual(['bar', 'baz'])
+    })
+
+    it('should create a new array when a property does not exist', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo'
+        })
+        entity.insert('foo', 'bar', 1000)
+        entity.should.have.property('foo').deepEqual(['bar'])
+    })
+
+    it('should gracefully handle indexes out of range', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: ['bar']
+        })
+        entity.insert('foo', 'baz', 1000)
+        entity.should.have.property('foo').deepEqual(['bar', 'baz'])
+        entity.insert('foo', 'qux', -1000)
+        entity.should.have.property('foo').deepEqual(['qux', 'bar', 'baz'])
+    })
+})
+
+describe('append()', function() {
+    it('should append a value to the end of an existing array', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: [1, 2, 3]
+        })
+        entity.append('foo', 4)
+        entity.should.have.property('foo').deepEqual([1, 2, 3, 4])
+    })
+
+    it('should create a new array if a property does not exist', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo'
+        })
+        entity.append('foo', 'bar')
+        entity.should.have.property('foo').deepEqual(['bar'])
+    })
+})
+
+describe('prepend()', function() {
+    it('should prepend a value to the beginning of an existing array', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: [1, 2, 3]
+        })
+        entity.prepend('foo', 0)
+        entity.should.have.property('foo').deepEqual([0, 1, 2, 3])
+    })
+
+    it('should create a new array if a property does not exist', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo'
+        })
+        entity.prepend('foo', 'bar')
+        entity.should.have.property('foo').deepEqual(['bar'])
+    })
+})
+
+describe('pop()', function() {
+    it('should remove the last value of an existing array', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: [1, 2, 3]
+        })
+        entity.pop('foo')
+        entity.should.have.property('foo').deepEqual([1, 2])
+    })
+
+    it('value should remain unchanged if it is not an array', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'bar'
+        })
+        entity.pop('foo')
+        entity.should.have.property('foo').deepEqual('bar')
+    })
+
+    it('should gracefully handle empty arrays', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: []
+        })
+        entity.pop('foo')
+        entity.should.have.property('foo').deepEqual([])
+    })
+})
+
+describe('shift()', function() {
+    it('should remove the first value of an existing array', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: [1, 2, 3]
+        })
+        entity.shift('foo')
+        entity.should.have.property('foo').deepEqual([2, 3])
+    })
+
+    it('value should remain unchanged if it is not an array', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: 'bar'
+        })
+        entity.shift('foo')
+        entity.should.have.property('foo').deepEqual('bar')
+    })
+
+    it('should gracefully handle empty arrays', function() {
+        var entity = new UsergridEntity({
+            type: 'cat',
+            name: 'Cosmo',
+            foo: []
+        })
+        entity.shift('foo')
+        entity.should.have.property('foo').deepEqual([])
+    })
+})
+
+describe('reload()', function() {
+
+    this.slow(_slow + 1000)
+    this.timeout(_timeout + 4000)
+
+    it('should refresh an entity with the latest server copy of itself', function(done) {
+        var client = new UsergridClient(config),
+            now = Date.now()
+        client.GET(config.test.collection, function(err, getResponse) {
+            var entity = new UsergridEntity(getResponse.first)
+            var modified = entity.modified
+            getResponse.first.putProperty('reloadTest', now)
+            client.PUT(getResponse.first, function(err, putResponse) {
+                entity.reload(function() {
+                    entity.reloadTest.should.equal(now)
+                    entity.modified.should.not.equal(modified)
+                    done()
+                })
+            })
+        })
+    })
+})
+
+describe('save()', function() {
+
+    this.slow(_slow + 1000)
+    this.timeout(_timeout + 4000)
+
+    it('should save an updated entity to the server', function(done) {
+        var client = new UsergridClient(config),
+            now = Date.now()
+        client.GET(config.test.collection, function(err, getResponse) {
+            var entity = new UsergridEntity(getResponse.first)
+            entity.putProperty('saveTest', now)
+            entity.save(function() {
+                entity.saveTest.should.equal(now)
+                done()
+            })
+        })
+    })
+})
+
+describe('remove()', function() {
+
+    this.slow(_slow + 1000)
+    this.timeout(_timeout + 4000)
+
+    it('should remove an entity from the server', function(done) {
+        var client = new UsergridClient(config)
+        client.POST(config.test.collection, {
+            removeTest: 'test'
+        }, function(err, postResponse) {
+            var entity = new UsergridEntity(postResponse.first)
+            entity.remove(function(err, deleteResponse) {
+                deleteResponse.statusCode.should.equal(200)
+                    // best practice is to delete the entity object here, because it no longer exists on the server
+                entity = null
+                done()
+            })
+        })
+    })
+})
+
 describe('connect()', function() {
 
     this.slow(_slow)
-    this.timeout(_timeout)
+    this.timeout(_timeout + 4000)
 
     var response,
         entity1,
@@ -109,7 +436,7 @@
 describe('getConnections()', function() {
 
     this.slow(_slow)
-    this.timeout(_timeout)
+    this.timeout(_timeout + 4000)
 
     var response,
         client = new UsergridClient(),
@@ -165,7 +492,7 @@
 describe('disconnect()', function() {
 
     this.slow(_slow)
-    this.timeout(_timeout)
+    this.timeout(_timeout + 4000)
 
     var response,
         client = new UsergridClient(),
diff --git a/tests/lib/response.test.js b/tests/lib/response.test.js
index 97bcc9a..4e77443 100644
--- a/tests/lib/response.test.js
+++ b/tests/lib/response.test.js
@@ -67,7 +67,7 @@
 
     it('response.users should be an array of UsergridUser objects', function(done) {
         client.setAppAuth(config.clientId, config.clientSecret, config.tokenTtl)
-        client.authenticateApp(function(err) {
+        client.authenticateApp(function(err, response) {
             should(err).be.null()
             client.GET('users', function(err, usergridResponse) {
                 usergridResponse.statusCode.should.equal(200)